@sideboard-ai/core 0.1.88 → 0.1.92

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 (31) hide show
  1. package/dist/agents/cursor-runner.cjs +176 -15
  2. package/dist/agents/cursor-runner.js +11 -2
  3. package/dist/{agents-LMUFTGKF.js → agents-JXQ5QHDU.js} +4 -4
  4. package/dist/{agents-ODBP7J6E.js → agents-TUV4NH7S.js} +5 -5
  5. package/dist/{chunk-RJLBSYUO.js → chunk-35LKGGOC.js} +45 -77
  6. package/dist/{chunk-WANQFU3S.js → chunk-6XBXVXX2.js} +2 -2
  7. package/dist/{chunk-7D27DD2X.js → chunk-CIRXAYWS.js} +260 -61
  8. package/dist/{chunk-B2KIO2SD.js → chunk-CLGO7TLO.js} +2 -2
  9. package/dist/{chunk-JE75QW2I.js → chunk-GJ2HJQIU.js} +236 -96
  10. package/dist/{chunk-CBJSPTBG.js → chunk-GXSYI7FH.js} +206 -5
  11. package/dist/chunk-MMI4RJ5I.js +46 -0
  12. package/dist/{chunk-UHTNJKZX.js → chunk-NR6APJLD.js} +2 -2
  13. package/dist/{chunk-6EZRSCIT.js → chunk-QKYO6BHB.js} +2 -2
  14. package/dist/{chunk-ZXYWWSHZ.js → chunk-R7BQBSDT.js} +254 -61
  15. package/dist/{chunk-OB6IRIFV.js → chunk-XH2GS2LO.js} +2 -2
  16. package/dist/{chunk-VZ2L4AEJ.js → chunk-XUWDLRAE.js} +2 -2
  17. package/dist/{coordinator-prompt-UK5LYFN5.js → coordinator-prompt-AKEY4WSO.js} +2 -2
  18. package/dist/{coordinator-prompt-CI5SHONJ.js → coordinator-prompt-OQOOD5ET.js} +2 -2
  19. package/dist/{global-workspace-2YZ2V4I5.js → global-workspace-3GNPQCLE.js} +3 -3
  20. package/dist/{global-workspace-JQQLPJM5.js → global-workspace-M3OMVDDH.js} +3 -3
  21. package/dist/index.cjs +998 -463
  22. package/dist/index.d.cts +77 -19
  23. package/dist/index.d.ts +77 -19
  24. package/dist/index.js +181 -50
  25. package/dist/mcp/run-stdio.cjs +872 -436
  26. package/dist/mcp/run-stdio.js +132 -48
  27. package/dist/{workspaces-YWCC3WV4.js → workspaces-ERZC7ULY.js} +4 -4
  28. package/dist/{workspaces-FDO5L4NI.js → workspaces-J4WG6UFR.js} +4 -4
  29. package/dist/{worktree-7YNSJ224.js → worktree-DA4BOV7G.js} +7 -1
  30. package/dist/{worktree-4555QBQ7.js → worktree-EO5QAGJU.js} +7 -1
  31. package/package.json +1 -1
@@ -3,8 +3,8 @@
3
3
 
4
4
  // src/agents/cursor-runner.ts
5
5
  var import_sdk = require("@cursor/sdk");
6
- var import_node_fs5 = require("fs");
7
- var import_node_path6 = require("path");
6
+ var import_node_fs9 = require("fs");
7
+ var import_node_path10 = require("path");
8
8
  var import_node_readline2 = require("readline");
9
9
 
10
10
  // src/hook/nested-electron-env.ts
@@ -54,6 +54,120 @@ function appDataDir() {
54
54
  return base;
55
55
  }
56
56
 
