Skip to content

[Provider compatibility] Cursor: incomplete tool-call streams poison conversation reuse #4874

Description

@MerryEcho

Client or integration

Codex App

Provider or upstream service

cursor

OpenCodex version

2.57.0

Endpoint or capability

/v1/responses Cursor protobuf tool calls

Current behaviour

On Codex Desktop through OpenCodex, Cursor models (including cursor/grok-4.6) talk Connect protobuf, not Responses. When a Cursor stream ends with a client tool still open, OpenCodex fail-closes:

Cursor stream ended with incomplete tool call(s)

That error is streamed. It is not thrown, so the overflow/invalid_argument remint ladder never runs. _cursorConversationId is assigned at the start of runTurn and persisted by continuationStateForResponse. The next turn reuses that id (or the deterministic thread hash). Cursor's side of the conversation is still waiting for mcpResult, so later turns in the same thread interrupt more often. Neighboring threads that never interrupted stay clean.

Native Composer replay also flushes unpaired toolCallStep history without a result, which looks like an interrupted attempt. External wire models such as grok-4.6 skip native mcpToolCall replay, so history repair alone cannot recover them; conversation remint is the path.

This is not a Cursor 429 / Ultra quota issue. The incomplete-tool event is a truncated stream, and CursorStreamTruncatedError is defined but never thrown.

Expected behaviour

Keep fail-closed on the current turn: do not emit a partial tool_call_start, and do not retry that send. After the incomplete-tool error is streamed, eligible non-isolated turns should remint the Cursor conversation id (same helper as overflow remint), persist the thread override for store:false clients, and invalidate the inherited checkpoint so the next turn does not resume a conversation left waiting for mcpResult. Isolated helper/compaction turns must not remint or donate that recovery to the parent.

Native Composer unpaired toolCallStep history should carry an honest [missing tool_result for this tool_use in history] placeholder (isError: true), matching Google #2199. External grok-4.6 stays on conversation remint.

Minimal redacted request or reproduction

Codex App -> local OpenCodex proxy -> cursor/grok-4.6 (or another Cursor model). Run a tool-using thread until the proxy reports Cursor stream ended with incomplete tool call(s), then continue the same thread. Later turns in that thread interrupt more often than a neighboring thread that never had a truncated tool stream.

Actual response or error

Cursor stream ended with incomplete tool call(s): <call id>. Arguments may be truncated; the call was not committed.
Subsequent turns in the same thread reuse the same Cursor conversation id and interrupt again.

Upstream documentation

No public Cursor Connect specification. The existing OpenCodex fail-closed path is finalizeTurnEvents in src/adapters/cursor/protobuf-events.ts. Overflow remint is the in-tree recovery helper this should reuse. Related repair: #2199 (Google missing tool_result). Distinct from xAI Responses adjacency (#4870 / #4871).

Suggested mapping or implementation notes

  • Add isCursorIncompleteToolCallMessage and flag that streamed error in src/adapters/cursor.ts.
  • After runOnce returns, remint via remintConversationId for non-isolated turns. Do not retry the current send.
  • Native conversationTurns flush: unpaired pendingToolCalls get toolCallStep(..., missingToolResult, codeMode).
  • Do not classify this as 429. Quota/rate cues stay on the existing overflow/rate path.

Additional context and attachments

Related: #2199, #3506, #1527, #4245, #4870 (xAI Responses, different adapter). Cursor 429 / empty-spin is a different failure and is not requested here.

Checks

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on an upstream specification or a concrete client requirement.

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

    providerProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions