summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-06-15 13:52:57 -0400
committerDax Raad <[email protected]>2025-06-15 13:52:57 -0400
commite30fba0d3cbf0a92d3dd1c51e051e9325a58013e (patch)
tree98bb58de8d1bf7816d75433ff36bd3eff2c3f125
parent7fbb2ca9a6c6f81519a45e4ce836b9dd3ceee9f2 (diff)
downloadopencode-e30fba0d3cbf0a92d3dd1c51e051e9325a58013e.tar.gz
opencode-e30fba0d3cbf0a92d3dd1c51e051e9325a58013e.zip
Improve LSP server initialization with timeout handling and skip failed servers
🤖 Generated with [opencode](https://opencode.ai) Co-Authored-By: opencode <[email protected]>
-rw-r--r--packages/opencode/src/cli/cmd/run.ts3
-rw-r--r--packages/opencode/src/lsp/client.ts60
-rw-r--r--packages/opencode/src/lsp/index.ts15
3 files changed, 50 insertions, 28 deletions
diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts
index dd9db3cc9..3a4677484 100644
--- a/packages/opencode/src/cli/cmd/run.ts
+++ b/packages/opencode/src/cli/cmd/run.ts
@@ -115,9 +115,6 @@ export const RunCommand = {
})
const { providerID, modelID } = await Provider.defaultModel()
- setTimeout(() => {
- Session.abort(session.id)
- }, 8000)
await Session.chat({
sessionID: session.id,
providerID,
diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts
index 6ad951fe7..628ccd5af 100644
--- a/packages/opencode/src/lsp/client.ts
+++ b/packages/opencode/src/lsp/client.ts
@@ -11,6 +11,7 @@ import { LANGUAGE_EXTENSIONS } from "./language"
import { Bus } from "../bus"
import z from "zod"
import type { LSPServer } from "./server"
+import { NamedError } from "../util/error"
export namespace LSPClient {
const log = Log.create({ service: "lsp.client" })
@@ -19,6 +20,13 @@ export namespace LSPClient {
export type Diagnostic = VSCodeDiagnostic
+ export const InitializeError = NamedError.create(
+ "LSPInitializeError",
+ z.object({
+ serverID: z.string(),
+ }),
+ )
+
export const Event = {
Diagnostics: Bus.event(
"lsp.client.diagnostics",
@@ -52,32 +60,40 @@ export namespace LSPClient {
})
connection.listen()
- await connection.sendRequest("initialize", {
- processId: server.process.pid,
- workspaceFolders: [
- {
- name: "workspace",
- uri: "file://" + app.path.cwd,
- },
- ],
- initializationOptions: {
- ...server.initialization,
- },
- capabilities: {
- workspace: {
- configuration: true,
+ log.info("sending initialize", { id: serverID })
+ await Promise.race([
+ connection.sendRequest("initialize", {
+ processId: server.process.pid,
+ workspaceFolders: [
+ {
+ name: "workspace",
+ uri: "file://" + app.path.cwd,
+ },
+ ],
+ initializationOptions: {
+ ...server.initialization,
},
- textDocument: {
- synchronization: {
- didOpen: true,
- didChange: true,
+ capabilities: {
+ workspace: {
+ configuration: true,
},
- publishDiagnostics: {
- versionSupport: true,
+ textDocument: {
+ synchronization: {
+ didOpen: true,
+ didChange: true,
+ },
+ publishDiagnostics: {
+ versionSupport: true,
+ },
},
},
- },
- })
+ }),
+ new Promise((_, reject) => {
+ setTimeout(() => {
+ reject(new InitializeError({ serverID }))
+ }, 5_000)
+ }),
+ ])
await connection.sendNotification("initialized", {})
log.info("initialized")
diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts
index ae8ec6835..f29dec378 100644
--- a/packages/opencode/src/lsp/index.ts
+++ b/packages/opencode/src/lsp/index.ts
@@ -12,9 +12,10 @@ export namespace LSP {
async () => {
log.info("initializing")
const clients = new Map<string, LSPClient.Info>()
-
+ const skip = new Set<string>()
return {
clients,
+ skip,
}
},
async (state) => {
@@ -31,11 +32,19 @@ export namespace LSP {
x.extensions.includes(extension),
)
for (const match of matches) {
+ if (s.skip.has(match.id)) continue
const existing = s.clients.get(match.id)
if (existing) continue
const handle = await match.spawn(App.info())
- if (!handle) continue
- const client = await LSPClient.create(match.id, handle)
+ if (!handle) {
+ s.skip.add(match.id)
+ continue
+ }
+ const client = await LSPClient.create(match.id, handle).catch(() => {})
+ if (!client) {
+ s.skip.add(match.id)
+ continue
+ }
s.clients.set(match.id, client)
}
if (waitForDiagnostics) {