Skip to content

fix(tools): map cursor-agent subagentType to canonical subagent_type - #122

Merged
Nomadcxx merged 1 commit into
Nomadcxx:mainfrom
griffinmartin:fix/task-subagent-type
Aug 10, 2026
Merged

fix(tools): map cursor-agent subagentType to canonical subagent_type#122
Nomadcxx merged 1 commit into
Nomadcxx:mainfrom
griffinmartin:fix/task-subagent-type

Conversation

@griffinmartin

Copy link
Copy Markdown
Contributor

Summary

Under a Cursor-hosted model, every OpenCode task call can fail schema validation:

The task tool was called with invalid arguments: SchemaError(Missing key at ["subagent_type"]).
Please rewrite the input so it satisfies the expected schema.

The model emits the Cursor Task envelope instead of the OpenCode one. Two things differ, and ARG_KEY_ALIASES covered neither:

Cursor Task OpenCode task
key subagentType subagent_type
value "explore", or a single-key wrapper such as { "unspecified": {} } / { "custom": "reviewer" } plain string

Because the key never normalized, sanitizeArgumentsForSchema dropped it as an unexpected property and validation reported subagent_type missing. Retrying re-emits the same envelope, so the call never converges.

This adds:

  • ["subagenttype", "subagent_type"] to ARG_KEY_ALIASES. Key normalization (lowercase + strip non-alphanumerics) means the one entry covers subagentType, subagent_type, and subagenttype.
  • A task branch in normalizeToolSpecificArgs that resolves the value to a string: { custom: "reviewer" } carries the name in the value, while oneof markers such as { unspecified: {} } carry it in the key.
  • Aliases for the two values with an unambiguous OpenCode counterpart: unspecified and generalPurpose map to general.

Cursor-only agent types (computer_use, browser_use, shell, vm_setup_helper, video_review) are deliberately not mapped. They are forwarded untouched so OpenCode answers with its own Agent not found: "shell". Available agents: ..., which names the valid set and lets the model self-correct. Silently rewriting them to general would dispatch the wrong agent with no signal.

Cursor-only extras (agentId, attachments, mode, environment, respondingToMessageIds) already fall out via sanitizeArgumentsForSchema; a test pins that.

How it was found

Reading the cursor-agent client bundle (2026.08.04-aaa8809), whose mapSubagentType enumerates the vocabulary:

mapSubagentType(e){switch(e){
  case"computer_use":return"computer_use";
  case"explore":return"explore";
  case"video_review":case"media_review":return"video_review";
  case"browser_use":return"browser_use";
  case"shell":return"shell";
  case"vm_setup_helper":return"vm_setup_helper";
  case void 0:case"unspecified":return"unspecified";
  default:return{custom:e}}}

That default branch is where the object-shaped values come from, which is why resolving the value has to handle both the wrapper and the bare string.

Prior art: #60 (closed as a duplicate of #51) is the same report. It was addressed prompt-side via TASK_BRIDGE_JSON_CONTEXT plus a higher loop-guard threshold. That guidance only binds when the model chooses the bridge-JSON envelope; when it emits a native Cursor Task tool call instead, nothing normalized the arguments. This closes that path. Reproduced on 2.5.4 / main @ 013ff8e.

Test

  • 7 new cases in tests/unit/provider-tool-schema-compat.test.ts covering: key alias, oneof unwrap, unspecified to general, {custom:...} unwrap, cursor-only pass-through, an already-canonical value left untouched, and extras being dropped.
  • bun test tests/unit/provider-tool-schema-compat.test.ts: 46 pass / 0 fail (39 before).
  • bun run test:ci:unit: 572 pass / 5 fail. The failures are in tests/unit/proxy/plugin-resume.test.ts, reproduce on clean main (baseline 564 pass / 6 fail), and are flaky across repeat runs (3 / 6 / 5 failing). Unrelated to this change.

- add ["subagenttype", "subagent_type"] to ARG_KEY_ALIASES
- unwrap cursor-agent single-key subagent wrappers to a string
- map unspecified/generalPurpose to OpenCode general
- forward every other value untouched so OpenCode reports its own
  "Agent not found: X. Available agents: ..." instead of a schema error
@Nomadcxx
Nomadcxx merged commit a14338a into Nomadcxx:main Aug 10, 2026
2 checks passed
@Nomadcxx

Copy link
Copy Markdown
Owner

Thanks Griffin, I merged your patch unchanged and followed it with a small compatibility fix on main.

Your change now handles cursor-agent’s subagentType, including { unspecified: {} }, and converts it to opencode’s subagent_type.

The follow-up preserves configured opencode agents named unspecified or generalPurpose, including names inside { custom: ... } wrappers. Cursor’s built-in values still map to general.

I verified the combined tree with 585 unit tests, 43 integration tests with one intentional skip, the build, and an npm package dry-run.

Thanks for tracking down the task-loop failure and supplying the fixture and tests.

cheers, RAMA

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants