Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/opencode/src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ export namespace LSPClient {
uri: pathToFileURL(input.root).href,
},
])
let alive = true
connection.onClose(() => {
l.info("connection closed")
alive = false
})
connection.onError((err) => {
l.error("connection error", { error: err })
})

connection.listen()

l.info("sending initialize")
Expand Down Expand Up @@ -141,6 +150,9 @@ export namespace LSPClient {
get serverID() {
return input.serverID
},
get alive() {
return alive
},
get connection() {
return connection
},
Expand Down
36 changes: 30 additions & 6 deletions packages/opencode/src/lsp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,18 +275,42 @@ export namespace LSP {
return false
}

async function removeClient(s: Awaited<ReturnType<typeof state>>, client: LSPClient.Info) {
const idx = s.clients.indexOf(client)
if (idx !== -1) s.clients.splice(idx, 1)
s.broken.add(client.root + client.serverID)
client.shutdown().catch(() => {})
log.info("removed dead LSP client", {
serverID: client.serverID,
root: client.root,
})
}

export async function touchFile(input: string, waitForDiagnostics?: boolean) {
log.info("touching file", { file: input })
const s = await state()
const clients = await getClients(input)
await Promise.all(
clients.map(async (client) => {
const wait = waitForDiagnostics ? client.waitForDiagnostics({ path: input }) : Promise.resolve()
await client.notify.open({ path: input })
return wait
if (!client.alive) {
await removeClient(s, client)
return
}
try {
const wait = waitForDiagnostics ? client.waitForDiagnostics({ path: input }) : Promise.resolve()
await client.notify.open({ path: input })
return wait
} catch (err: any) {
log.error("failed to touch file", { err, file: input })
if (
err?.message?.includes("Connection is closed") ||
err?.message?.includes("connection is disposed")
) {
await removeClient(s, client)
}
}
}),
).catch((err) => {
log.error("failed to touch file", { err, file: input })
})
)
}

export async function diagnostics() {
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/src/tool/write.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Writes a file to the local filesystem.
Usage:
- This tool will overwrite the existing file if there is one at the provided path.
- If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required. Use the Edit tool instead of Write when only a portion of the file changed.
- When creating or writing multiple files, avoid writing more than 5 files in rapid succession. Each write triggers formatting, LSP, and snapshot operations that need time to complete.
- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.
Loading