cursor-opencode-provider 0.1.1

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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/auth.d.ts +48 -0
  4. package/dist/auth.js +200 -0
  5. package/dist/context/agents.d.ts +8 -0
  6. package/dist/context/agents.js +76 -0
  7. package/dist/context/build.d.ts +12 -0
  8. package/dist/context/build.js +83 -0
  9. package/dist/context/env.d.ts +1 -0
  10. package/dist/context/env.js +29 -0
  11. package/dist/context/git.d.ts +20 -0
  12. package/dist/context/git.js +59 -0
  13. package/dist/context/index.d.ts +2 -0
  14. package/dist/context/index.js +2 -0
  15. package/dist/context/layout.d.ts +17 -0
  16. package/dist/context/layout.js +58 -0
  17. package/dist/context/paths.d.ts +3 -0
  18. package/dist/context/paths.js +11 -0
  19. package/dist/context/plugins.d.ts +8 -0
  20. package/dist/context/plugins.js +50 -0
  21. package/dist/context/rules.d.ts +19 -0
  22. package/dist/context/rules.js +198 -0
  23. package/dist/context/skills.d.ts +11 -0
  24. package/dist/context/skills.js +104 -0
  25. package/dist/index.d.ts +15 -0
  26. package/dist/index.js +18 -0
  27. package/dist/language-model.d.ts +45 -0
  28. package/dist/language-model.js +834 -0
  29. package/dist/models.d.ts +49 -0
  30. package/dist/models.js +136 -0
  31. package/dist/plugin-v2.d.ts +2 -0
  32. package/dist/plugin-v2.js +48 -0
  33. package/dist/plugin.d.ts +2 -0
  34. package/dist/plugin.js +201 -0
  35. package/dist/protocol/blob-store.d.ts +15 -0
  36. package/dist/protocol/blob-store.js +52 -0
  37. package/dist/protocol/checkpoint.d.ts +17 -0
  38. package/dist/protocol/checkpoint.js +29 -0
  39. package/dist/protocol/checksum.d.ts +2 -0
  40. package/dist/protocol/checksum.js +23 -0
  41. package/dist/protocol/client-version.d.ts +5 -0
  42. package/dist/protocol/client-version.js +150 -0
  43. package/dist/protocol/device-id.d.ts +8 -0
  44. package/dist/protocol/device-id.js +121 -0
  45. package/dist/protocol/framing.d.ts +10 -0
  46. package/dist/protocol/framing.js +90 -0
  47. package/dist/protocol/kv.d.ts +24 -0
  48. package/dist/protocol/kv.js +81 -0
  49. package/dist/protocol/messages.d.ts +11 -0
  50. package/dist/protocol/messages.js +676 -0
  51. package/dist/protocol/request.d.ts +36 -0
  52. package/dist/protocol/request.js +90 -0
  53. package/dist/protocol/stream.d.ts +38 -0
  54. package/dist/protocol/stream.js +64 -0
  55. package/dist/protocol/struct.d.ts +19 -0
  56. package/dist/protocol/struct.js +186 -0
  57. package/dist/protocol/thinking.d.ts +15 -0
  58. package/dist/protocol/thinking.js +17 -0
  59. package/dist/protocol/tools.d.ts +94 -0
  60. package/dist/protocol/tools.js +631 -0
  61. package/dist/session.d.ts +81 -0
  62. package/dist/session.js +96 -0
  63. package/dist/shared.d.ts +15 -0
  64. package/dist/shared.js +13 -0
  65. package/dist/transport/connect.d.ts +23 -0
  66. package/dist/transport/connect.js +275 -0
  67. package/package.json +65 -0
