cursor-opencode-provider 0.1.5 → 0.2.2

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.
@@ -27,22 +27,256 @@ export function createMessageTypes() {
27
27
  { id: 5, name: "reasoning_tokens", type: "uint32" },
28
28
  ]);
29
29
  addType(root, "Heartbeat", []);
30
- // Tool call types
31
- addType(root, "ToolCall", [
32
- { id: 1, name: "call_id", type: "string" },
30
+ // Display ToolCall (interaction_update.tool_call_*) — agent.v1 oneof, not
31
+ // {tool_name,args} strings. Args-only wrappers are enough to bridge into
32
+ // OpenCode; result payloads are ignored on decode.
33
+ addType(root, "TodoItem", [
34
+ { id: 1, name: "id", type: "string" },
35
+ { id: 2, name: "content", type: "string" },
36
+ { id: 3, name: "status", type: "int32" },
37
+ { id: 4, name: "created_at", type: "int64" },
38
+ { id: 5, name: "updated_at", type: "int64" },
39
+ { id: 6, name: "dependencies", type: "string", repeated: true },
40
+ ]);
41
+ addType(root, "UpdateTodosArgs", [
42
+ { id: 1, name: "todos", type: "TodoItem", repeated: true },
43
+ { id: 2, name: "merge", type: "bool" },
44
+ ]);
45
+ addType(root, "UpdateTodosSuccess", [
46
+ { id: 1, name: "todos", type: "TodoItem", repeated: true },
47
+ { id: 2, name: "total_count", type: "int32" },
48
+ { id: 3, name: "was_merge", type: "bool" },
49
+ ]);
50
+ addType(root, "UpdateTodosError", [{ id: 1, name: "error", type: "string" }]);
51
+ addType(root, "UpdateTodosResult", [
52
+ { id: 1, name: "success", type: "UpdateTodosSuccess" },
53
+ { id: 2, name: "error", type: "UpdateTodosError" },
54
+ ], [{ name: "result", fields: ["success", "error"] }]);
55
+ addType(root, "UpdateTodosToolCall", [
56
+ { id: 1, name: "args", type: "UpdateTodosArgs" },
57
+ { id: 2, name: "result", type: "UpdateTodosResult" },
58
+ ]);
59
+ addType(root, "ReadToolArgs", [
60
+ { id: 1, name: "path", type: "string" },
61
+ { id: 2, name: "offset", type: "int32" },
62
+ { id: 3, name: "limit", type: "int32" },
63
+ ]);
64
+ addType(root, "ReadToolCall", [{ id: 1, name: "args", type: "ReadToolArgs" }]);
65
+ addType(root, "ShellToolCall", [{ id: 1, name: "args", type: "ShellArgs" }]);
66
+ addType(root, "DeleteToolCall", [{ id: 1, name: "args", type: "DeleteArgs" }]);
67
+ addType(root, "GlobToolCall", [{ id: 1, name: "args", type: "GlobArgs" }]);
68
+ addType(root, "GrepToolCall", [{ id: 1, name: "args", type: "GrepArgs" }]);
69
+ addType(root, "EditToolArgs", [
70
+ { id: 1, name: "path", type: "string" },
71
+ { id: 6, name: "stream_content", type: "string" },
72
+ ]);
73
+ addType(root, "EditToolCall", [{ id: 1, name: "args", type: "EditToolArgs" }]);
74
+ addType(root, "LsToolCall", [{ id: 1, name: "args", type: "LsArgs" }]);
75
+ addType(root, "McpToolCall", [{ id: 1, name: "args", type: "McpArgs" }]);
76
+ addType(root, "CreatePlanArgs", [
77
+ { id: 1, name: "plan", type: "string" },
78
+ { id: 2, name: "todos", type: "TodoItem", repeated: true },
79
+ { id: 3, name: "overview", type: "string" },
80
+ { id: 4, name: "name", type: "string" },
81
+ { id: 5, name: "is_project", type: "bool" },
82
+ ]);
83
+ addType(root, "CreatePlanToolCall", [{ id: 1, name: "args", type: "CreatePlanArgs" }]);
84
+ addType(root, "WebSearchToolArgs", [
85
+ { id: 1, name: "search_term", type: "string" },
86
+ { id: 2, name: "tool_call_id", type: "string" },
87
+ ]);
88
+ addType(root, "WebSearchToolCall", [{ id: 1, name: "args", type: "WebSearchToolArgs" }]);
89
+ addType(root, "SubagentTypeUnspecified", []);
90
+ addType(root, "SubagentTypeComputerUse", []);
91
+ addType(root, "SubagentTypeCustom", [{ id: 1, name: "name", type: "string" }]);
92
+ addType(root, "SubagentTypeExplore", []);
93
+ addType(root, "SubagentTypeMediaReview", []);
94
+ addType(root, "SubagentTypeBash", []);
95
+ addType(root, "SubagentTypeBrowserUse", []);
96
+ addType(root, "SubagentTypeShell", []);
97
+ addType(root, "SubagentTypeVmSetupHelper", []);
98
+ addType(root, "SubagentTypeDebug", []);
99
+ addType(root, "SubagentTypeCursorGuide", []);
100
+ addType(root, "SubagentTypeWatchVideo", []);
101
+ addType(root, "SubagentType", [
102
+ { id: 1, name: "unspecified", type: "SubagentTypeUnspecified" },
103
+ { id: 2, name: "computer_use", type: "SubagentTypeComputerUse" },
104
+ { id: 3, name: "custom", type: "SubagentTypeCustom" },
105
+ { id: 4, name: "explore", type: "SubagentTypeExplore" },
106
+ { id: 5, name: "media_review", type: "SubagentTypeMediaReview" },
107
+ { id: 6, name: "bash", type: "SubagentTypeBash" },
108
+ { id: 7, name: "browser_use", type: "SubagentTypeBrowserUse" },
109
+ { id: 8, name: "shell", type: "SubagentTypeShell" },
110
+ { id: 9, name: "vm_setup_helper", type: "SubagentTypeVmSetupHelper" },
111
+ { id: 10, name: "debug", type: "SubagentTypeDebug" },
112
+ { id: 11, name: "cursor_guide", type: "SubagentTypeCursorGuide" },
113
+ { id: 12, name: "watch_video", type: "SubagentTypeWatchVideo" },
114
+ ], [{
115
+ name: "type",
116
+ fields: [
117
+ "unspecified", "computer_use", "custom", "explore", "media_review", "bash",
118
+ "browser_use", "shell", "vm_setup_helper", "debug", "cursor_guide", "watch_video",
119
+ ],
120
+ }]);
121
+ addType(root, "TaskToolArgs", [
122
+ { id: 1, name: "description", type: "string" },
123
+ { id: 2, name: "prompt", type: "string" },
124
+ { id: 3, name: "subagent_type", type: "SubagentType" },
125
+ { id: 4, name: "model", type: "string" },
126
+ { id: 5, name: "resume", type: "string" },
127
+ { id: 6, name: "agent_id", type: "string" },
128
+ ]);
129
+ addType(root, "TaskToolCall", [{ id: 1, name: "args", type: "TaskToolArgs" }]);
130
+ addType(root, "AskQuestionOption", [
131
+ { id: 1, name: "id", type: "string" },
132
+ { id: 2, name: "label", type: "string" },
133
+ ]);
134
+ addType(root, "AskQuestionItem", [
135
+ { id: 1, name: "id", type: "string" },
136
+ { id: 2, name: "prompt", type: "string" },
137
+ { id: 3, name: "options", type: "AskQuestionOption", repeated: true },
138
+ { id: 4, name: "allow_multiple", type: "bool" },
139
+ ]);
140
+ addType(root, "AskQuestionArgs", [
141
+ { id: 1, name: "title", type: "string" },
142
+ { id: 2, name: "questions", type: "AskQuestionItem", repeated: true },
143
+ ]);
144
+ addType(root, "AskQuestionToolCall", [{ id: 1, name: "args", type: "AskQuestionArgs" }]);
145
+ addType(root, "FetchToolArgs", [
146
+ { id: 1, name: "url", type: "string" },
147
+ { id: 2, name: "tool_call_id", type: "string" },
148
+ ]);
149
+ addType(root, "FetchToolCall", [{ id: 1, name: "args", type: "FetchToolArgs" }]);
150
+ addType(root, "WebFetchToolCall", [{ id: 1, name: "args", type: "FetchToolArgs" }]);
151
+ addType(root, "SwitchModeToolArgs", [
152
+ { id: 1, name: "target_mode_id", type: "string" },
153
+ { id: 2, name: "explanation", type: "string" },
154
+ { id: 3, name: "tool_call_id", type: "string" },
155
+ ]);
156
+ addType(root, "SwitchModeToolCall", [{ id: 1, name: "args", type: "SwitchModeToolArgs" }]);
157
+ addType(root, "PiReadToolArgs", [
158
+ { id: 1, name: "path", type: "string" },
159
+ { id: 2, name: "offset", type: "int32" },
160
+ { id: 3, name: "limit", type: "int32" },
161
+ ]);
162
+ addType(root, "PiBashToolArgs", [
163
+ { id: 1, name: "command", type: "string" },
164
+ { id: 2, name: "timeout", type: "double" },
165
+ ]);
166
+ addType(root, "PiEditReplacement", [
167
+ { id: 1, name: "old_text", type: "string" },
168
+ { id: 2, name: "new_text", type: "string" },
169
+ ]);
170
+ addType(root, "PiEditToolArgs", [
171
+ { id: 1, name: "path", type: "string" },
172
+ { id: 2, name: "edits", type: "PiEditReplacement", repeated: true },
173
+ ]);
174
+ addType(root, "PiWriteToolArgs", [
175
+ { id: 1, name: "path", type: "string" },
176
+ { id: 2, name: "content", type: "string" },
177
+ ]);
178
+ addType(root, "PiGrepToolArgs", [
179
+ { id: 1, name: "pattern", type: "string" },
180
+ { id: 2, name: "path", type: "string" },
181
+ { id: 3, name: "glob", type: "string" },
182
+ { id: 4, name: "ignore_case", type: "bool" },
183
+ { id: 5, name: "literal", type: "bool" },
184
+ { id: 6, name: "context", type: "int32" },
185
+ { id: 7, name: "limit", type: "int32" },
186
+ ]);
187
+ addType(root, "PiFindToolArgs", [
188
+ { id: 1, name: "pattern", type: "string" },
189
+ { id: 2, name: "path", type: "string" },
190
+ { id: 3, name: "limit", type: "int32" },
191
+ ]);
192
+ addType(root, "PiLsToolArgs", [
193
+ { id: 1, name: "path", type: "string" },
194
+ { id: 2, name: "limit", type: "int32" },
195
+ ]);
196
+ addType(root, "PiWriteToolCall", [{ id: 1, name: "args", type: "PiWriteToolArgs" }]);
197
+ addType(root, "PiReadToolCall", [{ id: 1, name: "args", type: "PiReadToolArgs" }]);
198
+ addType(root, "PiBashToolCall", [{ id: 1, name: "args", type: "PiBashToolArgs" }]);
199
+ addType(root, "PiEditToolCall", [{ id: 1, name: "args", type: "PiEditToolArgs" }]);
200
+ addType(root, "PiGrepToolCall", [{ id: 1, name: "args", type: "PiGrepToolArgs" }]);
201
+ addType(root, "PiFindToolCall", [{ id: 1, name: "args", type: "PiFindToolArgs" }]);
202
+ addType(root, "PiLsToolCall", [{ id: 1, name: "args", type: "PiLsToolArgs" }]);
203
+ // Display-only native tools Cursor may complete without an ExecServerMessage.
204
+ addType(root, "ReadTodosArgs", [
205
+ { id: 1, name: "todo_ids", type: "string", repeated: true },
206
+ ]);
207
+ addType(root, "ReadTodosToolCall", [{ id: 1, name: "args", type: "ReadTodosArgs" }]);
208
+ addType(root, "AwaitArgs", [
209
+ { id: 1, name: "task_id", type: "string" },
210
+ { id: 2, name: "block_until_ms", type: "uint32" },
211
+ { id: 3, name: "regex", type: "string" },
212
+ ]);
213
+ addType(root, "AwaitToolCall", [{ id: 1, name: "args", type: "AwaitArgs" }]);
214
+ addType(root, "GetMcpToolsArgs", [
215
+ { id: 1, name: "server", type: "string" },
33
216
  { id: 2, name: "tool_name", type: "string" },
34
- { id: 3, name: "args", type: "string" },
217
+ { id: 3, name: "pattern", type: "string" },
218
+ { id: 4, name: "tool_call_id", type: "string" },
35
219
  ]);
220
+ addType(root, "GetMcpToolsToolCall", [{ id: 1, name: "args", type: "GetMcpToolsArgs" }]);
221
+ addType(root, "GenerateImageToolArgs", [
222
+ { id: 1, name: "description", type: "string" },
223
+ { id: 2, name: "file_path", type: "string" },
224
+ { id: 5, name: "reference_image_paths", type: "string", repeated: true },
225
+ ]);
226
+ addType(root, "GenerateImageToolCall", [{ id: 1, name: "args", type: "GenerateImageToolArgs" }]);
227
+ addType(root, "ToolCall", [
228
+ { id: 57, name: "tool_call_id", type: "string" },
229
+ { id: 1, name: "shell_tool_call", type: "ShellToolCall" },
230
+ { id: 3, name: "delete_tool_call", type: "DeleteToolCall" },
231
+ { id: 4, name: "glob_tool_call", type: "GlobToolCall" },
232
+ { id: 5, name: "grep_tool_call", type: "GrepToolCall" },
233
+ { id: 8, name: "read_tool_call", type: "ReadToolCall" },
234
+ { id: 9, name: "update_todos_tool_call", type: "UpdateTodosToolCall" },
235
+ { id: 10, name: "read_todos_tool_call", type: "ReadTodosToolCall" },
236
+ { id: 12, name: "edit_tool_call", type: "EditToolCall" },
237
+ { id: 13, name: "ls_tool_call", type: "LsToolCall" },
238
+ { id: 15, name: "mcp_tool_call", type: "McpToolCall" },
239
+ { id: 17, name: "create_plan_tool_call", type: "CreatePlanToolCall" },
240
+ { id: 18, name: "web_search_tool_call", type: "WebSearchToolCall" },
241
+ { id: 19, name: "task_tool_call", type: "TaskToolCall" },
242
+ { id: 23, name: "ask_question_tool_call", type: "AskQuestionToolCall" },
243
+ { id: 24, name: "fetch_tool_call", type: "FetchToolCall" },
244
+ { id: 25, name: "switch_mode_tool_call", type: "SwitchModeToolCall" },
245
+ { id: 28, name: "generate_image_tool_call", type: "GenerateImageToolCall" },
246
+ { id: 37, name: "web_fetch_tool_call", type: "WebFetchToolCall" },
247
+ { id: 42, name: "await_tool_call", type: "AwaitToolCall" },
248
+ { id: 44, name: "get_mcp_tools_tool_call", type: "GetMcpToolsToolCall" },
249
+ { id: 61, name: "pi_read_tool_call", type: "PiReadToolCall" },
250
+ { id: 62, name: "pi_bash_tool_call", type: "PiBashToolCall" },
251
+ { id: 63, name: "pi_edit_tool_call", type: "PiEditToolCall" },
252
+ { id: 64, name: "pi_write_tool_call", type: "PiWriteToolCall" },
253
+ { id: 65, name: "pi_grep_tool_call", type: "PiGrepToolCall" },
254
+ { id: 66, name: "pi_find_tool_call", type: "PiFindToolCall" },
255
+ { id: 67, name: "pi_ls_tool_call", type: "PiLsToolCall" },
256
+ ], [{
257
+ name: "tool",
258
+ fields: [
259
+ "shell_tool_call", "delete_tool_call", "glob_tool_call", "grep_tool_call",
260
+ "read_tool_call", "update_todos_tool_call", "read_todos_tool_call",
261
+ "edit_tool_call", "ls_tool_call",
262
+ "mcp_tool_call", "create_plan_tool_call", "web_search_tool_call", "task_tool_call",
263
+ "ask_question_tool_call", "fetch_tool_call", "switch_mode_tool_call",
264
+ "generate_image_tool_call", "web_fetch_tool_call", "await_tool_call", "get_mcp_tools_tool_call",
265
+ "pi_read_tool_call", "pi_bash_tool_call", "pi_edit_tool_call",
266
+ "pi_write_tool_call", "pi_grep_tool_call", "pi_find_tool_call", "pi_ls_tool_call",
267
+ ],
268
+ }]);
36
269
  addType(root, "ToolCallStarted", [
37
270
  { id: 1, name: "call_id", type: "string" },
38
271
  { id: 2, name: "tool_call", type: "ToolCall" },
39
272
  { id: 3, name: "model_call_id", type: "string" },
40
273
  ]);
274
+ // agent.v1 ToolCallCompletedUpdate has no string result field — result lives
275
+ // inside the typed ToolCall variant.
41
276
  addType(root, "ToolCallCompleted", [
42
277
  { id: 1, name: "call_id", type: "string" },
43
278
  { id: 2, name: "tool_call", type: "ToolCall" },
44
279
  { id: 3, name: "model_call_id", type: "string" },
45
- { id: 4, name: "result", type: "string" },
46
280
  ]);
47
281
  addType(root, "PartialToolCall", [
48
282
  { id: 1, name: "call_id", type: "string" },
@@ -161,8 +395,12 @@ export function createMessageTypes() {
161
395
  { id: 1, name: "success", type: "WriteSuccess" },
162
396
  { id: 5, name: "error", type: "WriteError" },
163
397
  ], [{ name: "result", fields: ["success", "error"] }]);
164
- // agent.v1 PiWriteExecArgs / Result (exec #48 / #49) alternate write path
165
- // used by some Cursor models. Args are path+content; success is just output.
398
+ // agent.v1 Pi exec results. Cursor places Pi requests at ExecServerMessage
399
+ // fields #45..#51 and their corresponding ExecClientMessage results at
400
+ // #46..#52 (the result fields are deliberately offset by one).
401
+ //
402
+ // The success payloads contain additional optional truncation/diff metadata;
403
+ // OpenCode returns text, so the minimal output/error shapes are sufficient.
166
404
  addType(root, "PiWriteArgs", [
167
405
  { id: 1, name: "path", type: "string" },
168
406
  { id: 2, name: "content", type: "string" },
@@ -173,10 +411,34 @@ export function createMessageTypes() {
173
411
  addType(root, "PiWriteError", [
174
412
  { id: 1, name: "error", type: "string" },
175
413
  ]);
414
+ addType(root, "PiWriteRejected", [
415
+ { id: 1, name: "reason", type: "string" },
416
+ ]);
176
417
  addType(root, "PiWriteResult", [
177
418
  { id: 1, name: "success", type: "PiWriteSuccess" },
178
419
  { id: 2, name: "error", type: "PiWriteError" },
179
- ], [{ name: "result", fields: ["success", "error"] }]);
420
+ { id: 3, name: "rejected", type: "PiWriteRejected" },
421
+ ], [{ name: "result", fields: ["success", "error", "rejected"] }]);
422
+ addType(root, "PiOutputSuccess", [{ id: 1, name: "output", type: "string" }]);
423
+ addType(root, "PiExecError", [{ id: 1, name: "error", type: "string" }]);
424
+ addType(root, "PiExecRejected", [{ id: 1, name: "reason", type: "string" }]);
425
+ for (const resultType of [
426
+ "PiReadExecResult",
427
+ "PiBashExecResult",
428
+ "PiGrepExecResult",
429
+ "PiFindExecResult",
430
+ "PiLsExecResult",
431
+ ]) {
432
+ addType(root, resultType, [
433
+ { id: 1, name: "success", type: "PiOutputSuccess" },
434
+ { id: 2, name: "error", type: "PiExecError" },
435
+ ], [{ name: "result", fields: ["success", "error"] }]);
436
+ }
437
+ addType(root, "PiEditExecResult", [
438
+ { id: 1, name: "success", type: "PiOutputSuccess" },
439
+ { id: 2, name: "error", type: "PiExecError" },
440
+ { id: 3, name: "rejected", type: "PiExecRejected" },
441
+ ], [{ name: "result", fields: ["success", "error", "rejected"] }]);
180
442
  addType(root, "DeleteArgs", [
181
443
  { id: 1, name: "path", type: "string" },
182
444
  { id: 2, name: "tool_call_id", type: "string" },
@@ -408,9 +670,19 @@ export function createMessageTypes() {
408
670
  { id: 10, name: "request_context_args", type: "RequestContextArgs" },
409
671
  { id: 11, name: "mcp_args", type: "McpArgs" },
410
672
  { id: 14, name: "shell_stream_args", type: "ShellArgs" },
411
- // Pi write (#48 args #49 result). Field numbers differ from classic write (#3).
673
+ { id: 45, name: "pi_read_args", type: "PiReadToolArgs" },
674
+ { id: 46, name: "pi_bash_args", type: "PiBashToolArgs" },
675
+ { id: 47, name: "pi_edit_args", type: "PiEditToolArgs" },
412
676
  { id: 48, name: "pi_write_args", type: "PiWriteArgs" },
413
- ], [{ name: "args", fields: ["write_args", "delete_args", "grep_args", "read_args", "ls_args", "request_context_args", "mcp_args", "shell_stream_args", "pi_write_args"] }]);
677
+ { id: 49, name: "pi_grep_args", type: "PiGrepToolArgs" },
678
+ { id: 50, name: "pi_find_args", type: "PiFindToolArgs" },
679
+ { id: 51, name: "pi_ls_args", type: "PiLsToolArgs" },
680
+ ], [{ name: "args", fields: [
681
+ "write_args", "delete_args", "grep_args", "read_args", "ls_args",
682
+ "request_context_args", "mcp_args", "shell_stream_args",
683
+ "pi_read_args", "pi_bash_args", "pi_edit_args", "pi_write_args",
684
+ "pi_grep_args", "pi_find_args", "pi_ls_args",
685
+ ] }]);
414
686
  // ExecClientMessage — client sends tool result back
415
687
  addType(root, "ExecClientMessage", [
416
688
  { id: 1, name: "id", type: "uint32" },
@@ -424,8 +696,19 @@ export function createMessageTypes() {
424
696
  { id: 10, name: "request_context_result", type: "RequestContextResult" },
425
697
  { id: 11, name: "mcp_result", type: "McpResult" },
426
698
  { id: 14, name: "shell_stream", type: "ShellStream" },
699
+ { id: 46, name: "pi_read_result", type: "PiReadExecResult" },
700
+ { id: 47, name: "pi_bash_result", type: "PiBashExecResult" },
701
+ { id: 48, name: "pi_edit_result", type: "PiEditExecResult" },
427
702
  { id: 49, name: "pi_write_result", type: "PiWriteResult" },
428
- ], [{ name: "result", fields: ["write_result", "delete_result", "grep_result", "read_result", "ls_result", "request_context_result", "mcp_result", "shell_stream", "pi_write_result"] }]);
703
+ { id: 50, name: "pi_grep_result", type: "PiGrepExecResult" },
704
+ { id: 51, name: "pi_find_result", type: "PiFindExecResult" },
705
+ { id: 52, name: "pi_ls_result", type: "PiLsExecResult" },
706
+ ], [{ name: "result", fields: [
707
+ "write_result", "delete_result", "grep_result", "read_result", "ls_result",
708
+ "request_context_result", "mcp_result", "shell_stream",
709
+ "pi_read_result", "pi_bash_result", "pi_edit_result", "pi_write_result",
710
+ "pi_grep_result", "pi_find_result", "pi_ls_result",
711
+ ] }]);
429
712
  addType(root, "ExecServerControlMessage", [
430
713
  { id: 1, name: "abort", type: "ExecServerAbort" },
431
714
  ]);
@@ -556,6 +839,130 @@ export function createMessageTypes() {
556
839
  ]);
557
840
  // ── Client heartbeat ──
558
841
  addType(root, "ClientHeartbeat", []);
842
+ // ── Interaction query/response channel ──
843
+ // Cursor sends UI/integration requests outside the exec tool channel. Query
844
+ // bodies stay opaque: this headless provider only needs their id + variant
845
+ // to return a conservative typed response on the same Run stream.
846
+ addType(root, "InteractionQuery", [
847
+ { id: 1, name: "id", type: "uint32" },
848
+ { id: 2, name: "web_search_request_query", type: "bytes" },
849
+ { id: 3, name: "ask_question_interaction_query", type: "bytes" },
850
+ { id: 4, name: "switch_mode_request_query", type: "bytes" },
851
+ { id: 7, name: "create_plan_request_query", type: "bytes" },
852
+ { id: 8, name: "setup_vm_environment_args", type: "bytes" },
853
+ { id: 9, name: "web_fetch_request_query", type: "bytes" },
854
+ { id: 10, name: "pr_management_request_query", type: "bytes" },
855
+ { id: 11, name: "mcp_auth_request_query", type: "bytes" },
856
+ { id: 12, name: "generate_image_request_query", type: "bytes" },
857
+ { id: 13, name: "replace_env_args", type: "bytes" },
858
+ { id: 14, name: "connect_scm_request_query", type: "bytes" },
859
+ ], [{
860
+ name: "query",
861
+ fields: [
862
+ "web_search_request_query", "ask_question_interaction_query",
863
+ "switch_mode_request_query", "create_plan_request_query",
864
+ "setup_vm_environment_args", "web_fetch_request_query",
865
+ "pr_management_request_query", "mcp_auth_request_query",
866
+ "generate_image_request_query", "replace_env_args",
867
+ "connect_scm_request_query",
868
+ ],
869
+ }]);
870
+ addType(root, "WebSearchRequestApproved", []);
871
+ addType(root, "WebSearchRequestRejected", [{ id: 1, name: "reason", type: "string" }]);
872
+ addType(root, "WebSearchRequestResponse", [
873
+ { id: 1, name: "approved", type: "WebSearchRequestApproved" },
874
+ { id: 2, name: "rejected", type: "WebSearchRequestRejected" },
875
+ ], [{ name: "result", fields: ["approved", "rejected"] }]);
876
+ addType(root, "AskQuestionRejected", [{ id: 1, name: "reason", type: "string" }]);
877
+ addType(root, "AskQuestionResult", [
878
+ { id: 3, name: "rejected", type: "AskQuestionRejected" },
879
+ ], [{ name: "result", fields: ["rejected"] }]);
880
+ addType(root, "AskQuestionInteractionResponse", [
881
+ { id: 1, name: "result", type: "AskQuestionResult" },
882
+ ]);
883
+ addType(root, "SwitchModeRequestApproved", []);
884
+ addType(root, "SwitchModeRequestRejected", [{ id: 1, name: "reason", type: "string" }]);
885
+ addType(root, "SwitchModeRequestResponse", [
886
+ { id: 1, name: "approved", type: "SwitchModeRequestApproved" },
887
+ { id: 2, name: "rejected", type: "SwitchModeRequestRejected" },
888
+ ], [{ name: "result", fields: ["approved", "rejected"] }]);
889
+ addType(root, "CreatePlanSuccess", []);
890
+ addType(root, "CreatePlanError", [{ id: 1, name: "error", type: "string" }]);
891
+ addType(root, "CreatePlanResult", [
892
+ { id: 1, name: "success", type: "CreatePlanSuccess" },
893
+ { id: 2, name: "error", type: "CreatePlanError" },
894
+ { id: 3, name: "plan_uri", type: "string" },
895
+ ], [{ name: "result", fields: ["success", "error"] }]);
896
+ addType(root, "CreatePlanRequestResponse", [
897
+ { id: 1, name: "result", type: "CreatePlanResult" },
898
+ ]);
899
+ addType(root, "SetupVmEnvironmentSuccess", []);
900
+ addType(root, "SetupVmEnvironmentResult", [
901
+ { id: 1, name: "success", type: "SetupVmEnvironmentSuccess" },
902
+ ], [{ name: "result", fields: ["success"] }]);
903
+ addType(root, "WebFetchRequestApproved", []);
904
+ addType(root, "WebFetchRequestRejected", [{ id: 1, name: "reason", type: "string" }]);
905
+ addType(root, "WebFetchRequestResponse", [
906
+ { id: 1, name: "approved", type: "WebFetchRequestApproved" },
907
+ { id: 2, name: "rejected", type: "WebFetchRequestRejected" },
908
+ ], [{ name: "result", fields: ["approved", "rejected"] }]);
909
+ addType(root, "PrManagementRejected", [{ id: 1, name: "reason", type: "string" }]);
910
+ addType(root, "PrManagementResult", [
911
+ { id: 3, name: "rejected", type: "PrManagementRejected" },
912
+ ], [{ name: "result", fields: ["rejected"] }]);
913
+ addType(root, "McpAuthRequestApproved", []);
914
+ addType(root, "McpAuthRequestRejected", [{ id: 1, name: "reason", type: "string" }]);
915
+ addType(root, "McpAuthRequestResponse", [
916
+ { id: 1, name: "approved", type: "McpAuthRequestApproved" },
917
+ { id: 2, name: "rejected", type: "McpAuthRequestRejected" },
918
+ ], [{ name: "result", fields: ["approved", "rejected"] }]);
919
+ addType(root, "GenerateImageRequestApproved", [{ id: 1, name: "description", type: "string" }]);
920
+ addType(root, "GenerateImageRequestRejected", [{ id: 1, name: "reason", type: "string" }]);
921
+ addType(root, "GenerateImageRequestResponse", [
922
+ { id: 1, name: "approved", type: "GenerateImageRequestApproved" },
923
+ { id: 2, name: "rejected", type: "GenerateImageRequestRejected" },
924
+ ], [{ name: "result", fields: ["approved", "rejected"] }]);
925
+ addType(root, "ReplaceEnvSuccess", []);
926
+ addType(root, "ReplaceEnvFailure", [
927
+ { id: 1, name: "error_message", type: "string" },
928
+ { id: 2, name: "setup_logs", type: "string" },
929
+ ]);
930
+ addType(root, "ReplaceEnvResult", [
931
+ { id: 1, name: "success", type: "ReplaceEnvSuccess" },
932
+ { id: 2, name: "failure", type: "ReplaceEnvFailure" },
933
+ ], [{ name: "result", fields: ["success", "failure"] }]);
934
+ addType(root, "ConnectScmRequestApproved", []);
935
+ addType(root, "ConnectScmRequestRejected", [{ id: 1, name: "reason", type: "string" }]);
936
+ addType(root, "ConnectScmRequestFailed", [{ id: 1, name: "error", type: "string" }]);
937
+ addType(root, "ConnectScmRequestResponse", [
938
+ { id: 1, name: "approved", type: "ConnectScmRequestApproved" },
939
+ { id: 2, name: "rejected", type: "ConnectScmRequestRejected" },
940
+ { id: 3, name: "failed", type: "ConnectScmRequestFailed" },
941
+ ], [{ name: "result", fields: ["approved", "rejected", "failed"] }]);
942
+ addType(root, "InteractionResponse", [
943
+ { id: 1, name: "id", type: "uint32" },
944
+ { id: 2, name: "web_search_request_response", type: "WebSearchRequestResponse" },
945
+ { id: 3, name: "ask_question_interaction_response", type: "AskQuestionInteractionResponse" },
946
+ { id: 4, name: "switch_mode_request_response", type: "SwitchModeRequestResponse" },
947
+ { id: 7, name: "create_plan_request_response", type: "CreatePlanRequestResponse" },
948
+ { id: 8, name: "setup_vm_environment_result", type: "SetupVmEnvironmentResult" },
949
+ { id: 9, name: "web_fetch_request_response", type: "WebFetchRequestResponse" },
950
+ { id: 10, name: "pr_management_result", type: "PrManagementResult" },
951
+ { id: 11, name: "mcp_auth_request_response", type: "McpAuthRequestResponse" },
952
+ { id: 12, name: "generate_image_request_response", type: "GenerateImageRequestResponse" },
953
+ { id: 13, name: "replace_env_result", type: "ReplaceEnvResult" },
954
+ { id: 14, name: "connect_scm_request_response", type: "ConnectScmRequestResponse" },
955
+ ], [{
956
+ name: "result",
957
+ fields: [
958
+ "web_search_request_response", "ask_question_interaction_response",
959
+ "switch_mode_request_response", "create_plan_request_response",
960
+ "setup_vm_environment_result", "web_fetch_request_response",
961
+ "pr_management_result", "mcp_auth_request_response",
962
+ "generate_image_request_response", "replace_env_result",
963
+ "connect_scm_request_response",
964
+ ],
965
+ }]);
559
966
  // ── KV blob store (cursor moves large payloads out-of-band via this channel) ──
560
967
  // Server sends KvServerMessage (AgentServerMessage #4); client MUST reply with
561
968
  // KvClientMessage (AgentClientMessage #3) on the same Run stream, echoing `id`.
@@ -590,8 +997,9 @@ export function createMessageTypes() {
590
997
  { id: 2, name: "exec_client_message", type: "ExecClientMessage" },
591
998
  { id: 3, name: "kv_client_message", type: "KvClientMessage" },
592
999
  { id: 5, name: "exec_client_control_message", type: "ExecClientControlMessage" },
1000
+ { id: 6, name: "interaction_response", type: "InteractionResponse" },
593
1001
  { id: 7, name: "client_heartbeat", type: "ClientHeartbeat" },
594
- ], [{ name: "message", fields: ["run_request", "exec_client_message", "kv_client_message", "exec_client_control_message", "client_heartbeat"] }]);
1002
+ ], [{ name: "message", fields: ["run_request", "exec_client_message", "kv_client_message", "exec_client_control_message", "interaction_response", "client_heartbeat"] }]);
595
1003
  // ── AgentServerMessage ──
