-
Notifications
You must be signed in to change notification settings - Fork 0
fix(tui): resolve streaming freeze from unhandled finish event, missing timeouts, and unguarded effects #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
Comment on lines
+580
to
585
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Mcp timeout leaks clients On listTools() timeout/failure in MCP.tools(), the client is deleted from state without calling client.close(), potentially leaking transports/sockets. This is especially risky now that withTimeout() will trigger failures that previously would hang indefinitely. Agent Prompt
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -122,7 +122,7 @@ export namespace Database { | |||||
| if (err instanceof Context.NotFound) { | ||||||
| const effects: (() => void | Promise<void>)[] = [] | ||||||
| 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 })) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Prompt for AI agents
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. catch uses implicit any The new Promise rejection handlers introduce e as an implicit any (from Promise.catch), which weakens type safety. This can hide mistakes when logging/inspecting errors and violates the no-any rule. Agent Prompt
|
||||||
| 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 | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The batch window time
50is used as a magic number in both the condition and thesetTimeoutcall. To improve readability and maintainability, consider defining it as a constant, for exampleconst BATCH_WINDOW_MS = 50;, at a higher scope (e.g., at the top of theinitfunction) and using it here.