Composer tool loop remains busy after H2 socket closes

Open
#33 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
node.js, typescript
Domain
api, backend

Research direction

Read the end-stream and onClose branches in src/proxy.ts around lines 1493-1542, then trace the stderr and error handling in src/h2-bridge.mjs. Add a replay or integration test for multiple Composer tool/result turns with an injected H2 socket close; done means exactly one terminal state and no pending tool loop or busy state.

Written by the indexing model from the issue text.

Description

Environment

  • OpenCode: 1.18.9
  • Plugin: opencode-cursor-oauth 0.1.1
  • OS: macOS
  • Node.js: 22.19.0
  • Bun: 1.3.14

Summary

Composer can enter a busy state after a multi-turn tool loop when the H2 socket closes. The run does not emit a normal finish event, does not exit the tool loop, and does not return to idle. The same pressure test passes with Grok under the same client and tool setup.

Observed error text:

Cannot connect to API: The socket connection was closed unexpectedly

Sanitized timeline

  • 11:02:12Z: last stream activity
  • 11:02:40Z: H2 socket closed
  • 11:06:28Z: later retry
  • 11:10:48Z: later retry

The timestamps are approximate and intentionally omit local identifiers and request details.

Expected behavior

When the H2 stream closes, the proxy should deterministically emit a terminal error or completion, close the associated stream state, and let the client exit the tool loop. A retry should either establish a clean new stream or fail with a bounded, visible error. The Composer run should never remain indefinitely busy without a finish/exiting-loop/idle transition.

Safe reproduction outline

  1. Configure OpenCode with the Cursor OAuth plugin and a Composer model.
  2. Run a read-only agent task that requires several sequential tool turns, such as inspecting files, searching for a symbol, and returning a final summary.
  3. Allow the task to continue through multiple tool-result round trips.
  4. Observe a stream/socket close during the loop.
  5. Observe that Composer remains busy instead of emitting a terminal event or returning to idle.
  6. Repeat the same multi-round read-only test with Grok; it completes successfully under the same pressure conditions.

No credentials, private payloads, session identifiers, or full prompts are included.

Network observations

At the time of investigation, basic unauthenticated DNS, TCP 443, TLS, HTTPS, and HTTP/2 connectivity to the Cursor host was normal, including repeated HTTP/2 root requests. There were also intermittent historical connection anomalies, including timeout, connection reset, DNS resolution, and TLS handshake errors. This suggests the proxy should handle transient H2 failures explicitly, but the issue is not explained by a persistent basic connectivity outage.

Suspected code areas

  • src/proxy.ts: clean end-stream and onClose branches around lines 1493-1542
  • src/h2-bridge.mjs: stderr and error handling for the child H2 bridge

Please verify that socket-close paths settle pending promises, clear stream/session state, and propagate a terminal event to the OpenAI-compatible response layer.

Validation suggestion

Add a replay or integration test that runs multiple Composer tool/result turns, injects an H2 socket close after stream activity, and asserts that the request reaches exactly one terminal state: completed, failed, or bounded retry. Also assert that no pending tool loop or busy state remains after the close.

Dominant language
TypeScript
Stars
278
Forks
31
Avg merge
4h 13m
Merged PRs (30d)
1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ephraimduncan/opencode-cursor

All issues in ephraimduncan/opencode-cursor

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.