cursor-opencode-provider 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,10 +30,17 @@ export function createMessageTypes() {
30
30
  // Display ToolCall (interaction_update.tool_call_*) — agent.v1 oneof, not
31
31
  // {tool_name,args} strings. Args-only wrappers are enough to bridge into
32
32
  // OpenCode; result payloads are ignored on decode.
33
+ root.add(new protobuf.Enum("TodoStatus", {
34
+ TODO_STATUS_UNSPECIFIED: 0,
35
+ TODO_STATUS_PENDING: 1,
36
+ TODO_STATUS_IN_PROGRESS: 2,
37
+ TODO_STATUS_COMPLETED: 3,
38
+ TODO_STATUS_CANCELLED: 4,
39
+ }));
33
40
  addType(root, "TodoItem", [
34
41
  { id: 1, name: "id", type: "string" },
35
42
  { id: 2, name: "content", type: "string" },
36
- { id: 3, name: "status", type: "int32" },
43
+ { id: 3, name: "status", type: "TodoStatus" },
37
44
  { id: 4, name: "created_at", type: "int64" },
38
45
  { id: 5, name: "updated_at", type: "int64" },
39
46
  { id: 6, name: "dependencies", type: "string", repeated: true },
@@ -127,6 +134,33 @@ export function createMessageTypes() {
127
134
  { id: 6, name: "agent_id", type: "string" },
128
135
  ]);
129
136
  addType(root, "TaskToolCall", [{ id: 1, name: "args", type: "TaskToolArgs" }]);
137
+ // Native subagent execution is separate from the display-only TaskToolCall.
138
+ // Cursor asks the local client to run the task through ExecServerMessage #28
139
+ // and waits for the correlated SubagentResult at ExecClientMessage #28.
140
+ addType(root, "SubagentArgs", [
141
+ { id: 1, name: "tool_call_id", type: "string" },
142
+ { id: 2, name: "subagent_type", type: "string" },
143
+ { id: 3, name: "model_id", type: "string" },
144
+ { id: 4, name: "prompt", type: "string" },
145
+ { id: 5, name: "readonly", type: "bool" },
146
+ { id: 6, name: "resume_agent_id", type: "string" },
147
+ { id: 7, name: "run_in_background", type: "bool" },
148
+ ]);
149
+ addType(root, "SubagentSuccess", [
150
+ { id: 1, name: "agent_id", type: "string" },
151
+ { id: 2, name: "final_message", type: "string" },
152
+ { id: 3, name: "tool_call_count", type: "int32" },
153
+ { id: 4, name: "background_reason", type: "int32" },
154
+ { id: 5, name: "transcript_path", type: "string" },
155
+ ]);
156
+ addType(root, "SubagentError", [
157
+ { id: 1, name: "agent_id", type: "string" },
158
+ { id: 2, name: "error", type: "string" },
159
+ ]);
160
+ addType(root, "SubagentResult", [
161
+ { id: 1, name: "success", type: "SubagentSuccess" },
162
+ { id: 2, name: "error", type: "SubagentError" },
163
+ ], [{ name: "result", fields: ["success", "error"] }]);
130
164
  addType(root, "AskQuestionOption", [
131
165
  { id: 1, name: "id", type: "string" },
132
166
  { id: 2, name: "label", type: "string" },
@@ -202,7 +236,8 @@ export function createMessageTypes() {
202
236
  addType(root, "PiLsToolCall", [{ id: 1, name: "args", type: "PiLsToolArgs" }]);
203
237
  // Display-only native tools Cursor may complete without an ExecServerMessage.
204
238
  addType(root, "ReadTodosArgs", [
205
- { id: 1, name: "todo_ids", type: "string", repeated: true },
239
+ { id: 1, name: "status_filter", type: "TodoStatus", repeated: true },
240
+ { id: 2, name: "id_filter", type: "string", repeated: true },
206
241
  ]);
207
242
  addType(root, "ReadTodosToolCall", [{ id: 1, name: "args", type: "ReadTodosArgs" }]);
208
243
  addType(root, "AwaitArgs", [
@@ -483,6 +518,10 @@ export function createMessageTypes() {
483
518
  { id: 2, name: "working_directory", type: "string" },
484
519
  { id: 3, name: "timeout", type: "uint32" },
485
520
  { id: 4, name: "tool_call_id", type: "string" },
521
+ // Canonical agent.v1 fields used by the native CLI to distinguish a
522
+ // foreground cancellation deadline from a soft background handoff.
523
+ { id: 13, name: "timeout_behavior", type: "uint32" },
524
+ { id: 14, name: "hard_timeout", type: "uint32" },
486
525
  ]);
487
526
  addType(root, "ShellStreamStart", []); // optional SandboxPolicy only; empty is valid
488
527
  addType(root, "ShellStreamStdout", [{ id: 1, name: "data", type: "string" }]);
@@ -490,7 +529,18 @@ export function createMessageTypes() {
490
529
  // agent.v1: code is uint32; protobufjs must emit code=0 (defaults are load-bearing).
491
530
  addType(root, "ShellStreamExit", [
492
531
  { id: 1, name: "code", type: "uint32" },
532
+ { id: 2, name: "cwd", type: "string" },
493
533
  { id: 4, name: "aborted", type: "bool" },
534
+ { id: 5, name: "abort_reason", type: "uint32" },
535
+ { id: 6, name: "local_execution_time_ms", type: "uint32" },
536
+ ]);
537
+ addType(root, "ShellStreamBackgrounded", [
538
+ { id: 1, name: "shell_id", type: "uint32" },
539
+ { id: 2, name: "command", type: "string" },
540
+ { id: 3, name: "working_directory", type: "string" },
541
+ { id: 4, name: "pid", type: "uint32" },
542
+ { id: 5, name: "ms_to_wait", type: "uint32" },
543
+ { id: 6, name: "reason", type: "uint32" },
494
544
  ]);
495
545
  // ShellRejected / ShellPermissionDenied (shared with ShellResult) — reason/error at #3.
496
546
  addType(root, "ShellRejected", [
@@ -503,6 +553,36 @@ export function createMessageTypes() {
503
553
  { id: 2, name: "working_directory", type: "string" },
504
554
  { id: 3, name: "error", type: "string" },
505
555
  ]);
556
+ // Cursor's non-blocking shell path is a separate exec variant from the
557
+ // foreground ShellStream above. The host only needs the fields used at the
558
+ // OpenCode boundary; protobufjs safely skips the richer classifier/approval
559
+ // messages that are private to Cursor's native client.
560
+ addType(root, "BackgroundShellSpawnArgs", [
561
+ { id: 1, name: "command", type: "string" },
562
+ { id: 2, name: "working_directory", type: "string" },
563
+ { id: 3, name: "tool_call_id", type: "string" },
564
+ { id: 6, name: "enable_write_shell_stdin_tool", type: "bool" },
565
+ { id: 7, name: "description", type: "string" },
566
+ { id: 12, name: "skip_approval", type: "bool" },
567
+ { id: 13, name: "conversation_id", type: "string" },
568
+ ]);
569
+ addType(root, "BackgroundShellSpawnSuccess", [
570
+ { id: 1, name: "shell_id", type: "uint32" },
571
+ { id: 2, name: "command", type: "string" },
572
+ { id: 3, name: "working_directory", type: "string" },
573
+ { id: 4, name: "pid", type: "uint32" },
574
+ ]);
575
+ addType(root, "BackgroundShellSpawnError", [
576
+ { id: 1, name: "command", type: "string" },
577
+ { id: 2, name: "working_directory", type: "string" },
578
+ { id: 3, name: "error", type: "string" },
579
+ ]);
580
+ addType(root, "BackgroundShellSpawnResult", [
581
+ { id: 1, name: "success", type: "BackgroundShellSpawnSuccess" },
582
+ { id: 2, name: "error", type: "BackgroundShellSpawnError" },
583
+ { id: 3, name: "rejected", type: "ShellRejected" },
584
+ { id: 4, name: "permission_denied", type: "ShellPermissionDenied" },
585
+ ], [{ name: "result", fields: ["success", "error", "rejected", "permission_denied"] }]);
506
586
  addType(root, "ShellStream", [
507
587
  { id: 1, name: "stdout", type: "ShellStreamStdout" },
508
588
  { id: 2, name: "stderr", type: "ShellStreamStderr" },
@@ -510,7 +590,8 @@ export function createMessageTypes() {
510
590
  { id: 4, name: "start", type: "ShellStreamStart" },
511
591
  { id: 5, name: "rejected", type: "ShellRejected" },
512
592
  { id: 6, name: "permission_denied", type: "ShellPermissionDenied" },
513
- ], [{ name: "event", fields: ["stdout", "stderr", "exit", "start", "rejected", "permission_denied"] }]);
593
+ { id: 7, name: "backgrounded", type: "ShellStreamBackgrounded" },
594
+ ], [{ name: "event", fields: ["stdout", "stderr", "exit", "start", "rejected", "permission_denied", "backgrounded"] }]);
514
595
  addType(root, "GlobArgs", [
515
596
  { id: 1, name: "target_directory", type: "string" },
516
597
  { id: 2, name: "glob_pattern", type: "string" },
@@ -627,6 +708,10 @@ export function createMessageTypes() {
627
708
  { id: 1, name: "enabled", type: "bool" },
628
709
  { id: 2, name: "mcp_descriptors", type: "McpDescriptor", repeated: true },
629
710
  ]);
711
+ addType(root, "PermissionsAutoRunInstructions", [
712
+ { id: 1, name: "allow_instructions", type: "string", repeated: true },
713
+ { id: 2, name: "block_instructions", type: "string", repeated: true },
714
+ ]);
630
715
  addType(root, "RequestContextPayload", [
631
716
  { id: 2, name: "rules", type: "CursorRule", repeated: true },
632
717
  { id: 4, name: "env", type: "RequestContextEnv" },
@@ -648,8 +733,8 @@ export function createMessageTypes() {
648
733
  { id: 43, name: "agent_skills_info_complete", type: "bool" },
649
734
  { id: 44, name: "mcp_file_system_info_complete", type: "bool" },
650
735
  { id: 45, name: "git_status_info_complete", type: "bool" },
651
- { id: 46, name: "user_permissions_auto_run", type: "bool" },
652
- { id: 47, name: "project_permissions_auto_run", type: "bool" },
736
+ { id: 46, name: "user_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
737
+ { id: 47, name: "project_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
653
738
  ]);
654
739
  addType(root, "RequestContextSuccess", [
655
740
  { id: 1, name: "request_context", type: "RequestContextPayload" },
@@ -657,6 +742,39 @@ export function createMessageTypes() {
657
742
  addType(root, "RequestContextResult", [
658
743
  { id: 1, name: "success", type: "RequestContextSuccess" },
659
744
  ]);
745
+ // Cursor probes MCP server availability before emitting an MCP-backed tool
746
+ // call. OpenCode owns those servers, so answer from the descriptors already
747
+ // advertised in RequestContext rather than surfacing this as a user tool.
748
+ addType(root, "McpStateExecArgs", [
749
+ { id: 1, name: "server_identifiers", type: "string", repeated: true },
750
+ { id: 2, name: "kick_only", type: "bool" },
751
+ ]);
752
+ addType(root, "McpInstructions", [
753
+ { id: 1, name: "server_name", type: "string" },
754
+ { id: 2, name: "instructions", type: "string" },
755
+ { id: 3, name: "server_identifier", type: "string" },
756
+ ]);
757
+ addType(root, "McpStateServer", [
758
+ { id: 1, name: "server_name", type: "string" },
759
+ { id: 2, name: "server_identifier", type: "string" },
760
+ { id: 3, name: "plugin", type: "string" },
761
+ { id: 4, name: "marketplace", type: "string" },
762
+ // Unlike McpDescriptor (#23/#34), exec #36 returns the full canonical
763
+ // McpToolDefinition shape, including composite name and provider identity.
764
+ { id: 5, name: "tools", type: "McpToolDefinition", repeated: true },
765
+ { id: 6, name: "instructions", type: "McpInstructions", repeated: true },
766
+ { id: 7, name: "status", type: "string" },
767
+ ]);
768
+ addType(root, "McpStateSuccess", [
769
+ { id: 1, name: "servers", type: "McpStateServer", repeated: true },
770
+ ]);
771
+ addType(root, "McpStateError", [{ id: 1, name: "error", type: "string" }]);
772
+ addType(root, "McpStateRejected", [{ id: 1, name: "reason", type: "string" }]);
773
+ addType(root, "McpStateExecResult", [
774
+ { id: 1, name: "success", type: "McpStateSuccess" },
775
+ { id: 2, name: "error", type: "McpStateError" },
776
+ { id: 3, name: "rejected", type: "McpStateRejected" },
777
+ ], [{ name: "result", fields: ["success", "error", "rejected"] }]);
660
778
  // ExecServerMessage — server asks us to execute a tool
661
779
  addType(root, "ExecServerMessage", [
662
780
  { id: 1, name: "id", type: "uint32" },
@@ -670,6 +788,9 @@ export function createMessageTypes() {
670
788
  { id: 10, name: "request_context_args", type: "RequestContextArgs" },
671
789
  { id: 11, name: "mcp_args", type: "McpArgs" },
672
790
  { id: 14, name: "shell_stream_args", type: "ShellArgs" },
791
+ { id: 16, name: "background_shell_spawn_args", type: "BackgroundShellSpawnArgs" },
792
+ { id: 28, name: "subagent_args", type: "SubagentArgs" },
793
+ { id: 36, name: "mcp_state_exec_args", type: "McpStateExecArgs" },
673
794
  { id: 45, name: "pi_read_args", type: "PiReadToolArgs" },
674
795
  { id: 46, name: "pi_bash_args", type: "PiBashToolArgs" },
675
796
  { id: 47, name: "pi_edit_args", type: "PiEditToolArgs" },
@@ -679,7 +800,8 @@ export function createMessageTypes() {
679
800
  { id: 51, name: "pi_ls_args", type: "PiLsToolArgs" },
680
801
  ], [{ name: "args", fields: [
681
802
  "write_args", "delete_args", "grep_args", "read_args", "ls_args",
682
- "request_context_args", "mcp_args", "shell_stream_args",
803
+ "request_context_args", "mcp_args", "shell_stream_args", "background_shell_spawn_args", "mcp_state_exec_args",
804
+ "subagent_args",
683
805
  "pi_read_args", "pi_bash_args", "pi_edit_args", "pi_write_args",
684
806
  "pi_grep_args", "pi_find_args", "pi_ls_args",
685
807
  ] }]);
@@ -696,6 +818,9 @@ export function createMessageTypes() {
696
818
  { id: 10, name: "request_context_result", type: "RequestContextResult" },
697
819
  { id: 11, name: "mcp_result", type: "McpResult" },
698
820
  { id: 14, name: "shell_stream", type: "ShellStream" },
821
+ { id: 16, name: "background_shell_spawn_result", type: "BackgroundShellSpawnResult" },
822
+ { id: 28, name: "subagent_result", type: "SubagentResult" },
823
+ { id: 36, name: "mcp_state_exec_result", type: "McpStateExecResult" },
699
824
  { id: 46, name: "pi_read_result", type: "PiReadExecResult" },
700
825
  { id: 47, name: "pi_bash_result", type: "PiBashExecResult" },
701
826
  { id: 48, name: "pi_edit_result", type: "PiEditExecResult" },
@@ -705,7 +830,8 @@ export function createMessageTypes() {
705
830
  { id: 52, name: "pi_ls_result", type: "PiLsExecResult" },
706
831
  ], [{ name: "result", fields: [
707
832
  "write_result", "delete_result", "grep_result", "read_result", "ls_result",
708
- "request_context_result", "mcp_result", "shell_stream",
833
+ "request_context_result", "mcp_result", "shell_stream", "background_shell_spawn_result", "mcp_state_exec_result",
834
+ "subagent_result",
709
835
  "pi_read_result", "pi_bash_result", "pi_edit_result", "pi_write_result",
710
836
  "pi_grep_result", "pi_find_result", "pi_ls_result",
711
837
  ] }]);
@@ -743,19 +869,6 @@ export function createMessageTypes() {
743
869
  { id: 1, name: "text", type: "string" },
744
870
  { id: 2, name: "message_id", type: "string" },
745
871
  ]);
746
- // McpToolDefinition — agent.v1 shape used by RequestContext.tools (#7) and
747
- // AgentRunRequest.mcp_tools (#4). Capture 00074 / CLI: { #1 name (composite
748
- // <server>-<tool>), #2 description, #3 input_schema (Value bytes),
749
- // #4 provider_identifier, #5 tool_name }.
750
- // (Defined later as McpToolDefinition; keep a legacy alias type name for
751
- // any older encode paths that still look up "McpToolDescriptor".)
752
- addType(root, "McpToolDescriptor", [
753
- { id: 1, name: "name", type: "string" },
754
- { id: 2, name: "description", type: "string" },
755
- { id: 3, name: "input_schema", type: "bytes" },
756
- { id: 4, name: "provider_identifier", type: "string" },
757
- { id: 5, name: "tool_name", type: "string" },
758
- ]);
759
872
  // RequestContext — UserMessageAction #2. Live per-turn tools go here
760
873
  // (AgentRunRequest.mcp_tools #4 is prewarm-only / empty on real turns).
761
874
  addType(root, "RequestContext", [
@@ -779,8 +892,8 @@ export function createMessageTypes() {
779
892
  { id: 43, name: "agent_skills_info_complete", type: "bool" },
780
893
  { id: 44, name: "mcp_file_system_info_complete", type: "bool" },
781
894
  { id: 45, name: "git_status_info_complete", type: "bool" },
782
- { id: 46, name: "user_permissions_auto_run", type: "bool" },
783
- { id: 47, name: "project_permissions_auto_run", type: "bool" },
895
+ { id: 46, name: "user_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
896
+ { id: 47, name: "project_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
784
897
  ]);
785
898
  addType(root, "UserMessageAction", [
786
899
  { id: 1, name: "user_message", type: "UserMessage" },
@@ -834,8 +947,8 @@ export function createMessageTypes() {
834
947
  { id: 9, name: "requested_model", type: "RequestedModel" },
835
948
  { id: 10, name: "unknown_flag", type: "uint32" },
836
949
  { id: 12, name: "field_12", type: "uint32" },
837
- { id: 14, name: "available_models", type: "RequestedModel", repeated: true },
838
- { id: 16, name: "conversation_id_dup", type: "string" },
950
+ { id: 14, name: "selected_subagent_models", type: "RequestedModel", repeated: true },
951
+ { id: 16, name: "conversation_group_id", type: "string" },
839
952
  ]);
840
953
  // ── Client heartbeat ──
841
954
  addType(root, "ClientHeartbeat", []);
@@ -1,5 +1,4 @@
1
1
  import { type OpencodeToolDef } from "./tools.js";
2
- import type { ModelInfo } from "../models.js";
3
2
  export type SeedHistoryMessage = {
4
3
  role: "system" | "user" | "assistant";
5
4
  content: string;
@@ -28,7 +27,6 @@ export type RunRequestInput = {
28
27
  }>;
29
28
  maxMode?: boolean;
30
29
  messageId?: string;
31
- availableModels?: ModelInfo[];
32
30
  tools?: OpencodeToolDef[];
33
31
  /** Pre-resolved descriptors (including config-backed MCP server identity). */
34
32
  toolDescriptors?: Array<Record<string, unknown>>;
@@ -34,12 +34,6 @@ export function buildSeedConversationState(input) {
34
34
  obj.root_prompt_messages_json = messages;
35
35
  return type.encode(type.fromObject(obj)).finish();
36
36
  }
37
- function buildAvailableModels(models) {
38
- return models.map((m) => ({
39
- model_id: m.id,
40
- parameters: (m.variants ?? []).flatMap((v) => (v.parameterValues ?? []).map((p) => p)),
41
- }));
42
- }
43
37
  /**
44
38
  * Build an AgentClientMessage{run_request} for a conversation turn.
45
39
  *
@@ -88,8 +82,6 @@ export function buildRunRequest(input) {
88
82
  mcp_tools: { mcp_tools: mcpTools },
89
83
  unknown_flag: 0,
90
84
  field_12: 0,
91
- available_models: input.availableModels ? buildAvailableModels(input.availableModels) : [],
92
- conversation_id_dup: input.conversationId,
93
85
  };
94
86
  return encodeMessage("AgentClientMessage", {
95
87
  run_request: runRequest,
@@ -3,7 +3,7 @@
3
3
  // Cursor's per-turn tool descriptors carry the tool `input_schema` (a JSON
4
4
  // Schema object) as a `google.protobuf.Value` whose `struct_value` holds the
5
5
  // schema — NOT a JSON string. Verified against a live capture
6
- // (request_context #7 → McpToolDescriptor #3):
6
+ // (request_context #7 → McpToolDefinition #3):
7
7
  // 2a 9a07 0a10 0a04 74797065 1208 1a06 6f626a656374 ...
8
8
  // = Value{#5 struct_value: Struct{#1 fields: {"type": Value{#3 string "object"}}}}
9
9
  //
@@ -467,7 +467,9 @@ export function extractExecDisplayCallId(execMsg) {
467
467
  "ls_args",
468
468
  "delete_args",
469
469
  "shell_stream_args",
470
+ "background_shell_spawn_args",
470
471
  "mcp_args",
472
+ "subagent_args",
471
473
  ]) {
472
474
  const args = asRecord(execMsg[key]);
473
475
  if (!args)
@@ -1,3 +1,4 @@
1
+ import type { CursorShellOutcome } from "../shell-timeout.js";
1
2
  export declare const REQUEST_CONTEXT_RESULT_FIELD = 10;
2
3
  export type OpencodeToolDef = {
3
4
  name: string;
@@ -54,6 +55,8 @@ export type ParsedExecRequest = {
54
55
  resultField: string;
55
56
  /** Typed error to return without asking OpenCode to execute invalid args. */
56
57
  localError?: string;
58
+ /** Original request values needed by typed Cursor result messages. */
59
+ resultMetadata?: Record<string, unknown>;
57
60
  };
58
61
  export declare function parseExecServerMessage(msg: Record<string, unknown>): ParsedExecRequest | undefined;
59
62
  /**
@@ -84,6 +87,10 @@ export type ToolResultInput = {
84
87
  * rewritten. read_result is always a read, so it unwraps regardless.
85
88
  */
86
89
  toolName?: string;
90
+ /** Original request fields required by a typed result (background shell). */
91
+ resultMetadata?: Record<string, unknown>;
92
+ /** Structured shell completion captured by the OpenCode plugin hook. */
93
+ shellOutcome?: CursorShellOutcome;
87
94
  };
88
95
  /**
89
96
  * Build one or more ExecClientMessage frames for a tool result.
@@ -121,7 +128,7 @@ export declare function unwrapReadOutput(output: string): string;
121
128
  * OpenCode returns free-form text; we wrap it in the minimal success shape the
122
129
  * server accepts (verified against agent.v1 wire captures).
123
130
  */
124
- export declare function buildTypedExecResult(resultField: string, output: string, error?: string, toolName?: string): Record<string, unknown>;
131
+ export declare function buildTypedExecResult(resultField: string, output: string, error?: string, toolName?: string, resultMetadata?: Record<string, unknown>): Record<string, unknown>;
125
132
  export declare function buildToolCallPart(execMsg: ParsedExecRequest, sessionId: string): {
126
133
  toolCallId: string;
127
134
  toolName: string;
@@ -142,3 +149,9 @@ export declare function detectExecVariantField(agentServerPayload: Uint8Array):
142
149
  * Encode exec #10 request_context_result from a prebuilt RequestContext payload.
143
150
  */
144
151
  export declare function buildRequestContextResult(execId: number, requestContext: Record<string, unknown>): Uint8Array;
152
+ /**
153
+ * Answer Cursor's exec #36 MCP-state probe from the same descriptors advertised
154
+ * in RequestContext. OpenCode remains the executor; this only confirms that the
155
+ * provider's virtual MCP servers and their tools are available.
156
+ */
157
+ export declare function buildMcpStateResult(execId: number, args: Record<string, unknown>, requestContext: Record<string, unknown>): Uint8Array;