mixdog 0.9.37 → 0.9.39
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/package.json +9 -4
- package/scripts/abort-recovery-test.mjs +43 -2
- package/scripts/agent-tag-reuse-smoke.mjs +146 -6
- package/scripts/agent-terminal-reap-test.mjs +127 -0
- package/scripts/agent-trace-io-test.mjs +69 -0
- package/scripts/code-graph-disk-hit-test.mjs +224 -0
- package/scripts/dispatch-persist-recovery-test.mjs +141 -0
- package/scripts/execution-completion-dedup-test.mjs +157 -0
- package/scripts/execution-pending-resume-kick-test.mjs +57 -2
- package/scripts/execution-resume-esc-integration-test.mjs +174 -0
- package/scripts/explore-bench.mjs +101 -8
- package/scripts/explore-prompt-policy-test.mjs +156 -11
- package/scripts/find-fuzzy-hidden-test.mjs +122 -0
- package/scripts/internal-comms-bench-test.mjs +226 -0
- package/scripts/internal-comms-bench.mjs +185 -58
- package/scripts/internal-comms-smoke.mjs +171 -23
- package/scripts/live-worker-smoke.mjs +38 -2
- package/scripts/memory-cycle-routing-test.mjs +111 -0
- package/scripts/memory-rule-contract-test.mjs +93 -0
- package/scripts/notify-completion-mirror-test.mjs +73 -0
- package/scripts/output-style-smoke.mjs +2 -2
- package/scripts/rg-runner-test.mjs +240 -0
- package/scripts/routing-corpus-test.mjs +349 -0
- package/scripts/routing-corpus.mjs +211 -32
- package/scripts/session-orphan-sweep-test.mjs +83 -0
- package/scripts/session-sweep.mjs +266 -0
- package/scripts/steering-drain-buckets-test.mjs +179 -0
- package/scripts/tool-smoke.mjs +21 -13
- package/scripts/tool-tui-presentation-test.mjs +202 -0
- package/src/agents/heavy-worker/AGENT.md +10 -7
- package/src/agents/reviewer/AGENT.md +6 -4
- package/src/agents/worker/AGENT.md +7 -5
- package/src/rules/agent/00-common.md +4 -4
- package/src/rules/agent/00-core.md +11 -14
- package/src/rules/agent/20-skip-protocol.md +3 -3
- package/src/rules/agent/30-explorer.md +56 -48
- package/src/rules/agent/40-cycle1-agent.md +15 -24
- package/src/rules/agent/41-cycle2-agent.md +33 -57
- package/src/rules/agent/42-cycle3-agent.md +28 -42
- package/src/rules/lead/01-general.md +7 -10
- package/src/rules/lead/lead-brief.md +11 -14
- package/src/rules/lead/lead-tool.md +6 -5
- package/src/rules/shared/01-tool.md +44 -41
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +37 -1
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +20 -5
- package/src/runtime/agent/orchestrator/dispatch-persist.mjs +31 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +13 -7
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +21 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +6 -6
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +17 -38
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +5 -4
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +119 -3
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +17 -8
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +270 -78
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +18 -52
- package/src/runtime/agent/orchestrator/session/manager/delivered-completions.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +15 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +41 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store.mjs +339 -63
- package/src/runtime/agent/orchestrator/stall-policy.mjs +37 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +25 -20
- package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +118 -53
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +106 -29
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +151 -64
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +37 -13
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +84 -49
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +172 -23
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +3 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +68 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +17 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +24 -10
- package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +4 -7
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +1 -0
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +4 -4
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +4 -3
- package/src/runtime/memory/lib/memory-cycle3.mjs +12 -2
- package/src/runtime/shared/tool-primitives.mjs +4 -1
- package/src/runtime/shared/tool-status.mjs +27 -0
- package/src/runtime/shared/tool-surface.mjs +6 -3
- package/src/session-runtime/config-helpers.mjs +14 -0
- package/src/session-runtime/context-status.mjs +1 -0
- package/src/session-runtime/effort.mjs +6 -2
- package/src/session-runtime/model-recency.mjs +5 -2
- package/src/session-runtime/provider-models.mjs +3 -3
- package/src/session-runtime/runtime-core.mjs +78 -10
- package/src/session-runtime/tool-catalog.mjs +34 -0
- package/src/session-runtime/warmup-schedulers.mjs +7 -1
- package/src/standalone/agent-tool/notify.mjs +13 -0
- package/src/standalone/agent-tool.mjs +45 -69
- package/src/standalone/explore-tool.mjs +6 -7
- package/src/tui/App.jsx +31 -0
- package/src/tui/app/model-options.mjs +5 -3
- package/src/tui/app/model-picker.mjs +12 -24
- package/src/tui/app/transcript-window.mjs +1 -0
- package/src/tui/components/ToolExecution.jsx +11 -6
- package/src/tui/components/TranscriptItem.jsx +1 -1
- package/src/tui/components/tool-execution/surface-detail.mjs +24 -10
- package/src/tui/components/tool-execution/text-format.mjs +10 -19
- package/src/tui/dist/index.mjs +533 -143
- package/src/tui/engine/agent-job-feed.mjs +153 -16
- package/src/tui/engine/agent-response-tail.mjs +68 -0
- package/src/tui/engine/notification-plan.mjs +16 -0
- package/src/tui/engine/queue-helpers.mjs +8 -0
- package/src/tui/engine/session-api.mjs +8 -2
- package/src/tui/engine/session-flow.mjs +34 -2
- package/src/tui/engine/tool-card-results.mjs +54 -32
- package/src/tui/engine/tool-result-status.mjs +75 -21
- package/src/tui/engine/turn.mjs +83 -43
- package/src/tui/engine.mjs +63 -2
- package/src/workflows/bench/WORKFLOW.md +25 -35
- package/src/workflows/default/WORKFLOW.md +38 -32
- package/src/workflows/solo/WORKFLOW.md +19 -22
- package/scripts/_jitter-fuzz.mjs +0 -44410
- package/scripts/_jitter-fuzz2.mjs +0 -44400
- package/scripts/_jitter-probe.mjs +0 -44397
- package/scripts/_jp2.mjs +0 -45614
package/src/tui/dist/index.mjs
CHANGED
|
@@ -1976,10 +1976,11 @@ function bridgeAgentModelSummary(args) {
|
|
|
1976
1976
|
]);
|
|
1977
1977
|
}
|
|
1978
1978
|
function summarizeLineWindow(a) {
|
|
1979
|
+
const hasOffset = a.offset != null;
|
|
1979
1980
|
const offset = a.offset ?? a.start_line ?? a.startLine ?? a.line;
|
|
1980
1981
|
const limit = a.limit ?? a.line_count ?? a.lineCount ?? a.lines;
|
|
1981
1982
|
if (offset == null && limit == null) return "";
|
|
1982
|
-
const start = Number(offset);
|
|
1983
|
+
const start = Number(offset) + (hasOffset ? 1 : 0);
|
|
1983
1984
|
const count = Number(limit);
|
|
1984
1985
|
if (Number.isFinite(start) && Number.isFinite(count) && count > 0) {
|
|
1985
1986
|
return `lines ${start}-${Math.max(start, start + count - 1)}`;
|
|
@@ -2839,7 +2840,9 @@ function toolWorkUnit(name, args = {}, category = "") {
|
|
|
2839
2840
|
case "read_mcp_resource":
|
|
2840
2841
|
return unitDescriptor("Read", { count: queryCount(a, "uri", "uris") || 1, noun: "resource" });
|
|
2841
2842
|
case "apply_patch": {
|
|
2842
|
-
const
|
|
2843
|
+
const patchText = String(a.patch ?? "");
|
|
2844
|
+
const creating = a.old_string === "" || /^\*\*\*\s+Add File:/mi.test(patchText);
|
|
2845
|
+
const deleting = !creating && a.new_string === "" && a.old_string != null || /^\*\*\*\s+Delete File:/mi.test(patchText);
|
|
2843
2846
|
if (a.dry_run === true) {
|
|
2844
2847
|
return unitDescriptor("Patch", {
|
|
2845
2848
|
count: patchFileCount(a) || 1,
|
|
@@ -2850,8 +2853,8 @@ function toolWorkUnit(name, args = {}, category = "") {
|
|
|
2850
2853
|
}
|
|
2851
2854
|
return unitDescriptor("Patch", {
|
|
2852
2855
|
count: patchFileCount(a) || 1,
|
|
2853
|
-
active: creating ? "Creating" : "Editing",
|
|
2854
|
-
done: creating ? "Created" : "Edited",
|
|
2856
|
+
active: creating ? "Creating" : deleting ? "Deleting" : "Editing",
|
|
2857
|
+
done: creating ? "Created" : deleting ? "Deleted" : "Edited",
|
|
2855
2858
|
noun: "file"
|
|
2856
2859
|
});
|
|
2857
2860
|
}
|
|
@@ -10233,6 +10236,7 @@ function toolHasDisplayResultForRows(item) {
|
|
|
10233
10236
|
}
|
|
10234
10237
|
function toolExpandedRawTextForRows(item, rawRt) {
|
|
10235
10238
|
if (item?.aggregate) return rawRt;
|
|
10239
|
+
if (item?.agentResponseAggregate) return rawRt;
|
|
10236
10240
|
const hasDisplayResult = toolHasDisplayResultForRows(item);
|
|
10237
10241
|
if (hasDisplayResult) return toolDisplayedResultTextForRows(item);
|
|
10238
10242
|
return stripLeadingStatusMarkerFromTextForRows(rawRt || "");
|
|
@@ -12383,10 +12387,11 @@ var compareModelRecency = (a, b) => {
|
|
|
12383
12387
|
}
|
|
12384
12388
|
const ta = releaseTime(a);
|
|
12385
12389
|
const tb = releaseTime(b);
|
|
12386
|
-
if (ta !== tb) return tb - ta;
|
|
12387
|
-
if (!!a?.latest !== !!b?.latest) return a?.latest ? -1 : 1;
|
|
12388
12390
|
const versionDelta = compareModelVersion(a, b);
|
|
12391
|
+
if (ta > 0 && tb > 0 && ta !== tb) return tb - ta;
|
|
12389
12392
|
if (versionDelta) return versionDelta;
|
|
12393
|
+
if (!!a?.latest !== !!b?.latest) return a?.latest ? -1 : 1;
|
|
12394
|
+
if (ta !== tb) return tb - ta;
|
|
12390
12395
|
return String(a?.display || a?.id || "").localeCompare(String(b?.display || b?.id || ""));
|
|
12391
12396
|
};
|
|
12392
12397
|
var modelFamily = (m) => {
|
|
@@ -15835,11 +15840,9 @@ function createModelPicker({
|
|
|
15835
15840
|
setChannelPrompt(null);
|
|
15836
15841
|
setHookPrompt(null);
|
|
15837
15842
|
setSettingsPrompt(null);
|
|
15838
|
-
|
|
15843
|
+
modelPickerRequestRef.current += 1;
|
|
15839
15844
|
let modelPickerClosed = false;
|
|
15840
|
-
let activeModelProvider = null;
|
|
15841
15845
|
let providerListHighlightProvider = null;
|
|
15842
|
-
const isActiveModelPicker = () => !modelPickerClosed && modelPickerRequestRef.current === modelPickerRequest;
|
|
15843
15846
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
|
|
15844
15847
|
const returnLabel = String(options.returnLabel || "Agents");
|
|
15845
15848
|
const returnOnNestedCancel = options.returnOnNestedCancel === true;
|
|
@@ -15853,7 +15856,6 @@ function createModelPicker({
|
|
|
15853
15856
|
let providerModels = Array.isArray(cacheRef.current.models) ? cacheRef.current.models : [];
|
|
15854
15857
|
let refreshModelsPromise = null;
|
|
15855
15858
|
let renderedQuickModels = false;
|
|
15856
|
-
let renderActiveProviderModels = null;
|
|
15857
15859
|
if (!providerModels.length || options.refreshModels === true) {
|
|
15858
15860
|
setPicker({
|
|
15859
15861
|
title: options.title || "Model",
|
|
@@ -15904,16 +15906,12 @@ function createModelPicker({
|
|
|
15904
15906
|
providerListHighlightProvider = renderOptions.highlightProvider;
|
|
15905
15907
|
}
|
|
15906
15908
|
const highlightProvider = renderOptions.highlightProvider || providerListHighlightProvider || null;
|
|
15907
|
-
activeModelProvider = null;
|
|
15908
|
-
renderActiveProviderModels = null;
|
|
15909
15909
|
const openProviderModelsPicker = (provider) => {
|
|
15910
15910
|
if (!provider) return;
|
|
15911
|
-
activeModelProvider = provider;
|
|
15912
|
-
renderActiveProviderModels = () => openProviderModelsPicker(provider);
|
|
15913
15911
|
const providerModels2 = models.filter((model) => model.provider === provider);
|
|
15914
15912
|
const preferredEffort = (values = []) => {
|
|
15915
15913
|
const allowed = values.filter(Boolean);
|
|
15916
|
-
for (const value of ["high", "medium", "low", "none", "xhigh", "max"]) {
|
|
15914
|
+
for (const value of ["high", "medium", "low", "none", "xhigh", "max", "ultra"]) {
|
|
15917
15915
|
if (allowed.includes(value)) return value;
|
|
15918
15916
|
}
|
|
15919
15917
|
return allowed[0] || null;
|
|
@@ -15986,6 +15984,7 @@ ${model?.id || ""}`;
|
|
|
15986
15984
|
if (value === "medium") return "\u25D1";
|
|
15987
15985
|
if (value === "high") return "\u25D5";
|
|
15988
15986
|
if (value === "max") return "\u25C6";
|
|
15987
|
+
if (value === "ultra") return "\u2726";
|
|
15989
15988
|
return "\u25CF";
|
|
15990
15989
|
};
|
|
15991
15990
|
const effortColor = (value) => {
|
|
@@ -15994,6 +15993,7 @@ ${model?.id || ""}`;
|
|
|
15994
15993
|
if (value === "medium") return theme.claude;
|
|
15995
15994
|
if (value === "high") return theme.error;
|
|
15996
15995
|
if (value === "max") return theme.permission;
|
|
15996
|
+
if (value === "ultra") return theme.permission;
|
|
15997
15997
|
return theme.error;
|
|
15998
15998
|
};
|
|
15999
15999
|
const modelFooter = (model = null) => {
|
|
@@ -16128,33 +16128,23 @@ ${model?.id || ""}`;
|
|
|
16128
16128
|
});
|
|
16129
16129
|
};
|
|
16130
16130
|
renderModelPicker();
|
|
16131
|
-
const
|
|
16132
|
-
if (!isActiveModelPicker()) return;
|
|
16131
|
+
const adoptFreshModels = (freshModels) => {
|
|
16133
16132
|
if (!Array.isArray(freshModels) || freshModels.length === 0) return;
|
|
16134
|
-
|
|
16135
|
-
models = normalizeModelOptions(providerModels);
|
|
16136
|
-
cacheRef.current = { models: providerModels, at: Date.now() };
|
|
16137
|
-
if (activeModelProvider === null) {
|
|
16138
|
-
renderModelPicker();
|
|
16139
|
-
} else if (typeof renderActiveProviderModels === "function") {
|
|
16140
|
-
renderActiveProviderModels();
|
|
16141
|
-
}
|
|
16133
|
+
cacheRef.current = { models: freshModels, at: Date.now() };
|
|
16142
16134
|
};
|
|
16143
16135
|
if (renderedQuickModels && refreshModelsPromise) {
|
|
16144
|
-
void refreshModelsPromise.then(
|
|
16136
|
+
void refreshModelsPromise.then(adoptFreshModels).catch(() => {
|
|
16145
16137
|
});
|
|
16146
16138
|
} else if (cacheIsStale) {
|
|
16147
16139
|
if (!providerModelsTtlRefreshPromise) {
|
|
16148
16140
|
providerModelsTtlRefreshPromise = Promise.resolve(loadModels({ force: true })).then((freshModels) => {
|
|
16149
|
-
|
|
16150
|
-
cacheRef.current = { models: freshModels, at: Date.now() };
|
|
16151
|
-
}
|
|
16141
|
+
adoptFreshModels(freshModels);
|
|
16152
16142
|
return freshModels;
|
|
16153
16143
|
}).finally(() => {
|
|
16154
16144
|
providerModelsTtlRefreshPromise = null;
|
|
16155
16145
|
});
|
|
16156
16146
|
}
|
|
16157
|
-
void providerModelsTtlRefreshPromise.
|
|
16147
|
+
void providerModelsTtlRefreshPromise.catch(() => {
|
|
16158
16148
|
});
|
|
16159
16149
|
}
|
|
16160
16150
|
};
|
|
@@ -18531,6 +18521,29 @@ import stringWidth9 from "string-width";
|
|
|
18531
18521
|
|
|
18532
18522
|
// src/tui/components/tool-execution/text-format.mjs
|
|
18533
18523
|
import stripAnsi6 from "strip-ansi";
|
|
18524
|
+
|
|
18525
|
+
// src/runtime/shared/tool-status.mjs
|
|
18526
|
+
function normalizeToolTerminalStatus(value) {
|
|
18527
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
18528
|
+
if (!raw) return "";
|
|
18529
|
+
if (/^(running|pending|queued|in_progress|in-progress)$/.test(raw)) return "running";
|
|
18530
|
+
if (/^(completed|complete|done|success|succeeded|ok)$/.test(raw)) return "completed";
|
|
18531
|
+
if (/^(failed|fail|error|errored|timeout|timed_out|killed)$/.test(raw)) return "failed";
|
|
18532
|
+
if (/^(cancelled|canceled|cancel)$/.test(raw)) return "cancelled";
|
|
18533
|
+
if (/^(denied|deny|refused|rejected)$/.test(raw)) return "denied";
|
|
18534
|
+
return "";
|
|
18535
|
+
}
|
|
18536
|
+
function toolResultTerminalStatus(text) {
|
|
18537
|
+
const body = String(text || "");
|
|
18538
|
+
const tagged = body.match(/<status[^>]*>([\s\S]*?)<\/status>/i)?.[1]?.trim();
|
|
18539
|
+
if (tagged) return normalizeToolTerminalStatus(tagged);
|
|
18540
|
+
const bracketed = body.match(/^\[status:\s*([^\]]*)\]/mi)?.[1]?.trim();
|
|
18541
|
+
if (bracketed) return normalizeToolTerminalStatus(bracketed);
|
|
18542
|
+
const inline = body.match(/^(?:status|state):\s*([^\s·,;]+)/mi)?.[1]?.trim();
|
|
18543
|
+
return normalizeToolTerminalStatus(inline);
|
|
18544
|
+
}
|
|
18545
|
+
|
|
18546
|
+
// src/tui/components/tool-execution/text-format.mjs
|
|
18534
18547
|
var MIN_RESULT_LINE_CHARS = 24;
|
|
18535
18548
|
var RESULT_LINE_HARD_MAX = 80;
|
|
18536
18549
|
var SUMMARY_MAX_CHARS = 48;
|
|
@@ -18600,30 +18613,20 @@ function shellResultStatus(value) {
|
|
|
18600
18613
|
return match ? String(match[1] || "").toLowerCase() : "";
|
|
18601
18614
|
}
|
|
18602
18615
|
function normalizeTerminalStatus(value) {
|
|
18603
|
-
|
|
18604
|
-
if (!raw) return "";
|
|
18605
|
-
if (/^(running|pending|queued|in_progress|in-progress)$/.test(raw)) return "running";
|
|
18606
|
-
if (/^(completed|complete|done|success|succeeded|ok)$/.test(raw)) return "completed";
|
|
18607
|
-
if (/^(failed|fail|error|errored|timeout|timed_out|killed)$/.test(raw)) return "failed";
|
|
18608
|
-
if (/^(cancelled|canceled|cancel)$/.test(raw)) return "cancelled";
|
|
18609
|
-
return "";
|
|
18616
|
+
return normalizeToolTerminalStatus(value);
|
|
18610
18617
|
}
|
|
18611
18618
|
function displayTerminalStatus(value) {
|
|
18619
|
+
if (String(value || "").trim().toLowerCase() === "exit") return "Exit";
|
|
18612
18620
|
const status = normalizeTerminalStatus(value);
|
|
18613
18621
|
if (status === "running") return "Running";
|
|
18614
18622
|
if (status === "completed") return "Finished";
|
|
18615
18623
|
if (status === "failed") return "Failed";
|
|
18616
18624
|
if (status === "cancelled") return "Cancelled";
|
|
18625
|
+
if (status === "denied") return "Denied";
|
|
18617
18626
|
return "";
|
|
18618
18627
|
}
|
|
18619
18628
|
function resultTerminalStatus(value) {
|
|
18620
|
-
|
|
18621
|
-
const tagged = text.match(/<status[^>]*>([\s\S]*?)<\/status>/i)?.[1]?.trim();
|
|
18622
|
-
if (tagged) return normalizeTerminalStatus(tagged);
|
|
18623
|
-
const bracketed = text.match(/^\[status:\s*([^\]]*)\]/mi)?.[1]?.trim();
|
|
18624
|
-
if (bracketed) return normalizeTerminalStatus(bracketed);
|
|
18625
|
-
const inline = text.match(/^(?:status|state):\s*([^\s·,;]+)/mi)?.[1]?.trim();
|
|
18626
|
-
return normalizeTerminalStatus(inline);
|
|
18629
|
+
return toolResultTerminalStatus(value);
|
|
18627
18630
|
}
|
|
18628
18631
|
var LEADING_STATUS_MARKER_LINE_RE2 = /^\[status:\s*[^\]]*\]\s*$/i;
|
|
18629
18632
|
function stripLeadingStatusMarkerLines(lines) {
|
|
@@ -18647,11 +18650,15 @@ function isShellTool(normalizedName, label = "") {
|
|
|
18647
18650
|
const l = String(label || "").toLowerCase();
|
|
18648
18651
|
return n === "shell" || n === "bash" || n === "bash_session" || n === "shell_command" || n === "job_wait" || l === "run";
|
|
18649
18652
|
}
|
|
18650
|
-
function shellDisplayStatus({ pending = false, failedCount = 0, isError = false, result = "" } = {}) {
|
|
18653
|
+
function shellDisplayStatus({ pending = false, failedCount = 0, exitFailedCount = 0, isError = false, result = "" } = {}) {
|
|
18651
18654
|
const status = shellResultStatus(result);
|
|
18652
18655
|
if (pending || /^(running|pending|queued)$/.test(status)) return "running";
|
|
18653
18656
|
if (/^cancel/.test(status)) return "cancelled";
|
|
18654
|
-
if (/^(failed|error|killed|timeout)$/.test(status)
|
|
18657
|
+
if (/^(failed|error|killed|timeout)$/.test(status)) return "failed";
|
|
18658
|
+
const realFailed = Math.max(0, Number(failedCount) - Number(exitFailedCount));
|
|
18659
|
+
if (realFailed > 0) return "failed";
|
|
18660
|
+
if (Number(exitFailedCount) > 0) return "exit";
|
|
18661
|
+
if (isError || failedCount > 0) return "failed";
|
|
18655
18662
|
return "completed";
|
|
18656
18663
|
}
|
|
18657
18664
|
function shellHeader(status, count = 1) {
|
|
@@ -18707,7 +18714,9 @@ function withModelAndTag(label, args) {
|
|
|
18707
18714
|
function joinActionAgent(action, agent) {
|
|
18708
18715
|
return agent ? `${action} ${agent}` : action;
|
|
18709
18716
|
}
|
|
18710
|
-
function agentResponseTitle(args) {
|
|
18717
|
+
function agentResponseTitle(args, count = 1) {
|
|
18718
|
+
const total = Math.max(1, Number(count) || 1);
|
|
18719
|
+
if (total > 1) return `Responses ${total} agents`;
|
|
18711
18720
|
const name = titleizeAgentName(args?.agent || args?.subagent_type || args?.name || "");
|
|
18712
18721
|
return withModelAndTag(joinActionAgent("Response", name), args);
|
|
18713
18722
|
}
|
|
@@ -18962,13 +18971,17 @@ function clampFailureCount(errorCount, groupCount, isError) {
|
|
|
18962
18971
|
if (Number.isFinite(explicit)) return Math.max(0, Math.min(groupCount, Math.floor(explicit)));
|
|
18963
18972
|
return isError ? groupCount : 0;
|
|
18964
18973
|
}
|
|
18965
|
-
function toolStatusColor({ pending, groupCount, callFailedCount = 0, terminalStatus = "" }) {
|
|
18974
|
+
function toolStatusColor({ pending, groupCount, callFailedCount = 0, exitFailedCount = 0, terminalStatus = "" }) {
|
|
18966
18975
|
if (pending) return theme.text;
|
|
18967
18976
|
const status = normalizeTerminalStatus(terminalStatus);
|
|
18968
18977
|
if (status === "cancelled") return theme.warning;
|
|
18969
|
-
if (
|
|
18970
|
-
if (
|
|
18971
|
-
|
|
18978
|
+
if (status === "denied") return theme.warning;
|
|
18979
|
+
if (callFailedCount > 0) {
|
|
18980
|
+
if (groupCount > 1 && callFailedCount < groupCount) return theme.mixdogOrange || theme.warning;
|
|
18981
|
+
return theme.error;
|
|
18982
|
+
}
|
|
18983
|
+
if (exitFailedCount > 0) return theme.warning;
|
|
18984
|
+
return theme.success;
|
|
18972
18985
|
}
|
|
18973
18986
|
|
|
18974
18987
|
// src/tui/components/tool-execution/ResultBody.jsx
|
|
@@ -18999,7 +19012,7 @@ var TOOL_ANIM_TICK_MS = TOOL_BLINK_MS;
|
|
|
18999
19012
|
function statusCopy(name, label, count, doneCount, pending, isError, args = {}) {
|
|
19000
19013
|
return formatToolActionHeader(name, args, { pending, count });
|
|
19001
19014
|
}
|
|
19002
|
-
function ToolExecution({ name, args, result, rawResult, isError, errorCount, callErrorCount, expanded, columns = 80, attached = false, count = 1, completedCount = 0, startedAt = 0, completedAt = 0, aggregate = false, categories = {}, doneCategories = null, headerFinalized = true, deferredDisplayReady = false }) {
|
|
19015
|
+
function ToolExecution({ name, args, result, rawResult, isError, errorCount, callErrorCount, exitErrorCount, expanded, columns = 80, attached = false, count = 1, completedCount = 0, startedAt = 0, completedAt = 0, aggregate = false, categories = {}, doneCategories = null, headerFinalized = true, deferredDisplayReady = false, agentResponseAggregate = false }) {
|
|
19003
19016
|
const rowWidth = Math.max(1, Number(columns || 80));
|
|
19004
19017
|
const groupCount = Math.max(1, Number(count || 1));
|
|
19005
19018
|
const doneCount = Math.max(0, Math.min(groupCount, Number(completedCount || (result == null ? 0 : groupCount))));
|
|
@@ -19023,6 +19036,7 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, cal
|
|
|
19023
19036
|
const elapsed = elapsedMs >= 1e3 ? formatElapsed(elapsedMs) : "";
|
|
19024
19037
|
const failedCount = clampFailureCount(errorCount, groupCount, isError);
|
|
19025
19038
|
const callFailedCount = clampFailureCount(callErrorCount, groupCount, false);
|
|
19039
|
+
const exitFailedCount = clampFailureCount(exitErrorCount, groupCount, false);
|
|
19026
19040
|
const displayGroupCount = groupCount;
|
|
19027
19041
|
const displayCategories = normalizeCountMap(categories || {});
|
|
19028
19042
|
const normalizedDoneCategories = doneCategories ? normalizeCountMap(doneCategories) : displayCategories;
|
|
@@ -19048,7 +19062,7 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, cal
|
|
|
19048
19062
|
detailText = "";
|
|
19049
19063
|
}
|
|
19050
19064
|
const aggregateTerminalStatus = pending ? "running" : resultTerminalStatus(rt) || (isError || failedCount > 0 ? "failed" : "completed");
|
|
19051
|
-
const dotColor2 = toolStatusColor({ pending, groupCount, callFailedCount, terminalStatus: aggregateTerminalStatus });
|
|
19065
|
+
const dotColor2 = toolStatusColor({ pending, groupCount, callFailedCount, exitFailedCount, terminalStatus: aggregateTerminalStatus });
|
|
19052
19066
|
const dotText2 = pending && !blinkOn ? " " : TURN_MARKER;
|
|
19053
19067
|
const gutter2 = 2;
|
|
19054
19068
|
const showHeaderExpandHint2 = hasRawResult;
|
|
@@ -19103,7 +19117,7 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, cal
|
|
|
19103
19117
|
const firstResultLine = hasDisplayResult ? String(lines[0] ?? "") : "";
|
|
19104
19118
|
const firstResultLineClipped = hasDisplayBody && stringWidth9(firstResultLine) > maxResultChars;
|
|
19105
19119
|
const hasHiddenDetail = !pending && hasDisplayBody && (totalLines > 1 || firstResultLineClipped || Boolean(resultSummary));
|
|
19106
|
-
const shellStatus = isShellSurface ? shellDisplayStatus({ pending, failedCount, isError, result: displayedResultText }) : "";
|
|
19120
|
+
const shellStatus = isShellSurface ? shellDisplayStatus({ pending, failedCount, exitFailedCount, isError, result: displayedResultText }) : "";
|
|
19107
19121
|
const shellElapsed = isShellSurface ? shellResultElapsed(displayedResultText) || elapsed : "";
|
|
19108
19122
|
const backgroundElapsed = backgroundMeta ? backgroundTaskElapsed(backgroundMeta, elapsed) : isBackgroundTaskTool(normalizedName) ? backgroundTaskElapsed(parsedArgs, elapsed) : "";
|
|
19109
19123
|
const toolArgPath = parsedArgs?.path ?? parsedArgs?.file_path ?? parsedArgs?.file ?? "";
|
|
@@ -19128,7 +19142,7 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, cal
|
|
|
19128
19142
|
const collapsedDetail = pending ? pendingDetailPlaceholder : isShellSurface ? prefixElapsed(mergeTerminalDetail(shellStatus, shellCollapsedSummary), shellElapsed) : mergeTerminalDetail(terminalStatus, nonShellDetail);
|
|
19129
19143
|
const backgroundMetadataExpandable = isBackgroundMetadataResult && hasRawResult && !pending;
|
|
19130
19144
|
const showRawResult = expanded && (hasDisplayBody || hasRawResult) && (!isBackgroundMetadataResult || hasRawResult);
|
|
19131
|
-
const detailLines = showRawResult ? hasDisplayBody ? lines : rawRt ? stripLeadingStatusMarkerLines(rawRt.split("\n")) : [] : collapsedDetail ? [collapsedDetail] : [];
|
|
19145
|
+
const detailLines = showRawResult ? agentResponseAggregate && hasRawResult ? stripLeadingStatusMarkerLines(rawRt.split("\n")) : hasDisplayBody ? lines : rawRt ? stripLeadingStatusMarkerLines(rawRt.split("\n")) : [] : collapsedDetail ? [collapsedDetail] : [];
|
|
19132
19146
|
const isPendingPlaceholderDetail = !showRawResult && Boolean(pendingDetailPlaceholder);
|
|
19133
19147
|
const detailColor = isPendingPlaceholderDetail ? theme.subtle : theme.text;
|
|
19134
19148
|
const isAgentResult = !isBackgroundResult && !pending && isAgentTool(normalizedName) && hasDisplayResult;
|
|
@@ -19148,14 +19162,14 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, cal
|
|
|
19148
19162
|
const keepAgentDetail = (isError || agentFailureText) && !(agentHeaderFailure && !agentSurfaceBrief);
|
|
19149
19163
|
visibleDetailLines = keepAgentDetail ? [agentDetailLine] : [];
|
|
19150
19164
|
}
|
|
19151
|
-
const finalStatusColor = toolStatusColor({ pending, groupCount, callFailedCount, terminalStatus });
|
|
19165
|
+
const finalStatusColor = toolStatusColor({ pending, groupCount, callFailedCount, exitFailedCount, terminalStatus });
|
|
19152
19166
|
const dotColor = finalStatusColor;
|
|
19153
19167
|
const markerGlyph = isAgentResponse ? AGENT_RESPONSE_MARKER : isAgentSurfaceCard ? AGENT_CALL_MARKER : TURN_MARKER;
|
|
19154
19168
|
const isDirectionalMarker = isAgentResponse || isAgentSurfaceCard;
|
|
19155
19169
|
const markerText = isDirectionalMarker ? `${markerGlyph} ` : markerGlyph;
|
|
19156
19170
|
const dotText = pending && !blinkOn ? " " : markerText;
|
|
19157
19171
|
let labelText;
|
|
19158
|
-
if (isAgentResponse) labelText = agentResponseTitle(parsedArgs);
|
|
19172
|
+
if (isAgentResponse) labelText = agentResponseTitle(parsedArgs, displayGroupCount);
|
|
19159
19173
|
else if (isBackgroundResponse) labelText = backgroundTaskResultTitle(normalizedName, backgroundMeta || parsedArgs);
|
|
19160
19174
|
else if (isBackgroundMetadataResult) labelText = backgroundTaskActionTitle(normalizedName, backgroundMeta);
|
|
19161
19175
|
else if (isShellSurface) labelText = shellHeader(shellStatus, displayGroupCount);
|
|
@@ -19364,7 +19378,7 @@ var Item = React19.memo(function Item2({ item, prevKind, columns, toolOutputExpa
|
|
|
19364
19378
|
node = /* @__PURE__ */ jsx19(ToolHookDenialCard, { item, columns });
|
|
19365
19379
|
break;
|
|
19366
19380
|
}
|
|
19367
|
-
node = /* @__PURE__ */ jsx19(ToolExecution, { name: item.name, args: item.args, result: item.result, rawResult: item.rawResult, isError: item.isError, errorCount: item.errorCount, callErrorCount: item.callErrorCount, expanded: toolOutputExpanded || item.expanded, columns, attached: false, count: item.count, completedCount: item.completedCount, startedAt: item.startedAt, completedAt: item.completedAt, aggregate: item.aggregate, categories: item.categories, doneCategories: item.doneCategories, headerFinalized: item.headerFinalized, deferredDisplayReady: item.deferredDisplayReady });
|
|
19381
|
+
node = /* @__PURE__ */ jsx19(ToolExecution, { name: item.name, args: item.args, result: item.result, rawResult: item.rawResult, isError: item.isError, errorCount: item.errorCount, callErrorCount: item.callErrorCount, exitErrorCount: item.exitErrorCount, expanded: toolOutputExpanded || item.expanded, columns, attached: false, count: item.count, completedCount: item.completedCount, startedAt: item.startedAt, completedAt: item.completedAt, aggregate: item.aggregate, categories: item.categories, doneCategories: item.doneCategories, headerFinalized: item.headerFinalized, deferredDisplayReady: item.deferredDisplayReady, agentResponseAggregate: item.agentResponseAggregate });
|
|
19368
19382
|
break;
|
|
19369
19383
|
}
|
|
19370
19384
|
case "notice":
|
|
@@ -19672,6 +19686,32 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19672
19686
|
searchModelsCacheRef.current = { models: null, at: 0 };
|
|
19673
19687
|
}
|
|
19674
19688
|
}, []);
|
|
19689
|
+
useEffect10(() => {
|
|
19690
|
+
let alive = true;
|
|
19691
|
+
const timer2 = setTimeout(async () => {
|
|
19692
|
+
const seq = onboardingPrefetchSeqRef.current;
|
|
19693
|
+
try {
|
|
19694
|
+
const models = await Promise.resolve(store.listProviderModels?.() || []);
|
|
19695
|
+
if (alive && seq === onboardingPrefetchSeqRef.current && Array.isArray(models) && models.length > 0 && !Array.isArray(providerModelsCacheRef.current.models)) {
|
|
19696
|
+
providerModelsCacheRef.current = { models, at: Date.now() };
|
|
19697
|
+
}
|
|
19698
|
+
} catch {
|
|
19699
|
+
}
|
|
19700
|
+
if (!alive) return;
|
|
19701
|
+
try {
|
|
19702
|
+
const searchModels = await Promise.resolve(store.listSearchModels?.() || []);
|
|
19703
|
+
if (alive && Array.isArray(searchModels) && searchModels.length > 0 && !Array.isArray(searchModelsCacheRef.current.models)) {
|
|
19704
|
+
searchModelsCacheRef.current = { models: searchModels, at: Date.now() };
|
|
19705
|
+
}
|
|
19706
|
+
} catch {
|
|
19707
|
+
}
|
|
19708
|
+
}, 1500);
|
|
19709
|
+
timer2.unref?.();
|
|
19710
|
+
return () => {
|
|
19711
|
+
alive = false;
|
|
19712
|
+
clearTimeout(timer2);
|
|
19713
|
+
};
|
|
19714
|
+
}, [store]);
|
|
19675
19715
|
const { onboardingWarnReopen, openOnboardingAuthStep } = createOnboardingSteps({
|
|
19676
19716
|
store,
|
|
19677
19717
|
setPicker,
|
|
@@ -22507,18 +22547,6 @@ function bracketField(text, name) {
|
|
|
22507
22547
|
const re = new RegExp(`^\\[${name}:\\s*([^\\]]*)\\]`, "mi");
|
|
22508
22548
|
return re.exec(String(text ?? ""))?.[1]?.trim() || "";
|
|
22509
22549
|
}
|
|
22510
|
-
function toolResultStatus(text) {
|
|
22511
|
-
const value = String(text ?? "");
|
|
22512
|
-
const tagged = textBetweenTag2(value, "status");
|
|
22513
|
-
if (tagged) return tagged.trim();
|
|
22514
|
-
const bracketed = bracketField(value, "status");
|
|
22515
|
-
if (bracketed) return bracketed.trim();
|
|
22516
|
-
const inline = /^(?:status|state):\s*([^\s·,;]+)/mi.exec(value);
|
|
22517
|
-
return inline ? inline[1].trim() : "";
|
|
22518
|
-
}
|
|
22519
|
-
function isErrorToolStatus(status) {
|
|
22520
|
-
return /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(String(status || "").trim());
|
|
22521
|
-
}
|
|
22522
22550
|
function parseSyntheticAgentMessage(text) {
|
|
22523
22551
|
const value = String(text ?? "").trim();
|
|
22524
22552
|
if (!value) return null;
|
|
@@ -22625,6 +22653,7 @@ function agentArgsWithResultMetadata(args, parsed) {
|
|
|
22625
22653
|
|
|
22626
22654
|
// src/tui/engine/queue-helpers.mjs
|
|
22627
22655
|
var QUEUE_PRIORITY = { now: 0, next: 1, later: 2 };
|
|
22656
|
+
var STEERING_SUPPRESSED_DISPLAY = "\0mixdog:suppress-steer-display\0";
|
|
22628
22657
|
function queuePriorityValue(value) {
|
|
22629
22658
|
return QUEUE_PRIORITY[String(value || "next")] ?? QUEUE_PRIORITY.next;
|
|
22630
22659
|
}
|
|
@@ -22770,6 +22799,13 @@ function notificationQueueKey(event, text, parsed) {
|
|
|
22770
22799
|
const hasBody = /\n\s*\n[\s\S]*\S/.test(String(text || "")) ? "b1" : "b0";
|
|
22771
22800
|
return [id, type || fallbackKind, status, hasBody].filter(Boolean).join(":");
|
|
22772
22801
|
}
|
|
22802
|
+
function executionCardKey(event, text, parsed) {
|
|
22803
|
+
const meta = event?.meta && typeof event.meta === "object" ? event.meta : {};
|
|
22804
|
+
const executionId = String(meta.execution_id || "").trim();
|
|
22805
|
+
if (!executionId) return notificationQueueKey(event, text, parsed);
|
|
22806
|
+
const hasBody = /\n\s*\n[\s\S]*\S/.test(String(text || "")) ? "b1" : "b0";
|
|
22807
|
+
return `card:${executionId}:${hasBody}`;
|
|
22808
|
+
}
|
|
22773
22809
|
function isExecutionNotification(event, text, parsed) {
|
|
22774
22810
|
const meta = event?.meta && typeof event.meta === "object" ? event.meta : {};
|
|
22775
22811
|
if (meta.execution_id || meta.execution_surface) return true;
|
|
@@ -22868,23 +22904,43 @@ var yieldToRenderer = ({ frames = 1 } = {}) => new Promise((resolve5) => {
|
|
|
22868
22904
|
|
|
22869
22905
|
// src/tui/engine/tool-result-status.mjs
|
|
22870
22906
|
var CANCELLED_RESULT_STATUS_LINE = "[status: cancelled]";
|
|
22907
|
+
function shellCommandExitCode(text) {
|
|
22908
|
+
const body = String(text || "");
|
|
22909
|
+
if (!/^\s*(?:Error:\s*)?\[shell-run-failed\]/i.test(body)) return null;
|
|
22910
|
+
const header = body.split("\n", 1)[0] || "";
|
|
22911
|
+
if (/\[timeout:|\[signal:|timed out|aborted|interrupted/i.test(header)) return null;
|
|
22912
|
+
const m = header.match(/\[exit code:\s*(\d+)\]/i);
|
|
22913
|
+
if (!m) return null;
|
|
22914
|
+
const code = Number(m[1]);
|
|
22915
|
+
return Number.isFinite(code) ? code : null;
|
|
22916
|
+
}
|
|
22917
|
+
function toolCallOutcome(message, rawText) {
|
|
22918
|
+
const exitCode = shellCommandExitCode(rawText);
|
|
22919
|
+
if (exitCode != null) {
|
|
22920
|
+
return { isCallError: false, isExitError: true, exitCode };
|
|
22921
|
+
}
|
|
22922
|
+
const isCallError = message?.isError === true || message?.toolKind === "error";
|
|
22923
|
+
return {
|
|
22924
|
+
isCallError,
|
|
22925
|
+
isExitError: false,
|
|
22926
|
+
exitCode
|
|
22927
|
+
};
|
|
22928
|
+
}
|
|
22929
|
+
function failureDetailText({ succeeded = 0, realErrors = 0, exitErrors = 0, exitCode } = {}) {
|
|
22930
|
+
const parts = [];
|
|
22931
|
+
if (succeeded > 0) parts.push(`${succeeded} Ok`);
|
|
22932
|
+
if (realErrors > 0) parts.push(`${realErrors} Failed`);
|
|
22933
|
+
if (exitErrors > 0) {
|
|
22934
|
+
const solo = exitErrors === 1 && realErrors === 0 && succeeded === 0;
|
|
22935
|
+
parts.push(solo && Number.isFinite(exitCode) ? `Exit ${exitCode}` : `${exitErrors} Exit`);
|
|
22936
|
+
}
|
|
22937
|
+
return parts.join(" \xB7 ");
|
|
22938
|
+
}
|
|
22871
22939
|
function normalizedResultStatusToken(value) {
|
|
22872
|
-
|
|
22873
|
-
if (!raw) return "";
|
|
22874
|
-
if (/^(running|pending|queued|in_progress|in-progress)$/.test(raw)) return "running";
|
|
22875
|
-
if (/^(completed|complete|done|success|succeeded|ok)$/.test(raw)) return "completed";
|
|
22876
|
-
if (/^(failed|fail|error|errored|timeout|timed_out|killed)$/.test(raw)) return "failed";
|
|
22877
|
-
if (/^(cancelled|canceled|cancel)$/.test(raw)) return "cancelled";
|
|
22878
|
-
return "";
|
|
22940
|
+
return normalizeToolTerminalStatus(value);
|
|
22879
22941
|
}
|
|
22880
22942
|
function resultTextTerminalStatus(text) {
|
|
22881
|
-
|
|
22882
|
-
const tagged = body.match(/<status[^>]*>([\s\S]*?)<\/status>/i)?.[1]?.trim();
|
|
22883
|
-
if (tagged) return normalizedResultStatusToken(tagged);
|
|
22884
|
-
const bracketed = body.match(/^\[status:\s*([^\]]*)\]/mi)?.[1]?.trim();
|
|
22885
|
-
if (bracketed) return normalizedResultStatusToken(bracketed);
|
|
22886
|
-
const inline = body.match(/^(?:status|state):\s*([^\s·,;]+)/mi)?.[1]?.trim();
|
|
22887
|
-
return normalizedResultStatusToken(inline);
|
|
22943
|
+
return toolResultTerminalStatus(text);
|
|
22888
22944
|
}
|
|
22889
22945
|
function itemHasKnownTerminalStatus(item, texts = []) {
|
|
22890
22946
|
const settled = (token) => token === "completed" || token === "failed" || token === "cancelled";
|
|
@@ -22906,11 +22962,14 @@ ${body}`;
|
|
|
22906
22962
|
function groupedToolResultText(group) {
|
|
22907
22963
|
const completed = Math.min(group.count, group.completed);
|
|
22908
22964
|
if (group.count <= 1) return group.results.at(-1)?.text ?? "";
|
|
22909
|
-
|
|
22910
|
-
|
|
22911
|
-
const
|
|
22965
|
+
const exitErrors = Number(group.exitErrors || 0);
|
|
22966
|
+
if (group.errors > 0 || exitErrors > 0) {
|
|
22967
|
+
const realErrors = Math.max(0, Number(group.callErrors || group.errors || 0));
|
|
22968
|
+
const succeeded = Math.max(0, completed - group.errors - exitErrors);
|
|
22969
|
+
const exitCode = group.results.find((result) => result?.isExitError)?.exitCode;
|
|
22970
|
+
const reasons = group.results.filter((result) => result?.isError && !result?.isExitError).map((result) => firstErrorLine(result?.text)).filter(Boolean);
|
|
22912
22971
|
const uniqueReasons = [...new Set(reasons)].slice(0, 2);
|
|
22913
|
-
const base =
|
|
22972
|
+
const base = failureDetailText({ succeeded, realErrors, exitErrors, exitCode });
|
|
22914
22973
|
return [
|
|
22915
22974
|
`${base}${uniqueReasons[0] ? ` \xB7 ${uniqueReasons[0]}` : ""}`,
|
|
22916
22975
|
...uniqueReasons.slice(1)
|
|
@@ -22944,9 +23003,10 @@ ${text}`);
|
|
|
22944
23003
|
}
|
|
22945
23004
|
return chunks.join("\n\n");
|
|
22946
23005
|
}
|
|
22947
|
-
function aggregateBucketForCategory(category) {
|
|
23006
|
+
function aggregateBucketForCategory(category, { agentBatch = "" } = {}) {
|
|
22948
23007
|
const key = String(category || "").trim();
|
|
22949
23008
|
if (key === "Read" || key === "Search") return "category:Read+Search";
|
|
23009
|
+
if (key === "Agent") return agentBatch ? `category:Agent:${agentBatch}` : "category:Agent";
|
|
22950
23010
|
return key ? `category:${key}` : "default";
|
|
22951
23011
|
}
|
|
22952
23012
|
function aggregateSummaries(aggregate) {
|
|
@@ -23065,6 +23125,12 @@ function createToolCardResults({
|
|
|
23065
23125
|
buildAgentJobCardPatch,
|
|
23066
23126
|
agentStatusState
|
|
23067
23127
|
}) {
|
|
23128
|
+
function finalizedErrorFallbackBody(body, text, exitCode) {
|
|
23129
|
+
if (String(body || "").trim()) return body;
|
|
23130
|
+
if (String(text || "").trim()) return text;
|
|
23131
|
+
if (exitCode != null) return `Exit ${exitCode}`;
|
|
23132
|
+
return "Failed";
|
|
23133
|
+
}
|
|
23068
23134
|
function patchToolItem(id, patch) {
|
|
23069
23135
|
const prev = getState().items.find((it) => it.id === id);
|
|
23070
23136
|
const ok = patchItem(id, patch);
|
|
@@ -23082,10 +23148,8 @@ function createToolCardResults({
|
|
|
23082
23148
|
const rawText = toolResultText(message?.content);
|
|
23083
23149
|
const aggregate = card.aggregate;
|
|
23084
23150
|
const callRec = aggregate && callId ? aggregate.calls.get(callId) : null;
|
|
23085
|
-
const
|
|
23086
|
-
const
|
|
23087
|
-
const isResultError = /^\s*\[?error/i.test(rawText) || isErrorToolStatus(toolResultStatus(rawText)) || isMemoryCall && memoryCoreResultErrorText(rawText) != null;
|
|
23088
|
-
const isError = isCallError || isResultError;
|
|
23151
|
+
const { exitCode, isExitError, isCallError } = toolCallOutcome(message, rawText);
|
|
23152
|
+
const isError = isCallError;
|
|
23089
23153
|
const text = isError ? toolErrorDisplay(rawText, card?.name || "tool") : rawText;
|
|
23090
23154
|
if (aggregate && card.itemId === aggregate.itemId) {
|
|
23091
23155
|
if (!callRec) return false;
|
|
@@ -23098,14 +23162,17 @@ function createToolCardResults({
|
|
|
23098
23162
|
assignAggregateSummaryOrder(aggregate, callRec);
|
|
23099
23163
|
callRec.isError = isError;
|
|
23100
23164
|
callRec.isCallError = isCallError;
|
|
23165
|
+
callRec.isExitError = isExitError;
|
|
23166
|
+
callRec.exitCode = exitCode;
|
|
23101
23167
|
callRec.resultText = text;
|
|
23102
23168
|
callRec.resolved = true;
|
|
23103
23169
|
const allCalls = [...aggregate.calls.values()];
|
|
23104
23170
|
const completed = allCalls.filter((r) => r.resolved).length;
|
|
23105
23171
|
const errors = allCalls.filter((r) => r.isError).length;
|
|
23106
23172
|
const callErrors = allCalls.filter((r) => r.isCallError).length;
|
|
23107
|
-
const
|
|
23108
|
-
const
|
|
23173
|
+
const exitErrors = allCalls.filter((r) => r.isExitError).length;
|
|
23174
|
+
const succeeded = Math.max(0, completed - errors - exitErrors);
|
|
23175
|
+
const detailText = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
23109
23176
|
const currentItem = getState().items.find((it) => it.id === card.itemId);
|
|
23110
23177
|
const earlyCompleted = allCalls.filter((r) => r.resolved || r.completedEarly).length;
|
|
23111
23178
|
const visualCompleted = Math.max(completed, earlyCompleted, Math.min(allCalls.length, Number(currentItem?.completedCount || 0)));
|
|
@@ -23118,6 +23185,7 @@ function createToolCardResults({
|
|
|
23118
23185
|
isError: errors > 0,
|
|
23119
23186
|
errorCount: errors,
|
|
23120
23187
|
callErrorCount: callErrors,
|
|
23188
|
+
exitErrorCount: exitErrors,
|
|
23121
23189
|
count: allCalls.length,
|
|
23122
23190
|
completedCount: visualCompleted,
|
|
23123
23191
|
doneCategories: aggregateDoneCategories(allCalls),
|
|
@@ -23127,20 +23195,25 @@ function createToolCardResults({
|
|
|
23127
23195
|
if (callId) done.add(callId);
|
|
23128
23196
|
return true;
|
|
23129
23197
|
}
|
|
23130
|
-
const group = toolGroups.get(card.itemId) || { count: 1, completed: 0, errors: 0, callErrors: 0, results: [] };
|
|
23198
|
+
const group = toolGroups.get(card.itemId) || { count: 1, completed: 0, errors: 0, callErrors: 0, exitErrors: 0, results: [] };
|
|
23131
23199
|
group.completed = Math.min(group.count, group.completed + 1);
|
|
23132
23200
|
group.errors += isError ? 1 : 0;
|
|
23133
23201
|
group.callErrors = (group.callErrors || 0) + (isCallError ? 1 : 0);
|
|
23134
|
-
group.
|
|
23202
|
+
group.exitErrors = (group.exitErrors || 0) + (isExitError ? 1 : 0);
|
|
23203
|
+
group.results.push({ text, isError, isExitError, exitCode });
|
|
23135
23204
|
toolGroups.set(card.itemId, group);
|
|
23136
23205
|
const resultText = groupedToolResultText(group);
|
|
23137
|
-
|
|
23206
|
+
let displayResult = toolGroupedDisplayFallback(resultText, text, rawText);
|
|
23207
|
+
if (group.errors > 0 && !String(displayResult || "").trim()) {
|
|
23208
|
+
displayResult = finalizedErrorFallbackBody(displayResult, text, exitCode);
|
|
23209
|
+
}
|
|
23138
23210
|
const patch = {
|
|
23139
23211
|
result: displayResult,
|
|
23140
23212
|
text: displayResult,
|
|
23141
23213
|
isError: group.errors > 0,
|
|
23142
23214
|
errorCount: group.errors,
|
|
23143
23215
|
callErrorCount: group.callErrors || 0,
|
|
23216
|
+
exitErrorCount: group.exitErrors || 0,
|
|
23144
23217
|
count: group.count,
|
|
23145
23218
|
completedCount: group.completed,
|
|
23146
23219
|
completedAt: Date.now()
|
|
@@ -23153,6 +23226,9 @@ function createToolCardResults({
|
|
|
23153
23226
|
set(agentStatusState({ force: true }));
|
|
23154
23227
|
}
|
|
23155
23228
|
Object.assign(patch, buildAgentJobCardPatch(card.itemId, rawText, isError));
|
|
23229
|
+
if (group.errors > 0 && !String(patch.result || "").trim()) {
|
|
23230
|
+
patch.result = patch.text = finalizedErrorFallbackBody(patch.result, text, exitCode);
|
|
23231
|
+
}
|
|
23156
23232
|
}
|
|
23157
23233
|
patchToolItem(card.itemId, patch);
|
|
23158
23234
|
card.done = true;
|
|
@@ -23203,9 +23279,10 @@ function createToolCardResults({
|
|
|
23203
23279
|
const totalCompleted = completed;
|
|
23204
23280
|
const errors = allCalls.filter((r) => r.isError).length;
|
|
23205
23281
|
const callErrors = allCalls.filter((r) => r.isCallError).length;
|
|
23206
|
-
const
|
|
23282
|
+
const exitErrors = allCalls.filter((r) => r.isExitError).length;
|
|
23283
|
+
const succeeded = Math.max(0, completed - errors - exitErrors);
|
|
23207
23284
|
const rawResult = aggregateRawResult(allCalls);
|
|
23208
|
-
let displayDetail = errors > 0
|
|
23285
|
+
let displayDetail = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
23209
23286
|
if (cancelled) {
|
|
23210
23287
|
const currentItem = getState().items.find((it) => it.id === card.itemId);
|
|
23211
23288
|
displayDetail = withCancelledResultMarker(displayDetail, currentItem);
|
|
@@ -23217,6 +23294,7 @@ function createToolCardResults({
|
|
|
23217
23294
|
isError: errors > 0,
|
|
23218
23295
|
errorCount: errors,
|
|
23219
23296
|
callErrorCount: callErrors,
|
|
23297
|
+
exitErrorCount: exitErrors,
|
|
23220
23298
|
count: allCalls.length,
|
|
23221
23299
|
completedCount: totalCompleted,
|
|
23222
23300
|
doneCategories: aggregateDoneCategories(allCalls),
|
|
@@ -23229,15 +23307,19 @@ function createToolCardResults({
|
|
|
23229
23307
|
}
|
|
23230
23308
|
continue;
|
|
23231
23309
|
}
|
|
23232
|
-
const group = toolGroups.get(card.itemId) || { count: 1, completed: 0, errors: 0, results: [] };
|
|
23310
|
+
const group = toolGroups.get(card.itemId) || { count: 1, completed: 0, errors: 0, exitErrors: 0, results: [] };
|
|
23233
23311
|
group.completed = Math.min(group.count, group.completed + 1);
|
|
23234
23312
|
toolGroups.set(card.itemId, group);
|
|
23235
23313
|
let resultText = groupedToolResultText(group);
|
|
23314
|
+
if (group.errors > 0 && !String(resultText || "").trim()) {
|
|
23315
|
+
const exitRec = (group.results || []).find((r) => r && r.isExitError);
|
|
23316
|
+
resultText = finalizedErrorFallbackBody(resultText, exitRec?.text, exitRec?.exitCode);
|
|
23317
|
+
}
|
|
23236
23318
|
if (cancelled) {
|
|
23237
23319
|
const currentItem = getState().items.find((it) => it.id === card.itemId);
|
|
23238
23320
|
resultText = withCancelledResultMarker(resultText, currentItem);
|
|
23239
23321
|
}
|
|
23240
|
-
patchToolItem(card.itemId, { result: resultText, text: resultText, isError: group.errors > 0, errorCount: group.errors, callErrorCount: group.callErrors || 0, count: group.count, completedCount: group.completed, completedAt: Date.now() });
|
|
23322
|
+
patchToolItem(card.itemId, { result: resultText, text: resultText, isError: group.errors > 0, errorCount: group.errors, callErrorCount: group.callErrors || 0, exitErrorCount: group.exitErrors || 0, count: group.count, completedCount: group.completed, completedAt: Date.now() });
|
|
23241
23323
|
card.done = true;
|
|
23242
23324
|
if (card.callId) done.add(card.callId);
|
|
23243
23325
|
}
|
|
@@ -23245,6 +23327,73 @@ function createToolCardResults({
|
|
|
23245
23327
|
return { patchToolCardResult, flushToolResults };
|
|
23246
23328
|
}
|
|
23247
23329
|
|
|
23330
|
+
// src/runtime/agent/orchestrator/session/manager/delivered-completions.mjs
|
|
23331
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
23332
|
+
var DELIVERED_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
23333
|
+
var DELIVERED_MAX_ENTRIES = 512;
|
|
23334
|
+
var _delivered = /* @__PURE__ */ new Map();
|
|
23335
|
+
function hashCompletionText(text) {
|
|
23336
|
+
const value = String(text ?? "").trim();
|
|
23337
|
+
if (!value) return null;
|
|
23338
|
+
return createHash3("sha1").update(value).digest("hex");
|
|
23339
|
+
}
|
|
23340
|
+
function execKey(executionId) {
|
|
23341
|
+
const id = executionId == null ? "" : String(executionId).trim();
|
|
23342
|
+
return id ? `id:${id}` : null;
|
|
23343
|
+
}
|
|
23344
|
+
function textKey(text) {
|
|
23345
|
+
const h = hashCompletionText(text);
|
|
23346
|
+
return h ? `tx:${h}` : null;
|
|
23347
|
+
}
|
|
23348
|
+
function pruneExpired(now) {
|
|
23349
|
+
for (const [key, expiresAt] of _delivered) {
|
|
23350
|
+
if (expiresAt <= now) _delivered.delete(key);
|
|
23351
|
+
}
|
|
23352
|
+
}
|
|
23353
|
+
function enforceBound() {
|
|
23354
|
+
while (_delivered.size > DELIVERED_MAX_ENTRIES) {
|
|
23355
|
+
const oldest = _delivered.keys().next().value;
|
|
23356
|
+
if (oldest === void 0) break;
|
|
23357
|
+
_delivered.delete(oldest);
|
|
23358
|
+
}
|
|
23359
|
+
}
|
|
23360
|
+
function recordDeliveredCompletion({ executionId, text } = {}) {
|
|
23361
|
+
const now = Date.now();
|
|
23362
|
+
pruneExpired(now);
|
|
23363
|
+
const expiresAt = now + DELIVERED_TTL_MS;
|
|
23364
|
+
let recorded = false;
|
|
23365
|
+
for (const key of [execKey(executionId), textKey(text)]) {
|
|
23366
|
+
if (!key) continue;
|
|
23367
|
+
_delivered.delete(key);
|
|
23368
|
+
_delivered.set(key, expiresAt);
|
|
23369
|
+
recorded = true;
|
|
23370
|
+
}
|
|
23371
|
+
if (recorded) enforceBound();
|
|
23372
|
+
return recorded;
|
|
23373
|
+
}
|
|
23374
|
+
function isDeliveredCompletion({ executionId, text } = {}) {
|
|
23375
|
+
const now = Date.now();
|
|
23376
|
+
const keys = [execKey(executionId), textKey(text)].filter(Boolean);
|
|
23377
|
+
let hit = false;
|
|
23378
|
+
for (const key of keys) {
|
|
23379
|
+
const expiresAt2 = _delivered.get(key);
|
|
23380
|
+
if (expiresAt2 === void 0) continue;
|
|
23381
|
+
if (expiresAt2 <= now) {
|
|
23382
|
+
_delivered.delete(key);
|
|
23383
|
+
continue;
|
|
23384
|
+
}
|
|
23385
|
+
hit = true;
|
|
23386
|
+
}
|
|
23387
|
+
if (!hit) return false;
|
|
23388
|
+
const expiresAt = now + DELIVERED_TTL_MS;
|
|
23389
|
+
for (const key of keys) {
|
|
23390
|
+
if (!_delivered.has(key)) continue;
|
|
23391
|
+
_delivered.delete(key);
|
|
23392
|
+
_delivered.set(key, expiresAt);
|
|
23393
|
+
}
|
|
23394
|
+
return true;
|
|
23395
|
+
}
|
|
23396
|
+
|
|
23248
23397
|
// src/tui/engine/agent-job-feed.mjs
|
|
23249
23398
|
function parseInboundImagePaths(raw) {
|
|
23250
23399
|
if (typeof raw !== "string" || !raw) return [];
|
|
@@ -23265,16 +23414,58 @@ function createAgentJobFeed({
|
|
|
23265
23414
|
enqueue,
|
|
23266
23415
|
drain,
|
|
23267
23416
|
pushUserOrSyntheticItem,
|
|
23417
|
+
pushAsyncAgentResponse,
|
|
23268
23418
|
makeQueueEntry,
|
|
23269
23419
|
getPending,
|
|
23270
23420
|
agentStatusState,
|
|
23271
23421
|
displayedExecutionNotificationKeys,
|
|
23272
|
-
pushNotice
|
|
23422
|
+
pushNotice,
|
|
23423
|
+
now = () => Date.now(),
|
|
23424
|
+
executionResumeTombstoneTtlMs = 3e4,
|
|
23425
|
+
executionResumeTombstoneLimit = 128
|
|
23273
23426
|
}) {
|
|
23274
23427
|
let executionResumeKickDeferred = false;
|
|
23428
|
+
const discardedExecutionResumeKeys = /* @__PURE__ */ new Map();
|
|
23429
|
+
const displayedExecutionResponseStates = /* @__PURE__ */ new Map();
|
|
23275
23430
|
const executionResumeKickBodies = [];
|
|
23276
|
-
function
|
|
23277
|
-
if (
|
|
23431
|
+
function executionResumeKey(body, completionKey = "") {
|
|
23432
|
+
if (completionKey && typeof completionKey === "object") {
|
|
23433
|
+
completionKey = completionKey.executionId || completionKey.key || "";
|
|
23434
|
+
}
|
|
23435
|
+
const explicitKey = String(completionKey || "").trim();
|
|
23436
|
+
if (explicitKey.startsWith("execution:") || explicitKey.startsWith("body:")) return explicitKey;
|
|
23437
|
+
if (explicitKey) return `execution:${explicitKey}`;
|
|
23438
|
+
const value = String(body || "").trim();
|
|
23439
|
+
return value ? `body:${shortTextFingerprint(value)}` : "";
|
|
23440
|
+
}
|
|
23441
|
+
function pruneDiscardedExecutionResumeKeys() {
|
|
23442
|
+
const nowMs = Number(now()) || Date.now();
|
|
23443
|
+
for (const [key, expiresAt] of discardedExecutionResumeKeys) {
|
|
23444
|
+
if (expiresAt <= nowMs) discardedExecutionResumeKeys.delete(key);
|
|
23445
|
+
}
|
|
23446
|
+
}
|
|
23447
|
+
function isDiscardedExecutionResumeKey(key) {
|
|
23448
|
+
if (!key) return false;
|
|
23449
|
+
pruneDiscardedExecutionResumeKeys();
|
|
23450
|
+
return discardedExecutionResumeKeys.has(key);
|
|
23451
|
+
}
|
|
23452
|
+
function rememberDiscardedExecutionResumeKey(key) {
|
|
23453
|
+
if (!key) return;
|
|
23454
|
+
pruneDiscardedExecutionResumeKeys();
|
|
23455
|
+
const limit = Math.max(1, Number(executionResumeTombstoneLimit) || 128);
|
|
23456
|
+
while (!discardedExecutionResumeKeys.has(key) && discardedExecutionResumeKeys.size >= limit) {
|
|
23457
|
+
const oldest = discardedExecutionResumeKeys.keys().next().value;
|
|
23458
|
+
if (oldest == null) break;
|
|
23459
|
+
discardedExecutionResumeKeys.delete(oldest);
|
|
23460
|
+
}
|
|
23461
|
+
const ttlMs = Math.max(1, Number(executionResumeTombstoneTtlMs) || 3e4);
|
|
23462
|
+
discardedExecutionResumeKeys.delete(key);
|
|
23463
|
+
discardedExecutionResumeKeys.set(key, (Number(now()) || Date.now()) + ttlMs);
|
|
23464
|
+
}
|
|
23465
|
+
function kickExecutionPendingResume(body = "", completionKey = "") {
|
|
23466
|
+
const key = executionResumeKey(body, completionKey);
|
|
23467
|
+
if (body && isDiscardedExecutionResumeKey(key)) return;
|
|
23468
|
+
if (body) executionResumeKickBodies.push({ body, key });
|
|
23278
23469
|
if (getDisposed()) return;
|
|
23279
23470
|
if (getState().busy) {
|
|
23280
23471
|
executionResumeKickDeferred = true;
|
|
@@ -23286,16 +23477,34 @@ function createAgentJobFeed({
|
|
|
23286
23477
|
return;
|
|
23287
23478
|
}
|
|
23288
23479
|
executionResumeKickDeferred = false;
|
|
23289
|
-
const
|
|
23290
|
-
|
|
23480
|
+
const resumeBodies = executionResumeKickBodies.splice(0);
|
|
23481
|
+
const resumeBody = resumeBodies.map(({ body: value }) => value).filter(Boolean).join("\n\n");
|
|
23482
|
+
const resumeCompletionKeys = resumeBodies.map(({ key: key2 }) => key2).filter(Boolean);
|
|
23483
|
+
pending.push(makeQueueEntry(resumeBody, {
|
|
23484
|
+
mode: "pending-resume",
|
|
23485
|
+
priority: "next",
|
|
23486
|
+
abortDiscardOnAbort: true,
|
|
23487
|
+
resumeCompletionKeys
|
|
23488
|
+
}));
|
|
23291
23489
|
void drain();
|
|
23292
23490
|
}
|
|
23293
23491
|
function flushDeferredExecutionPendingResumeKick() {
|
|
23294
23492
|
if (!executionResumeKickDeferred || getDisposed() || getState().busy) return;
|
|
23295
23493
|
kickExecutionPendingResume();
|
|
23296
23494
|
}
|
|
23297
|
-
function scheduleExecutionPendingResumeKick(body = "") {
|
|
23298
|
-
queueMicrotask(() => kickExecutionPendingResume(body));
|
|
23495
|
+
function scheduleExecutionPendingResumeKick(body = "", completionKey = "") {
|
|
23496
|
+
queueMicrotask(() => kickExecutionPendingResume(body, completionKey));
|
|
23497
|
+
}
|
|
23498
|
+
function discardExecutionPendingResume(completionKeys = []) {
|
|
23499
|
+
const keys = (Array.isArray(completionKeys) ? completionKeys : [completionKeys]).map((key) => executionResumeKey("", key)).filter(Boolean);
|
|
23500
|
+
if (keys.length === 0) return;
|
|
23501
|
+
for (const key of keys) rememberDiscardedExecutionResumeKey(key);
|
|
23502
|
+
for (let i = executionResumeKickBodies.length - 1; i >= 0; i -= 1) {
|
|
23503
|
+
if (isDiscardedExecutionResumeKey(executionResumeKickBodies[i].key)) {
|
|
23504
|
+
executionResumeKickBodies.splice(i, 1);
|
|
23505
|
+
}
|
|
23506
|
+
}
|
|
23507
|
+
executionResumeKickDeferred = executionResumeKickBodies.length > 0;
|
|
23299
23508
|
}
|
|
23300
23509
|
function buildAgentJobCardPatch(itemId, text, isError = false) {
|
|
23301
23510
|
const parsed = parseAgentJob(text);
|
|
@@ -23313,6 +23522,12 @@ function createAgentJobFeed({
|
|
|
23313
23522
|
function updateAgentJobCard(itemId, text, isError = false) {
|
|
23314
23523
|
patchItem(itemId, buildAgentJobCardPatch(itemId, text, isError));
|
|
23315
23524
|
}
|
|
23525
|
+
function refreshAgentStatus(parsed) {
|
|
23526
|
+
if (!parsed?.taskId) return;
|
|
23527
|
+
const status = String(parsed.status || "").toLowerCase();
|
|
23528
|
+
const terminal = /^(completed|complete|done|success|succeeded|ok|failed|error|timeout|killed|cancelled|canceled|denied)$/.test(status);
|
|
23529
|
+
set(agentStatusState(terminal ? { force: true } : void 0));
|
|
23530
|
+
}
|
|
23316
23531
|
function subscribeRuntimeNotifications() {
|
|
23317
23532
|
if (typeof runtime.onNotification !== "function") return null;
|
|
23318
23533
|
return runtime.onNotification((event) => {
|
|
@@ -23328,33 +23543,53 @@ function createAgentJobFeed({
|
|
|
23328
23543
|
return true;
|
|
23329
23544
|
}
|
|
23330
23545
|
if (delivery.action === "status-only") {
|
|
23331
|
-
|
|
23546
|
+
refreshAgentStatus(parsed);
|
|
23332
23547
|
return true;
|
|
23333
23548
|
}
|
|
23334
23549
|
if (delivery.action === "execution-ui") {
|
|
23335
|
-
const
|
|
23336
|
-
|
|
23337
|
-
|
|
23338
|
-
|
|
23550
|
+
const cardKey = executionCardKey(event, text, parsed);
|
|
23551
|
+
const firstDelivery = !cardKey || !displayedExecutionNotificationKeys.has(cardKey);
|
|
23552
|
+
const executionId = String(event?.meta?.execution_id || parsed?.taskId || "").trim();
|
|
23553
|
+
const status = String(event?.meta?.status || parsed?.status || "").toLowerCase();
|
|
23554
|
+
const hasBody = /\n\s*\n[\s\S]*\S/.test(text);
|
|
23555
|
+
const isFailure = /^(failed|error|timeout|killed|cancelled|canceled|denied)$/.test(status);
|
|
23556
|
+
const successfulPreview = !hasBody && !isFailure && /^(completed|complete|done|success|succeeded|ok)$/.test(status);
|
|
23557
|
+
const responseState = executionId ? displayedExecutionResponseStates.get(executionId) : "";
|
|
23558
|
+
const bodyAlreadyDisplayed = responseState === "body";
|
|
23559
|
+
if (firstDelivery && !successfulPreview && !bodyAlreadyDisplayed) {
|
|
23560
|
+
if (cardKey) displayedExecutionNotificationKeys.add(cardKey);
|
|
23561
|
+
if (executionId) displayedExecutionResponseStates.set(executionId, hasBody ? "body" : "preview");
|
|
23562
|
+
(pushAsyncAgentResponse || pushUserOrSyntheticItem)(delivery.displayText, nextId2(), "injected", { responseKey: executionId });
|
|
23339
23563
|
}
|
|
23340
|
-
|
|
23564
|
+
refreshAgentStatus(parsed);
|
|
23341
23565
|
const resumeBody = String(delivery.modelContent || "").trim();
|
|
23342
23566
|
if (resumeBody) {
|
|
23343
|
-
|
|
23567
|
+
const completionKey = executionResumeKey(resumeBody, executionId);
|
|
23568
|
+
if (isDiscardedExecutionResumeKey(completionKey) || isDeliveredCompletion({ executionId, text: resumeBody })) {
|
|
23569
|
+
if (event && typeof event === "object") event.modelVisibleDelivered = true;
|
|
23570
|
+
return true;
|
|
23571
|
+
}
|
|
23572
|
+
const enqueued = enqueue(resumeBody, {
|
|
23344
23573
|
mode: "task-notification",
|
|
23345
23574
|
// Claude Code parity: live execution completions are queued as
|
|
23346
23575
|
// task notifications so the active loop can attach them after the
|
|
23347
23576
|
// next tool batch; no special pending-resume bypass.
|
|
23348
23577
|
priority: "next",
|
|
23349
23578
|
key: notificationKey || void 0,
|
|
23350
|
-
|
|
23579
|
+
abortDiscardOnAbort: true,
|
|
23580
|
+
resumeCompletionKeys: completionKey ? [completionKey] : [],
|
|
23581
|
+
displayText: delivery.displayText || text,
|
|
23582
|
+
// The immediate Response card was already pushed above
|
|
23583
|
+
// (pushUserOrSyntheticItem). Keep this queued twin model-visible
|
|
23584
|
+
// but suppress its drain-time transcript card to avoid a duplicate.
|
|
23585
|
+
suppressDisplay: true
|
|
23351
23586
|
});
|
|
23587
|
+
if (enqueued) recordDeliveredCompletion({ executionId, text: resumeBody });
|
|
23588
|
+
if (event && typeof event === "object") event.modelVisibleDelivered = true;
|
|
23352
23589
|
}
|
|
23353
23590
|
return true;
|
|
23354
23591
|
}
|
|
23355
|
-
|
|
23356
|
-
set(agentStatusState({ force: true }));
|
|
23357
|
-
}
|
|
23592
|
+
refreshAgentStatus(parsed);
|
|
23358
23593
|
const modelContent = String(delivery.modelContent ?? delivery.displayText ?? text).trim();
|
|
23359
23594
|
const imagePaths = parseInboundImagePaths(event?.meta?.image_paths);
|
|
23360
23595
|
if (!modelContent && imagePaths.length === 0) return true;
|
|
@@ -23397,12 +23632,68 @@ function createAgentJobFeed({
|
|
|
23397
23632
|
kickExecutionPendingResume,
|
|
23398
23633
|
flushDeferredExecutionPendingResumeKick,
|
|
23399
23634
|
scheduleExecutionPendingResumeKick,
|
|
23635
|
+
discardExecutionPendingResume,
|
|
23400
23636
|
updateAgentJobCard,
|
|
23401
23637
|
buildAgentJobCardPatch,
|
|
23402
23638
|
subscribeRuntimeNotifications
|
|
23403
23639
|
};
|
|
23404
23640
|
}
|
|
23405
23641
|
|
|
23642
|
+
// src/tui/engine/agent-response-tail.mjs
|
|
23643
|
+
function responseEntry(response = {}) {
|
|
23644
|
+
return {
|
|
23645
|
+
key: String(response.key || ""),
|
|
23646
|
+
raw: String(response.rawResult ?? response.raw ?? "").trim(),
|
|
23647
|
+
result: response.result,
|
|
23648
|
+
hasBody: response.hasBody === true,
|
|
23649
|
+
isError: response.isError === true
|
|
23650
|
+
};
|
|
23651
|
+
}
|
|
23652
|
+
function formatAgentResponseRaw(entries = []) {
|
|
23653
|
+
return entries.map((entry, index) => {
|
|
23654
|
+
const raw = String(entry?.raw || "").trim();
|
|
23655
|
+
return raw ? `${index + 1}. agent
|
|
23656
|
+
${raw}` : "";
|
|
23657
|
+
}).filter(Boolean).join("\n\n");
|
|
23658
|
+
}
|
|
23659
|
+
function priorEntries(previous) {
|
|
23660
|
+
if (Array.isArray(previous?.agentResponseEntries) && previous.agentResponseEntries.length) {
|
|
23661
|
+
return previous.agentResponseEntries.map(responseEntry);
|
|
23662
|
+
}
|
|
23663
|
+
return [responseEntry({
|
|
23664
|
+
key: previous?.agentResponseKey,
|
|
23665
|
+
rawResult: previous?.rawResult ?? previous?.result,
|
|
23666
|
+
result: previous?.result,
|
|
23667
|
+
hasBody: previous?.agentResponseHasBody,
|
|
23668
|
+
isError: previous?.isError
|
|
23669
|
+
})];
|
|
23670
|
+
}
|
|
23671
|
+
function appendAgentResponseTail(previous, response, now = Date.now()) {
|
|
23672
|
+
if (previous?.kind !== "tool" || previous.agentDirection !== "inbound") return null;
|
|
23673
|
+
const next = responseEntry(response);
|
|
23674
|
+
const entries = priorEntries(previous);
|
|
23675
|
+
const existingIndex = next.key ? entries.findIndex((entry) => entry.key === next.key) : -1;
|
|
23676
|
+
if (existingIndex >= 0) {
|
|
23677
|
+
entries[existingIndex] = next;
|
|
23678
|
+
} else {
|
|
23679
|
+
if (previous.agentResponseHasBody !== next.hasBody) return null;
|
|
23680
|
+
entries.push(next);
|
|
23681
|
+
}
|
|
23682
|
+
return {
|
|
23683
|
+
args: response.args,
|
|
23684
|
+
result: response.result,
|
|
23685
|
+
rawResult: formatAgentResponseRaw(entries) || null,
|
|
23686
|
+
isError: entries.some((entry) => entry.isError),
|
|
23687
|
+
count: entries.length,
|
|
23688
|
+
completedCount: entries.length,
|
|
23689
|
+
completedAt: now,
|
|
23690
|
+
agentResponseEntries: entries,
|
|
23691
|
+
agentResponseKeys: entries.map((entry) => entry.key).filter(Boolean),
|
|
23692
|
+
agentResponseHasBody: entries.every((entry) => entry.hasBody),
|
|
23693
|
+
agentResponseAggregate: entries.length > 1
|
|
23694
|
+
};
|
|
23695
|
+
}
|
|
23696
|
+
|
|
23406
23697
|
// src/tui/engine/tui-steering-persist.mjs
|
|
23407
23698
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
23408
23699
|
import { join as join8 } from "path";
|
|
@@ -23771,6 +24062,11 @@ function createSessionFlow(bag) {
|
|
|
23771
24062
|
key: options.key || null,
|
|
23772
24063
|
skipSlashCommands: options.skipSlashCommands === true,
|
|
23773
24064
|
displayText: mode === "task-notification" ? notificationDisplayText(displayText) : String(displayText || ""),
|
|
24065
|
+
suppressDisplay: options.suppressDisplay === true,
|
|
24066
|
+
// Completion resumes are consumed exactly once: Esc abandons their
|
|
24067
|
+
// uncommitted body instead of putting it back at the queue front.
|
|
24068
|
+
abortDiscardOnAbort: options.abortDiscardOnAbort === true,
|
|
24069
|
+
resumeCompletionKeys: Array.isArray(options.resumeCompletionKeys) ? options.resumeCompletionKeys.filter((key) => key != null && String(key).trim()) : [],
|
|
23774
24070
|
steeringPersistId: options.steeringPersistId || null,
|
|
23775
24071
|
steeringPersistRestored: options.steeringPersistRestored === true
|
|
23776
24072
|
};
|
|
@@ -23882,9 +24178,17 @@ function createSessionFlow(bag) {
|
|
|
23882
24178
|
const merged = mergePromptContents(batch);
|
|
23883
24179
|
for (const entry of batch) {
|
|
23884
24180
|
if (entry.mode === "pending-resume") continue;
|
|
24181
|
+
if (entry.suppressDisplay) continue;
|
|
23885
24182
|
pushUserOrSyntheticItem(entry.text, entry.id, isQueuedEntryEditable(entry) ? "user" : "injected");
|
|
23886
24183
|
}
|
|
23887
24184
|
const nonEditable = batch.filter((entry) => !isQueuedEntryEditable(entry));
|
|
24185
|
+
const discardOnAbort = nonEditable.filter(
|
|
24186
|
+
(entry) => entry?.abortDiscardOnAbort === true || entry?.mode === "pending-resume"
|
|
24187
|
+
);
|
|
24188
|
+
const requeueOnAbort = nonEditable.filter((entry) => !discardOnAbort.includes(entry));
|
|
24189
|
+
const discardExecutionPendingResumeKeys = discardOnAbort.flatMap(
|
|
24190
|
+
(entry) => Array.isArray(entry?.resumeCompletionKeys) ? entry.resumeCompletionKeys : []
|
|
24191
|
+
);
|
|
23888
24192
|
const batchPastedImages = mergePastedImages(batch);
|
|
23889
24193
|
const batchPastedTexts = mergePastedTexts(batch);
|
|
23890
24194
|
const turnStatus = await bag.runTurn(merged, {
|
|
@@ -23894,7 +24198,8 @@ function createSessionFlow(bag) {
|
|
|
23894
24198
|
onCommitted: () => commitSteeringQueueEntries(batch),
|
|
23895
24199
|
submittedIds: [...ids],
|
|
23896
24200
|
restorable: nonEditable.length === 0,
|
|
23897
|
-
requeueOnAbort
|
|
24201
|
+
requeueOnAbort,
|
|
24202
|
+
discardExecutionPendingResumeKeys
|
|
23898
24203
|
});
|
|
23899
24204
|
if (flags.drainEpoch !== drainEpoch) return;
|
|
23900
24205
|
flushDeferredClearedSessionUi();
|
|
@@ -23948,6 +24253,12 @@ function createSessionFlow(bag) {
|
|
|
23948
24253
|
if (batch.length === 0) break;
|
|
23949
24254
|
for (const entry of batch) {
|
|
23950
24255
|
const content = entry.content;
|
|
24256
|
+
if (entry.suppressDisplay) {
|
|
24257
|
+
if (Array.isArray(content) ? content.length > 0 : String(content ?? "").trim().length > 0) {
|
|
24258
|
+
out.push({ text: STEERING_SUPPRESSED_DISPLAY, content });
|
|
24259
|
+
}
|
|
24260
|
+
continue;
|
|
24261
|
+
}
|
|
23951
24262
|
const value = typeof content === "string" ? content.trim() : { text: String(entry.text || "").trim(), content };
|
|
23952
24263
|
if (typeof value === "string") {
|
|
23953
24264
|
if (value.length > 0) out.push(value);
|
|
@@ -24236,7 +24547,8 @@ function createRunTurn(bag) {
|
|
|
24236
24547
|
submittedIds,
|
|
24237
24548
|
reclaimed: false,
|
|
24238
24549
|
committed: false,
|
|
24239
|
-
requeueEntries: Array.isArray(options.requeueOnAbort) ? options.requeueOnAbort.slice() : []
|
|
24550
|
+
requeueEntries: Array.isArray(options.requeueOnAbort) ? options.requeueOnAbort.slice() : [],
|
|
24551
|
+
discardExecutionPendingResumeKeys: Array.isArray(options.discardExecutionPendingResumeKeys) ? options.discardExecutionPendingResumeKeys.slice() : []
|
|
24240
24552
|
};
|
|
24241
24553
|
set({ busy: true, lastTurn: null, spinner: { active: true, verb: pickVerb(turnIndex), startedAt, responseLength: 0, inputTokens: 0, outputTokens: 0, mode: "requesting" } });
|
|
24242
24554
|
let assistantText = "";
|
|
@@ -24319,6 +24631,7 @@ function createRunTurn(bag) {
|
|
|
24319
24631
|
};
|
|
24320
24632
|
armWatchdog();
|
|
24321
24633
|
let currentAssistantText = "";
|
|
24634
|
+
const committedSegments = [];
|
|
24322
24635
|
let thinkingText = "";
|
|
24323
24636
|
let thinkingStartedAt = 0;
|
|
24324
24637
|
let thinkingSegmentStartedAt = 0;
|
|
@@ -24334,7 +24647,8 @@ function createRunTurn(bag) {
|
|
|
24334
24647
|
const earlyResultBuffer = /* @__PURE__ */ new Map();
|
|
24335
24648
|
const aggregateCards = [];
|
|
24336
24649
|
let tailAggregate = null;
|
|
24337
|
-
|
|
24650
|
+
let providerToolBatch = 0;
|
|
24651
|
+
const TOOL_CARD_PUSH_DELAY_MS = 1e3;
|
|
24338
24652
|
let deferredSeqCounter = 0;
|
|
24339
24653
|
const deferredEntries = [];
|
|
24340
24654
|
const flushDeferredUpTo = (entry) => {
|
|
@@ -24501,10 +24815,11 @@ function createRunTurn(bag) {
|
|
|
24501
24815
|
aggregate.ensureVisible?.();
|
|
24502
24816
|
const errors = allCalls.filter((r) => r.isError).length;
|
|
24503
24817
|
const callErrors = allCalls.filter((r) => r.isCallError).length;
|
|
24818
|
+
const exitErrors = allCalls.filter((r) => r.isExitError).length;
|
|
24504
24819
|
const completed = allCalls.filter((r) => r.resolved).length;
|
|
24505
|
-
const succeeded = completed - errors;
|
|
24820
|
+
const succeeded = Math.max(0, completed - errors - exitErrors);
|
|
24506
24821
|
const rawResult = aggregateRawResult(allCalls);
|
|
24507
|
-
const displayDetail = errors > 0
|
|
24822
|
+
const displayDetail = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
24508
24823
|
patchItem(aggregate.itemId, {
|
|
24509
24824
|
result: displayDetail,
|
|
24510
24825
|
text: displayDetail,
|
|
@@ -24512,6 +24827,7 @@ function createRunTurn(bag) {
|
|
|
24512
24827
|
isError: errors > 0,
|
|
24513
24828
|
errorCount: errors,
|
|
24514
24829
|
callErrorCount: callErrors,
|
|
24830
|
+
exitErrorCount: exitErrors,
|
|
24515
24831
|
count: allCalls.length,
|
|
24516
24832
|
completedCount: allCalls.length,
|
|
24517
24833
|
doneCategories: aggregateDoneCategories(allCalls),
|
|
@@ -24602,6 +24918,7 @@ function createRunTurn(bag) {
|
|
|
24602
24918
|
if (sealToolBlock) clearAggregateContinuation();
|
|
24603
24919
|
const id = currentAssistantId || ensureAssistant(text);
|
|
24604
24920
|
patchItem(id, { text, streaming: false });
|
|
24921
|
+
committedSegments.push(text);
|
|
24605
24922
|
closeAssistantSegment();
|
|
24606
24923
|
return true;
|
|
24607
24924
|
};
|
|
@@ -24718,24 +25035,25 @@ function createRunTurn(bag) {
|
|
|
24718
25035
|
if (!callRec || callRec.resolved || callRec.completedEarly) return;
|
|
24719
25036
|
aggregate.ensureVisible?.();
|
|
24720
25037
|
const rawText = toolResultText(message?.content);
|
|
24721
|
-
const
|
|
24722
|
-
const
|
|
24723
|
-
const isResultError = /^\s*\[?error/i.test(rawText) || isErrorToolStatus(toolResultStatus(rawText)) || isMemoryCall && memoryCoreResultErrorText(rawText) != null;
|
|
24724
|
-
const isError = isCallError || isResultError;
|
|
25038
|
+
const { exitCode, isExitError, isCallError } = toolCallOutcome(message, rawText);
|
|
25039
|
+
const isError = isCallError;
|
|
24725
25040
|
const text = isError ? toolErrorDisplay(rawText, callRec.name || "tool") : rawText;
|
|
24726
25041
|
callRec.summary = !isError ? summarizeToolResult(callRec.name, callRec.args, rawText, isError) : null;
|
|
24727
25042
|
assignAggregateSummaryOrder(aggregate, callRec);
|
|
24728
25043
|
callRec.isError = isError;
|
|
24729
25044
|
callRec.isCallError = isCallError;
|
|
25045
|
+
callRec.isExitError = isExitError;
|
|
25046
|
+
callRec.exitCode = exitCode;
|
|
24730
25047
|
callRec.resultText = text;
|
|
24731
25048
|
callRec.completedEarly = true;
|
|
24732
25049
|
const allCalls = [...aggregate.calls.values()];
|
|
24733
25050
|
const completedCount = allCalls.filter((r) => r.resolved || r.completedEarly).length;
|
|
24734
25051
|
const errors = allCalls.filter((r) => r.isError).length;
|
|
24735
25052
|
const callErrors = allCalls.filter((r) => r.isCallError).length;
|
|
24736
|
-
const
|
|
25053
|
+
const exitErrors = allCalls.filter((r) => r.isExitError).length;
|
|
25054
|
+
const succeeded = Math.max(0, completedCount - errors - exitErrors);
|
|
24737
25055
|
const rawResult = aggregateRawResult(allCalls);
|
|
24738
|
-
const displayDetail = errors > 0
|
|
25056
|
+
const displayDetail = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
24739
25057
|
const currentItem = getState().items.find((it) => it.id === card.itemId);
|
|
24740
25058
|
const visualCompleted = Math.max(
|
|
24741
25059
|
completedCount,
|
|
@@ -24747,6 +25065,7 @@ function createRunTurn(bag) {
|
|
|
24747
25065
|
isError: errors > 0,
|
|
24748
25066
|
errorCount: errors,
|
|
24749
25067
|
callErrorCount: callErrors,
|
|
25068
|
+
exitErrorCount: exitErrors,
|
|
24750
25069
|
count: allCalls.length,
|
|
24751
25070
|
completedCount: visualCompleted
|
|
24752
25071
|
};
|
|
@@ -24770,11 +25089,9 @@ function createRunTurn(bag) {
|
|
|
24770
25089
|
drainSteering: (_sessionId, drainOptions) => isCurrentTurn() ? drainPendingSteering(drainOptions) : [],
|
|
24771
25090
|
onSteerMessage: (text) => {
|
|
24772
25091
|
if (!markTurnProgress("steer-message")) return;
|
|
25092
|
+
if (text === STEERING_SUPPRESSED_DISPLAY) return;
|
|
24773
25093
|
flushStreamBatch();
|
|
24774
|
-
|
|
24775
|
-
patchItem(currentAssistantId, { text: currentAssistantText || assistantText, streaming: false });
|
|
24776
|
-
closeAssistantSegment();
|
|
24777
|
-
}
|
|
25094
|
+
commitAssistantSegment({ sealToolBlock: true });
|
|
24778
25095
|
assistantText = "";
|
|
24779
25096
|
const value = String(text || "").trim();
|
|
24780
25097
|
if (value) {
|
|
@@ -24795,6 +25112,7 @@ function createRunTurn(bag) {
|
|
|
24795
25112
|
}
|
|
24796
25113
|
const batchCalls = (calls || []).filter(Boolean);
|
|
24797
25114
|
if (batchCalls.length === 0) return;
|
|
25115
|
+
const agentBatch = ++providerToolBatch;
|
|
24798
25116
|
const committedAssistantSegment = commitAssistantSegment({ sealToolBlock: true });
|
|
24799
25117
|
if (committedAssistantSegment) {
|
|
24800
25118
|
await yieldToRenderer({ frames: 2 });
|
|
@@ -24807,7 +25125,7 @@ function createRunTurn(bag) {
|
|
|
24807
25125
|
const name = toolCallName(c);
|
|
24808
25126
|
const args = toolCallArgs(c);
|
|
24809
25127
|
const category = classifyToolCategory(name, args);
|
|
24810
|
-
const bucket = category
|
|
25128
|
+
const bucket = aggregateBucketForCategory(category, { agentBatch });
|
|
24811
25129
|
const callId = toolCallId(c);
|
|
24812
25130
|
const callKey = callId || `__tool_${toolCards.length}_${i}`;
|
|
24813
25131
|
const activeCount = Number(aggregateToolCategoryEntry(name, args, category)?.count || 1);
|
|
@@ -24850,7 +25168,7 @@ function createRunTurn(bag) {
|
|
|
24850
25168
|
...categoryEntry,
|
|
24851
25169
|
count: Number(prevCategory?.count || 0) + Number(categoryEntry.count || 1)
|
|
24852
25170
|
});
|
|
24853
|
-
aggregateCard.calls.set(callKey, { name, args, category, summary: null, summarySeq: null, isError: false, isCallError: false, resultText: null, resolved: false, completedEarly: false });
|
|
25171
|
+
aggregateCard.calls.set(callKey, { name, args, category, summary: null, summarySeq: null, isError: false, isCallError: false, isExitError: false, exitCode: null, resultText: null, resolved: false, completedEarly: false });
|
|
24854
25172
|
touchedAggregates.add(aggregateCard);
|
|
24855
25173
|
const card = { itemId: aggregateCard.itemId, callId: callKey, done: false, aggregate: aggregateCard };
|
|
24856
25174
|
if (callId) {
|
|
@@ -24998,10 +25316,18 @@ function createRunTurn(bag) {
|
|
|
24998
25316
|
flushStreamBatch();
|
|
24999
25317
|
syncContextStats({ allowEstimated: true });
|
|
25000
25318
|
const finalText = result?.content != null ? String(result.content) : "";
|
|
25001
|
-
|
|
25002
|
-
|
|
25003
|
-
|
|
25004
|
-
|
|
25319
|
+
let finalRemainder = finalText;
|
|
25320
|
+
for (const seg of committedSegments) {
|
|
25321
|
+
const skipped = finalRemainder.replace(/^\s+/, "");
|
|
25322
|
+
const trimmedSeg = seg ? seg.replace(/^\s+/, "") : "";
|
|
25323
|
+
if (trimmedSeg && skipped.startsWith(trimmedSeg)) {
|
|
25324
|
+
finalRemainder = skipped.slice(trimmedSeg.length);
|
|
25325
|
+
}
|
|
25326
|
+
}
|
|
25327
|
+
if (finalRemainder.trim()) {
|
|
25328
|
+
const id = currentAssistantId || ensureAssistant(finalRemainder);
|
|
25329
|
+
currentAssistantText = finalRemainder;
|
|
25330
|
+
patchItem(id, { text: finalRemainder, streaming: false });
|
|
25005
25331
|
} else if (currentAssistantId && (currentAssistantText.trim() || assistantText.trim())) {
|
|
25006
25332
|
const streamedText = currentAssistantText || assistantText;
|
|
25007
25333
|
patchItem(currentAssistantId, { text: streamedText, streaming: false });
|
|
@@ -25792,7 +26118,8 @@ function createEngineApiA(bag) {
|
|
|
25792
26118
|
restoreQueued,
|
|
25793
26119
|
resetStatsAndSyncContext,
|
|
25794
26120
|
drain,
|
|
25795
|
-
flushDeferredExecutionPendingResumeKick
|
|
26121
|
+
flushDeferredExecutionPendingResumeKick,
|
|
26122
|
+
discardExecutionPendingResume
|
|
25796
26123
|
} = bag;
|
|
25797
26124
|
return {
|
|
25798
26125
|
getState: () => getState(),
|
|
@@ -26286,9 +26613,14 @@ function createEngineApiA(bag) {
|
|
|
26286
26613
|
const restorePastedTexts = canRestore && restoreState?.pastedTexts ? restoreState.pastedTexts : null;
|
|
26287
26614
|
const discardPastedImages = restoreState?.restorable && hasPendingSteering && restoreState?.pastedImages ? restoreState.pastedImages : null;
|
|
26288
26615
|
const discardPastedTexts = restoreState?.restorable && hasPendingSteering && restoreState?.pastedTexts ? restoreState.pastedTexts : null;
|
|
26289
|
-
const requeueEntries = restoreState && !restoreState.committed && Array.isArray(restoreState.requeueEntries) ? restoreState.requeueEntries.
|
|
26616
|
+
const requeueEntries = restoreState && !restoreState.committed && Array.isArray(restoreState.requeueEntries) ? restoreState.requeueEntries.filter(
|
|
26617
|
+
(entry) => entry?.abortDiscardOnAbort !== true && entry?.mode !== "pending-resume"
|
|
26618
|
+
) : [];
|
|
26290
26619
|
const aborted = runtime.abort("cli-react-abort");
|
|
26291
26620
|
if (restoreState) {
|
|
26621
|
+
if (aborted !== false && Array.isArray(restoreState.discardExecutionPendingResumeKeys)) {
|
|
26622
|
+
discardExecutionPendingResume?.(restoreState.discardExecutionPendingResumeKeys);
|
|
26623
|
+
}
|
|
26292
26624
|
if ((restoreText || requeueEntries.length > 0) && aborted !== false) {
|
|
26293
26625
|
restoreState.reclaimed = true;
|
|
26294
26626
|
const idSet = new Set((restoreState.submittedIds || []).filter((id) => id != null));
|
|
@@ -26304,6 +26636,7 @@ function createEngineApiA(bag) {
|
|
|
26304
26636
|
}
|
|
26305
26637
|
restoreState.restorable = false;
|
|
26306
26638
|
restoreState.requeueEntries = [];
|
|
26639
|
+
restoreState.discardExecutionPendingResumeKeys = [];
|
|
26307
26640
|
}
|
|
26308
26641
|
const abortEpoch = flags.leadTurnEpoch;
|
|
26309
26642
|
const recoveryMs = Number(flags.manualAbortRecoveryMs) > 0 ? Number(flags.manualAbortRecoveryMs) : MANUAL_ABORT_RECOVERY_MS;
|
|
@@ -26564,6 +26897,59 @@ async function createEngineSession({
|
|
|
26564
26897
|
if (origin === "user") appendPromptHistory(state.cwd, text);
|
|
26565
26898
|
pushItem({ kind: "user", id, text });
|
|
26566
26899
|
};
|
|
26900
|
+
const pushAsyncAgentResponse = (text, id = nextId(), origin = "injected", metadata = {}) => {
|
|
26901
|
+
const synthetic = parseSyntheticAgentMessage(text);
|
|
26902
|
+
const isAgent = synthetic?.name === "agent";
|
|
26903
|
+
if (!isAgent) return pushUserOrSyntheticItem(text, id, origin);
|
|
26904
|
+
const responseHasBody = /\n\s*\n[\s\S]*\S/.test(String(text || ""));
|
|
26905
|
+
const rawResult = synthetic.rawResult ?? text;
|
|
26906
|
+
const args = {
|
|
26907
|
+
...synthetic.args && typeof synthetic.args === "object" ? synthetic.args : {},
|
|
26908
|
+
type: "result"
|
|
26909
|
+
};
|
|
26910
|
+
const responseKey = String(metadata.responseKey || metadata.executionId || args.task_id || "").trim();
|
|
26911
|
+
const previous = state.items.at(-1);
|
|
26912
|
+
if (previous?.kind === "tool" && previous.agentDirection === "inbound") {
|
|
26913
|
+
const patch = appendAgentResponseTail(previous, {
|
|
26914
|
+
key: responseKey,
|
|
26915
|
+
args,
|
|
26916
|
+
result: synthetic.result,
|
|
26917
|
+
rawResult,
|
|
26918
|
+
hasBody: responseHasBody,
|
|
26919
|
+
isError: synthetic.isError === true
|
|
26920
|
+
});
|
|
26921
|
+
if (patch) {
|
|
26922
|
+
patchItem(previous.id, patch);
|
|
26923
|
+
return true;
|
|
26924
|
+
}
|
|
26925
|
+
}
|
|
26926
|
+
pushItem({
|
|
26927
|
+
kind: "tool",
|
|
26928
|
+
id,
|
|
26929
|
+
name: "agent",
|
|
26930
|
+
args,
|
|
26931
|
+
result: synthetic.result,
|
|
26932
|
+
rawResult,
|
|
26933
|
+
isError: synthetic.isError === true,
|
|
26934
|
+
expanded: false,
|
|
26935
|
+
count: 1,
|
|
26936
|
+
completedCount: 1,
|
|
26937
|
+
startedAt: Date.now(),
|
|
26938
|
+
completedAt: Date.now(),
|
|
26939
|
+
agentDirection: "inbound",
|
|
26940
|
+
agentResponseKey: responseKey,
|
|
26941
|
+
agentResponseHasBody: responseHasBody,
|
|
26942
|
+
agentResponseAggregate: false,
|
|
26943
|
+
agentResponseEntries: [{
|
|
26944
|
+
key: responseKey,
|
|
26945
|
+
raw: String(rawResult ?? "").trim(),
|
|
26946
|
+
result: synthetic.result,
|
|
26947
|
+
hasBody: responseHasBody,
|
|
26948
|
+
isError: synthetic.isError === true
|
|
26949
|
+
}]
|
|
26950
|
+
});
|
|
26951
|
+
return true;
|
|
26952
|
+
};
|
|
26567
26953
|
const pushToast = (text, tone = "info", ttlMs = 3e3) => {
|
|
26568
26954
|
const id = nextId();
|
|
26569
26955
|
const value = String(text ?? "").trim();
|
|
@@ -26653,6 +27039,7 @@ async function createEngineSession({
|
|
|
26653
27039
|
kickExecutionPendingResume,
|
|
26654
27040
|
flushDeferredExecutionPendingResumeKick,
|
|
26655
27041
|
scheduleExecutionPendingResumeKick,
|
|
27042
|
+
discardExecutionPendingResume,
|
|
26656
27043
|
updateAgentJobCard,
|
|
26657
27044
|
buildAgentJobCardPatch,
|
|
26658
27045
|
subscribeRuntimeNotifications
|
|
@@ -26666,6 +27053,7 @@ async function createEngineSession({
|
|
|
26666
27053
|
enqueue: (...args) => bag.enqueue(...args),
|
|
26667
27054
|
drain: (...args) => bag.drain(...args),
|
|
26668
27055
|
pushUserOrSyntheticItem,
|
|
27056
|
+
pushAsyncAgentResponse,
|
|
26669
27057
|
makeQueueEntry: (...args) => bag.makeQueueEntry(...args),
|
|
26670
27058
|
getPending: () => pending,
|
|
26671
27059
|
agentStatusState,
|
|
@@ -26713,6 +27101,7 @@ async function createEngineSession({
|
|
|
26713
27101
|
removeNotice,
|
|
26714
27102
|
setProgressHint,
|
|
26715
27103
|
pushUserOrSyntheticItem,
|
|
27104
|
+
pushAsyncAgentResponse,
|
|
26716
27105
|
upsertSyntheticToolItem,
|
|
26717
27106
|
markToolCallActive,
|
|
26718
27107
|
markToolCallDone,
|
|
@@ -26732,6 +27121,7 @@ async function createEngineSession({
|
|
|
26732
27121
|
kickExecutionPendingResume,
|
|
26733
27122
|
flushDeferredExecutionPendingResumeKick,
|
|
26734
27123
|
scheduleExecutionPendingResumeKick,
|
|
27124
|
+
discardExecutionPendingResume,
|
|
26735
27125
|
updateAgentJobCard,
|
|
26736
27126
|
subscribeRuntimeNotifications
|
|
26737
27127
|
});
|