@sideboard-ai/core 0.1.111 → 0.1.116
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.
- package/dist/agents/cursor-runner.cjs +51 -21
- package/dist/agents/cursor-runner.js +3 -3
- package/dist/{agents-NN22A4G5.js → agents-7NIX44RB.js} +7 -7
- package/dist/{agents-GH3FWDW2.js → agents-DU7DHY7A.js} +10 -10
- package/dist/{chunk-JTQQPJAU.js → chunk-4HOFVKPC.js} +52 -38
- package/dist/{chunk-4EWPKYOU.js → chunk-4OJMZ6P2.js} +2 -2
- package/dist/{chunk-NC3U42ZP.js → chunk-5KSLD4MU.js} +317 -33
- package/dist/{chunk-KQBI5HNT.js → chunk-7WC5UWEB.js} +2 -2
- package/dist/{chunk-WIHKHR5R.js → chunk-AXQ4ZWHK.js} +5 -0
- package/dist/{chunk-LGXBYZZA.js → chunk-DVM4ID64.js} +69 -13
- package/dist/{chunk-DMJKOFTO.js → chunk-DWP25N32.js} +44 -35
- package/dist/{chunk-2GO3YKBA.js → chunk-EKIDHL2T.js} +4 -4
- package/dist/{chunk-C4KHDW3U.js → chunk-FZCIQYNQ.js} +1 -1
- package/dist/{chunk-363Z34PY.js → chunk-GBY7OOMB.js} +273 -218
- package/dist/{chunk-7KWYXGIU.js → chunk-K3TIQXOH.js} +2 -2
- package/dist/{chunk-3KETJKYA.js → chunk-KPIYENTF.js} +69 -13
- package/dist/{chunk-KVFNTWFG.js → chunk-OFF5AFCR.js} +300 -43
- package/dist/{chunk-VOD3HFLP.js → chunk-XOYQ7LNQ.js} +2 -2
- package/dist/{chunk-7YKXHBIW.js → chunk-YMRT2DU6.js} +3 -3
- package/dist/{chunk-YXDR43ZC.js → chunk-ZMROW673.js} +5 -5
- package/dist/{chunk-YFAXVUY2.js → chunk-ZRCX43LS.js} +2 -2
- package/dist/{chunk-AROMOP3C.js → chunk-ZYEFCSZJ.js} +2 -2
- package/dist/{connected-teams-M5XNXRI5.js → connected-teams-O6D4PM7A.js} +2 -2
- package/dist/{connected-teams-J4I5AKMR.js → connected-teams-ZCOU6KCD.js} +2 -2
- package/dist/{coordinator-prompt-AR66L3N4.js → coordinator-prompt-4KCALEKD.js} +3 -3
- package/dist/{coordinator-prompt-BHMLWL64.js → coordinator-prompt-FML4I5AR.js} +3 -3
- package/dist/{global-workspace-XSUFEIAQ.js → global-workspace-CSWABOG5.js} +4 -4
- package/dist/{global-workspace-SKFODUQQ.js → global-workspace-H4YNASM6.js} +4 -4
- package/dist/index.cjs +855 -440
- package/dist/index.d.cts +59 -1
- package/dist/index.d.ts +59 -1
- package/dist/index.js +37 -17
- package/dist/mcp/run-stdio.cjs +966 -635
- package/dist/mcp/run-stdio.js +20 -16
- package/dist/{orchestrator-4T2SXDZ7.js → orchestrator-NXPANCZA.js} +8 -8
- package/dist/{orchestrator-EP57AB5W.js → orchestrator-ZY4RUJKT.js} +10 -10
- package/dist/{run-XKTAJRWF.js → run-USF6FRKV.js} +3 -1
- package/dist/{run-CFKZPY7F.js → run-XQKGHQZ2.js} +3 -1
- package/dist/{workspaces-XAQVKTLO.js → workspaces-HJ3EVATC.js} +5 -5
- package/dist/{workspaces-HV3J4TTW.js → workspaces-QG6PGFQR.js} +5 -5
- package/dist/{worktree-XFJED3VU.js → worktree-IW3BX26B.js} +2 -2
- package/dist/{worktree-N2EV24EE.js → worktree-OTFQO2W7.js} +2 -2
- package/package.json +1 -1
|
@@ -4,11 +4,12 @@ import {
|
|
|
4
4
|
ensureCliTeamTracked,
|
|
5
5
|
ensureConnectedBrightsyTeamTokens,
|
|
6
6
|
loadBrightsyConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EKIDHL2T.js";
|
|
8
8
|
import {
|
|
9
9
|
isOrchestratorThread
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4OJMZ6P2.js";
|
|
11
11
|
import {
|
|
12
|
+
applyAgentRunnerHeapEnv,
|
|
12
13
|
applyNodeLaunch,
|
|
13
14
|
cursorRipgrepEnv,
|
|
14
15
|
extractJsonErrorMessage,
|
|
@@ -19,13 +20,13 @@ import {
|
|
|
19
20
|
packagedMcpStdioPath,
|
|
20
21
|
parseCursorRunnerLine,
|
|
21
22
|
resolveNodeLaunch
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GBY7OOMB.js";
|
|
23
24
|
import {
|
|
24
25
|
codexUnattendedGitConfigArgs,
|
|
25
26
|
mergeAgentGitAuthEnv,
|
|
26
27
|
resolveAgentGitAuthEnv,
|
|
27
28
|
resolveCodexGitWritableRoots
|
|
28
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-FZCIQYNQ.js";
|
|
29
30
|
import {
|
|
30
31
|
claudeChromeEnabled,
|
|
31
32
|
loadAppSettings,
|
|
@@ -45,7 +46,7 @@ import {
|
|
|
45
46
|
resolveCommandBinarySync,
|
|
46
47
|
run,
|
|
47
48
|
withExportedPath
|
|
48
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-DVM4ID64.js";
|
|
49
50
|
|
|
50
51
|
// src/agents/brightsy.ts
|
|
51
52
|
import { existsSync } from "fs";
|
|
@@ -582,9 +583,9 @@ function toolDescription(name, input) {
|
|
|
582
583
|
if (/connectedAgentRequest/i.test(name)) {
|
|
583
584
|
return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
|
|
584
585
|
}
|
|
585
|
-
if (desc && kind) return `${kind}: ${desc}`;
|
|
586
|
-
if (desc) return desc
|
|
587
|
-
return
|
|
586
|
+
if (desc && kind) return `${kind}: ${desc}${subagentLiveSuffix(input)}`;
|
|
587
|
+
if (desc) return `${desc}${subagentLiveSuffix(input)}`;
|
|
588
|
+
return `Subagent${subagentLiveSuffix(input)}`;
|
|
588
589
|
}
|
|
589
590
|
if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
|
|
590
591
|
return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
|
|
@@ -609,13 +610,151 @@ function toolDescription(name, input) {
|
|
|
609
610
|
}
|
|
610
611
|
if (/grep/i.test(name)) return "Search files";
|
|
611
612
|
if (/glob/i.test(name)) return "Find files";
|
|
613
|
+
const compact = n.replace(/[_-]/g, "");
|
|
614
|
+
if (/^taskoutput$/i.test(compact)) {
|
|
615
|
+
return str(input.task_id) ? `Wait for ${str(input.task_id)}` : "Wait for background task";
|
|
616
|
+
}
|
|
617
|
+
if (/^taskstop$/i.test(compact)) {
|
|
618
|
+
return str(input.task_id) ? `Stop ${str(input.task_id)}` : "Stop background task";
|
|
619
|
+
}
|
|
620
|
+
if (/^monitor$/i.test(compact)) {
|
|
621
|
+
const command = str(input.command);
|
|
622
|
+
return command ? `Watch ${command.length > 48 ? `${command.slice(0, 45)}\u2026` : command}` : "Watch command";
|
|
623
|
+
}
|
|
612
624
|
return n;
|
|
613
625
|
}
|
|
626
|
+
function subagentLiveSuffix(input) {
|
|
627
|
+
if (!input) return "";
|
|
628
|
+
const bits = [];
|
|
629
|
+
const status = str(input.live_status);
|
|
630
|
+
if (status && !/^runn(ing)?$|^working$/i.test(status)) bits.push(status);
|
|
631
|
+
if (typeof input.live_tool_uses === "number") bits.push(`${input.live_tool_uses} tools`);
|
|
632
|
+
if (typeof input.live_duration_ms === "number") {
|
|
633
|
+
bits.push(`${Math.max(0, Math.round(Number(input.live_duration_ms) / 1e3))}s`);
|
|
634
|
+
}
|
|
635
|
+
const last = str(input.live_last_tool);
|
|
636
|
+
if (last) bits.push(last);
|
|
637
|
+
return bits.length ? ` \xB7 ${bits.join(" \xB7 ")}` : "";
|
|
638
|
+
}
|
|
614
639
|
function isSubagentToolName(name) {
|
|
615
640
|
const n = (name ?? "").trim();
|
|
616
641
|
if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
|
|
617
642
|
return /connectedAgentRequest/i.test(n);
|
|
618
643
|
}
|
|
644
|
+
function isPollWrapperToolName(name) {
|
|
645
|
+
const n = (name ?? "").replace(/[_-]/g, "");
|
|
646
|
+
return /^(taskoutput|taskstop|sleep)$/i.test(n);
|
|
647
|
+
}
|
|
648
|
+
function lastTextPart(parts, type) {
|
|
649
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
650
|
+
const p = parts[i];
|
|
651
|
+
if (p.type === type && p.text.trim()) return p.text.trim();
|
|
652
|
+
}
|
|
653
|
+
return "";
|
|
654
|
+
}
|
|
655
|
+
function toolLabel(tool) {
|
|
656
|
+
return tool.description || toolDescription(tool.name, tool.input) || tool.name;
|
|
657
|
+
}
|
|
658
|
+
function fileBasename(path) {
|
|
659
|
+
const parts = path.replace(/\/$/, "").split(/[/\\]/);
|
|
660
|
+
return parts[parts.length - 1] || path;
|
|
661
|
+
}
|
|
662
|
+
function classifyTool(name) {
|
|
663
|
+
const compact = name.replace(/^mcp__[^_]+__/, "").replace(/[_-]/g, "");
|
|
664
|
+
if (/bash|shell|terminal|^zsh$|^sh$/i.test(compact)) return "shell";
|
|
665
|
+
if (/grep|glob|search|ripgrep|findfiles|semsearch/i.test(compact)) return "search";
|
|
666
|
+
if (/^(read|cat)$/i.test(compact) || /^read/i.test(compact)) return "read";
|
|
667
|
+
if (/edit|write|apply|strreplace|multiedit|updatefile|createfile/i.test(compact)) {
|
|
668
|
+
return "edit";
|
|
669
|
+
}
|
|
670
|
+
return "other";
|
|
671
|
+
}
|
|
672
|
+
function isShellToolName(name) {
|
|
673
|
+
return classifyTool(name ?? "") === "shell";
|
|
674
|
+
}
|
|
675
|
+
function toolActivityLine(parts) {
|
|
676
|
+
const tools = parts.filter((p) => {
|
|
677
|
+
if (p.type !== "tool" || p.parentId) return false;
|
|
678
|
+
if (isPollWrapperToolName(p.name)) return false;
|
|
679
|
+
if (/present_plan$/i.test(p.name ?? "")) return false;
|
|
680
|
+
if (/ask_user|AskUserQuestion/i.test(p.name ?? "")) return false;
|
|
681
|
+
return true;
|
|
682
|
+
});
|
|
683
|
+
if (tools.length === 0) return null;
|
|
684
|
+
const edited = [];
|
|
685
|
+
let reads = 0;
|
|
686
|
+
let searches = 0;
|
|
687
|
+
let shells = 0;
|
|
688
|
+
let others = 0;
|
|
689
|
+
let additions = 0;
|
|
690
|
+
let deletions = 0;
|
|
691
|
+
for (const tool of tools) {
|
|
692
|
+
const kind = classifyTool(tool.name);
|
|
693
|
+
if (kind === "edit") {
|
|
694
|
+
const path = tool.filePath ?? toolFilePath(tool.input);
|
|
695
|
+
edited.push({
|
|
696
|
+
name: path ? fileBasename(path) : tool.name,
|
|
697
|
+
running: tool.status === "running"
|
|
698
|
+
});
|
|
699
|
+
} else if (kind === "read") reads += 1;
|
|
700
|
+
else if (kind === "search") searches += 1;
|
|
701
|
+
else if (kind === "shell") shells += 1;
|
|
702
|
+
else others += 1;
|
|
703
|
+
if (typeof tool.additions === "number") additions += tool.additions;
|
|
704
|
+
if (typeof tool.deletions === "number") deletions += tool.deletions;
|
|
705
|
+
}
|
|
706
|
+
const bits = [];
|
|
707
|
+
const editing = edited.filter((e) => e.running);
|
|
708
|
+
const editedDone = edited.filter((e) => !e.running);
|
|
709
|
+
if (editing.length === 1) bits.push(`Editing ${editing[0].name}`);
|
|
710
|
+
else if (editing.length > 1) bits.push(`Editing ${editing.length} files`);
|
|
711
|
+
if (editedDone.length === 1) bits.push(`${editing.length ? "edited" : "Edited"} ${editedDone[0].name}`);
|
|
712
|
+
else if (editedDone.length > 1) {
|
|
713
|
+
bits.push(`${editing.length ? "edited" : "Edited"} ${editedDone.length} files`);
|
|
714
|
+
}
|
|
715
|
+
if (reads === 1) bits.push("explored 1 file");
|
|
716
|
+
else if (reads > 1) bits.push(`explored ${reads} files`);
|
|
717
|
+
if (searches === 1) bits.push("1 search");
|
|
718
|
+
else if (searches > 1) bits.push(`${searches} searches`);
|
|
719
|
+
if (shells === 1) bits.push("ran 1 command");
|
|
720
|
+
else if (shells > 1) bits.push(`ran ${shells} commands`);
|
|
721
|
+
if (others === 1) bits.push("1 tool");
|
|
722
|
+
else if (others > 1) bits.push(`${others} tools`);
|
|
723
|
+
if (bits.length === 0) return null;
|
|
724
|
+
return { text: bits.join(", "), additions, deletions };
|
|
725
|
+
}
|
|
726
|
+
function liveActivitySummary(parts, opts) {
|
|
727
|
+
if (opts?.queued && parts.length === 0) {
|
|
728
|
+
return "Queued \u2014 waiting for a slot";
|
|
729
|
+
}
|
|
730
|
+
const tools = parts.filter((p) => p.type === "tool");
|
|
731
|
+
const runningSubs = tools.filter(
|
|
732
|
+
(t) => t.status === "running" && !t.parentId && isSubagentToolName(t.name)
|
|
733
|
+
);
|
|
734
|
+
const runningNested = [...tools].reverse().find((t) => t.status === "running" && t.parentId && !isPollWrapperToolName(t.name));
|
|
735
|
+
const runningTop = [...tools].reverse().find(
|
|
736
|
+
(t) => t.status === "running" && !t.parentId && !isPollWrapperToolName(t.name) && !isSubagentToolName(t.name)
|
|
737
|
+
);
|
|
738
|
+
const runningPoll = [...tools].reverse().find((t) => t.status === "running" && isPollWrapperToolName(t.name));
|
|
739
|
+
const thinking = lastTextPart(parts, "thinking");
|
|
740
|
+
const text = lastTextPart(parts, "text");
|
|
741
|
+
if (runningSubs.length > 0) {
|
|
742
|
+
const heads = runningSubs.map(toolLabel);
|
|
743
|
+
const head = runningSubs.length === 1 ? heads[0] : `${runningSubs.length} subagents \xB7 ${heads.slice(0, 2).join(" \xB7 ")}`;
|
|
744
|
+
if (runningNested) return `${head} \xB7 ${toolLabel(runningNested)}`;
|
|
745
|
+
return head;
|
|
746
|
+
}
|
|
747
|
+
if (runningTop) return toolLabel(runningTop);
|
|
748
|
+
if (runningPoll) return toolLabel(runningPoll);
|
|
749
|
+
if (thinking) return thinking.length > 96 ? `\u2026${thinking.slice(-96)}` : thinking;
|
|
750
|
+
if (text) return "Writing reply\u2026";
|
|
751
|
+
const last = [...tools].reverse().find((t) => !isPollWrapperToolName(t.name)) ?? tools.at(-1);
|
|
752
|
+
if (last) {
|
|
753
|
+
const label = toolLabel(last);
|
|
754
|
+
return last.status === "running" ? label : `Finished ${label}`;
|
|
755
|
+
}
|
|
756
|
+
return "Working\u2026";
|
|
757
|
+
}
|
|
619
758
|
function messagePartParentId(part) {
|
|
620
759
|
if ("parentId" in part && typeof part.parentId === "string" && part.parentId.trim()) {
|
|
621
760
|
return part.parentId;
|
|
@@ -701,6 +840,25 @@ function applyAgentEvent(parts, event) {
|
|
|
701
840
|
const data = event.data;
|
|
702
841
|
if (!data) return parts;
|
|
703
842
|
const next = [...parts];
|
|
843
|
+
if (event.replace) {
|
|
844
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
845
|
+
const prev = next[i];
|
|
846
|
+
if (prev?.type === "thinking" && sameParentId(prev.parentId, event.parentId)) {
|
|
847
|
+
next[i] = {
|
|
848
|
+
type: "thinking",
|
|
849
|
+
text: data,
|
|
850
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
851
|
+
};
|
|
852
|
+
return next;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
next.push({
|
|
856
|
+
type: "thinking",
|
|
857
|
+
text: data,
|
|
858
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
859
|
+
});
|
|
860
|
+
return next;
|
|
861
|
+
}
|
|
704
862
|
const last = next[next.length - 1];
|
|
705
863
|
if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
|
|
706
864
|
next[next.length - 1] = {
|
|
@@ -724,14 +882,18 @@ function applyAgentEvent(parts, event) {
|
|
|
724
882
|
if (existing >= 0) {
|
|
725
883
|
const prev = parts[existing];
|
|
726
884
|
const next = [...parts];
|
|
727
|
-
const mergedInput =
|
|
885
|
+
const mergedInput = {
|
|
886
|
+
...prev.input ?? {},
|
|
887
|
+
...input ?? {}
|
|
888
|
+
};
|
|
889
|
+
const mergedRecord = Object.keys(mergedInput).length > 0 ? mergedInput : void 0;
|
|
728
890
|
next[existing] = {
|
|
729
891
|
...prev,
|
|
730
892
|
name: event.name || prev.name,
|
|
731
|
-
input:
|
|
732
|
-
description: toolDescription(event.name || prev.name,
|
|
733
|
-
detail: toolDetail(event.name || prev.name,
|
|
734
|
-
filePath: toolFilePath(
|
|
893
|
+
input: mergedRecord,
|
|
894
|
+
description: toolDescription(event.name || prev.name, mergedRecord),
|
|
895
|
+
detail: toolDetail(event.name || prev.name, mergedRecord) ?? prev.detail,
|
|
896
|
+
filePath: toolFilePath(mergedRecord) ?? prev.filePath,
|
|
735
897
|
additions: diff.additions ?? prev.additions,
|
|
736
898
|
deletions: diff.deletions ?? prev.deletions,
|
|
737
899
|
parentId: event.parentId ?? prev.parentId
|
|
@@ -757,6 +919,30 @@ function applyAgentEvent(parts, event) {
|
|
|
757
919
|
if (event.type === "tool_result") {
|
|
758
920
|
const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
|
|
759
921
|
const fromResult = parseDiffStat(event.content);
|
|
922
|
+
if (event.partial) {
|
|
923
|
+
if (existing < 0) {
|
|
924
|
+
return [
|
|
925
|
+
...parts,
|
|
926
|
+
{
|
|
927
|
+
type: "tool",
|
|
928
|
+
id: event.id,
|
|
929
|
+
name: "tool",
|
|
930
|
+
description: "tool",
|
|
931
|
+
status: event.isError ? "error" : "running",
|
|
932
|
+
result: event.content,
|
|
933
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
934
|
+
}
|
|
935
|
+
];
|
|
936
|
+
}
|
|
937
|
+
return parts.map((p, i) => {
|
|
938
|
+
if (i !== existing || p.type !== "tool") return p;
|
|
939
|
+
if (p.status === "done" || p.status === "error") return p;
|
|
940
|
+
return {
|
|
941
|
+
...p,
|
|
942
|
+
result: event.content ?? p.result
|
|
943
|
+
};
|
|
944
|
+
});
|
|
945
|
+
}
|
|
760
946
|
if (existing < 0) {
|
|
761
947
|
return [
|
|
762
948
|
...parts,
|
|
@@ -1014,6 +1200,7 @@ async function buildInjectedMcpServers(opts) {
|
|
|
1014
1200
|
);
|
|
1015
1201
|
} catch {
|
|
1016
1202
|
}
|
|
1203
|
+
applyAgentRunnerHeapEnv(sideboard.env);
|
|
1017
1204
|
servers.push(sideboard);
|
|
1018
1205
|
}
|
|
1019
1206
|
if (opts.includeBrightsy && isBrightsyConnected()) {
|
|
@@ -1169,8 +1356,14 @@ var BASE_ALLOWED_TOOLS = [
|
|
|
1169
1356
|
"WebSearch",
|
|
1170
1357
|
// Subagents (Claude Code v2.1.63 renamed Task → Agent; allow both).
|
|
1171
1358
|
"Task",
|
|
1172
|
-
"Agent"
|
|
1359
|
+
"Agent",
|
|
1360
|
+
"TaskOutput",
|
|
1361
|
+
"TaskStop",
|
|
1362
|
+
"EnterWorktree",
|
|
1363
|
+
"ExitWorktree",
|
|
1364
|
+
"Skill"
|
|
1173
1365
|
];
|
|
1366
|
+
var CLAUDE_PRINT_BG_WAIT_CEILING_MS = 72e5;
|
|
1174
1367
|
var CLAUDE_CHROME_ALLOWED_TOOLS = [
|
|
1175
1368
|
"mcp__claude-in-chrome",
|
|
1176
1369
|
"mcp__claude-in-chrome__*",
|
|
@@ -1274,6 +1467,80 @@ function claudeParentToolUseId(obj) {
|
|
|
1274
1467
|
}
|
|
1275
1468
|
return void 0;
|
|
1276
1469
|
}
|
|
1470
|
+
function claudeString(obj, key) {
|
|
1471
|
+
const v = obj[key];
|
|
1472
|
+
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
1473
|
+
}
|
|
1474
|
+
function eventsFromClaudeSystem(obj) {
|
|
1475
|
+
const subtype = claudeString(obj, "subtype") ?? "";
|
|
1476
|
+
const parentId = claudeParentToolUseId(obj);
|
|
1477
|
+
if (subtype === "init") {
|
|
1478
|
+
if (parentId) return null;
|
|
1479
|
+
const sid = claudeString(obj, "session_id");
|
|
1480
|
+
return sid ? { type: "session_id", data: sid } : null;
|
|
1481
|
+
}
|
|
1482
|
+
if (subtype === "task_started") {
|
|
1483
|
+
const id = claudeString(obj, "tool_use_id") ?? claudeString(obj, "task_id");
|
|
1484
|
+
if (!id) return null;
|
|
1485
|
+
const description = claudeString(obj, "description");
|
|
1486
|
+
const taskType = claudeString(obj, "task_type");
|
|
1487
|
+
const prompt = claudeString(obj, "prompt");
|
|
1488
|
+
return withEventParentId(
|
|
1489
|
+
{
|
|
1490
|
+
type: "tool_use",
|
|
1491
|
+
id,
|
|
1492
|
+
name: taskType || "Agent",
|
|
1493
|
+
input: {
|
|
1494
|
+
...description ? { description } : {},
|
|
1495
|
+
...prompt ? { prompt } : {},
|
|
1496
|
+
...claudeString(obj, "task_id") ? { task_id: claudeString(obj, "task_id") } : {}
|
|
1497
|
+
}
|
|
1498
|
+
},
|
|
1499
|
+
parentId
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1502
|
+
if (subtype === "task_notification") {
|
|
1503
|
+
const id = claudeString(obj, "tool_use_id") ?? claudeString(obj, "task_id") ?? parentId;
|
|
1504
|
+
if (!id) return null;
|
|
1505
|
+
const status = claudeString(obj, "status") ?? "working";
|
|
1506
|
+
const tools = typeof obj.tool_uses === "number" ? obj.tool_uses : void 0;
|
|
1507
|
+
const durationMs = typeof obj.duration_ms === "number" ? obj.duration_ms : void 0;
|
|
1508
|
+
const lastTool = claudeString(obj, "last_tool") ?? claudeString(obj, "current_tool") ?? claudeString(obj, "tool");
|
|
1509
|
+
const snapshot = [
|
|
1510
|
+
status,
|
|
1511
|
+
tools != null ? `${tools} tools` : null,
|
|
1512
|
+
durationMs != null ? `${Math.round(durationMs / 1e3)}s` : null,
|
|
1513
|
+
lastTool
|
|
1514
|
+
].filter((bit) => Boolean(bit)).join(" \xB7 ");
|
|
1515
|
+
return [
|
|
1516
|
+
{
|
|
1517
|
+
type: "tool_use",
|
|
1518
|
+
id,
|
|
1519
|
+
name: claudeString(obj, "task_type") || "Agent",
|
|
1520
|
+
input: {
|
|
1521
|
+
live_status: status,
|
|
1522
|
+
...tools != null ? { live_tool_uses: tools } : {},
|
|
1523
|
+
...durationMs != null ? { live_duration_ms: durationMs } : {},
|
|
1524
|
+
...lastTool ? { live_last_tool: lastTool } : {}
|
|
1525
|
+
}
|
|
1526
|
+
},
|
|
1527
|
+
withEventParentId(
|
|
1528
|
+
{ type: "thinking", data: snapshot, replace: true },
|
|
1529
|
+
id
|
|
1530
|
+
)
|
|
1531
|
+
];
|
|
1532
|
+
}
|
|
1533
|
+
if (subtype === "api_retry") {
|
|
1534
|
+
const attempt = obj.attempt;
|
|
1535
|
+
const max = obj.max_retries;
|
|
1536
|
+
const delay = obj.retry_delay_ms;
|
|
1537
|
+
return {
|
|
1538
|
+
type: "thinking",
|
|
1539
|
+
data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay === "number" ? ` (wait ${delay}ms)` : ""}`
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
return null;
|
|
1543
|
+
}
|
|
1277
1544
|
var claudeAdapter = {
|
|
1278
1545
|
kind: "claude",
|
|
1279
1546
|
async detect() {
|
|
@@ -1328,7 +1595,7 @@ var claudeAdapter = {
|
|
|
1328
1595
|
);
|
|
1329
1596
|
}
|
|
1330
1597
|
const mode = permissionMode(thread);
|
|
1331
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
1598
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-CSWABOG5.js");
|
|
1332
1599
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
1333
1600
|
const injectedServers = await buildInjectedMcpServers({
|
|
1334
1601
|
includeSideboard: true,
|
|
@@ -1396,7 +1663,12 @@ var claudeAdapter = {
|
|
|
1396
1663
|
stdin: useStdin ? `${promptText}
|
|
1397
1664
|
` : void 0,
|
|
1398
1665
|
// Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
|
|
1399
|
-
|
|
1666
|
+
// Raise the -p background-agent wait so long TaskOutput polls are not
|
|
1667
|
+
// abandoned at Claude Code’s 10-minute default.
|
|
1668
|
+
env: {
|
|
1669
|
+
CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1",
|
|
1670
|
+
CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: process.env.CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS ?? String(CLAUDE_PRINT_BG_WAIT_CEILING_MS)
|
|
1671
|
+
}
|
|
1400
1672
|
};
|
|
1401
1673
|
},
|
|
1402
1674
|
parseEvent(line) {
|
|
@@ -1404,13 +1676,8 @@ var claudeAdapter = {
|
|
|
1404
1676
|
if (!trimmed) return null;
|
|
1405
1677
|
try {
|
|
1406
1678
|
const obj = JSON.parse(trimmed);
|
|
1407
|
-
if (obj.type === "system"
|
|
1408
|
-
|
|
1409
|
-
if (typeof sid === "string") return { type: "session_id", data: sid };
|
|
1410
|
-
return null;
|
|
1411
|
-
}
|
|
1412
|
-
if (obj.type === "system" && typeof obj.session_id === "string") {
|
|
1413
|
-
return { type: "session_id", data: obj.session_id };
|
|
1679
|
+
if (obj.type === "system") {
|
|
1680
|
+
return eventsFromClaudeSystem(obj);
|
|
1414
1681
|
}
|
|
1415
1682
|
if (obj.type === "assistant" || obj.type === "user") {
|
|
1416
1683
|
const parentId = claudeParentToolUseId(obj);
|
|
@@ -1791,13 +2058,22 @@ var codexAdapter = {
|
|
|
1791
2058
|
const events = [
|
|
1792
2059
|
{ type: "tool_use", id: item.id, name: "Bash", input }
|
|
1793
2060
|
];
|
|
1794
|
-
|
|
2061
|
+
const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
|
|
2062
|
+
const output = typeof item.aggregated_output === "string" && item.aggregated_output ? item.aggregated_output : void 0;
|
|
2063
|
+
if (finished) {
|
|
1795
2064
|
events.push({
|
|
1796
2065
|
type: "tool_result",
|
|
1797
2066
|
id: item.id,
|
|
1798
|
-
content:
|
|
2067
|
+
content: output,
|
|
1799
2068
|
isError: item.status === "failed"
|
|
1800
2069
|
});
|
|
2070
|
+
} else if (output) {
|
|
2071
|
+
events.push({
|
|
2072
|
+
type: "tool_result",
|
|
2073
|
+
id: item.id,
|
|
2074
|
+
content: output,
|
|
2075
|
+
partial: true
|
|
2076
|
+
});
|
|
1801
2077
|
}
|
|
1802
2078
|
return events.length === 1 ? events[0] : events;
|
|
1803
2079
|
}
|
|
@@ -1840,9 +2116,6 @@ var codexAdapter = {
|
|
|
1840
2116
|
if (sid && (type === "thread.started" || type === "session" || !type)) {
|
|
1841
2117
|
return { type: "session_id", data: sid };
|
|
1842
2118
|
}
|
|
1843
|
-
if (sid && type.endsWith(".started")) {
|
|
1844
|
-
return { type: "session_id", data: sid };
|
|
1845
|
-
}
|
|
1846
2119
|
if (type === "turn.completed" || type === "turn_completed") {
|
|
1847
2120
|
const usage = usageFromCodex(obj.usage);
|
|
1848
2121
|
return usage ? { type: "usage", data: usage, scope: "turn" } : null;
|
|
@@ -2246,7 +2519,8 @@ var opencodeAdapter = {
|
|
|
2246
2519
|
return { type: "stderr", data: detail };
|
|
2247
2520
|
}
|
|
2248
2521
|
const sid = typeof obj.sessionID === "string" && obj.sessionID || typeof obj.sessionId === "string" && obj.sessionId || typeof obj.session_id === "string" && obj.session_id;
|
|
2249
|
-
|
|
2522
|
+
const childSid = str2(obj.childSessionID) ?? str2(obj.childSessionId) ?? str2(obj.parentID) ?? str2(obj.parentId);
|
|
2523
|
+
if (sid && !childSid && (!obj.type || obj.type === "step_start" || obj.type === "session")) {
|
|
2250
2524
|
return { type: "session_id", data: sid };
|
|
2251
2525
|
}
|
|
2252
2526
|
if (obj.type === "text") {
|
|
@@ -2266,13 +2540,16 @@ var opencodeAdapter = {
|
|
|
2266
2540
|
);
|
|
2267
2541
|
const events = [{ type: "tool_use", id, name, input }];
|
|
2268
2542
|
const output = state?.output;
|
|
2269
|
-
|
|
2543
|
+
const finished = state?.status === "completed" || state?.status === "error" || state?.status === "failed";
|
|
2544
|
+
const running = state?.status === "running" || state?.status === "in_progress" || state?.status === "pending";
|
|
2545
|
+
if (output != null || finished) {
|
|
2270
2546
|
const content = typeof output === "string" ? output : output != null ? JSON.stringify(output) : formatUnknownDetail(state?.error) || void 0;
|
|
2271
2547
|
events.push({
|
|
2272
2548
|
type: "tool_result",
|
|
2273
2549
|
id,
|
|
2274
2550
|
content,
|
|
2275
|
-
isError: state?.status === "error" || state?.status === "failed"
|
|
2551
|
+
isError: state?.status === "error" || state?.status === "failed",
|
|
2552
|
+
...running && !finished ? { partial: true } : {}
|
|
2276
2553
|
});
|
|
2277
2554
|
}
|
|
2278
2555
|
return events.length === 1 ? events[0] : events;
|
|
@@ -2307,14 +2584,17 @@ var opencodeAdapter = {
|
|
|
2307
2584
|
withEventParentId({ type: "tool_use", id, name, input }, parentId)
|
|
2308
2585
|
];
|
|
2309
2586
|
const output = state?.output ?? part.output;
|
|
2310
|
-
|
|
2587
|
+
const finished = state?.status === "completed" || state?.status === "error" || state?.status === "failed";
|
|
2588
|
+
const running = state?.status === "running" || state?.status === "in_progress" || state?.status === "pending";
|
|
2589
|
+
if (output != null || finished) {
|
|
2311
2590
|
nested.push(
|
|
2312
2591
|
withEventParentId(
|
|
2313
2592
|
{
|
|
2314
2593
|
type: "tool_result",
|
|
2315
2594
|
id,
|
|
2316
2595
|
content: typeof output === "string" ? output : output != null ? JSON.stringify(output) : void 0,
|
|
2317
|
-
isError: state?.status === "error" || state?.status === "failed"
|
|
2596
|
+
isError: state?.status === "error" || state?.status === "failed",
|
|
2597
|
+
...running && !finished ? { partial: true } : {}
|
|
2318
2598
|
},
|
|
2319
2599
|
parentId
|
|
2320
2600
|
)
|
|
@@ -2868,6 +3148,10 @@ export {
|
|
|
2868
3148
|
toolDetail,
|
|
2869
3149
|
toolDescription,
|
|
2870
3150
|
isSubagentToolName,
|
|
3151
|
+
isPollWrapperToolName,
|
|
3152
|
+
isShellToolName,
|
|
3153
|
+
toolActivityLine,
|
|
3154
|
+
liveActivitySummary,
|
|
2871
3155
|
messagePartParentId,
|
|
2872
3156
|
withEventParentId,
|
|
2873
3157
|
withEventsParentId,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveGithubRepoSlug
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FZCIQYNQ.js";
|
|
4
4
|
import {
|
|
5
5
|
resolveThreadDefaults
|
|
6
6
|
} from "./chunk-4NR5FL46.js";
|
|
@@ -61,7 +61,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
61
61
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
62
62
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
63
63
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
|
|
64
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply. wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
|
|
64
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply. wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
|
|
65
65
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
66
66
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
67
67
|
"Setup / run:",
|
|
@@ -36,6 +36,11 @@ function createAgentStreamCoalescer(emit, opts) {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
if (!event.data) return;
|
|
39
|
+
if (event.type === "thinking" && event.replace) {
|
|
40
|
+
flush();
|
|
41
|
+
emit(event);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
39
44
|
if (pending && pending.type === event.type && parentKey(pending) === parentKey(event)) {
|
|
40
45
|
pending.data += event.data;
|
|
41
46
|
} else {
|
|
@@ -96,6 +96,34 @@ function withExportedPath(command, pathValue) {
|
|
|
96
96
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// src/git/stale-lock.ts
|
|
100
|
+
import { existsSync as existsSync2, statSync, unlinkSync } from "fs";
|
|
101
|
+
import { join as join2 } from "path";
|
|
102
|
+
var STALE_INDEX_LOCK_MS = 2e4;
|
|
103
|
+
function isIndexLockError(text) {
|
|
104
|
+
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text);
|
|
105
|
+
}
|
|
106
|
+
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
107
|
+
const lockPath = join2(gitDir, "index.lock");
|
|
108
|
+
try {
|
|
109
|
+
if (!existsSync2(lockPath)) return null;
|
|
110
|
+
if (now - statSync(lockPath).mtimeMs < maxAgeMs) return null;
|
|
111
|
+
unlinkSync(lockPath);
|
|
112
|
+
return lockPath;
|
|
113
|
+
} catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
|
|
118
|
+
const now = Date.now();
|
|
119
|
+
const removed = [];
|
|
120
|
+
for (const dir of new Set(gitDirs)) {
|
|
121
|
+
const cleared = clearStaleIndexLock(dir, maxAgeMs, now);
|
|
122
|
+
if (cleared) removed.push(cleared);
|
|
123
|
+
}
|
|
124
|
+
return removed;
|
|
125
|
+
}
|
|
126
|
+
|
|
99
127
|
// src/git/run.ts
|
|
100
128
|
async function run(file, args, opts) {
|
|
101
129
|
ensureAgentPath();
|
|
@@ -123,6 +151,21 @@ async function run(file, args, opts) {
|
|
|
123
151
|
throw err;
|
|
124
152
|
}
|
|
125
153
|
}
|
|
154
|
+
async function resolveGitDirsForLockRecovery(cwd, env = {}) {
|
|
155
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
156
|
+
const [gitDir, commonDir] = await Promise.all([
|
|
157
|
+
run("git", ["rev-parse", "--absolute-git-dir"], { cwd, reject: false, env, timeoutMs: 5e3 }),
|
|
158
|
+
run("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
|
|
159
|
+
cwd,
|
|
160
|
+
reject: false,
|
|
161
|
+
env,
|
|
162
|
+
timeoutMs: 5e3
|
|
163
|
+
})
|
|
164
|
+
]);
|
|
165
|
+
if (gitDir.exitCode === 0 && gitDir.stdout.trim()) dirs.add(gitDir.stdout.trim());
|
|
166
|
+
if (commonDir.exitCode === 0 && commonDir.stdout.trim()) dirs.add(commonDir.stdout.trim());
|
|
167
|
+
return [...dirs];
|
|
168
|
+
}
|
|
126
169
|
async function git(args, cwd, opts) {
|
|
127
170
|
const prefix = [];
|
|
128
171
|
if (opts?.config) {
|
|
@@ -131,21 +174,32 @@ async function git(args, cwd, opts) {
|
|
|
131
174
|
prefix.push("-c", `${key}=${value}`);
|
|
132
175
|
}
|
|
133
176
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
reject: opts?.reject,
|
|
137
|
-
timeoutMs: opts?.timeoutMs,
|
|
177
|
+
const gitArgs = ["--no-pager", ...prefix, ...args];
|
|
178
|
+
const env = {
|
|
138
179
|
// Never block forever on a credential/SSH prompt inside MCP / Electron.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
180
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
181
|
+
GIT_ASKPASS: process.env.GIT_ASKPASS || "echo",
|
|
182
|
+
SSH_ASKPASS: process.env.SSH_ASKPASS || "echo",
|
|
183
|
+
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND || "ssh -o BatchMode=yes -o ConnectTimeout=15",
|
|
184
|
+
GCM_INTERACTIVE: "never",
|
|
185
|
+
GH_PROMPT_DISABLED: "1",
|
|
186
|
+
...opts?.env
|
|
187
|
+
};
|
|
188
|
+
let result = await run("git", gitArgs, { cwd, reject: false, timeoutMs: opts?.timeoutMs, env });
|
|
189
|
+
if (result.exitCode !== 0 && isIndexLockError(result.stderr)) {
|
|
190
|
+
const gitDirs = await resolveGitDirsForLockRecovery(cwd, env);
|
|
191
|
+
const cleared = clearStaleIndexLocks(gitDirs);
|
|
192
|
+
if (cleared.length > 0) {
|
|
193
|
+
result = await run("git", gitArgs, { cwd, reject: false, timeoutMs: opts?.timeoutMs, env });
|
|
147
194
|
}
|
|
148
|
-
}
|
|
195
|
+
}
|
|
196
|
+
if ((opts?.reject ?? true) && result.exitCode !== 0) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Command failed with exit code ${result.exitCode}: git ${gitArgs.join(" ")}
|
|
199
|
+
${result.stderr}`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
149
203
|
}
|
|
150
204
|
async function gh(args, cwd, opts) {
|
|
151
205
|
return run("gh", args, {
|
|
@@ -173,7 +227,9 @@ export {
|
|
|
173
227
|
posixShellSingleQuote,
|
|
174
228
|
resolveCommandBinarySync,
|
|
175
229
|
withExportedPath,
|
|
230
|
+
clearStaleIndexLocks,
|
|
176
231
|
run,
|
|
232
|
+
resolveGitDirsForLockRecovery,
|
|
177
233
|
git,
|
|
178
234
|
gh,
|
|
179
235
|
resolveGhAuthToken
|