import type { LspSession, LspOperation, LspRequestParams, LspResult, LspTransport, LspReadText } from "./lsp.js"; import type { LspDiagnosticsRegistry } from "./lsp-diagnostics.js"; export interface SessionWarmup { /** Empty results within this window after session creation are retried (a freshly-spawned server answers * non-blocking ops with EMPTY results while its project is still loading — the model may call * hover/documentSymbol FIRST and get non-null-but-empty answers; goToDefinition happens to block on load, * which is why op-order made it look random). 0 disables. */ windowMs: number; retryMs: number; } export declare class TransportLspSession implements LspSession { private readonly transport; private readonly languageId; private readonly readText; /** Observability hook for swallowed degrades (graceful "none" hides real transport faults otherwise). */ private readonly log; private readonly warmup; /** filePath → the last text SENT to the server (didOpen/didChange) + its document version. */ private readonly opened; /** In-flight per-file syncs — concurrent ops on the same new file share ONE read/didOpen. */ private readonly syncing; private readonly createdAt; private warmupBarrierDone; constructor(transport: LspTransport, languageId: string, readText: LspReadText, /** Observability hook for swallowed degrades (graceful "none" hides real transport faults otherwise). */ log?: (event: string, fields: Record) => void, warmup?: SessionWarmup, /** design/121: when set (and the transport dispatches notifications), the session feeds this * registry from `textDocument/publishDiagnostics` — with version-staleness protection: a * notification versioned OLDER than the text this session last SENT for that file is dropped * (the server is still churning on stale content). Absent ⇒ pre-121 behavior byte-for-byte. */ diagnostics?: LspDiagnosticsRegistry); request(op: LspOperation, params: LspRequestParams, signal?: AbortSignal): Promise; /** Re-sync every opened file (+ the queried one) with its CURRENT on-disk text, in parallel. */ private syncOpenedFiles; /** didOpen a new file / didChange (full-text replace) an opened one whose disk content moved. Never throws: * an unreadable NEW file just skips didOpen (the server may read from disk); an unreadable OPENED one keeps * the last-sent text (best-effort — e.g. the agent deleted it). Concurrent callers share one in-flight sync. */ private syncOne; /** Underlying connection gone (e.g. the server crashed / the WS was idle-killed) → the manager evicts + reopens. */ get closed(): boolean; /** Files didOpen'd on this server — the manager carries them to a HEALED session: a fresh server with no * project config only "sees" its open files (e.g. tsserver inferred project), so without the carry-over, * cross-file ops (references/calls) silently degrade to single-file after a heal. */ openedFiles(): string[]; /** Re-open carried files on a fresh session (heal). Best-effort per file (a deleted file just skips). */ warmOpen(filePaths: string[], signal?: AbortSignal): Promise; /** * design/121: push the file's CURRENT text to the server WITHOUT an op (didOpen/didChange as * appropriate). The agent's edit/write tools call this fire-and-forget so the server re-analyzes * and pushes publishDiagnostics — the session's normal lazy sync only runs on the next LSP op, * which may never come. Never throws (same best-effort contract as syncOne). */ notifyFileChanged(filePath: string, signal?: AbortSignal): Promise; close(): Promise; } //# sourceMappingURL=lsp-session.d.ts.map