cursor-opencode-provider 0.2.3 → 0.2.5
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.
- package/README.md +36 -17
- package/SECURITY.md +42 -0
- package/dist/activity.d.ts +15 -0
- package/dist/activity.js +76 -0
- package/dist/auth.d.ts +2 -1
- package/dist/auth.js +19 -13
- package/dist/context/build.js +0 -7
- package/dist/context/rules.d.ts +4 -0
- package/dist/context/rules.js +53 -17
- package/dist/debug.d.ts +9 -0
- package/dist/debug.js +44 -4
- package/dist/errors.d.ts +59 -0
- package/dist/errors.js +199 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +4 -0
- package/dist/language-model.d.ts +54 -7
- package/dist/language-model.js +730 -197
- package/dist/models.d.ts +7 -0
- package/dist/models.js +259 -79
- package/dist/plugin.js +38 -11
- package/dist/protocol/exec-variants.d.ts +24 -0
- package/dist/protocol/exec-variants.js +55 -0
- package/dist/protocol/interactions.d.ts +8 -1
- package/dist/protocol/interactions.js +15 -2
- package/dist/protocol/messages.js +109 -26
- package/dist/protocol/request.d.ts +2 -4
- package/dist/protocol/request.js +0 -8
- package/dist/protocol/struct.js +1 -1
- package/dist/protocol/tool-call-bridge.js +13 -1
- package/dist/protocol/tools.d.ts +8 -1
- package/dist/protocol/tools.js +384 -39
- package/dist/session.d.ts +115 -8
- package/dist/session.js +362 -31
- package/dist/shell-timeout.d.ts +57 -0
- package/dist/shell-timeout.js +186 -0
- package/dist/transport/connect.d.ts +37 -1
- package/dist/transport/connect.js +679 -115
- package/package.json +8 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const CURSOR_EXEC_VARIANTS = [
|
|
2
|
+
{ requestField: 2, requestName: "shell_args", resultField: 2, resultName: "shell_result", handling: "unsupported" },
|
|
3
|
+
{ requestField: 3, requestName: "write_args", resultField: 3, resultName: "write_result", handling: "opencode-tool" },
|
|
4
|
+
{ requestField: 4, requestName: "delete_args", resultField: 4, resultName: "delete_result", handling: "opencode-tool" },
|
|
5
|
+
{ requestField: 5, requestName: "grep_args", resultField: 5, resultName: "grep_result", handling: "opencode-tool" },
|
|
6
|
+
{ requestField: 7, requestName: "read_args", resultField: 7, resultName: "read_result", handling: "opencode-tool" },
|
|
7
|
+
{ requestField: 8, requestName: "ls_args", resultField: 8, resultName: "ls_result", handling: "opencode-tool" },
|
|
8
|
+
{ requestField: 9, requestName: "diagnostics_args", resultField: 9, resultName: "diagnostics_result", handling: "unsupported" },
|
|
9
|
+
{ requestField: 10, requestName: "request_context_args", resultField: 10, resultName: "request_context_result", handling: "provider-control" },
|
|
10
|
+
{ requestField: 11, requestName: "mcp_args", resultField: 11, resultName: "mcp_result", handling: "opencode-tool" },
|
|
11
|
+
{ requestField: 14, requestName: "shell_stream_args", resultField: 14, resultName: "shell_stream", handling: "opencode-tool" },
|
|
12
|
+
{ requestField: 16, requestName: "background_shell_spawn_args", resultField: 16, resultName: "background_shell_spawn_result", handling: "opencode-tool" },
|
|
13
|
+
{ requestField: 17, requestName: "list_mcp_resources_exec_args", resultField: 17, resultName: "list_mcp_resources_exec_result", handling: "unsupported" },
|
|
14
|
+
{ requestField: 18, requestName: "read_mcp_resource_exec_args", resultField: 18, resultName: "read_mcp_resource_exec_result", handling: "unsupported" },
|
|
15
|
+
{ requestField: 20, requestName: "fetch_args", resultField: 20, resultName: "fetch_result", handling: "unsupported" },
|
|
16
|
+
{ requestField: 21, requestName: "record_screen_args", resultField: 21, resultName: "record_screen_result", handling: "unsupported" },
|
|
17
|
+
{ requestField: 22, requestName: "computer_use_args", resultField: 22, resultName: "computer_use_result", handling: "unsupported" },
|
|
18
|
+
{ requestField: 23, requestName: "write_shell_stdin_args", resultField: 23, resultName: "write_shell_stdin_result", handling: "unsupported" },
|
|
19
|
+
{ requestField: 27, requestName: "execute_hook_args", resultField: 27, resultName: "execute_hook_result", handling: "unsupported" },
|
|
20
|
+
{ requestField: 28, requestName: "subagent_args", resultField: 28, resultName: "subagent_result", handling: "opencode-tool" },
|
|
21
|
+
{ requestField: 29, requestName: "redacted_read_args", resultField: 29, resultName: "redacted_read_result", handling: "unsupported" },
|
|
22
|
+
{ requestField: 30, requestName: "force_background_shell_args", resultField: 30, resultName: "force_background_shell_result", handling: "unsupported" },
|
|
23
|
+
{ requestField: 31, requestName: "force_background_subagent_args", resultField: 31, resultName: "force_background_subagent_result", handling: "unsupported" },
|
|
24
|
+
{ requestField: 36, requestName: "mcp_state_exec_args", resultField: 36, resultName: "mcp_state_exec_result", handling: "provider-control" },
|
|
25
|
+
{ requestField: 37, requestName: "subagent_await_args", resultField: 37, resultName: "subagent_await_result", handling: "unsupported" },
|
|
26
|
+
{ requestField: 38, requestName: "smart_mode_classifier_args", resultField: 38, resultName: "smart_mode_classifier_result", handling: "unsupported" },
|
|
27
|
+
{ requestField: 40, requestName: "canvas_diagnostics_args", resultField: 40, resultName: "canvas_diagnostics_result", handling: "unsupported" },
|
|
28
|
+
{ requestField: 41, requestName: "shell_allowlist_precheck_args", resultField: 41, resultName: "shell_allowlist_precheck_result", handling: "unsupported" },
|
|
29
|
+
{ requestField: 42, requestName: "mcp_allowlist_precheck_args", resultField: 42, resultName: "mcp_allowlist_precheck_result", handling: "unsupported" },
|
|
30
|
+
{ requestField: 43, requestName: "web_fetch_allowlist_precheck_args", resultField: 43, resultName: "web_fetch_allowlist_precheck_result", handling: "unsupported" },
|
|
31
|
+
{ requestField: 44, requestName: "git_diff_request", resultField: 44, resultName: "git_diff_response", handling: "unsupported" },
|
|
32
|
+
{ requestField: 45, requestName: "pi_read_args", resultField: 46, resultName: "pi_read_result", handling: "opencode-tool" },
|
|
33
|
+
{ requestField: 46, requestName: "pi_bash_args", resultField: 47, resultName: "pi_bash_result", handling: "opencode-tool" },
|
|
34
|
+
{ requestField: 47, requestName: "pi_edit_args", resultField: 48, resultName: "pi_edit_result", handling: "opencode-tool" },
|
|
35
|
+
{ requestField: 48, requestName: "pi_write_args", resultField: 49, resultName: "pi_write_result", handling: "opencode-tool" },
|
|
36
|
+
{ requestField: 49, requestName: "pi_grep_args", resultField: 50, resultName: "pi_grep_result", handling: "opencode-tool" },
|
|
37
|
+
{ requestField: 50, requestName: "pi_find_args", resultField: 51, resultName: "pi_find_result", handling: "opencode-tool" },
|
|
38
|
+
{ requestField: 51, requestName: "pi_ls_args", resultField: 52, resultName: "pi_ls_result", handling: "opencode-tool" },
|
|
39
|
+
];
|
|
40
|
+
const BY_REQUEST_FIELD = new Map(CURSOR_EXEC_VARIANTS.map((variant) => [variant.requestField, variant]));
|
|
41
|
+
const BY_REQUEST_NAME = new Map(CURSOR_EXEC_VARIANTS.map((variant) => [variant.requestName, variant]));
|
|
42
|
+
export function cursorExecVariantByRequestField(field) {
|
|
43
|
+
return BY_REQUEST_FIELD.get(field);
|
|
44
|
+
}
|
|
45
|
+
export function cursorExecVariantByRequestName(name) {
|
|
46
|
+
return BY_REQUEST_NAME.get(name);
|
|
47
|
+
}
|
|
48
|
+
export function describeCursorExecVariant(field) {
|
|
49
|
+
if (field === undefined)
|
|
50
|
+
return "unknown request field";
|
|
51
|
+
const variant = cursorExecVariantByRequestField(field);
|
|
52
|
+
if (!variant)
|
|
53
|
+
return `unknown request field #${field}`;
|
|
54
|
+
return `${variant.requestName} (request field #${variant.requestField}, expected result ${variant.resultName} field #${variant.resultField}, handling=${variant.handling})`;
|
|
55
|
+
}
|
|
@@ -19,5 +19,12 @@ export declare class UnsupportedInteractionQueryError extends Error {
|
|
|
19
19
|
* instead of accidentally restoring the heartbeat-only deadlock.
|
|
20
20
|
*/
|
|
21
21
|
export declare function inspectInteractionQueryWire(agentServerPayload: Uint8Array): InteractionQueryWireInfo;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Build the immediate typed response required by Cursor's Run RPC.
|
|
24
|
+
*
|
|
25
|
+
* OpenCode has no Cursor UI callbacks, so every InteractionQuery is answered
|
|
26
|
+
* here with a conservative headless policy (reject UI-bound prompts; ack a few
|
|
27
|
+
* no-UI cases). See case 7 / F14 for create_plan auto-ack parity with Cursor
|
|
28
|
+
* CLI headless mode.
|
|
29
|
+
*/
|
|
23
30
|
export declare function handleInteractionQuery(query: Record<string, unknown>, agentServerPayload: Uint8Array): HandledInteraction;
|
|
@@ -51,7 +51,14 @@ export function inspectInteractionQueryWire(agentServerPayload) {
|
|
|
51
51
|
variantName: variantField === undefined ? undefined : variantNames[variantField],
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Build the immediate typed response required by Cursor's Run RPC.
|
|
56
|
+
*
|
|
57
|
+
* OpenCode has no Cursor UI callbacks, so every InteractionQuery is answered
|
|
58
|
+
* here with a conservative headless policy (reject UI-bound prompts; ack a few
|
|
59
|
+
* no-UI cases). See case 7 / F14 for create_plan auto-ack parity with Cursor
|
|
60
|
+
* CLI headless mode.
|
|
61
|
+
*/
|
|
55
62
|
export function handleInteractionQuery(query, agentServerPayload) {
|
|
56
63
|
const info = inspectInteractionQueryWire(agentServerPayload);
|
|
57
64
|
if (info.id === undefined || info.variantField === undefined || !info.variantName) {
|
|
@@ -80,8 +87,14 @@ export function handleInteractionQuery(query, agentServerPayload) {
|
|
|
80
87
|
outcome = "rejected";
|
|
81
88
|
break;
|
|
82
89
|
case 7:
|
|
90
|
+
// F14: create_plan_request_query auto-ack (Cursor CLI headless parity).
|
|
83
91
|
// Cursor CLI's headless fallback acknowledges plan creation without a
|
|
84
|
-
// client-side URI; the plan remains in
|
|
92
|
+
// client-side URI (`success` + empty `plan_uri`); the plan remains in
|
|
93
|
+
// conversation state / checkpoints. This provider mirrors that reply so
|
|
94
|
+
// the Run RPC does not deadlock waiting for UI approval. Impact: Cursor
|
|
95
|
+
// may treat the plan as accepted without an OpenCode UI confirm; local
|
|
96
|
+
// tool execution is still gated by OpenCode permissions. Do not change
|
|
97
|
+
// this to reject/prompt without CLI parity evidence.
|
|
85
98
|
response = { create_plan_request_response: { result: { success: {}, plan_uri: "" } } };
|
|
86
99
|
outcome = "acknowledged";
|
|
87
100
|
break;
|
|
@@ -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: "
|
|
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: "
|
|
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", [
|
|
@@ -322,8 +357,11 @@ export function createMessageTypes() {
|
|
|
322
357
|
{ id: 2, name: "content", type: "string" },
|
|
323
358
|
{ id: 3, name: "total_lines", type: "int32" },
|
|
324
359
|
{ id: 4, name: "file_size", type: "int64" },
|
|
360
|
+
{ id: 5, name: "data", type: "bytes" },
|
|
325
361
|
{ id: 6, name: "truncated", type: "bool" },
|
|
326
|
-
|
|
362
|
+
{ id: 7, name: "output_blob_id", type: "bytes" },
|
|
363
|
+
{ id: 8, name: "range_applied", type: "bool" },
|
|
364
|
+
], [{ name: "output", fields: ["content", "data"] }]);
|
|
327
365
|
addType(root, "ReadError", [
|
|
328
366
|
{ id: 1, name: "path", type: "string" },
|
|
329
367
|
{ id: 2, name: "error", type: "string" },
|
|
@@ -483,6 +521,10 @@ export function createMessageTypes() {
|
|
|
483
521
|
{ id: 2, name: "working_directory", type: "string" },
|
|
484
522
|
{ id: 3, name: "timeout", type: "uint32" },
|
|
485
523
|
{ id: 4, name: "tool_call_id", type: "string" },
|
|
524
|
+
// Canonical agent.v1 fields used by the native CLI to distinguish a
|
|
525
|
+
// foreground cancellation deadline from a soft background handoff.
|
|
526
|
+
{ id: 13, name: "timeout_behavior", type: "uint32" },
|
|
527
|
+
{ id: 14, name: "hard_timeout", type: "uint32" },
|
|
486
528
|
]);
|
|
487
529
|
addType(root, "ShellStreamStart", []); // optional SandboxPolicy only; empty is valid
|
|
488
530
|
addType(root, "ShellStreamStdout", [{ id: 1, name: "data", type: "string" }]);
|
|
@@ -490,7 +532,18 @@ export function createMessageTypes() {
|
|
|
490
532
|
// agent.v1: code is uint32; protobufjs must emit code=0 (defaults are load-bearing).
|
|
491
533
|
addType(root, "ShellStreamExit", [
|
|
492
534
|
{ id: 1, name: "code", type: "uint32" },
|
|
535
|
+
{ id: 2, name: "cwd", type: "string" },
|
|
493
536
|
{ id: 4, name: "aborted", type: "bool" },
|
|
537
|
+
{ id: 5, name: "abort_reason", type: "uint32" },
|
|
538
|
+
{ id: 6, name: "local_execution_time_ms", type: "uint32" },
|
|
539
|
+
]);
|
|
540
|
+
addType(root, "ShellStreamBackgrounded", [
|
|
541
|
+
{ id: 1, name: "shell_id", type: "uint32" },
|
|
542
|
+
{ id: 2, name: "command", type: "string" },
|
|
543
|
+
{ id: 3, name: "working_directory", type: "string" },
|
|
544
|
+
{ id: 4, name: "pid", type: "uint32" },
|
|
545
|
+
{ id: 5, name: "ms_to_wait", type: "uint32" },
|
|
546
|
+
{ id: 6, name: "reason", type: "uint32" },
|
|
494
547
|
]);
|
|
495
548
|
// ShellRejected / ShellPermissionDenied (shared with ShellResult) — reason/error at #3.
|
|
496
549
|
addType(root, "ShellRejected", [
|
|
@@ -503,6 +556,36 @@ export function createMessageTypes() {
|
|
|
503
556
|
{ id: 2, name: "working_directory", type: "string" },
|
|
504
557
|
{ id: 3, name: "error", type: "string" },
|
|
505
558
|
]);
|
|
559
|
+
// Cursor's non-blocking shell path is a separate exec variant from the
|
|
560
|
+
// foreground ShellStream above. The host only needs the fields used at the
|
|
561
|
+
// OpenCode boundary; protobufjs safely skips the richer classifier/approval
|
|
562
|
+
// messages that are private to Cursor's native client.
|
|
563
|
+
addType(root, "BackgroundShellSpawnArgs", [
|
|
564
|
+
{ id: 1, name: "command", type: "string" },
|
|
565
|
+
{ id: 2, name: "working_directory", type: "string" },
|
|
566
|
+
{ id: 3, name: "tool_call_id", type: "string" },
|
|
567
|
+
{ id: 6, name: "enable_write_shell_stdin_tool", type: "bool" },
|
|
568
|
+
{ id: 7, name: "description", type: "string" },
|
|
569
|
+
{ id: 12, name: "skip_approval", type: "bool" },
|
|
570
|
+
{ id: 13, name: "conversation_id", type: "string" },
|
|
571
|
+
]);
|
|
572
|
+
addType(root, "BackgroundShellSpawnSuccess", [
|
|
573
|
+
{ id: 1, name: "shell_id", type: "uint32" },
|
|
574
|
+
{ id: 2, name: "command", type: "string" },
|
|
575
|
+
{ id: 3, name: "working_directory", type: "string" },
|
|
576
|
+
{ id: 4, name: "pid", type: "uint32" },
|
|
577
|
+
]);
|
|
578
|
+
addType(root, "BackgroundShellSpawnError", [
|
|
579
|
+
{ id: 1, name: "command", type: "string" },
|
|
580
|
+
{ id: 2, name: "working_directory", type: "string" },
|
|
581
|
+
{ id: 3, name: "error", type: "string" },
|
|
582
|
+
]);
|
|
583
|
+
addType(root, "BackgroundShellSpawnResult", [
|
|
584
|
+
{ id: 1, name: "success", type: "BackgroundShellSpawnSuccess" },
|
|
585
|
+
{ id: 2, name: "error", type: "BackgroundShellSpawnError" },
|
|
586
|
+
{ id: 3, name: "rejected", type: "ShellRejected" },
|
|
587
|
+
{ id: 4, name: "permission_denied", type: "ShellPermissionDenied" },
|
|
588
|
+
], [{ name: "result", fields: ["success", "error", "rejected", "permission_denied"] }]);
|
|
506
589
|
addType(root, "ShellStream", [
|
|
507
590
|
{ id: 1, name: "stdout", type: "ShellStreamStdout" },
|
|
508
591
|
{ id: 2, name: "stderr", type: "ShellStreamStderr" },
|
|
@@ -510,7 +593,8 @@ export function createMessageTypes() {
|
|
|
510
593
|
{ id: 4, name: "start", type: "ShellStreamStart" },
|
|
511
594
|
{ id: 5, name: "rejected", type: "ShellRejected" },
|
|
512
595
|
{ id: 6, name: "permission_denied", type: "ShellPermissionDenied" },
|
|
513
|
-
|
|
596
|
+
{ id: 7, name: "backgrounded", type: "ShellStreamBackgrounded" },
|
|
597
|
+
], [{ name: "event", fields: ["stdout", "stderr", "exit", "start", "rejected", "permission_denied", "backgrounded"] }]);
|
|
514
598
|
addType(root, "GlobArgs", [
|
|
515
599
|
{ id: 1, name: "target_directory", type: "string" },
|
|
516
600
|
{ id: 2, name: "glob_pattern", type: "string" },
|
|
@@ -627,6 +711,10 @@ export function createMessageTypes() {
|
|
|
627
711
|
{ id: 1, name: "enabled", type: "bool" },
|
|
628
712
|
{ id: 2, name: "mcp_descriptors", type: "McpDescriptor", repeated: true },
|
|
629
713
|
]);
|
|
714
|
+
addType(root, "PermissionsAutoRunInstructions", [
|
|
715
|
+
{ id: 1, name: "allow_instructions", type: "string", repeated: true },
|
|
716
|
+
{ id: 2, name: "block_instructions", type: "string", repeated: true },
|
|
717
|
+
]);
|
|
630
718
|
addType(root, "RequestContextPayload", [
|
|
631
719
|
{ id: 2, name: "rules", type: "CursorRule", repeated: true },
|
|
632
720
|
{ id: 4, name: "env", type: "RequestContextEnv" },
|
|
@@ -648,8 +736,8 @@ export function createMessageTypes() {
|
|
|
648
736
|
{ id: 43, name: "agent_skills_info_complete", type: "bool" },
|
|
649
737
|
{ id: 44, name: "mcp_file_system_info_complete", type: "bool" },
|
|
650
738
|
{ id: 45, name: "git_status_info_complete", type: "bool" },
|
|
651
|
-
{ id: 46, name: "user_permissions_auto_run", type: "
|
|
652
|
-
{ id: 47, name: "project_permissions_auto_run", type: "
|
|
739
|
+
{ id: 46, name: "user_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
|
|
740
|
+
{ id: 47, name: "project_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
|
|
653
741
|
]);
|
|
654
742
|
addType(root, "RequestContextSuccess", [
|
|
655
743
|
{ id: 1, name: "request_context", type: "RequestContextPayload" },
|
|
@@ -674,7 +762,9 @@ export function createMessageTypes() {
|
|
|
674
762
|
{ id: 2, name: "server_identifier", type: "string" },
|
|
675
763
|
{ id: 3, name: "plugin", type: "string" },
|
|
676
764
|
{ id: 4, name: "marketplace", type: "string" },
|
|
677
|
-
|
|
765
|
+
// Unlike McpDescriptor (#23/#34), exec #36 returns the full canonical
|
|
766
|
+
// McpToolDefinition shape, including composite name and provider identity.
|
|
767
|
+
{ id: 5, name: "tools", type: "McpToolDefinition", repeated: true },
|
|
678
768
|
{ id: 6, name: "instructions", type: "McpInstructions", repeated: true },
|
|
679
769
|
{ id: 7, name: "status", type: "string" },
|
|
680
770
|
]);
|
|
@@ -701,6 +791,8 @@ export function createMessageTypes() {
|
|
|
701
791
|
{ id: 10, name: "request_context_args", type: "RequestContextArgs" },
|
|
702
792
|
{ id: 11, name: "mcp_args", type: "McpArgs" },
|
|
703
793
|
{ id: 14, name: "shell_stream_args", type: "ShellArgs" },
|
|
794
|
+
{ id: 16, name: "background_shell_spawn_args", type: "BackgroundShellSpawnArgs" },
|
|
795
|
+
{ id: 28, name: "subagent_args", type: "SubagentArgs" },
|
|
704
796
|
{ id: 36, name: "mcp_state_exec_args", type: "McpStateExecArgs" },
|
|
705
797
|
{ id: 45, name: "pi_read_args", type: "PiReadToolArgs" },
|
|
706
798
|
{ id: 46, name: "pi_bash_args", type: "PiBashToolArgs" },
|
|
@@ -711,7 +803,8 @@ export function createMessageTypes() {
|
|
|
711
803
|
{ id: 51, name: "pi_ls_args", type: "PiLsToolArgs" },
|
|
712
804
|
], [{ name: "args", fields: [
|
|
713
805
|
"write_args", "delete_args", "grep_args", "read_args", "ls_args",
|
|
714
|
-
"request_context_args", "mcp_args", "shell_stream_args", "mcp_state_exec_args",
|
|
806
|
+
"request_context_args", "mcp_args", "shell_stream_args", "background_shell_spawn_args", "mcp_state_exec_args",
|
|
807
|
+
"subagent_args",
|
|
715
808
|
"pi_read_args", "pi_bash_args", "pi_edit_args", "pi_write_args",
|
|
716
809
|
"pi_grep_args", "pi_find_args", "pi_ls_args",
|
|
717
810
|
] }]);
|
|
@@ -728,6 +821,8 @@ export function createMessageTypes() {
|
|
|
728
821
|
{ id: 10, name: "request_context_result", type: "RequestContextResult" },
|
|
729
822
|
{ id: 11, name: "mcp_result", type: "McpResult" },
|
|
730
823
|
{ id: 14, name: "shell_stream", type: "ShellStream" },
|
|
824
|
+
{ id: 16, name: "background_shell_spawn_result", type: "BackgroundShellSpawnResult" },
|
|
825
|
+
{ id: 28, name: "subagent_result", type: "SubagentResult" },
|
|
731
826
|
{ id: 36, name: "mcp_state_exec_result", type: "McpStateExecResult" },
|
|
732
827
|
{ id: 46, name: "pi_read_result", type: "PiReadExecResult" },
|
|
733
828
|
{ id: 47, name: "pi_bash_result", type: "PiBashExecResult" },
|
|
@@ -738,7 +833,8 @@ export function createMessageTypes() {
|
|
|
738
833
|
{ id: 52, name: "pi_ls_result", type: "PiLsExecResult" },
|
|
739
834
|
], [{ name: "result", fields: [
|
|
740
835
|
"write_result", "delete_result", "grep_result", "read_result", "ls_result",
|
|
741
|
-
"request_context_result", "mcp_result", "shell_stream", "mcp_state_exec_result",
|
|
836
|
+
"request_context_result", "mcp_result", "shell_stream", "background_shell_spawn_result", "mcp_state_exec_result",
|
|
837
|
+
"subagent_result",
|
|
742
838
|
"pi_read_result", "pi_bash_result", "pi_edit_result", "pi_write_result",
|
|
743
839
|
"pi_grep_result", "pi_find_result", "pi_ls_result",
|
|
744
840
|
] }]);
|
|
@@ -776,19 +872,6 @@ export function createMessageTypes() {
|
|
|
776
872
|
{ id: 1, name: "text", type: "string" },
|
|
777
873
|
{ id: 2, name: "message_id", type: "string" },
|
|
778
874
|
]);
|
|
779
|
-
// McpToolDefinition — agent.v1 shape used by RequestContext.tools (#7) and
|
|
780
|
-
// AgentRunRequest.mcp_tools (#4). Capture 00074 / CLI: { #1 name (composite
|
|
781
|
-
// <server>-<tool>), #2 description, #3 input_schema (Value bytes),
|
|
782
|
-
// #4 provider_identifier, #5 tool_name }.
|
|
783
|
-
// (Defined later as McpToolDefinition; keep a legacy alias type name for
|
|
784
|
-
// any older encode paths that still look up "McpToolDescriptor".)
|
|
785
|
-
addType(root, "McpToolDescriptor", [
|
|
786
|
-
{ id: 1, name: "name", type: "string" },
|
|
787
|
-
{ id: 2, name: "description", type: "string" },
|
|
788
|
-
{ id: 3, name: "input_schema", type: "bytes" },
|
|
789
|
-
{ id: 4, name: "provider_identifier", type: "string" },
|
|
790
|
-
{ id: 5, name: "tool_name", type: "string" },
|
|
791
|
-
]);
|
|
792
875
|
// RequestContext — UserMessageAction #2. Live per-turn tools go here
|
|
793
876
|
// (AgentRunRequest.mcp_tools #4 is prewarm-only / empty on real turns).
|
|
794
877
|
addType(root, "RequestContext", [
|
|
@@ -812,8 +895,8 @@ export function createMessageTypes() {
|
|
|
812
895
|
{ id: 43, name: "agent_skills_info_complete", type: "bool" },
|
|
813
896
|
{ id: 44, name: "mcp_file_system_info_complete", type: "bool" },
|
|
814
897
|
{ id: 45, name: "git_status_info_complete", type: "bool" },
|
|
815
|
-
{ id: 46, name: "user_permissions_auto_run", type: "
|
|
816
|
-
{ id: 47, name: "project_permissions_auto_run", type: "
|
|
898
|
+
{ id: 46, name: "user_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
|
|
899
|
+
{ id: 47, name: "project_permissions_auto_run", type: "PermissionsAutoRunInstructions" },
|
|
817
900
|
]);
|
|
818
901
|
addType(root, "UserMessageAction", [
|
|
819
902
|
{ id: 1, name: "user_message", type: "UserMessage" },
|
|
@@ -867,8 +950,8 @@ export function createMessageTypes() {
|
|
|
867
950
|
{ id: 9, name: "requested_model", type: "RequestedModel" },
|
|
868
951
|
{ id: 10, name: "unknown_flag", type: "uint32" },
|
|
869
952
|
{ id: 12, name: "field_12", type: "uint32" },
|
|
870
|
-
{ id: 14, name: "
|
|
871
|
-
{ id: 16, name: "
|
|
953
|
+
{ id: 14, name: "selected_subagent_models", type: "RequestedModel", repeated: true },
|
|
954
|
+
{ id: 16, name: "conversation_group_id", type: "string" },
|
|
872
955
|
]);
|
|
873
956
|
// ── Client heartbeat ──
|
|
874
957
|
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;
|
|
@@ -11,8 +10,8 @@ export type RunRequestInput = {
|
|
|
11
10
|
systemPrompt?: string;
|
|
12
11
|
/**
|
|
13
12
|
* Prior chat turns for a seed ConversationStateStructure (no checkpoint).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Tool outputs, when required for compaction/recovery, are represented as
|
|
14
|
+
* user-role OpenCode host observations rather than assistant-authored prose.
|
|
16
15
|
*/
|
|
17
16
|
history?: SeedHistoryMessage[];
|
|
18
17
|
/**
|
|
@@ -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>>;
|
package/dist/protocol/request.js
CHANGED
|
@@ -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,
|
package/dist/protocol/struct.js
CHANGED
|
@@ -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 →
|
|
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
|
//
|
|
@@ -7,7 +7,12 @@ const TODO_STATUS = {
|
|
|
7
7
|
3: "completed",
|
|
8
8
|
4: "cancelled",
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Cursor ToolCall oneof field → default OpenCode tool id.
|
|
12
|
+
*
|
|
13
|
+
* F11: `delete_tool_call` has no OpenCode builtin; it remaps to bash (see the
|
|
14
|
+
* delete_tool_call branch below for `rm -f -- <path>`).
|
|
15
|
+
*/
|
|
11
16
|
const VARIANT_TO_OPENCODE = {
|
|
12
17
|
shell_tool_call: "bash",
|
|
13
18
|
delete_tool_call: "bash",
|
|
@@ -121,6 +126,10 @@ export function parseDisplayToolCall(callId, toolCall) {
|
|
|
121
126
|
args: mcpArgs,
|
|
122
127
|
};
|
|
123
128
|
}
|
|
129
|
+
// create_plan_tool_call here is display-state mirroring into todowrite.
|
|
130
|
+
// Separately, InteractionQuery create_plan_request_query is auto-acked in
|
|
131
|
+
// protocol/interactions.ts (F14 / CLI headless parity) — that ack is not an
|
|
132
|
+
// execution of this display payload.
|
|
124
133
|
if (variant === "update_todos_tool_call" || variant === "create_plan_tool_call") {
|
|
125
134
|
const result = asRecord(payload.result);
|
|
126
135
|
const success = asRecord(result?.success);
|
|
@@ -238,6 +247,7 @@ export function parseDisplayToolCall(callId, toolCall) {
|
|
|
238
247
|
args: {},
|
|
239
248
|
};
|
|
240
249
|
}
|
|
250
|
+
// F11: display-path delete → bash `rm -f` (OpenCode has no delete tool).
|
|
241
251
|
if (variant === "delete_tool_call") {
|
|
242
252
|
const path = typeof args.path === "string" ? args.path : "";
|
|
243
253
|
return {
|
|
@@ -467,7 +477,9 @@ export function extractExecDisplayCallId(execMsg) {
|
|
|
467
477
|
"ls_args",
|
|
468
478
|
"delete_args",
|
|
469
479
|
"shell_stream_args",
|
|
480
|
+
"background_shell_spawn_args",
|
|
470
481
|
"mcp_args",
|
|
482
|
+
"subagent_args",
|
|
471
483
|
]) {
|
|
472
484
|
const args = asRecord(execMsg[key]);
|
|
473
485
|
if (!args)
|
package/dist/protocol/tools.d.ts
CHANGED
|
@@ -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;
|