@@ -0,0 +1,676 @@
1
+ import protobuf from "protobufjs";
2
+ function addType(root, name, fields, oneofs) {
3
+ const t = new protobuf.Type(name);
4
+ for (const f of fields) {
5
+ t.add(new protobuf.Field(f.name, f.id, f.type, f.repeated ? "repeated" : undefined));
6
+ }
7
+ for (const o of oneofs ?? []) {
8
+ t.add(new protobuf.OneOf(o.name, o.fields));
9
+ }
10
+ root.add(t);
11
+ return t;
12
+ }
13
+ // ── Utility messages ──
14
+ export function createMessageTypes() {
15
+ const root = new protobuf.Root();
16
+ addType(root, "TextDeltaUpdate", [
17
+ { id: 1, name: "text", type: "string" },
18
+ ]);
19
+ addType(root, "ThinkingDeltaUpdate", [
20
+ { id: 1, name: "text", type: "string" },
21
+ ]);
22
+ addType(root, "TurnEnded", [
23
+ { id: 1, name: "input_tokens", type: "uint32" },
24
+ { id: 2, name: "output_tokens", type: "uint32" },
25
+ { id: 3, name: "cache_read", type: "uint32" },
26
+ { id: 4, name: "cache_write", type: "uint32" },
27
+ { id: 5, name: "reasoning_tokens", type: "uint32" },
28
+ ]);
29
+ addType(root, "Heartbeat", []);
30
+ // Tool call types
31
+ addType(root, "ToolCall", [
32
+ { id: 1, name: "call_id", type: "string" },
33
+ { id: 2, name: "tool_name", type: "string" },
34
+ { id: 3, name: "args", type: "string" },
35
+ ]);
36
+ addType(root, "ToolCallStarted", [
37
+ { id: 1, name: "call_id", type: "string" },
38
+ { id: 2, name: "tool_call", type: "ToolCall" },
39
+ { id: 3, name: "model_call_id", type: "string" },
40
+ ]);
41
+ addType(root, "ToolCallCompleted", [
42
+ { id: 1, name: "call_id", type: "string" },
43
+ { id: 2, name: "tool_call", type: "ToolCall" },
44
+ { id: 3, name: "model_call_id", type: "string" },
45
+ { id: 4, name: "result", type: "string" },
46
+ ]);
47
+ addType(root, "PartialToolCall", [
48
+ { id: 1, name: "call_id", type: "string" },
49
+ { id: 2, name: "tool_call", type: "ToolCall" },
50
+ { id: 3, name: "args_text_delta", type: "string" },
51
+ { id: 4, name: "model_call_id", type: "string" },
52
+ ]);
53
+ // agent.v1 StepStartedUpdate / StepCompletedUpdate: step_id is uint64 (T:4),
54
+ // not string — wrong type made every step_completed frame throw
55
+ // "index out of range" in decodeMessage.
56
+ addType(root, "StepStarted", [
57
+ { id: 1, name: "step_id", type: "uint64" },
58
+ ]);
59
+ addType(root, "StepCompleted", [
60
+ { id: 1, name: "step_id", type: "uint64" },
61
+ { id: 2, name: "step_duration_ms", type: "int64" },
62
+ ]);
63
+ // InteractionUpdate — the core streaming update message
64
+ addType(root, "InteractionUpdate", [
65
+ { id: 1, name: "text_delta", type: "TextDeltaUpdate" },
66
+ { id: 2, name: "tool_call_started", type: "ToolCallStarted" },
67
+ { id: 3, name: "tool_call_completed", type: "ToolCallCompleted" },
68
+ { id: 4, name: "thinking_delta", type: "ThinkingDeltaUpdate" },
69
+ { id: 7, name: "partial_tool_call", type: "PartialToolCall" },
70
+ { id: 13, name: "heartbeat", type: "Heartbeat" },
71
+ { id: 14, name: "turn_ended", type: "TurnEnded" },
72
+ { id: 16, name: "step_started", type: "StepStarted" },
73
+ { id: 17, name: "step_completed", type: "StepCompleted" },
74
+ ], [{ name: "update", fields: ["text_delta", "tool_call_started", "tool_call_completed", "thinking_delta", "partial_tool_call", "heartbeat", "turn_ended", "step_started", "step_completed"] }]);
75
+ // ── Exec channel ──
76
+ // Field numbers match agent.v1. Extra fields we don't use are still declared
77
+ // so protobufjs doesn't drop them on decode.
78
+ addType(root, "ReadArgs", [
79
+ { id: 1, name: "path", type: "string" },
80
+ { id: 2, name: "tool_call_id", type: "string" },
81
+ { id: 4, name: "offset", type: "int32" },
82
+ { id: 5, name: "limit", type: "uint32" },
83
+ ]);
84
+ // agent.v1 ReadResult is a oneof — flat {content,error} was rejected by the
85
+ // server (endless heartbeats after read_result).
86
+ addType(root, "ReadSuccess", [
87
+ { id: 1, name: "path", type: "string" },
88
+ { id: 2, name: "content", type: "string" },
89
+ { id: 3, name: "total_lines", type: "int32" },
90
+ { id: 4, name: "file_size", type: "int64" },
91
+ { id: 6, name: "truncated", type: "bool" },
92
+ ]);
93
+ addType(root, "ReadError", [
94
+ { id: 1, name: "path", type: "string" },
95
+ { id: 2, name: "error", type: "string" },
96
+ ]);
97
+ addType(root, "ReadResult", [
98
+ { id: 1, name: "success", type: "ReadSuccess" },
99
+ { id: 2, name: "error", type: "ReadError" },
100
+ ], [{ name: "result", fields: ["success", "error"] }]);
101
+ addType(root, "GrepArgs", [
102
+ { id: 1, name: "pattern", type: "string" },
103
+ { id: 2, name: "path", type: "string" },
104
+ { id: 3, name: "glob", type: "string" },
105
+ { id: 4, name: "output_mode", type: "string" },
106
+ { id: 8, name: "case_insensitive", type: "bool" },
107
+ { id: 10, name: "head_limit", type: "int32" },
108
+ { id: 14, name: "tool_call_id", type: "string" },
109
+ { id: 16, name: "offset", type: "int32" },
110
+ ]);
111
+ addType(root, "GrepError", [{ id: 1, name: "error", type: "string" }]);
112
+ addType(root, "GrepFilesResult", [
113
+ { id: 1, name: "files", type: "string", repeated: true },
114
+ { id: 2, name: "total_files", type: "int32" },
115
+ { id: 3, name: "client_truncated", type: "bool" },
116
+ ]);
117
+ addType(root, "GrepContentMatch", [
118
+ { id: 1, name: "line_number", type: "int32" },
119
+ { id: 2, name: "content", type: "string" },
120
+ ]);
121
+ addType(root, "GrepFileMatch", [
122
+ { id: 1, name: "file", type: "string" },
123
+ { id: 2, name: "matches", type: "GrepContentMatch", repeated: true },
124
+ ]);
125
+ addType(root, "GrepContentResult", [
126
+ { id: 1, name: "matches", type: "GrepFileMatch", repeated: true },
127
+ { id: 2, name: "total_lines", type: "int32" },
128
+ { id: 3, name: "total_matched_lines", type: "int32" },
129
+ ]);
130
+ addType(root, "GrepUnionResult", [
131
+ { id: 2, name: "files", type: "GrepFilesResult" },
132
+ { id: 3, name: "content", type: "GrepContentResult" },
133
+ ], [{ name: "result", fields: ["files", "content"] }]);
134
+ {
135
+ const t = new protobuf.Type("GrepSuccess");
136
+ t.add(new protobuf.Field("pattern", 1, "string"));
137
+ t.add(new protobuf.Field("path", 2, "string"));
138
+ t.add(new protobuf.Field("output_mode", 3, "string"));
139
+ t.add(new protobuf.MapField("workspace_results", 4, "string", "GrepUnionResult"));
140
+ root.add(t);
141
+ }
142
+ addType(root, "GrepResult", [
143
+ { id: 1, name: "success", type: "GrepSuccess" },
144
+ { id: 2, name: "error", type: "GrepError" },
145
+ ], [{ name: "result", fields: ["success", "error"] }]);
146
+ addType(root, "WriteArgs", [
147
+ { id: 1, name: "path", type: "string" },
148
+ { id: 2, name: "file_text", type: "string" },
149
+ { id: 3, name: "tool_call_id", type: "string" },
150
+ ]);
151
+ addType(root, "WriteSuccess", [
152
+ { id: 1, name: "path", type: "string" },
153
+ { id: 2, name: "lines_created", type: "int32" },
154
+ { id: 3, name: "file_size", type: "int32" },
155
+ ]);
156
+ addType(root, "WriteError", [
157
+ { id: 1, name: "path", type: "string" },
158
+ { id: 2, name: "error", type: "string" },
159
+ ]);
160
+ addType(root, "WriteResult", [
161
+ { id: 1, name: "success", type: "WriteSuccess" },
162
+ { id: 5, name: "error", type: "WriteError" },
163
+ ], [{ 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.
166
+ addType(root, "PiWriteArgs", [
167
+ { id: 1, name: "path", type: "string" },
168
+ { id: 2, name: "content", type: "string" },
169
+ ]);
170
+ addType(root, "PiWriteSuccess", [
171
+ { id: 1, name: "output", type: "string" },
172
+ ]);
173
+ addType(root, "PiWriteError", [
174
+ { id: 1, name: "error", type: "string" },
175
+ ]);
176
+ addType(root, "PiWriteResult", [
177
+ { id: 1, name: "success", type: "PiWriteSuccess" },
178
+ { id: 2, name: "error", type: "PiWriteError" },
179
+ ], [{ name: "result", fields: ["success", "error"] }]);
180
+ addType(root, "DeleteArgs", [
181
+ { id: 1, name: "path", type: "string" },
182
+ { id: 2, name: "tool_call_id", type: "string" },
183
+ ]);
184
+ addType(root, "DeleteSuccess", [
185
+ { id: 1, name: "path", type: "string" },
186
+ { id: 2, name: "deleted_file", type: "string" },
187
+ ]);
188
+ addType(root, "DeleteError", [
189
+ { id: 1, name: "path", type: "string" },
190
+ { id: 2, name: "error", type: "string" },
191
+ ]);
192
+ addType(root, "DeleteResult", [
193
+ { id: 1, name: "success", type: "DeleteSuccess" },
194
+ { id: 7, name: "error", type: "DeleteError" },
195
+ ], [{ name: "result", fields: ["success", "error"] }]);
196
+ addType(root, "LsArgs", [
197
+ { id: 1, name: "path", type: "string" },
198
+ { id: 2, name: "ignore", type: "string", repeated: true },
199
+ { id: 3, name: "tool_call_id", type: "string" },
200
+ ]);
201
+ addType(root, "LsDirectoryTreeFile", [{ id: 1, name: "name", type: "string" }]);
202
+ addType(root, "LsDirectoryTreeNode", [
203
+ { id: 1, name: "abs_path", type: "string" },
204
+ { id: 2, name: "children_dirs", type: "LsDirectoryTreeNode", repeated: true },
205
+ { id: 3, name: "children_files", type: "LsDirectoryTreeFile", repeated: true },
206
+ { id: 6, name: "num_files", type: "int32" },
207
+ ]);
208
+ addType(root, "LsSuccess", [
209
+ { id: 1, name: "directory_tree_root", type: "LsDirectoryTreeNode" },
210
+ ]);
211
+ addType(root, "LsError", [
212
+ { id: 1, name: "path", type: "string" },
213
+ { id: 2, name: "error", type: "string" },
214
+ ]);
215
+ addType(root, "LsResult", [
216
+ { id: 1, name: "success", type: "LsSuccess" },
217
+ { id: 2, name: "error", type: "LsError" },
218
+ ], [{ name: "result", fields: ["success", "error"] }]);
219
+ addType(root, "ShellArgs", [
220
+ { id: 1, name: "command", type: "string" },
221
+ { id: 2, name: "working_directory", type: "string" },
222
+ { id: 3, name: "timeout", type: "uint32" },
223
+ { id: 4, name: "tool_call_id", type: "string" },
224
+ ]);
225
+ addType(root, "ShellStreamStart", []); // optional SandboxPolicy only; empty is valid
226
+ addType(root, "ShellStreamStdout", [{ id: 1, name: "data", type: "string" }]);
227
+ addType(root, "ShellStreamStderr", [{ id: 1, name: "data", type: "string" }]);
228
+ // agent.v1: code is uint32; protobufjs must emit code=0 (defaults are load-bearing).
229
+ addType(root, "ShellStreamExit", [
230
+ { id: 1, name: "code", type: "uint32" },
231
+ { id: 4, name: "aborted", type: "bool" },
232
+ ]);
233
+ // ShellRejected / ShellPermissionDenied (shared with ShellResult) — reason/error at #3.
234
+ addType(root, "ShellRejected", [
235
+ { id: 1, name: "command", type: "string" },
236
+ { id: 2, name: "working_directory", type: "string" },
237
+ { id: 3, name: "reason", type: "string" },
238
+ ]);
239
+ addType(root, "ShellPermissionDenied", [
240
+ { id: 1, name: "command", type: "string" },
241
+ { id: 2, name: "working_directory", type: "string" },
242
+ { id: 3, name: "error", type: "string" },
243
+ ]);
244
+ addType(root, "ShellStream", [
245
+ { id: 1, name: "stdout", type: "ShellStreamStdout" },
246
+ { id: 2, name: "stderr", type: "ShellStreamStderr" },
247
+ { id: 3, name: "exit", type: "ShellStreamExit" },
248
+ { id: 4, name: "start", type: "ShellStreamStart" },
249
+ { id: 5, name: "rejected", type: "ShellRejected" },
250
+ { id: 6, name: "permission_denied", type: "ShellPermissionDenied" },
251
+ ], [{ name: "event", fields: ["stdout", "stderr", "exit", "start", "rejected", "permission_denied"] }]);
252
+ addType(root, "GlobArgs", [
253
+ { id: 1, name: "target_directory", type: "string" },
254
+ { id: 2, name: "glob_pattern", type: "string" },
255
+ ]);
256
+ addType(root, "GlobResult", [
257
+ { id: 1, name: "files", type: "string", repeated: true },
258
+ { id: 2, name: "error", type: "string" },
259
+ ]);
260
+ // `args` is a map<string, google.protobuf.Value> on the wire (repeated map
261
+ // entries at field #2). We capture each entry as raw bytes and decode them in
262
+ // tools.ts via struct.decodeStructEntriesToJson.
263
+ addType(root, "McpArgs", [
264
+ { id: 1, name: "name", type: "string" },
265
+ { id: 2, name: "args", type: "bytes", repeated: true },
266
+ { id: 3, name: "tool_call_id", type: "string" },
267
+ { id: 4, name: "provider_identifier", type: "string" },
268
+ { id: 5, name: "tool_name", type: "string" },
269
+ ]);
270
+ addType(root, "McpTextContent", [{ id: 1, name: "text", type: "string" }]);
271
+ addType(root, "McpToolResultContentItem", [{ id: 1, name: "text", type: "McpTextContent" }], [{ name: "content", fields: ["text"] }]);
272
+ addType(root, "McpSuccess", [
273
+ { id: 1, name: "content", type: "McpToolResultContentItem", repeated: true },
274
+ { id: 2, name: "is_error", type: "bool" },
275
+ ]);
276
+ addType(root, "McpError", [{ id: 1, name: "error", type: "string" }]);
277
+ addType(root, "McpResult", [
278
+ { id: 1, name: "success", type: "McpSuccess" },
279
+ { id: 2, name: "error", type: "McpError" },
280
+ ], [{ name: "result", fields: ["success", "error"] }]);
281
+ // McpToolDefinition — agent.v1 shape for RequestContext.tools (#7) and
282
+ // AgentRunRequest.mcp_tools (#4). Defined early so RequestContext* can
283
+ // reference it.
284
+ addType(root, "McpToolDefinition", [
285
+ { id: 1, name: "name", type: "string" },
286
+ { id: 2, name: "description", type: "string" },
287
+ { id: 3, name: "input_schema", type: "bytes" },
288
+ { id: 4, name: "provider_identifier", type: "string" },
289
+ { id: 5, name: "tool_name", type: "string" },
290
+ ]);
291
+ // ── request_context (#10): server-initiated setup probe ──
292
+ // At the start of an agent turn the server sends ExecServerMessage
293
+ // {request_context_args} to ask the client for workspace/env/tool context.
294
+ // The reply is ExecClientMessage {request_context_result{success{request_context}}}.
295
+ // If we don't reply, the server blocks on heartbeats forever (the "times out,
296
+ // no response" symptom). We populate a minimal-but-real RequestContext — env
297
+ // (workspace/shell/os) plus the tool list echoed into #7 tools (same
298
+ // McpToolDefinition shape as AgentRunRequest #4 mcp_tools) so the model keeps
299
+ // the tools opencode advertised.
300
+ addType(root, "RequestContextArgs", [
301
+ { id: 2, name: "notes_session_id", type: "string" },
302
+ { id: 3, name: "workspace_id", type: "string" },
303
+ { id: 7, name: "use_cached", type: "bool" },
304
+ ]);
305
+ addType(root, "RequestContextEnv", [
306
+ { id: 1, name: "os_version", type: "string" },
307
+ { id: 2, name: "workspace_paths", type: "string", repeated: true },
308
+ { id: 3, name: "shell", type: "string" },
309
+ { id: 5, name: "sandbox_enabled", type: "bool" },
310
+ { id: 10, name: "time_zone", type: "string" },
311
+ { id: 11, name: "project_folder", type: "string" },
312
+ { id: 14, name: "sandbox_supported", type: "bool" },
313
+ { id: 20, name: "is_working_dir_home_dir", type: "bool" },
314
+ { id: 21, name: "process_working_directory", type: "string" },
315
+ ]);
316
+ addType(root, "CursorRule", [
317
+ { id: 1, name: "full_path", type: "string" },
318
+ { id: 2, name: "content", type: "string" },
319
+ ]);
320
+ addType(root, "RepositoryIndexingInfo", [
321
+ { id: 1, name: "relative_workspace_path", type: "string" },
322
+ { id: 2, name: "remote_urls", type: "string", repeated: true },
323
+ { id: 3, name: "remote_names", type: "string", repeated: true },
324
+ { id: 4, name: "repo_name", type: "string" },
325
+ { id: 5, name: "repo_owner", type: "string" },
326
+ { id: 6, name: "is_tracked", type: "bool" },
327
+ { id: 7, name: "is_local", type: "bool" },
328
+ { id: 9, name: "workspace_uri", type: "string" },
329
+ ]);
330
+ addType(root, "GitRepoInfo", [
331
+ { id: 1, name: "path", type: "string" },
332
+ { id: 2, name: "status", type: "string" },
333
+ { id: 3, name: "branch_name", type: "string" },
334
+ { id: 4, name: "remote_url", type: "string" },
335
+ ]);
336
+ addType(root, "AgentSkill", [
337
+ { id: 1, name: "full_path", type: "string" },
338
+ { id: 2, name: "content", type: "string" },
339
+ { id: 3, name: "description", type: "string" },
340
+ ]);
341
+ addType(root, "CustomSubagent", [
342
+ { id: 1, name: "full_path", type: "string" },
343
+ { id: 2, name: "name", type: "string" },
344
+ { id: 3, name: "description", type: "string" },
345
+ { id: 6, name: "prompt", type: "string" },
346
+ ]);
347
+ // Nested MCP filesystem / meta-tool shapes (agent.v1). Must be defined
348
+ // before RequestContextPayload / RequestContext reference them.
349
+ addType(root, "McpFsToolDescriptor", [
350
+ { id: 1, name: "tool_name", type: "string" },
351
+ { id: 3, name: "description", type: "string" },
352
+ { id: 4, name: "input_schema", type: "bytes" },
353
+ ]);
354
+ addType(root, "McpDescriptor", [
355
+ { id: 1, name: "server_name", type: "string" },
356
+ { id: 2, name: "server_identifier", type: "string" },
357
+ { id: 5, name: "tools", type: "McpFsToolDescriptor", repeated: true },
358
+ ]);
359
+ addType(root, "McpFileSystemOptions", [
360
+ { id: 1, name: "enabled", type: "bool" },
361
+ { id: 2, name: "workspace_project_dir", type: "string" },
362
+ { id: 3, name: "mcp_descriptors", type: "McpDescriptor", repeated: true },
363
+ ]);
364
+ addType(root, "McpMetaToolOptions", [
365
+ { id: 1, name: "enabled", type: "bool" },
366
+ { id: 2, name: "mcp_descriptors", type: "McpDescriptor", repeated: true },
367
+ ]);
368
+ addType(root, "RequestContextPayload", [
369
+ { id: 2, name: "rules", type: "CursorRule", repeated: true },
370
+ { id: 4, name: "env", type: "RequestContextEnv" },
371
+ { id: 6, name: "repository_info", type: "RepositoryIndexingInfo", repeated: true },
372
+ { id: 7, name: "tools", type: "McpToolDefinition", repeated: true },
373
+ { id: 11, name: "git_repos", type: "GitRepoInfo", repeated: true },
374
+ { id: 13, name: "project_layouts", type: "LsDirectoryTreeNode", repeated: true },
375
+ { id: 22, name: "custom_subagents", type: "CustomSubagent", repeated: true },
376
+ { id: 23, name: "mcp_file_system_options", type: "McpFileSystemOptions" },
377
+ { id: 25, name: "hooks_additional_context", type: "string" },
378
+ { id: 29, name: "agent_skills", type: "AgentSkill", repeated: true },
379
+ { id: 33, name: "git_repo_info_complete", type: "bool" },
380
+ { id: 34, name: "mcp_meta_tool_options", type: "McpMetaToolOptions" },
381
+ { id: 36, name: "mcp_info_complete", type: "bool" },
382
+ { id: 39, name: "rules_info_complete", type: "bool" },
383
+ { id: 40, name: "env_info_complete", type: "bool" },
384
+ { id: 41, name: "repository_info_complete", type: "bool" },
385
+ { id: 42, name: "custom_subagents_info_complete", type: "bool" },
386
+ { id: 43, name: "agent_skills_info_complete", type: "bool" },
387
+ { id: 44, name: "mcp_file_system_info_complete", type: "bool" },
388
+ { id: 45, name: "git_status_info_complete", type: "bool" },
389
+ { id: 46, name: "user_permissions_auto_run", type: "bool" },
390
+ { id: 47, name: "project_permissions_auto_run", type: "bool" },
391
+ ]);
392
+ addType(root, "RequestContextSuccess", [
393
+ { id: 1, name: "request_context", type: "RequestContextPayload" },
394
+ ]);
395
+ addType(root, "RequestContextResult", [
396
+ { id: 1, name: "success", type: "RequestContextSuccess" },
397
+ ]);
398
+ // ExecServerMessage — server asks us to execute a tool
399
+ addType(root, "ExecServerMessage", [
400
+ { id: 1, name: "id", type: "uint32" },
401
+ { id: 15, name: "exec_id", type: "string" },
402
+ { id: 19, name: "span", type: "string" },
403
+ { id: 3, name: "write_args", type: "WriteArgs" },
404
+ { id: 4, name: "delete_args", type: "DeleteArgs" },
405
+ { id: 5, name: "grep_args", type: "GrepArgs" },
406
+ { id: 7, name: "read_args", type: "ReadArgs" },
407
+ { id: 8, name: "ls_args", type: "LsArgs" },
408
+ { id: 10, name: "request_context_args", type: "RequestContextArgs" },
409
+ { id: 11, name: "mcp_args", type: "McpArgs" },
410
+ { id: 14, name: "shell_stream_args", type: "ShellArgs" },
411
+ // Pi write (#48 args → #49 result). Field numbers differ from classic write (#3).
412
+ { 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"] }]);
414
+ // ExecClientMessage — client sends tool result back
415
+ addType(root, "ExecClientMessage", [
416
+ { id: 1, name: "id", type: "uint32" },
417
+ { id: 15, name: "exec_id", type: "string" },
418
+ { id: 39, name: "local_execution_time_ms", type: "uint64" },
419
+ { id: 3, name: "write_result", type: "WriteResult" },
420
+ { id: 4, name: "delete_result", type: "DeleteResult" },
421
+ { id: 5, name: "grep_result", type: "GrepResult" },
422
+ { id: 7, name: "read_result", type: "ReadResult" },
423
+ { id: 8, name: "ls_result", type: "LsResult" },
424
+ { id: 10, name: "request_context_result", type: "RequestContextResult" },
425
+ { id: 11, name: "mcp_result", type: "McpResult" },
426
+ { id: 14, name: "shell_stream", type: "ShellStream" },
427
+ { 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"] }]);
429
+ addType(root, "ExecServerControlMessage", [
430
+ { id: 1, name: "abort", type: "ExecServerAbort" },
431
+ ]);
432
+ addType(root, "ExecServerAbort", [
433
+ { id: 1, name: "id", type: "uint32" },
434
+ ]);
435
+ // Client→server control (ACM #5). Distinct from ExecServerControlMessage (ASM #5).
436
+ // After every exec result (especially multi-frame shell_stream), the real CLI
437
+ // sends stream_close{id} — without it the cloud waits forever on shell execs.
438
+ addType(root, "ExecClientStreamClose", [{ id: 1, name: "id", type: "uint32" }]);
439
+ addType(root, "ExecClientThrow", [
440
+ { id: 1, name: "id", type: "uint32" },
441
+ { id: 2, name: "error", type: "string" },
442
+ ]);
443
+ addType(root, "ExecClientHeartbeat", [{ id: 1, name: "id", type: "uint32" }]);
444
+ addType(root, "ExecClientControlMessage", [
445
+ { id: 1, name: "stream_close", type: "ExecClientStreamClose" },
446
+ { id: 2, name: "throw", type: "ExecClientThrow" },
447
+ { id: 3, name: "heartbeat", type: "ExecClientHeartbeat" },
448
+ ], [{ name: "message", fields: ["stream_close", "throw", "heartbeat"] }]);
449
+ // ── Run request types ──
450
+ addType(root, "ParameterValue", [
451
+ { id: 1, name: "id", type: "string" },
452
+ { id: 2, name: "value", type: "string" },
453
+ ]);
454
+ addType(root, "RequestedModel", [
455
+ { id: 1, name: "model_id", type: "string" },
456
+ { id: 2, name: "max_mode", type: "bool" },
457
+ { id: 3, name: "parameters", type: "ParameterValue", repeated: true },
458
+ ]);
459
+ addType(root, "UserMessage", [
460
+ { id: 1, name: "text", type: "string" },
461
+ { id: 2, name: "message_id", type: "string" },
462
+ ]);
463
+ // McpToolDefinition — agent.v1 shape used by RequestContext.tools (#7) and
464
+ // AgentRunRequest.mcp_tools (#4). Capture 00074 / CLI: { #1 name (composite
465
+ // <server>-<tool>), #2 description, #3 input_schema (Value bytes),
466
+ // #4 provider_identifier, #5 tool_name }.
467
+ // (Defined later as McpToolDefinition; keep a legacy alias type name for
468
+ // any older encode paths that still look up "McpToolDescriptor".)
469
+ addType(root, "McpToolDescriptor", [
470
+ { id: 1, name: "name", type: "string" },
471
+ { id: 2, name: "description", type: "string" },
472
+ { id: 3, name: "input_schema", type: "bytes" },
473
+ { id: 4, name: "provider_identifier", type: "string" },
474
+ { id: 5, name: "tool_name", type: "string" },
475
+ ]);
476
+ // RequestContext — UserMessageAction #2. Live per-turn tools go here
477
+ // (AgentRunRequest.mcp_tools #4 is prewarm-only / empty on real turns).
478
+ addType(root, "RequestContext", [
479
+ { id: 2, name: "rules", type: "CursorRule", repeated: true },
480
+ { id: 4, name: "env", type: "RequestContextEnv" },
481
+ { id: 6, name: "repository_info", type: "RepositoryIndexingInfo", repeated: true },
482
+ { id: 7, name: "tools", type: "McpToolDefinition", repeated: true },
483
+ { id: 11, name: "git_repos", type: "GitRepoInfo", repeated: true },
484
+ { id: 13, name: "project_layouts", type: "LsDirectoryTreeNode", repeated: true },
485
+ { id: 22, name: "custom_subagents", type: "CustomSubagent", repeated: true },
486
+ { id: 23, name: "mcp_file_system_options", type: "McpFileSystemOptions" },
487
+ { id: 25, name: "hooks_additional_context", type: "string" },
488
+ { id: 29, name: "agent_skills", type: "AgentSkill", repeated: true },
489
+ { id: 33, name: "git_repo_info_complete", type: "bool" },
490
+ { id: 34, name: "mcp_meta_tool_options", type: "McpMetaToolOptions" },
491
+ { id: 36, name: "mcp_info_complete", type: "bool" },
492
+ { id: 39, name: "rules_info_complete", type: "bool" },
493
+ { id: 40, name: "env_info_complete", type: "bool" },
494
+ { id: 41, name: "repository_info_complete", type: "bool" },
495
+ { id: 42, name: "custom_subagents_info_complete", type: "bool" },
496
+ { id: 43, name: "agent_skills_info_complete", type: "bool" },
497
+ { id: 44, name: "mcp_file_system_info_complete", type: "bool" },
498
+ { id: 45, name: "git_status_info_complete", type: "bool" },
499
+ { id: 46, name: "user_permissions_auto_run", type: "bool" },
500
+ { id: 47, name: "project_permissions_auto_run", type: "bool" },
501
+ ]);
502
+ addType(root, "UserMessageAction", [
503
+ { id: 1, name: "user_message", type: "UserMessage" },
504
+ { id: 2, name: "request_context", type: "RequestContext" },
505
+ ]);
506
+ addType(root, "ResumeAction", [
507
+ { id: 1, name: "conversation_id", type: "string" },
508
+ ]);
509
+ addType(root, "CancelAction", [
510
+ { id: 1, name: "conversation_id", type: "string" },
511
+ ]);
512
+ addType(root, "ConversationAction", [
513
+ { id: 1, name: "user_message_action", type: "UserMessageAction" },
514
+ { id: 2, name: "resume_action", type: "ResumeAction" },
515
+ { id: 3, name: "cancel_action", type: "CancelAction" },
516
+ ], [{ name: "action", fields: ["user_message_action", "resume_action", "cancel_action"] }]);
517
+ // Seed ConversationStateStructure for turn 1 (system prompt as JSON strings
518
+ // in #1). After the first conversation_checkpoint_update we echo opaque
519
+ // server bytes instead — CLI's live structure uses blob-id bytes in #1/#8.
520
+ addType(root, "AssistantMessage", [
521
+ { id: 1, name: "text", type: "string" },
522
+ ]);
523
+ addType(root, "ConversationStep", [
524
+ { id: 1, name: "assistant_message", type: "AssistantMessage" },
525
+ ], [{ name: "message", fields: ["assistant_message"] }]);
526
+ addType(root, "AgentConversationTurn", [
527
+ { id: 1, name: "user_message", type: "UserMessage" },
528
+ { id: 2, name: "steps", type: "ConversationStep", repeated: true },
529
+ ]);
530
+ addType(root, "ConversationTurn", [
531
+ { id: 1, name: "agent_conversation_turn", type: "AgentConversationTurn" },
532
+ ], [{ name: "turn", fields: ["agent_conversation_turn"] }]);
533
+ // Seed-only schema (JSON strings). Checkpoint bytes are never decoded here —
534
+ // AgentRunRequest.conversation_state is typed as bytes and carries them opaque.
535
+ addType(root, "ConversationStateStructure", [
536
+ { id: 1, name: "root_prompt_messages_json", type: "string", repeated: true },
537
+ { id: 8, name: "turns", type: "ConversationTurn", repeated: true },
538
+ ]);
539
+ addType(root, "ModelDetails", [
540
+ { id: 1, name: "model_id", type: "string" },
541
+ ]);
542
+ addType(root, "McpTools", [
543
+ { id: 1, name: "mcp_tools", type: "McpToolDefinition", repeated: true },
544
+ ]);
545
+ addType(root, "AgentRunRequest", [
546
+ { id: 1, name: "conversation_state", type: "bytes" },
547
+ { id: 2, name: "action", type: "ConversationAction" },
548
+ { id: 4, name: "mcp_tools", type: "McpTools" },
549
+ { id: 5, name: "conversation_id", type: "string" },
550
+ { id: 8, name: "custom_system_prompt", type: "string" },
551
+ { id: 9, name: "requested_model", type: "RequestedModel" },
552
+ { id: 10, name: "unknown_flag", type: "uint32" },
553
+ { id: 12, name: "field_12", type: "uint32" },
554
+ { id: 14, name: "available_models", type: "RequestedModel", repeated: true },
555
+ { id: 16, name: "conversation_id_dup", type: "string" },
556
+ ]);
557
+ // ── Client heartbeat ──
558
+ addType(root, "ClientHeartbeat", []);
559
+ // ── KV blob store (cursor moves large payloads out-of-band via this channel) ──
560
+ // Server sends KvServerMessage (AgentServerMessage #4); client MUST reply with
561
+ // KvClientMessage (AgentClientMessage #3) on the same Run stream, echoing `id`.
562
+ // If we don't ack set_blob / answer get_blob, the server hangs (endless
563
+ // heartbeats, no response) — this was the "no response" root cause.
564
+ addType(root, "GetBlobArgs", [
565
+ { id: 1, name: "blob_id", type: "bytes" },
566
+ ]);
567
+ addType(root, "GetBlobResult", [
568
+ { id: 1, name: "blob_data", type: "bytes" },
569
+ ]);
570
+ addType(root, "SetBlobArgs", [
571
+ { id: 1, name: "blob_id", type: "bytes" },
572
+ { id: 2, name: "blob_data", type: "bytes" },
573
+ ]);
574
+ addType(root, "SetBlobResult", [
575
+ { id: 1, name: "error", type: "string" },
576
+ ]);
577
+ addType(root, "KvServerMessage", [
578
+ { id: 1, name: "id", type: "uint32" },
579
+ { id: 2, name: "get_blob_args", type: "GetBlobArgs" },
580
+ { id: 3, name: "set_blob_args", type: "SetBlobArgs" },
581
+ ], [{ name: "message", fields: ["get_blob_args", "set_blob_args"] }]);
582
+ addType(root, "KvClientMessage", [
583
+ { id: 1, name: "id", type: "uint32" },
584
+ { id: 2, name: "get_blob_result", type: "GetBlobResult" },
585
+ { id: 3, name: "set_blob_result", type: "SetBlobResult" },
586
+ ], [{ name: "message", fields: ["get_blob_result", "set_blob_result"] }]);
587
+ // ── AgentClientMessage ──
588
+ addType(root, "AgentClientMessage", [
589
+ { id: 1, name: "run_request", type: "AgentRunRequest" },
590
+ { id: 2, name: "exec_client_message", type: "ExecClientMessage" },
591
+ { id: 3, name: "kv_client_message", type: "KvClientMessage" },
592
+ { id: 5, name: "exec_client_control_message", type: "ExecClientControlMessage" },
593
+ { 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"] }]);
595
+ // ── AgentServerMessage ──
596
+ addType(root, "AgentServerMessage", [
597
+ { id: 1, name: "interaction_update", type: "InteractionUpdate" },
598
+ { id: 2, name: "exec_server_message", type: "ExecServerMessage" },
599
+ { id: 3, name: "conversation_checkpoint_update", type: "bytes" },
600
+ { id: 4, name: "kv_server_message", type: "KvServerMessage" },
601
+ { id: 5, name: "exec_server_control_message", type: "ExecServerControlMessage" },
602
+ { id: 7, name: "interaction_query", type: "bytes" },
603
+ ], [{ name: "message", fields: ["interaction_update", "exec_server_message", "conversation_checkpoint_update", "kv_server_message", "exec_server_control_message", "interaction_query"] }]);
604
+ // ── AvailableModels types ──
605
+ addType(root, "AvailableModelsRequest", []);
606
+ addType(root, "AvailableModelParameterDefinition", [
607
+ { id: 1, name: "id", type: "string" },
608
+ { id: 2, name: "values", type: "string", repeated: true },
609
+ ]);
610
+ addType(root, "AvailableModelParameterValue", [
611
+ { id: 1, name: "id", type: "string" },
612
+ { id: 2, name: "value", type: "string" },
613
+ ]);
614
+ addType(root, "AvailableModelVariant", [
615
+ { id: 1, name: "display_name", type: "string" },
616
+ { id: 2, name: "is_max_mode", type: "bool" },
617
+ { id: 3, name: "is_default_max_config", type: "bool" },
618
+ { id: 4, name: "is_default_non_max_config", type: "bool" },
619
+ { id: 5, name: "parameter_values", type: "AvailableModelParameterValue", repeated: true },
620
+ ]);
621
+ addType(root, "AvailableModelEntry", [
622
+ { id: 1, name: "name", type: "string" },
623
+ { id: 2, name: "default_on", type: "bool" },
624
+ { id: 5, name: "supports_agent", type: "bool" },
625
+ { id: 9, name: "supports_thinking", type: "bool" },
626
+ { id: 10, name: "supports_images", type: "bool" },
627
+ { id: 14, name: "supports_max_mode", type: "bool" },
628
+ { id: 15, name: "context_token_limit", type: "uint32" },
629
+ { id: 17, name: "client_display_name", type: "string" },
630
+ { id: 18, name: "server_model_name", type: "string" },
631
+ { id: 29, name: "parameter_definitions", type: "AvailableModelParameterDefinition", repeated: true },
632
+ { id: 30, name: "variants", type: "AvailableModelVariant", repeated: true },
633
+ ]);
634
+ addType(root, "AvailableModelsResponse", [
635
+ { id: 1, name: "models", type: "AvailableModelEntry", repeated: true },
636
+ ]);
637
+ return root;
638
+ }
639
+ // ── Singleton root ──
640
+ let _root = null;
641
+ export function getMessageTypes() {
642
+ if (!_root) {
643
+ _root = createMessageTypes();
644
+ }
645
+ return _root;
646
+ }
647
+ export function encodeMessage(typeName, message) {
648
+ const root = getMessageTypes();
649
+ const type = root.lookupType(typeName);
650
+ const err = type.verify(message);
651
+ if (err)
652
+ throw new Error(`Invalid message for ${typeName}: ${err}`);
653
+ return type.encode(type.fromObject(message)).finish();
654
+ }
655
+ export function decodeMessage(typeName, data) {
656
+ const root = getMessageTypes();
657
+ const type = root.lookupType(typeName);
658
+ const decoded = type.decode(data);
659
+ return type.toObject(decoded, { defaults: true, json: true, longs: Number });
660
+ }
661
+ /**
662
+ * Decode a protobuf sub-message from a frame payload that wraps it in
663
+ * a top-level field key + length varint. Skips the outer wrapper and
664
+ * decodes the inner body as `typeName`.
665
+ */
666
+ export function decodeWrappedMessage(typeName, data) {
667
+ let offset = 1; // skip field key
668
+ // skip varint length
669
+ while (offset < data.length) {
670
+ const b = data[offset];
671
+ offset++;
672
+ if (!(b & 0x80))
673
+ break;
674
+ }
675
+ return decodeMessage(typeName, data.subarray(offset));
676
+ }