@sideboard-ai/core 0.1.109 → 0.1.111

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 (43) hide show
  1. package/dist/agents/cursor-runner.cjs +90 -15
  2. package/dist/agents/cursor-runner.js +37 -11
  3. package/dist/{agents-XB332VUJ.js → agents-GH3FWDW2.js} +6 -6
  4. package/dist/{agents-YIMHDI46.js → agents-NN22A4G5.js} +7 -7
  5. package/dist/{app-settings-EBCVMFF6.js → app-settings-5XAGNDX7.js} +3 -1
  6. package/dist/{app-settings-IYSSVZHH.js → app-settings-J4LUWIRN.js} +3 -1
  7. package/dist/{chunk-WD2TARQS.js → chunk-363Z34PY.js} +72 -12
  8. package/dist/{chunk-756EO4GK.js → chunk-4EWPKYOU.js} +4 -4
  9. package/dist/{chunk-4LKD3PGO.js → chunk-4NR5FL46.js} +10 -0
  10. package/dist/{chunk-FBV6NK62.js → chunk-7KWYXGIU.js} +2 -2
  11. package/dist/{chunk-KGSVLZV6.js → chunk-A4VZXJEJ.js} +2 -0
  12. package/dist/{chunk-VRTKGKUW.js → chunk-AROMOP3C.js} +2 -2
  13. package/dist/{chunk-EW7COXYE.js → chunk-C4KHDW3U.js} +2 -2
  14. package/dist/{chunk-Q6B3NRCT.js → chunk-DMJKOFTO.js} +159 -288
  15. package/dist/{chunk-LTPX5N6K.js → chunk-JTQQPJAU.js} +167 -277
  16. package/dist/{chunk-I2OJ2YSP.js → chunk-KQBI5HNT.js} +2 -2
  17. package/dist/{chunk-AY2EQI2P.js → chunk-KVFNTWFG.js} +506 -60
  18. package/dist/{chunk-P3BQ5DOL.js → chunk-KYOTBZ6S.js} +2 -0
  19. package/dist/{chunk-KKHDPV45.js → chunk-NC3U42ZP.js} +473 -37
  20. package/dist/{chunk-NE4TOOKS.js → chunk-SGEVS5SY.js} +10 -0
  21. package/dist/{chunk-TROJ3PVH.js → chunk-VOD3HFLP.js} +4 -4
  22. package/dist/{chunk-MMI4RJ5I.js → chunk-WIHKHR5R.js} +14 -3
  23. package/dist/{chunk-OQDIYVDD.js → chunk-YFAXVUY2.js} +2 -2
  24. package/dist/{chunk-JVIW55KT.js → chunk-YXDR43ZC.js} +2 -2
  25. package/dist/{coordinator-prompt-JKOU6BWV.js → coordinator-prompt-AR66L3N4.js} +4 -4
  26. package/dist/{coordinator-prompt-V66BYTUV.js → coordinator-prompt-BHMLWL64.js} +4 -4
  27. package/dist/{global-workspace-WBQWQQQY.js → global-workspace-SKFODUQQ.js} +5 -5
  28. package/dist/{global-workspace-NCTBE7G7.js → global-workspace-XSUFEIAQ.js} +5 -5
  29. package/dist/index.cjs +880 -512
  30. package/dist/index.d.cts +51 -3
  31. package/dist/index.d.ts +51 -3
  32. package/dist/index.js +44 -23
  33. package/dist/mcp/run-stdio.cjs +858 -511
  34. package/dist/mcp/run-stdio.js +17 -12
  35. package/dist/{orchestrator-JVGVPKLI.js → orchestrator-4T2SXDZ7.js} +8 -8
  36. package/dist/{orchestrator-6W7EKSPO.js → orchestrator-EP57AB5W.js} +10 -10
  37. package/dist/{thread-store-DQJGDKIJ.js → thread-store-LPTBVW5C.js} +1 -1
  38. package/dist/{thread-store-4OUEQ2DB.js → thread-store-OEALWU7Y.js} +1 -1
  39. package/dist/{workspaces-SUBEDSGB.js → workspaces-HV3J4TTW.js} +6 -6
  40. package/dist/{workspaces-I3554R3F.js → workspaces-XAQVKTLO.js} +6 -6
  41. package/dist/{worktree-7H6HB6GW.js → worktree-N2EV24EE.js} +3 -3
  42. package/dist/{worktree-2UWO7VEK.js → worktree-XFJED3VU.js} +3 -3
  43. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -820,6 +820,7 @@ __export(app_settings_exports, {
820
820
  childEnvWithAppSettings: () => childEnvWithAppSettings,
821
821
  claudeChromeEnabled: () => claudeChromeEnabled,
822
822
  claudeUserSettingsPath: () => claudeUserSettingsPath,
823
+ cowboyModeEnabled: () => cowboyModeEnabled,
823
824
  deleteBranchOnPurgeEnabled: () => deleteBranchOnPurgeEnabled,
824
825
  disconnectLinearConnection: () => disconnectLinearConnection,
825
826
  ensureSlackDeviceIdentity: () => ensureSlackDeviceIdentity,
@@ -1058,6 +1059,9 @@ function normalizeAdvanced(raw) {
1058
1059
  if (typeof source.deleteBranchOnPurge === "boolean") {
1059
1060
  out.deleteBranchOnPurge = source.deleteBranchOnPurge;
1060
1061
  }
1062
+ if (typeof source.cowboyMode === "boolean") {
1063
+ out.cowboyMode = source.cowboyMode;
1064
+ }
1061
1065
  if (typeof source.autoArchiveOnMerge === "boolean") {
1062
1066
  out.autoArchiveOnMerge = source.autoArchiveOnMerge;
1063
1067
  }
@@ -1582,6 +1586,9 @@ function updateAdvancedSettings(patch) {
1582
1586
  if (typeof patch.deleteBranchOnPurge === "boolean") {
1583
1587
  advanced.deleteBranchOnPurge = patch.deleteBranchOnPurge;
1584
1588
  }
1589
+ if (typeof patch.cowboyMode === "boolean") {
1590
+ advanced.cowboyMode = patch.cowboyMode;
1591
+ }
1585
1592
  if (typeof patch.autoArchiveOnMerge === "boolean") {
1586
1593
  advanced.autoArchiveOnMerge = patch.autoArchiveOnMerge;
1587
1594
  }
@@ -1632,6 +1639,9 @@ function caffeinateWhileCloudConnectEnabled(settings = loadAppSettings()) {
1632
1639
  function deleteBranchOnPurgeEnabled(settings = loadAppSettings()) {
1633
1640
  return Boolean(settings.advanced.deleteBranchOnPurge);
1634
1641
  }
1642
+ function cowboyModeEnabled(settings = loadAppSettings()) {
1643
+ return Boolean(settings.advanced.cowboyMode);
1644
+ }
1635
1645
  function autoArchiveOnMergeEnabled(settings = loadAppSettings()) {
1636
1646
  return Boolean(settings.advanced.autoArchiveOnMerge);
1637
1647
  }
@@ -1977,6 +1987,7 @@ function normalizeThread(raw) {
1977
1987
  prTitle: raw.prTitle ?? null,
1978
1988
  prState: raw.prState ?? null,
1979
1989
  skipAutoArchiveOnMerge: Boolean(raw.skipAutoArchiveOnMerge),
1990
+ cowboy: Boolean(raw.cowboy),
1980
1991
  stackId: raw.stackId ?? null,
1981
1992
  stackLayer: raw.stackLayer ?? null,
1982
1993
  userSetTitle: Boolean(raw.userSetTitle),
@@ -2005,6 +2016,7 @@ function createEmptyThread(partial) {
2005
2016
  prTitle: partial.prTitle ?? null,
2006
2017
  prState: partial.prState ?? null,
2007
2018
  skipAutoArchiveOnMerge: partial.skipAutoArchiveOnMerge ?? false,
2019
+ cowboy: Boolean(partial.cowboy),
2008
2020
  stackId: partial.stackId ?? null,
2009
2021
  stackLayer: partial.stackLayer ?? null,
2010
2022
  userSetTitle: partial.userSetTitle ?? false,
@@ -6535,7 +6547,7 @@ function extractJsonErrorMessage(obj) {
6535
6547
  }
6536
6548
  function isPinnedStderrLine(line) {
6537
6549
  if (/^\s*at\s/.test(line)) return false;
6538
- return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:/i.test(
6550
+ return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:|FATAL ERROR|heap out of memory|javascript heap|OOMErrorHandler|FatalProcessOutOfMemory/i.test(
6539
6551
  line
6540
6552
  );
6541
6553
  }
@@ -6558,12 +6570,17 @@ function looksLikeMinifiedJsDump(line) {
6558
6570
  function looksLikeNestedElectronCrash(line) {
6559
6571
  return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
6560
6572
  }
6561
- function looksLikeHomebrewLibuvCrash(line) {
6562
- const uvRun = /uv_run/i.test(line);
6563
- const spin = /SpinEventLoopInternal/i.test(line);
6564
- const homebrewUv = /Cellar\/libuv|libuv\.\d\.dylib/i.test(line);
6565
- const homebrewNode = /Cellar\/node\//i.test(line);
6566
- return uvRun && (homebrewUv || spin || homebrewNode) || spin && (homebrewUv || homebrewNode);
6573
+ function looksLikeNativeEventLoopCrash(text4) {
6574
+ return /uv_run|uv__io_poll|SpinEventLoopInternal/i.test(text4);
6575
+ }
6576
+ function looksLikeV8Oom(text4) {
6577
+ return /javascript heap|reached heap limit|OOMErrorHandler|FatalProcessOutOfMemory|Allocation failed - JavaScript heap/i.test(
6578
+ text4
6579
+ );
6580
+ }
6581
+ function looksLikeHomebrewLibuvCrash(text4) {
6582
+ if (!looksLikeNativeEventLoopCrash(text4)) return false;
6583
+ return /Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(text4);
6567
6584
  }
6568
6585
  function clipStderr(text4, maxChars) {
6569
6586
  const trimmed = text4.trim();
@@ -6577,7 +6594,12 @@ function summarizeTurnStderr(tail, maxChars = 500) {
6577
6594
  const cursorRunFailed = [...tail].reverse().find((line) => /^cursor run failed\b/i.test(line.trim()));
6578
6595
  if (cursorRunFailed) return clipStderr(cursorRunFailed, maxChars);
6579
6596
  if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
6580
- if (tail.some(looksLikeHomebrewLibuvCrash)) return HOMEBREW_LIBUV_SUMMARY;
6597
+ const blob = tail.join("\n");
6598
+ if (looksLikeV8Oom(blob)) return V8_OOM_SUMMARY;
6599
+ if (looksLikeHomebrewLibuvCrash(blob)) return HOMEBREW_LIBUV_SUMMARY;
6600
+ if (looksLikeNativeEventLoopCrash(blob)) {
6601
+ return BUNDLED_NODE_CRASH_SUMMARY;
6602
+ }
6581
6603
  if (tail.some(
6582
6604
  (line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
6583
6605
  )) {
@@ -6603,10 +6625,11 @@ function looksLikeInvalidAgentSession(text4) {
6603
6625
  function looksLikeRetryableRunnerCrash(text4) {
6604
6626
  if (looksLikeAgentFailureMessage(text4)) return false;
6605
6627
  if (looksLikeInvalidAgentSession(text4)) return false;
6628
+ if (looksLikeV8Oom(text4)) return false;
6606
6629
  const lower = text4.trim().toLowerCase();
6607
6630
  if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
6608
6631
  if (!lower) return true;
6609
- return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|connection stalled|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
6632
+ return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|cursor runner crashed in node|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|connection stalled|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
6610
6633
  lower
6611
6634
  );
6612
6635
  }
@@ -6658,9 +6681,15 @@ function humanizeAgentFailDetail(detail) {
6658
6681
  if (/hascustomhostobject|electroninitializeicuandstartnode|nested chromium/i.test(lower)) {
6659
6682
  return `${raw} \u2014 retry the turn; if it keeps failing, pick another agent.`;
6660
6683
  }
6661
- if (/homebrew node \+ shared libuv|uv_run|spineventloopinternal/i.test(lower)) {
6684
+ if (looksLikeV8Oom(raw) || /javascript heap out of memory/i.test(lower)) {
6685
+ return /ran out of memory/i.test(raw) ? raw : V8_OOM_SUMMARY;
6686
+ }
6687
+ if (/homebrew node \+ shared libuv|Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(raw)) {
6662
6688
  return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
6663
6689
  }
6690
+ if (/uv_run|spineventloopinternal|uv__io_poll|cursor runner crashed in node/i.test(lower)) {
6691
+ return /retry the turn/i.test(raw) ? raw : BUNDLED_NODE_CRASH_SUMMARY;
6692
+ }
6664
6693
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
6665
6694
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
6666
6695
  }
@@ -6690,13 +6719,15 @@ function formatTurnExitError(exitCode, stderrSummary) {
6690
6719
  if (looksLikeAgentFailureMessage(raw)) return detail;
6691
6720
  return `exit ${code}: ${detail}`;
6692
6721
  }
6693
- var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, HOMEBREW_LIBUV_SUMMARY, MINIFIED_DUMP_SUMMARY;
6722
+ var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, HOMEBREW_LIBUV_SUMMARY, BUNDLED_NODE_CRASH_SUMMARY, V8_OOM_SUMMARY, MINIFIED_DUMP_SUMMARY;
6694
6723
  var init_error_detail = __esm({
6695
6724
  "src/agents/error-detail.ts"() {
6696
6725
  "use strict";
6697
6726
  NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
6698
6727
  NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
6699
6728
  HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
6729
+ BUNDLED_NODE_CRASH_SUMMARY = "Cursor runner crashed in Node. Retry the turn.";
6730
+ V8_OOM_SUMMARY = "Cursor runner ran out of memory (JavaScript heap). Retry; if it keeps happening, exclude large files from the project folder or start a new chat.";
6700
6731
  MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
6701
6732
  }
6702
6733
  });
@@ -7531,6 +7562,300 @@ var init_claude_mcp = __esm({
7531
7562
  }
7532
7563
  });
7533
7564
 
7565
+ // src/agents/message-parts.ts
7566
+ function asRecord(input) {
7567
+ if (input && typeof input === "object" && !Array.isArray(input)) {
7568
+ return input;
7569
+ }
7570
+ return void 0;
7571
+ }
7572
+ function str2(v) {
7573
+ return typeof v === "string" && v.trim() ? v : void 0;
7574
+ }
7575
+ function toolDetail(name, input) {
7576
+ if (!input) return void 0;
7577
+ const command = str2(input.command) ?? str2(input.cmd);
7578
+ if (command) return command;
7579
+ const path2 = str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
7580
+ if (path2) return path2;
7581
+ const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
7582
+ if (pattern) return pattern;
7583
+ const query = str2(input.query) ?? str2(input.prompt);
7584
+ if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
7585
+ try {
7586
+ const raw = JSON.stringify(input);
7587
+ return raw.length > 80 ? `${raw.slice(0, 77)}\u2026` : raw;
7588
+ } catch {
7589
+ return name;
7590
+ }
7591
+ }
7592
+ function toolDescription(name, input) {
7593
+ const n = name.replace(/^mcp__/, "").replace(/__/g, " \xB7 ");
7594
+ if (/^get_record_types$|recordTypes/i.test(name)) return "List record types";
7595
+ if (/connectedAgentRequest/i.test(name)) {
7596
+ return str2(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
7597
+ }
7598
+ if (/present_artifact$/i.test(name)) {
7599
+ return str2(input?.title) ? `Present ${str2(input?.title)}` : "Present artifact";
7600
+ }
7601
+ if (/present_plan$/i.test(name)) {
7602
+ return str2(input?.title) ? `Plan ${str2(input?.title)}` : "Present plan";
7603
+ }
7604
+ if (/present_schema$/i.test(name)) {
7605
+ return str2(input?.title) ? `Schema ${str2(input?.title)}` : "Present schema";
7606
+ }
7607
+ if (/present_files$/i.test(name)) {
7608
+ return str2(input?.title) ? `Files ${str2(input?.title)}` : "Present files";
7609
+ }
7610
+ if (isSubagentToolName(name)) {
7611
+ const desc = str2(input?.description);
7612
+ const sub = asRecord(input?.subagentType);
7613
+ const kind = str2(sub?.name) ?? str2(sub?.kind) ?? str2(input?.subagent_type) ?? str2(input?.subagentType);
7614
+ if (/^spawn_agent$/i.test(name)) {
7615
+ return str2(input?.prompt) ?? desc ?? "Subagent";
7616
+ }
7617
+ if (/connectedAgentRequest/i.test(name)) {
7618
+ return str2(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
7619
+ }
7620
+ if (desc && kind) return `${kind}: ${desc}`;
7621
+ if (desc) return desc;
7622
+ return "Subagent";
7623
+ }
7624
+ if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
7625
+ return str2(input?.title) ? `Artifact ${str2(input?.title)}` : "Artifact";
7626
+ }
7627
+ if (!input) return n;
7628
+ if (/bash|shell|terminal/i.test(name) && str2(input.command)) {
7629
+ const cmd = str2(input.command);
7630
+ if (/git\s+fetch/i.test(cmd)) return "Fetch latest from origin and check status";
7631
+ if (/git\s+status/i.test(cmd)) return "Check git status";
7632
+ if (/git\s+log/i.test(cmd)) return "Inspect recent commits";
7633
+ if (/git\s+branch/i.test(cmd)) return "List branches";
7634
+ if (/grep|rg\b/i.test(cmd)) return "Search repository";
7635
+ return "Run shell command";
7636
+ }
7637
+ if (/edit|write|apply/i.test(name)) {
7638
+ const path2 = str2(input.file_path) ?? str2(input.path);
7639
+ return path2 ? `Edit ${path2.split("/").pop()}` : "Edit file";
7640
+ }
7641
+ if (/read/i.test(name)) {
7642
+ const path2 = str2(input.file_path) ?? str2(input.path);
7643
+ return path2 ? `Read ${path2.split("/").pop()}` : "Read file";
7644
+ }
7645
+ if (/grep/i.test(name)) return "Search files";
7646
+ if (/glob/i.test(name)) return "Find files";
7647
+ return n;
7648
+ }
7649
+ function isSubagentToolName(name) {
7650
+ const n = (name ?? "").trim();
7651
+ if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
7652
+ return /connectedAgentRequest/i.test(n);
7653
+ }
7654
+ function messagePartParentId(part) {
7655
+ if ("parentId" in part && typeof part.parentId === "string" && part.parentId.trim()) {
7656
+ return part.parentId;
7657
+ }
7658
+ return void 0;
7659
+ }
7660
+ function sameParentId(a, b) {
7661
+ return (a ?? "") === (b ?? "");
7662
+ }
7663
+ function withEventParentId(event, parentId) {
7664
+ if (!parentId) return event;
7665
+ if (event.type === "stdout" || event.type === "thinking" || event.type === "tool_use" || event.type === "tool_result") {
7666
+ return { ...event, parentId: event.parentId ?? parentId };
7667
+ }
7668
+ return event;
7669
+ }
7670
+ function withEventsParentId(events, parentId) {
7671
+ if (!parentId) return events;
7672
+ return events.map((event) => withEventParentId(event, parentId));
7673
+ }
7674
+ function toolFilePath(input) {
7675
+ if (!input) return void 0;
7676
+ return str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
7677
+ }
7678
+ function countLines(text4) {
7679
+ if (!text4) return 0;
7680
+ return text4.split("\n").length;
7681
+ }
7682
+ function diffFromInput(input) {
7683
+ if (!input) return {};
7684
+ const oldS = str2(input.old_string) ?? str2(input.oldString);
7685
+ const newS = str2(input.new_string) ?? str2(input.newString) ?? str2(input.content);
7686
+ if (oldS != null || newS != null) {
7687
+ return {
7688
+ additions: countLines(newS),
7689
+ deletions: countLines(oldS)
7690
+ };
7691
+ }
7692
+ return {};
7693
+ }
7694
+ function parseDiffStat(result) {
7695
+ if (!result) return {};
7696
+ const paired = result.match(/\+(\d+)\s+-(\d+)/);
7697
+ if (paired) {
7698
+ return {
7699
+ additions: Number(paired[1]),
7700
+ deletions: Number(paired[2])
7701
+ };
7702
+ }
7703
+ const verbose = result.match(
7704
+ /(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
7705
+ );
7706
+ if (verbose) {
7707
+ return {
7708
+ additions: Number(verbose[1]),
7709
+ deletions: verbose[2] != null ? Number(verbose[2]) : void 0
7710
+ };
7711
+ }
7712
+ return {};
7713
+ }
7714
+ function applyAgentEvent(parts, event) {
7715
+ if (event.type === "stdout") {
7716
+ const data = event.data;
7717
+ if (!data) return parts;
7718
+ const next = [...parts];
7719
+ const last = next[next.length - 1];
7720
+ if (last?.type === "text" && sameParentId(last.parentId, event.parentId)) {
7721
+ next[next.length - 1] = {
7722
+ type: "text",
7723
+ text: last.text + data,
7724
+ ...event.parentId ? { parentId: event.parentId } : {}
7725
+ };
7726
+ } else {
7727
+ next.push({
7728
+ type: "text",
7729
+ text: data,
7730
+ ...event.parentId ? { parentId: event.parentId } : {}
7731
+ });
7732
+ }
7733
+ return next;
7734
+ }
7735
+ if (event.type === "thinking") {
7736
+ const data = event.data;
7737
+ if (!data) return parts;
7738
+ const next = [...parts];
7739
+ const last = next[next.length - 1];
7740
+ if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
7741
+ next[next.length - 1] = {
7742
+ type: "thinking",
7743
+ text: last.text + data,
7744
+ ...event.parentId ? { parentId: event.parentId } : {}
7745
+ };
7746
+ } else {
7747
+ next.push({
7748
+ type: "thinking",
7749
+ text: data,
7750
+ ...event.parentId ? { parentId: event.parentId } : {}
7751
+ });
7752
+ }
7753
+ return next;
7754
+ }
7755
+ if (event.type === "tool_use") {
7756
+ const input = asRecord(event.input);
7757
+ const diff = diffFromInput(input);
7758
+ const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
7759
+ if (existing >= 0) {
7760
+ const prev = parts[existing];
7761
+ const next = [...parts];
7762
+ const mergedInput = input && Object.keys(input).length > 0 ? input : prev.input ?? input;
7763
+ next[existing] = {
7764
+ ...prev,
7765
+ name: event.name || prev.name,
7766
+ input: mergedInput,
7767
+ description: toolDescription(event.name || prev.name, mergedInput),
7768
+ detail: toolDetail(event.name || prev.name, mergedInput) ?? prev.detail,
7769
+ filePath: toolFilePath(mergedInput) ?? prev.filePath,
7770
+ additions: diff.additions ?? prev.additions,
7771
+ deletions: diff.deletions ?? prev.deletions,
7772
+ parentId: event.parentId ?? prev.parentId
7773
+ };
7774
+ return next;
7775
+ }
7776
+ return [
7777
+ ...parts,
7778
+ {
7779
+ type: "tool",
7780
+ id: event.id,
7781
+ name: event.name,
7782
+ input,
7783
+ description: toolDescription(event.name, input),
7784
+ detail: toolDetail(event.name, input),
7785
+ status: "running",
7786
+ filePath: toolFilePath(input),
7787
+ ...event.parentId ? { parentId: event.parentId } : {},
7788
+ ...diff
7789
+ }
7790
+ ];
7791
+ }
7792
+ if (event.type === "tool_result") {
7793
+ const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
7794
+ const fromResult = parseDiffStat(event.content);
7795
+ if (existing < 0) {
7796
+ return [
7797
+ ...parts,
7798
+ {
7799
+ type: "tool",
7800
+ id: event.id,
7801
+ name: "tool",
7802
+ description: "tool",
7803
+ status: event.isError ? "error" : "done",
7804
+ result: event.content,
7805
+ ...event.parentId ? { parentId: event.parentId } : {},
7806
+ ...fromResult.additions != null ? { additions: fromResult.additions } : {},
7807
+ ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
7808
+ }
7809
+ ];
7810
+ }
7811
+ return parts.map((p, i) => {
7812
+ if (i !== existing || p.type !== "tool") return p;
7813
+ return {
7814
+ ...p,
7815
+ status: event.isError ? "error" : "done",
7816
+ result: event.content,
7817
+ ...fromResult.additions != null ? { additions: fromResult.additions } : {},
7818
+ ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
7819
+ };
7820
+ });
7821
+ }
7822
+ return parts;
7823
+ }
7824
+ function partsToAssistantText(parts) {
7825
+ return parts.filter(
7826
+ (p) => p.type === "text" && !messagePartParentId(p)
7827
+ ).map((p) => p.text).join("").trim();
7828
+ }
7829
+ function stripBrightsyNdjsonNoise(text4) {
7830
+ if (!text4 || !text4.includes('"type"')) return text4;
7831
+ let out = text4;
7832
+ out = out.replace(
7833
+ /\{"type":"(?:tool_use|tool_result|tool|thinking|usage|done|error)"[\s\S]*?\}\s*(?=\{"type":"|$|(?=[A-Za-z*#]))/g,
7834
+ ""
7835
+ );
7836
+ out = out.replace(/\{"type":"(?:tool_use|tool_result|tool)"[\s\S]*$/g, "");
7837
+ return out.trim();
7838
+ }
7839
+ function isBrightsyNdjsonLine(line) {
7840
+ const t = line.trim();
7841
+ if (!t.startsWith("{")) return false;
7842
+ return /"type"\s*:\s*"(tool_use|tool_result|tool|thinking|usage|done|error|text)"/.test(t);
7843
+ }
7844
+ function finalizeParts(parts) {
7845
+ return parts.map(
7846
+ (p) => p.type === "tool" && p.status === "running" ? { ...p, status: "done" } : p
7847
+ );
7848
+ }
7849
+ function normalizeParseResult(parsed) {
7850
+ if (!parsed) return [];
7851
+ return Array.isArray(parsed) ? parsed : [parsed];
7852
+ }
7853
+ var init_message_parts = __esm({
7854
+ "src/agents/message-parts.ts"() {
7855
+ "use strict";
7856
+ }
7857
+ });
7858
+
7534
7859
  // src/mcp/profile.ts
7535
7860
  function sideboardMcpProfile(env = process.env) {
7536
7861
  return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
@@ -8170,42 +8495,59 @@ function claudeResultErrorDetail(obj) {
8170
8495
  }
8171
8496
  return "Claude turn failed";
8172
8497
  }
8173
- function eventsFromContentBlocks(blocks) {
8498
+ function eventsFromContentBlocks(blocks, parentId) {
8174
8499
  if (!blocks?.length) return [];
8175
8500
  const out = [];
8176
8501
  for (const block of blocks) {
8177
8502
  if (!block?.type) continue;
8178
8503
  if (block.type === "text" && block.text) {
8179
- out.push({ type: "stdout", data: block.text });
8504
+ out.push(withEventParentId({ type: "stdout", data: block.text }, parentId));
8180
8505
  continue;
8181
8506
  }
8182
8507
  if ((block.type === "thinking" || block.type === "redacted_thinking") && block.thinking) {
8183
- out.push({ type: "thinking", data: block.thinking });
8508
+ out.push(withEventParentId({ type: "thinking", data: block.thinking }, parentId));
8184
8509
  continue;
8185
8510
  }
8186
8511
  if (block.type === "tool_use" && block.id && block.name) {
8187
- out.push({
8188
- type: "tool_use",
8189
- id: block.id,
8190
- name: block.name,
8191
- input: block.input
8192
- });
8512
+ out.push(
8513
+ withEventParentId(
8514
+ {
8515
+ type: "tool_use",
8516
+ id: block.id,
8517
+ name: block.name,
8518
+ input: block.input
8519
+ },
8520
+ parentId
8521
+ )
8522
+ );
8193
8523
  continue;
8194
8524
  }
8195
8525
  if (block.type === "tool_result" && block.tool_use_id) {
8196
8526
  const content = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map(
8197
8527
  (c) => typeof c === "string" ? c : c && typeof c === "object" && "text" in c ? String(c.text ?? "") : ""
8198
8528
  ).join("") : block.content != null ? JSON.stringify(block.content) : void 0;
8199
- out.push({
8200
- type: "tool_result",
8201
- id: block.tool_use_id,
8202
- content,
8203
- isError: Boolean(block.is_error)
8204
- });
8205
- }
8206
- }
8529
+ out.push(
8530
+ withEventParentId(
8531
+ {
8532
+ type: "tool_result",
8533
+ id: block.tool_use_id,
8534
+ content,
8535
+ isError: Boolean(block.is_error)
8536
+ },
8537
+ parentId
8538
+ )
8539
+ );
8540
+ }
8541
+ }
8207
8542
  return out;
8208
8543
  }
8544
+ function claudeParentToolUseId(obj) {
8545
+ const nested = obj.event && typeof obj.event === "object" && !Array.isArray(obj.event) ? obj.event : void 0;
8546
+ for (const id of [obj.parent_tool_use_id, nested?.parent_tool_use_id]) {
8547
+ if (typeof id === "string" && id.trim()) return id.trim();
8548
+ }
8549
+ return void 0;
8550
+ }
8209
8551
  function parseIssuesJson(raw) {
8210
8552
  const text4 = raw.trim();
8211
8553
  const candidates = [text4];
@@ -8240,6 +8582,7 @@ var init_claude = __esm({
8240
8582
  init_app_settings();
8241
8583
  init_claude_mcp();
8242
8584
  init_error_detail();
8585
+ init_message_parts();
8243
8586
  init_injected_mcp();
8244
8587
  init_turn_input();
8245
8588
  init_types();
@@ -8251,7 +8594,10 @@ var init_claude = __esm({
8251
8594
  "Glob",
8252
8595
  "Grep",
8253
8596
  "WebFetch",
8254
- "WebSearch"
8597
+ "WebSearch",
8598
+ // Subagents (Claude Code v2.1.63 renamed Task → Agent; allow both).
8599
+ "Task",
8600
+ "Agent"
8255
8601
  ];
8256
8602
  CLAUDE_CHROME_ALLOWED_TOOLS = [
8257
8603
  "mcp__claude-in-chrome",
@@ -8379,7 +8725,9 @@ var init_claude = __esm({
8379
8725
  args,
8380
8726
  cwd: thread.worktreePath,
8381
8727
  stdin: useStdin ? `${promptText}
8382
- ` : void 0
8728
+ ` : void 0,
8729
+ // Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
8730
+ env: { CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1" }
8383
8731
  };
8384
8732
  },
8385
8733
  parseEvent(line) {
@@ -8396,8 +8744,9 @@ var init_claude = __esm({
8396
8744
  return { type: "session_id", data: obj.session_id };
8397
8745
  }
8398
8746
  if (obj.type === "assistant" || obj.type === "user") {
8747
+ const parentId = claudeParentToolUseId(obj);
8399
8748
  const message = obj.message;
8400
- const events = eventsFromContentBlocks(message?.content);
8749
+ const events = eventsFromContentBlocks(message?.content, parentId);
8401
8750
  if (obj.type === "assistant") {
8402
8751
  const usage = usageFromClaude(message?.usage);
8403
8752
  if (usage) events.push({ type: "usage", data: usage, scope: "request" });
@@ -8406,34 +8755,45 @@ var init_claude = __esm({
8406
8755
  return events.length === 1 ? events[0] : events;
8407
8756
  }
8408
8757
  if (obj.type === "stream_event") {
8758
+ const parentId = claudeParentToolUseId(obj);
8409
8759
  const event = obj.event;
8410
8760
  if (!event) return null;
8411
8761
  if (event.type === "content_block_start" && event.content_block) {
8412
8762
  const block = event.content_block;
8413
8763
  if (block.type === "tool_use" && block.id && block.name) {
8414
- return {
8415
- type: "tool_use",
8416
- id: block.id,
8417
- name: block.name,
8418
- input: block.input
8419
- };
8764
+ return withEventParentId(
8765
+ {
8766
+ type: "tool_use",
8767
+ id: block.id,
8768
+ name: block.name,
8769
+ input: block.input
8770
+ },
8771
+ parentId
8772
+ );
8420
8773
  }
8421
8774
  if (block.type === "thinking" && block.thinking) {
8422
- return { type: "thinking", data: block.thinking };
8775
+ return withEventParentId({ type: "thinking", data: block.thinking }, parentId);
8423
8776
  }
8424
8777
  return null;
8425
8778
  }
8426
8779
  if (event.type === "content_block_delta" && event.delta) {
8427
- if (event.delta.text) return { type: "stdout", data: event.delta.text };
8428
- if (event.delta.thinking) return { type: "thinking", data: event.delta.thinking };
8780
+ if (event.delta.text) {
8781
+ return withEventParentId({ type: "stdout", data: event.delta.text }, parentId);
8782
+ }
8783
+ if (event.delta.thinking) {
8784
+ return withEventParentId({ type: "thinking", data: event.delta.thinking }, parentId);
8785
+ }
8429
8786
  return null;
8430
8787
  }
8431
8788
  return null;
8432
8789
  }
8433
8790
  if (obj.type === "content_block_delta") {
8791
+ const parentId = claudeParentToolUseId(obj);
8434
8792
  const delta = obj.delta;
8435
- if (delta?.text) return { type: "stdout", data: delta.text };
8436
- if (delta?.thinking) return { type: "thinking", data: delta.thinking };
8793
+ if (delta?.text) return withEventParentId({ type: "stdout", data: delta.text }, parentId);
8794
+ if (delta?.thinking) {
8795
+ return withEventParentId({ type: "thinking", data: delta.thinking }, parentId);
8796
+ }
8437
8797
  return null;
8438
8798
  }
8439
8799
  if (obj.type === "result") {
@@ -8566,7 +8926,7 @@ function unwrapCodexMcpResult(result) {
8566
8926
  return String(result);
8567
8927
  }
8568
8928
  }
8569
- function asRecord(value) {
8929
+ function asRecord2(value) {
8570
8930
  if (value && typeof value === "object" && !Array.isArray(value)) {
8571
8931
  return value;
8572
8932
  }
@@ -8731,7 +9091,7 @@ var init_codex = __esm({
8731
9091
  }
8732
9092
  if (itemType === "mcp_tool_call" && item.id && item.server && item.tool) {
8733
9093
  const name = `mcp__${item.server}__${item.tool}`;
8734
- const input = asRecord(item.arguments);
9094
+ const input = asRecord2(item.arguments);
8735
9095
  const events = [
8736
9096
  { type: "tool_use", id: item.id, name, input }
8737
9097
  ];
@@ -8762,6 +9122,36 @@ var init_codex = __esm({
8762
9122
  }
8763
9123
  return events.length === 1 ? events[0] : events;
8764
9124
  }
9125
+ if (itemType === "collab_tool_call" && item.id) {
9126
+ const rawTool = typeof item.tool === "string" ? item.tool : "spawn_agent";
9127
+ const name = /spawn/i.test(rawTool) ? "spawn_agent" : rawTool;
9128
+ const input = {};
9129
+ if (item.prompt) input.prompt = item.prompt;
9130
+ if (Array.isArray(item.receiver_thread_ids)) {
9131
+ input.receiver_thread_ids = item.receiver_thread_ids;
9132
+ }
9133
+ const events = [{ type: "tool_use", id: item.id, name, input }];
9134
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
9135
+ if (finished) {
9136
+ const nested = [];
9137
+ if (item.agents_states && typeof item.agents_states === "object") {
9138
+ for (const value of Object.values(item.agents_states)) {
9139
+ const msg = value && typeof value === "object" && typeof value.message === "string" ? value.message.trim() : "";
9140
+ if (msg) nested.push(msg);
9141
+ }
9142
+ }
9143
+ for (const text4 of nested) {
9144
+ events.push({ type: "stdout", data: text4, parentId: item.id });
9145
+ }
9146
+ events.push({
9147
+ type: "tool_result",
9148
+ id: item.id,
9149
+ content: nested.join("\n") || void 0,
9150
+ isError: item.status === "failed"
9151
+ });
9152
+ }
9153
+ return events.length === 1 ? events[0] : events;
9154
+ }
8765
9155
  if (item.status === "failed") {
8766
9156
  const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
8767
9157
  return { type: "stderr", data: detail };
@@ -8850,20 +9240,20 @@ function usageFromCursor(usage) {
8850
9240
  cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
8851
9241
  };
8852
9242
  }
8853
- function asRecord2(value) {
9243
+ function asRecord3(value) {
8854
9244
  if (value && typeof value === "object" && !Array.isArray(value)) {
8855
9245
  return value;
8856
9246
  }
8857
9247
  return void 0;
8858
9248
  }
8859
9249
  function normalizeCursorToolCall(name, args) {
8860
- const raw = asRecord2(args);
9250
+ const raw = asRecord3(args);
8861
9251
  const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
8862
- const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord2(raw?.args) != null);
9252
+ const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord3(raw?.args) != null);
8863
9253
  if (looksLikeMcp && toolName) {
8864
9254
  const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
8865
9255
  const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
8866
- const nested = asRecord2(raw.args);
9256
+ const nested = asRecord3(raw.args);
8867
9257
  return {
8868
9258
  name: `mcp__${provider}__${toolName}`,
8869
9259
  input: nested ?? { toolName }
@@ -8874,7 +9264,7 @@ function normalizeCursorToolCall(name, args) {
8874
9264
  function unwrapCursorToolResult(result) {
8875
9265
  if (result == null) return void 0;
8876
9266
  if (typeof result === "string") return result;
8877
- const rec = asRecord2(result);
9267
+ const rec = asRecord3(result);
8878
9268
  if (!rec) {
8879
9269
  try {
8880
9270
  return JSON.stringify(result);
@@ -8885,18 +9275,18 @@ function unwrapCursorToolResult(result) {
8885
9275
  const collectTexts = (items) => {
8886
9276
  const texts = [];
8887
9277
  for (const item of items) {
8888
- const row = asRecord2(item);
9278
+ const row = asRecord3(item);
8889
9279
  if (!row) continue;
8890
9280
  if (typeof row.text === "string") {
8891
9281
  texts.push(row.text);
8892
9282
  continue;
8893
9283
  }
8894
- const nested = asRecord2(row.text);
9284
+ const nested = asRecord3(row.text);
8895
9285
  if (typeof nested?.text === "string") texts.push(nested.text);
8896
9286
  }
8897
9287
  return texts;
8898
9288
  };
8899
- const value = asRecord2(rec.value);
9289
+ const value = asRecord3(rec.value);
8900
9290
  if (value && Array.isArray(value.content)) {
8901
9291
  const texts = collectTexts(value.content);
8902
9292
  if (texts.length) return texts.join("\n");
@@ -8913,10 +9303,10 @@ function unwrapCursorToolResult(result) {
8913
9303
  }
8914
9304
  function cursorToolResultIsError(status, result) {
8915
9305
  if (status === "error") return true;
8916
- const rec = asRecord2(result);
9306
+ const rec = asRecord3(result);
8917
9307
  if (!rec) return false;
8918
9308
  if (rec.status === "error") return true;
8919
- const value = asRecord2(rec.value);
9309
+ const value = asRecord3(rec.value);
8920
9310
  return value?.isError === true;
8921
9311
  }
8922
9312
  function cursorSdkMessageToEvents(msg) {
@@ -9058,24 +9448,24 @@ function resolveCursorRipgrepPath(opts) {
9058
9448
  packagedCursorRipgrepCandidate(platformRipgrepPackage(), rgBinaryName())
9059
9449
  );
9060
9450
  if (fromPackaged) return fromPackaged;
9061
- const start = opts?.startFile?.trim() || process.argv[1] || (0, import_node_url2.fileURLToPath)(import_meta2.url);
9451
+ const start = opts?.startFile?.trim() || process.argv[1] || // CJS bundle only — ESM has no __filename; argv[1] is the running script.
9452
+ // eslint-disable-next-line camelcase
9453
+ (typeof __filename !== "undefined" ? __filename : "");
9062
9454
  return walkForBundledRipgrep(start) ?? requireResolveBundledRipgrep(start);
9063
9455
  }
9064
9456
  function cursorRipgrepEnv(opts) {
9065
9457
  const path2 = resolveCursorRipgrepPath(opts);
9066
9458
  return path2 ? { [RIPGREP_ENV]: path2 } : {};
9067
9459
  }
9068
- var import_node_fs26, import_node_module2, import_node_path26, import_node_url2, import_meta2, RIPGREP_ENV;
9460
+ var import_node_fs26, import_node_module2, import_node_path26, RIPGREP_ENV;
9069
9461
  var init_cursor_ripgrep = __esm({
9070
9462
  "src/agents/cursor-ripgrep.ts"() {
9071
9463
  "use strict";
9072
9464
  import_node_fs26 = require("fs");
9073
9465
  import_node_module2 = require("module");
9074
9466
  import_node_path26 = require("path");
9075
- import_node_url2 = require("url");
9076
9467
  init_node_launch();
9077
9468
  init_packaged_runtime();
9078
- import_meta2 = {};
9079
9469
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
9080
9470
  }
9081
9471
  });
@@ -9119,7 +9509,7 @@ function entryDir() {
9119
9509
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
9120
9510
  if (cjsDir) return cjsDir;
9121
9511
  try {
9122
- return (0, import_node_path27.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
9512
+ return (0, import_node_path27.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
9123
9513
  } catch {
9124
9514
  try {
9125
9515
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
@@ -9148,14 +9538,14 @@ function cursorRunnerPath() {
9148
9538
  }
9149
9539
  return candidates[0];
9150
9540
  }
9151
- var import_node_fs27, import_node_module3, import_node_path27, import_node_url3, import_sdk, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
9541
+ var import_node_fs27, import_node_module3, import_node_path27, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
9152
9542
  var init_cursor = __esm({
9153
9543
  "src/agents/cursor.ts"() {
9154
9544
  "use strict";
9155
9545
  import_node_fs27 = require("fs");
9156
9546
  import_node_module3 = require("module");
9157
9547
  import_node_path27 = require("path");
9158
- import_node_url3 = require("url");
9548
+ import_node_url2 = require("url");
9159
9549
  import_sdk = require("@cursor/sdk");
9160
9550
  init_run();
9161
9551
  init_app_settings();
@@ -9167,7 +9557,7 @@ var init_cursor = __esm({
9167
9557
  init_packaged_runtime();
9168
9558
  init_turn_input();
9169
9559
  init_cursor_events();
9170
- import_meta3 = {};
9560
+ import_meta2 = {};
9171
9561
  FALLBACK_CURSOR_MODELS = [
9172
9562
  { id: "default", displayName: "Auto" },
9173
9563
  { id: "composer-2.5", displayName: "Composer 2.5" },
@@ -9259,6 +9649,24 @@ var init_cursor = __esm({
9259
9649
  });
9260
9650
 
9261
9651
  // src/agents/opencode.ts
9652
+ function asRecord4(value) {
9653
+ if (value && typeof value === "object" && !Array.isArray(value)) {
9654
+ return value;
9655
+ }
9656
+ return void 0;
9657
+ }
9658
+ function str3(v) {
9659
+ return typeof v === "string" && v.trim() ? v.trim() : void 0;
9660
+ }
9661
+ function opencodeToolId(name, callId, metadata) {
9662
+ const sessionId = str3(metadata?.sessionId) ?? str3(metadata?.sessionID);
9663
+ if (name === "task" && sessionId) return sessionId;
9664
+ return callId || `tool-${Date.now()}`;
9665
+ }
9666
+ function withTaskParent(parentId, nested) {
9667
+ const events = Array.isArray(nested) ? nested : [nested];
9668
+ return [{ type: "tool_use", id: parentId, name: "task" }, ...events];
9669
+ }
9262
9670
  function displayNameFromOpencodeId(id) {
9263
9671
  const slash = id.indexOf("/");
9264
9672
  if (slash <= 0) return id;
@@ -9325,6 +9733,7 @@ var init_opencode = __esm({
9325
9733
  init_app_settings();
9326
9734
  init_global_workspace();
9327
9735
  init_error_detail();
9736
+ init_message_parts();
9328
9737
  init_injected_mcp();
9329
9738
  init_turn_input();
9330
9739
  init_types();
@@ -9441,10 +9850,15 @@ var init_opencode = __esm({
9441
9850
  }
9442
9851
  if (obj.type === "tool_use") {
9443
9852
  const part = obj.part;
9444
- const id = part?.callID ?? part?.id ?? obj.id ?? `tool-${Date.now()}`;
9445
9853
  const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
9446
9854
  const state = part?.state;
9447
9855
  const input = (state?.input && typeof state.input === "object" ? state.input : void 0) ?? part?.input ?? obj.input;
9856
+ const metadata = asRecord4(state?.metadata);
9857
+ const id = opencodeToolId(
9858
+ name,
9859
+ part?.callID ?? part?.id ?? obj.id,
9860
+ metadata
9861
+ );
9448
9862
  const events = [{ type: "tool_use", id, name, input }];
9449
9863
  const output = state?.output;
9450
9864
  if (output != null || state?.status === "completed" || state?.status === "error") {
@@ -9458,6 +9872,53 @@ var init_opencode = __esm({
9458
9872
  }
9459
9873
  return events.length === 1 ? events[0] : events;
9460
9874
  }
9875
+ if (obj.type === "subtask_delta") {
9876
+ const parentId = str3(obj.childSessionID) ?? str3(obj.childSessionId);
9877
+ const delta = str3(obj.delta);
9878
+ if (parentId && delta) {
9879
+ return withTaskParent(
9880
+ parentId,
9881
+ withEventParentId({ type: "thinking", data: delta }, parentId)
9882
+ );
9883
+ }
9884
+ return null;
9885
+ }
9886
+ if (obj.type === "subtask_event") {
9887
+ const parentId = str3(obj.childSessionID) ?? str3(obj.childSessionId);
9888
+ const part = asRecord4(obj.part);
9889
+ if (!parentId || !part) return null;
9890
+ if (part.type === "text" && str3(part.text)) {
9891
+ return withTaskParent(
9892
+ parentId,
9893
+ withEventParentId({ type: "stdout", data: str3(part.text) }, parentId)
9894
+ );
9895
+ }
9896
+ if (part.type === "tool" || str3(part.tool)) {
9897
+ const name = str3(part.tool) ?? str3(part.name) ?? "tool";
9898
+ const id = str3(part.callID) ?? str3(part.id) ?? `${parentId}-${name}`;
9899
+ const state = asRecord4(part.state);
9900
+ const input = asRecord4(state?.input) ?? asRecord4(part.input);
9901
+ const nested = [
9902
+ withEventParentId({ type: "tool_use", id, name, input }, parentId)
9903
+ ];
9904
+ const output = state?.output ?? part.output;
9905
+ if (output != null || state?.status === "completed" || state?.status === "error") {
9906
+ nested.push(
9907
+ withEventParentId(
9908
+ {
9909
+ type: "tool_result",
9910
+ id,
9911
+ content: typeof output === "string" ? output : output != null ? JSON.stringify(output) : void 0,
9912
+ isError: state?.status === "error" || state?.status === "failed"
9913
+ },
9914
+ parentId
9915
+ )
9916
+ );
9917
+ }
9918
+ return withTaskParent(parentId, nested);
9919
+ }
9920
+ return null;
9921
+ }
9461
9922
  if (obj.type === "tool_result") {
9462
9923
  const part = obj.part;
9463
9924
  const id = part?.tool_use_id ?? part?.id ?? obj.tool_use_id ?? obj.id;
@@ -9887,422 +10348,189 @@ async function installAgent(agent) {
9887
10348
  };
9888
10349
  }
9889
10350
  }
9890
- enrichPathWithNpmGlobalBin();
9891
- let binPath = null;
9892
- if (cliBin) {
9893
- binPath = await whichCli(cliBin);
9894
- }
9895
- return {
9896
- ok: true,
9897
- command: info.installCommand,
9898
- exitCode: 0,
9899
- stdout: result.stdout,
9900
- stderr: result.stderr,
9901
- message: binPath ? `Installed ${info.npmPackage} \u2192 ${binPath}` : `Installed ${info.npmPackage} (CLI not yet on PATH \u2014 Log in still exports Electron\u2019s PATH into Terminal)`
9902
- };
9903
- }
9904
- async function loginAgent(agent) {
9905
- const info = getAgentSetupInfo(agent);
9906
- const loginCommand = resolveLoginCommand(agent);
9907
- if (!loginCommand) {
9908
- return {
9909
- ok: true,
9910
- message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
9911
- };
9912
- }
9913
- const prepared = await prepareTerminalCommand(loginCommand);
9914
- await openInSystemTerminal(prepared);
9915
- return {
9916
- ok: true,
9917
- openedTerminal: true,
9918
- command: prepared,
9919
- message: `Opened Terminal to run: ${prepared}`
9920
- };
9921
- }
9922
- var SETUP, CLI_BIN, CLI_LOGIN_AGENTS;
9923
- var init_install = __esm({
9924
- "src/agents/install.ts"() {
9925
- "use strict";
9926
- init_run();
9927
- init_app_settings();
9928
- init_path();
9929
- SETUP = {
9930
- claude: {
9931
- agent: "claude",
9932
- kind: "cli",
9933
- summary: "Install the Claude Code CLI, then complete login in a terminal.",
9934
- docsUrl: "https://code.claude.com/docs/en/install",
9935
- installCommand: "npm install -g @anthropic-ai/claude-code",
9936
- loginCommand: "claude auth login",
9937
- npmPackage: "@anthropic-ai/claude-code"
9938
- },
9939
- codex: {
9940
- agent: "codex",
9941
- kind: "cli",
9942
- summary: "Install the Codex CLI, then run login in a terminal.",
9943
- docsUrl: "https://github.com/openai/codex",
9944
- installCommand: "npm install -g @openai/codex",
9945
- loginCommand: "codex login",
9946
- npmPackage: "@openai/codex"
9947
- },
9948
- opencode: {
9949
- agent: "opencode",
9950
- kind: "cli",
9951
- summary: "Install OpenCode (curl installer or npm), then authenticate providers.",
9952
- docsUrl: "https://opencode.ai/docs",
9953
- // Prefer the official installer; npm package name is opencode-ai.
9954
- installCommand: "curl -fsSL https://opencode.ai/install | bash",
9955
- loginCommand: "opencode auth login",
9956
- npmPackage: "opencode-ai@latest"
9957
- },
9958
- cursor: {
9959
- agent: "cursor",
9960
- kind: "bundled-sdk",
9961
- summary: "No CLI install \u2014 Sideboard ships the Cursor SDK. Add a CURSOR_API_KEY from the Cursor dashboard.",
9962
- docsUrl: "https://cursor.com/dashboard/integrations",
9963
- installCommand: null,
9964
- loginCommand: null
9965
- },
9966
- brightsy: {
9967
- agent: "brightsy",
9968
- kind: "cli",
9969
- summary: "Install the Brightsy CLI, then run `brightsy login`.",
9970
- docsUrl: "https://www.npmjs.com/package/@brightsy/cli",
9971
- installCommand: "npm install -g @brightsy/cli",
9972
- loginCommand: "brightsy login",
9973
- npmPackage: "@brightsy/cli"
9974
- }
9975
- };
9976
- CLI_BIN = {
9977
- claude: "claude",
9978
- codex: "codex",
9979
- opencode: "opencode",
9980
- brightsy: "brightsy"
9981
- };
9982
- CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
9983
- "claude",
9984
- "codex",
9985
- "opencode",
9986
- "brightsy"
9987
- ]);
9988
- }
9989
- });
9990
-
9991
- // src/agents/index.ts
9992
- var agents_exports = {};
9993
- __export(agents_exports, {
9994
- CLAUDE_MODEL_CATALOG: () => CLAUDE_MODEL_CATALOG,
9995
- ORCHESTRATOR_AGENT_KINDS: () => ORCHESTRATOR_AGENT_KINDS,
9996
- PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
9997
- allAdapters: () => allAdapters,
9998
- assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
9999
- brightsyAdapter: () => brightsyAdapter,
10000
- claudeAdapter: () => claudeAdapter,
10001
- codexAdapter: () => codexAdapter,
10002
- coerceOrchestratorAgent: () => coerceOrchestratorAgent,
10003
- conductorBundledBinDir: () => conductorBundledBinDir,
10004
- cursorAdapter: () => cursorAdapter,
10005
- cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
10006
- decodeBrightsyTarget: () => decodeBrightsyTarget,
10007
- encodeBrightsyTarget: () => encodeBrightsyTarget,
10008
- enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
10009
- ensureAgentPath: () => ensureAgentPath,
10010
- getAdapter: () => getAdapter,
10011
- getAgentSetupInfo: () => getAgentSetupInfo,
10012
- installAgent: () => installAgent,
10013
- isConductorBundledCli: () => isConductorBundledCli,
10014
- isCursorAutoModel: () => isCursorAutoModel,
10015
- isOrchestratorCapableAgent: () => isOrchestratorCapableAgent,
10016
- isSessionQuotaLimit: () => isSessionQuotaLimit,
10017
- listAgentSetupInfo: () => listAgentSetupInfo,
10018
- listBrightsyChatTargets: () => listBrightsyChatTargets,
10019
- listCodexModels: () => listCodexModels,
10020
- listCursorModels: () => listCursorModels,
10021
- listModelsForAgent: () => listModelsForAgent,
10022
- listOpencodeModels: () => listOpencodeModels,
10023
- loginAgent: () => loginAgent,
10024
- openInSystemTerminal: () => openInSystemTerminal,
10025
- opencodeAdapter: () => opencodeAdapter,
10026
- parseCursorRunnerLine: () => parseCursorRunnerLine,
10027
- parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
10028
- permissionMode: () => permissionMode,
10029
- posixShellSingleQuote: () => posixShellSingleQuote,
10030
- prepareTerminalCommand: () => prepareTerminalCommand,
10031
- resolveCommandBinarySync: () => resolveCommandBinarySync,
10032
- resolveCursorModelId: () => resolveCursorModelId,
10033
- resolveLoginCommand: () => resolveLoginCommand,
10034
- resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
10035
- withExportedPath: () => withExportedPath
10036
- });
10037
- function getAdapter(kind) {
10038
- return adapters[kind];
10039
- }
10040
- function allAdapters() {
10041
- return Object.values(adapters);
10042
- }
10043
- var adapters;
10044
- var init_agents = __esm({
10045
- "src/agents/index.ts"() {
10046
- "use strict";
10047
- init_brightsy();
10048
- init_claude();
10049
- init_codex();
10050
- init_cursor();
10051
- init_opencode();
10052
- init_types();
10053
- init_brightsy();
10054
- init_brightsy_targets();
10055
- init_claude();
10056
- init_codex();
10057
- init_cursor();
10058
- init_cursor_events();
10059
- init_cursor();
10060
- init_opencode();
10061
- init_list_models();
10062
- init_session_quota();
10063
- init_orchestrator_capable();
10064
- init_path();
10065
- init_install();
10066
- adapters = {
10067
- claude: claudeAdapter,
10068
- codex: codexAdapter,
10069
- opencode: opencodeAdapter,
10070
- brightsy: brightsyAdapter,
10071
- cursor: cursorAdapter
10072
- };
10073
- }
10074
- });
10075
-
10076
- // src/agents/message-parts.ts
10077
- function asRecord3(input) {
10078
- if (input && typeof input === "object" && !Array.isArray(input)) {
10079
- return input;
10080
- }
10081
- return void 0;
10082
- }
10083
- function str2(v) {
10084
- return typeof v === "string" && v.trim() ? v : void 0;
10085
- }
10086
- function toolDetail(name, input) {
10087
- if (!input) return void 0;
10088
- const command = str2(input.command) ?? str2(input.cmd);
10089
- if (command) return command;
10090
- const path2 = str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
10091
- if (path2) return path2;
10092
- const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
10093
- if (pattern) return pattern;
10094
- const query = str2(input.query) ?? str2(input.prompt);
10095
- if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
10096
- try {
10097
- const raw = JSON.stringify(input);
10098
- return raw.length > 80 ? `${raw.slice(0, 77)}\u2026` : raw;
10099
- } catch {
10100
- return name;
10101
- }
10102
- }
10103
- function toolDescription(name, input) {
10104
- const n = name.replace(/^mcp__/, "").replace(/__/g, " \xB7 ");
10105
- if (/^get_record_types$|recordTypes/i.test(name)) return "List record types";
10106
- if (/connectedAgentRequest/i.test(name)) {
10107
- return str2(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
10108
- }
10109
- if (/present_artifact$/i.test(name)) {
10110
- return str2(input?.title) ? `Present ${str2(input?.title)}` : "Present artifact";
10111
- }
10112
- if (/present_plan$/i.test(name)) {
10113
- return str2(input?.title) ? `Plan ${str2(input?.title)}` : "Present plan";
10114
- }
10115
- if (/present_schema$/i.test(name)) {
10116
- return str2(input?.title) ? `Schema ${str2(input?.title)}` : "Present schema";
10117
- }
10118
- if (/present_files$/i.test(name)) {
10119
- return str2(input?.title) ? `Files ${str2(input?.title)}` : "Present files";
10120
- }
10121
- if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
10122
- return str2(input?.title) ? `Artifact ${str2(input?.title)}` : "Artifact";
10123
- }
10124
- if (!input) return n;
10125
- if (/bash|shell|terminal/i.test(name) && str2(input.command)) {
10126
- const cmd = str2(input.command);
10127
- if (/git\s+fetch/i.test(cmd)) return "Fetch latest from origin and check status";
10128
- if (/git\s+status/i.test(cmd)) return "Check git status";
10129
- if (/git\s+log/i.test(cmd)) return "Inspect recent commits";
10130
- if (/git\s+branch/i.test(cmd)) return "List branches";
10131
- if (/grep|rg\b/i.test(cmd)) return "Search repository";
10132
- return "Run shell command";
10133
- }
10134
- if (/edit|write|apply/i.test(name)) {
10135
- const path2 = str2(input.file_path) ?? str2(input.path);
10136
- return path2 ? `Edit ${path2.split("/").pop()}` : "Edit file";
10137
- }
10138
- if (/read/i.test(name)) {
10139
- const path2 = str2(input.file_path) ?? str2(input.path);
10140
- return path2 ? `Read ${path2.split("/").pop()}` : "Read file";
10141
- }
10142
- if (/grep/i.test(name)) return "Search files";
10143
- if (/glob/i.test(name)) return "Find files";
10144
- return n;
10145
- }
10146
- function toolFilePath(input) {
10147
- if (!input) return void 0;
10148
- return str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
10149
- }
10150
- function countLines(text4) {
10151
- if (!text4) return 0;
10152
- return text4.split("\n").length;
10153
- }
10154
- function diffFromInput(input) {
10155
- if (!input) return {};
10156
- const oldS = str2(input.old_string) ?? str2(input.oldString);
10157
- const newS = str2(input.new_string) ?? str2(input.newString) ?? str2(input.content);
10158
- if (oldS != null || newS != null) {
10159
- return {
10160
- additions: countLines(newS),
10161
- deletions: countLines(oldS)
10162
- };
10163
- }
10164
- return {};
10165
- }
10166
- function parseDiffStat(result) {
10167
- if (!result) return {};
10168
- const paired = result.match(/\+(\d+)\s+-(\d+)/);
10169
- if (paired) {
10170
- return {
10171
- additions: Number(paired[1]),
10172
- deletions: Number(paired[2])
10173
- };
10174
- }
10175
- const verbose = result.match(
10176
- /(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
10177
- );
10178
- if (verbose) {
10179
- return {
10180
- additions: Number(verbose[1]),
10181
- deletions: verbose[2] != null ? Number(verbose[2]) : void 0
10182
- };
10183
- }
10184
- return {};
10185
- }
10186
- function applyAgentEvent(parts, event) {
10187
- if (event.type === "stdout") {
10188
- const data = event.data;
10189
- if (!data) return parts;
10190
- const next = [...parts];
10191
- const last = next[next.length - 1];
10192
- if (last?.type === "text") {
10193
- next[next.length - 1] = { type: "text", text: last.text + data };
10194
- } else {
10195
- next.push({ type: "text", text: data });
10196
- }
10197
- return next;
10198
- }
10199
- if (event.type === "thinking") {
10200
- const data = event.data;
10201
- if (!data) return parts;
10202
- const next = [...parts];
10203
- const last = next[next.length - 1];
10204
- if (last?.type === "thinking") {
10205
- next[next.length - 1] = { type: "thinking", text: last.text + data };
10206
- } else {
10207
- next.push({ type: "thinking", text: data });
10208
- }
10209
- return next;
10210
- }
10211
- if (event.type === "tool_use") {
10212
- const input = asRecord3(event.input);
10213
- const diff = diffFromInput(input);
10214
- const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
10215
- if (existing >= 0) {
10216
- const prev = parts[existing];
10217
- const next = [...parts];
10218
- next[existing] = {
10219
- ...prev,
10220
- name: event.name || prev.name,
10221
- input: input ?? prev.input,
10222
- description: toolDescription(event.name || prev.name, input ?? prev.input),
10223
- detail: toolDetail(event.name || prev.name, input ?? prev.input) ?? prev.detail,
10224
- filePath: toolFilePath(input) ?? prev.filePath,
10225
- additions: diff.additions ?? prev.additions,
10226
- deletions: diff.deletions ?? prev.deletions
10227
- };
10228
- return next;
10229
- }
10230
- return [
10231
- ...parts,
10232
- {
10233
- type: "tool",
10234
- id: event.id,
10235
- name: event.name,
10236
- input,
10237
- description: toolDescription(event.name, input),
10238
- detail: toolDetail(event.name, input),
10239
- status: "running",
10240
- filePath: toolFilePath(input),
10241
- ...diff
10242
- }
10243
- ];
10244
- }
10245
- if (event.type === "tool_result") {
10246
- const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
10247
- const fromResult = parseDiffStat(event.content);
10248
- if (existing < 0) {
10249
- return [
10250
- ...parts,
10251
- {
10252
- type: "tool",
10253
- id: event.id,
10254
- name: "tool",
10255
- description: "tool",
10256
- status: event.isError ? "error" : "done",
10257
- result: event.content,
10258
- ...fromResult.additions != null ? { additions: fromResult.additions } : {},
10259
- ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
10260
- }
10261
- ];
10262
- }
10263
- return parts.map((p, i) => {
10264
- if (i !== existing || p.type !== "tool") return p;
10265
- return {
10266
- ...p,
10267
- status: event.isError ? "error" : "done",
10268
- result: event.content,
10269
- ...fromResult.additions != null ? { additions: fromResult.additions } : {},
10270
- ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
10271
- };
10272
- });
10351
+ enrichPathWithNpmGlobalBin();
10352
+ let binPath = null;
10353
+ if (cliBin) {
10354
+ binPath = await whichCli(cliBin);
10273
10355
  }
10274
- return parts;
10275
- }
10276
- function partsToAssistantText(parts) {
10277
- return parts.filter((p) => p.type === "text").map((p) => p.text).join("").trim();
10278
- }
10279
- function stripBrightsyNdjsonNoise(text4) {
10280
- if (!text4 || !text4.includes('"type"')) return text4;
10281
- let out = text4;
10282
- out = out.replace(
10283
- /\{"type":"(?:tool_use|tool_result|tool|thinking|usage|done|error)"[\s\S]*?\}\s*(?=\{"type":"|$|(?=[A-Za-z*#]))/g,
10284
- ""
10285
- );
10286
- out = out.replace(/\{"type":"(?:tool_use|tool_result|tool)"[\s\S]*$/g, "");
10287
- return out.trim();
10356
+ return {
10357
+ ok: true,
10358
+ command: info.installCommand,
10359
+ exitCode: 0,
10360
+ stdout: result.stdout,
10361
+ stderr: result.stderr,
10362
+ message: binPath ? `Installed ${info.npmPackage} \u2192 ${binPath}` : `Installed ${info.npmPackage} (CLI not yet on PATH \u2014 Log in still exports Electron\u2019s PATH into Terminal)`
10363
+ };
10288
10364
  }
10289
- function isBrightsyNdjsonLine(line) {
10290
- const t = line.trim();
10291
- if (!t.startsWith("{")) return false;
10292
- return /"type"\s*:\s*"(tool_use|tool_result|tool|thinking|usage|done|error|text)"/.test(t);
10365
+ async function loginAgent(agent) {
10366
+ const info = getAgentSetupInfo(agent);
10367
+ const loginCommand = resolveLoginCommand(agent);
10368
+ if (!loginCommand) {
10369
+ return {
10370
+ ok: true,
10371
+ message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
10372
+ };
10373
+ }
10374
+ const prepared = await prepareTerminalCommand(loginCommand);
10375
+ await openInSystemTerminal(prepared);
10376
+ return {
10377
+ ok: true,
10378
+ openedTerminal: true,
10379
+ command: prepared,
10380
+ message: `Opened Terminal to run: ${prepared}`
10381
+ };
10293
10382
  }
10294
- function finalizeParts(parts) {
10295
- return parts.map(
10296
- (p) => p.type === "tool" && p.status === "running" ? { ...p, status: "done" } : p
10297
- );
10383
+ var SETUP, CLI_BIN, CLI_LOGIN_AGENTS;
10384
+ var init_install = __esm({
10385
+ "src/agents/install.ts"() {
10386
+ "use strict";
10387
+ init_run();
10388
+ init_app_settings();
10389
+ init_path();
10390
+ SETUP = {
10391
+ claude: {
10392
+ agent: "claude",
10393
+ kind: "cli",
10394
+ summary: "Install the Claude Code CLI, then complete login in a terminal.",
10395
+ docsUrl: "https://code.claude.com/docs/en/install",
10396
+ installCommand: "npm install -g @anthropic-ai/claude-code",
10397
+ loginCommand: "claude auth login",
10398
+ npmPackage: "@anthropic-ai/claude-code"
10399
+ },
10400
+ codex: {
10401
+ agent: "codex",
10402
+ kind: "cli",
10403
+ summary: "Install the Codex CLI, then run login in a terminal.",
10404
+ docsUrl: "https://github.com/openai/codex",
10405
+ installCommand: "npm install -g @openai/codex",
10406
+ loginCommand: "codex login",
10407
+ npmPackage: "@openai/codex"
10408
+ },
10409
+ opencode: {
10410
+ agent: "opencode",
10411
+ kind: "cli",
10412
+ summary: "Install OpenCode (curl installer or npm), then authenticate providers.",
10413
+ docsUrl: "https://opencode.ai/docs",
10414
+ // Prefer the official installer; npm package name is opencode-ai.
10415
+ installCommand: "curl -fsSL https://opencode.ai/install | bash",
10416
+ loginCommand: "opencode auth login",
10417
+ npmPackage: "opencode-ai@latest"
10418
+ },
10419
+ cursor: {
10420
+ agent: "cursor",
10421
+ kind: "bundled-sdk",
10422
+ summary: "No CLI install \u2014 Sideboard ships the Cursor SDK. Add a CURSOR_API_KEY from the Cursor dashboard.",
10423
+ docsUrl: "https://cursor.com/dashboard/integrations",
10424
+ installCommand: null,
10425
+ loginCommand: null
10426
+ },
10427
+ brightsy: {
10428
+ agent: "brightsy",
10429
+ kind: "cli",
10430
+ summary: "Install the Brightsy CLI, then run `brightsy login`.",
10431
+ docsUrl: "https://www.npmjs.com/package/@brightsy/cli",
10432
+ installCommand: "npm install -g @brightsy/cli",
10433
+ loginCommand: "brightsy login",
10434
+ npmPackage: "@brightsy/cli"
10435
+ }
10436
+ };
10437
+ CLI_BIN = {
10438
+ claude: "claude",
10439
+ codex: "codex",
10440
+ opencode: "opencode",
10441
+ brightsy: "brightsy"
10442
+ };
10443
+ CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
10444
+ "claude",
10445
+ "codex",
10446
+ "opencode",
10447
+ "brightsy"
10448
+ ]);
10449
+ }
10450
+ });
10451
+
10452
+ // src/agents/index.ts
10453
+ var agents_exports = {};
10454
+ __export(agents_exports, {
10455
+ CLAUDE_MODEL_CATALOG: () => CLAUDE_MODEL_CATALOG,
10456
+ ORCHESTRATOR_AGENT_KINDS: () => ORCHESTRATOR_AGENT_KINDS,
10457
+ PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
10458
+ allAdapters: () => allAdapters,
10459
+ assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
10460
+ brightsyAdapter: () => brightsyAdapter,
10461
+ claudeAdapter: () => claudeAdapter,
10462
+ codexAdapter: () => codexAdapter,
10463
+ coerceOrchestratorAgent: () => coerceOrchestratorAgent,
10464
+ conductorBundledBinDir: () => conductorBundledBinDir,
10465
+ cursorAdapter: () => cursorAdapter,
10466
+ cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
10467
+ decodeBrightsyTarget: () => decodeBrightsyTarget,
10468
+ encodeBrightsyTarget: () => encodeBrightsyTarget,
10469
+ enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
10470
+ ensureAgentPath: () => ensureAgentPath,
10471
+ getAdapter: () => getAdapter,
10472
+ getAgentSetupInfo: () => getAgentSetupInfo,
10473
+ installAgent: () => installAgent,
10474
+ isConductorBundledCli: () => isConductorBundledCli,
10475
+ isCursorAutoModel: () => isCursorAutoModel,
10476
+ isOrchestratorCapableAgent: () => isOrchestratorCapableAgent,
10477
+ isSessionQuotaLimit: () => isSessionQuotaLimit,
10478
+ listAgentSetupInfo: () => listAgentSetupInfo,
10479
+ listBrightsyChatTargets: () => listBrightsyChatTargets,
10480
+ listCodexModels: () => listCodexModels,
10481
+ listCursorModels: () => listCursorModels,
10482
+ listModelsForAgent: () => listModelsForAgent,
10483
+ listOpencodeModels: () => listOpencodeModels,
10484
+ loginAgent: () => loginAgent,
10485
+ openInSystemTerminal: () => openInSystemTerminal,
10486
+ opencodeAdapter: () => opencodeAdapter,
10487
+ parseCursorRunnerLine: () => parseCursorRunnerLine,
10488
+ parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
10489
+ permissionMode: () => permissionMode,
10490
+ posixShellSingleQuote: () => posixShellSingleQuote,
10491
+ prepareTerminalCommand: () => prepareTerminalCommand,
10492
+ resolveCommandBinarySync: () => resolveCommandBinarySync,
10493
+ resolveCursorModelId: () => resolveCursorModelId,
10494
+ resolveLoginCommand: () => resolveLoginCommand,
10495
+ resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
10496
+ withExportedPath: () => withExportedPath
10497
+ });
10498
+ function getAdapter(kind) {
10499
+ return adapters[kind];
10298
10500
  }
10299
- function normalizeParseResult(parsed) {
10300
- if (!parsed) return [];
10301
- return Array.isArray(parsed) ? parsed : [parsed];
10501
+ function allAdapters() {
10502
+ return Object.values(adapters);
10302
10503
  }
10303
- var init_message_parts = __esm({
10304
- "src/agents/message-parts.ts"() {
10504
+ var adapters;
10505
+ var init_agents = __esm({
10506
+ "src/agents/index.ts"() {
10305
10507
  "use strict";
10508
+ init_brightsy();
10509
+ init_claude();
10510
+ init_codex();
10511
+ init_cursor();
10512
+ init_opencode();
10513
+ init_types();
10514
+ init_brightsy();
10515
+ init_brightsy_targets();
10516
+ init_claude();
10517
+ init_codex();
10518
+ init_cursor();
10519
+ init_cursor_events();
10520
+ init_cursor();
10521
+ init_opencode();
10522
+ init_list_models();
10523
+ init_session_quota();
10524
+ init_orchestrator_capable();
10525
+ init_path();
10526
+ init_install();
10527
+ adapters = {
10528
+ claude: claudeAdapter,
10529
+ codex: codexAdapter,
10530
+ opencode: opencodeAdapter,
10531
+ brightsy: brightsyAdapter,
10532
+ cursor: cursorAdapter
10533
+ };
10306
10534
  }
10307
10535
  });
10308
10536
 
@@ -10310,6 +10538,9 @@ var init_message_parts = __esm({
10310
10538
  function isTextEvent(event) {
10311
10539
  return event.type === "stdout" || event.type === "thinking";
10312
10540
  }
10541
+ function parentKey(event) {
10542
+ return event.parentId ?? "";
10543
+ }
10313
10544
  function createAgentStreamCoalescer(emit, opts) {
10314
10545
  const intervalMs = opts?.intervalMs ?? 32;
10315
10546
  let pending = null;
@@ -10322,7 +10553,11 @@ function createAgentStreamCoalescer(emit, opts) {
10322
10553
  if (!pending) return;
10323
10554
  const event = pending;
10324
10555
  pending = null;
10325
- emit({ type: event.type, data: event.data });
10556
+ emit({
10557
+ type: event.type,
10558
+ data: event.data,
10559
+ ...event.parentId ? { parentId: event.parentId } : {}
10560
+ });
10326
10561
  };
10327
10562
  const schedule = () => {
10328
10563
  if (timer) return;
@@ -10337,11 +10572,15 @@ function createAgentStreamCoalescer(emit, opts) {
10337
10572
  return;
10338
10573
  }
10339
10574
  if (!event.data) return;
10340
- if (pending && pending.type === event.type) {
10575
+ if (pending && pending.type === event.type && parentKey(pending) === parentKey(event)) {
10341
10576
  pending.data += event.data;
10342
10577
  } else {
10343
10578
  flush2();
10344
- pending = { type: event.type, data: event.data };
10579
+ pending = {
10580
+ type: event.type,
10581
+ data: event.data,
10582
+ ...event.parentId ? { parentId: event.parentId } : {}
10583
+ };
10345
10584
  }
10346
10585
  schedule();
10347
10586
  },
@@ -10971,7 +11210,8 @@ function worktreeBindingFrom(from) {
10971
11210
  prState: from.prState,
10972
11211
  skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
10973
11212
  stackId: from.stackId,
10974
- stackLayer: from.stackLayer
11213
+ stackLayer: from.stackLayer,
11214
+ cowboy: from.cowboy
10975
11215
  };
10976
11216
  }
10977
11217
  function threadsSharingWorktree(worktreePath) {
@@ -12143,6 +12383,55 @@ async function createThread(input, _onSetupLine) {
12143
12383
  if (!(0, import_node_fs34.existsSync)(repoPath)) {
12144
12384
  throw new Error(`Repo not found: ${repoPath}`);
12145
12385
  }
12386
+ if (input.cowboy) {
12387
+ const { cowboyModeEnabled: cowboyModeEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
12388
+ if (!cowboyModeEnabled2()) {
12389
+ throw new Error(
12390
+ "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
12391
+ );
12392
+ }
12393
+ if (input.sourceType === "pr" || input.sourceType === "ticket" || input.sourceType === "adopt") {
12394
+ throw new Error(
12395
+ "Cowboy mode works on the project folder (default branch), not a PR, ticket, or adopt."
12396
+ );
12397
+ }
12398
+ const defaultBranch = await resolveDefaultBranch(repoPath, { network: false });
12399
+ const head = await currentBranch(repoPath);
12400
+ if (head === "HEAD") {
12401
+ throw new Error(
12402
+ "Cowboy mode needs a named branch in the project folder (not a detached HEAD)."
12403
+ );
12404
+ }
12405
+ if (head !== defaultBranch) {
12406
+ throw new Error(
12407
+ `Cowboy mode uses ${defaultBranch} in the project folder. Switch that checkout to ${defaultBranch} first (currently ${head}).`
12408
+ );
12409
+ }
12410
+ const explicitTitle2 = input.title?.trim();
12411
+ const thread2 = createEmptyThread({
12412
+ title: explicitTitle2 || `Cowboy \xB7 ${head}`,
12413
+ userSetTitle: Boolean(explicitTitle2),
12414
+ sourceType: "branch",
12415
+ sourceRef: head,
12416
+ branchName: head,
12417
+ worktreePath: repoPath,
12418
+ repoPath,
12419
+ agent: resolved.agent,
12420
+ autonomy: input.autonomy ?? "default",
12421
+ model: resolved.model,
12422
+ effort: resolved.effort,
12423
+ fast: resolved.fast,
12424
+ planMode: Boolean(input.planMode),
12425
+ attachments: input.attachments ?? [],
12426
+ sourceIsFork: false,
12427
+ parentThreadId: input.parentThreadId ?? null,
12428
+ status: "idle",
12429
+ cowboy: true
12430
+ });
12431
+ writeThread(thread2);
12432
+ await ensureWorkspace(repoPath);
12433
+ return readThread(thread2.id) ?? thread2;
12434
+ }
12146
12435
  let sourceRef = input.sourceRef;
12147
12436
  let sourceIsFork = false;
12148
12437
  let prUrl = null;
@@ -12228,6 +12517,24 @@ var init_create = __esm({
12228
12517
  }
12229
12518
  });
12230
12519
 
12520
+ // src/threads/cowboy.ts
12521
+ function isCowboyThread(thread) {
12522
+ return Boolean(thread?.cowboy);
12523
+ }
12524
+ function isPrimaryCheckoutThread(thread) {
12525
+ if (!thread?.worktreePath || !thread.repoPath) return false;
12526
+ return normalizeWorktreePath(thread.worktreePath) === normalizeWorktreePath(thread.repoPath);
12527
+ }
12528
+ function shouldRemoveWorktreeOnTeardown(thread) {
12529
+ return !isCowboyThread(thread) && !isPrimaryCheckoutThread(thread);
12530
+ }
12531
+ var init_cowboy = __esm({
12532
+ "src/threads/cowboy.ts"() {
12533
+ "use strict";
12534
+ init_worktree_labels();
12535
+ }
12536
+ });
12537
+
12231
12538
  // src/store/turn-live.ts
12232
12539
  function trimParts(parts) {
12233
12540
  if (parts.length <= MAX_PARTS) return parts;
@@ -12521,8 +12828,12 @@ var init_quota_failover = __esm({
12521
12828
  });
12522
12829
 
12523
12830
  // src/threads/adopt.ts
12831
+ function thisModuleFile() {
12832
+ const cjsFile = typeof __filename !== "undefined" ? __filename : "";
12833
+ return cjsFile || process.argv[1] || (0, import_node_path33.join)(process.cwd(), "package.json");
12834
+ }
12524
12835
  function openReadonlySqlite(file) {
12525
- const req = (0, import_node_module4.createRequire)(import_meta4.url);
12836
+ const req = (0, import_node_module4.createRequire)(thisModuleFile());
12526
12837
  const Database = req("better-sqlite3");
12527
12838
  return new Database(file, { readonly: true, fileMustExist: true });
12528
12839
  }
@@ -12791,7 +13102,7 @@ function importConductorWorkspace(workspaceId) {
12791
13102
  async function importConductorWorkspaceAsync(workspaceId) {
12792
13103
  return importConductorWorkspace(workspaceId);
12793
13104
  }
12794
- var import_node_child_process4, import_node_fs36, import_node_os10, import_node_path33, import_node_module4, import_meta4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
13105
+ var import_node_child_process4, import_node_fs36, import_node_os10, import_node_path33, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
12795
13106
  var init_adopt = __esm({
12796
13107
  "src/threads/adopt.ts"() {
12797
13108
  "use strict";
@@ -12802,7 +13113,6 @@ var init_adopt = __esm({
12802
13113
  import_node_module4 = require("module");
12803
13114
  init_worktree();
12804
13115
  init_thread_store();
12805
- import_meta4 = {};
12806
13116
  CONDUCTOR_APP_SUPPORT = (0, import_node_path33.join)(
12807
13117
  process.env.HOME ?? "",
12808
13118
  "Library",
@@ -13883,13 +14193,22 @@ async function previewLand(thread) {
13883
14193
  isFork: true
13884
14194
  };
13885
14195
  }
13886
- const target = await resolveDefaultBranch(thread.repoPath);
13887
- if (thread.branchName === target || thread.branchName === "main" || thread.branchName === "master") {
14196
+ if (isCowboyThread(thread)) {
14197
+ const current2 = await currentBranch(thread.worktreePath);
14198
+ const dirty = await isDirty(thread.worktreePath);
14199
+ const diff2 = await getDiff(thread.worktreePath, thread.repoPath, { base: current2 });
14200
+ return {
14201
+ branch: current2,
14202
+ target: current2,
14203
+ diffStat: diff2.stat,
14204
+ dirty,
14205
+ blocked: false,
14206
+ isFork: false,
14207
+ cowboy: true
14208
+ };
13888
14209
  }
13889
- const { stdout: head } = await Promise.resolve().then(() => (init_run(), run_exports)).then(
13890
- ({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], thread.worktreePath)
13891
- );
13892
- const current = head.trim();
14210
+ const target = await resolveDefaultBranch(thread.repoPath);
14211
+ const current = await currentBranch(thread.worktreePath);
13893
14212
  if (current === target) {
13894
14213
  return {
13895
14214
  branch: current,
@@ -13916,6 +14235,19 @@ async function confirmLand(thread, opts) {
13916
14235
  if (preview.blocked) {
13917
14236
  throw new Error(preview.blockReason ?? "Land blocked");
13918
14237
  }
14238
+ if (preview.cowboy) {
14239
+ const meta2 = await suggestPrMetadata(thread.worktreePath, {
14240
+ base: preview.branch,
14241
+ fallbackTitle: thread.title,
14242
+ sourceLabel: `${thread.sourceType}:${thread.sourceRef}`
14243
+ });
14244
+ let committed2 = false;
14245
+ if (preview.dirty) {
14246
+ committed2 = await commitAll(thread.worktreePath, meta2.commitMessage);
14247
+ }
14248
+ await pushBranch(thread.worktreePath, preview.branch);
14249
+ return { prUrl: null, pushed: true, committed: committed2 };
14250
+ }
13919
14251
  const meta = await suggestPrMetadata(thread.worktreePath, {
13920
14252
  base: preview.target,
13921
14253
  fallbackTitle: thread.title,
@@ -13960,6 +14292,7 @@ var init_land = __esm({
13960
14292
  init_diff();
13961
14293
  init_pr_metadata();
13962
14294
  init_gh_errors();
14295
+ init_cowboy();
13963
14296
  }
13964
14297
  });
13965
14298
 
@@ -14649,7 +14982,7 @@ var init_instructions = __esm({
14649
14982
  });
14650
14983
 
14651
14984
  // src/plan/plan-present.ts
14652
- function asRecord4(v) {
14985
+ function asRecord5(v) {
14653
14986
  return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
14654
14987
  }
14655
14988
  function isPresentPlanToolName(name) {
@@ -14661,7 +14994,7 @@ function extractPresentedPlan(parts) {
14661
14994
  for (let i = parts.length - 1; i >= 0; i--) {
14662
14995
  const p = parts[i];
14663
14996
  if (p.type !== "tool" || !isPresentPlanToolName(p.name)) continue;
14664
- const input = asRecord4(p.input) ?? {};
14997
+ const input = asRecord5(p.input) ?? {};
14665
14998
  const content = typeof input.content === "string" ? input.content : typeof input.plan === "string" ? input.plan : typeof input.markdown === "string" ? input.markdown : "";
14666
14999
  if (!content.trim()) continue;
14667
15000
  const title = typeof input.title === "string" && input.title.trim() ? input.title.trim() : "Plan";
@@ -14992,6 +15325,7 @@ var init_orchestrator = __esm({
14992
15325
  init_thread_store();
14993
15326
  init_desktop_host();
14994
15327
  init_create();
15328
+ init_cowboy();
14995
15329
  init_orchestrator_capable();
14996
15330
  init_chat_tabs();
14997
15331
  init_enqueue_by_key();
@@ -15268,7 +15602,9 @@ var init_orchestrator = __esm({
15268
15602
  return thread;
15269
15603
  }
15270
15604
  async finishCreateThread(threadId, prompt) {
15271
- const setup = this.runSetupAfterCreate(threadId);
15605
+ const created = this.getThread(threadId);
15606
+ const skipSetup = isCowboyThread(created);
15607
+ const setup = skipSetup ? Promise.resolve() : this.runSetupAfterCreate(threadId);
15272
15608
  if (prompt) {
15273
15609
  try {
15274
15610
  await this.send(threadId, prompt);
@@ -15280,6 +15616,7 @@ var init_orchestrator = __esm({
15280
15616
  }
15281
15617
  }
15282
15618
  await setup;
15619
+ if (skipSetup) return;
15283
15620
  const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
15284
15621
  if (autoRunAfterSetupEnabled2()) {
15285
15622
  try {
@@ -16611,17 +16948,19 @@ var init_orchestrator = __esm({
16611
16948
  const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
16612
16949
  if (siblings.length === 0) {
16613
16950
  this.stopDev(thread.id);
16614
- try {
16615
- await runArchiveScript(thread.repoPath, thread.worktreePath, (line) => {
16616
- this.emit({
16617
- type: "turn_output",
16618
- threadId: thread.id,
16619
- event: { type: "stdout", data: `[archive] ${line}` }
16951
+ if (shouldRemoveWorktreeOnTeardown(thread)) {
16952
+ try {
16953
+ await runArchiveScript(thread.repoPath, thread.worktreePath, (line) => {
16954
+ this.emit({
16955
+ type: "turn_output",
16956
+ threadId: thread.id,
16957
+ event: { type: "stdout", data: `[archive] ${line}` }
16958
+ });
16620
16959
  });
16621
- });
16622
- } catch {
16960
+ } catch {
16961
+ }
16962
+ await removeWorktree(thread.repoPath, thread.worktreePath);
16623
16963
  }
16624
- await removeWorktree(thread.repoPath, thread.worktreePath);
16625
16964
  }
16626
16965
  const archived = setStatus(thread.id, "archived");
16627
16966
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
@@ -16649,15 +16988,17 @@ var init_orchestrator = __esm({
16649
16988
  const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
16650
16989
  if (siblings.length === 0) {
16651
16990
  this.stopDev(thread.id);
16652
- try {
16653
- await runArchiveScript(thread.repoPath, thread.worktreePath);
16654
- } catch {
16991
+ if (shouldRemoveWorktreeOnTeardown(thread)) {
16992
+ try {
16993
+ await runArchiveScript(thread.repoPath, thread.worktreePath);
16994
+ } catch {
16995
+ }
16996
+ const { deleteBranchOnPurgeEnabled: deleteBranchOnPurgeEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
16997
+ const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled2();
16998
+ await removeWorktree(thread.repoPath, thread.worktreePath, {
16999
+ deleteBranch: deleteBranch ? thread.branchName : void 0
17000
+ });
16655
17001
  }
16656
- const { deleteBranchOnPurgeEnabled: deleteBranchOnPurgeEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
16657
- const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled2();
16658
- await removeWorktree(thread.repoPath, thread.worktreePath, {
16659
- deleteBranch: deleteBranch ? thread.branchName : void 0
16660
- });
16661
17002
  }
16662
17003
  deleteThreadRecord(thread.id);
16663
17004
  }
@@ -16674,6 +17015,11 @@ var init_orchestrator = __esm({
16674
17015
  return restored2;
16675
17016
  }
16676
17017
  if (!(0, import_node_fs44.existsSync)(thread.worktreePath)) {
17018
+ if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
17019
+ throw new Error(
17020
+ `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
17021
+ );
17022
+ }
16677
17023
  const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
16678
17024
  const slug = thread.worktreePath.split("/").pop();
16679
17025
  const dest = thread.worktreePath;
@@ -17010,6 +17356,7 @@ __export(index_exports, {
17010
17356
  coordinatorTurnReminder: () => coordinatorTurnReminder,
17011
17357
  copyConfiguredFiles: () => copyConfiguredFiles,
17012
17358
  countCacheControlBlocks: () => countCacheControlBlocks,
17359
+ cowboyModeEnabled: () => cowboyModeEnabled,
17013
17360
  createChatTab: () => createChatTab,
17014
17361
  createEmptyThread: () => createEmptyThread,
17015
17362
  createExistingBranchWorktree: () => createExistingBranchWorktree,
@@ -17160,6 +17507,7 @@ __export(index_exports, {
17160
17507
  isBrightsyNdjsonLine: () => isBrightsyNdjsonLine,
17161
17508
  isCloudCoordinatorThread: () => isCloudCoordinatorThread,
17162
17509
  isConductorBundledCli: () => isConductorBundledCli,
17510
+ isCowboyThread: () => isCowboyThread,
17163
17511
  isCursorAutoModel: () => isCursorAutoModel,
17164
17512
  isDefaultishSourceRef: () => isDefaultishSourceRef,
17165
17513
  isDesktopHostAlive: () => isDesktopHostAlive,
@@ -17178,11 +17526,13 @@ __export(index_exports, {
17178
17526
  isPlaceholderBranch: () => isPlaceholderBranch,
17179
17527
  isPrNotMergeableError: () => isPrNotMergeableError,
17180
17528
  isPresentPlanToolName: () => isPresentPlanToolName,
17529
+ isPrimaryCheckoutThread: () => isPrimaryCheckoutThread,
17181
17530
  isSessionQuotaLimit: () => isSessionQuotaLimit,
17182
17531
  isSideboardScratchPath: () => isSideboardScratchPath,
17183
17532
  isSlackCoordinatorThread: () => isSlackCoordinatorThread,
17184
17533
  isSlackExternalReplyPrompt: () => isSlackExternalReplyPrompt,
17185
17534
  isSlackOAuthCancelled: () => isSlackOAuthCancelled,
17535
+ isSubagentToolName: () => isSubagentToolName,
17186
17536
  isThinkingEffort: () => isThinkingEffort,
17187
17537
  isThisProcessDesktopHost: () => isThisProcessDesktopHost,
17188
17538
  isThreadCaffeinated: () => isThreadCaffeinated,
@@ -17237,6 +17587,7 @@ __export(index_exports, {
17237
17587
  mergePrStack: () => mergePrStack,
17238
17588
  mergeSideboardIntoMcpServersJson: () => mergeSideboardIntoMcpServersJson,
17239
17589
  mergeUsage: () => mergeUsage,
17590
+ messagePartParentId: () => messagePartParentId,
17240
17591
  nextPastedTextName: () => nextPastedTextName,
17241
17592
  nextThinkingEffort: () => nextThinkingEffort,
17242
17593
  nonInteractiveGitProcessEnv: () => nonInteractiveGitProcessEnv,
@@ -17355,6 +17706,7 @@ __export(index_exports, {
17355
17706
  shouldCompactContext: () => shouldCompactContext,
17356
17707
  shouldInjectBrightsyMcp: () => shouldInjectBrightsyMcp,
17357
17708
  shouldRefreshReviewRequestTemplate: () => shouldRefreshReviewRequestTemplate,
17709
+ shouldRemoveWorktreeOnTeardown: () => shouldRemoveWorktreeOnTeardown,
17358
17710
  shouldResetSessionForOccupancy: () => shouldResetSessionForOccupancy,
17359
17711
  shouldRunWorktreeCleanup: () => shouldRunWorktreeCleanup,
17360
17712
  sideboardHomeDir: () => sideboardHomeDir,
@@ -17425,6 +17777,8 @@ __export(index_exports, {
17425
17777
  waitForPidExit: () => waitForPidExit,
17426
17778
  warmGithubAgentAuth: () => warmGithubAgentAuth,
17427
17779
  withAgentInstructions: () => withAgentInstructions,
17780
+ withEventParentId: () => withEventParentId,
17781
+ withEventsParentId: () => withEventsParentId,
17428
17782
  withExportedPath: () => withExportedPath,
17429
17783
  withThreadLock: () => withThreadLock,
17430
17784
  workspaceSettingsSourceLabel: () => workspaceSettingsSourceLabel,
@@ -18278,6 +18632,7 @@ init_context_compact();
18278
18632
  init_summarize();
18279
18633
  init_land();
18280
18634
  init_create();
18635
+ init_cowboy();
18281
18636
  init_chat_tabs();
18282
18637
  init_fork_worktree();
18283
18638
  init_stack_layers();
@@ -18287,7 +18642,7 @@ init_request_review();
18287
18642
  init_workspace_scratch();
18288
18643
 
18289
18644
  // src/plan/ask-user.ts
18290
- function asRecord5(v) {
18645
+ function asRecord6(v) {
18291
18646
  return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
18292
18647
  }
18293
18648
  function parseOptions(raw) {
@@ -18298,7 +18653,7 @@ function parseOptions(raw) {
18298
18653
  out.push({ label: item.trim() });
18299
18654
  continue;
18300
18655
  }
18301
- const o = asRecord5(item);
18656
+ const o = asRecord6(item);
18302
18657
  if (!o) continue;
18303
18658
  const label = typeof o.label === "string" ? o.label.trim() : typeof o.text === "string" ? o.text.trim() : typeof o.title === "string" ? o.title.trim() : "";
18304
18659
  if (!label) continue;
@@ -18308,7 +18663,7 @@ function parseOptions(raw) {
18308
18663
  return out;
18309
18664
  }
18310
18665
  function parseOneQuestion(raw) {
18311
- const o = asRecord5(raw);
18666
+ const o = asRecord6(raw);
18312
18667
  if (!o) return null;
18313
18668
  const question = typeof o.question === "string" ? o.question.trim() : typeof o.text === "string" ? o.text.trim() : typeof o.prompt === "string" ? o.prompt.trim() : "";
18314
18669
  if (!question) return null;
@@ -18319,7 +18674,7 @@ function parseOneQuestion(raw) {
18319
18674
  return { question, header, multiSelect, options };
18320
18675
  }
18321
18676
  function parsePlanQuestionsInput(input) {
18322
- const root = asRecord5(input);
18677
+ const root = asRecord6(input);
18323
18678
  if (!root) return [];
18324
18679
  const list = Array.isArray(root.questions) ? root.questions : Array.isArray(root.question) ? root.question : root.question || root.prompt ? [root] : [];
18325
18680
  const out = [];
@@ -19488,7 +19843,7 @@ async function startMcpServer() {
19488
19843
  );
19489
19844
  server.tool(
19490
19845
  "create_thread",
19491
- `Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn. Then use send_to_thread to chat.`,
19846
+ `Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Then use send_to_thread to chat.`,
19492
19847
  {
19493
19848
  sourceType: import_zod4.z.enum(["branch", "pr", "ticket"]),
19494
19849
  sourceRef: import_zod4.z.string(),
@@ -19498,6 +19853,9 @@ async function startMcpServer() {
19498
19853
  ),
19499
19854
  repoPath: import_zod4.z.string(),
19500
19855
  title: import_zod4.z.string().optional(),
19856
+ cowboy: import_zod4.z.boolean().optional().describe(
19857
+ "If true, work in the project folder on the default branch (no thread/* worktree). Requires Settings \u2192 Advanced \u2192 Cowboy mode. Land is commit+push to that branch. Archive does not delete the folder."
19858
+ ),
19501
19859
  parentThreadId: import_zod4.z.string().optional().describe(
19502
19860
  "Orchestration: omit (preferred) or pass YOUR chat id from the turn reminder / AGENTS.md. Do not invent uuids."
19503
19861
  )
@@ -19558,7 +19916,8 @@ async function startMcpServer() {
19558
19916
  fast: opts.fast,
19559
19917
  repoPath: args.repoPath,
19560
19918
  title: args.title,
19561
- parentThreadId: parentId || null
19919
+ parentThreadId: parentId || null,
19920
+ cowboy: args.cowboy || void 0
19562
19921
  }),
19563
19922
  CREATE_THREAD_TIMEOUT_MS,
19564
19923
  "create_thread"
@@ -19576,6 +19935,7 @@ async function startMcpServer() {
19576
19935
  agent: thread.agent,
19577
19936
  model: thread.model,
19578
19937
  status: thread.status,
19938
+ cowboy: Boolean(thread.cowboy),
19579
19939
  link: `sideboard://thread/${thread.id}`,
19580
19940
  parentThreadId: thread.parentThreadId,
19581
19941
  ...agentCoercedFrom ? {
@@ -22741,6 +23101,7 @@ init_outbound_watch();
22741
23101
  coordinatorTurnReminder,
22742
23102
  copyConfiguredFiles,
22743
23103
  countCacheControlBlocks,
23104
+ cowboyModeEnabled,
22744
23105
  createChatTab,
22745
23106
  createEmptyThread,
22746
23107
  createExistingBranchWorktree,
@@ -22891,6 +23252,7 @@ init_outbound_watch();
22891
23252
  isBrightsyNdjsonLine,
22892
23253
  isCloudCoordinatorThread,
22893
23254
  isConductorBundledCli,
23255
+ isCowboyThread,
22894
23256
  isCursorAutoModel,
22895
23257
  isDefaultishSourceRef,
22896
23258
  isDesktopHostAlive,
@@ -22909,11 +23271,13 @@ init_outbound_watch();
22909
23271
  isPlaceholderBranch,
22910
23272
  isPrNotMergeableError,
22911
23273
  isPresentPlanToolName,
23274
+ isPrimaryCheckoutThread,
22912
23275
  isSessionQuotaLimit,
22913
23276
  isSideboardScratchPath,
22914
23277
  isSlackCoordinatorThread,
22915
23278
  isSlackExternalReplyPrompt,
22916
23279
  isSlackOAuthCancelled,
23280
+ isSubagentToolName,
22917
23281
  isThinkingEffort,
22918
23282
  isThisProcessDesktopHost,
22919
23283
  isThreadCaffeinated,
@@ -22968,6 +23332,7 @@ init_outbound_watch();
22968
23332
  mergePrStack,
22969
23333
  mergeSideboardIntoMcpServersJson,
22970
23334
  mergeUsage,
23335
+ messagePartParentId,
22971
23336
  nextPastedTextName,
22972
23337
  nextThinkingEffort,
22973
23338
  nonInteractiveGitProcessEnv,
@@ -23086,6 +23451,7 @@ init_outbound_watch();
23086
23451
  shouldCompactContext,
23087
23452
  shouldInjectBrightsyMcp,
23088
23453
  shouldRefreshReviewRequestTemplate,
23454
+ shouldRemoveWorktreeOnTeardown,
23089
23455
  shouldResetSessionForOccupancy,
23090
23456
  shouldRunWorktreeCleanup,
23091
23457
  sideboardHomeDir,
@@ -23156,6 +23522,8 @@ init_outbound_watch();
23156
23522
  waitForPidExit,
23157
23523
  warmGithubAgentAuth,
23158
23524
  withAgentInstructions,
23525
+ withEventParentId,
23526
+ withEventsParentId,
23159
23527
  withExportedPath,
23160
23528
  withThreadLock,
23161
23529
  workspaceSettingsSourceLabel,