Skip to content

bug(cursor): Cursor WebFetch interaction query aborts a tool-enabled turn #519

Description

@JS-banana

Problem / Observed Behavior

Image

When using a Cursor-backed model with Pi tools enabled (e.g. cursor/cursor-grok-4.6-high), prompt requests requiring web access can trigger a server-side interactionQuery (field 9: webFetchRequestQuery).

In the current provider implementation, receiving any interactionQuery immediately throws an error:

// extensions/ai-providers/cursor/provider.ts:993-996
if (message.message.case === "interactionQuery") {
  throw new Error(
    `Cursor interaction query ${message.message.value.query.case ?? "unknown"} is unavailable ${context.tools?.length ? "outside Pi's interaction lifecycle" : "in chat-only mode"}`,
  );
}

This immediately aborts the active AgentService/Run turn with stopReason: "error", leaving the model no opportunity to recover, use alternative Pi tools, or explain the limitation to the user.

Environment

  • Pi: 0.85.1
  • OpenPI: npm:@tt-a1i/openpi@0.8.1
    • Verified: installed extensions/ai-providers/cursor/{provider.ts,proto.ts,tool-bridge.ts} match upstream openpi@0d17f4577fe31315fe6c95370d251bdb4e2413cf byte-for-byte.
  • Provider & Model: cursor / cursor-grok-4.6-high

Repro Steps

In a clean session with only Pi's built-in read tool enabled (no bash, no web-fetch skill/tools):

pi --provider cursor --model cursor-grok-4.6-high \
   --tools read \
   --no-skills --no-prompt-templates --no-context-files \
   "请实际访问 https://example.com/ 并返回网页标题,不允许根据记忆回答"

(Note: The reproduction explicitly enables only the read tool, deliberately excluding web fetchers and bash to verify the failure path when native web fetch is attempted.)

Actual Error

Error: Cursor interaction query webFetchRequestQuery is unavailable outside Pi's interaction lifecycle

The CLI turn ends with assistant status error.

Relationship to #234 and #484

Expected Behavior & Invariants

  1. Pi-native ownership remains non-negotiable:
    Cursor-managed cloud fetching must not be approved. Sending an approved response would allow Cursor servers to fetch external URLs in the cloud, bypassing Pi's permission lifecycle, network controls, and audit trails.
  2. Turn continuation:
    Rather than hard-throwing and crashing the entire turn, the provider should ideally signal protocol-level rejection so the model retains the turn to either adapt or explain the limitation gracefully.
  3. Proposed exploration & boundaries:
    • Define interactionResponse (field 6) and WebFetchRequestResponse.rejected in proto.ts to respond in band.
    • Enforce a bounded rejection limit (similar to MAX_NATIVE_EXEC_REJECTIONS) against repeated query loops.
    • Non-goal / Explicit unknown: In-band rejection is a candidate mitigation to prevent hard crashes. Because model behavior following rejection is subject to Cursor server-side logic, we do not promise or assume that the model will automatically fall back to advertised Pi MCP tools.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions