{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;GAIG;AAEH,MAAM,WAAW,iBAAiB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,UAAU;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IAEnC,YAAY,IAAI,EAAE,iBAAiB,EASlC;IAED,gFAAgF;IAC1E,eAAe,CACpB,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,OAAO,CAAC;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;KACZ,CAAC,CAQD;IAED;;;OAGG;IACG,aAAa,CAClB,IAAI,EAAE,MAAM,EACZ,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,GAChC,OAAO,CAAC;QACV,MAAM,CAAC,EAAE,SAAS,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC,CAkBD;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9B;CACD","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport type { WorkspaceBoundary } from \"../safety/boundary.js\";\nimport { type LspClient, toFileUri } from \"./client.js\";\nimport { detectLanguage } from \"./discovery.js\";\nimport { LspServerManager } from \"./manager.js\";\n\n/**\n * Shared runtime context for the LSP tools. Owns the server manager and\n * enforces workspace-boundary enforcement on every path input. Lives for the\n * duration of an agent session; `dispose()` shuts down all servers (no leaks).\n */\n\nexport interface LspRuntimeOptions {\n\tworkspaceRoot: string;\n\tboundary: WorkspaceBoundary;\n\tstartupTimeoutMs?: number;\n\tinitializeTimeoutMs?: number;\n\trequestTimeoutMs?: number;\n}\n\nexport class LspRuntime {\n\treadonly workspaceRoot: string;\n\treadonly boundary: WorkspaceBoundary;\n\treadonly manager: LspServerManager;\n\n\tconstructor(opts: LspRuntimeOptions) {\n\t\tthis.workspaceRoot = nodePath.resolve(opts.workspaceRoot);\n\t\tthis.boundary = opts.boundary;\n\t\tthis.manager = new LspServerManager({\n\t\t\tworkspaceRoot: this.workspaceRoot,\n\t\t\tstartupTimeoutMs: opts.startupTimeoutMs,\n\t\t\tinitializeTimeoutMs: opts.initializeTimeoutMs,\n\t\t\trequestTimeoutMs: opts.requestTimeoutMs,\n\t\t});\n\t}\n\n\t/** Resolve a workspace-relative path through the boundary. Throws on escape. */\n\tasync resolveFilePath(\n\t\tfile: string,\n\t\tlangIdOverride?: string | null,\n\t): Promise<{\n\t\tabsPath: string;\n\t\trelPath: string;\n\t\tlanguageId: string;\n\t\turi: string;\n\t}> {\n\t\tconst abs = await this.boundary.resolveWithin(file);\n\t\tconst rel = nodePath.relative(this.workspaceRoot, abs).replace(/\\\\/g, \"/\");\n\t\tlet languageId = langIdOverride ?? null;\n\t\tif (!languageId) {\n\t\t\tlanguageId = detectLanguage(abs).languageId ?? \"plaintext\";\n\t\t}\n\t\treturn { absPath: abs, relPath: rel, languageId, uri: toFileUri(abs) };\n\t}\n\n\t/**\n\t * Get a managed server for a language and sync the given document. Returns\n\t * `{ client, server }` or `{ unavailableReason }`.\n\t */\n\tasync serverForFile(\n\t\tfile: string,\n\t\tlanguageIdOverride?: string | null,\n\t): Promise<{\n\t\tclient?: LspClient;\n\t\tserverId?: string;\n\t\tabsPath?: string;\n\t\turi?: string;\n\t\tlanguageId?: string;\n\t\tunavailableReason?: string;\n\t}> {\n\t\tconst resolved = await this.resolveFilePath(file, languageIdOverride);\n\t\tconst { server, unavailableReason } = await this.manager.getServer(resolved.languageId);\n\t\tif (unavailableReason || !server) {\n\t\t\treturn { unavailableReason: unavailableReason ?? \"server_unavailable\", languageId: resolved.languageId };\n\t\t}\n\t\t// Sync current document content.\n\t\tconst content = await readFile(resolved.absPath, \"utf-8\").catch(() => null);\n\t\tif (content !== null) {\n\t\t\tawait server.client.openDocument(resolved.uri, content);\n\t\t}\n\t\treturn {\n\t\t\tclient: server.client,\n\t\t\tserverId: server.serverId,\n\t\t\tabsPath: resolved.absPath,\n\t\t\turi: resolved.uri,\n\t\t\tlanguageId: resolved.languageId,\n\t\t};\n\t}\n\n\tasync shutdown(): Promise<void> {\n\t\tawait this.manager.shutdownAll();\n\t}\n}\n"]}