diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx index 7fa7e05c3d2..104ccb8be62 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx @@ -52,10 +52,10 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ const elapsed = Date.now() - last if (timer) return - // If we just flushed recently (within 16ms), batch this with future events + // If we just flushed recently (within 50ms), batch this with future events // Otherwise, process immediately to avoid latency - if (elapsed < 16) { - timer = setTimeout(flush, 16) + if (elapsed < 50) { + timer = setTimeout(flush, 50) return } flush() diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index 3c29fe03d30..f8ba0d78714 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -577,7 +577,9 @@ export namespace MCP { const toolsResults = await Promise.all( connectedClients.map(async ([clientName, client]) => { - const toolsResult = await client.listTools().catch((e) => { + const mcpEntry = config[clientName] + const timeout = (isMcpConfigured(mcpEntry) ? mcpEntry.timeout : undefined) ?? defaultTimeout ?? DEFAULT_TIMEOUT + const toolsResult = await withTimeout(client.listTools(), timeout).catch((e) => { log.error("failed to get tools", { clientName, error: e.message }) const failedStatus = { status: "failed" as const, diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index e7532d20073..d154c6c80c0 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -50,6 +50,7 @@ export namespace SessionProcessor { try { let currentText: MessageV2.TextPart | undefined let reasoningMap: Record = {} + let finished = false const stream = await LLM.stream(streamInput) for await (const value of stream.fullStream) { @@ -337,6 +338,8 @@ export namespace SessionProcessor { break case "finish": + log.info("stream finish event received") + finished = true break default: @@ -345,7 +348,7 @@ export namespace SessionProcessor { }) continue } - if (needsCompaction) break + if (needsCompaction || finished) break } } catch (e: any) { log.error("process", { diff --git a/packages/opencode/src/storage/db.ts b/packages/opencode/src/storage/db.ts index f29aac18d16..b71f67d82c2 100644 --- a/packages/opencode/src/storage/db.ts +++ b/packages/opencode/src/storage/db.ts @@ -122,7 +122,7 @@ export namespace Database { if (err instanceof Context.NotFound) { const effects: (() => void | Promise)[] = [] const result = ctx.provide({ effects, tx: Client() }, () => callback(Client())) - for (const effect of effects) effect() + for (const effect of effects) Promise.resolve(effect()).catch((e) => log.error("effect failed", { error: e })) return result } throw err @@ -146,7 +146,7 @@ export namespace Database { const result = Client().transaction((tx) => { return ctx.provide({ tx, effects }, () => callback(tx)) }) - for (const effect of effects) effect() + for (const effect of effects) Promise.resolve(effect()).catch((e) => log.error("effect failed", { error: e })) return result } throw err