Skip to content

After getting stuck and retrying, the LLM indicates that this is a new conversation with no context. #10

Description

@Icarix9

When using this plugin within oh-my-pi under the iOA network environment, I frequently encounter this warning:
Warning: CodeBuddy SDK: 1 tool handler(s) still waiting — provider may be stuck.

However, after I retried, the LLM seemed unable to access the previous context to continue the conversation.

Image

I asked AI to analyze this issue and propose a solution; I’m not sure if it will be helpful to you, but I hope it resolves the problem:

Title: Fatal unhandledRejection on retry-after-interrupt: fire-and-forget handleMcpMessageRequest throws on torn-down transport (root cause in @tencent-ai/agent-sdk); same retry also silently drops session history

Summary

Two related defects triggered by one user action — pressing retry after interrupting a wedged turn:

  1. Fatal crash (root cause in the upstream @tencent-ai/agent-sdk dependency): ProcessTransport.handleLine dispatches control_request/mcp_message via fire-and-forget handleMcpMessageRequest() with no await / .catch. When the CodeBuddy CLI subprocess
    has just been torn down (interrupt → retry), a late-arriving mcp_message makes sendControlErrorResponse → writeLine throw Error: Transport not started inside an unowned async function → unhandled rejection → the host process (oh-my-pi) escalates
    unhandledRejection to kind: "fatal" and exits.
  2. Silent context loss (plugin side): on that same retry, when pi's rewritten history is shorter than the stored cursor, sharedSession takes the "Case 1 synthetic: clean start for shorter context" branch and sends only the final user message with no
    resume:. The model then truthfully reports it has no memory of the previous conversation.

Environment

  • pi-codebuddy-sdk 0.4.4
  • @tencent-ai/agent-sdk 0.3.244 (dependency)
  • Host: oh-my-pi 18.1.21, plugins loaded under Bun, Windows 11

Crash mechanism (code level)

In @tencent-ai/agent-sdk/lib/transport/process-transport.js (line numbers approximate — from the installed 0.3.244; the crashing build was a slightly older patch):

  1. ~L768 — handleLine() receives control_request/mcp_message and calls this.handleMcpMessageRequest(controlRequest) fire-and-forget: no await, no .catch. The comment above says this is intentional (control requests must still dispatch after the
    consumer's for-await loop is cancelled) — but the returned promise is unowned.
  2. ~L956 / ~L961 / ~L984 — handleMcpMessageRequest: when the target transport can't be found, it calls sendControlErrorResponse directly, outside any try/catch; the general error path also funnels into sendControlErrorResponse.
  3. ~L650 → ~L844 — sendControlErrorResponse → writeLine: if (!this.process?.stdin) throw new Error('Transport not started').

Observed sequence in my session:

  • The turn wedges: the plugin logs CodeBuddy SDK: 1 tool handler(s) still waiting — provider may be stuck (plugin index.ts ~L1134) — a tool callback is never collected by the CLI.
  • I interrupt, then press retry. Retry tears down the CLI subprocess; stdin is destroyed.
  • ~15s later a late mcp_message control request arrives on the half-dead pipe → steps 1→2→3 → the throw lands in an unowned async function → unhandled rejection → host's default handler terminates the process as fatal. (Only
    ipc-send/stdio-write/expected-cleanup errors are swallowable in the host; this rejection is none of those.)

Context-loss mechanism (plugin side)

index.ts ~L522–597, sharedSession { sessionId, cursor }:

  • Normal path REUSE: sends only the delta; the CLI reads its own session file.
  • Divergent history → REBUILD: rewrites pi's full history into a new CLI session.
  • ~L554–557 — "Case 1 synthetic: clean start for shorter context": when the delivered history is shorter than the cursor (priorMessages.length < cursor), return { sessionId: null } → the query goes out without resume: and contains only the last user
    message.

On retry, pi rewrites history (branch summary discards the aborted branch; the log shows advisor-delivered prefix changing from index 92 on), so the delivered history shrinks → clean-start branch fires → the only thing on the wire was a synthetic
[tool_result:call_…] [continue] message. The model first returned an empty stop, then (accurately) stated it had no context of the prior conversation.

Reproduction

  1. Session with an MCP tool call in flight.
  2. Provider wedges (tool handler never collected → provider may be stuck warning). I don't have a deterministic trigger for the wedge itself.
  3. Interrupt, then retry while pi's history rewrite makes the visible history shorter (e.g. right after a branch summary).
  4. Observe: process exits with fatal unhandledRejection (Transport not started), stack: writeLine ← sendControlErrorResponse ← handleMcpMessageRequest ← handleLine. After relaunch/resume, the model has no context.

Suggested fixes

  • SDK (root fix): attach rejection handling to every fire-and-forget dispatch in handleLine, e.g.
void this.handleMcpMessageRequest(controlRequest).catch(() => {});

Swallowing is appropriate here: the transport is mid-teardown and the error response is undeliverable anyway. Alternative: make writeLine/sendControlErrorResponse a no-op (instead of throwing) when stdin is already destroyed.

  • Plugin (defense in depth): make the clean-start branch visible — warn the user that history was dropped — or fall back to REBUILD with the truncated history instead of sending a single synthetic message.

Workaround (for users, until fixed)

When CodeBuddy SDK: N tool handler(s) still waiting — provider may be stuck appears, do not retry in place. Exit and resume with omp --resume — the local transcript is intact. The crash only occurs in the window where in-place retry has
torn down the transport while the control pipe is still alive.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions