@sideboard-ai/core 0.1.107 → 0.1.110

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 (44) hide show
  1. package/dist/agents/cursor-runner.cjs +87 -12
  2. package/dist/agents/cursor-runner.js +38 -12
  3. package/dist/{agents-T4RHL5UX.js → agents-MQDW3YXL.js} +6 -6
  4. package/dist/{agents-4XQANGFO.js → agents-WK54VP7J.js} +8 -8
  5. package/dist/{app-settings-2WH6DVOW.js → app-settings-5XAGNDX7.js} +3 -1
  6. package/dist/{app-settings-6AXBWM3K.js → app-settings-J4LUWIRN.js} +4 -2
  7. package/dist/{chunk-HUKCGRAT.js → chunk-3UOKB6VQ.js} +47 -2
  8. package/dist/{chunk-SMWVSSE5.js → chunk-4EWPKYOU.js} +4 -4
  9. package/dist/{chunk-7ZTQHC2Q.js → chunk-4NR5FL46.js} +11 -1
  10. package/dist/{chunk-TLPJHLLM.js → chunk-4TR3HZFT.js} +1 -1
  11. package/dist/{chunk-VTTTV2LM.js → chunk-7KWYXGIU.js} +2 -2
  12. package/dist/{chunk-KGSVLZV6.js → chunk-A4VZXJEJ.js} +2 -0
  13. package/dist/{chunk-5XUKY2JY.js → chunk-AROMOP3C.js} +8 -16
  14. package/dist/{chunk-PZVA2VDF.js → chunk-C4KHDW3U.js} +2 -2
  15. package/dist/{chunk-3SIFRHJ3.js → chunk-EAAB4EK5.js} +1597 -1704
  16. package/dist/{chunk-GYFNFU62.js → chunk-KQBI5HNT.js} +8 -16
  17. package/dist/{chunk-P3BQ5DOL.js → chunk-KYOTBZ6S.js} +2 -0
  18. package/dist/{chunk-6HRR4T4P.js → chunk-RSIWPLRG.js} +483 -46
  19. package/dist/{chunk-EX4NZN3O.js → chunk-SGEVS5SY.js} +11 -1
  20. package/dist/{chunk-THXSFETX.js → chunk-VOD3HFLP.js} +4 -4
  21. package/dist/{chunk-XOYH3OMI.js → chunk-VOJSO3RM.js} +484 -55
  22. package/dist/{chunk-MMI4RJ5I.js → chunk-WIHKHR5R.js} +14 -3
  23. package/dist/{chunk-XEFHG6VG.js → chunk-XOZDAVOP.js} +1449 -1518
  24. package/dist/{chunk-LRO7YVLJ.js → chunk-YFAXVUY2.js} +2 -2
  25. package/dist/{chunk-6JJTMI7G.js → chunk-YXDR43ZC.js} +2 -2
  26. package/dist/{coordinator-prompt-4TUQUEHY.js → coordinator-prompt-AR66L3N4.js} +5 -5
  27. package/dist/{coordinator-prompt-YQWRXCPX.js → coordinator-prompt-BHMLWL64.js} +4 -4
  28. package/dist/{global-workspace-H37LFFXI.js → global-workspace-SKFODUQQ.js} +5 -5
  29. package/dist/{global-workspace-V6TMECDU.js → global-workspace-XSUFEIAQ.js} +6 -6
  30. package/dist/index.cjs +2388 -2006
  31. package/dist/index.d.cts +115 -26
  32. package/dist/index.d.ts +115 -26
  33. package/dist/index.js +141 -98
  34. package/dist/mcp/run-stdio.cjs +2354 -1988
  35. package/dist/mcp/run-stdio.js +90 -82
  36. package/dist/{orchestrator-DEHSKERK.js → orchestrator-FCZVCKBK.js} +11 -11
  37. package/dist/{orchestrator-2P7DX44Q.js → orchestrator-SCATSB3O.js} +8 -8
  38. package/dist/{thread-store-DQJGDKIJ.js → thread-store-LPTBVW5C.js} +1 -1
  39. package/dist/{thread-store-4OUEQ2DB.js → thread-store-OEALWU7Y.js} +1 -1
  40. package/dist/{workspaces-UPEVANU4.js → workspaces-HV3J4TTW.js} +7 -7
  41. package/dist/{workspaces-JU3P6FHB.js → workspaces-XAQVKTLO.js} +6 -6
  42. package/dist/{worktree-6MFKE465.js → worktree-N2EV24EE.js} +3 -3
  43. package/dist/{worktree-NR5YJG2E.js → worktree-XFJED3VU.js} +4 -4
  44. package/package.json +1 -1
@@ -9,13 +9,13 @@ import {
9
9
  } from "./chunk-7YKXHBIW.js";
10
10
  import {
11
11
  isOrchestratorThread
12
- } from "./chunk-THXSFETX.js";
12
+ } from "./chunk-VOD3HFLP.js";
13
13
  import {
14
14
  codexUnattendedGitConfigArgs,
15
15
  mergeAgentGitAuthEnv,
16
16
  resolveAgentGitAuthEnv,
17
17
  resolveCodexGitWritableRoots
18
- } from "./chunk-6JJTMI7G.js";
18
+ } from "./chunk-YXDR43ZC.js";
19
19
  import {
20
20
  claudeChromeEnabled,
21
21
  isElectronLikeCommand,
@@ -24,7 +24,7 @@ import {
24
24
  resolveClaudeExecutable,
25
25
  unwrapStrippedElectronLaunch,
26
26
  wrapElectronAsNodeLaunch
27
- } from "./chunk-EX4NZN3O.js";
27
+ } from "./chunk-SGEVS5SY.js";
28
28
  import {
29
29
  appDataDir
30
30
  } from "./chunk-BD2ICC4D.js";
@@ -78,6 +78,10 @@ function applyTurnUsage(current, incoming, scope = "request") {
78
78
  const merged = mergeUsage(current, incoming);
79
79
  return { ...merged, lastRequestTokens: requestOccupancy(incoming) };
80
80
  }
81
+ function contextTokens(u) {
82
+ if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
83
+ return requestOccupancy(u);
84
+ }
81
85
 
82
86
  // src/agents/brightsy-targets.ts
83
87
  function encodeBrightsyTarget(type, id, accountId) {
@@ -197,6 +201,8 @@ function summarizeTurnStderr(tail, maxChars = 500) {
197
201
  if (tail.length === 0) return "";
198
202
  const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
199
203
  if (cursorStartup) return clipStderr(cursorStartup, maxChars);
204
+ const cursorRunFailed = [...tail].reverse().find((line) => /^cursor run failed\b/i.test(line.trim()));
205
+ if (cursorRunFailed) return clipStderr(cursorRunFailed, maxChars);
200
206
  if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
201
207
  if (tail.some(looksLikeHomebrewLibuvCrash)) return HOMEBREW_LIBUV_SUMMARY;
202
208
  if (tail.some(
@@ -227,7 +233,7 @@ function looksLikeRetryableRunnerCrash(text) {
227
233
  const lower = text.trim().toLowerCase();
228
234
  if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
229
235
  if (!lower) return true;
230
- return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
236
+ 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(
231
237
  lower
232
238
  );
233
239
  }
@@ -285,6 +291,9 @@ function humanizeAgentFailDetail(detail) {
285
291
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
286
292
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
287
293
  }
294
+ if (/connection stalled/.test(lower)) {
295
+ return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
296
+ }
288
297
  return raw;
289
298
  }
290
299
  function turnFailChatText(opts) {
@@ -659,6 +668,291 @@ function mcpAllowTools(servers) {
659
668
  return out;
660
669
  }
661
670
 
671
+ // src/agents/message-parts.ts
672
+ function asRecord(input) {
673
+ if (input && typeof input === "object" && !Array.isArray(input)) {
674
+ return input;
675
+ }
676
+ return void 0;
677
+ }
678
+ function str(v) {
679
+ return typeof v === "string" && v.trim() ? v : void 0;
680
+ }
681
+ function toolDetail(name, input) {
682
+ if (!input) return void 0;
683
+ const command = str(input.command) ?? str(input.cmd);
684
+ if (command) return command;
685
+ const path = str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
686
+ if (path) return path;
687
+ const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
688
+ if (pattern) return pattern;
689
+ const query = str(input.query) ?? str(input.prompt);
690
+ if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
691
+ try {
692
+ const raw = JSON.stringify(input);
693
+ return raw.length > 80 ? `${raw.slice(0, 77)}\u2026` : raw;
694
+ } catch {
695
+ return name;
696
+ }
697
+ }
698
+ function toolDescription(name, input) {
699
+ const n = name.replace(/^mcp__/, "").replace(/__/g, " \xB7 ");
700
+ if (/^get_record_types$|recordTypes/i.test(name)) return "List record types";
701
+ if (/connectedAgentRequest/i.test(name)) {
702
+ return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
703
+ }
704
+ if (/present_artifact$/i.test(name)) {
705
+ return str(input?.title) ? `Present ${str(input?.title)}` : "Present artifact";
706
+ }
707
+ if (/present_plan$/i.test(name)) {
708
+ return str(input?.title) ? `Plan ${str(input?.title)}` : "Present plan";
709
+ }
710
+ if (/present_schema$/i.test(name)) {
711
+ return str(input?.title) ? `Schema ${str(input?.title)}` : "Present schema";
712
+ }
713
+ if (/present_files$/i.test(name)) {
714
+ return str(input?.title) ? `Files ${str(input?.title)}` : "Present files";
715
+ }
716
+ if (isSubagentToolName(name)) {
717
+ const desc = str(input?.description);
718
+ const sub = asRecord(input?.subagentType);
719
+ const kind = str(sub?.name) ?? str(sub?.kind) ?? str(input?.subagent_type) ?? str(input?.subagentType);
720
+ if (/^spawn_agent$/i.test(name)) {
721
+ return str(input?.prompt) ?? desc ?? "Subagent";
722
+ }
723
+ if (/connectedAgentRequest/i.test(name)) {
724
+ return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
725
+ }
726
+ if (desc && kind) return `${kind}: ${desc}`;
727
+ if (desc) return desc;
728
+ return "Subagent";
729
+ }
730
+ if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
731
+ return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
732
+ }
733
+ if (!input) return n;
734
+ if (/bash|shell|terminal/i.test(name) && str(input.command)) {
735
+ const cmd = str(input.command);
736
+ if (/git\s+fetch/i.test(cmd)) return "Fetch latest from origin and check status";
737
+ if (/git\s+status/i.test(cmd)) return "Check git status";
738
+ if (/git\s+log/i.test(cmd)) return "Inspect recent commits";
739
+ if (/git\s+branch/i.test(cmd)) return "List branches";
740
+ if (/grep|rg\b/i.test(cmd)) return "Search repository";
741
+ return "Run shell command";
742
+ }
743
+ if (/edit|write|apply/i.test(name)) {
744
+ const path = str(input.file_path) ?? str(input.path);
745
+ return path ? `Edit ${path.split("/").pop()}` : "Edit file";
746
+ }
747
+ if (/read/i.test(name)) {
748
+ const path = str(input.file_path) ?? str(input.path);
749
+ return path ? `Read ${path.split("/").pop()}` : "Read file";
750
+ }
751
+ if (/grep/i.test(name)) return "Search files";
752
+ if (/glob/i.test(name)) return "Find files";
753
+ return n;
754
+ }
755
+ function isSubagentToolName(name) {
756
+ const n = (name ?? "").trim();
757
+ if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
758
+ return /connectedAgentRequest/i.test(n);
759
+ }
760
+ function messagePartParentId(part) {
761
+ if ("parentId" in part && typeof part.parentId === "string" && part.parentId.trim()) {
762
+ return part.parentId;
763
+ }
764
+ return void 0;
765
+ }
766
+ function sameParentId(a, b) {
767
+ return (a ?? "") === (b ?? "");
768
+ }
769
+ function withEventParentId(event, parentId) {
770
+ if (!parentId) return event;
771
+ if (event.type === "stdout" || event.type === "thinking" || event.type === "tool_use" || event.type === "tool_result") {
772
+ return { ...event, parentId: event.parentId ?? parentId };
773
+ }
774
+ return event;
775
+ }
776
+ function toolFilePath(input) {
777
+ if (!input) return void 0;
778
+ return str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
779
+ }
780
+ function countLines(text) {
781
+ if (!text) return 0;
782
+ return text.split("\n").length;
783
+ }
784
+ function diffFromInput(input) {
785
+ if (!input) return {};
786
+ const oldS = str(input.old_string) ?? str(input.oldString);
787
+ const newS = str(input.new_string) ?? str(input.newString) ?? str(input.content);
788
+ if (oldS != null || newS != null) {
789
+ return {
790
+ additions: countLines(newS),
791
+ deletions: countLines(oldS)
792
+ };
793
+ }
794
+ return {};
795
+ }
796
+ function parseDiffStat(result) {
797
+ if (!result) return {};
798
+ const paired = result.match(/\+(\d+)\s+-(\d+)/);
799
+ if (paired) {
800
+ return {
801
+ additions: Number(paired[1]),
802
+ deletions: Number(paired[2])
803
+ };
804
+ }
805
+ const verbose = result.match(
806
+ /(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
807
+ );
808
+ if (verbose) {
809
+ return {
810
+ additions: Number(verbose[1]),
811
+ deletions: verbose[2] != null ? Number(verbose[2]) : void 0
812
+ };
813
+ }
814
+ return {};
815
+ }
816
+ function applyAgentEvent(parts, event) {
817
+ if (event.type === "stdout") {
818
+ const data = event.data;
819
+ if (!data) return parts;
820
+ const next = [...parts];
821
+ const last = next[next.length - 1];
822
+ if (last?.type === "text" && sameParentId(last.parentId, event.parentId)) {
823
+ next[next.length - 1] = {
824
+ type: "text",
825
+ text: last.text + data,
826
+ ...event.parentId ? { parentId: event.parentId } : {}
827
+ };
828
+ } else {
829
+ next.push({
830
+ type: "text",
831
+ text: data,
832
+ ...event.parentId ? { parentId: event.parentId } : {}
833
+ });
834
+ }
835
+ return next;
836
+ }
837
+ if (event.type === "thinking") {
838
+ const data = event.data;
839
+ if (!data) return parts;
840
+ const next = [...parts];
841
+ const last = next[next.length - 1];
842
+ if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
843
+ next[next.length - 1] = {
844
+ type: "thinking",
845
+ text: last.text + data,
846
+ ...event.parentId ? { parentId: event.parentId } : {}
847
+ };
848
+ } else {
849
+ next.push({
850
+ type: "thinking",
851
+ text: data,
852
+ ...event.parentId ? { parentId: event.parentId } : {}
853
+ });
854
+ }
855
+ return next;
856
+ }
857
+ if (event.type === "tool_use") {
858
+ const input = asRecord(event.input);
859
+ const diff = diffFromInput(input);
860
+ const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
861
+ if (existing >= 0) {
862
+ const prev = parts[existing];
863
+ const next = [...parts];
864
+ const mergedInput = input && Object.keys(input).length > 0 ? input : prev.input ?? input;
865
+ next[existing] = {
866
+ ...prev,
867
+ name: event.name || prev.name,
868
+ input: mergedInput,
869
+ description: toolDescription(event.name || prev.name, mergedInput),
870
+ detail: toolDetail(event.name || prev.name, mergedInput) ?? prev.detail,
871
+ filePath: toolFilePath(mergedInput) ?? prev.filePath,
872
+ additions: diff.additions ?? prev.additions,
873
+ deletions: diff.deletions ?? prev.deletions,
874
+ parentId: event.parentId ?? prev.parentId
875
+ };
876
+ return next;
877
+ }
878
+ return [
879
+ ...parts,
880
+ {
881
+ type: "tool",
882
+ id: event.id,
883
+ name: event.name,
884
+ input,
885
+ description: toolDescription(event.name, input),
886
+ detail: toolDetail(event.name, input),
887
+ status: "running",
888
+ filePath: toolFilePath(input),
889
+ ...event.parentId ? { parentId: event.parentId } : {},
890
+ ...diff
891
+ }
892
+ ];
893
+ }
894
+ if (event.type === "tool_result") {
895
+ const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
896
+ const fromResult = parseDiffStat(event.content);
897
+ if (existing < 0) {
898
+ return [
899
+ ...parts,
900
+ {
901
+ type: "tool",
902
+ id: event.id,
903
+ name: "tool",
904
+ description: "tool",
905
+ status: event.isError ? "error" : "done",
906
+ result: event.content,
907
+ ...event.parentId ? { parentId: event.parentId } : {},
908
+ ...fromResult.additions != null ? { additions: fromResult.additions } : {},
909
+ ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
910
+ }
911
+ ];
912
+ }
913
+ return parts.map((p, i) => {
914
+ if (i !== existing || p.type !== "tool") return p;
915
+ return {
916
+ ...p,
917
+ status: event.isError ? "error" : "done",
918
+ result: event.content,
919
+ ...fromResult.additions != null ? { additions: fromResult.additions } : {},
920
+ ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
921
+ };
922
+ });
923
+ }
924
+ return parts;
925
+ }
926
+ function partsToAssistantText(parts) {
927
+ return parts.filter(
928
+ (p) => p.type === "text" && !messagePartParentId(p)
929
+ ).map((p) => p.text).join("").trim();
930
+ }
931
+ function stripBrightsyNdjsonNoise(text) {
932
+ if (!text || !text.includes('"type"')) return text;
933
+ let out = text;
934
+ out = out.replace(
935
+ /\{"type":"(?:tool_use|tool_result|tool|thinking|usage|done|error)"[\s\S]*?\}\s*(?=\{"type":"|$|(?=[A-Za-z*#]))/g,
936
+ ""
937
+ );
938
+ out = out.replace(/\{"type":"(?:tool_use|tool_result|tool)"[\s\S]*$/g, "");
939
+ return out.trim();
940
+ }
941
+ function isBrightsyNdjsonLine(line) {
942
+ const t = line.trim();
943
+ if (!t.startsWith("{")) return false;
944
+ return /"type"\s*:\s*"(tool_use|tool_result|tool|thinking|usage|done|error|text)"/.test(t);
945
+ }
946
+ function finalizeParts(parts) {
947
+ return parts.map(
948
+ (p) => p.type === "tool" && p.status === "running" ? { ...p, status: "done" } : p
949
+ );
950
+ }
951
+ function normalizeParseResult(parsed) {
952
+ if (!parsed) return [];
953
+ return Array.isArray(parsed) ? parsed : [parsed];
954
+ }
955
+
662
956
  // src/agents/injected-mcp.ts
663
957
  import { existsSync as existsSync4, mkdtempSync, writeFileSync } from "fs";
664
958
  import { createRequire } from "module";
@@ -895,14 +1189,7 @@ var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
895
1189
  "mcp__sideboard__present_schema",
896
1190
  "mcp__sideboard__present_files",
897
1191
  "mcp__sideboard__ask_user",
898
- "mcp__sideboard__present_plan",
899
- "mcp__sideboard__list_teams",
900
- "mcp__sideboard__slack_list_channels",
901
- "mcp__sideboard__slack_list_users",
902
- "mcp__sideboard__slack_search",
903
- "mcp__sideboard__slack_read",
904
- "mcp__sideboard__slack_post",
905
- "mcp__sideboard__slack_replies"
1192
+ "mcp__sideboard__present_plan"
906
1193
  ];
907
1194
  var brightsyMcpCommandCache = null;
908
1195
  async function resolveBrightsyMcpCommand() {
@@ -1215,7 +1502,10 @@ var BASE_ALLOWED_TOOLS = [
1215
1502
  "Glob",
1216
1503
  "Grep",
1217
1504
  "WebFetch",
1218
- "WebSearch"
1505
+ "WebSearch",
1506
+ // Subagents (Claude Code v2.1.63 renamed Task → Agent; allow both).
1507
+ "Task",
1508
+ "Agent"
1219
1509
  ];
1220
1510
  var CLAUDE_CHROME_ALLOWED_TOOLS = [
1221
1511
  "mcp__claude-in-chrome",
@@ -1267,42 +1557,59 @@ function claudeResultErrorDetail(obj) {
1267
1557
  }
1268
1558
  return "Claude turn failed";
1269
1559
  }
1270
- function eventsFromContentBlocks(blocks) {
1560
+ function eventsFromContentBlocks(blocks, parentId) {
1271
1561
  if (!blocks?.length) return [];
1272
1562
  const out = [];
1273
1563
  for (const block of blocks) {
1274
1564
  if (!block?.type) continue;
1275
1565
  if (block.type === "text" && block.text) {
1276
- out.push({ type: "stdout", data: block.text });
1566
+ out.push(withEventParentId({ type: "stdout", data: block.text }, parentId));
1277
1567
  continue;
1278
1568
  }
1279
1569
  if ((block.type === "thinking" || block.type === "redacted_thinking") && block.thinking) {
1280
- out.push({ type: "thinking", data: block.thinking });
1570
+ out.push(withEventParentId({ type: "thinking", data: block.thinking }, parentId));
1281
1571
  continue;
1282
1572
  }
1283
1573
  if (block.type === "tool_use" && block.id && block.name) {
1284
- out.push({
1285
- type: "tool_use",
1286
- id: block.id,
1287
- name: block.name,
1288
- input: block.input
1289
- });
1574
+ out.push(
1575
+ withEventParentId(
1576
+ {
1577
+ type: "tool_use",
1578
+ id: block.id,
1579
+ name: block.name,
1580
+ input: block.input
1581
+ },
1582
+ parentId
1583
+ )
1584
+ );
1290
1585
  continue;
1291
1586
  }
1292
1587
  if (block.type === "tool_result" && block.tool_use_id) {
1293
1588
  const content = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map(
1294
1589
  (c) => typeof c === "string" ? c : c && typeof c === "object" && "text" in c ? String(c.text ?? "") : ""
1295
1590
  ).join("") : block.content != null ? JSON.stringify(block.content) : void 0;
1296
- out.push({
1297
- type: "tool_result",
1298
- id: block.tool_use_id,
1299
- content,
1300
- isError: Boolean(block.is_error)
1301
- });
1591
+ out.push(
1592
+ withEventParentId(
1593
+ {
1594
+ type: "tool_result",
1595
+ id: block.tool_use_id,
1596
+ content,
1597
+ isError: Boolean(block.is_error)
1598
+ },
1599
+ parentId
1600
+ )
1601
+ );
1302
1602
  }
1303
1603
  }
1304
1604
  return out;
1305
1605
  }
1606
+ function claudeParentToolUseId(obj) {
1607
+ const nested = obj.event && typeof obj.event === "object" && !Array.isArray(obj.event) ? obj.event : void 0;
1608
+ for (const id of [obj.parent_tool_use_id, nested?.parent_tool_use_id]) {
1609
+ if (typeof id === "string" && id.trim()) return id.trim();
1610
+ }
1611
+ return void 0;
1612
+ }
1306
1613
  var claudeAdapter = {
1307
1614
  kind: "claude",
1308
1615
  async detect() {
@@ -1357,7 +1664,7 @@ var claudeAdapter = {
1357
1664
  );
1358
1665
  }
1359
1666
  const mode = permissionMode(thread);
1360
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-H37LFFXI.js");
1667
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-SKFODUQQ.js");
1361
1668
  const isOrchestrator = isOrchestratorThread2(thread);
1362
1669
  const injectedServers = await buildInjectedMcpServers({
1363
1670
  includeSideboard: true,
@@ -1423,7 +1730,9 @@ var claudeAdapter = {
1423
1730
  args,
1424
1731
  cwd: thread.worktreePath,
1425
1732
  stdin: useStdin ? `${promptText}
1426
- ` : void 0
1733
+ ` : void 0,
1734
+ // Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
1735
+ env: { CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1" }
1427
1736
  };
1428
1737
  },
1429
1738
  parseEvent(line) {
@@ -1440,8 +1749,9 @@ var claudeAdapter = {
1440
1749
  return { type: "session_id", data: obj.session_id };
1441
1750
  }
1442
1751
  if (obj.type === "assistant" || obj.type === "user") {
1752
+ const parentId = claudeParentToolUseId(obj);
1443
1753
  const message = obj.message;
1444
- const events = eventsFromContentBlocks(message?.content);
1754
+ const events = eventsFromContentBlocks(message?.content, parentId);
1445
1755
  if (obj.type === "assistant") {
1446
1756
  const usage = usageFromClaude(message?.usage);
1447
1757
  if (usage) events.push({ type: "usage", data: usage, scope: "request" });
@@ -1450,34 +1760,45 @@ var claudeAdapter = {
1450
1760
  return events.length === 1 ? events[0] : events;
1451
1761
  }
1452
1762
  if (obj.type === "stream_event") {
1763
+ const parentId = claudeParentToolUseId(obj);
1453
1764
  const event = obj.event;
1454
1765
  if (!event) return null;
1455
1766
  if (event.type === "content_block_start" && event.content_block) {
1456
1767
  const block = event.content_block;
1457
1768
  if (block.type === "tool_use" && block.id && block.name) {
1458
- return {
1459
- type: "tool_use",
1460
- id: block.id,
1461
- name: block.name,
1462
- input: block.input
1463
- };
1769
+ return withEventParentId(
1770
+ {
1771
+ type: "tool_use",
1772
+ id: block.id,
1773
+ name: block.name,
1774
+ input: block.input
1775
+ },
1776
+ parentId
1777
+ );
1464
1778
  }
1465
1779
  if (block.type === "thinking" && block.thinking) {
1466
- return { type: "thinking", data: block.thinking };
1780
+ return withEventParentId({ type: "thinking", data: block.thinking }, parentId);
1467
1781
  }
1468
1782
  return null;
1469
1783
  }
1470
1784
  if (event.type === "content_block_delta" && event.delta) {
1471
- if (event.delta.text) return { type: "stdout", data: event.delta.text };
1472
- if (event.delta.thinking) return { type: "thinking", data: event.delta.thinking };
1785
+ if (event.delta.text) {
1786
+ return withEventParentId({ type: "stdout", data: event.delta.text }, parentId);
1787
+ }
1788
+ if (event.delta.thinking) {
1789
+ return withEventParentId({ type: "thinking", data: event.delta.thinking }, parentId);
1790
+ }
1473
1791
  return null;
1474
1792
  }
1475
1793
  return null;
1476
1794
  }
1477
1795
  if (obj.type === "content_block_delta") {
1796
+ const parentId = claudeParentToolUseId(obj);
1478
1797
  const delta = obj.delta;
1479
- if (delta?.text) return { type: "stdout", data: delta.text };
1480
- if (delta?.thinking) return { type: "thinking", data: delta.thinking };
1798
+ if (delta?.text) return withEventParentId({ type: "stdout", data: delta.text }, parentId);
1799
+ if (delta?.thinking) {
1800
+ return withEventParentId({ type: "thinking", data: delta.thinking }, parentId);
1801
+ }
1481
1802
  return null;
1482
1803
  }
1483
1804
  if (obj.type === "result") {
@@ -1646,7 +1967,7 @@ function unwrapCodexMcpResult(result) {
1646
1967
  return String(result);
1647
1968
  }
1648
1969
  }
1649
- function asRecord(value) {
1970
+ function asRecord2(value) {
1650
1971
  if (value && typeof value === "object" && !Array.isArray(value)) {
1651
1972
  return value;
1652
1973
  }
@@ -1785,7 +2106,7 @@ var codexAdapter = {
1785
2106
  }
1786
2107
  if (itemType === "mcp_tool_call" && item.id && item.server && item.tool) {
1787
2108
  const name = `mcp__${item.server}__${item.tool}`;
1788
- const input = asRecord(item.arguments);
2109
+ const input = asRecord2(item.arguments);
1789
2110
  const events = [
1790
2111
  { type: "tool_use", id: item.id, name, input }
1791
2112
  ];
@@ -1816,6 +2137,36 @@ var codexAdapter = {
1816
2137
  }
1817
2138
  return events.length === 1 ? events[0] : events;
1818
2139
  }
2140
+ if (itemType === "collab_tool_call" && item.id) {
2141
+ const rawTool = typeof item.tool === "string" ? item.tool : "spawn_agent";
2142
+ const name = /spawn/i.test(rawTool) ? "spawn_agent" : rawTool;
2143
+ const input = {};
2144
+ if (item.prompt) input.prompt = item.prompt;
2145
+ if (Array.isArray(item.receiver_thread_ids)) {
2146
+ input.receiver_thread_ids = item.receiver_thread_ids;
2147
+ }
2148
+ const events = [{ type: "tool_use", id: item.id, name, input }];
2149
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
2150
+ if (finished) {
2151
+ const nested = [];
2152
+ if (item.agents_states && typeof item.agents_states === "object") {
2153
+ for (const value of Object.values(item.agents_states)) {
2154
+ const msg = value && typeof value === "object" && typeof value.message === "string" ? value.message.trim() : "";
2155
+ if (msg) nested.push(msg);
2156
+ }
2157
+ }
2158
+ for (const text of nested) {
2159
+ events.push({ type: "stdout", data: text, parentId: item.id });
2160
+ }
2161
+ events.push({
2162
+ type: "tool_result",
2163
+ id: item.id,
2164
+ content: nested.join("\n") || void 0,
2165
+ isError: item.status === "failed"
2166
+ });
2167
+ }
2168
+ return events.length === 1 ? events[0] : events;
2169
+ }
1819
2170
  if (item.status === "failed") {
1820
2171
  const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
1821
2172
  return { type: "stderr", data: detail };
@@ -1909,20 +2260,20 @@ function usageFromCursor(usage) {
1909
2260
  cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
1910
2261
  };
1911
2262
  }
1912
- function asRecord2(value) {
2263
+ function asRecord3(value) {
1913
2264
  if (value && typeof value === "object" && !Array.isArray(value)) {
1914
2265
  return value;
1915
2266
  }
1916
2267
  return void 0;
1917
2268
  }
1918
2269
  function normalizeCursorToolCall(name, args) {
1919
- const raw = asRecord2(args);
2270
+ const raw = asRecord3(args);
1920
2271
  const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
1921
- const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord2(raw?.args) != null);
2272
+ const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord3(raw?.args) != null);
1922
2273
  if (looksLikeMcp && toolName) {
1923
2274
  const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
1924
2275
  const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
1925
- const nested = asRecord2(raw.args);
2276
+ const nested = asRecord3(raw.args);
1926
2277
  return {
1927
2278
  name: `mcp__${provider}__${toolName}`,
1928
2279
  input: nested ?? { toolName }
@@ -1933,7 +2284,7 @@ function normalizeCursorToolCall(name, args) {
1933
2284
  function unwrapCursorToolResult(result) {
1934
2285
  if (result == null) return void 0;
1935
2286
  if (typeof result === "string") return result;
1936
- const rec = asRecord2(result);
2287
+ const rec = asRecord3(result);
1937
2288
  if (!rec) {
1938
2289
  try {
1939
2290
  return JSON.stringify(result);
@@ -1944,18 +2295,18 @@ function unwrapCursorToolResult(result) {
1944
2295
  const collectTexts = (items) => {
1945
2296
  const texts = [];
1946
2297
  for (const item of items) {
1947
- const row = asRecord2(item);
2298
+ const row = asRecord3(item);
1948
2299
  if (!row) continue;
1949
2300
  if (typeof row.text === "string") {
1950
2301
  texts.push(row.text);
1951
2302
  continue;
1952
2303
  }
1953
- const nested = asRecord2(row.text);
2304
+ const nested = asRecord3(row.text);
1954
2305
  if (typeof nested?.text === "string") texts.push(nested.text);
1955
2306
  }
1956
2307
  return texts;
1957
2308
  };
1958
- const value = asRecord2(rec.value);
2309
+ const value = asRecord3(rec.value);
1959
2310
  if (value && Array.isArray(value.content)) {
1960
2311
  const texts = collectTexts(value.content);
1961
2312
  if (texts.length) return texts.join("\n");
@@ -1972,10 +2323,10 @@ function unwrapCursorToolResult(result) {
1972
2323
  }
1973
2324
  function cursorToolResultIsError(status, result) {
1974
2325
  if (status === "error") return true;
1975
- const rec = asRecord2(result);
2326
+ const rec = asRecord3(result);
1976
2327
  if (!rec) return false;
1977
2328
  if (rec.status === "error") return true;
1978
- const value = asRecord2(rec.value);
2329
+ const value = asRecord3(rec.value);
1979
2330
  return value?.isError === true;
1980
2331
  }
1981
2332
  function cursorSdkMessageToEvents(msg) {
@@ -2295,6 +2646,24 @@ var FALLBACK_OPENCODE_MODELS = [
2295
2646
  ];
2296
2647
  var cachedOpencodeModels = null;
2297
2648
  var OPENCODE_MODEL_CACHE_MS = 5 * 60 * 1e3;
2649
+ function asRecord4(value) {
2650
+ if (value && typeof value === "object" && !Array.isArray(value)) {
2651
+ return value;
2652
+ }
2653
+ return void 0;
2654
+ }
2655
+ function str2(v) {
2656
+ return typeof v === "string" && v.trim() ? v.trim() : void 0;
2657
+ }
2658
+ function opencodeToolId(name, callId, metadata) {
2659
+ const sessionId = str2(metadata?.sessionId) ?? str2(metadata?.sessionID);
2660
+ if (name === "task" && sessionId) return sessionId;
2661
+ return callId || `tool-${Date.now()}`;
2662
+ }
2663
+ function withTaskParent(parentId, nested) {
2664
+ const events = Array.isArray(nested) ? nested : [nested];
2665
+ return [{ type: "tool_use", id: parentId, name: "task" }, ...events];
2666
+ }
2298
2667
  function displayNameFromOpencodeId(id) {
2299
2668
  const slash = id.indexOf("/");
2300
2669
  if (slash <= 0) return id;
@@ -2452,10 +2821,15 @@ var opencodeAdapter = {
2452
2821
  }
2453
2822
  if (obj.type === "tool_use") {
2454
2823
  const part = obj.part;
2455
- const id = part?.callID ?? part?.id ?? obj.id ?? `tool-${Date.now()}`;
2456
2824
  const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
2457
2825
  const state = part?.state;
2458
2826
  const input = (state?.input && typeof state.input === "object" ? state.input : void 0) ?? part?.input ?? obj.input;
2827
+ const metadata = asRecord4(state?.metadata);
2828
+ const id = opencodeToolId(
2829
+ name,
2830
+ part?.callID ?? part?.id ?? obj.id,
2831
+ metadata
2832
+ );
2459
2833
  const events = [{ type: "tool_use", id, name, input }];
2460
2834
  const output = state?.output;
2461
2835
  if (output != null || state?.status === "completed" || state?.status === "error") {
@@ -2469,6 +2843,53 @@ var opencodeAdapter = {
2469
2843
  }
2470
2844
  return events.length === 1 ? events[0] : events;
2471
2845
  }
2846
+ if (obj.type === "subtask_delta") {
2847
+ const parentId = str2(obj.childSessionID) ?? str2(obj.childSessionId);
2848
+ const delta = str2(obj.delta);
2849
+ if (parentId && delta) {
2850
+ return withTaskParent(
2851
+ parentId,
2852
+ withEventParentId({ type: "thinking", data: delta }, parentId)
2853
+ );
2854
+ }
2855
+ return null;
2856
+ }
2857
+ if (obj.type === "subtask_event") {
2858
+ const parentId = str2(obj.childSessionID) ?? str2(obj.childSessionId);
2859
+ const part = asRecord4(obj.part);
2860
+ if (!parentId || !part) return null;
2861
+ if (part.type === "text" && str2(part.text)) {
2862
+ return withTaskParent(
2863
+ parentId,
2864
+ withEventParentId({ type: "stdout", data: str2(part.text) }, parentId)
2865
+ );
2866
+ }
2867
+ if (part.type === "tool" || str2(part.tool)) {
2868
+ const name = str2(part.tool) ?? str2(part.name) ?? "tool";
2869
+ const id = str2(part.callID) ?? str2(part.id) ?? `${parentId}-${name}`;
2870
+ const state = asRecord4(part.state);
2871
+ const input = asRecord4(state?.input) ?? asRecord4(part.input);
2872
+ const nested = [
2873
+ withEventParentId({ type: "tool_use", id, name, input }, parentId)
2874
+ ];
2875
+ const output = state?.output ?? part.output;
2876
+ if (output != null || state?.status === "completed" || state?.status === "error") {
2877
+ nested.push(
2878
+ withEventParentId(
2879
+ {
2880
+ type: "tool_result",
2881
+ id,
2882
+ content: typeof output === "string" ? output : output != null ? JSON.stringify(output) : void 0,
2883
+ isError: state?.status === "error" || state?.status === "failed"
2884
+ },
2885
+ parentId
2886
+ )
2887
+ );
2888
+ }
2889
+ return withTaskParent(parentId, nested);
2890
+ }
2891
+ return null;
2892
+ }
2472
2893
  if (obj.type === "tool_result") {
2473
2894
  const part = obj.part;
2474
2895
  const id = part?.tool_use_id ?? part?.id ?? obj.tool_use_id ?? obj.id;
@@ -2996,11 +3417,19 @@ export {
2996
3417
  turnFailChatText,
2997
3418
  formatTurnExitError,
2998
3419
  applyTurnUsage,
3420
+ contextTokens,
2999
3421
  encodeBrightsyTarget,
3000
3422
  decodeBrightsyTarget,
3001
3423
  parseBrightsyCliLine,
3002
3424
  listBrightsyChatTargets,
3003
3425
  brightsyAdapter,
3426
+ toolDescription,
3427
+ applyAgentEvent,
3428
+ partsToAssistantText,
3429
+ stripBrightsyNdjsonNoise,
3430
+ isBrightsyNdjsonLine,
3431
+ finalizeParts,
3432
+ normalizeParseResult,
3004
3433
  sideboardMcpProfile,
3005
3434
  PLAN_MODE_INSTRUCTION,
3006
3435
  permissionMode,