mixdog 0.9.39 → 0.9.40
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 +1 -1
- package/scripts/agent-terminal-reap-test.mjs +6 -6
- package/scripts/execution-resume-esc-integration-test.mjs +4 -2
- package/scripts/steering-drain-buckets-test.mjs +140 -5
- package/scripts/tui-transcript-perf-test.mjs +279 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +26 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +43 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +27 -13
- package/src/runtime/shared/buffered-appender.mjs +13 -2
- package/src/session-runtime/config-helpers.mjs +6 -6
- package/src/session-runtime/lifecycle-api.mjs +4 -0
- package/src/session-runtime/runtime-core.mjs +1 -0
- package/src/session-runtime/session-turn-api.mjs +12 -0
- package/src/standalone/agent-tool.mjs +8 -1
- package/src/tui/App.jsx +2 -1
- package/src/tui/app/transcript-window.mjs +9 -10
- package/src/tui/app/use-transcript-window.mjs +38 -56
- package/src/tui/dist/index.mjs +354 -163
- package/src/tui/engine/agent-job-feed.mjs +76 -6
- package/src/tui/engine/session-api.mjs +7 -1
- package/src/tui/engine/session-flow.mjs +3 -1
- package/src/tui/engine/tool-card-results.mjs +10 -5
- package/src/tui/engine/turn.mjs +96 -36
- package/src/tui/engine.mjs +136 -37
- package/src/tui/index.jsx +2 -2
package/src/tui/dist/index.mjs
CHANGED
|
@@ -10437,22 +10437,6 @@ function fnv1a32(str) {
|
|
|
10437
10437
|
}
|
|
10438
10438
|
return h >>> 0;
|
|
10439
10439
|
}
|
|
10440
|
-
function fnvStepA(hash, str) {
|
|
10441
|
-
let h = hash >>> 0;
|
|
10442
|
-
for (let i = 0; i < str.length; i++) {
|
|
10443
|
-
h ^= str.charCodeAt(i);
|
|
10444
|
-
h = h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)) >>> 0;
|
|
10445
|
-
}
|
|
10446
|
-
return h >>> 0;
|
|
10447
|
-
}
|
|
10448
|
-
function fnvStepB(hash, str) {
|
|
10449
|
-
let h = hash >>> 0;
|
|
10450
|
-
for (let i = 0; i < str.length; i++) {
|
|
10451
|
-
h = Math.imul(h ^ str.charCodeAt(i), 2246822519) >>> 0;
|
|
10452
|
-
h = (h ^ h >>> 13) >>> 0;
|
|
10453
|
-
}
|
|
10454
|
-
return h >>> 0;
|
|
10455
|
-
}
|
|
10456
10440
|
function textShapeFingerprint(value) {
|
|
10457
10441
|
if (value == null) return "z";
|
|
10458
10442
|
const text = String(value);
|
|
@@ -10637,7 +10621,7 @@ function buildTranscriptRowIndexIncremental(items, {
|
|
|
10637
10621
|
suppressMeasuredRowHeights = false,
|
|
10638
10622
|
measuredRowsVersion = 0,
|
|
10639
10623
|
cacheRef = null,
|
|
10640
|
-
|
|
10624
|
+
prefixRevision = null
|
|
10641
10625
|
} = {}) {
|
|
10642
10626
|
const allItems = Array.isArray(items) ? items : [];
|
|
10643
10627
|
const tail = trailingStreamingItem(allItems);
|
|
@@ -10652,7 +10636,7 @@ function buildTranscriptRowIndexIncremental(items, {
|
|
|
10652
10636
|
}
|
|
10653
10637
|
const prefixLen = allItems.length - 1;
|
|
10654
10638
|
const cache = holder.current;
|
|
10655
|
-
if (cache && cache.columns === columns && cache.toolExpanded === (toolOutputExpanded ? 1 : 0) && cache.suppress === suppressMeasuredRowHeights && cache.version === measuredRowsVersion && cache.prefixLen === prefixLen &&
|
|
10639
|
+
if (cache && cache.columns === columns && cache.toolExpanded === (toolOutputExpanded ? 1 : 0) && cache.suppress === suppressMeasuredRowHeights && cache.version === measuredRowsVersion && cache.prefixLen === prefixLen && prefixRevision != null && cache.prefixRevision === prefixRevision && cache.tailId === tail.id) {
|
|
10656
10640
|
{
|
|
10657
10641
|
const tailMeasured = suppressMeasuredRowHeights ? null : measuredTranscriptRows(tail, columns, toolOutputExpanded);
|
|
10658
10642
|
const tailRows = tailMeasured != null ? tailMeasured : estimateTranscriptItemRowsCached(tail, columns, toolOutputExpanded);
|
|
@@ -10674,7 +10658,7 @@ function buildTranscriptRowIndexIncremental(items, {
|
|
|
10674
10658
|
suppress: suppressMeasuredRowHeights,
|
|
10675
10659
|
version: measuredRowsVersion,
|
|
10676
10660
|
prefixLen,
|
|
10677
|
-
|
|
10661
|
+
prefixRevision,
|
|
10678
10662
|
tailId: tail.id,
|
|
10679
10663
|
prefixRowsArr: full.rows.slice(0, prefixLen),
|
|
10680
10664
|
prefixPrefixRows: full.prefixRows.slice(0, prefixLen + 1),
|
|
@@ -10682,36 +10666,6 @@ function buildTranscriptRowIndexIncremental(items, {
|
|
|
10682
10666
|
};
|
|
10683
10667
|
return full;
|
|
10684
10668
|
}
|
|
10685
|
-
var transcriptSigPartCache = /* @__PURE__ */ new WeakMap();
|
|
10686
|
-
function transcriptStructureSignature(items, columns, toolOutputExpanded) {
|
|
10687
|
-
const list = Array.isArray(items) ? items : [];
|
|
10688
|
-
let hA = fnvStepA(2166136261, `${list.length}|${columns}|${toolOutputExpanded ? 1 : 0}`);
|
|
10689
|
-
let hB = fnvStepB(3421674724, `${list.length}|${columns}|${toolOutputExpanded ? 1 : 0}`);
|
|
10690
|
-
for (let i = 0; i < list.length; i++) {
|
|
10691
|
-
const it = list[i];
|
|
10692
|
-
let sigPart;
|
|
10693
|
-
if (!it) {
|
|
10694
|
-
sigPart = "_";
|
|
10695
|
-
} else if (it.kind === "assistant" && it.streaming) {
|
|
10696
|
-
const resolvedRows = estimateTranscriptItemRowsCached(it, columns, toolOutputExpanded);
|
|
10697
|
-
sigPart = `a${it.id}:${resolvedRows}`;
|
|
10698
|
-
} else {
|
|
10699
|
-
const variantKey = transcriptItemVariantKey(it);
|
|
10700
|
-
const cached = transcriptSigPartCache.get(it);
|
|
10701
|
-
if (cached && cached.variantKey === variantKey && cached.columns === columns && cached.id === it.id && cached.kind === it.kind) {
|
|
10702
|
-
sigPart = cached.sigPart;
|
|
10703
|
-
} else {
|
|
10704
|
-
sigPart = `${it.kind?.[0] || "?"}${it.id}:${variantKey}`;
|
|
10705
|
-
transcriptSigPartCache.set(it, { id: it.id, kind: it.kind, variantKey, columns, sigPart });
|
|
10706
|
-
}
|
|
10707
|
-
}
|
|
10708
|
-
hA = fnvStepA(hA, `;${i};`);
|
|
10709
|
-
hA = fnvStepA(hA, sigPart);
|
|
10710
|
-
hB = fnvStepB(hB, `;${i};`);
|
|
10711
|
-
hB = fnvStepB(hB, sigPart);
|
|
10712
|
-
}
|
|
10713
|
-
return `${hA.toString(36)}.${hB.toString(36)}`;
|
|
10714
|
-
}
|
|
10715
10669
|
function transcriptRenderWindow(items, { scrollOffset = 0, viewportHeight = 24, columns = 80, toolOutputExpanded = false, rowIndex = null } = {}) {
|
|
10716
10670
|
const allItems = Array.isArray(items) ? items : [];
|
|
10717
10671
|
const itemCount = allItems.length;
|
|
@@ -11705,7 +11659,9 @@ function useTranscriptScroll({
|
|
|
11705
11659
|
// src/tui/app/use-transcript-window.mjs
|
|
11706
11660
|
import { useCallback as useCallback4, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useMemo, useRef as useRef9, useState as useState7 } from "react";
|
|
11707
11661
|
function useTranscriptWindow({
|
|
11708
|
-
items,
|
|
11662
|
+
items: settledItems,
|
|
11663
|
+
structureRevision,
|
|
11664
|
+
streamingTail,
|
|
11709
11665
|
themeEpoch,
|
|
11710
11666
|
frameColumns,
|
|
11711
11667
|
toolOutputExpanded,
|
|
@@ -11763,41 +11719,34 @@ function useTranscriptWindow({
|
|
|
11763
11719
|
}
|
|
11764
11720
|
return fn;
|
|
11765
11721
|
}, []);
|
|
11766
|
-
const streamingTailItem =
|
|
11767
|
-
const last = (items || []).length > 0 ? items[items.length - 1] : null;
|
|
11768
|
-
return last && last.kind === "assistant" && last.streaming ? last : null;
|
|
11769
|
-
}, [items]);
|
|
11770
|
-
const prefixLen = streamingTailItem ? (items || []).length - 1 : (items || []).length;
|
|
11771
|
-
const prefixSig = useMemo(
|
|
11772
|
-
() => transcriptStructureSignature(
|
|
11773
|
-
streamingTailItem ? (items || []).slice(0, prefixLen) : items || [],
|
|
11774
|
-
frameColumns,
|
|
11775
|
-
toolOutputExpanded
|
|
11776
|
-
),
|
|
11777
|
-
[items, streamingTailItem, prefixLen, frameColumns, toolOutputExpanded]
|
|
11778
|
-
);
|
|
11722
|
+
const streamingTailItem = streamingTail?.kind === "assistant" && streamingTail.streaming ? streamingTail : null;
|
|
11779
11723
|
const scrolledUpRowsForPin = Math.max(0, Number(scrollTargetRef.current) || 0);
|
|
11780
11724
|
const transcriptPinnedForStreaming = followingRef.current || scrolledUpRowsForPin <= transcriptBottomSlackRows;
|
|
11781
11725
|
setStreamingBottomPinned(transcriptPinnedForStreaming);
|
|
11782
|
-
const
|
|
11783
|
-
const
|
|
11784
|
-
const
|
|
11785
|
-
|
|
11726
|
+
const tailRows = streamingTailItem ? estimateTranscriptItemRowsCached(streamingTailItem, frameColumns, toolOutputExpanded) : 0;
|
|
11727
|
+
const tailSig = streamingTailItem ? `${streamingTailItem.id}:${tailRows}` : "_";
|
|
11728
|
+
const revision = Math.max(0, Number(structureRevision) || 0);
|
|
11729
|
+
const transcriptItems = useMemo(
|
|
11730
|
+
() => streamingTailItem ? [...settledItems || [], streamingTailItem] : settledItems || [],
|
|
11731
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- tail text at the same resolved height is injected into the bounded visible slice below
|
|
11732
|
+
[settledItems, revision, streamingTailItem?.id, tailRows]
|
|
11786
11733
|
);
|
|
11734
|
+
const transcriptStructureSig = `${revision}#${tailSig}`;
|
|
11735
|
+
const transcriptStreamingActive = !!streamingTailItem;
|
|
11787
11736
|
const scrolledUpForStreamingMeasure = scrolledUpRowsForPin > transcriptBottomSlackRows;
|
|
11788
11737
|
const prevEstimateGeometry = transcriptGeomRef.current?.suppressMeasuredRowHeights === true;
|
|
11789
11738
|
const hasStreamingReadingAnchor = !!transcriptAnchorRef.current || transcriptAnchorDirtyRef.current;
|
|
11790
11739
|
const bottomPinnedForMeasure = transcriptPinnedForStreaming;
|
|
11791
11740
|
const suppressMeasuredRowHeights = bottomPinnedForMeasure || transcriptStreamingActive && (scrolledUpForStreamingMeasure && hasStreamingReadingAnchor || scrolledUpForStreamingMeasure && prevEstimateGeometry && !transcriptPinnedForStreaming);
|
|
11792
|
-
const transcriptRowIndex = useMemo(() => buildTranscriptRowIndexIncremental(
|
|
11741
|
+
const transcriptRowIndex = useMemo(() => buildTranscriptRowIndexIncremental(transcriptItems, {
|
|
11793
11742
|
columns: frameColumns,
|
|
11794
11743
|
toolOutputExpanded,
|
|
11795
11744
|
suppressMeasuredRowHeights,
|
|
11796
11745
|
measuredRowsVersion,
|
|
11797
11746
|
cacheRef: incrementalRowIndexCacheRef,
|
|
11798
|
-
|
|
11799
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps --
|
|
11800
|
-
}), [
|
|
11747
|
+
prefixRevision: revision
|
|
11748
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- revision/tail height capture structural geometry; measuredRowsVersion folds in measured corrections
|
|
11749
|
+
}), [revision, tailSig, frameColumns, toolOutputExpanded, measuredRowsVersion, suppressMeasuredRowHeights]);
|
|
11801
11750
|
const hasReadingAnchor = !!transcriptAnchorRef.current && !transcriptAnchorDirtyRef.current;
|
|
11802
11751
|
const scrolledUpRows = Math.max(0, Number(scrollTargetRef.current) || 0);
|
|
11803
11752
|
const scrolledUp = scrolledUpRows > transcriptBottomSlackRows;
|
|
@@ -11812,7 +11761,7 @@ function useTranscriptWindow({
|
|
|
11812
11761
|
if (anchorLockActive) {
|
|
11813
11762
|
const locked = resolveAnchorScrollOffset({
|
|
11814
11763
|
anchor: transcriptAnchorRef.current,
|
|
11815
|
-
items,
|
|
11764
|
+
items: transcriptItems,
|
|
11816
11765
|
curPrefix: curPrefixForLock,
|
|
11817
11766
|
totalRows: lockTotalRows,
|
|
11818
11767
|
viewRows: lockViewRows,
|
|
@@ -11836,7 +11785,7 @@ function useTranscriptWindow({
|
|
|
11836
11785
|
const captured = { id: anchorItem.id, offset: Math.max(0, prevTopRow - (prevPrefix[idx] || 0)) };
|
|
11837
11786
|
const locked = resolveAnchorScrollOffset({
|
|
11838
11787
|
anchor: captured,
|
|
11839
|
-
items,
|
|
11788
|
+
items: transcriptItems,
|
|
11840
11789
|
curPrefix: curPrefixForLock,
|
|
11841
11790
|
totalRows: lockTotalRows,
|
|
11842
11791
|
viewRows: lockViewRows,
|
|
@@ -11869,7 +11818,7 @@ function useTranscriptWindow({
|
|
|
11869
11818
|
const captured = { id: anchorItem.id, offset: Math.max(0, prevTopRow - (prevPrefix[idx] || 0)) };
|
|
11870
11819
|
const locked = resolveAnchorScrollOffset({
|
|
11871
11820
|
anchor: captured,
|
|
11872
|
-
items,
|
|
11821
|
+
items: transcriptItems,
|
|
11873
11822
|
curPrefix: curPrefixForLock,
|
|
11874
11823
|
totalRows: lockTotalRows,
|
|
11875
11824
|
viewRows: lockViewRows,
|
|
@@ -11888,7 +11837,7 @@ function useTranscriptWindow({
|
|
|
11888
11837
|
floatingPanelRows: Number(floatingPanelRows) || 0
|
|
11889
11838
|
};
|
|
11890
11839
|
if (scrolledUp && !followingRef.current) {
|
|
11891
|
-
const growth = streamingTailMountedGrowth(
|
|
11840
|
+
const growth = streamingTailMountedGrowth(transcriptItems, frameColumns, toolOutputExpanded);
|
|
11892
11841
|
if (growth && growth.delta > 0) {
|
|
11893
11842
|
const maxOffsetKeepingTailMounted = growth.tailRows + TRANSCRIPT_WINDOW_OVERSCAN_ROWS - 1;
|
|
11894
11843
|
if (renderScrollOffset <= maxOffsetKeepingTailMounted) {
|
|
@@ -11896,7 +11845,7 @@ function useTranscriptWindow({
|
|
|
11896
11845
|
}
|
|
11897
11846
|
}
|
|
11898
11847
|
}
|
|
11899
|
-
const transcriptWindow = useMemo(() => transcriptRenderWindow(
|
|
11848
|
+
const transcriptWindow = useMemo(() => transcriptRenderWindow(transcriptItems, {
|
|
11900
11849
|
scrollOffset: renderScrollOffset,
|
|
11901
11850
|
viewportHeight: transcriptContentHeight,
|
|
11902
11851
|
columns: frameColumns,
|
|
@@ -11933,7 +11882,7 @@ function useTranscriptWindow({
|
|
|
11933
11882
|
prefixRows: transcriptRowIndex?.prefixRows || null,
|
|
11934
11883
|
totalRows: Math.max(0, Number(transcriptWindow.totalRows) || 0),
|
|
11935
11884
|
viewRows: Math.max(1, Number(transcriptContentHeight) || 1),
|
|
11936
|
-
items:
|
|
11885
|
+
items: transcriptItems || null,
|
|
11937
11886
|
// The offset THIS frame actually rendered with. The same-frame anchor
|
|
11938
11887
|
// CAPTURE for a missing/dirty anchor (above) reads this from the PREVIOUS
|
|
11939
11888
|
// frame to reconstruct the exact top-edge row that was on screen, so the
|
|
@@ -11945,10 +11894,16 @@ function useTranscriptWindow({
|
|
|
11945
11894
|
renderOffset: Math.max(0, Number(transcriptWindow.effectiveScrollOffset) || 0),
|
|
11946
11895
|
suppressMeasuredRowHeights
|
|
11947
11896
|
};
|
|
11948
|
-
const transcriptVisibleItems = (
|
|
11897
|
+
const transcriptVisibleItems = (transcriptItems || []).slice(
|
|
11949
11898
|
transcriptWindow.startIndex,
|
|
11950
11899
|
transcriptWindow.endIndex
|
|
11951
11900
|
);
|
|
11901
|
+
if (streamingTailItem && transcriptVisibleItems.length > 0) {
|
|
11902
|
+
const last = transcriptVisibleItems.length - 1;
|
|
11903
|
+
if (transcriptVisibleItems[last]?.id === streamingTailItem.id) {
|
|
11904
|
+
transcriptVisibleItems[last] = streamingTailItem;
|
|
11905
|
+
}
|
|
11906
|
+
}
|
|
11952
11907
|
const renderedTranscriptItems = transcriptVisibleItems;
|
|
11953
11908
|
let overlayHintAttachItemIndex = -1;
|
|
11954
11909
|
for (let i = renderedTranscriptItems.length - 1; i >= 0; i--) {
|
|
@@ -12068,7 +12023,7 @@ function useTranscriptWindow({
|
|
|
12068
12023
|
return;
|
|
12069
12024
|
}
|
|
12070
12025
|
const viewRows = Math.max(1, Number(transcriptContentHeight) || 1);
|
|
12071
|
-
const itemList =
|
|
12026
|
+
const itemList = transcriptItems || [];
|
|
12072
12027
|
let anchor = transcriptAnchorRef.current;
|
|
12073
12028
|
if (!followingRef.current && (!anchor || transcriptAnchorDirtyRef.current)) {
|
|
12074
12029
|
if (curPrefix && curPrefix.length > 1) {
|
|
@@ -21475,6 +21430,8 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
21475
21430
|
transcriptMeasureRef
|
|
21476
21431
|
} = useTranscriptWindow({
|
|
21477
21432
|
items: state.items,
|
|
21433
|
+
structureRevision: state.structureRevision,
|
|
21434
|
+
streamingTail: state.streamingTail,
|
|
21478
21435
|
themeEpoch: state.themeEpoch,
|
|
21479
21436
|
frameColumns,
|
|
21480
21437
|
toolOutputExpanded,
|
|
@@ -23123,8 +23080,13 @@ function createToolCardResults({
|
|
|
23123
23080
|
markToolCallDone,
|
|
23124
23081
|
updateAgentJobCard,
|
|
23125
23082
|
buildAgentJobCardPatch,
|
|
23126
|
-
agentStatusState
|
|
23083
|
+
agentStatusState,
|
|
23084
|
+
itemIndexById
|
|
23127
23085
|
}) {
|
|
23086
|
+
const itemById = (id) => {
|
|
23087
|
+
const index = itemIndexById?.get(id);
|
|
23088
|
+
return Number.isInteger(index) ? getState().items[index]?.id === id ? getState().items[index] : null : null;
|
|
23089
|
+
};
|
|
23128
23090
|
function finalizedErrorFallbackBody(body, text, exitCode) {
|
|
23129
23091
|
if (String(body || "").trim()) return body;
|
|
23130
23092
|
if (String(text || "").trim()) return text;
|
|
@@ -23132,10 +23094,10 @@ function createToolCardResults({
|
|
|
23132
23094
|
return "Failed";
|
|
23133
23095
|
}
|
|
23134
23096
|
function patchToolItem(id, patch) {
|
|
23135
|
-
const prev =
|
|
23097
|
+
const prev = itemById(id);
|
|
23136
23098
|
const ok = patchItem(id, patch);
|
|
23137
23099
|
if (!ok || !prev) return ok;
|
|
23138
|
-
const next =
|
|
23100
|
+
const next = itemById(id);
|
|
23139
23101
|
if (next && next !== prev) carryTranscriptMeasuredRowsCache(prev, next);
|
|
23140
23102
|
return ok;
|
|
23141
23103
|
}
|
|
@@ -23173,7 +23135,7 @@ function createToolCardResults({
|
|
|
23173
23135
|
const exitErrors = allCalls.filter((r) => r.isExitError).length;
|
|
23174
23136
|
const succeeded = Math.max(0, completed - errors - exitErrors);
|
|
23175
23137
|
const detailText = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
23176
|
-
const currentItem =
|
|
23138
|
+
const currentItem = itemById(card.itemId);
|
|
23177
23139
|
const earlyCompleted = allCalls.filter((r) => r.resolved || r.completedEarly).length;
|
|
23178
23140
|
const visualCompleted = Math.max(completed, earlyCompleted, Math.min(allCalls.length, Number(currentItem?.completedCount || 0)));
|
|
23179
23141
|
const rawResult = aggregateRawResult(allCalls);
|
|
@@ -23284,7 +23246,7 @@ function createToolCardResults({
|
|
|
23284
23246
|
const rawResult = aggregateRawResult(allCalls);
|
|
23285
23247
|
let displayDetail = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
23286
23248
|
if (cancelled) {
|
|
23287
|
-
const currentItem =
|
|
23249
|
+
const currentItem = itemById(card.itemId);
|
|
23288
23250
|
displayDetail = withCancelledResultMarker(displayDetail, currentItem);
|
|
23289
23251
|
}
|
|
23290
23252
|
patchToolItem(card.itemId, {
|
|
@@ -23316,7 +23278,7 @@ function createToolCardResults({
|
|
|
23316
23278
|
resultText = finalizedErrorFallbackBody(resultText, exitRec?.text, exitRec?.exitCode);
|
|
23317
23279
|
}
|
|
23318
23280
|
if (cancelled) {
|
|
23319
|
-
const currentItem =
|
|
23281
|
+
const currentItem = itemById(card.itemId);
|
|
23320
23282
|
resultText = withCancelledResultMarker(resultText, currentItem);
|
|
23321
23283
|
}
|
|
23322
23284
|
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() });
|
|
@@ -23419,14 +23381,67 @@ function createAgentJobFeed({
|
|
|
23419
23381
|
getPending,
|
|
23420
23382
|
agentStatusState,
|
|
23421
23383
|
displayedExecutionNotificationKeys,
|
|
23384
|
+
itemIndexById,
|
|
23422
23385
|
pushNotice,
|
|
23423
23386
|
now = () => Date.now(),
|
|
23424
23387
|
executionResumeTombstoneTtlMs = 3e4,
|
|
23425
23388
|
executionResumeTombstoneLimit = 128
|
|
23426
23389
|
}) {
|
|
23390
|
+
const executionDedupLimit = 256;
|
|
23427
23391
|
let executionResumeKickDeferred = false;
|
|
23428
23392
|
const discardedExecutionResumeKeys = /* @__PURE__ */ new Map();
|
|
23429
23393
|
const displayedExecutionResponseStates = /* @__PURE__ */ new Map();
|
|
23394
|
+
const terminalExecutionNotificationKeys = /* @__PURE__ */ new Set();
|
|
23395
|
+
const terminalExecutionResponseKeys = /* @__PURE__ */ new Set();
|
|
23396
|
+
const executionNotificationKeys = /* @__PURE__ */ new Map();
|
|
23397
|
+
const clearExecutionDedupState = () => {
|
|
23398
|
+
displayedExecutionNotificationKeys.clear();
|
|
23399
|
+
displayedExecutionResponseStates.clear();
|
|
23400
|
+
terminalExecutionNotificationKeys.clear();
|
|
23401
|
+
terminalExecutionResponseKeys.clear();
|
|
23402
|
+
executionNotificationKeys.clear();
|
|
23403
|
+
};
|
|
23404
|
+
const rememberDisplayedExecutionNotificationKey = (key, terminal = false, executionId = "") => {
|
|
23405
|
+
if (!key) return;
|
|
23406
|
+
displayedExecutionNotificationKeys.delete(key);
|
|
23407
|
+
if (executionId) executionNotificationKeys.set(key, executionId);
|
|
23408
|
+
if (terminal) terminalExecutionNotificationKeys.add(key);
|
|
23409
|
+
else terminalExecutionNotificationKeys.delete(key);
|
|
23410
|
+
while (displayedExecutionNotificationKeys.size >= executionDedupLimit) {
|
|
23411
|
+
const oldestTerminal = [...displayedExecutionNotificationKeys].find((candidate) => terminalExecutionNotificationKeys.has(candidate));
|
|
23412
|
+
if (oldestTerminal == null) break;
|
|
23413
|
+
displayedExecutionNotificationKeys.delete(oldestTerminal);
|
|
23414
|
+
terminalExecutionNotificationKeys.delete(oldestTerminal);
|
|
23415
|
+
executionNotificationKeys.delete(oldestTerminal);
|
|
23416
|
+
}
|
|
23417
|
+
displayedExecutionNotificationKeys.add(key);
|
|
23418
|
+
};
|
|
23419
|
+
const promoteExecutionNotificationKeys = (executionId) => {
|
|
23420
|
+
if (!executionId) return;
|
|
23421
|
+
for (const [key, keyExecutionId] of executionNotificationKeys) {
|
|
23422
|
+
if (keyExecutionId !== executionId || !displayedExecutionNotificationKeys.has(key)) continue;
|
|
23423
|
+
terminalExecutionNotificationKeys.add(key);
|
|
23424
|
+
}
|
|
23425
|
+
};
|
|
23426
|
+
const promoteExecutionDedupState = (executionId) => {
|
|
23427
|
+
if (!executionId) return;
|
|
23428
|
+
promoteExecutionNotificationKeys(executionId);
|
|
23429
|
+
const responseState = displayedExecutionResponseStates.get(executionId);
|
|
23430
|
+
if (responseState) rememberDisplayedExecutionResponseState(executionId, responseState, true);
|
|
23431
|
+
};
|
|
23432
|
+
const rememberDisplayedExecutionResponseState = (key, value, terminal = false) => {
|
|
23433
|
+
if (!key) return;
|
|
23434
|
+
displayedExecutionResponseStates.delete(key);
|
|
23435
|
+
if (terminal) terminalExecutionResponseKeys.add(key);
|
|
23436
|
+
else terminalExecutionResponseKeys.delete(key);
|
|
23437
|
+
while (displayedExecutionResponseStates.size >= executionDedupLimit) {
|
|
23438
|
+
const oldestTerminal = [...displayedExecutionResponseStates.keys()].find((candidate) => terminalExecutionResponseKeys.has(candidate));
|
|
23439
|
+
if (oldestTerminal == null) break;
|
|
23440
|
+
displayedExecutionResponseStates.delete(oldestTerminal);
|
|
23441
|
+
terminalExecutionResponseKeys.delete(oldestTerminal);
|
|
23442
|
+
}
|
|
23443
|
+
displayedExecutionResponseStates.set(key, value);
|
|
23444
|
+
};
|
|
23430
23445
|
const executionResumeKickBodies = [];
|
|
23431
23446
|
function executionResumeKey(body, completionKey = "") {
|
|
23432
23447
|
if (completionKey && typeof completionKey === "object") {
|
|
@@ -23508,7 +23523,8 @@ function createAgentJobFeed({
|
|
|
23508
23523
|
}
|
|
23509
23524
|
function buildAgentJobCardPatch(itemId, text, isError = false) {
|
|
23510
23525
|
const parsed = parseAgentJob(text);
|
|
23511
|
-
const
|
|
23526
|
+
const index = itemIndexById?.get(itemId);
|
|
23527
|
+
const current = Number.isInteger(index) && getState().items[index]?.id === itemId ? getState().items[index] : null;
|
|
23512
23528
|
const rawDisplayText = agentJobResultText(text, parsed) || String(text ?? "").trim();
|
|
23513
23529
|
const displayText = isError ? toolErrorDisplay(rawDisplayText, "agent") : rawDisplayText;
|
|
23514
23530
|
return {
|
|
@@ -23530,13 +23546,17 @@ function createAgentJobFeed({
|
|
|
23530
23546
|
}
|
|
23531
23547
|
function subscribeRuntimeNotifications() {
|
|
23532
23548
|
if (typeof runtime.onNotification !== "function") return null;
|
|
23533
|
-
|
|
23549
|
+
const unsubscribe = runtime.onNotification((event) => {
|
|
23534
23550
|
if (getDisposed()) return;
|
|
23535
23551
|
const text = String(event?.content ?? event?.text ?? event ?? "").trim();
|
|
23536
23552
|
if (!text) return;
|
|
23537
23553
|
const parsed = parseAgentJob(text);
|
|
23538
23554
|
const notificationKey = notificationQueueKey(event, text, parsed);
|
|
23539
23555
|
const delivery = resolveTuiRuntimeNotificationDelivery(event, text);
|
|
23556
|
+
const executionId = String(event?.meta?.execution_id || parsed?.taskId || "").trim();
|
|
23557
|
+
const status = String(event?.meta?.status || parsed?.status || "").toLowerCase();
|
|
23558
|
+
const terminalStatus = /^(completed|complete|done|success|succeeded|ok|failed|error|timeout|killed|cancelled|canceled|denied)$/.test(status);
|
|
23559
|
+
if (terminalStatus) promoteExecutionDedupState(executionId);
|
|
23540
23560
|
if (delivery.action === "ignore") return;
|
|
23541
23561
|
if (delivery.action === "notice") {
|
|
23542
23562
|
pushNotice?.(delivery.displayText, delivery.tone || "info", { transcript: delivery.transcript === true });
|
|
@@ -23549,16 +23569,19 @@ function createAgentJobFeed({
|
|
|
23549
23569
|
if (delivery.action === "execution-ui") {
|
|
23550
23570
|
const cardKey = executionCardKey(event, text, parsed);
|
|
23551
23571
|
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
23572
|
const hasBody = /\n\s*\n[\s\S]*\S/.test(text);
|
|
23555
23573
|
const isFailure = /^(failed|error|timeout|killed|cancelled|canceled|denied)$/.test(status);
|
|
23556
23574
|
const successfulPreview = !hasBody && !isFailure && /^(completed|complete|done|success|succeeded|ok)$/.test(status);
|
|
23575
|
+
const terminal = terminalStatus;
|
|
23557
23576
|
const responseState = executionId ? displayedExecutionResponseStates.get(executionId) : "";
|
|
23558
23577
|
const bodyAlreadyDisplayed = responseState === "body";
|
|
23578
|
+
if (cardKey && terminal && displayedExecutionNotificationKeys.has(cardKey)) {
|
|
23579
|
+
rememberDisplayedExecutionNotificationKey(cardKey, true, executionId);
|
|
23580
|
+
}
|
|
23581
|
+
if (terminal) promoteExecutionDedupState(executionId);
|
|
23559
23582
|
if (firstDelivery && !successfulPreview && !bodyAlreadyDisplayed) {
|
|
23560
|
-
if (cardKey)
|
|
23561
|
-
if (executionId)
|
|
23583
|
+
if (cardKey) rememberDisplayedExecutionNotificationKey(cardKey, terminal, executionId);
|
|
23584
|
+
if (executionId) rememberDisplayedExecutionResponseState(executionId, hasBody ? "body" : "preview", terminal);
|
|
23562
23585
|
(pushAsyncAgentResponse || pushUserOrSyntheticItem)(delivery.displayText, nextId2(), "injected", { responseKey: executionId });
|
|
23563
23586
|
}
|
|
23564
23587
|
refreshAgentStatus(parsed);
|
|
@@ -23627,6 +23650,13 @@ function createAgentJobFeed({
|
|
|
23627
23650
|
enqueue(modelContent, enqueueOpts);
|
|
23628
23651
|
return true;
|
|
23629
23652
|
});
|
|
23653
|
+
return () => {
|
|
23654
|
+
try {
|
|
23655
|
+
unsubscribe?.();
|
|
23656
|
+
} finally {
|
|
23657
|
+
clearExecutionDedupState();
|
|
23658
|
+
}
|
|
23659
|
+
};
|
|
23630
23660
|
}
|
|
23631
23661
|
return {
|
|
23632
23662
|
kickExecutionPendingResume,
|
|
@@ -23635,7 +23665,8 @@ function createAgentJobFeed({
|
|
|
23635
23665
|
discardExecutionPendingResume,
|
|
23636
23666
|
updateAgentJobCard,
|
|
23637
23667
|
buildAgentJobCardPatch,
|
|
23638
|
-
subscribeRuntimeNotifications
|
|
23668
|
+
subscribeRuntimeNotifications,
|
|
23669
|
+
clearExecutionDedupState
|
|
23639
23670
|
};
|
|
23640
23671
|
}
|
|
23641
23672
|
|
|
@@ -24022,6 +24053,7 @@ function createSessionFlow(bag) {
|
|
|
24022
24053
|
pending,
|
|
24023
24054
|
pendingNotificationKeys,
|
|
24024
24055
|
displayedExecutionNotificationKeys,
|
|
24056
|
+
clearExecutionDedupState,
|
|
24025
24057
|
getState,
|
|
24026
24058
|
set,
|
|
24027
24059
|
pushItem,
|
|
@@ -24120,6 +24152,7 @@ function createSessionFlow(bag) {
|
|
|
24120
24152
|
if (predicate(entry) && (entry.mode || "prompt") === targetMode && queuePriorityValue(entry.priority) === bestPriority) {
|
|
24121
24153
|
batch.push(entry);
|
|
24122
24154
|
pending.splice(i, 1);
|
|
24155
|
+
if (entry.mode === "task-notification" && entry.key) pendingNotificationKeys.delete(entry.key);
|
|
24123
24156
|
if (batch.length >= limit) break;
|
|
24124
24157
|
} else {
|
|
24125
24158
|
i += 1;
|
|
@@ -24417,6 +24450,7 @@ function createSessionFlow(bag) {
|
|
|
24417
24450
|
getState().busy = false;
|
|
24418
24451
|
pendingNotificationKeys.clear();
|
|
24419
24452
|
displayedExecutionNotificationKeys.clear();
|
|
24453
|
+
clearExecutionDedupState?.();
|
|
24420
24454
|
};
|
|
24421
24455
|
const applyClearedSessionUi = (doneLabel) => {
|
|
24422
24456
|
resetStats();
|
|
@@ -24512,6 +24546,9 @@ function createRunTurn(bag) {
|
|
|
24512
24546
|
set,
|
|
24513
24547
|
pushItem,
|
|
24514
24548
|
patchItem,
|
|
24549
|
+
updateStreamingTail: updateStreamingTailFromStore,
|
|
24550
|
+
settleStreamingTail: settleStreamingTailFromStore,
|
|
24551
|
+
clearStreamingTail: clearStreamingTailFromStore,
|
|
24515
24552
|
pushNotice,
|
|
24516
24553
|
pushUserOrSyntheticItem,
|
|
24517
24554
|
markToolCallActive,
|
|
@@ -24528,6 +24565,21 @@ function createRunTurn(bag) {
|
|
|
24528
24565
|
drain,
|
|
24529
24566
|
drainPendingSteering
|
|
24530
24567
|
} = bag;
|
|
24568
|
+
const updateStreamingTail = updateStreamingTailFromStore || ((id, patch = {}) => {
|
|
24569
|
+
set({ streamingTail: { ...getState().streamingTail || {}, ...patch, kind: "assistant", id, streaming: true } });
|
|
24570
|
+
return true;
|
|
24571
|
+
});
|
|
24572
|
+
const settleStreamingTail = settleStreamingTailFromStore || ((id, patch = {}) => {
|
|
24573
|
+
const tail = getState().streamingTail;
|
|
24574
|
+
if (!tail || tail.id !== id) return false;
|
|
24575
|
+
pushItem({ ...tail, ...patch, kind: "assistant", id, streaming: false });
|
|
24576
|
+
set({ streamingTail: null });
|
|
24577
|
+
return true;
|
|
24578
|
+
});
|
|
24579
|
+
const clearStreamingTail = clearStreamingTailFromStore || ((id = null) => {
|
|
24580
|
+
if (id == null || getState().streamingTail?.id === id) set({ streamingTail: null });
|
|
24581
|
+
return true;
|
|
24582
|
+
});
|
|
24531
24583
|
async function runTurn(userText, options = {}) {
|
|
24532
24584
|
const turnIndex = getState().stats.turns || 0;
|
|
24533
24585
|
const startedAt = Date.now();
|
|
@@ -24559,6 +24611,9 @@ function createRunTurn(bag) {
|
|
|
24559
24611
|
let watchdogGraceTimer = null;
|
|
24560
24612
|
let lastProgressAt = startedAt;
|
|
24561
24613
|
let lastProgressLabel = "start";
|
|
24614
|
+
let watchdogDeferralCeilingAt = 0;
|
|
24615
|
+
const configuredLeadToolMaxMs = Number(process.env.MIXDOG_LEAD_TOOL_MAX_MS);
|
|
24616
|
+
const leadToolMaxMs = Number.isFinite(configuredLeadToolMaxMs) && configuredLeadToolMaxMs > 0 ? configuredLeadToolMaxMs : 30 * 60 * 1e3;
|
|
24562
24617
|
const clearWatchdog = () => {
|
|
24563
24618
|
if (watchdogTimer) {
|
|
24564
24619
|
clearTimeout(watchdogTimer);
|
|
@@ -24569,21 +24624,57 @@ function createRunTurn(bag) {
|
|
|
24569
24624
|
watchdogGraceTimer = null;
|
|
24570
24625
|
}
|
|
24571
24626
|
};
|
|
24627
|
+
const refreshWatchdogFromRuntimeLiveness = () => {
|
|
24628
|
+
let liveness;
|
|
24629
|
+
try {
|
|
24630
|
+
liveness = runtime.getTurnLiveness?.();
|
|
24631
|
+
} catch {
|
|
24632
|
+
return false;
|
|
24633
|
+
}
|
|
24634
|
+
if (liveness?.stage !== "tool_running") watchdogDeferralCeilingAt = 0;
|
|
24635
|
+
const progressAt = Number(liveness?.lastProgressAt);
|
|
24636
|
+
const now = Date.now();
|
|
24637
|
+
if (!liveness || !Number.isFinite(progressAt) || progressAt <= now - LEAD_TURN_TIMEOUT_MS2) return false;
|
|
24638
|
+
if (liveness.stage === "tool_running") {
|
|
24639
|
+
watchdogDeferralCeilingAt = 0;
|
|
24640
|
+
const toolStartedAt = Number(liveness.toolStartedAt);
|
|
24641
|
+
if (!Number.isFinite(toolStartedAt) || toolStartedAt <= 0) return false;
|
|
24642
|
+
const toolSelfDeadlineMs = Number(liveness.toolSelfDeadlineMs);
|
|
24643
|
+
const toolCeilingMs = Math.max(
|
|
24644
|
+
Number.isFinite(toolSelfDeadlineMs) && toolSelfDeadlineMs > 0 ? toolSelfDeadlineMs + 6e4 : 0,
|
|
24645
|
+
leadToolMaxMs
|
|
24646
|
+
);
|
|
24647
|
+
if (now - toolStartedAt >= toolCeilingMs) return false;
|
|
24648
|
+
watchdogDeferralCeilingAt = toolStartedAt + toolCeilingMs;
|
|
24649
|
+
}
|
|
24650
|
+
lastProgressAt = progressAt;
|
|
24651
|
+
lastProgressLabel = `orchestrator:${String(liveness.stage || "unknown")}`;
|
|
24652
|
+
armWatchdog();
|
|
24653
|
+
return true;
|
|
24654
|
+
};
|
|
24572
24655
|
const armWatchdog = () => {
|
|
24573
24656
|
if (watchdogTimer) {
|
|
24574
24657
|
clearTimeout(watchdogTimer);
|
|
24575
24658
|
watchdogTimer = null;
|
|
24576
24659
|
}
|
|
24577
24660
|
if (watchdogTripped) return;
|
|
24578
|
-
const
|
|
24661
|
+
const now = Date.now();
|
|
24662
|
+
const remaining = Math.max(1, LEAD_TURN_TIMEOUT_MS2 - Math.max(0, now - lastProgressAt));
|
|
24663
|
+
const ceilingRemaining = watchdogDeferralCeilingAt > 0 ? Math.max(1, watchdogDeferralCeilingAt - now) : Infinity;
|
|
24664
|
+
const delay = Math.min(remaining, ceilingRemaining);
|
|
24579
24665
|
watchdogTimer = setTimeout(() => {
|
|
24580
24666
|
if (!isCurrentTurn()) return;
|
|
24581
24667
|
if (watchdogTripped) return;
|
|
24582
|
-
const
|
|
24668
|
+
const now2 = Date.now();
|
|
24669
|
+
const idleMs = now2 - lastProgressAt;
|
|
24583
24670
|
if (idleMs < LEAD_TURN_TIMEOUT_MS2) {
|
|
24584
|
-
|
|
24585
|
-
|
|
24586
|
-
|
|
24671
|
+
if (watchdogDeferralCeilingAt > 0 && now2 >= watchdogDeferralCeilingAt) {
|
|
24672
|
+
if (refreshWatchdogFromRuntimeLiveness()) return;
|
|
24673
|
+
} else {
|
|
24674
|
+
armWatchdog();
|
|
24675
|
+
return;
|
|
24676
|
+
}
|
|
24677
|
+
} else if (refreshWatchdogFromRuntimeLiveness()) return;
|
|
24587
24678
|
watchdogTripped = true;
|
|
24588
24679
|
if (_batchTimer !== null) {
|
|
24589
24680
|
clearTimeout(_batchTimer);
|
|
@@ -24594,7 +24685,7 @@ function createRunTurn(bag) {
|
|
|
24594
24685
|
_pendingThinkingLastEndedAt = 0;
|
|
24595
24686
|
const elapsed = Date.now() - startedAt;
|
|
24596
24687
|
tuiDebug2(`runTurn WATCHDOG TRIP turn=${turnIndex} elapsedMs=${elapsed} idleMs=${idleMs} lastProgress=${lastProgressLabel} \u2014 aborting stuck turn`);
|
|
24597
|
-
pushNotice(`Turn timed out after ${Math.round(idleMs / 1e3)}s idle \u2014 aborting stuck request. Input will be released shortly if abort does not unwind.`, "warn", { transcript: true });
|
|
24688
|
+
pushNotice(`Turn timed out after ${Math.round(idleMs / 1e3)}s idle (last progress: ${lastProgressLabel}) \u2014 aborting stuck request. Input will be released shortly if abort does not unwind.`, "warn", { transcript: true });
|
|
24598
24689
|
try {
|
|
24599
24690
|
runtime.abort("cli-react-abort-watchdog");
|
|
24600
24691
|
} catch {
|
|
@@ -24610,6 +24701,11 @@ function createRunTurn(bag) {
|
|
|
24610
24701
|
finalizeToolHeaders();
|
|
24611
24702
|
clearDeferredTimers();
|
|
24612
24703
|
flags.flushDeferredBeforeImmediatePush = null;
|
|
24704
|
+
if (currentAssistantId && currentAssistantText.trim()) {
|
|
24705
|
+
settleStreamingTail(currentAssistantId, { text: currentAssistantText });
|
|
24706
|
+
} else {
|
|
24707
|
+
clearStreamingTail(currentAssistantId);
|
|
24708
|
+
}
|
|
24613
24709
|
flags.leadTurnEpoch++;
|
|
24614
24710
|
set({ busy: false, spinner: null, thinking: null, lastTurn: null });
|
|
24615
24711
|
flags.activePromptRestore = null;
|
|
@@ -24618,7 +24714,7 @@ function createRunTurn(bag) {
|
|
|
24618
24714
|
flushDeferredExecutionPendingResumeKick();
|
|
24619
24715
|
}, 5e3);
|
|
24620
24716
|
watchdogGraceTimer.unref?.();
|
|
24621
|
-
},
|
|
24717
|
+
}, delay);
|
|
24622
24718
|
watchdogTimer.unref?.();
|
|
24623
24719
|
};
|
|
24624
24720
|
const markTurnProgress = (label) => {
|
|
@@ -24626,7 +24722,6 @@ function createRunTurn(bag) {
|
|
|
24626
24722
|
if (watchdogTripped) return;
|
|
24627
24723
|
lastProgressAt = Date.now();
|
|
24628
24724
|
lastProgressLabel = String(label || "progress");
|
|
24629
|
-
armWatchdog();
|
|
24630
24725
|
return true;
|
|
24631
24726
|
};
|
|
24632
24727
|
armWatchdog();
|
|
@@ -24770,7 +24865,7 @@ function createRunTurn(bag) {
|
|
|
24770
24865
|
const it = newItems[i];
|
|
24771
24866
|
if (it?.id != null) itemIndexById.set(it.id, base + i);
|
|
24772
24867
|
}
|
|
24773
|
-
set({ items, ...extra });
|
|
24868
|
+
set({ items, structureRevision: (Number(getState().structureRevision) || 0) + 1, ...extra });
|
|
24774
24869
|
};
|
|
24775
24870
|
const markPromptCommitted = () => {
|
|
24776
24871
|
if (flags.activePromptRestore) {
|
|
@@ -24805,7 +24900,7 @@ function createRunTurn(bag) {
|
|
|
24805
24900
|
changed = true;
|
|
24806
24901
|
return { ...item, headerFinalized: true };
|
|
24807
24902
|
});
|
|
24808
|
-
if (changed) set({ items });
|
|
24903
|
+
if (changed) set({ items, structureRevision: (Number(getState().structureRevision) || 0) + 1 });
|
|
24809
24904
|
return changed;
|
|
24810
24905
|
};
|
|
24811
24906
|
const completeAggregateVisual = () => {
|
|
@@ -24896,7 +24991,7 @@ function createRunTurn(bag) {
|
|
|
24896
24991
|
const ensureAssistant = (initialText = "") => {
|
|
24897
24992
|
if (!currentAssistantId) {
|
|
24898
24993
|
currentAssistantId = nextId2();
|
|
24899
|
-
|
|
24994
|
+
updateStreamingTail(currentAssistantId, { text: String(initialText || "") });
|
|
24900
24995
|
}
|
|
24901
24996
|
return currentAssistantId;
|
|
24902
24997
|
};
|
|
@@ -24907,7 +25002,6 @@ function createRunTurn(bag) {
|
|
|
24907
25002
|
_lastNewlineIdx = -1;
|
|
24908
25003
|
_emittedNewlineIdx = -2;
|
|
24909
25004
|
_emittedVisibleText = "";
|
|
24910
|
-
_cachedAssistantIndex = -1;
|
|
24911
25005
|
};
|
|
24912
25006
|
const commitAssistantSegment = ({ sealToolBlock = false } = {}) => {
|
|
24913
25007
|
const text = currentAssistantText || "";
|
|
@@ -24917,7 +25011,7 @@ function createRunTurn(bag) {
|
|
|
24917
25011
|
}
|
|
24918
25012
|
if (sealToolBlock) clearAggregateContinuation();
|
|
24919
25013
|
const id = currentAssistantId || ensureAssistant(text);
|
|
24920
|
-
|
|
25014
|
+
settleStreamingTail(id, { text });
|
|
24921
25015
|
committedSegments.push(text);
|
|
24922
25016
|
closeAssistantSegment();
|
|
24923
25017
|
return true;
|
|
@@ -24945,7 +25039,6 @@ function createRunTurn(bag) {
|
|
|
24945
25039
|
let _lastNewlineIdx = -1;
|
|
24946
25040
|
let _emittedNewlineIdx = -2;
|
|
24947
25041
|
let _emittedVisibleText = "";
|
|
24948
|
-
let _cachedAssistantIndex = -1;
|
|
24949
25042
|
let _publishedThinkingActive = false;
|
|
24950
25043
|
const flushStreamBatch = () => {
|
|
24951
25044
|
if (_batchTimer !== null) {
|
|
@@ -24980,22 +25073,13 @@ function createRunTurn(bag) {
|
|
|
24980
25073
|
const patch = {};
|
|
24981
25074
|
if (currentAssistantId || streamingVisibleText.trim()) {
|
|
24982
25075
|
const id = ensureAssistant(streamingVisibleText);
|
|
24983
|
-
|
|
24984
|
-
if (
|
|
24985
|
-
|
|
24986
|
-
_cachedAssistantIndex = index;
|
|
24987
|
-
}
|
|
24988
|
-
if (index >= 0) {
|
|
24989
|
-
const current = getState().items[index];
|
|
24990
|
-
if (!Object.is(current.text, streamingVisibleText) || current.streaming !== true) {
|
|
24991
|
-
const items = getState().items.slice();
|
|
24992
|
-
items[index] = { ...current, text: streamingVisibleText, streaming: true };
|
|
24993
|
-
patch.items = items;
|
|
24994
|
-
}
|
|
25076
|
+
const current = getState().streamingTail;
|
|
25077
|
+
if (!current || current.id !== id || !Object.is(current.text, streamingVisibleText)) {
|
|
25078
|
+
patch.streamingTail = { kind: "assistant", id, text: streamingVisibleText, streaming: true };
|
|
24995
25079
|
}
|
|
24996
25080
|
}
|
|
24997
25081
|
const responseLengthVal = assistantText.length + thinkingText.length;
|
|
24998
|
-
const visibleLineChanged = patch.
|
|
25082
|
+
const visibleLineChanged = patch.streamingTail !== void 0;
|
|
24999
25083
|
const thinkingTransition = _publishedThinkingActive === true;
|
|
25000
25084
|
if (getState().spinner && (visibleLineChanged || thinkingTransition || _pendingThinkingLastEndedAt)) {
|
|
25001
25085
|
patch.spinner = { ...getState().spinner, responseLength: responseLengthVal, thinking: false, thinkingLastEndedAt: _pendingThinkingLastEndedAt || getState().spinner.thinkingLastEndedAt, mode: compactingActive ? "compacting" : "responding" };
|
|
@@ -25054,7 +25138,8 @@ function createRunTurn(bag) {
|
|
|
25054
25138
|
const succeeded = Math.max(0, completedCount - errors - exitErrors);
|
|
25055
25139
|
const rawResult = aggregateRawResult(allCalls);
|
|
25056
25140
|
const displayDetail = errors > 0 || exitErrors > 0 ? failureDetailText({ succeeded, realErrors: callErrors, exitErrors, exitCode: allCalls.find((r) => r.isExitError)?.exitCode }) : formatAggregateDetail(aggregateSummaries(aggregate));
|
|
25057
|
-
const
|
|
25141
|
+
const currentIndex = itemIndexById.get(card.itemId);
|
|
25142
|
+
const currentItem = Number.isInteger(currentIndex) && getState().items[currentIndex]?.id === card.itemId ? getState().items[currentIndex] : null;
|
|
25058
25143
|
const visualCompleted = Math.max(
|
|
25059
25144
|
completedCount,
|
|
25060
25145
|
Math.min(allCalls.length, Number(currentItem?.completedCount || 0))
|
|
@@ -25087,6 +25172,9 @@ function createRunTurn(bag) {
|
|
|
25087
25172
|
try {
|
|
25088
25173
|
const { result, session } = await runtime.ask(userText, {
|
|
25089
25174
|
drainSteering: (_sessionId, drainOptions) => isCurrentTurn() ? drainPendingSteering(drainOptions) : [],
|
|
25175
|
+
onStreamDelta: () => {
|
|
25176
|
+
markTurnProgress("stream-delta");
|
|
25177
|
+
},
|
|
25090
25178
|
onSteerMessage: (text) => {
|
|
25091
25179
|
if (!markTurnProgress("steer-message")) return;
|
|
25092
25180
|
if (text === STEERING_SUPPRESSED_DISPLAY) return;
|
|
@@ -25327,10 +25415,10 @@ function createRunTurn(bag) {
|
|
|
25327
25415
|
if (finalRemainder.trim()) {
|
|
25328
25416
|
const id = currentAssistantId || ensureAssistant(finalRemainder);
|
|
25329
25417
|
currentAssistantText = finalRemainder;
|
|
25330
|
-
|
|
25418
|
+
settleStreamingTail(id, { text: finalRemainder });
|
|
25331
25419
|
} else if (currentAssistantId && (currentAssistantText.trim() || assistantText.trim())) {
|
|
25332
25420
|
const streamedText = currentAssistantText || assistantText;
|
|
25333
|
-
|
|
25421
|
+
settleStreamingTail(currentAssistantId, { text: streamedText });
|
|
25334
25422
|
}
|
|
25335
25423
|
turnFinishedNormally = true;
|
|
25336
25424
|
}
|
|
@@ -25343,7 +25431,7 @@ function createRunTurn(bag) {
|
|
|
25343
25431
|
if (error?.name === "SessionClosedError") {
|
|
25344
25432
|
cancelled = true;
|
|
25345
25433
|
if (assistantText.trim() && currentAssistantId) {
|
|
25346
|
-
|
|
25434
|
+
settleStreamingTail(currentAssistantId, { text: currentAssistantText || assistantText });
|
|
25347
25435
|
}
|
|
25348
25436
|
flushToolResults([], toolCards, cardByCallId, toolGroups, resultsDone, { finalize: true, cancelled: true });
|
|
25349
25437
|
finalizeToolHeaders();
|
|
@@ -25369,6 +25457,13 @@ function createRunTurn(bag) {
|
|
|
25369
25457
|
if (isStaleUnwind) {
|
|
25370
25458
|
tuiDebug2(`runTurn STALE UNWIND turn=${turnIndex} \u2014 force-released; skipping shared UI/state writes`);
|
|
25371
25459
|
} else {
|
|
25460
|
+
if (currentAssistantId && getState().streamingTail?.id === currentAssistantId) {
|
|
25461
|
+
if (currentAssistantText.trim()) {
|
|
25462
|
+
settleStreamingTail(currentAssistantId, { text: currentAssistantText });
|
|
25463
|
+
} else {
|
|
25464
|
+
clearStreamingTail(currentAssistantId);
|
|
25465
|
+
}
|
|
25466
|
+
}
|
|
25372
25467
|
const producedTranscriptItem = getState().items.length + closingItems.length > itemsAtTurnStart;
|
|
25373
25468
|
const reclaimed = cancelled && flags.activePromptRestore?.reclaimed === true;
|
|
25374
25469
|
flags.activePromptRestore = null;
|
|
@@ -26105,6 +26200,8 @@ function createEngineApiA(bag) {
|
|
|
26105
26200
|
pushItem,
|
|
26106
26201
|
patchItem,
|
|
26107
26202
|
replaceItems,
|
|
26203
|
+
settleStreamingTail,
|
|
26204
|
+
clearStreamingTail,
|
|
26108
26205
|
pushNotice,
|
|
26109
26206
|
autoClearState,
|
|
26110
26207
|
agentStatusState,
|
|
@@ -26644,6 +26741,12 @@ function createEngineApiA(bag) {
|
|
|
26644
26741
|
if (flags.disposed) return;
|
|
26645
26742
|
if (!getState().busy) return;
|
|
26646
26743
|
if (flags.leadTurnEpoch !== abortEpoch) return;
|
|
26744
|
+
const streamingTail = getState().streamingTail;
|
|
26745
|
+
if (streamingTail?.text?.trim()) {
|
|
26746
|
+
settleStreamingTail?.(streamingTail.id, {});
|
|
26747
|
+
} else {
|
|
26748
|
+
clearStreamingTail?.();
|
|
26749
|
+
}
|
|
26647
26750
|
flags.leadTurnEpoch = (Number(flags.leadTurnEpoch) || 0) + 1;
|
|
26648
26751
|
set({ busy: false, spinner: null, thinking: null, lastTurn: null });
|
|
26649
26752
|
flags.activePromptRestore = null;
|
|
@@ -26680,6 +26783,79 @@ var tuiDebug = (msg) => {
|
|
|
26680
26783
|
};
|
|
26681
26784
|
var _idSeq = 0;
|
|
26682
26785
|
var nextId = () => `it_${++_idSeq}`;
|
|
26786
|
+
function replaceEngineItemsState({
|
|
26787
|
+
state,
|
|
26788
|
+
items,
|
|
26789
|
+
itemIndexById,
|
|
26790
|
+
preserveStreamingTail = false,
|
|
26791
|
+
extra = {}
|
|
26792
|
+
}) {
|
|
26793
|
+
const nextItems = Array.isArray(items) ? items : [];
|
|
26794
|
+
itemIndexById.clear();
|
|
26795
|
+
for (let i = 0; i < nextItems.length; i++) {
|
|
26796
|
+
const id = nextItems[i]?.id;
|
|
26797
|
+
if (id != null) itemIndexById.set(id, i);
|
|
26798
|
+
}
|
|
26799
|
+
return {
|
|
26800
|
+
...state,
|
|
26801
|
+
...extra,
|
|
26802
|
+
items: nextItems,
|
|
26803
|
+
structureRevision: (Number(state.structureRevision) || 0) + 1,
|
|
26804
|
+
streamingTail: preserveStreamingTail ? state.streamingTail : null
|
|
26805
|
+
};
|
|
26806
|
+
}
|
|
26807
|
+
function createEngineItemMutators({ getState, set, itemIndexById }) {
|
|
26808
|
+
const patchItem = (id, patch) => {
|
|
26809
|
+
const state = getState();
|
|
26810
|
+
let index = itemIndexById.get(id);
|
|
26811
|
+
if (!Number.isInteger(index) || state.items[index]?.id !== id) {
|
|
26812
|
+
index = state.items.findIndex((it) => it.id === id);
|
|
26813
|
+
if (index >= 0) itemIndexById.set(id, index);
|
|
26814
|
+
}
|
|
26815
|
+
if (index < 0) return false;
|
|
26816
|
+
const current = state.items[index];
|
|
26817
|
+
let changed = false;
|
|
26818
|
+
for (const [key, value] of Object.entries(patch || {})) {
|
|
26819
|
+
if (!Object.is(current[key], value)) {
|
|
26820
|
+
changed = true;
|
|
26821
|
+
break;
|
|
26822
|
+
}
|
|
26823
|
+
}
|
|
26824
|
+
if (!changed) return false;
|
|
26825
|
+
const items = state.items.slice();
|
|
26826
|
+
items[index] = { ...current, ...patch };
|
|
26827
|
+
set({ items, structureRevision: (Number(state.structureRevision) || 0) + 1 });
|
|
26828
|
+
return true;
|
|
26829
|
+
};
|
|
26830
|
+
const settleStreamingTail = (id, patch = {}, extra = {}) => {
|
|
26831
|
+
const state = getState();
|
|
26832
|
+
const tail = state.streamingTail?.id === id ? state.streamingTail : null;
|
|
26833
|
+
if (!tail) return false;
|
|
26834
|
+
let existingIndex = itemIndexById.get(id);
|
|
26835
|
+
if (!Number.isInteger(existingIndex) || state.items[existingIndex]?.id !== id) {
|
|
26836
|
+
existingIndex = state.items.findIndex((item2) => item2?.id === id);
|
|
26837
|
+
}
|
|
26838
|
+
if (existingIndex >= 0) return false;
|
|
26839
|
+
const item = {
|
|
26840
|
+
...tail || {},
|
|
26841
|
+
...patch,
|
|
26842
|
+
kind: "assistant",
|
|
26843
|
+
id,
|
|
26844
|
+
streaming: false
|
|
26845
|
+
};
|
|
26846
|
+
const index = state.items.length;
|
|
26847
|
+
const items = [...state.items, item];
|
|
26848
|
+
itemIndexById.set(id, index);
|
|
26849
|
+
set({
|
|
26850
|
+
items,
|
|
26851
|
+
structureRevision: (Number(state.structureRevision) || 0) + 1,
|
|
26852
|
+
streamingTail: null,
|
|
26853
|
+
...extra
|
|
26854
|
+
});
|
|
26855
|
+
return true;
|
|
26856
|
+
};
|
|
26857
|
+
return { patchItem, settleStreamingTail };
|
|
26858
|
+
}
|
|
26683
26859
|
async function createEngineSession({
|
|
26684
26860
|
provider: providerName,
|
|
26685
26861
|
model,
|
|
@@ -26734,6 +26910,8 @@ async function createEngineSession({
|
|
|
26734
26910
|
};
|
|
26735
26911
|
let state = {
|
|
26736
26912
|
items: [],
|
|
26913
|
+
structureRevision: 0,
|
|
26914
|
+
streamingTail: null,
|
|
26737
26915
|
toasts: [],
|
|
26738
26916
|
progressHint: null,
|
|
26739
26917
|
busy: false,
|
|
@@ -26799,20 +26977,20 @@ async function createEngineSession({
|
|
|
26799
26977
|
return true;
|
|
26800
26978
|
};
|
|
26801
26979
|
const itemIndexById = /* @__PURE__ */ new Map();
|
|
26802
|
-
const replaceItems = (items) => {
|
|
26980
|
+
const replaceItems = (items, { preserveStreamingTail = false } = {}) => {
|
|
26803
26981
|
const nextItems = Array.isArray(items) ? items : [];
|
|
26804
|
-
itemIndexById.clear();
|
|
26805
|
-
for (let i = 0; i < nextItems.length; i++) {
|
|
26806
|
-
const id = nextItems[i]?.id;
|
|
26807
|
-
if (id != null) itemIndexById.set(id, i);
|
|
26808
|
-
}
|
|
26809
26982
|
activeToolCalls.clear();
|
|
26810
|
-
state = {
|
|
26811
|
-
|
|
26983
|
+
state = replaceEngineItemsState({
|
|
26984
|
+
state,
|
|
26812
26985
|
items: nextItems,
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
|
|
26986
|
+
itemIndexById,
|
|
26987
|
+
preserveStreamingTail,
|
|
26988
|
+
extra: {
|
|
26989
|
+
promptHistoryList: buildMergedPromptHistory(recomputePromptHistory(nextItems), loadPromptHistory(state.cwd)),
|
|
26990
|
+
activeToolSummary: null
|
|
26991
|
+
}
|
|
26992
|
+
});
|
|
26993
|
+
emit();
|
|
26816
26994
|
return nextItems;
|
|
26817
26995
|
};
|
|
26818
26996
|
const activeToolCalls = /* @__PURE__ */ new Map();
|
|
@@ -26858,11 +27036,37 @@ async function createEngineSession({
|
|
|
26858
27036
|
if (item?.id != null) itemIndexById.set(item.id, index);
|
|
26859
27037
|
if (item?.kind === "user") {
|
|
26860
27038
|
const promptHistoryList = buildMergedPromptHistory(recomputePromptHistory(items), loadPromptHistory(state.cwd));
|
|
26861
|
-
set({ items, promptHistoryList });
|
|
27039
|
+
set({ items, structureRevision: state.structureRevision + 1, promptHistoryList });
|
|
26862
27040
|
} else {
|
|
26863
|
-
set({ items });
|
|
27041
|
+
set({ items, structureRevision: state.structureRevision + 1 });
|
|
27042
|
+
}
|
|
27043
|
+
};
|
|
27044
|
+
const updateStreamingTail = (id, patch = {}, extra = {}) => {
|
|
27045
|
+
if (id == null) return false;
|
|
27046
|
+
const current = state.streamingTail?.id === id ? state.streamingTail : { kind: "assistant", id, text: "", streaming: true };
|
|
27047
|
+
const next = { ...current, ...patch, kind: "assistant", id, streaming: true };
|
|
27048
|
+
let changed = state.streamingTail !== current;
|
|
27049
|
+
if (!changed) {
|
|
27050
|
+
for (const [key, value] of Object.entries(next)) {
|
|
27051
|
+
if (!Object.is(current[key], value)) {
|
|
27052
|
+
changed = true;
|
|
27053
|
+
break;
|
|
27054
|
+
}
|
|
27055
|
+
}
|
|
26864
27056
|
}
|
|
27057
|
+
return set(changed ? { streamingTail: next, ...extra } : extra);
|
|
26865
27058
|
};
|
|
27059
|
+
const clearStreamingTail = (id = null, extra = {}) => {
|
|
27060
|
+
if (!state.streamingTail || id != null && state.streamingTail.id !== id) {
|
|
27061
|
+
return set(extra);
|
|
27062
|
+
}
|
|
27063
|
+
return set({ streamingTail: null, ...extra });
|
|
27064
|
+
};
|
|
27065
|
+
const { patchItem, settleStreamingTail } = createEngineItemMutators({
|
|
27066
|
+
getState: () => state,
|
|
27067
|
+
set,
|
|
27068
|
+
itemIndexById
|
|
27069
|
+
});
|
|
26866
27070
|
const upsertSyntheticToolItem = (text, id = nextId(), parsed = null) => {
|
|
26867
27071
|
const synthetic = parseSyntheticAgentMessage(text);
|
|
26868
27072
|
if (!synthetic) return false;
|
|
@@ -26977,7 +27181,7 @@ async function createEngineSession({
|
|
|
26977
27181
|
if (id == null) return false;
|
|
26978
27182
|
const items = state.items.filter((it) => !(it?.kind === "notice" && it?.id === id));
|
|
26979
27183
|
if (items.length === state.items.length) return false;
|
|
26980
|
-
set({ items: replaceItems(items) });
|
|
27184
|
+
set({ items: replaceItems(items, { preserveStreamingTail: true }) });
|
|
26981
27185
|
return true;
|
|
26982
27186
|
};
|
|
26983
27187
|
const setProgressHint = (text, tone = "info") => {
|
|
@@ -26996,27 +27200,6 @@ async function createEngineSession({
|
|
|
26996
27200
|
getDisposed: () => flags.disposed,
|
|
26997
27201
|
timeoutMs: TOOL_APPROVAL_TIMEOUT_MS
|
|
26998
27202
|
});
|
|
26999
|
-
const patchItem = (id, patch) => {
|
|
27000
|
-
let index = itemIndexById.get(id);
|
|
27001
|
-
if (!Number.isInteger(index) || state.items[index]?.id !== id) {
|
|
27002
|
-
index = state.items.findIndex((it) => it.id === id);
|
|
27003
|
-
if (index >= 0) itemIndexById.set(id, index);
|
|
27004
|
-
}
|
|
27005
|
-
if (index < 0) return false;
|
|
27006
|
-
const current = state.items[index];
|
|
27007
|
-
let changed = false;
|
|
27008
|
-
for (const [key, value] of Object.entries(patch || {})) {
|
|
27009
|
-
if (!Object.is(current[key], value)) {
|
|
27010
|
-
changed = true;
|
|
27011
|
-
break;
|
|
27012
|
-
}
|
|
27013
|
-
}
|
|
27014
|
-
if (!changed) return false;
|
|
27015
|
-
const items = state.items.slice();
|
|
27016
|
-
items[index] = { ...current, ...patch };
|
|
27017
|
-
set({ items });
|
|
27018
|
-
return true;
|
|
27019
|
-
};
|
|
27020
27203
|
const toastTimers = /* @__PURE__ */ new Set();
|
|
27021
27204
|
lifecycle.runtimePulseTimer = setInterval(() => {
|
|
27022
27205
|
if (flags.disposed) return;
|
|
@@ -27042,7 +27225,8 @@ async function createEngineSession({
|
|
|
27042
27225
|
discardExecutionPendingResume,
|
|
27043
27226
|
updateAgentJobCard,
|
|
27044
27227
|
buildAgentJobCardPatch,
|
|
27045
|
-
subscribeRuntimeNotifications
|
|
27228
|
+
subscribeRuntimeNotifications,
|
|
27229
|
+
clearExecutionDedupState
|
|
27046
27230
|
} = createAgentJobFeed({
|
|
27047
27231
|
runtime,
|
|
27048
27232
|
getState: () => state,
|
|
@@ -27058,7 +27242,8 @@ async function createEngineSession({
|
|
|
27058
27242
|
getPending: () => pending,
|
|
27059
27243
|
agentStatusState,
|
|
27060
27244
|
displayedExecutionNotificationKeys,
|
|
27061
|
-
pushNotice
|
|
27245
|
+
pushNotice,
|
|
27246
|
+
itemIndexById
|
|
27062
27247
|
});
|
|
27063
27248
|
lifecycle.unsubscribeRuntimeNotifications = subscribeRuntimeNotifications();
|
|
27064
27249
|
if (typeof runtime.onRemoteStateChange === "function") {
|
|
@@ -27077,7 +27262,8 @@ async function createEngineSession({
|
|
|
27077
27262
|
markToolCallDone,
|
|
27078
27263
|
updateAgentJobCard,
|
|
27079
27264
|
buildAgentJobCardPatch,
|
|
27080
|
-
agentStatusState
|
|
27265
|
+
agentStatusState,
|
|
27266
|
+
itemIndexById
|
|
27081
27267
|
});
|
|
27082
27268
|
Object.assign(bag, {
|
|
27083
27269
|
runtime,
|
|
@@ -27089,6 +27275,7 @@ async function createEngineSession({
|
|
|
27089
27275
|
pending,
|
|
27090
27276
|
pendingNotificationKeys,
|
|
27091
27277
|
displayedExecutionNotificationKeys,
|
|
27278
|
+
clearExecutionDedupState,
|
|
27092
27279
|
listeners,
|
|
27093
27280
|
itemIndexById,
|
|
27094
27281
|
getState: () => state,
|
|
@@ -27096,6 +27283,9 @@ async function createEngineSession({
|
|
|
27096
27283
|
pushItem,
|
|
27097
27284
|
patchItem,
|
|
27098
27285
|
replaceItems,
|
|
27286
|
+
updateStreamingTail,
|
|
27287
|
+
settleStreamingTail,
|
|
27288
|
+
clearStreamingTail,
|
|
27099
27289
|
pushToast,
|
|
27100
27290
|
pushNotice,
|
|
27101
27291
|
removeNotice,
|
|
@@ -27118,6 +27308,7 @@ async function createEngineSession({
|
|
|
27118
27308
|
requestToolApproval,
|
|
27119
27309
|
patchToolCardResult,
|
|
27120
27310
|
flushToolResults,
|
|
27311
|
+
clearExecutionDedupState,
|
|
27121
27312
|
kickExecutionPendingResume,
|
|
27122
27313
|
flushDeferredExecutionPendingResumeKick,
|
|
27123
27314
|
scheduleExecutionPendingResumeKick,
|
|
@@ -27511,7 +27702,7 @@ function paintBootSplash() {
|
|
|
27511
27702
|
const rows = Math.max(1, Number(process.stdout.rows) || 24);
|
|
27512
27703
|
const windowsLikeTerminal = process.platform === "win32" || Boolean(process.env.WT_SESSION);
|
|
27513
27704
|
const frameCols = Math.max(1, cols - (windowsLikeTerminal ? 1 : 0));
|
|
27514
|
-
const center = (s) => `${" ".repeat(Math.max(0, Math.floor((frameCols - displayWidth(s)) / 2)))}${s}`;
|
|
27705
|
+
const center = (s, reserve = 0) => `${" ".repeat(Math.max(0, Math.floor((frameCols - reserve - displayWidth(s)) / 2)))}${s}`;
|
|
27515
27706
|
const logo = [
|
|
27516
27707
|
"\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
27517
27708
|
"\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ",
|
|
@@ -27531,7 +27722,7 @@ function paintBootSplash() {
|
|
|
27531
27722
|
`;
|
|
27532
27723
|
}
|
|
27533
27724
|
out += "\r\n";
|
|
27534
|
-
out += `${subtleFg}${center(`mixdog coding agent \xB7 v${localPackageVersion()} \xB7 ${process.cwd()}
|
|
27725
|
+
out += `${subtleFg}${center(`mixdog coding agent \xB7 v${localPackageVersion()} \xB7 ${process.cwd()}`, 4)}${reset}`;
|
|
27535
27726
|
out += "\x1B[H";
|
|
27536
27727
|
process.stdout.write(out);
|
|
27537
27728
|
return { stop: () => {
|