596
1004
  addType(root, "AgentServerMessage", [
597
1005
  { id: 1, name: "interaction_update", type: "InteractionUpdate" },
@@ -599,7 +1007,7 @@ export function createMessageTypes() {
599
1007
  { id: 3, name: "conversation_checkpoint_update", type: "bytes" },
600
1008
  { id: 4, name: "kv_server_message", type: "KvServerMessage" },
601
1009
  { id: 5, name: "exec_server_control_message", type: "ExecServerControlMessage" },
602
- { id: 7, name: "interaction_query", type: "bytes" },
1010
+ { id: 7, name: "interaction_query", type: "InteractionQuery" },
603
1011
  ], [{ name: "message", fields: ["interaction_update", "exec_server_message", "conversation_checkpoint_update", "kv_server_message", "exec_server_control_message", "interaction_query"] }]);
604
1012
  // ── AvailableModels types ──
605
1013
  addType(root, "AvailableModelsRequest", []);
@@ -1,10 +1,20 @@
1
1
  import { type OpencodeToolDef } from "./tools.js";
2
2
  import type { ModelInfo } from "../models.js";
3
+ export type SeedHistoryMessage = {
4
+ role: "system" | "user" | "assistant";
5
+ content: string;
6
+ };
3
7
  export type RunRequestInput = {
4
8
  text: string;
5
9
  modelId: string;
6
10
  conversationId: string;
7
11
  systemPrompt?: string;
12
+ /**
13
+ * Prior chat turns for a seed ConversationStateStructure (no checkpoint).
14
+ * Used after compaction reset so Cursor sees OpenCode's compacted history
15
+ * instead of an empty conversation.
16
+ */
17
+ history?: SeedHistoryMessage[];
8
18
  /**
9
19
  * Opaque ConversationStateStructure bytes from the last
10
20
  * conversation_checkpoint_update for this conversation_id. When set, echoed
@@ -20,9 +30,29 @@ export type RunRequestInput = {
20
30
  messageId?: string;
21
31
  availableModels?: ModelInfo[];
22
32
  tools?: OpencodeToolDef[];
33
+ /** Pre-resolved descriptors (including config-backed MCP server identity). */
34
+ toolDescriptors?: Array<Record<string, unknown>>;
23
35
  /** Prebuilt RequestContext (OpenCode-sourced). */
24
36
  requestContext?: Record<string, unknown>;
25
37
  };
38
+ /**
39
+ * Seed ConversationStateStructure for the first turn (no checkpoint yet).
40
+ *
41
+ * OpenCode needs a system prompt channel; we put it in root_prompt_messages_json
42
+ * as a JSON chat message. After the first checkpoint arrives we stop inventing
43
+ * state and echo the server's opaque structure instead (CLI behavior).
44
+ *
45
+ * Compaction resets also use this seed, with `history` carrying OpenCode's
46
+ * compacted prompt turns so Cursor can summarize without the old checkpoint.
47
+ *
48
+ * We deliberately do NOT use `AgentRunRequest.custom_system_prompt` (#8): that
49
+ * field is the internal `--system-prompt` CLI override and the server rejects
50
+ * it for normal accounts.
51
+ */
52
+ export declare function buildSeedConversationState(input?: {
53
+ systemPrompt?: string;
54
+ history?: SeedHistoryMessage[];
55
+ }): Uint8Array;
26
56
  /**
27
57
  * Build an AgentClientMessage{run_request} for a conversation turn.
28
58
  *
@@ -7,19 +7,31 @@ import { toolsToDescriptors } from "./tools.js";
7
7
  * as a JSON chat message. After the first checkpoint arrives we stop inventing
8
8
  * state and echo the server's opaque structure instead (CLI behavior).
9
9
  *
10
+ * Compaction resets also use this seed, with `history` carrying OpenCode's
11
+ * compacted prompt turns so Cursor can summarize without the old checkpoint.
12
+ *
10
13
  * We deliberately do NOT use `AgentRunRequest.custom_system_prompt` (#8): that
11
14
  * field is the internal `--system-prompt` CLI override and the server rejects
12
15
  * it for normal accounts.
13
16
  */
14
- function buildSeedConversationState(systemPrompt) {
17
+ export function buildSeedConversationState(input) {
15
18
  const root = getMessageTypes();
16
19
  const type = root.lookupType("ConversationStateStructure");
17
- const obj = {};
18
- if (systemPrompt && systemPrompt.length > 0) {
19
- obj.root_prompt_messages_json = [
20
- JSON.stringify({ role: "system", content: systemPrompt }),
21
- ];
20
+ const messages = [];
21
+ if (input?.systemPrompt && input.systemPrompt.length > 0) {
22
+ messages.push(JSON.stringify({ role: "system", content: input.systemPrompt }));
22
23
  }
24
+ for (const entry of input?.history ?? []) {
25
+ if (!entry.content)
26
+ continue;
27
+ // Avoid duplicating the system prompt when history also carries one.
28
+ if (entry.role === "system" && input?.systemPrompt)
29
+ continue;
30
+ messages.push(JSON.stringify({ role: entry.role, content: entry.content }));
31
+ }
32
+ const obj = {};
33
+ if (messages.length > 0)
34
+ obj.root_prompt_messages_json = messages;
23
35
  return type.encode(type.fromObject(obj)).finish();
24
36
  }
25
37
  function buildAvailableModels(models) {
@@ -40,7 +52,7 @@ export function buildRunRequest(input) {
40
52
  // (#2). AgentRunRequest.mcp_tools (#4) is prewarm-only / empty on real turns —
41
53
  // putting tools only there is why the model fell back to native Grep/Read.
42
54
  const tools = input.tools ?? [];
43
- const mcpTools = tools.length > 0 ? toolsToDescriptors(tools) : [];
55
+ const mcpTools = input.toolDescriptors ?? (tools.length > 0 ? toolsToDescriptors(tools) : []);
44
56
  const requestContext = input.requestContext;
45
57
  const userMessageAction = {
46
58
  user_message: {
@@ -53,7 +65,10 @@ export function buildRunRequest(input) {
53
65
  }
54
66
  const conversationState = input.conversationState && input.conversationState.length > 0
55
67
  ? input.conversationState
56
- : buildSeedConversationState(input.systemPrompt);
68
+ : buildSeedConversationState({
69
+ systemPrompt: input.systemPrompt,
70
+ history: input.history,
71
+ });
57
72
  const runRequest = {
58
73
  conversation_id: input.conversationId,
59
74
  action: {
@@ -34,19 +34,25 @@ export function parseInteractionUpdate(payload) {
34
34
  if (iu.tool_call_started) {
35
35
  const tc = iu.tool_call_started;
36
36
  const toolCall = tc.tool_call;
37
+ const variant = toolCall && typeof toolCall === "object"
38
+ ? Object.keys(toolCall).find((k) => k.endsWith("_tool_call"))
39
+ : undefined;
40
+ const variantPayload = variant && toolCall ? toolCall[variant] : undefined;
41
+ const args = variantPayload?.args ?? variantPayload;
37
42
  return {
38
43
  type: "tool-call-started",
39
44
  callId: tc.call_id ?? "",
40
- toolName: toolCall?.tool_name ?? "",
41
- args: toolCall?.args ?? "{}",
45
+ toolName: variant ?? "",
46
+ args: JSON.stringify(args ?? {}),
42
47
  };
43
48
  }
44
49
  if (iu.tool_call_completed) {
45
50
  const tc = iu.tool_call_completed;
51
+ const toolCall = tc.tool_call;
46
52
  return {
47
53
  type: "tool-call-completed",
48
54
  callId: tc.call_id ?? "",
49
- result: tc.result ?? "{}",
55
+ result: JSON.stringify(toolCall ?? {}),
50
56
  };
51
57
  }
52
58
  if (iu.partial_tool_call) {