cursor-opencode-provider 0.6.4 → 0.6.6

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.
@@ -0,0 +1,372 @@
1
+ import { execFile } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { promisify } from "node:util";
5
+ import { encodeMessage } from "./messages.js";
6
+ const execFileAsync = promisify(execFile);
7
+ /** aiserver.v1.GetDiffRequest.OutputFormat */
8
+ export const GIT_DIFF_FORMAT_UNSPECIFIED = 0;
9
+ export const GIT_DIFF_FORMAT_NAME_STATUS = 1;
10
+ export const GIT_DIFF_FORMAT_NAME_STATUS_AND_NUMSTAT = 2;
11
+ export const GIT_DIFF_FORMAT_FILE_DIFFS = 3;
12
+ export const GIT_DIFF_FORMAT_DIFFS_WITH_BEFORE_AND_AFTER = 4;
13
+ const DEFAULT_REMOTE_BRANCHES = ["main", "master", "develop"];
14
+ const GIT_TIMEOUT_MS = 30_000;
15
+ const GIT_MAX_BUFFER = 32 * 1024 * 1024;
16
+ const GIT_ENV = {
17
+ ...process.env,
18
+ GIT_TERMINAL_PROMPT: "0",
19
+ GIT_OPTIONAL_LOCKS: "0",
20
+ };
21
+ function gitErrorMessage(error, fallback) {
22
+ if (!error || typeof error !== "object")
23
+ return fallback;
24
+ const err = error;
25
+ const stderr = typeof err.stderr === "string" ? err.stderr.trim() : "";
26
+ if (stderr)
27
+ return stderr.split("\n")[0] ?? stderr;
28
+ if (typeof err.message === "string" && err.message)
29
+ return err.message;
30
+ return fallback;
31
+ }
32
+ async function git(cwd, args, options) {
33
+ try {
34
+ const { stdout, stderr } = await execFileAsync("git", args, {
35
+ cwd,
36
+ encoding: "utf8",
37
+ timeout: GIT_TIMEOUT_MS,
38
+ maxBuffer: GIT_MAX_BUFFER,
39
+ env: GIT_ENV,
40
+ });
41
+ return {
42
+ stdout: options?.trim === false ? stdout : stdout.trimEnd(),
43
+ stderr: stderr ?? "",
44
+ code: 0,
45
+ };
46
+ }
47
+ catch (error) {
48
+ const err = error;
49
+ const code = typeof err.code === "number" ? err.code : 1;
50
+ if (options?.ignoreExit) {
51
+ return {
52
+ stdout: options.trim === false ? (err.stdout ?? "") : (err.stdout ?? "").trimEnd(),
53
+ stderr: err.stderr ?? "",
54
+ code,
55
+ };
56
+ }
57
+ throw new Error(gitErrorMessage(error, `git ${args.join(" ")} failed`));
58
+ }
59
+ }
60
+ function str(value) {
61
+ return typeof value === "string" ? value : "";
62
+ }
63
+ function num(value) {
64
+ if (typeof value === "number" && Number.isFinite(value))
65
+ return value;
66
+ if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) {
67
+ return Number(value);
68
+ }
69
+ return undefined;
70
+ }
71
+ function resolveGitCwd(requestCwd, workspaceRoot) {
72
+ const root = path.resolve(workspaceRoot || process.cwd());
73
+ const requested = requestCwd.trim();
74
+ if (!requested)
75
+ return root;
76
+ return path.isAbsolute(requested) ? path.resolve(requested) : path.resolve(root, requested);
77
+ }
78
+ async function resolveDefaultBase(cwd) {
79
+ try {
80
+ const head = (await git(cwd, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"])).stdout.trim();
81
+ if (head)
82
+ return head;
83
+ }
84
+ catch {
85
+ /* try origin/<main|master|develop> */
86
+ }
87
+ for (const name of DEFAULT_REMOTE_BRANCHES) {
88
+ const ref = `origin/${name}`;
89
+ try {
90
+ await git(cwd, ["rev-parse", "--verify", ref]);
91
+ return ref;
92
+ }
93
+ catch {
94
+ /* next candidate */
95
+ }
96
+ }
97
+ try {
98
+ const remotes = (await git(cwd, ["branch", "-r"])).stdout.split("\n")
99
+ .map((line) => line.trim())
100
+ .find((line) => line.startsWith("origin/"));
101
+ if (remotes)
102
+ return remotes;
103
+ }
104
+ catch {
105
+ /* try init.defaultBranch */
106
+ }
107
+ try {
108
+ const configured = (await git(cwd, ["config", "--get", "init.defaultBranch"])).stdout.trim();
109
+ if (configured)
110
+ return configured;
111
+ }
112
+ catch {
113
+ /* no default */
114
+ }
115
+ throw new Error("Could not determine default branch");
116
+ }
117
+ function stripDiffPrefix(value) {
118
+ return value.replace(/^[abiwco12]\//, "");
119
+ }
120
+ function parseDiffGitPaths(line) {
121
+ if (!line.startsWith("diff --git "))
122
+ return undefined;
123
+ const rest = line.slice("diff --git ".length).trim();
124
+ const match = rest.match(/^(?:[abiwco12]\/)?(.+?) (?:[abiwco12]\/)?(.+)$/);
125
+ if (!match)
126
+ return undefined;
127
+ return { from: stripDiffPrefix(match[1]), to: stripDiffPrefix(match[2]) };
128
+ }
129
+ function parsePathHeader(line) {
130
+ const body = line.replace(/^(---|\+\+\+)\s+/, "");
131
+ const tab = body.indexOf("\t");
132
+ const raw = (tab >= 0 ? body.slice(0, tab) : body).trim().replace(/^["']|["']$/g, "");
133
+ if (raw === "/dev/null")
134
+ return "/dev/null";
135
+ return stripDiffPrefix(raw);
136
+ }
137
+ /** Parse `git diff --no-color` into aiserver.v1.FileDiff rows (CLI `Oc` / `FR`). */
138
+ export function parseUnifiedDiff(text) {
139
+ if (!text || /^\s+$/.test(text))
140
+ return [];
141
+ const diffs = [];
142
+ let current;
143
+ let chunk;
144
+ let remainingOld = 0;
145
+ let remainingNew = 0;
146
+ let oldLine = 0;
147
+ let newLine = 0;
148
+ let inHunk = false;
149
+ const startFile = (from = "", to = "") => {
150
+ current = { from, to, chunks: [], added: 0, removed: 0 };
151
+ diffs.push(current);
152
+ chunk = undefined;
153
+ inHunk = false;
154
+ };
155
+ const ensureFile = () => {
156
+ if (!current)
157
+ startFile();
158
+ };
159
+ const appendNoNewline = (line) => {
160
+ if (!chunk || chunk.lines.length === 0)
161
+ return;
162
+ chunk.lines.push(line);
163
+ };
164
+ for (const line of text.split("\n")) {
165
+ if (inHunk && chunk && current) {
166
+ if (line === "\") {
167
+ appendNoNewline(line);
168
+ continue;
169
+ }
170
+ if (line.startsWith("-")) {
171
+ chunk.lines.push(line);
172
+ current.removed++;
173
+ oldLine++;
174
+ remainingOld--;
175
+ }
176
+ else if (line.startsWith("+")) {
177
+ chunk.lines.push(line);
178
+ current.added++;
179
+ newLine++;
180
+ remainingNew--;
181
+ }
182
+ else if (line.startsWith(" ") || line === "") {
183
+ chunk.lines.push(line.length === 0 ? " " : line);
184
+ oldLine++;
185
+ newLine++;
186
+ remainingOld--;
187
+ remainingNew--;
188
+ }
189
+ else {
190
+ inHunk = false;
191
+ }
192
+ if (inHunk && remainingOld <= 0 && remainingNew <= 0)
193
+ inHunk = false;
194
+ if (inHunk)
195
+ continue;
196
+ }
197
+ if (line.startsWith("diff --git ")) {
198
+ const paths = parseDiffGitPaths(line);
199
+ startFile(paths?.from ?? "", paths?.to ?? "");
200
+ continue;
201
+ }
202
+ if (line.startsWith("new file mode ")) {
203
+ ensureFile();
204
+ current.from = "/dev/null";
205
+ continue;
206
+ }
207
+ if (line.startsWith("deleted file mode ")) {
208
+ ensureFile();
209
+ current.to = "/dev/null";
210
+ continue;
211
+ }
212
+ if (line.startsWith("--- ")) {
213
+ ensureFile();
214
+ current.from = parsePathHeader(line);
215
+ continue;
216
+ }
217
+ if (line.startsWith("+++ ")) {
218
+ ensureFile();
219
+ current.to = parsePathHeader(line);
220
+ continue;
221
+ }
222
+ const hunk = /^@@\s+-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/.exec(line);
223
+ if (hunk) {
224
+ ensureFile();
225
+ oldLine = Number(hunk[1]);
226
+ newLine = Number(hunk[3]);
227
+ remainingOld = hunk[2] !== undefined ? Number(hunk[2]) : 1;
228
+ remainingNew = hunk[4] !== undefined ? Number(hunk[4]) : 1;
229
+ chunk = {
230
+ content: line,
231
+ lines: [],
232
+ old_start: Number(hunk[1]),
233
+ old_lines: remainingOld,
234
+ new_start: Number(hunk[3]),
235
+ new_lines: remainingNew,
236
+ };
237
+ current.chunks.push(chunk);
238
+ inHunk = true;
239
+ }
240
+ }
241
+ return diffs;
242
+ }
243
+ function effectiveFormat(raw) {
244
+ switch (raw) {
245
+ case GIT_DIFF_FORMAT_NAME_STATUS:
246
+ case GIT_DIFF_FORMAT_NAME_STATUS_AND_NUMSTAT:
247
+ case GIT_DIFF_FORMAT_FILE_DIFFS:
248
+ case GIT_DIFF_FORMAT_DIFFS_WITH_BEFORE_AND_AFTER:
249
+ return raw;
250
+ default:
251
+ return GIT_DIFF_FORMAT_FILE_DIFFS;
252
+ }
253
+ }
254
+ async function collectUntrackedDiffs(cwd, maxFiles) {
255
+ if (maxFiles <= 0)
256
+ return [];
257
+ const listed = (await git(cwd, ["ls-files", "--others", "--exclude-standard"])).stdout
258
+ .split("\n")
259
+ .map((line) => line.trim())
260
+ .filter(Boolean)
261
+ .slice(0, maxFiles);
262
+ const extra = [];
263
+ for (const file of listed) {
264
+ const raw = await git(cwd, ["diff", "--no-color", "--no-index", "/dev/null", file], {
265
+ ignoreExit: true,
266
+ trim: false,
267
+ });
268
+ extra.push(...parseUnifiedDiff(raw.stdout));
269
+ }
270
+ return extra;
271
+ }
272
+ export async function executeGitDiff(request, workspaceRoot) {
273
+ const cwd = resolveGitCwd(str(request.cwd), workspaceRoot);
274
+ if (!fs.existsSync(cwd)) {
275
+ throw new Error(`git_diff cwd does not exist: ${cwd}`);
276
+ }
277
+ const inside = await git(cwd, ["rev-parse", "--is-inside-work-tree"]).catch((error) => {
278
+ throw new Error(gitErrorMessage(error, "not a git repository"));
279
+ });
280
+ if (inside.stdout.trim() !== "true") {
281
+ throw new Error("not a git repository");
282
+ }
283
+ const ref = str(request.ref);
284
+ let base = str(request.base_ref);
285
+ if (!base)
286
+ base = await resolveDefaultBase(cwd);
287
+ if (request.merge_base === true) {
288
+ base = (await git(cwd, ["merge-base", base, ref || "HEAD"])).stdout.trim();
289
+ }
290
+ const args = ["diff", "--no-color"];
291
+ if (request.include_space_changes !== true)
292
+ args.push("--ignore-space-change");
293
+ const contextLines = num(request.unified_context_lines);
294
+ if (contextLines !== undefined && contextLines > 0)
295
+ args.push(`-U${contextLines}`);
296
+ args.push(base);
297
+ if (ref)
298
+ args.push(ref);
299
+ const targetPaths = Array.isArray(request.target_paths)
300
+ ? request.target_paths.filter((item) => typeof item === "string" && item.length > 0)
301
+ : [];
302
+ if (targetPaths.length > 0) {
303
+ args.push("--");
304
+ args.push(...targetPaths);
305
+ }
306
+ const diffText = (await git(cwd, args, { trim: false })).stdout;
307
+ const diffs = parseUnifiedDiff(diffText);
308
+ diffs.push(...await collectUntrackedDiffs(cwd, num(request.max_untracked_files) ?? 0));
309
+ const format = effectiveFormat(num(request.output_format));
310
+ if (format !== GIT_DIFF_FORMAT_FILE_DIFFS && format !== GIT_DIFF_FORMAT_DIFFS_WITH_BEFORE_AND_AFTER) {
311
+ for (const diff of diffs)
312
+ diff.chunks = [];
313
+ }
314
+ const response = {
315
+ diff: {
316
+ diffs,
317
+ diff_type: 0,
318
+ },
319
+ };
320
+ if (request.return_head_sha === true) {
321
+ response.head_sha = (await git(cwd, ["rev-parse", "HEAD"])).stdout.trim();
322
+ const status = (await git(cwd, ["status", "--porcelain=v1", "--untracked-files=all"])).stdout.trim();
323
+ response.has_uncommitted_changes = status.length > 0;
324
+ }
325
+ return response;
326
+ }
327
+ function throwAndClose(execId, error) {
328
+ return [
329
+ encodeMessage("AgentClientMessage", {
330
+ exec_client_control_message: {
331
+ throw: { id: execId, error },
332
+ },
333
+ }),
334
+ encodeMessage("AgentClientMessage", {
335
+ exec_client_control_message: {
336
+ stream_close: { id: execId },
337
+ },
338
+ }),
339
+ ];
340
+ }
341
+ /**
342
+ * Answer exec #44. GetDiffResponse has no error oneof — failures use
343
+ * exec_client_control_message.throw, matching Cursor CLI `class Dc`.
344
+ */
345
+ export async function buildGitDiffExecMessages(input) {
346
+ let response;
347
+ try {
348
+ response = await executeGitDiff(input.request, input.workspaceRoot);
349
+ }
350
+ catch (error) {
351
+ return throwAndClose(input.execId, error.message || "git_diff failed");
352
+ }
353
+ const responseBytes = encodeMessage("GetDiffResponse", response);
354
+ const maxBytes = num(input.request.max_response_bytes) ?? 0;
355
+ if (maxBytes > 0 && responseBytes.byteLength > maxBytes) {
356
+ return throwAndClose(input.execId, `GetDiffResponseTooLarge: ${responseBytes.byteLength} bytes exceeds the ${maxBytes} byte limit`);
357
+ }
358
+ return [
359
+ encodeMessage("AgentClientMessage", {
360
+ exec_client_message: {
361
+ id: input.execId,
362
+ local_execution_time_ms: 0,
363
+ git_diff_response: response,
364
+ },
365
+ }),
366
+ encodeMessage("AgentClientMessage", {
367
+ exec_client_control_message: {
368
+ stream_close: { id: input.execId },
369
+ },
370
+ }),
371
+ ];
372
+ }
@@ -653,6 +653,199 @@ export function createMessageTypes() {
653
653
  { id: 2, name: "working_directory", type: "string" },
654
654
  { id: 3, name: "error", type: "string" },
655
655
  ]);
656
+ // ── Soft-deny stubs for known unsupported Cursor-native exec variants ──
657
+ // These are encode-only: enough to emit a populated deny, not full success.
658
+ // Canonical field numbers from agent.proto ExecClientMessage.
659
+ // ShellResult is also the live reply for exec #2 shell_args (OpenCode bash).
660
+ addType(root, "ShellSuccess", [
661
+ { id: 1, name: "command", type: "string" },
662
+ { id: 2, name: "working_directory", type: "string" },
663
+ { id: 3, name: "exit_code", type: "int32" },
664
+ { id: 4, name: "signal", type: "string" },
665
+ { id: 5, name: "stdout", type: "string" },
666
+ { id: 6, name: "stderr", type: "string" },
667
+ { id: 7, name: "execution_time", type: "int32" },
668
+ { id: 9, name: "shell_id", type: "uint32" },
669
+ { id: 11, name: "pid", type: "uint32" },
670
+ { id: 12, name: "ms_to_wait", type: "int32" },
671
+ { id: 13, name: "local_execution_time_ms", type: "int32" },
672
+ { id: 14, name: "background_reason", type: "uint32" },
673
+ ]);
674
+ addType(root, "ShellFailure", [
675
+ { id: 1, name: "command", type: "string" },
676
+ { id: 2, name: "working_directory", type: "string" },
677
+ { id: 3, name: "exit_code", type: "int32" },
678
+ { id: 4, name: "signal", type: "string" },
679
+ { id: 5, name: "stdout", type: "string" },
680
+ { id: 6, name: "stderr", type: "string" },
681
+ { id: 7, name: "execution_time", type: "int32" },
682
+ { id: 10, name: "abort_reason", type: "uint32" },
683
+ { id: 11, name: "aborted", type: "bool" },
684
+ ]);
685
+ addType(root, "ShellTimeout", [
686
+ { id: 1, name: "command", type: "string" },
687
+ { id: 2, name: "working_directory", type: "string" },
688
+ { id: 3, name: "timeout_ms", type: "int32" },
689
+ ]);
690
+ addType(root, "ShellResult", [
691
+ { id: 1, name: "success", type: "ShellSuccess" },
692
+ { id: 2, name: "failure", type: "ShellFailure" },
693
+ { id: 3, name: "timeout", type: "ShellTimeout" },
694
+ { id: 4, name: "rejected", type: "ShellRejected" },
695
+ { id: 102, name: "is_background", type: "bool" },
696
+ { id: 104, name: "pid", type: "uint32" },
697
+ ], [{ name: "result", fields: ["success", "failure", "timeout", "rejected"] }]);
698
+ addType(root, "DiagnosticsError", [
699
+ { id: 1, name: "path", type: "string" },
700
+ { id: 2, name: "error", type: "string" },
701
+ ]);
702
+ addType(root, "DiagnosticsResult", [
703
+ { id: 2, name: "error", type: "DiagnosticsError" },
704
+ ], [{ name: "result", fields: ["error"] }]);
705
+ addType(root, "FetchError", [
706
+ { id: 1, name: "url", type: "string" },
707
+ { id: 2, name: "error", type: "string" },
708
+ ]);
709
+ addType(root, "FetchResult", [
710
+ { id: 2, name: "error", type: "FetchError" },
711
+ ], [{ name: "result", fields: ["error"] }]);
712
+ addType(root, "RecordScreenFailure", [
713
+ { id: 1, name: "error", type: "string" },
714
+ ]);
715
+ addType(root, "RecordScreenResult", [
716
+ { id: 4, name: "failure", type: "RecordScreenFailure" },
717
+ ], [{ name: "result", fields: ["failure"] }]);
718
+ addType(root, "ComputerUseError", [
719
+ { id: 1, name: "error", type: "string" },
720
+ ]);
721
+ addType(root, "ComputerUseResult", [
722
+ { id: 2, name: "error", type: "ComputerUseError" },
723
+ ], [{ name: "result", fields: ["error"] }]);
724
+ addType(root, "WriteShellStdinError", [
725
+ { id: 1, name: "error", type: "string" },
726
+ ]);
727
+ addType(root, "WriteShellStdinResult", [
728
+ { id: 2, name: "error", type: "WriteShellStdinError" },
729
+ ], [{ name: "result", fields: ["error"] }]);
730
+ addType(root, "SubagentAwaitError", [
731
+ { id: 1, name: "agent_id", type: "string" },
732
+ { id: 2, name: "error", type: "string" },
733
+ ]);
734
+ addType(root, "SubagentAwaitResult", [
735
+ { id: 4, name: "error", type: "SubagentAwaitError" },
736
+ ], [{ name: "result", fields: ["error"] }]);
737
+ addType(root, "SmartModeClassifierError", [
738
+ { id: 1, name: "error", type: "string" },
739
+ ]);
740
+ addType(root, "SmartModeClassifierResult", [
741
+ { id: 2, name: "error", type: "SmartModeClassifierError" },
742
+ ], [{ name: "result", fields: ["error"] }]);
743
+ addType(root, "CanvasDiagnosticsError", [
744
+ { id: 1, name: "path", type: "string" },
745
+ { id: 2, name: "error", type: "string" },
746
+ ]);
747
+ addType(root, "CanvasDiagnosticsResult", [
748
+ { id: 2, name: "error", type: "CanvasDiagnosticsError" },
749
+ ], [{ name: "result", fields: ["error"] }]);
750
+ addType(root, "ShellAllowlistPrecheckResult", [
751
+ { id: 1, name: "allowlisted", type: "bool" },
752
+ ]);
753
+ addType(root, "McpAllowlistPrecheckResult", [
754
+ { id: 1, name: "allowlisted", type: "bool" },
755
+ ]);
756
+ addType(root, "WebFetchAllowlistPrecheckResult", [
757
+ { id: 1, name: "allowlisted", type: "bool" },
758
+ ]);
759
+ addType(root, "ForceBackgroundShellResult", [
760
+ { id: 1, name: "status", type: "uint32" },
761
+ ]);
762
+ addType(root, "ForceBackgroundSubagentResult", [
763
+ { id: 1, name: "status", type: "uint32" },
764
+ ]);
765
+ addType(root, "ConversationSearchHit", [
766
+ { id: 1, name: "conversation_id", type: "string" },
767
+ { id: 2, name: "title", type: "string" },
768
+ { id: 3, name: "source", type: "uint32" },
769
+ { id: 4, name: "updated_at_ms", type: "int64" },
770
+ { id: 5, name: "snippet", type: "string" },
771
+ ]);
772
+ addType(root, "ConversationSearchSuccess", [
773
+ { id: 1, name: "hits", type: "ConversationSearchHit", repeated: true },
774
+ { id: 2, name: "truncated", type: "bool" },
775
+ { id: 3, name: "partial", type: "bool" },
776
+ { id: 4, name: "rebuilding", type: "bool" },
777
+ ]);
778
+ addType(root, "ConversationSearchError", [
779
+ { id: 1, name: "error", type: "string" },
780
+ ]);
781
+ addType(root, "ConversationSearchResult", [
782
+ { id: 1, name: "success", type: "ConversationSearchSuccess" },
783
+ { id: 2, name: "error", type: "ConversationSearchError" },
784
+ ], [{ name: "result", fields: ["success", "error"] }]);
785
+ addType(root, "AgentStoreConflictError", [
786
+ { id: 1, name: "error", type: "string" },
787
+ ]);
788
+ addType(root, "AgentStoreConflictResult", [
789
+ { id: 2, name: "error", type: "AgentStoreConflictError" },
790
+ ], [{ name: "result", fields: ["error"] }]);
791
+ addType(root, "AdoptResult", [
792
+ { id: 1, name: "source_agent_id", type: "string" },
793
+ { id: 2, name: "target_agent_id", type: "string" },
794
+ { id: 3, name: "project_root_id", type: "string" },
795
+ { id: 5, name: "error", type: "string" },
796
+ ], [{ name: "result", fields: ["error"] }]);
797
+ // aiserver.v1.GetDiffRequest / GetDiffResponse (exec #44). Enums as uint32
798
+ // so protobufjs json decode does not stringify output_format / diff_type.
799
+ addType(root, "GitDiffChunk", [
800
+ { id: 1, name: "content", type: "string" },
801
+ { id: 2, name: "lines", type: "string", repeated: true },
802
+ { id: 3, name: "old_start", type: "int32" },
803
+ { id: 4, name: "old_lines", type: "int32" },
804
+ { id: 5, name: "new_start", type: "int32" },
805
+ { id: 6, name: "new_lines", type: "int32" },
806
+ ]);
807
+ addType(root, "GitFileDiff", [
808
+ { id: 1, name: "from", type: "string" },
809
+ { id: 2, name: "to", type: "string" },
810
+ { id: 3, name: "chunks", type: "GitDiffChunk", repeated: true },
811
+ { id: 4, name: "added", type: "int32" },
812
+ { id: 5, name: "removed", type: "int32" },
813
+ { id: 6, name: "before_file_contents", type: "string" },
814
+ { id: 7, name: "after_file_contents", type: "string" },
815
+ { id: 8, name: "is_generated", type: "bool" },
816
+ ]);
817
+ addType(root, "GitDiff", [
818
+ { id: 1, name: "diffs", type: "GitFileDiff", repeated: true },
819
+ { id: 2, name: "diff_type", type: "uint32" },
820
+ ]);
821
+ addType(root, "GitDiffSubmoduleDiff", [
822
+ { id: 1, name: "relative_path", type: "string" },
823
+ { id: 2, name: "diff", type: "GitDiff" },
824
+ { id: 3, name: "errored", type: "bool" },
825
+ ]);
826
+ addType(root, "GetDiffRequest", [
827
+ { id: 1, name: "cwd", type: "string" },
828
+ { id: 2, name: "ref", type: "string" },
829
+ { id: 3, name: "base_ref", type: "string" },
830
+ { id: 4, name: "merge_base", type: "bool" },
831
+ { id: 5, name: "target_paths", type: "string", repeated: true },
832
+ { id: 6, name: "unified_context_lines", type: "int32" },
833
+ { id: 7, name: "max_untracked_files", type: "int32" },
834
+ { id: 8, name: "output_format", type: "uint32" },
835
+ { id: 9, name: "submodule_recurse_depth", type: "int32" },
836
+ { id: 10, name: "include_space_changes", type: "bool" },
837
+ { id: 11, name: "committed_only", type: "bool" },
838
+ { id: 12, name: "compute_patch_id", type: "bool" },
839
+ { id: 13, name: "return_head_sha", type: "bool" },
840
+ { id: 14, name: "max_response_bytes", type: "int32" },
841
+ ]);
842
+ addType(root, "GetDiffResponse", [
843
+ { id: 1, name: "diff", type: "GitDiff" },
844
+ { id: 2, name: "submodule_diffs", type: "GitDiffSubmoduleDiff", repeated: true },
845
+ { id: 3, name: "patch_id", type: "string" },
846
+ { id: 4, name: "head_sha", type: "string" },
847
+ { id: 5, name: "has_uncommitted_changes", type: "bool" },
848
+ ]);
656
849
  // Cursor's non-blocking shell path is a separate exec variant from the
657
850
  // foreground ShellStream above. The host only needs the fields used at the
658
851
  // OpenCode boundary; protobufjs safely skips the richer classifier/approval
@@ -965,6 +1158,7 @@ export function createMessageTypes() {
965
1158
  { id: 1, name: "id", type: "uint32" },
966
1159
  { id: 15, name: "exec_id", type: "string" },
967
1160
  { id: 19, name: "span", type: "string" },
1161
+ { id: 2, name: "shell_args", type: "ShellArgs" },
968
1162
  { id: 3, name: "write_args", type: "WriteArgs" },
969
1163
  { id: 4, name: "delete_args", type: "DeleteArgs" },
970
1164
  { id: 5, name: "grep_args", type: "GrepArgs" },
@@ -978,6 +1172,7 @@ export function createMessageTypes() {
978
1172
  { id: 18, name: "read_mcp_resource_exec_args", type: "ReadMcpResourceExecArgs" },
979
1173
  { id: 28, name: "subagent_args", type: "SubagentArgs" },
980
1174
  { id: 36, name: "mcp_state_exec_args", type: "McpStateExecArgs" },
1175
+ { id: 44, name: "git_diff_request", type: "GetDiffRequest" },
981
1176
  { id: 45, name: "pi_read_args", type: "PiReadToolArgs" },
982
1177
  { id: 46, name: "pi_bash_args", type: "PiBashToolArgs" },
983
1178
  { id: 47, name: "pi_edit_args", type: "PiEditToolArgs" },
@@ -986,10 +1181,10 @@ export function createMessageTypes() {
986
1181
  { id: 50, name: "pi_find_args", type: "PiFindToolArgs" },
987
1182
  { id: 51, name: "pi_ls_args", type: "PiLsToolArgs" },
988
1183
  ], [{ name: "args", fields: [
989
- "write_args", "delete_args", "grep_args", "read_args", "ls_args",
1184
+ "shell_args", "write_args", "delete_args", "grep_args", "read_args", "ls_args",
990
1185
  "request_context_args", "mcp_args", "shell_stream_args", "background_shell_spawn_args",
991
1186
  "list_mcp_resources_exec_args", "read_mcp_resource_exec_args", "mcp_state_exec_args",
992
- "subagent_args",
1187
+ "subagent_args", "git_diff_request",
993
1188
  "pi_read_args", "pi_bash_args", "pi_edit_args", "pi_write_args",
994
1189
  "pi_grep_args", "pi_find_args", "pi_ls_args",
995
1190
  ] }]);
@@ -998,19 +1193,35 @@ export function createMessageTypes() {
998
1193
  { id: 1, name: "id", type: "uint32" },
999
1194
  { id: 15, name: "exec_id", type: "string" },
1000
1195
  { id: 39, name: "local_execution_time_ms", type: "uint64" },
1196
+ { id: 2, name: "shell_result", type: "ShellResult" },
1001
1197
  { id: 3, name: "write_result", type: "WriteResult" },
1002
1198
  { id: 4, name: "delete_result", type: "DeleteResult" },
1003
1199
  { id: 5, name: "grep_result", type: "GrepResult" },
1004
1200
  { id: 7, name: "read_result", type: "ReadResult" },
1005
1201
  { id: 8, name: "ls_result", type: "LsResult" },
1202
+ { id: 9, name: "diagnostics_result", type: "DiagnosticsResult" },
1006
1203
  { id: 10, name: "request_context_result", type: "RequestContextResult" },
1007
1204
  { id: 11, name: "mcp_result", type: "McpResult" },
1008
1205
  { id: 14, name: "shell_stream", type: "ShellStream" },
1009
1206
  { id: 16, name: "background_shell_spawn_result", type: "BackgroundShellSpawnResult" },
1010
1207
  { id: 17, name: "list_mcp_resources_exec_result", type: "ListMcpResourcesExecResult" },
1011
1208
  { id: 18, name: "read_mcp_resource_exec_result", type: "ReadMcpResourceExecResult" },
1209
+ { id: 20, name: "fetch_result", type: "FetchResult" },
1210
+ { id: 21, name: "record_screen_result", type: "RecordScreenResult" },
1211
+ { id: 22, name: "computer_use_result", type: "ComputerUseResult" },
1212
+ { id: 23, name: "write_shell_stdin_result", type: "WriteShellStdinResult" },
1012
1213
  { id: 28, name: "subagent_result", type: "SubagentResult" },
1214
+ { id: 29, name: "redacted_read_result", type: "ReadResult" },
1215
+ { id: 30, name: "force_background_shell_result", type: "ForceBackgroundShellResult" },
1216
+ { id: 31, name: "force_background_subagent_result", type: "ForceBackgroundSubagentResult" },
1013
1217
  { id: 36, name: "mcp_state_exec_result", type: "McpStateExecResult" },
1218
+ { id: 37, name: "subagent_await_result", type: "SubagentAwaitResult" },
1219
+ { id: 38, name: "smart_mode_classifier_result", type: "SmartModeClassifierResult" },
1220
+ { id: 40, name: "canvas_diagnostics_result", type: "CanvasDiagnosticsResult" },
1221
+ { id: 41, name: "shell_allowlist_precheck_result", type: "ShellAllowlistPrecheckResult" },
1222
+ { id: 42, name: "mcp_allowlist_precheck_result", type: "McpAllowlistPrecheckResult" },
1223
+ { id: 43, name: "web_fetch_allowlist_precheck_result", type: "WebFetchAllowlistPrecheckResult" },
1224
+ { id: 44, name: "git_diff_response", type: "GetDiffResponse" },
1014
1225
  { id: 46, name: "pi_read_result", type: "PiReadExecResult" },
1015
1226
  { id: 47, name: "pi_bash_result", type: "PiBashExecResult" },
1016
1227
  { id: 48, name: "pi_edit_result", type: "PiEditExecResult" },
@@ -1018,13 +1229,25 @@ export function createMessageTypes() {
1018
1229
  { id: 50, name: "pi_grep_result", type: "PiGrepExecResult" },
1019
1230
  { id: 51, name: "pi_find_result", type: "PiFindExecResult" },
1020
1231
  { id: 52, name: "pi_ls_result", type: "PiLsExecResult" },
1232
+ { id: 53, name: "conversation_search_result", type: "ConversationSearchResult" },
1233
+ { id: 54, name: "agent_store_conflict_result", type: "AgentStoreConflictResult" },
1234
+ { id: 55, name: "mini_swe_agent_bash_result", type: "ShellResult" },
1235
+ { id: 56, name: "adopt_result", type: "AdoptResult" },
1021
1236
  ], [{ name: "result", fields: [
1022
- "write_result", "delete_result", "grep_result", "read_result", "ls_result",
1023
- "request_context_result", "mcp_result", "shell_stream", "background_shell_spawn_result",
1024
- "list_mcp_resources_exec_result", "read_mcp_resource_exec_result", "mcp_state_exec_result",
1025
- "subagent_result",
1237
+ "shell_result", "write_result", "delete_result", "grep_result", "read_result", "ls_result",
1238
+ "diagnostics_result", "request_context_result", "mcp_result", "shell_stream", "background_shell_spawn_result",
1239
+ "list_mcp_resources_exec_result", "read_mcp_resource_exec_result",
1240
+ "fetch_result", "record_screen_result", "computer_use_result", "write_shell_stdin_result",
1241
+ "subagent_result", "redacted_read_result",
1242
+ "force_background_shell_result", "force_background_subagent_result",
1243
+ "mcp_state_exec_result",
1244
+ "subagent_await_result", "smart_mode_classifier_result", "canvas_diagnostics_result",
1245
+ "shell_allowlist_precheck_result", "mcp_allowlist_precheck_result", "web_fetch_allowlist_precheck_result",
1246
+ "git_diff_response",
1026
1247
  "pi_read_result", "pi_bash_result", "pi_edit_result", "pi_write_result",
1027
1248
  "pi_grep_result", "pi_find_result", "pi_ls_result",
1249
+ "conversation_search_result", "agent_store_conflict_result",
1250
+ "mini_swe_agent_bash_result", "adopt_result",
1028
1251
  ] }]);
1029
1252
  addType(root, "ExecServerControlMessage", [
1030
1253
  { id: 1, name: "abort", type: "ExecServerAbort" },