mixdog 0.9.50 → 0.9.52
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 +5 -3
- package/scripts/abort-recovery-test.mjs +17 -1
- package/scripts/agent-model-liveness-test.mjs +79 -2
- package/scripts/anthropic-admission-retry-integration-test.mjs +119 -0
- package/scripts/anthropic-transport-policy-test.mjs +466 -0
- package/scripts/atomic-lock-tryonce-test.mjs +60 -1
- package/scripts/build-tui.mjs +13 -1
- package/scripts/channel-daemon-smoke.mjs +630 -10
- package/scripts/code-graph-aggregate-cwd-test.mjs +41 -37
- package/scripts/code-graph-disk-hit-test.mjs +11 -0
- package/scripts/code-graph-root-federation-test.mjs +273 -0
- package/scripts/compact-pressure-test.mjs +55 -1
- package/scripts/compact-smoke.mjs +80 -0
- package/scripts/context-mcp-metering-test.mjs +1350 -19
- package/scripts/deferred-tool-loading-test.mjs +17 -0
- package/scripts/gemini-provider-test.mjs +1053 -0
- package/scripts/hook-bus-test.mjs +23 -0
- package/scripts/internal-tools-normalization-test.mjs +10 -0
- package/scripts/interrupted-turn-history-test.mjs +371 -0
- package/scripts/lifecycle-api-test.mjs +76 -0
- package/scripts/max-output-recovery-test.mjs +55 -0
- package/scripts/mcp-grace-deferred-test.mjs +89 -13
- package/scripts/memory-pg-recovery-test.mjs +59 -0
- package/scripts/openai-oauth-ws-1006-retry-test.mjs +391 -4
- package/scripts/process-lifecycle-test.mjs +389 -0
- package/scripts/provider-admission-scheduler-test.mjs +582 -0
- package/scripts/provider-contract-test.mjs +268 -0
- package/scripts/provider-toolcall-test.mjs +520 -3
- package/scripts/reactive-compact-persist-smoke.mjs +59 -0
- package/scripts/resource-admission-test.mjs +789 -0
- package/scripts/session-bench-cache-break-test.mjs +102 -0
- package/scripts/session-bench.mjs +101 -42
- package/scripts/shell-failure-diagnostics-test.mjs +73 -4
- package/scripts/shell-jobs-windows-hide-test.mjs +1 -1
- package/scripts/smoke-loop-failure-summary-test.mjs +38 -0
- package/scripts/smoke-loop-failure-summary.mjs +16 -0
- package/scripts/smoke-loop.mjs +2 -7
- package/scripts/steering-drain-buckets-test.mjs +18 -0
- package/scripts/tool-failures.mjs +15 -1
- package/scripts/toolcall-args-test.mjs +14 -6
- package/scripts/tui-transcript-perf-test.mjs +43 -7
- package/scripts/web-fetch-routing-test.mjs +158 -0
- package/src/cli.mjs +15 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +26 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +4 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +12 -0
- package/src/runtime/agent/orchestrator/internal-tools.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +331 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +118 -26
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +29 -17
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +136 -38
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +24 -4
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +554 -42
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +67 -18
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +95 -46
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +12 -4
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +54 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +10 -80
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +89 -17
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +93 -26
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +144 -51
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +22 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +74 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +111 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +13 -17
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +78 -12
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +44 -5
- package/src/runtime/agent/orchestrator/providers/registry.mjs +49 -8
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +224 -104
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +127 -55
- package/src/runtime/agent/orchestrator/session/compact/engine.mjs +99 -32
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +17 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +69 -37
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/manager/message-sanitize.mjs +8 -28
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +6 -7
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +42 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +220 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -4
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +17 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +89 -22
- package/src/runtime/agent/orchestrator/stall-policy.mjs +2 -12
- package/src/runtime/agent/orchestrator/tools/bash-session.mjs +42 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +74 -37
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +223 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +380 -37
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +176 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +14 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +108 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +93 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +124 -14
- package/src/runtime/memory/index.mjs +22 -4
- package/src/runtime/memory/lib/pg/adapter.mjs +84 -10
- package/src/runtime/memory/lib/pg/process.mjs +91 -47
- package/src/runtime/memory/lib/pg/supervisor.mjs +50 -13
- package/src/runtime/search/index.mjs +41 -0
- package/src/runtime/search/lib/http-fetch.mjs +154 -0
- package/src/runtime/search/tool-defs.mjs +23 -0
- package/src/runtime/shared/atomic-file.mjs +28 -150
- package/src/runtime/shared/process-lifecycle.mjs +363 -0
- package/src/runtime/shared/process-shutdown.mjs +27 -4
- package/src/runtime/shared/resource-admission.mjs +359 -0
- package/src/runtime/shared/staged-child-result.mjs +19 -0
- package/src/session-runtime/context-status.mjs +38 -27
- package/src/session-runtime/lifecycle-api.mjs +26 -6
- package/src/session-runtime/provider-request-tools.mjs +72 -0
- package/src/session-runtime/runtime-core.mjs +43 -18
- package/src/session-runtime/session-turn-api.mjs +5 -4
- package/src/session-runtime/tool-catalog.mjs +375 -15
- package/src/standalone/agent-tool.mjs +17 -38
- package/src/standalone/channel-daemon-client.mjs +200 -38
- package/src/standalone/channel-daemon-transport.mjs +136 -9
- package/src/standalone/channel-worker.mjs +79 -12
- package/src/standalone/hook-bus/handlers.mjs +4 -0
- package/src/standalone/hook-bus/rules.mjs +7 -1
- package/src/standalone/hook-bus.mjs +10 -2
- package/src/tui/App.jsx +17 -11
- package/src/tui/app/live-spinner-visibility.mjs +20 -0
- package/src/tui/dist/index.mjs +101 -281
- package/src/tui/engine/session-api-ext.mjs +13 -2
- package/src/tui/engine/session-api.mjs +1 -1
- package/src/tui/engine/turn.mjs +10 -6
- package/src/tui/engine.mjs +13 -4
- package/src/tui/index.jsx +4 -1
- package/src/tui/lib/voice-setup.mjs +16 -0
package/src/tui/dist/index.mjs
CHANGED
|
@@ -8083,6 +8083,23 @@ function slashArgumentHint(value) {
|
|
|
8083
8083
|
return command?.params ? `${command.usage} ${command.params}` : "";
|
|
8084
8084
|
}
|
|
8085
8085
|
|
|
8086
|
+
// src/tui/app/live-spinner-visibility.mjs
|
|
8087
|
+
function isCompletedTranscriptTail(latestTranscriptItem) {
|
|
8088
|
+
return latestTranscriptItem?.kind === "turndone" || latestTranscriptItem?.kind === "statusdone";
|
|
8089
|
+
}
|
|
8090
|
+
function isCompletedTranscriptTailAppendedThisCommit(latestTranscriptItem, previousTailId) {
|
|
8091
|
+
return isCompletedTranscriptTail(latestTranscriptItem) && (latestTranscriptItem?.id ?? null) !== previousTailId;
|
|
8092
|
+
}
|
|
8093
|
+
function isLiveSpinnerMetaVisible({
|
|
8094
|
+
inputBoxHidden,
|
|
8095
|
+
slashPaletteOpen,
|
|
8096
|
+
liveSpinner,
|
|
8097
|
+
liveSpinnerIsCommand,
|
|
8098
|
+
latestTranscriptItem
|
|
8099
|
+
}) {
|
|
8100
|
+
return !inputBoxHidden && !slashPaletteOpen && !!liveSpinner && (liveSpinnerIsCommand || latestTranscriptItem?.kind !== "turndone");
|
|
8101
|
+
}
|
|
8102
|
+
|
|
8086
8103
|
// src/tui/app/input-parsers.mjs
|
|
8087
8104
|
function parseHookRuleInput(text) {
|
|
8088
8105
|
const parts = String(text || "").split("|").map((part) => part.trim());
|
|
@@ -14531,26 +14548,6 @@ function withFileLockSync(lockPath, fn, opts = {}) {
|
|
|
14531
14548
|
timeoutErr.cause = lastErr;
|
|
14532
14549
|
throw timeoutErr;
|
|
14533
14550
|
}
|
|
14534
|
-
function _readLockOwnerPid(lockPath) {
|
|
14535
|
-
try {
|
|
14536
|
-
const raw = readFileSync3(lockPath, "utf8");
|
|
14537
|
-
const tok = String(raw).trim().split(/\s+/)[0];
|
|
14538
|
-
const pid = Number.parseInt(tok, 10);
|
|
14539
|
-
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
14540
|
-
} catch {
|
|
14541
|
-
return null;
|
|
14542
|
-
}
|
|
14543
|
-
}
|
|
14544
|
-
function _pidIsDead(pid) {
|
|
14545
|
-
if (pid === null) return false;
|
|
14546
|
-
if (pid === process.pid) return false;
|
|
14547
|
-
try {
|
|
14548
|
-
process.kill(pid, 0);
|
|
14549
|
-
return false;
|
|
14550
|
-
} catch (err) {
|
|
14551
|
-
return err?.code === "ESRCH";
|
|
14552
|
-
}
|
|
14553
|
-
}
|
|
14554
14551
|
function _readLockOwner(lockPath) {
|
|
14555
14552
|
try {
|
|
14556
14553
|
const raw = readFileSync3(lockPath, "utf8");
|
|
@@ -14574,27 +14571,20 @@ function _ownerIsLive(owner) {
|
|
|
14574
14571
|
return err?.code !== "ESRCH";
|
|
14575
14572
|
}
|
|
14576
14573
|
}
|
|
14577
|
-
function _ownerIsSelfForeign(owner) {
|
|
14578
|
-
return owner.pid === process.pid && owner.token !== null && owner.token !== _OWNER_TOKEN;
|
|
14579
|
-
}
|
|
14580
14574
|
function _lockOwnedBySelf(lockPath) {
|
|
14581
14575
|
const owner = _readLockOwner(lockPath);
|
|
14582
14576
|
if (owner.pid !== process.pid) return false;
|
|
14583
14577
|
return owner.token === null ? true : owner.token === _OWNER_TOKEN;
|
|
14584
14578
|
}
|
|
14585
14579
|
function _tryReclaimStaleLock(lockPath, staleMs) {
|
|
14586
|
-
let st;
|
|
14587
14580
|
try {
|
|
14588
|
-
|
|
14581
|
+
statSync2(lockPath);
|
|
14589
14582
|
} catch {
|
|
14590
14583
|
return false;
|
|
14591
14584
|
}
|
|
14592
14585
|
const owner = _readLockOwner(lockPath);
|
|
14593
|
-
const stale = Date.now() - st.mtimeMs > staleMs;
|
|
14594
14586
|
const dead = owner.pid !== null && !_ownerIsLive(owner);
|
|
14595
|
-
|
|
14596
|
-
const selfForeign = _ownerIsSelfForeign(owner);
|
|
14597
|
-
if (!dead && !((pidless || selfForeign) && stale)) return false;
|
|
14587
|
+
if (!dead) return false;
|
|
14598
14588
|
const reclaim = _tryAcquireReclaimGuard(lockPath, staleMs);
|
|
14599
14589
|
if (reclaim === null) return false;
|
|
14600
14590
|
try {
|
|
@@ -14606,11 +14596,8 @@ function _tryReclaimStaleLock(lockPath, staleMs) {
|
|
|
14606
14596
|
}
|
|
14607
14597
|
const curOwner = _readLockOwner(lockPath);
|
|
14608
14598
|
if (curOwner.pid !== owner.pid || curOwner.token !== owner.token) return false;
|
|
14609
|
-
const curStale = Date.now() - cur.mtimeMs > staleMs;
|
|
14610
14599
|
const curDead = curOwner.pid !== null && !_ownerIsLive(curOwner);
|
|
14611
|
-
|
|
14612
|
-
const curSelfForeign = _ownerIsSelfForeign(curOwner);
|
|
14613
|
-
if (curDead || (curPidless || curSelfForeign) && curStale) {
|
|
14600
|
+
if (curDead) {
|
|
14614
14601
|
try {
|
|
14615
14602
|
unlinkSync2(lockPath);
|
|
14616
14603
|
return true;
|
|
@@ -14623,83 +14610,22 @@ function _tryReclaimStaleLock(lockPath, staleMs) {
|
|
|
14623
14610
|
_releaseReclaimGuard(reclaim);
|
|
14624
14611
|
}
|
|
14625
14612
|
}
|
|
14626
|
-
function _reclaimGuardIsUnreadableAndStale(guardPath, staleMs) {
|
|
14627
|
-
if (_readLockOwnerPid(guardPath) !== null) return false;
|
|
14628
|
-
try {
|
|
14629
|
-
const st = statSync2(guardPath);
|
|
14630
|
-
return Date.now() - st.mtimeMs > staleMs;
|
|
14631
|
-
} catch {
|
|
14632
|
-
return false;
|
|
14633
|
-
}
|
|
14634
|
-
}
|
|
14635
|
-
function _reclaimGuardMatchesToken(guardPath, token) {
|
|
14636
|
-
try {
|
|
14637
|
-
return readFileSync3(guardPath, "utf8") === token;
|
|
14638
|
-
} catch {
|
|
14639
|
-
return false;
|
|
14640
|
-
}
|
|
14641
|
-
}
|
|
14642
|
-
function _readGuardContent(guardPath) {
|
|
14643
|
-
try {
|
|
14644
|
-
return readFileSync3(guardPath, "utf8");
|
|
14645
|
-
} catch {
|
|
14646
|
-
return null;
|
|
14647
|
-
}
|
|
14648
|
-
}
|
|
14649
|
-
function _parseStampPid(raw) {
|
|
14650
|
-
if (raw === null) return null;
|
|
14651
|
-
const tok = String(raw).trim().split(/\s+/)[0];
|
|
14652
|
-
const pid = Number.parseInt(tok, 10);
|
|
14653
|
-
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
14654
|
-
}
|
|
14655
|
-
function _unlinkReclaimGuardIfContentMatches(guardPath, content) {
|
|
14656
|
-
if (_readGuardContent(guardPath) !== content) return false;
|
|
14657
|
-
try {
|
|
14658
|
-
unlinkSync2(guardPath);
|
|
14659
|
-
return true;
|
|
14660
|
-
} catch {
|
|
14661
|
-
return false;
|
|
14662
|
-
}
|
|
14663
|
-
}
|
|
14664
|
-
function _unlinkUnreadableStaleReclaimGuard(guardPath, staleMs) {
|
|
14665
|
-
if (!_reclaimGuardIsUnreadableAndStale(guardPath, staleMs)) return false;
|
|
14666
|
-
try {
|
|
14667
|
-
unlinkSync2(guardPath);
|
|
14668
|
-
return true;
|
|
14669
|
-
} catch {
|
|
14670
|
-
return false;
|
|
14671
|
-
}
|
|
14672
|
-
}
|
|
14673
|
-
function _tryClearStaleReclaimGuard(guardPath, staleMs) {
|
|
14674
|
-
const guardContent = _readGuardContent(guardPath);
|
|
14675
|
-
const guardPid = _parseStampPid(guardContent);
|
|
14676
|
-
if (guardPid !== null) {
|
|
14677
|
-
let guardStale = false;
|
|
14678
|
-
try {
|
|
14679
|
-
guardStale = Date.now() - statSync2(guardPath).mtimeMs > staleMs;
|
|
14680
|
-
} catch {
|
|
14681
|
-
}
|
|
14682
|
-
if (_pidIsDead(guardPid) || guardStale) {
|
|
14683
|
-
_unlinkReclaimGuardIfContentMatches(guardPath, guardContent);
|
|
14684
|
-
}
|
|
14685
|
-
return;
|
|
14686
|
-
}
|
|
14687
|
-
_unlinkUnreadableStaleReclaimGuard(guardPath, staleMs);
|
|
14688
|
-
}
|
|
14689
14613
|
function _tryAcquireReclaimGuard(lockPath, staleMs) {
|
|
14690
14614
|
const guardPath = `${lockPath}.reclaim`;
|
|
14691
|
-
|
|
14692
|
-
const fd = openSync(guardPath, "wx", 384);
|
|
14693
|
-
const token = `${process.pid} ${Date.now()} ${randomBytes2(8).toString("hex")}
|
|
14615
|
+
const token = `${process.pid} ${Date.now()} ${randomBytes2(8).toString("hex")}
|
|
14694
14616
|
`;
|
|
14617
|
+
const stagedPath = `${guardPath}.${process.pid}.${randomBytes2(8).toString("hex")}.tmp`;
|
|
14618
|
+
try {
|
|
14619
|
+
writeFileSync3(stagedPath, token, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
14620
|
+
linkSync(stagedPath, guardPath);
|
|
14621
|
+
unlinkSync2(stagedPath);
|
|
14622
|
+
return { guardPath };
|
|
14623
|
+
} catch (err) {
|
|
14695
14624
|
try {
|
|
14696
|
-
|
|
14625
|
+
unlinkSync2(stagedPath);
|
|
14697
14626
|
} catch {
|
|
14698
14627
|
}
|
|
14699
|
-
return { fd, guardPath, token };
|
|
14700
|
-
} catch (err) {
|
|
14701
14628
|
if (LOCK_WAIT_CODES.has(err?.code)) {
|
|
14702
|
-
_tryClearStaleReclaimGuard(guardPath, staleMs);
|
|
14703
14629
|
return null;
|
|
14704
14630
|
}
|
|
14705
14631
|
throw err;
|
|
@@ -14707,15 +14633,9 @@ function _tryAcquireReclaimGuard(lockPath, staleMs) {
|
|
|
14707
14633
|
}
|
|
14708
14634
|
function _releaseReclaimGuard(reclaim) {
|
|
14709
14635
|
try {
|
|
14710
|
-
|
|
14636
|
+
unlinkSync2(reclaim.guardPath);
|
|
14711
14637
|
} catch {
|
|
14712
14638
|
}
|
|
14713
|
-
if (_reclaimGuardMatchesToken(reclaim.guardPath, reclaim.token)) {
|
|
14714
|
-
try {
|
|
14715
|
-
unlinkSync2(reclaim.guardPath);
|
|
14716
|
-
} catch {
|
|
14717
|
-
}
|
|
14718
|
-
}
|
|
14719
14639
|
}
|
|
14720
14640
|
function _asyncSleep(ms) {
|
|
14721
14641
|
return new Promise((resolve5) => {
|
|
@@ -15357,6 +15277,20 @@ function isVoiceEnabled() {
|
|
|
15357
15277
|
return false;
|
|
15358
15278
|
}
|
|
15359
15279
|
}
|
|
15280
|
+
async function getVoiceStatus({ dataDir = resolvePluginData() } = {}) {
|
|
15281
|
+
const fetcher = await loadVoiceRuntimeFetcher();
|
|
15282
|
+
const runtime = fetcher.resolveVoiceRuntime(dataDir);
|
|
15283
|
+
return {
|
|
15284
|
+
enabled: isVoiceEnabled(),
|
|
15285
|
+
busy: isVoiceInstallBusy(),
|
|
15286
|
+
installed: runtime.installed === true,
|
|
15287
|
+
components: {
|
|
15288
|
+
whisper: Boolean(runtime.binary && runtime.serverCmd),
|
|
15289
|
+
model: Boolean(runtime.model),
|
|
15290
|
+
ffmpeg: Boolean(runtime.ffmpeg)
|
|
15291
|
+
}
|
|
15292
|
+
};
|
|
15293
|
+
}
|
|
15360
15294
|
var PROGRESS_BAR_CELLS = 6;
|
|
15361
15295
|
function renderProgressBarText(phase, downloaded, total) {
|
|
15362
15296
|
const label = phaseLabel(phase);
|
|
@@ -21453,7 +21387,6 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
21453
21387
|
const inputHint = promptHint || toastHint || (progressHint?.text || "");
|
|
21454
21388
|
const inputHintTone = promptHint ? promptHintTone : latestToast?.tone || progressHint?.tone || "info";
|
|
21455
21389
|
const latestTranscriptItem = state.items[state.items.length - 1] || null;
|
|
21456
|
-
const latestDoneAtTail = latestTranscriptItem?.kind === "turndone" || latestTranscriptItem?.kind === "statusdone";
|
|
21457
21390
|
const latestDoneItem = null;
|
|
21458
21391
|
const SCROLL_HINT_ROWS = 0;
|
|
21459
21392
|
const LIVE_STATUS_ROWS = 0;
|
|
@@ -21473,7 +21406,13 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
21473
21406
|
const TEXT_ENTRY_ROWS = PANEL_CHROME_ROWS + textEntryContentRows + textEntryDetailRows;
|
|
21474
21407
|
const OPTION_PANEL_EXTRA_ROWS = expandedOptionPanel ? 3 : 0;
|
|
21475
21408
|
const queuedVisible = !hasFloatingPanel && !inputBoxHidden && state.queued?.length > 0;
|
|
21476
|
-
const promptMetaVisible =
|
|
21409
|
+
const promptMetaVisible = isLiveSpinnerMetaVisible({
|
|
21410
|
+
inputBoxHidden,
|
|
21411
|
+
slashPaletteOpen,
|
|
21412
|
+
liveSpinner,
|
|
21413
|
+
liveSpinnerIsCommand,
|
|
21414
|
+
latestTranscriptItem
|
|
21415
|
+
});
|
|
21477
21416
|
const promptMetaRows = promptMetaVisible ? 2 : 0;
|
|
21478
21417
|
const overlayHintRequested = !inputBoxHidden && !hasFloatingPanel && !liveSpinner && !!inputHint && !queuedVisible;
|
|
21479
21418
|
const overlayHintRows = 0;
|
|
@@ -21516,7 +21455,10 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
21516
21455
|
const promptRowsOnlyChange = panelShrinkRows > 0 && panelKindSignature(panelTransition.signature) === panelKindSignature(panelLayoutSignature);
|
|
21517
21456
|
const prevMetaRows = Number(String(panelTransition.signature).split("|")[PANEL_LAYOUT_SIG.PROMPT_META]) || 0;
|
|
21518
21457
|
const nextMetaRows = Number(String(panelLayoutSignature).split("|")[PANEL_LAYOUT_SIG.PROMPT_META]) || 0;
|
|
21519
|
-
const doneTailAppendedThisCommit =
|
|
21458
|
+
const doneTailAppendedThisCommit = isCompletedTranscriptTailAppendedThisCommit(
|
|
21459
|
+
latestTranscriptItem,
|
|
21460
|
+
panelTransition.tailId
|
|
21461
|
+
);
|
|
21520
21462
|
const spinnerMetaCollapseRows = doneTailAppendedThisCommit ? Math.max(0, prevMetaRows - nextMetaRows) : 0;
|
|
21521
21463
|
const prevQueuedSigRows = Number(String(panelTransition.signature).split("|")[PANEL_LAYOUT_SIG.QUEUED]) || 0;
|
|
21522
21464
|
const nextQueuedSigRows = Number(String(panelLayoutSignature).split("|")[PANEL_LAYOUT_SIG.QUEUED]) || 0;
|
|
@@ -22626,7 +22568,7 @@ function parseBackgroundTaskEnvelope(text) {
|
|
|
22626
22568
|
const name = surface === "explore" || surface === "search" || surface === "shell" || surface === "agent" ? surface : "task";
|
|
22627
22569
|
const status = String(fields.status || "").toLowerCase();
|
|
22628
22570
|
const taskId = fields.task_id || fields.taskid || "";
|
|
22629
|
-
const
|
|
22571
|
+
const errorText = fields.error || "";
|
|
22630
22572
|
const agentResult = parseAgentResultEnvelope(body, {
|
|
22631
22573
|
status,
|
|
22632
22574
|
taskId,
|
|
@@ -22639,7 +22581,7 @@ function parseBackgroundTaskEnvelope(text) {
|
|
|
22639
22581
|
fast: fields.fast
|
|
22640
22582
|
});
|
|
22641
22583
|
if (agentResult) return { ...agentResult, rawResult: value };
|
|
22642
|
-
const errorOnlyBody = isBackgroundErrorOnlyBody(body,
|
|
22584
|
+
const errorOnlyBody = isBackgroundErrorOnlyBody(body, errorText);
|
|
22643
22585
|
const resultBody = body && !errorOnlyBody ? body : "";
|
|
22644
22586
|
return {
|
|
22645
22587
|
name,
|
|
@@ -22658,13 +22600,13 @@ function parseBackgroundTaskEnvelope(text) {
|
|
|
22658
22600
|
preset: fields.preset || void 0,
|
|
22659
22601
|
effort: fields.effort || void 0,
|
|
22660
22602
|
fast: fields.fast || void 0,
|
|
22661
|
-
error:
|
|
22603
|
+
error: errorText || void 0,
|
|
22662
22604
|
startedAt: fields.started || fields.startedat || void 0,
|
|
22663
22605
|
finishedAt: fields.finished || fields.finishedat || void 0
|
|
22664
22606
|
},
|
|
22665
|
-
result: resultBody || (!
|
|
22607
|
+
result: resultBody || (!errorText ? [status ? `status: ${status}` : "", taskId ? `task_id: ${taskId}` : ""].filter(Boolean).join(" \xB7 ") : ""),
|
|
22666
22608
|
rawResult: value,
|
|
22667
|
-
isError: /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(status) || /^error:/i.test(body) || Boolean(
|
|
22609
|
+
isError: /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(status) || /^error:/i.test(body) || Boolean(errorText)
|
|
22668
22610
|
};
|
|
22669
22611
|
}
|
|
22670
22612
|
function isStatusOnlyAgentCompletionNotification(text) {
|
|
@@ -24906,7 +24848,7 @@ function createRunTurn(bag) {
|
|
|
24906
24848
|
tuiDebug2(`runTurn WATCHDOG TRIP turn=${turnIndex} elapsedMs=${elapsed} idleMs=${idleMs} lastProgress=${lastProgressLabel} \u2014 aborting stuck turn`);
|
|
24907
24849
|
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 });
|
|
24908
24850
|
try {
|
|
24909
|
-
runtime.abort("
|
|
24851
|
+
runtime.abort("watchdog");
|
|
24910
24852
|
} catch {
|
|
24911
24853
|
}
|
|
24912
24854
|
watchdogGraceTimer = setTimeout(() => {
|
|
@@ -24951,6 +24893,7 @@ function createRunTurn(bag) {
|
|
|
24951
24893
|
let thinkingSegmentStartedAt = 0;
|
|
24952
24894
|
let accumulatedThinkingMs = 0;
|
|
24953
24895
|
let cancelled = false;
|
|
24896
|
+
let failed = false;
|
|
24954
24897
|
let askResult = null;
|
|
24955
24898
|
let turnFinishedNormally = false;
|
|
24956
24899
|
let transcriptCompactedThisTurn = false;
|
|
@@ -25675,12 +25618,14 @@ function createRunTurn(bag) {
|
|
|
25675
25618
|
flushStreamBatch();
|
|
25676
25619
|
if (error?.name === "SessionClosedError") {
|
|
25677
25620
|
cancelled = true;
|
|
25678
|
-
if (assistantText.trim()
|
|
25679
|
-
|
|
25621
|
+
if (assistantText.trim()) {
|
|
25622
|
+
const id = currentAssistantId || ensureAssistant(assistantText);
|
|
25623
|
+
settleStreamingTail(id, { text: currentAssistantText || assistantText });
|
|
25680
25624
|
}
|
|
25681
25625
|
flushToolResults([], toolCards, cardByCallId, toolGroups, resultsDone, { finalize: true, cancelled: true });
|
|
25682
25626
|
finalizeToolHeaders();
|
|
25683
25627
|
} else {
|
|
25628
|
+
failed = true;
|
|
25684
25629
|
finalizeToolHeaders();
|
|
25685
25630
|
pushNotice(toolErrorDisplay(error, "turn"), "error");
|
|
25686
25631
|
}
|
|
@@ -25717,7 +25662,7 @@ function createRunTurn(bag) {
|
|
|
25717
25662
|
const finalAssistantLen = Math.max(assistantText.length, currentAssistantText.length);
|
|
25718
25663
|
const finalResponseLength = finalAssistantLen + thinkingText.length;
|
|
25719
25664
|
const finalOutputTokens = Math.max(0, Number(getState().spinner?.outputTokens || 0), Math.round(finalResponseLength / 4));
|
|
25720
|
-
const turnStatus = cancelled ? "cancelled" : "done";
|
|
25665
|
+
const turnStatus = cancelled ? "cancelled" : failed ? "failed" : "done";
|
|
25721
25666
|
const resultContent = askResult?.content != null ? String(askResult.content).trim() : "";
|
|
25722
25667
|
const assistantOutput = (currentAssistantText || assistantText || "").trim();
|
|
25723
25668
|
const isNoOpTurn = turnFinishedNormally && !cancelled && toolCards.length === 0 && !resultContent && !assistantOutput && !producedTranscriptItem;
|
|
@@ -25742,8 +25687,9 @@ function createRunTurn(bag) {
|
|
|
25742
25687
|
}
|
|
25743
25688
|
if (flags.leadTurnEpoch === turnEpoch) clearActiveToolSummary();
|
|
25744
25689
|
_publishedThinkingActive = false;
|
|
25745
|
-
|
|
25746
|
-
|
|
25690
|
+
const finalStatus = cancelled ? "cancelled" : failed ? "failed" : "done";
|
|
25691
|
+
tuiDebug2(`runTurn end turn=${turnIndex} status=${finalStatus} elapsedMs=${Date.now() - startedAt}${watchdogTripped ? " watchdogTripped=1" : ""} pending=${pending.length}`);
|
|
25692
|
+
return finalStatus;
|
|
25747
25693
|
}
|
|
25748
25694
|
return runTurn;
|
|
25749
25695
|
}
|
|
@@ -25878,6 +25824,14 @@ function createEngineApiB(bag) {
|
|
|
25878
25824
|
return next;
|
|
25879
25825
|
},
|
|
25880
25826
|
isRemoteEnabled: () => runtime.isRemoteEnabled?.() === true,
|
|
25827
|
+
getVoiceStatus: () => getVoiceStatus(),
|
|
25828
|
+
toggleVoice: async () => {
|
|
25829
|
+
const result = await toggleVoice({ pushNotice, setProgressHint });
|
|
25830
|
+
return {
|
|
25831
|
+
...await getVoiceStatus(),
|
|
25832
|
+
result: typeof result === "boolean" ? { ok: true, enabled: result } : result && typeof result === "object" ? result : { ok: false }
|
|
25833
|
+
};
|
|
25834
|
+
},
|
|
25881
25835
|
// Theme is a TUI-local concern (no runtime round-trip). listThemes returns
|
|
25882
25836
|
// picker metadata; getTheme reports the active id; setTheme applies the
|
|
25883
25837
|
// palette in-place + persists ui.theme and bumps a themeEpoch so the React
|
|
@@ -26119,8 +26073,8 @@ function createEngineApiB(bag) {
|
|
|
26119
26073
|
set({ commandBusy: false });
|
|
26120
26074
|
}
|
|
26121
26075
|
},
|
|
26122
|
-
listSessions: () => {
|
|
26123
|
-
return runtime.listSessions();
|
|
26076
|
+
listSessions: (options) => {
|
|
26077
|
+
return runtime.listSessions(options);
|
|
26124
26078
|
},
|
|
26125
26079
|
newSession: async () => {
|
|
26126
26080
|
if (getState().commandBusy) return false;
|
|
@@ -26961,7 +26915,7 @@ function createEngineApiA(bag) {
|
|
|
26961
26915
|
const requeueEntries = restoreState && !restoreState.committed && Array.isArray(restoreState.requeueEntries) ? restoreState.requeueEntries.filter(
|
|
26962
26916
|
(entry) => entry?.abortDiscardOnAbort !== true && entry?.mode !== "pending-resume"
|
|
26963
26917
|
) : [];
|
|
26964
|
-
const aborted = runtime.abort("
|
|
26918
|
+
const aborted = runtime.abort(hasPendingSteering ? "interrupt" : "user-cancel");
|
|
26965
26919
|
if (restoreState) {
|
|
26966
26920
|
if (aborted !== false && Array.isArray(restoreState.discardExecutionPendingResumeKeys)) {
|
|
26967
26921
|
discardExecutionPendingResume?.(restoreState.discardExecutionPendingResumeKeys);
|
|
@@ -27108,7 +27062,9 @@ async function createEngineSession({
|
|
|
27108
27062
|
provider: providerName,
|
|
27109
27063
|
model,
|
|
27110
27064
|
toolMode = "full",
|
|
27111
|
-
remote = false
|
|
27065
|
+
remote = false,
|
|
27066
|
+
cwd,
|
|
27067
|
+
desktopSession
|
|
27112
27068
|
} = {}) {
|
|
27113
27069
|
const startedAt = performance2.now();
|
|
27114
27070
|
bootProfile("engine:create:start", { provider: providerName, model, toolMode, remote });
|
|
@@ -27120,9 +27076,16 @@ async function createEngineSession({
|
|
|
27120
27076
|
const importStartedAt = performance2.now();
|
|
27121
27077
|
const { createMixdogSessionRuntime } = await import(SESSION_RUNTIME_MODULE);
|
|
27122
27078
|
bootProfile("session-runtime:imported", { ms: (performance2.now() - importStartedAt).toFixed(1) });
|
|
27123
|
-
const runtime = await createMixdogSessionRuntime({
|
|
27079
|
+
const runtime = await createMixdogSessionRuntime({
|
|
27080
|
+
provider: providerName,
|
|
27081
|
+
model,
|
|
27082
|
+
toolMode,
|
|
27083
|
+
remote,
|
|
27084
|
+
...cwd ? { cwd } : {},
|
|
27085
|
+
...desktopSession ? { desktopSession } : {}
|
|
27086
|
+
});
|
|
27124
27087
|
bootProfile("engine:create:runtime-ready", { ms: (performance2.now() - startedAt).toFixed(1) });
|
|
27125
|
-
const
|
|
27088
|
+
const runtimeCwd = runtime.cwd || process.cwd();
|
|
27126
27089
|
const stateStartedAt = performance2.now();
|
|
27127
27090
|
const flags = {
|
|
27128
27091
|
disposed: false,
|
|
@@ -27180,14 +27143,14 @@ async function createEngineSession({
|
|
|
27180
27143
|
activeToolSummary: null,
|
|
27181
27144
|
// Seed from the persisted cwd-scoped store so up-arrow history is available
|
|
27182
27145
|
// on a fresh start, before any bulk swap / first submit republishes it.
|
|
27183
|
-
promptHistoryList: buildMergedPromptHistory([], loadPromptHistory(
|
|
27146
|
+
promptHistoryList: buildMergedPromptHistory([], loadPromptHistory(runtimeCwd)),
|
|
27184
27147
|
...baseRouteState(),
|
|
27185
27148
|
displayContextWindow: 0,
|
|
27186
27149
|
compactBoundaryTokens: 0,
|
|
27187
27150
|
autoCompactTokenLimit: 0,
|
|
27188
27151
|
...initialAgentState,
|
|
27189
27152
|
toolMode: runtime.toolMode,
|
|
27190
|
-
cwd,
|
|
27153
|
+
cwd: runtimeCwd,
|
|
27191
27154
|
themeEpoch: 0
|
|
27192
27155
|
};
|
|
27193
27156
|
bootProfile("engine:route-state-ready", { ms: (performance2.now() - stateStartedAt).toFixed(1) });
|
|
@@ -27569,154 +27532,9 @@ async function createEngineSession({
|
|
|
27569
27532
|
return createEngineApi(bag);
|
|
27570
27533
|
}
|
|
27571
27534
|
|
|
27572
|
-
// src/runtime/shared/process-shutdown.mjs
|
|
27573
|
-
var SIGNAL_EXIT_CODES = {
|
|
27574
|
-
SIGINT: 130,
|
|
27575
|
-
SIGTERM: 143,
|
|
27576
|
-
SIGHUP: 129
|
|
27577
|
-
};
|
|
27578
|
-
function errorText(error) {
|
|
27579
|
-
return error?.stack || error?.message || String(error);
|
|
27580
|
-
}
|
|
27581
|
-
function writeStderr(line) {
|
|
27582
|
-
try {
|
|
27583
|
-
process.stderr.write(`${line}
|
|
27584
|
-
`);
|
|
27585
|
-
} catch {
|
|
27586
|
-
}
|
|
27587
|
-
}
|
|
27588
|
-
function signalExitCode(signal, fallback = 1) {
|
|
27589
|
-
return SIGNAL_EXIT_CODES[signal] || fallback;
|
|
27590
|
-
}
|
|
27591
|
-
function waitWithTimeout(promise, timeoutMs, label = "cleanup") {
|
|
27592
|
-
const ms = Math.max(1, Math.floor(Number(timeoutMs) || 1));
|
|
27593
|
-
return new Promise((resolve5, reject) => {
|
|
27594
|
-
let settled = false;
|
|
27595
|
-
const timer2 = setTimeout(() => {
|
|
27596
|
-
if (settled) return;
|
|
27597
|
-
settled = true;
|
|
27598
|
-
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
27599
|
-
}, ms);
|
|
27600
|
-
if (typeof timer2.unref === "function") timer2.unref();
|
|
27601
|
-
Promise.resolve(promise).then((value) => {
|
|
27602
|
-
if (settled) return;
|
|
27603
|
-
settled = true;
|
|
27604
|
-
clearTimeout(timer2);
|
|
27605
|
-
resolve5(value);
|
|
27606
|
-
}).catch((error) => {
|
|
27607
|
-
if (settled) return;
|
|
27608
|
-
settled = true;
|
|
27609
|
-
clearTimeout(timer2);
|
|
27610
|
-
reject(error);
|
|
27611
|
-
});
|
|
27612
|
-
});
|
|
27613
|
-
}
|
|
27614
|
-
function installProcessSignalCleanup({
|
|
27615
|
-
name = "mixdog",
|
|
27616
|
-
signals = ["SIGINT", "SIGTERM", "SIGHUP"],
|
|
27617
|
-
timeoutMs = 6500,
|
|
27618
|
-
exit = true,
|
|
27619
|
-
fatal = true,
|
|
27620
|
-
beforeCleanup,
|
|
27621
|
-
cleanup,
|
|
27622
|
-
afterCleanup,
|
|
27623
|
-
log = writeStderr
|
|
27624
|
-
} = {}) {
|
|
27625
|
-
let installed = true;
|
|
27626
|
-
let running = false;
|
|
27627
|
-
let hardExitTimer = null;
|
|
27628
|
-
const handlers = [];
|
|
27629
|
-
const removeHandlers = () => {
|
|
27630
|
-
for (const [event, handler] of handlers.splice(0)) {
|
|
27631
|
-
try {
|
|
27632
|
-
process.removeListener(event, handler);
|
|
27633
|
-
} catch {
|
|
27634
|
-
}
|
|
27635
|
-
}
|
|
27636
|
-
};
|
|
27637
|
-
const hardExit = (code) => {
|
|
27638
|
-
try {
|
|
27639
|
-
process.exit(code);
|
|
27640
|
-
} catch {
|
|
27641
|
-
}
|
|
27642
|
-
};
|
|
27643
|
-
const run = async (reason = "process-exit", {
|
|
27644
|
-
code = 0,
|
|
27645
|
-
shouldExit = false,
|
|
27646
|
-
error = null
|
|
27647
|
-
} = {}) => {
|
|
27648
|
-
if (running) {
|
|
27649
|
-
if (shouldExit) hardExit(code);
|
|
27650
|
-
return false;
|
|
27651
|
-
}
|
|
27652
|
-
running = true;
|
|
27653
|
-
removeHandlers();
|
|
27654
|
-
if (shouldExit) {
|
|
27655
|
-
hardExitTimer = setTimeout(() => hardExit(code), Math.max(1e3, Number(timeoutMs) + 1e3));
|
|
27656
|
-
if (typeof hardExitTimer.unref === "function") hardExitTimer.unref();
|
|
27657
|
-
}
|
|
27658
|
-
if (error && typeof log === "function") {
|
|
27659
|
-
log(`[${name}] ${reason}: ${errorText(error)}`);
|
|
27660
|
-
}
|
|
27661
|
-
try {
|
|
27662
|
-
beforeCleanup?.(reason, { code, error });
|
|
27663
|
-
} catch {
|
|
27664
|
-
}
|
|
27665
|
-
try {
|
|
27666
|
-
if (typeof cleanup === "function") {
|
|
27667
|
-
await waitWithTimeout(cleanup(reason, { code, error }), timeoutMs, `${name} shutdown`);
|
|
27668
|
-
}
|
|
27669
|
-
} catch (cleanupError) {
|
|
27670
|
-
if (typeof log === "function") log(`[${name}] cleanup failed: ${errorText(cleanupError)}`);
|
|
27671
|
-
}
|
|
27672
|
-
try {
|
|
27673
|
-
afterCleanup?.(reason, { code, error });
|
|
27674
|
-
} catch {
|
|
27675
|
-
}
|
|
27676
|
-
if (hardExitTimer) {
|
|
27677
|
-
clearTimeout(hardExitTimer);
|
|
27678
|
-
hardExitTimer = null;
|
|
27679
|
-
}
|
|
27680
|
-
running = false;
|
|
27681
|
-
if (shouldExit) hardExit(code);
|
|
27682
|
-
return true;
|
|
27683
|
-
};
|
|
27684
|
-
const add = (event, handler) => {
|
|
27685
|
-
try {
|
|
27686
|
-
process.once(event, handler);
|
|
27687
|
-
handlers.push([event, handler]);
|
|
27688
|
-
} catch {
|
|
27689
|
-
}
|
|
27690
|
-
};
|
|
27691
|
-
for (const signal of signals) {
|
|
27692
|
-
if (!signal) continue;
|
|
27693
|
-
add(signal, () => {
|
|
27694
|
-
void run(signal, { code: signalExitCode(signal), shouldExit: exit });
|
|
27695
|
-
});
|
|
27696
|
-
}
|
|
27697
|
-
if (fatal) {
|
|
27698
|
-
add("uncaughtException", (error) => {
|
|
27699
|
-
void run("uncaughtException", { code: 1, shouldExit: exit, error });
|
|
27700
|
-
});
|
|
27701
|
-
add("unhandledRejection", (error) => {
|
|
27702
|
-
void run("unhandledRejection", { code: 1, shouldExit: exit, error });
|
|
27703
|
-
});
|
|
27704
|
-
}
|
|
27705
|
-
return {
|
|
27706
|
-
run,
|
|
27707
|
-
uninstall() {
|
|
27708
|
-
if (!installed) return;
|
|
27709
|
-
installed = false;
|
|
27710
|
-
removeHandlers();
|
|
27711
|
-
if (hardExitTimer) {
|
|
27712
|
-
clearTimeout(hardExitTimer);
|
|
27713
|
-
hardExitTimer = null;
|
|
27714
|
-
}
|
|
27715
|
-
}
|
|
27716
|
-
};
|
|
27717
|
-
}
|
|
27718
|
-
|
|
27719
27535
|
// src/tui/index.jsx
|
|
27536
|
+
import { installProcessSignalCleanup } from "../../runtime/shared/process-shutdown.mjs";
|
|
27537
|
+
import { finishProcessLifecycle } from "../../runtime/shared/process-lifecycle.mjs";
|
|
27720
27538
|
var import_mixdog_debug = __toESM(require_mixdog_debug(), 1);
|
|
27721
27539
|
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
27722
27540
|
var TERMINAL_MODE_RESET = "\x1B[?1006l\x1B[?1005l\x1B[?1015l\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?2004l\x1B[>0s\x1B[?25h";
|
|
@@ -27913,7 +27731,7 @@ function dumpActiveHandles(label) {
|
|
|
27913
27731
|
tuiExitDebug(`${label}:failed`, { error: error?.message || String(error) });
|
|
27914
27732
|
}
|
|
27915
27733
|
}
|
|
27916
|
-
function
|
|
27734
|
+
function waitWithTimeout(promise, ms) {
|
|
27917
27735
|
let timer2 = null;
|
|
27918
27736
|
return Promise.race([
|
|
27919
27737
|
Promise.resolve(promise).then(() => true),
|
|
@@ -28147,7 +27965,8 @@ async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {
|
|
|
28147
27965
|
const disposeStoreOnce = async (reason = "cli-react-exit") => {
|
|
28148
27966
|
if (storeDisposed) return;
|
|
28149
27967
|
storeDisposed = true;
|
|
28150
|
-
await
|
|
27968
|
+
const completed = await waitWithTimeout(store.dispose?.(reason), EXIT_WAIT_TIMEOUT_MS);
|
|
27969
|
+
if (!completed) throw new Error(`mixdog-tui dispose timed out after ${EXIT_WAIT_TIMEOUT_MS}ms`);
|
|
28151
27970
|
};
|
|
28152
27971
|
const signalCleanup = installProcessSignalCleanup({
|
|
28153
27972
|
name: "mixdog-tui",
|
|
@@ -28221,6 +28040,7 @@ async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {
|
|
|
28221
28040
|
await disposeStoreOnce("cli-react-exit");
|
|
28222
28041
|
} catch (error) {
|
|
28223
28042
|
tuiExitDebug("store:dispose:failed", { error: error?.message || String(error) });
|
|
28043
|
+
finishProcessLifecycle("forced-cleanup", 0);
|
|
28224
28044
|
}
|
|
28225
28045
|
restoreTerminal();
|
|
28226
28046
|
dumpActiveHandles("after-restore");
|
|
@@ -6,6 +6,7 @@ import { resetAllStreamingMarkdownStablePrefixes } from '../markdown/streaming-m
|
|
|
6
6
|
import { toolResultText } from './tool-result-text.mjs';
|
|
7
7
|
import { parseSyntheticAgentMessage } from './agent-envelope.mjs';
|
|
8
8
|
import { flushTuiSteeringPersist } from './tui-steering-persist.mjs';
|
|
9
|
+
import { getVoiceStatus, toggleVoice } from '../lib/voice-setup.mjs';
|
|
9
10
|
|
|
10
11
|
export function createEngineApiB(bag) {
|
|
11
12
|
const {
|
|
@@ -118,6 +119,16 @@ export function createEngineApiB(bag) {
|
|
|
118
119
|
return next;
|
|
119
120
|
},
|
|
120
121
|
isRemoteEnabled: () => runtime.isRemoteEnabled?.() === true,
|
|
122
|
+
getVoiceStatus: () => getVoiceStatus(),
|
|
123
|
+
toggleVoice: async () => {
|
|
124
|
+
const result = await toggleVoice({ pushNotice, setProgressHint });
|
|
125
|
+
return {
|
|
126
|
+
...(await getVoiceStatus()),
|
|
127
|
+
result: typeof result === 'boolean'
|
|
128
|
+
? { ok: true, enabled: result }
|
|
129
|
+
: (result && typeof result === 'object' ? result : { ok: false }),
|
|
130
|
+
};
|
|
131
|
+
},
|
|
121
132
|
// Theme is a TUI-local concern (no runtime round-trip). listThemes returns
|
|
122
133
|
// picker metadata; getTheme reports the active id; setTheme applies the
|
|
123
134
|
// palette in-place + persists ui.theme and bumps a themeEpoch so the React
|
|
@@ -362,8 +373,8 @@ export function createEngineApiB(bag) {
|
|
|
362
373
|
set({ commandBusy: false });
|
|
363
374
|
}
|
|
364
375
|
},
|
|
365
|
-
listSessions: () => {
|
|
366
|
-
return runtime.listSessions();
|
|
376
|
+
listSessions: (options) => {
|
|
377
|
+
return runtime.listSessions(options);
|
|
367
378
|
},
|
|
368
379
|
newSession: async () => {
|
|
369
380
|
if (getState().commandBusy) return false;
|
|
@@ -580,7 +580,7 @@ export function createEngineApiA(bag) {
|
|
|
580
580
|
(entry) => entry?.abortDiscardOnAbort !== true && entry?.mode !== 'pending-resume',
|
|
581
581
|
)
|
|
582
582
|
: [];
|
|
583
|
-
const aborted = runtime.abort('
|
|
583
|
+
const aborted = runtime.abort(hasPendingSteering ? 'interrupt' : 'user-cancel');
|
|
584
584
|
if (restoreState) {
|
|
585
585
|
if (aborted !== false && Array.isArray(restoreState.discardExecutionPendingResumeKeys)) {
|
|
586
586
|
discardExecutionPendingResume?.(restoreState.discardExecutionPendingResumeKeys);
|