mixdog 0.9.22 → 0.9.24
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/README.md +1 -4
- package/package.json +1 -1
- package/scripts/boot-smoke.mjs +1 -1
- package/scripts/channel-daemon-smoke.mjs +483 -0
- package/scripts/channel-daemon-stub.mjs +80 -0
- package/scripts/debounced-skills-async-save-test.mjs +57 -0
- package/scripts/explore-bench-tmp.mjs +17 -0
- package/scripts/find-fuzzy-hidden-test.mjs +145 -0
- package/scripts/mcp-grace-deferred-test.mjs +149 -0
- package/scripts/statusline-quota-hysteresis-test.mjs +37 -0
- package/scripts/tool-smoke.mjs +68 -47
- package/src/rules/agent/30-explorer.md +6 -0
- package/src/rules/shared/01-tool.md +11 -4
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +76 -1
- package/src/runtime/agent/orchestrator/config.mjs +33 -7
- package/src/runtime/agent/orchestrator/context/collect.mjs +43 -8
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +226 -0
- package/src/runtime/agent/orchestrator/mcp/client.mjs +184 -33
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +38 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +39 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +24 -7
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -4
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +40 -6
- package/src/runtime/agent/orchestrator/session/store.mjs +30 -14
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/bash-session.mjs +13 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +62 -24
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +20 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +34 -3
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +220 -27
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +61 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +67 -27
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +6 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +54 -5
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +97 -54
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +49 -31
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +35 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +126 -22
- package/src/runtime/channels/lib/crash-log.mjs +4 -2
- package/src/runtime/channels/lib/output-forwarder.mjs +2 -1
- package/src/runtime/channels/lib/owned-runtime.mjs +67 -223
- package/src/runtime/channels/lib/owner-heartbeat.mjs +9 -62
- package/src/runtime/channels/lib/parent-bridge.mjs +16 -1
- package/src/runtime/channels/lib/runtime-paths.mjs +32 -113
- package/src/runtime/channels/lib/session-discovery.mjs +2 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +22 -14
- package/src/runtime/channels/lib/tool-format.mjs +7 -2
- package/src/runtime/channels/lib/worker-main.mjs +42 -30
- package/src/runtime/memory/index.mjs +54 -7
- package/src/runtime/memory/lib/embedding-warmup.mjs +7 -0
- package/src/runtime/memory/lib/pg/process.mjs +85 -40
- package/src/runtime/memory/lib/pg/supervisor.mjs +82 -17
- package/src/runtime/memory/lib/query-handlers.mjs +4 -1
- package/src/runtime/memory/lib/recall-format.mjs +7 -3
- package/src/runtime/memory/tool-defs.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +150 -6
- package/src/runtime/shared/background-tasks.mjs +1 -1
- package/src/runtime/shared/config.mjs +53 -1
- package/src/runtime/shared/tool-execution-contract.mjs +1 -1
- package/src/runtime/shared/tool-primitives.mjs +31 -1
- package/src/runtime/shared/tool-surface.mjs +42 -13
- package/src/runtime/shared/update-checker.mjs +3 -0
- package/src/runtime/shared/user-data-guard.mjs +66 -0
- package/src/session-runtime/config-lifecycle.mjs +221 -20
- package/src/session-runtime/lifecycle-api.mjs +9 -0
- package/src/session-runtime/mcp-glue.mjs +93 -1
- package/src/session-runtime/resource-api.mjs +62 -8
- package/src/session-runtime/runtime-core.mjs +118 -4
- package/src/session-runtime/session-text.mjs +41 -0
- package/src/session-runtime/session-turn-api.mjs +50 -0
- package/src/session-runtime/settings-api.mjs +8 -1
- package/src/session-runtime/tool-catalog.mjs +350 -38
- package/src/session-runtime/tool-defs.mjs +7 -7
- package/src/session-runtime/workflow.mjs +2 -1
- package/src/standalone/channel-admin.mjs +32 -3
- package/src/standalone/channel-daemon-client.mjs +226 -0
- package/src/standalone/channel-daemon-transport.mjs +545 -0
- package/src/standalone/channel-daemon.mjs +176 -0
- package/src/standalone/channel-worker.mjs +224 -4
- package/src/standalone/explore-tool.mjs +87 -15
- package/src/standalone/hook-bus.mjs +71 -3
- package/src/tui/App.jsx +107 -19
- package/src/tui/app/clipboard.mjs +39 -19
- package/src/tui/app/doctor.mjs +57 -0
- package/src/tui/app/extension-pickers.mjs +53 -9
- package/src/tui/app/maintenance-pickers.mjs +0 -5
- package/src/tui/app/slash-dispatch.mjs +4 -4
- package/src/tui/app/text-layout.mjs +11 -0
- package/src/tui/app/use-mouse-input.mjs +235 -51
- package/src/tui/app/use-prompt-handlers.mjs +49 -30
- package/src/tui/app/use-transcript-scroll.mjs +124 -27
- package/src/tui/app/use-transcript-window.mjs +55 -1
- package/src/tui/components/Message.jsx +1 -1
- package/src/tui/components/PromptInput.jsx +3 -1
- package/src/tui/components/QueuedCommands.jsx +21 -10
- package/src/tui/components/StatusLine.jsx +3 -3
- package/src/tui/components/ToolExecution.jsx +16 -4
- package/src/tui/components/TranscriptItem.jsx +1 -1
- package/src/tui/dist/index.mjs +820 -326
- package/src/tui/engine/agent-job-feed.mjs +5 -0
- package/src/tui/engine/notification-plan.mjs +5 -0
- package/src/tui/engine/session-api.mjs +23 -8
- package/src/tui/engine/session-flow.mjs +6 -0
- package/src/tui/engine/tool-card-results.mjs +14 -5
- package/src/tui/engine/turn.mjs +9 -2
- package/src/tui/engine.mjs +32 -5
- package/src/tui/index.jsx +62 -18
- package/src/tui/paste-attachments.mjs +26 -0
- package/src/ui/statusline-agents.mjs +36 -0
- package/src/ui/statusline.mjs +60 -10
- package/src/ui/tool-card.mjs +8 -1
- package/src/vendor/statusline/bin/statusline-route.mjs +23 -7
- package/src/workflows/bench/WORKFLOW.md +46 -0
- package/src/workflows/default/WORKFLOW.md +6 -0
- package/src/workflows/solo/WORKFLOW.md +5 -0
- package/vendor/ink/build/ink.js +23 -1
- package/vendor/ink/build/output.js +154 -71
- package/vendor/ink/build/render-node-to-output.js +44 -2
- package/vendor/ink/build/render.js +4 -0
- package/vendor/ink/build/renderer.js +4 -1
|
@@ -37,7 +37,7 @@ import { startChildGuardian } from '../../../shared/child-guardian.mjs';
|
|
|
37
37
|
// transition). shell-jobs.mjs imports stripAnsi from this module, so this is
|
|
38
38
|
// a static cycle — safe because neither binding is touched at module-eval
|
|
39
39
|
// time, only when the respective functions actually run.
|
|
40
|
-
import { adoptForegroundShellJob } from './builtin/shell-jobs.mjs';
|
|
40
|
+
import { adoptForegroundShellJob, killShellJob } from './builtin/shell-jobs.mjs';
|
|
41
41
|
import {
|
|
42
42
|
_maybeEncodePowerShellCommand,
|
|
43
43
|
extractPowerShellCommandInner,
|
|
@@ -433,6 +433,55 @@ async function _execPolicyBlockMessage(command) {
|
|
|
433
433
|
return checkExecPolicyMessage(command);
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
// Count of shell spawns currently in-flight (including those parked in an
|
|
437
|
+
// EPERM backoff). Logged with each failed spawn so a Defender-induced storm
|
|
438
|
+
// is reconstructable: activeSpawnCount > 1 means concurrent spawns were
|
|
439
|
+
// racing the AV scan when the failure hit.
|
|
440
|
+
let _activeShellSpawns = 0;
|
|
441
|
+
|
|
442
|
+
function _isPowerShellSpawn(shell, shellArg) {
|
|
443
|
+
return /pwsh|powershell/i.test(String(shell || '')) || shellArg === '-Command';
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Windows Defender intermittently fails node→PowerShell spawns with EPERM
|
|
447
|
+
// while it scans the child image (see shell-runtime.mjs Trojan false-positive
|
|
448
|
+
// note). The failure is at spawn() time — before any stdio/side effect — so a
|
|
449
|
+
// short bounded retry is safe and never re-runs a command that already ran.
|
|
450
|
+
// Retry ONLY on EPERM/win32/powershell; everything else throws on first
|
|
451
|
+
// failure. Backoff 100/300/700ms caps added latency at ~1.1s. Every failed
|
|
452
|
+
// attempt logs one diagnostic line for later reconstruction.
|
|
453
|
+
async function _spawnShellWithRetry({ shell, argv, spawnOptions, shellArg, cwd }) {
|
|
454
|
+
const _delays = [100, 300, 700];
|
|
455
|
+
const _isPowerShell = _isPowerShellSpawn(shell, shellArg);
|
|
456
|
+
_activeShellSpawns++;
|
|
457
|
+
try {
|
|
458
|
+
let attempt = 0;
|
|
459
|
+
for (;;) {
|
|
460
|
+
try {
|
|
461
|
+
return spawn(shell, argv, spawnOptions);
|
|
462
|
+
} catch (err) {
|
|
463
|
+
try {
|
|
464
|
+
console.error('[shell-spawn-retry] ' + JSON.stringify({
|
|
465
|
+
code: (err && err.code) || null,
|
|
466
|
+
syscall: (err && err.syscall) || null,
|
|
467
|
+
shell,
|
|
468
|
+
cwd,
|
|
469
|
+
activeSpawnCount: _activeShellSpawns,
|
|
470
|
+
}));
|
|
471
|
+
} catch { /* logging must never mask the spawn error */ }
|
|
472
|
+
const _canRetry = err && err.code === 'EPERM'
|
|
473
|
+
&& process.platform === 'win32'
|
|
474
|
+
&& _isPowerShell
|
|
475
|
+
&& attempt < _delays.length;
|
|
476
|
+
if (!_canRetry) throw err;
|
|
477
|
+
await new Promise((r) => setTimeout(r, _delays[attempt++]));
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
} finally {
|
|
481
|
+
_activeShellSpawns--;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
436
485
|
export function execShellCommand({
|
|
437
486
|
shell,
|
|
438
487
|
shellArg,
|
|
@@ -445,6 +494,7 @@ export function execShellCommand({
|
|
|
445
494
|
autoBackgroundMs,
|
|
446
495
|
onProgress,
|
|
447
496
|
clientHostPid,
|
|
497
|
+
backgroundOnTimeout,
|
|
448
498
|
}) {
|
|
449
499
|
return new Promise(async (resolve) => {
|
|
450
500
|
const taskId = `shell_${randomUUID().slice(0, 8)}`;
|
|
@@ -516,7 +566,12 @@ export function execShellCommand({
|
|
|
516
566
|
const argv = Array.isArray(shellArgs) && shellArgs.length > 0
|
|
517
567
|
? [...shellArgs, _spawnCommand]
|
|
518
568
|
: [shellArg, _spawnCommand];
|
|
519
|
-
child =
|
|
569
|
+
child = await _spawnShellWithRetry({
|
|
570
|
+
shell,
|
|
571
|
+
argv,
|
|
572
|
+
shellArg,
|
|
573
|
+
cwd,
|
|
574
|
+
spawnOptions: {
|
|
520
575
|
env,
|
|
521
576
|
cwd,
|
|
522
577
|
windowsHide: true,
|
|
@@ -533,6 +588,7 @@ export function execShellCommand({
|
|
|
533
588
|
// not unref it after adoption. Windows detached has different console
|
|
534
589
|
// semantics, so it stays off there.
|
|
535
590
|
detached: process.platform !== 'win32',
|
|
591
|
+
},
|
|
536
592
|
});
|
|
537
593
|
startChildGuardian({
|
|
538
594
|
childPid: child.pid,
|
|
@@ -668,16 +724,20 @@ export function execShellCommand({
|
|
|
668
724
|
if (grace.unref) grace.unref();
|
|
669
725
|
});
|
|
670
726
|
|
|
671
|
-
// Auto-background transition (CC
|
|
672
|
-
//
|
|
673
|
-
//
|
|
674
|
-
//
|
|
675
|
-
//
|
|
676
|
-
//
|
|
677
|
-
//
|
|
678
|
-
//
|
|
679
|
-
//
|
|
680
|
-
|
|
727
|
+
// Auto-background transition (CC startBackgrounding analogue). Two triggers
|
|
728
|
+
// resolve the call immediately with a 'backgrounded' result while the
|
|
729
|
+
// child keeps running, adopted into the shell-jobs registry but still
|
|
730
|
+
// owned by this CLI process:
|
|
731
|
+
// 1. the optional autoBackgroundMs soft threshold (MIXDOG_SHELL_AUTO_
|
|
732
|
+
// BACKGROUND_MS opt-in) — an EARLIER promotion before the timeout, and
|
|
733
|
+
// 2. the foreground timeout deadline (backgroundOnTimeout) — the default
|
|
734
|
+
// promote-on-timeout that replaces the old tree-kill.
|
|
735
|
+
// Either way the adopted job runs UNLIMITED (timeoutMs 0, matching the
|
|
736
|
+
// async default): the original foreground timeout no longer bounds it, and
|
|
737
|
+
// the adopted-job cap poll still enforces the 100 MB output ceiling.
|
|
738
|
+
// Mutually exclusive with settle() via the autoBackgrounded flag set
|
|
739
|
+
// synchronously at the top before any await.
|
|
740
|
+
const _autoBackground = async ({ reason = 'threshold' } = {}) => {
|
|
681
741
|
// Win the race: bail if a terminal transition already happened, and
|
|
682
742
|
// claim the transition synchronously so a concurrently-queued settle()
|
|
683
743
|
// (which checks autoBackgrounded) becomes inert.
|
|
@@ -685,16 +745,18 @@ export function execShellCommand({
|
|
|
685
745
|
if (child.exitCode != null || child.signalCode != null) return;
|
|
686
746
|
autoBackgrounded = true;
|
|
687
747
|
// The foreground capture is over; stop the local watchdogs/timers so
|
|
688
|
-
// they cannot treeKill the now-adopted child. The
|
|
689
|
-
//
|
|
748
|
+
// they cannot treeKill the now-adopted child. The adopted job runs
|
|
749
|
+
// unlimited; refreshShellJob only enforces the output cap.
|
|
690
750
|
if (timer) { clearTimeout(timer); timer = null; }
|
|
691
751
|
_clearProgressTimer();
|
|
692
752
|
if (sizeWatchdog) { clearInterval(sizeWatchdog); sizeWatchdog = null; }
|
|
693
753
|
if (autoBgTimer) { clearTimeout(autoBgTimer); autoBgTimer = null; }
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
754
|
+
// Keep the abort handler ATTACHED through the promotion window. A user
|
|
755
|
+
// cancel racing in after promotion starts must still bring the adopted
|
|
756
|
+
// child down — the handler's treeKill(child) does exactly that (settle()
|
|
757
|
+
// is inert once autoBackgrounded, but the kill itself still lands, and
|
|
758
|
+
// refreshShellJob then flags the job failed). We only detach on a real
|
|
759
|
+
// settle() or on the adoption-failure fallback below.
|
|
698
760
|
// Every subsequent stdout/stderr chunk must hit disk — the call is
|
|
699
761
|
// about to resolve and nobody will drain the in-memory buffers again.
|
|
700
762
|
try { taskOutput.forceSpill(); } catch {}
|
|
@@ -711,7 +773,9 @@ export function execShellCommand({
|
|
|
711
773
|
command,
|
|
712
774
|
cwd,
|
|
713
775
|
pid: child.pid,
|
|
714
|
-
|
|
776
|
+
// Unlimited: the promoted job is no longer bounded by the foreground
|
|
777
|
+
// timeout (matches the async omitted-default behavior).
|
|
778
|
+
timeoutMs: 0,
|
|
715
779
|
mergeStderr: false,
|
|
716
780
|
stdoutPath,
|
|
717
781
|
stderrPath,
|
|
@@ -722,6 +786,18 @@ export function execShellCommand({
|
|
|
722
786
|
} catch {
|
|
723
787
|
job = null;
|
|
724
788
|
}
|
|
789
|
+
// Adoption failed AFTER the foreground timers/size-watchdog were already
|
|
790
|
+
// torn down. Do NOT resolve as backgrounded — that would leave the child
|
|
791
|
+
// running unlimited with no task_id and no watcher. Release the claim and
|
|
792
|
+
// fall back to the old kill path so the command never outlives a failed
|
|
793
|
+
// promotion. (The abort handler is still attached, so an in-flight cancel
|
|
794
|
+
// is honored by the kill path too.)
|
|
795
|
+
if (!job) {
|
|
796
|
+
autoBackgrounded = false;
|
|
797
|
+
if (reason === 'timeout') timedOut = true; else killed = true;
|
|
798
|
+
_treeKillForceSettle();
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
725
801
|
// Wire the lifecycle: on close, write the exit-code file FIRST then
|
|
726
802
|
// touch donePath STRICTLY AFTER — the exact ordering refreshShellJob()
|
|
727
803
|
// gates completion on (donePath visible ⇒ exit file fully flushed).
|
|
@@ -732,6 +808,14 @@ export function execShellCommand({
|
|
|
732
808
|
try { writeFileSync(job.donePath, ''); } catch {}
|
|
733
809
|
});
|
|
734
810
|
}
|
|
811
|
+
// Adoption committed. If a cancel already fired (before or during the
|
|
812
|
+
// adoption window), bring the now-adopted child down via its jobId so the
|
|
813
|
+
// promotion can't outlive a user abort. Idempotent with the still-attached
|
|
814
|
+
// abort handler's treeKill.
|
|
815
|
+
if (abortSignal && abortSignal.aborted) {
|
|
816
|
+
try { killShellJob(job.jobId); } catch {}
|
|
817
|
+
try { treeKill(child); } catch {}
|
|
818
|
+
}
|
|
735
819
|
// Snapshot the partial output captured so far for the immediate result.
|
|
736
820
|
let stdout = '';
|
|
737
821
|
let stderr = '';
|
|
@@ -740,7 +824,10 @@ export function execShellCommand({
|
|
|
740
824
|
try { stderr = await taskOutput.getStderr(); }
|
|
741
825
|
catch (err) { taskOutput.writeError = taskOutput.writeError || err; }
|
|
742
826
|
const jobId = job ? job.jobId : null;
|
|
743
|
-
const secs = Math.round(
|
|
827
|
+
const secs = Math.max(0, Math.round((Date.now() - _startMs) / 1000));
|
|
828
|
+
const _verb = reason === 'timeout'
|
|
829
|
+
? `moved to background at timeout after ${secs}s`
|
|
830
|
+
: `auto-backgrounded after ${secs}s`;
|
|
744
831
|
resolve(
|
|
745
832
|
new ExecResult({
|
|
746
833
|
stdout,
|
|
@@ -759,14 +846,31 @@ export function execShellCommand({
|
|
|
759
846
|
backgrounded: true,
|
|
760
847
|
jobId,
|
|
761
848
|
backgroundMessage: jobId
|
|
762
|
-
?
|
|
763
|
-
:
|
|
849
|
+
? `${_verb}; still running — completion will be delivered as a background task notification. Use task with task_id:${jobId} only for manual wait/status/read/cancel.`
|
|
850
|
+
: `${_verb}; still running`,
|
|
764
851
|
}),
|
|
765
852
|
);
|
|
766
853
|
};
|
|
767
854
|
|
|
768
855
|
if (timeoutMs > 0) {
|
|
769
856
|
timer = setTimeout(() => {
|
|
857
|
+
// Promote-on-timeout: if the caller allows backgrounding and the child
|
|
858
|
+
// is still running (not a trailing-`&` detach), adopt it as a tracked
|
|
859
|
+
// background job instead of tree-killing it. Falls through to the old
|
|
860
|
+
// kill path for disallowed/opted-out commands (backgroundOnTimeout
|
|
861
|
+
// false) or when a terminal transition already won the race.
|
|
862
|
+
if (
|
|
863
|
+
backgroundOnTimeout &&
|
|
864
|
+
!_isBackground &&
|
|
865
|
+
!settled &&
|
|
866
|
+
!autoBackgrounded &&
|
|
867
|
+
!killed &&
|
|
868
|
+
child.exitCode == null &&
|
|
869
|
+
child.signalCode == null
|
|
870
|
+
) {
|
|
871
|
+
_autoBackground({ reason: 'timeout' });
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
770
874
|
timedOut = true;
|
|
771
875
|
_treeKillForceSettle();
|
|
772
876
|
}, timeoutMs);
|
|
@@ -23,8 +23,9 @@ function isChannelsDegraded() { return _channelsDegraded; }
|
|
|
23
23
|
try {
|
|
24
24
|
process.stderr.on('error', (e) => {
|
|
25
25
|
if (e && (e.code === 'EPIPE' || /EPIPE/.test(String(e.message || '')))) {
|
|
26
|
+
// Parent stdio pipe loss stops stderr writes only. It is NOT runtime
|
|
27
|
+
// corruption, so it must not degrade tool dispatch (_channelsDegraded).
|
|
26
28
|
_stderrBroken = true;
|
|
27
|
-
_channelsDegraded = true;
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
31
|
} catch {}
|
|
@@ -75,7 +76,8 @@ ${err instanceof Error ? err.stack : ""}
|
|
|
75
76
|
_writeCrashLine(crashLog, msg);
|
|
76
77
|
}
|
|
77
78
|
if (err instanceof Error && err.message.includes("EPIPE")) {
|
|
78
|
-
|
|
79
|
+
// EPIPE = a broken pipe (parent stdio/IPC gone), not corrupted runtime
|
|
80
|
+
// state. Stop writing to the dead pipe but keep serving tool calls.
|
|
79
81
|
_stderrBroken = true;
|
|
80
82
|
}
|
|
81
83
|
crashLogging = false;
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
formatToolSurface,
|
|
7
7
|
isExplorerSurface,
|
|
8
8
|
isMemorySurface,
|
|
9
|
+
stripToolPrefix,
|
|
9
10
|
} from "../../shared/tool-surface.mjs";
|
|
10
11
|
import {
|
|
11
12
|
cwdToProjectSlug,
|
|
@@ -726,7 +727,7 @@ ${_bt.trim()}` : _bt.trim();
|
|
|
726
727
|
// The non-set checks are inlined rather than delegated to the imported
|
|
727
728
|
// isHidden, because that helper would re-consult the module-local
|
|
728
729
|
// HIDDEN_TOOLS Set and ignore the OutputForwarder static.
|
|
729
|
-
if (OutputForwarder.HIDDEN_TOOLS.has(name)) return true;
|
|
730
|
+
if (OutputForwarder.HIDDEN_TOOLS.has(name) || OutputForwarder.HIDDEN_TOOLS.has(stripToolPrefix(name))) return true;
|
|
730
731
|
if (name === "reply" || name === "fetch") return true;
|
|
731
732
|
return false;
|
|
732
733
|
};
|