57
+ // src/agents/cursor-ripgrep.ts
58
+ var import_node_fs8 = require("fs");
59
+ var import_node_module = require("module");
60
+ var import_node_path9 = require("path");
61
+ var import_node_url = require("url");
62
+
63
+ // src/agents/node-launch.ts
64
+ var import_node_fs6 = require("fs");
65
+ var import_node_os4 = require("os");
66
+ var import_node_path7 = require("path");
67
+
68
+ // src/git/run.ts
69
+ var import_execa2 = require("execa");
70
+
71
+ // src/agents/path.ts
72
+ var import_node_fs5 = require("fs");
73
+ var import_node_child_process = require("child_process");
74
+ var import_node_os3 = require("os");
75
+ var import_node_path6 = require("path");
76
+
77
+ // src/agents/node-launch.ts
78
+ function isAsarPath(filePath) {
79
+ if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
80
+ return /\.asar([/\\]|$)/.test(filePath);
81
+ }
82
+ function unpackedAsarPath(filePath) {
83
+ if (!isAsarPath(filePath)) return null;
84
+ const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
85
+ if (unpacked === filePath) return null;
86
+ return (0, import_node_fs6.existsSync)(unpacked) ? unpacked : null;
87
+ }
88
+ function nodeReadableScriptPath(scriptPath) {
89
+ return unpackedAsarPath(scriptPath) ?? scriptPath;
90
+ }
91
+
92
+ // src/agents/packaged-runtime.ts
93
+ var import_node_fs7 = require("fs");
94
+ var import_node_path8 = require("path");
95
+ function electronResourcesPath() {
96
+ const resources = process.resourcesPath;
97
+ if (typeof resources !== "string" || !resources) return null;
98
+ return resources;
99
+ }
100
+ function packagedCursorRuntimeDir() {
101
+ const resources = electronResourcesPath();
102
+ if (!resources) return null;
103
+ const dir = (0, import_node_path8.join)(resources, "cursor-runtime");
104
+ if (!(0, import_node_fs7.existsSync)((0, import_node_path8.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
105
+ return dir;
106
+ }
107
+ function packagedCursorRipgrepCandidate(platformPkg, binName) {
108
+ const dir = packagedCursorRuntimeDir();
109
+ if (!dir) return null;
110
+ return (0, import_node_path8.join)(dir, "node_modules", platformPkg, "bin", binName);
111
+ }
112
+
113
+ // src/agents/cursor-ripgrep.ts
114
+ var import_meta = {};
115
+ var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
116
+ function rgBinaryName() {
117
+ return process.platform === "win32" ? "rg.exe" : "rg";
118
+ }
119
+ function platformRipgrepPackage() {
120
+ return `@cursor/sdk-${process.platform}-${process.arch}`;
121
+ }
122
+ function usableRipgrepPath(candidate) {
123
+ const raw = candidate?.trim();
124
+ if (!raw || !(0, import_node_path9.isAbsolute)(raw)) return null;
125
+ const readable = nodeReadableScriptPath(raw);
126
+ if (!(0, import_node_fs8.existsSync)(readable) || isAsarPath(readable)) return null;
127
+ return readable;
128
+ }
129
+ function walkForBundledRipgrep(startFile) {
130
+ if (!startFile) return null;
131
+ const pkg = platformRipgrepPackage();
132
+ const name = rgBinaryName();
133
+ let dir = (0, import_node_path9.dirname)((0, import_node_path9.resolve)(startFile));
134
+ const root = (0, import_node_path9.parse)(dir).root;
135
+ while (dir !== root) {
136
+ const hit = usableRipgrepPath((0, import_node_path9.join)(dir, "node_modules", pkg, "bin", name));
137
+ if (hit) return hit;
138
+ const next = (0, import_node_path9.dirname)(dir);
139
+ if (next === dir) break;
140
+ dir = next;
141
+ }
142
+ return null;
143
+ }
144
+ function requireResolveBundledRipgrep(fromFile) {
145
+ try {
146
+ const req = (0, import_node_module.createRequire)(fromFile);
147
+ const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
148
+ return usableRipgrepPath((0, import_node_path9.join)((0, import_node_path9.dirname)(pkgJson), "bin", rgBinaryName()));
149
+ } catch {
150
+ return null;
151
+ }
152
+ }
153
+ function resolveCursorRipgrepPath(opts) {
154
+ const env = opts?.env ?? process.env;
155
+ const fromEnv = usableRipgrepPath(env[RIPGREP_ENV]);
156
+ if (fromEnv) return fromEnv;
157
+ const fromPackaged = usableRipgrepPath(
158
+ packagedCursorRipgrepCandidate(platformRipgrepPackage(), rgBinaryName())
159
+ );
160
+ if (fromPackaged) return fromPackaged;
161
+ const start = opts?.startFile?.trim() || process.argv[1] || (0, import_node_url.fileURLToPath)(import_meta.url);
162
+ return walkForBundledRipgrep(start) ?? requireResolveBundledRipgrep(start);
163
+ }
164
+ function ensureCursorRipgrepPath(opts) {
165
+ const target = opts?.env ?? process.env;
166
+ const path = resolveCursorRipgrepPath({ env: target, startFile: opts?.startFile });
167
+ if (path) target[RIPGREP_ENV] = path;
168
+ return path;
169
+ }
170
+
57
171
  // src/agents/cursor-session.ts
58
172
  function cursorErrorMessage(err) {
59
173
  if (err instanceof Error) return err.message.trim();
@@ -286,8 +400,52 @@ function cursorSdkMessageToEvents(msg) {
286
400
  return [];
287
401
  }
288
402
 
403
+ // src/agents/cursor-stream-coalesce.ts
404
+ function isTextEvent(event) {
405
+ return event.type === "stdout" || event.type === "thinking";
406
+ }
407
+ function createAgentStreamCoalescer(emit2, opts) {
408
+ const intervalMs = opts?.intervalMs ?? 32;
409
+ let pending = null;
410
+ let timer = null;
411
+ const flush = () => {
412
+ if (timer) {
413
+ clearTimeout(timer);
414
+ timer = null;
415
+ }
416
+ if (!pending) return;
417
+ const event = pending;
418
+ pending = null;
419
+ emit2({ type: event.type, data: event.data });
420
+ };
421
+ const schedule = () => {
422
+ if (timer) return;
423
+ timer = setTimeout(flush, intervalMs);
424
+ timer.unref?.();
425
+ };
426
+ return {
427
+ push(event) {
428
+ if (!isTextEvent(event)) {
429
+ flush();
430
+ emit2(event);
431
+ return;
432
+ }
433
+ if (!event.data) return;
434
+ if (pending && pending.type === event.type) {
435
+ pending.data += event.data;
436
+ } else {
437
+ flush();
438
+ pending = { type: event.type, data: event.data };
439
+ }
440
+ schedule();
441
+ },
442
+ flush
443
+ };
444
+ }
445
+
289
446
  // src/agents/cursor-runner.ts
290
447
  dropNestedElectronEnvFromProcess();
448
+ ensureCursorRipgrepPath();
291
449
  function emit(event) {
292
450
  process.stdout.write(`${JSON.stringify(event)}
293
451
  `);
@@ -307,8 +465,8 @@ function modelSelection(model, opts) {
307
465
  return params.length > 0 ? { id, params } : { id };
308
466
  }
309
467
  function localAgentStore() {
310
- const root = (0, import_node_path6.join)(appDataDir(), "cursor-sdk-store");
311
- (0, import_node_fs5.mkdirSync)(root, { recursive: true });
468
+ const root = (0, import_node_path10.join)(appDataDir(), "cursor-sdk-store");
469
+ (0, import_node_fs9.mkdirSync)(root, { recursive: true });
312
470
  return new import_sdk.JsonlLocalAgentStore(root);
313
471
  }
314
472
  async function cancelStaleLocalRuns(agentId, opts) {
@@ -319,10 +477,10 @@ async function cancelStaleLocalRuns(agentId, opts) {
319
477
  limit: 20
320
478
  });
321
479
  let cancelled = 0;
322
- for (const run of listed.items) {
323
- if (run.status !== "running") continue;
480
+ for (const run2 of listed.items) {
481
+ if (run2.status !== "running") continue;
324
482
  try {
325
- await import_sdk.Agent.cancelRun(run.id, {
483
+ await import_sdk.Agent.cancelRun(run2.id, {
326
484
  runtime: "local",
327
485
  cwd: opts.cwd,
328
486
  store: opts.store
@@ -418,11 +576,11 @@ async function main() {
418
576
  let liveRun = null;
419
577
  let shuttingDown = false;
420
578
  const cancelLiveRun = async () => {
421
- const run = liveRun;
579
+ const run2 = liveRun;
422
580
  liveRun = null;
423
- if (!run) return;
581
+ if (!run2) return;
424
582
  try {
425
- await run.cancel();
583
+ await run2.cancel();
426
584
  } catch {
427
585
  }
428
586
  };
@@ -440,15 +598,17 @@ async function main() {
440
598
  process.once("SIGINT", onSignal);
441
599
  async function runTurn(agent) {
442
600
  emit({ type: "session_id", data: agent.agentId });
443
- const run = await sendPrompt(agent);
444
- liveRun = run;
601
+ const run2 = await sendPrompt(agent);
602
+ liveRun = run2;
603
+ const stream = createAgentStreamCoalescer(emit);
445
604
  try {
446
- for await (const msg of run.stream()) {
605
+ for await (const msg of run2.stream()) {
447
606
  for (const event of cursorSdkMessageToEvents(msg)) {
448
- emit(event);
607
+ stream.push(event);
449
608
  }
450
609
  }
451
- const result = await run.wait();
610
+ stream.flush();
611
+ const result = await run2.wait();
452
612
  if (result.status === "error") {
453
613
  const detail = formatUnknownDetail(result.error);
454
614
  emit({
@@ -460,6 +620,7 @@ async function main() {
460
620
  if (result.status === "cancelled") return 0;
461
621
  return 0;
462
622
  } finally {
623
+ stream.flush();
463
624
  liveRun = null;
464
625
  }
465
626
  }
@@ -1,14 +1,19 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ createAgentStreamCoalescer
4
+ } from "../chunk-MMI4RJ5I.js";
2
5
  import {
3
6
  cursorSdkMessageToEvents,
7
+ ensureCursorRipgrepPath,
4
8
  formatUnknownDetail
5
- } from "../chunk-CBJSPTBG.js";
9
+ } from "../chunk-GXSYI7FH.js";
6
10
  import {
7
11
  dropNestedElectronEnvFromProcess
8
12
  } from "../chunk-TLPJHLLM.js";
9
13
  import {
10
14
  appDataDir
11
15
  } from "../chunk-B4R2VB2A.js";
16
+ import "../chunk-LGXBYZZA.js";
12
17
 
13
18
  // src/agents/cursor-runner.ts
14
19
  import { Agent, CursorAgentError, JsonlLocalAgentStore } from "@cursor/sdk";
@@ -54,6 +59,7 @@ function withCursorLocalHangGuards(local) {
54
59
 
55
60
  // src/agents/cursor-runner.ts
56
61
  dropNestedElectronEnvFromProcess();
62
+ ensureCursorRipgrepPath();
57
63
  function emit(event) {
58
64
  process.stdout.write(`${JSON.stringify(event)}
59
65
  `);
@@ -208,12 +214,14 @@ async function main() {
208
214
  emit({ type: "session_id", data: agent.agentId });
209
215
  const run = await sendPrompt(agent);
210
216
  liveRun = run;
217
+ const stream = createAgentStreamCoalescer(emit);
211
218
  try {
212
219
  for await (const msg of run.stream()) {
213
220
  for (const event of cursorSdkMessageToEvents(msg)) {
214
- emit(event);
221
+ stream.push(event);
215
222
  }
216
223
  }
224
+ stream.flush();
217
225
  const result = await run.wait();
218
226
  if (result.status === "error") {
219
227
  const detail = formatUnknownDetail(result.error);
@@ -226,6 +234,7 @@ async function main() {
226
234
  if (result.status === "cancelled") return 0;
227
235
  return 0;
228
236
  } finally {
237
+ stream.flush();
229
238
  liveRun = null;
230
239
  }
231
240
  }
@@ -32,16 +32,16 @@ import {
32
32
  resolveCursorModelId,
33
33
  resolveLoginCommand,
34
34
  resolveQuotaFallbackAgent
35
- } from "./chunk-JE75QW2I.js";
35
+ } from "./chunk-GJ2HJQIU.js";
36
36
  import "./chunk-DKHGWYWR.js";
37
37
  import {
38
38
  ORCHESTRATOR_AGENT_KINDS,
39
39
  assertOrchestratorCapableAgent,
40
40
  coerceOrchestratorAgent,
41
41
  isOrchestratorCapableAgent
42
- } from "./chunk-UHTNJKZX.js";
43
- import "./chunk-OB6IRIFV.js";
44
- import "./chunk-ZXYWWSHZ.js";
42
+ } from "./chunk-NR6APJLD.js";
43
+ import "./chunk-XH2GS2LO.js";
44
+ import "./chunk-R7BQBSDT.js";
45
45
  import "./chunk-B3SJXYIJ.js";
46
46
  import "./chunk-JOF3XIEM.js";
47
47
  import "./chunk-6LFV4VFI.js";
@@ -28,20 +28,20 @@ import {
28
28
  resolveCursorModelId,
29
29
  resolveLoginCommand,
30
30
  resolveQuotaFallbackAgent
31
- } from "./chunk-RJLBSYUO.js";
31
+ } from "./chunk-35LKGGOC.js";
32
32
  import {
33
33
  ORCHESTRATOR_AGENT_KINDS,
34
34
  assertOrchestratorCapableAgent,
35
35
  coerceOrchestratorAgent,
36
36
  isOrchestratorCapableAgent
37
- } from "./chunk-B2KIO2SD.js";
38
- import "./chunk-VZ2L4AEJ.js";
37
+ } from "./chunk-CLGO7TLO.js";
38
+ import "./chunk-XUWDLRAE.js";
39
39
  import "./chunk-QSLE4VEM.js";
40
40
  import {
41
41
  cursorSdkMessageToEvents,
42
42
  parseCursorRunnerLine
43
- } from "./chunk-CBJSPTBG.js";
44
- import "./chunk-7D27DD2X.js";
43
+ } from "./chunk-GXSYI7FH.js";
44
+ import "./chunk-CIRXAYWS.js";
45
45
  import "./chunk-FKOIHGKV.js";
46
46
  import "./chunk-FT2SQOL4.js";
47
47
  import "./chunk-TLPJHLLM.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isOrchestratorThread
3
- } from "./chunk-B2KIO2SD.js";
3
+ } from "./chunk-CLGO7TLO.js";
4
4
  import {
5
5
  applyConnectedTeamToCli,
6
6
  brightsyMcpServerName,
@@ -9,15 +9,23 @@ import {
9
9
  loadBrightsyConfig
10
10
  } from "./chunk-QSLE4VEM.js";
11
11
  import {
12
+ applyNodeLaunch,
13
+ cursorRipgrepEnv,
12
14
  extractJsonErrorMessage,
13
15
  formatUnknownDetail,
16
+ isAsarPath,
14
17
  looksLikeAgentFailureMessage,
15
- parseCursorRunnerLine
16
- } from "./chunk-CBJSPTBG.js";
18
+ packagedCursorRunnerPath,
19
+ packagedMcpStdioPath,
20
+ parseCursorRunnerLine,
21
+ resolveNodeLaunch
22
+ } from "./chunk-GXSYI7FH.js";
17
23
  import {
18
24
  codexUnattendedGitConfigArgs,
19
- resolveAgentGitAuthEnv
20
- } from "./chunk-7D27DD2X.js";
25
+ mergeAgentGitAuthEnv,
26
+ resolveAgentGitAuthEnv,
27
+ resolveCodexGitWritableRoots
28
+ } from "./chunk-CIRXAYWS.js";
21
29
  import {
22
30
  claudeChromeEnabled,
23
31
  loadAppSettings,
@@ -26,8 +34,7 @@ import {
26
34
  } from "./chunk-FT2SQOL4.js";
27
35
  import {
28
36
  isElectronLikeCommand,
29
- unwrapStrippedElectronLaunch,
30
- wrapElectronAsNodeLaunch
37
+ unwrapStrippedElectronLaunch
31
38
  } from "./chunk-TLPJHLLM.js";
32
39
  import {
33
40
  appDataDir
@@ -521,7 +528,7 @@ function mcpAuthWarnings(servers) {
521
528
  }
522
529
 
523
530
  // src/agents/injected-mcp.ts
524
- import { existsSync as existsSync2, mkdirSync, mkdtempSync, writeFileSync } from "fs";
531
+ import { existsSync as existsSync2, mkdtempSync, writeFileSync } from "fs";
525
532
  import { createRequire } from "module";
526
533
  import { tmpdir } from "os";
527
534
  import { dirname, join } from "path";
@@ -533,40 +540,6 @@ function sideboardMcpProfile(env = process.env) {
533
540
  return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
534
541
  }
535
542
 
536
- // src/agents/node-launch.ts
537
- function isAsarPath(filePath) {
538
- return /\.asar([/\\]|$)/.test(filePath);
539
- }
540
- function applyNodeLaunch(launch, args) {
541
- if (!launch.env.ELECTRON_RUN_AS_NODE) {
542
- return { file: launch.file, args, env: launch.env };
543
- }
544
- const wrapped = wrapElectronAsNodeLaunch(launch.file, args);
545
- if (process.platform === "win32") {
546
- return { file: wrapped.file, args: wrapped.args, env: launch.env };
547
- }
548
- const env = { ...launch.env };
549
- delete env.ELECTRON_RUN_AS_NODE;
550
- return { file: wrapped.file, args: wrapped.args, env };
551
- }
552
- async function resolveNodeLaunch(scriptPath) {
553
- if (isAsarPath(scriptPath)) {
554
- return {
555
- file: process.execPath,
556
- env: { ELECTRON_RUN_AS_NODE: "1" }
557
- };
558
- }
559
- const whichNode = await run("which", ["node"], { reject: false });
560
- const nodeBin = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : null;
561
- if (nodeBin) {
562
- return { file: nodeBin, env: {} };
563
- }
564
- return {
565
- file: process.execPath,
566
- env: { ELECTRON_RUN_AS_NODE: "1" }
567
- };
568
- }
569
-
570
543
  // src/agents/injected-mcp.ts
571
544
  var SIDEBOARD_MCP_ALLOWED_TOOLS = [
572
545
  "mcp__sideboard",
@@ -688,6 +661,8 @@ function corePackageDir() {
688
661
  function findSideboardMcpJsEntry() {
689
662
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
690
663
  if (override && existsSync2(override)) return override;
664
+ const packaged = packagedMcpStdioPath();
665
+ if (packaged) return packaged;
691
666
  let dir = corePackageDir();
692
667
  for (let i = 0; i < 10; i++) {
693
668
  const candidates = [
@@ -700,7 +675,7 @@ function findSideboardMcpJsEntry() {
700
675
  join(dir, "cli/dist/index.js")
701
676
  ];
702
677
  for (const p of candidates) {
703
- if (existsSync2(p)) return p;
678
+ if (existsSync2(p) && !isAsarPath(p)) return p;
704
679
  }
705
680
  const parent = dirname(dir);
706
681
  if (parent === dir) break;
@@ -714,12 +689,14 @@ async function resolveSideboardMcpServer() {
714
689
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
715
690
  const scriptArgs = isCli ? [entry, "mcp"] : [entry];
716
691
  const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
717
- return {
718
- name: "sideboard",
719
- command: launch.file,
720
- args: launch.args,
721
- ...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
722
- };
692
+ if (launch.file !== "/bin/sh" && !isElectronLikeCommand(launch.file)) {
693
+ return {
694
+ name: "sideboard",
695
+ command: launch.file,
696
+ args: launch.args,
697
+ ...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
698
+ };
699
+ }
723
700
  }
724
701
  const which = await run("which", ["sideboard"], { reject: false });
725
702
  if (which.exitCode === 0 && which.stdout.trim()) {
@@ -742,7 +719,10 @@ async function buildInjectedMcpServers(opts) {
742
719
  sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
743
720
  }
744
721
  try {
745
- Object.assign(sideboard.env, await resolveAgentGitAuthEnv(sideboard.env));
722
+ mergeAgentGitAuthEnv(
723
+ sideboard.env,
724
+ await resolveAgentGitAuthEnv(sideboard.env)
725
+ );
746
726
  } catch {
747
727
  }
748
728
  servers.push(sideboard);
@@ -764,9 +744,6 @@ async function buildInjectedMcpServers(opts) {
764
744
  }
765
745
  return servers;
766
746
  }
767
- function shSingleQuote(value) {
768
- return `'${value.replace(/'/g, `'\\''`)}'`;
769
- }
770
747
  function cursorSafeMcpLaunch(command, args) {
771
748
  if (process.platform === "win32") {
772
749
  return args && args.length > 0 ? { command, args } : { command };
@@ -774,31 +751,13 @@ function cursorSafeMcpLaunch(command, args) {
774
751
  const unwrapped = unwrapStrippedElectronLaunch(command, args);
775
752
  const file = unwrapped?.file ?? command;
776
753
  const fileArgs = unwrapped?.args ?? args ?? [];
777
- if (!isElectronLikeCommand(file)) {
778
- return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
779
- }
780
- const dir = join(appDataDir(), "mcp-launch");
781
- mkdirSync(dir, { recursive: true });
782
- const wrap = join(dir, "cursor-electron-as-node.sh");
783
- const execLine = [file, ...fileArgs].map(shSingleQuote).join(" ");
784
- writeFileSync(
785
- wrap,
786
- [
787
- "#!/bin/sh",
788
- "vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
789
- '[ -n "$vars" ] && unset $vars',
790
- "export ELECTRON_RUN_AS_NODE=1",
791
- `exec ${execLine} "$@"`,
792
- ""
793
- ].join("\n"),
794
- { mode: 493 }
795
- );
796
- return { command: wrap };
754
+ return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
797
755
  }
798
756
  function mcpSpawnEnv(env) {
799
757
  if (!env) return void 0;
800
758
  const out = { ...env };
801
759
  delete out.ELECTRON_RUN_AS_NODE;
760
+ delete out.ELECTRON_RUN_AS_NODE;
802
761
  return Object.keys(out).length > 0 ? out : void 0;
803
762
  }
804
763
  function toCursorMcpServers(servers) {
@@ -868,7 +827,7 @@ async function writeInjectedMcpConfig(opts) {
868
827
  }
869
828
 
870
829
  // src/agents/types.ts
871
- var PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope): (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
830
+ var PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope) \u2014 not greetings, check-ins, or an invented task menu: (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. If one option is the obvious default, proceed without asking. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
872
831
  function permissionMode(thread) {
873
832
  if (thread.sourceType === "orchestration") {
874
833
  return {
@@ -1059,7 +1018,7 @@ var claudeAdapter = {
1059
1018
  );
1060
1019
  }
1061
1020
  const mode = permissionMode(thread);
1062
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-JQQLPJM5.js");
1021
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-M3OMVDDH.js");
1063
1022
  const isOrchestrator = isOrchestratorThread2(thread);
1064
1023
  const injectedServers = await buildInjectedMcpServers({
1065
1024
  includeSideboard: true,
@@ -1441,8 +1400,13 @@ var codexAdapter = {
1441
1400
  // `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
1442
1401
  "-c",
1443
1402
  'approval_policy="never"',
1444
- // Seatbelt cannot use the login Keychain; default policy also strips GH_TOKEN.
1445
- ...codexUnattendedGitConfigArgs(mode.codexSandbox),
1403
+ // Seatbelt cannot use the login Keychain; inherit GH_CONFIG_DIR / GIT_CONFIG_*.
1404
+ // Default policy also strips *TOKEN*. Linked worktrees need the main
1405
+ // repo `.git` (+ `.git/worktrees/<name>`) as writable_roots so git commit
1406
+ // can create index.lock.
1407
+ ...codexUnattendedGitConfigArgs(mode.codexSandbox, {
1408
+ writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
1409
+ }),
1446
1410
  ...model ? ["--model", model] : [],
1447
1411
  ...mcpOverrides
1448
1412
  ];
@@ -1648,6 +1612,8 @@ function entryDir() {
1648
1612
  }
1649
1613
  }
1650
1614
  function cursorRunnerPath() {
1615
+ const packaged = packagedCursorRunnerPath();
1616
+ if (packaged) return packaged;
1651
1617
  const root = entryDir();
1652
1618
  const candidates = [
1653
1619
  join3(root, "agents", "cursor-runner.js"),
@@ -1723,6 +1689,7 @@ var cursorAdapter = {
1723
1689
  stdin: JSON.stringify(req),
1724
1690
  env: {
1725
1691
  ...launch.env,
1692
+ ...cursorRipgrepEnv({ startFile: runner }),
1726
1693
  ...apiKey ? { CURSOR_API_KEY: apiKey } : {}
1727
1694
  }
1728
1695
  };
@@ -2483,6 +2450,7 @@ export {
2483
2450
  threadRequestsBrightsyMcp,
2484
2451
  shouldInjectBrightsyMcp,
2485
2452
  brightsyMcpAllowedTools,
2453
+ resolveSideboardMcpServer,
2486
2454
  writeInjectedMcpConfig,
2487
2455
  PLAN_MODE_INSTRUCTION,
2488
2456
  permissionMode,
@@ -2,11 +2,11 @@
2
2
 
3
3
  import {
4
4
  isGlobalRepoPath
5
- } from "./chunk-UHTNJKZX.js";
5
+ } from "./chunk-NR6APJLD.js";
6
6
  import {
7
7
  ensureGhPreferOrigin,
8
8
  resolveRepoRoot
9
- } from "./chunk-ZXYWWSHZ.js";
9
+ } from "./chunk-R7BQBSDT.js";
10
10
  import {
11
11
  appDataDir
12
12
  } from "./chunk-JL4SJ6V7.js";