claude-code-session-manager 0.87.0 → 0.88.1
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 +26 -53
- package/dist/assets/{AgentLibrary-DyLWzZDf.js → AgentLibrary-kQF8_wAw.js} +1 -1
- package/dist/assets/{DataModel--mISIJ6h.js → DataModel-CY_mMnsr.js} +1 -1
- package/dist/assets/{History-C2ahUXTg.js → History-Sji2brb0.js} +1 -1
- package/dist/assets/{Hooks-BiC6oyR2.js → Hooks-CtqpO-p5.js} +1 -1
- package/dist/assets/{HostBilko-BPleEOld.js → HostBilko-DN0ydOCr.js} +1 -1
- package/dist/assets/{Library-Dc8Qst1R.js → Library-CoiLZTKh.js} +1 -1
- package/dist/assets/{ListDetail-DIXh-OLX.js → ListDetail-CmqiQ_io.js} +1 -1
- package/dist/assets/{MarkdownEditor-C90bkLXK.js → MarkdownEditor-HPoNeKhT.js} +1 -1
- package/dist/assets/{McpServers-DqcbLOLZ.js → McpServers-Bj1X3_NT.js} +1 -1
- package/dist/assets/{Memory-CW62MXlh.js → Memory-1PKjsM3b.js} +1 -1
- package/dist/assets/{Panel-Bw1FhRuF.js → Panel-I1s6ghPo.js} +1 -1
- package/dist/assets/{Permissions-BcUC-5y8.js → Permissions-BhiiZjHQ.js} +1 -1
- package/dist/assets/{Plugins-BnKx9flD.js → Plugins-gv3_fkPX.js} +2 -2
- package/dist/assets/{ProvenanceBadge-Bw5vNVPT.js → ProvenanceBadge-BGcgBd8V.js} +1 -1
- package/dist/assets/{SaveBar-CWr0O_w-.js → SaveBar-BGr9eZ4g.js} +1 -1
- package/dist/assets/{Scheduler-DYdLuUqq.js → Scheduler-Bdo_awPq.js} +7 -7
- package/dist/assets/{ScopeSwitcher-CrBLbg8s.js → ScopeSwitcher-ukl0qWaA.js} +1 -1
- package/dist/assets/{Settings-DluB-vN1.js → Settings-DJkFj22G.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-CHLSseay.js → SkillReferenceGraph-0t1Qblp6.js} +1 -1
- package/dist/assets/{Skills-gNdo_HNK.js → Skills-CeVdBGE-.js} +1 -1
- package/dist/assets/{SystemPrompt-Cru05-Ia.js → SystemPrompt-CfKvNHi3.js} +1 -1
- package/dist/assets/{TagLibrary-DNHY0xou.js → TagLibrary-DAzNaUPd.js} +1 -1
- package/dist/assets/{TiptapBody-I4lmbCgP.js → TiptapBody--S_rGXoA.js} +1 -1
- package/dist/assets/{Toggle-bWMHjmRh.js → Toggle-Dszm0xnp.js} +1 -1
- package/dist/assets/{index-DV3PorRY.css → index-BHTX4OTc.css} +1 -1
- package/dist/assets/{index-fc_JjdxL.js → index-Dp4Rc--q.js} +356 -356
- package/dist/assets/{settingsSchema-BfhtZnGD.js → settingsSchema-BLbssMYo.js} +1 -1
- package/dist/assets/{whisperWorker-Dbia1OpC.js → whisperWorker-C7ZGQwKg.js} +7 -7
- package/dist/index.html +2 -2
- package/dist/vad/ort-wasm-simd-threaded.asyncify.mjs +106 -110
- package/dist/vad/ort-wasm-simd-threaded.asyncify.wasm +0 -0
- package/dist/vad/ort-wasm-simd-threaded.jsep.mjs +98 -98
- package/dist/vad/ort-wasm-simd-threaded.jsep.wasm +0 -0
- package/dist/vad/ort-wasm-simd-threaded.jspi.mjs +99 -102
- package/dist/vad/ort-wasm-simd-threaded.jspi.wasm +0 -0
- package/dist/vad/ort-wasm-simd-threaded.mjs +46 -46
- package/dist/vad/ort-wasm-simd-threaded.wasm +0 -0
- package/package.json +10 -13
- package/scripts/README.md +59 -0
- package/scripts/audit-ops-hygiene.cjs +350 -0
- package/scripts/hooks/guard-destructive-git.cjs +10 -34
- package/scripts/hooks/guard-inline-implementation.cjs +14 -8
- package/scripts/hooks/guard-prd-writes.cjs +7 -36
- package/scripts/hooks/guard-self-schedule.cjs +175 -0
- package/scripts/ops-sweep.cjs +355 -0
- package/scripts/scheduler-mcp-server.cjs +28 -71
- package/src/main/__tests__/bilkoHost-integration.test.cjs +3 -3
- package/src/main/__tests__/chat-cancel-terminal.test.cjs +6 -9
- package/src/main/__tests__/chat-exit-close-race.test.cjs +3 -3
- package/src/main/__tests__/chat-mcp-consent-notice.test.cjs +4 -5
- package/src/main/__tests__/chat-queue.test.cjs +2 -2
- package/src/main/__tests__/chat-stop-signal.test.cjs +2 -2
- package/src/main/__tests__/dep-orphan-archive-health.test.cjs +77 -0
- package/src/main/__tests__/dod-batchkey.test.cjs +2 -2
- package/src/main/__tests__/dod-drain-hook.test.cjs +2 -2
- package/src/main/__tests__/dod-report.test.cjs +2 -2
- package/src/main/__tests__/dod-reverify.test.cjs +2 -2
- package/src/main/__tests__/epicMint.test.cjs +2 -2
- package/src/main/__tests__/exchanges.test.cjs +2 -2
- package/src/main/__tests__/extractJson.test.cjs +2 -2
- package/src/main/__tests__/files-reject-credentials.test.cjs +1 -1
- package/src/main/__tests__/fixtures/1218-fo-01-move-scripts-lib-into-src-main-lib.log +556 -0
- package/src/main/__tests__/health-build-freshness.test.cjs +39 -0
- package/src/main/__tests__/health-delegation-chain.test.cjs +15 -1
- package/src/main/__tests__/health-queue-dispatch.test.cjs +58 -7
- package/src/main/__tests__/health-tick-liveness.test.cjs +27 -3
- package/src/main/__tests__/health-usage-poller.test.cjs +70 -23
- package/src/main/__tests__/historyRollup.test.cjs +2 -2
- package/src/main/__tests__/kg-augment.test.cjs +2 -2
- package/src/main/__tests__/mcpStatus.test.cjs +2 -2
- package/src/main/__tests__/memoryAggregate.test.cjs +1 -1
- package/src/main/__tests__/memoryStale.test.cjs +1 -1
- package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +25 -1
- package/src/main/__tests__/pollLoop-dispatch-on-failure.test.cjs +33 -3
- package/src/main/__tests__/prd-group-allocator.test.cjs +2 -2
- package/src/main/__tests__/prdAdminRouteParity.test.cjs +2 -0
- package/src/main/__tests__/prdAdminRoutes.test.cjs +14 -2
- package/src/main/__tests__/prdAuthoringSeed.test.cjs +39 -0
- package/src/main/__tests__/prdLocationsArchived.test.cjs +20 -13
- package/src/main/__tests__/proc-role-env.test.cjs +125 -0
- package/src/main/__tests__/procname-claude-spawn-sites.test.cjs +304 -0
- package/src/main/__tests__/procname-sm-processes.test.cjs +127 -0
- package/src/main/__tests__/projectHomeAdminRoutes.test.cjs +81 -401
- package/src/main/__tests__/projectPages.test.cjs +63 -149
- package/src/main/__tests__/queue-health-verdict.test.cjs +9 -9
- package/src/main/__tests__/queue-starvation-dispatch-driver.test.cjs +117 -20
- package/src/main/__tests__/queueHistory.test.cjs +2 -2
- package/src/main/__tests__/rateLimitPollerStreak.test.cjs +38 -3
- package/src/main/__tests__/runVerify-landed-commit-outranks.test.cjs +181 -0
- package/src/main/__tests__/runVerify.test.cjs +5 -5
- package/src/main/__tests__/scheduleJobStatusDrift.test.cjs +3 -3
- package/src/main/__tests__/scheduleJobTransitions.test.cjs +2 -2
- package/src/main/__tests__/scheduler-adopted-run-supervision.test.cjs +143 -0
- package/src/main/__tests__/scheduler-autofix-select.test.cjs +2 -2
- package/src/main/__tests__/scheduler-autopromote.test.cjs +2 -2
- package/src/main/__tests__/scheduler-bash-timeout-env.test.cjs +3 -5
- package/src/main/__tests__/scheduler-boot-orphans.test.cjs +78 -97
- package/src/main/__tests__/scheduler-default-eligible-heal.test.cjs +161 -0
- package/src/main/__tests__/scheduler-dispatch-loop.test.cjs +58 -0
- package/src/main/__tests__/scheduler-epic-digest.test.cjs +3 -5
- package/src/main/__tests__/scheduler-force-tick-outcome.test.cjs +2 -2
- package/src/main/__tests__/scheduler-gate-shadow.test.cjs +119 -0
- package/src/main/__tests__/scheduler-guard-verdict-autoresolve.test.cjs +46 -0
- package/src/main/__tests__/scheduler-heartbeat-payload.test.cjs +80 -0
- package/src/main/__tests__/scheduler-inplace-salvage.test.cjs +25 -18
- package/src/main/__tests__/scheduler-investigation-prompt.test.cjs +4 -4
- package/src/main/__tests__/scheduler-launch-failure.test.cjs +3 -5
- package/src/main/__tests__/scheduler-looks-done.test.cjs +26 -7
- package/src/main/__tests__/scheduler-manual-pause.test.cjs +118 -0
- package/src/main/__tests__/scheduler-meta-code-sha.test.cjs +26 -3
- package/src/main/__tests__/scheduler-prd-missing-skip.test.cjs +17 -2
- package/src/main/__tests__/scheduler-prd-persona-spawn.test.cjs +3 -5
- package/src/main/__tests__/scheduler-quiet-machine-lease.test.cjs +41 -6
- package/src/main/__tests__/scheduler-rate-limit-pause.test.cjs +62 -6
- package/src/main/__tests__/scheduler-rate-limit-spin-guard.test.cjs +3 -5
- package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +23 -4
- package/src/main/__tests__/scheduler-reconcile-cwd-preserve.test.cjs +100 -0
- package/src/main/__tests__/scheduler-reconcile-invalid-repair.test.cjs +3 -3
- package/src/main/__tests__/scheduler-reconcile-quarantine.test.cjs +4 -4
- package/src/main/__tests__/scheduler-shard-quarantine.test.cjs +110 -0
- package/src/main/__tests__/scheduler-shared-tree-guard.test.cjs +81 -1
- package/src/main/__tests__/scheduler-stall-per-project.test.cjs +14 -0
- package/src/main/__tests__/scheduler-starve-escalation.test.cjs +4 -4
- package/src/main/__tests__/scheduler-stranded-autofix-park.test.cjs +245 -0
- package/src/main/__tests__/scheduler-supervisor-record.test.cjs +81 -0
- package/src/main/__tests__/scheduler-tick-cancel-token.test.cjs +2 -2
- package/src/main/__tests__/scheduler-tick-wedge.test.cjs +172 -0
- package/src/main/__tests__/scheduler-transient-failure.test.cjs +2 -2
- package/src/main/__tests__/scheduler-worktree-cap-defer.test.cjs +37 -11
- package/src/main/__tests__/scheduler-worktree-exec-cwd.test.cjs +3 -5
- package/src/main/__tests__/usageSingleFlight.test.cjs +157 -0
- package/src/main/__tests__/workTypeLibrary.test.cjs +1 -1
- package/src/main/bilkoHost.cjs +16 -7
- package/src/main/build-info.json +8 -0
- package/src/main/chatRunner.cjs +4 -2
- package/src/main/config.cjs +2 -3
- package/src/main/docEdit.cjs +4 -2
- package/src/main/health.cjs +276 -52
- package/src/main/heapSnapshot.cjs +2 -2
- package/src/main/historyAggregator.cjs +1 -1
- package/src/main/index.cjs +61 -10
- package/src/main/ipcSchemas.cjs +6 -17
- package/src/main/lib/__tests__/auditLog.test.cjs +38 -0
- package/src/main/lib/__tests__/buildIdentity.test.cjs +121 -0
- package/src/main/lib/__tests__/cwdClassify.test.cjs +111 -0
- package/src/main/lib/__tests__/definitionOfDoneSequence.test.cjs +95 -0
- package/src/main/lib/__tests__/delegationReadiness.test.cjs +1 -1
- package/src/main/lib/__tests__/dispatchLoop.test.cjs +63 -0
- package/src/main/lib/__tests__/gateFixtures.json +20 -0
- package/src/main/lib/__tests__/gitWorktree.test.cjs +8 -1
- package/src/main/lib/__tests__/instanceLock.test.cjs +93 -7
- package/src/main/lib/__tests__/jobSupervisorRecord.test.cjs +78 -0
- package/src/main/lib/__tests__/jobWorktreeBootLive.test.cjs +11 -0
- package/src/main/lib/__tests__/localAdminHttp.test.cjs +1 -1
- package/src/main/lib/__tests__/mcpToolCatalog.test.cjs +6 -1
- package/src/main/lib/__tests__/procIdentity.test.cjs +119 -0
- package/src/main/lib/__tests__/procName.test.cjs +92 -0
- package/src/main/lib/__tests__/queueStoreMachineStateRecovery.test.cjs +67 -0
- package/src/main/lib/__tests__/schedulerMcpServerHelp.test.cjs +6 -7
- package/src/main/lib/__tests__/schedulerMcpServerProjectHome.test.cjs +37 -204
- package/src/main/lib/__tests__/schedulerPaths.test.cjs +226 -0
- package/src/main/lib/__tests__/schedulerPathsWorktree.test.cjs +94 -0
- package/src/main/lib/__tests__/schedulerRuntimeState.test.cjs +56 -0
- package/src/main/lib/__tests__/sessionSlots.test.cjs +45 -0
- package/src/main/lib/__tests__/telemetryBacklog.test.cjs +1 -1
- package/src/main/lib/__tests__/upgradeDrain.test.cjs +130 -0
- package/src/main/lib/__tests__/usageCircuit.test.cjs +61 -0
- package/src/main/lib/__tests__/watchdog-helpers.test.cjs +63 -0
- package/src/main/lib/__tests__/watchdog-relaunch.test.cjs +73 -0
- package/src/main/lib/activeIndexRebuild.cjs +1 -3
- package/src/main/lib/activeSessions.cjs +20 -88
- package/src/main/lib/adoptedRunSupervisor.cjs +136 -0
- package/src/main/lib/agentModelResolve.cjs +33 -1
- package/src/main/lib/agentPersonaSchema.cjs +2 -2
- package/src/main/lib/auditLog.cjs +30 -5
- package/src/main/lib/buildIdentity.cjs +113 -0
- package/src/main/lib/classifyPromptTicket.cjs +3 -2
- package/src/main/lib/claudeBin.cjs +37 -2
- package/src/main/lib/cleanEnv.cjs +27 -1
- package/src/main/lib/credentials.cjs +4 -2
- package/src/main/lib/cwdClassify.cjs +185 -0
- package/src/main/lib/definitionOfDone.cjs +296 -52
- package/src/main/lib/dispatchLoop.cjs +40 -0
- package/src/main/lib/effectiveModelInfo.cjs +9 -10
- package/src/main/lib/ephemeralCwd.cjs +7 -28
- package/src/main/lib/gitWorktree.cjs +95 -8
- package/src/main/lib/guardShims.cjs +3 -3
- package/src/main/lib/historyRollup.cjs +6 -7
- package/src/main/lib/instanceLock.cjs +32 -5
- package/src/main/lib/jobSupervisorRecord.cjs +147 -0
- package/src/main/lib/jobWorktreeBootLive.cjs +9 -5
- package/src/main/lib/localAdminHttp.cjs +9 -27
- package/src/main/lib/mcpToolCatalog.cjs +29 -77
- package/src/main/lib/opsOwnership.cjs +27 -19
- package/src/main/lib/prdAuthoringSeed.cjs +36 -0
- package/src/main/lib/prdLocations.cjs +48 -1
- package/src/main/lib/procIdentity.cjs +126 -0
- package/src/main/lib/procName.cjs +98 -0
- package/src/main/lib/projectHomeAdminRoutes.cjs +56 -327
- package/src/main/lib/queueHistory.cjs +8 -7
- package/src/main/lib/queueStore.cjs +57 -37
- package/src/main/lib/quietMachineLease.cjs +19 -2
- package/src/main/lib/reservationExpiry.cjs +30 -0
- package/src/main/lib/runClaudeP.cjs +4 -2
- package/src/main/lib/runLogRetention.cjs +3 -2
- package/src/main/lib/scheduleJobSchema.cjs +2 -2
- package/src/main/lib/scheduleJobTransitions.cjs +29 -2
- package/src/main/lib/schedulerBatch.cjs +27 -2
- package/src/main/lib/schedulerPaths.cjs +175 -0
- package/src/main/lib/schedulerRuntimeState.cjs +59 -0
- package/src/main/lib/sessionSlots.cjs +47 -9
- package/src/main/lib/smProcNames.cjs +51 -0
- package/src/main/lib/upgradeDrain.cjs +188 -0
- package/src/main/lib/usageCircuit.cjs +53 -6
- package/src/main/lib/watchdogHelpers.cjs +70 -37
- package/src/main/lib/withTimeout.cjs +33 -0
- package/src/main/mcpStatus.cjs +4 -2
- package/src/main/pluginInstall.cjs +6 -2
- package/src/main/projectPages.cjs +41 -145
- package/src/main/pty.cjs +8 -1
- package/src/main/queueOps.cjs +10 -10
- package/src/main/runVerify.cjs +69 -3
- package/src/main/scheduler.cjs +1607 -383
- package/src/main/seedAgentPersonas.cjs +1 -1
- package/src/main/seedDevPlugin.cjs +1 -1
- package/src/main/seedSchedulerMcp.cjs +7 -6
- package/src/main/seedStatus.cjs +1 -1
- package/src/main/supervisor.cjs +5 -3
- package/src/main/usage.cjs +126 -62
- package/src/preload/api.d.ts +18 -64
- package/src/preload/index.cjs +2 -4
- package/src/seed/agents/project-home-builder.md +31 -48
- package/screenshots/.gitkeep +0 -0
- package/screenshots/README-screenshots.md +0 -13
- package/src/main/lib/projectPageSummarySchema.cjs +0 -181
- package/src/main/teams.cjs +0 -95
- package/src/main/templates/project-pages-catalog.json +0 -741
- package/src/main/templates/project-pages-default-home.html +0 -123
- package/src/main/templates/project-pages-pipeline.md +0 -417
- package/src/seed/prompts/code-review/ac-coverage-check.md +0 -8
- package/src/seed/prompts/code-review/correctness-only.md +0 -8
- package/src/seed/prompts/code-review/full-spectrum-high.md +0 -8
- package/src/seed/prompts/code-review/hallucination-check.md +0 -8
- package/src/seed/prompts/code-review/public-api-compat.md +0 -8
- package/src/seed/prompts/code-review/readability-naming.md +0 -8
- package/src/seed/prompts/debugging/bug-as-failing-test.md +0 -8
- package/src/seed/prompts/debugging/git-bisect-regression.md +0 -8
- package/src/seed/prompts/debugging/instrument-intermittent-bug.md +0 -8
- package/src/seed/prompts/debugging/localize-pipeline-failure.md +0 -8
- package/src/seed/prompts/debugging/reproduce-then-diagnose.md +0 -8
- package/src/seed/prompts/documentation/adr-from-change.md +0 -8
- package/src/seed/prompts/documentation/module-readme.md +0 -8
- package/src/seed/prompts/documentation/onboarding-plan.md +0 -8
- package/src/seed/prompts/documentation/refresh-claude-md.md +0 -8
- package/src/seed/prompts/documentation/tsdoc-public-exports.md +0 -8
- package/src/seed/prompts/git-pr/conventional-commit.md +0 -8
- package/src/seed/prompts/git-pr/draft-pr-title-body.md +0 -8
- package/src/seed/prompts/git-pr/pre-commit-safety-sweep.md +0 -8
- package/src/seed/prompts/git-pr/release-notes-block.md +0 -8
- package/src/seed/prompts/git-pr/split-large-pr.md +0 -8
- package/src/seed/prompts/performance/bundle-startup-audit.md +0 -8
- package/src/seed/prompts/performance/complexity-audit.md +0 -8
- package/src/seed/prompts/performance/cpu-profile-hot-path.md +0 -8
- package/src/seed/prompts/performance/db-query-plan-review.md +0 -8
- package/src/seed/prompts/performance/memory-leak-hunt.md +0 -8
- package/src/seed/prompts/qa/api-contract-tests.md +0 -8
- package/src/seed/prompts/qa/e2e-critical-path.md +0 -8
- package/src/seed/prompts/qa/failing-test-for-bug.md +0 -8
- package/src/seed/prompts/qa/find-missing-test-coverage.md +0 -8
- package/src/seed/prompts/qa/stabilize-flaky-test.md +0 -8
- package/src/seed/prompts/qa/tdd-red-first.md +0 -8
- package/src/seed/prompts/qa/visual-regression-review.md +0 -8
- package/src/seed/prompts/qa/wcag-axe-scan.md +0 -8
- package/src/seed/prompts/refactoring/dead-code-sweep.md +0 -8
- package/src/seed/prompts/refactoring/extract-duplicated-pattern.md +0 -8
- package/src/seed/prompts/refactoring/modernize-legacy-file.md +0 -8
- package/src/seed/prompts/refactoring/reduce-cyclomatic-complexity.md +0 -8
- package/src/seed/prompts/refactoring/tighten-module-boundaries.md +0 -8
- package/src/seed/prompts/security/authz-audit.md +0 -8
- package/src/seed/prompts/security/crypto-correctness.md +0 -8
- package/src/seed/prompts/security/cwe-top-25-hunt.md +0 -8
- package/src/seed/prompts/security/dependency-audit.md +0 -8
- package/src/seed/prompts/security/ipc-boundary-hardening.md +0 -8
- package/src/seed/prompts/security/owasp-top-10-staged-diff.md +0 -8
- package/src/seed/prompts/security/secret-credential-scan.md +0 -8
- package/web/README.md +0 -41
- package/web/project-pages/logic/dist/logic.cjs +0 -4709
- package/web/project-pages/render.cjs +0 -70
- package/web/project-pages/renderer/dist/renderer.cjs +0 -18900
- package/web/project-pages/validate-summary.cjs +0 -62
|
@@ -6,6 +6,17 @@
|
|
|
6
6
|
* circuit with jittered backoff; degradedBudget() carries forward the last
|
|
7
7
|
* known-good BINDING window's utilization (never 0), pinning to 100 on a
|
|
8
8
|
* fresh executor-observed 429 and capping concurrency at 2. Pure Node.
|
|
9
|
+
*
|
|
10
|
+
* Kill switches (read live from process.env, so a test/operator can flip
|
|
11
|
+
* them without restarting anything that already holds a circuit instance):
|
|
12
|
+
* SM_USAGE_CIRCUIT=0 — bypasses the breaker entirely: state() always
|
|
13
|
+
* reports 'closed' and recordFailure() never
|
|
14
|
+
* opens it. Escape hatch if the breaker itself
|
|
15
|
+
* is ever suspected of wedging dispatch.
|
|
16
|
+
* SM_USAGE_DEGRADED_CAP=n — overrides degradedBudget()'s concurrencyCap
|
|
17
|
+
* outright (bypasses the normal min(cap, 2)),
|
|
18
|
+
* for an operator who needs a different ceiling
|
|
19
|
+
* while the meter is degraded.
|
|
9
20
|
*/
|
|
10
21
|
|
|
11
22
|
const FLOOR_MS = 30_000;
|
|
@@ -63,12 +74,25 @@ function bindingWindow(payload) {
|
|
|
63
74
|
};
|
|
64
75
|
}
|
|
65
76
|
|
|
77
|
+
/**
|
|
78
|
+
* SM_USAGE_DEGRADED_CAP=<n> overrides the normal min(configuredCap, 2)
|
|
79
|
+
* ceiling outright — an operator escape hatch, not a default path. Falls
|
|
80
|
+
* through to the normal min(cap, 2) rule when unset/non-positive.
|
|
81
|
+
*/
|
|
82
|
+
function degradedConcurrencyCap(configuredCap) {
|
|
83
|
+
const override = Number(process.env.SM_USAGE_DEGRADED_CAP);
|
|
84
|
+
if (Number.isFinite(override) && override > 0) return override;
|
|
85
|
+
const cap = Number.isFinite(configuredCap) ? configuredCap : 2;
|
|
86
|
+
return Math.min(cap, 2);
|
|
87
|
+
}
|
|
88
|
+
|
|
66
89
|
/**
|
|
67
90
|
* Conservative budget to run on while the meter is down. utilization is
|
|
68
91
|
* carried forward from the last known-good BINDING window — never 0, which
|
|
69
92
|
* would read as "plenty of headroom" instead of "we don't know." A fresh
|
|
70
93
|
* executor-observed 429 (its own window not yet passed) pins utilization to
|
|
71
|
-
* 100 regardless of the stale cached value. concurrencyCap never exceeds 2
|
|
94
|
+
* 100 regardless of the stale cached value. concurrencyCap never exceeds 2
|
|
95
|
+
* (or SM_USAGE_DEGRADED_CAP, if set).
|
|
72
96
|
*/
|
|
73
97
|
function degradedBudget(lastGoodPayload, executorEvidence = {}) {
|
|
74
98
|
const window = bindingWindow(lastGoodPayload);
|
|
@@ -76,10 +100,7 @@ function degradedBudget(lastGoodPayload, executorEvidence = {}) {
|
|
|
76
100
|
? window.utilization
|
|
77
101
|
: 100;
|
|
78
102
|
|
|
79
|
-
const
|
|
80
|
-
? executorEvidence.configuredCap
|
|
81
|
-
: 2;
|
|
82
|
-
const concurrencyCap = Math.min(configuredCap, 2);
|
|
103
|
+
const concurrencyCap = degradedConcurrencyCap(executorEvidence.configuredCap);
|
|
83
104
|
|
|
84
105
|
if (executorEvidence.observed429 && isResetFresh(executorEvidence.resetsAt, executorEvidence.now)) {
|
|
85
106
|
utilization = 100;
|
|
@@ -98,6 +119,12 @@ function singleFlight(fn) {
|
|
|
98
119
|
};
|
|
99
120
|
}
|
|
100
121
|
|
|
122
|
+
/** SM_USAGE_CIRCUIT=0 (or 'false') bypasses the breaker entirely. */
|
|
123
|
+
function breakerEnabled() {
|
|
124
|
+
const v = process.env.SM_USAGE_CIRCUIT;
|
|
125
|
+
return v == null || v === '' || (v !== '0' && String(v).toLowerCase() !== 'false');
|
|
126
|
+
}
|
|
127
|
+
|
|
101
128
|
/**
|
|
102
129
|
* Breaker state machine over the meter: closed -> open after 3 consecutive
|
|
103
130
|
* failures; open allows exactly one probe per backoff interval (half_open);
|
|
@@ -110,6 +137,12 @@ function createUsageCircuit({ now = () => Date.now() } = {}) {
|
|
|
110
137
|
let backoffBaseMs = 0;
|
|
111
138
|
let nextProbeAtMs = 0;
|
|
112
139
|
let probeInFlight = false;
|
|
140
|
+
// ms timestamp the circuit most recently transitioned closed -> open; kept
|
|
141
|
+
// through half_open <-> open cycles of the SAME streak (a failed probe
|
|
142
|
+
// re-arms the timer but the meter has been down continuously since this
|
|
143
|
+
// timestamp), cleared only by recordSuccess. Feeds health.cjs's
|
|
144
|
+
// GREEN/YELLOW/RED ladder (open duration), not just a failure count.
|
|
145
|
+
let openedAtMs = null;
|
|
113
146
|
|
|
114
147
|
function scheduleNextProbe() {
|
|
115
148
|
const intervalMs = backoffWithJitter(backoffBaseMs);
|
|
@@ -118,6 +151,7 @@ function createUsageCircuit({ now = () => Date.now() } = {}) {
|
|
|
118
151
|
}
|
|
119
152
|
|
|
120
153
|
function state() {
|
|
154
|
+
if (!breakerEnabled()) return 'closed';
|
|
121
155
|
if (currentState === 'open' && !probeInFlight && now() >= nextProbeAtMs) {
|
|
122
156
|
currentState = 'half_open';
|
|
123
157
|
probeInFlight = true;
|
|
@@ -127,6 +161,7 @@ function createUsageCircuit({ now = () => Date.now() } = {}) {
|
|
|
127
161
|
|
|
128
162
|
function recordFailure(kind) { // eslint-disable-line no-unused-vars
|
|
129
163
|
consecutiveFailures += 1;
|
|
164
|
+
if (!breakerEnabled()) return;
|
|
130
165
|
if (currentState === 'half_open') {
|
|
131
166
|
probeInFlight = false;
|
|
132
167
|
currentState = 'open';
|
|
@@ -135,6 +170,7 @@ function createUsageCircuit({ now = () => Date.now() } = {}) {
|
|
|
135
170
|
}
|
|
136
171
|
if (currentState === 'closed' && consecutiveFailures >= 3) {
|
|
137
172
|
currentState = 'open';
|
|
173
|
+
openedAtMs = now();
|
|
138
174
|
scheduleNextProbe();
|
|
139
175
|
}
|
|
140
176
|
}
|
|
@@ -144,9 +180,19 @@ function createUsageCircuit({ now = () => Date.now() } = {}) {
|
|
|
144
180
|
probeInFlight = false;
|
|
145
181
|
backoffBaseMs = 0;
|
|
146
182
|
currentState = 'closed';
|
|
183
|
+
openedAtMs = null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** ms timestamp this streak opened, or null while closed. */
|
|
187
|
+
function openedAt() {
|
|
188
|
+
return currentState === 'open' || currentState === 'half_open' ? openedAtMs : null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function getConsecutiveFailures() {
|
|
192
|
+
return consecutiveFailures;
|
|
147
193
|
}
|
|
148
194
|
|
|
149
|
-
return { recordSuccess, recordFailure, state };
|
|
195
|
+
return { recordSuccess, recordFailure, state, openedAt, getConsecutiveFailures };
|
|
150
196
|
}
|
|
151
197
|
|
|
152
198
|
module.exports = {
|
|
@@ -155,5 +201,6 @@ module.exports = {
|
|
|
155
201
|
isResetFresh,
|
|
156
202
|
bindingWindow,
|
|
157
203
|
degradedBudget,
|
|
204
|
+
degradedConcurrencyCap,
|
|
158
205
|
singleFlight,
|
|
159
206
|
};
|
|
@@ -4,14 +4,11 @@
|
|
|
4
4
|
// Testable without spawning the watchdog entry script.
|
|
5
5
|
|
|
6
6
|
const fs = require('node:fs');
|
|
7
|
-
const os = require('node:os');
|
|
8
7
|
const path = require('node:path');
|
|
8
|
+
const schedulerPaths = require('./schedulerPaths.cjs');
|
|
9
|
+
const { isRestartingMarkerActive } = require('./upgradeDrain.cjs');
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
// Mirrors scheduler.cjs:215 (single source of truth there; kept in sync here).
|
|
12
|
-
const DEFAULT_HEARTBEAT_PATH = path.join(
|
|
13
|
-
os.homedir(), '.claude', 'session-manager', 'scheduler-heartbeat.log',
|
|
14
|
-
);
|
|
15
12
|
|
|
16
13
|
// The in-app heartbeat ticks every 60 s; 3 missed ticks = stale.
|
|
17
14
|
const DEFAULT_MAX_AGE_MS = 180_000;
|
|
@@ -40,7 +37,7 @@ const TAIL_BYTES = 4096;
|
|
|
40
37
|
* Single source of truth for the file-read + reverse-scan logic; used by
|
|
41
38
|
* readLastHeartbeatTs() and heartbeatFresh().
|
|
42
39
|
*/
|
|
43
|
-
function readLastHeartbeat(heartbeatPath =
|
|
40
|
+
function readLastHeartbeat(heartbeatPath = schedulerPaths.heartbeatPath()) {
|
|
44
41
|
let buf;
|
|
45
42
|
try {
|
|
46
43
|
const stat = fs.statSync(heartbeatPath);
|
|
@@ -79,7 +76,7 @@ function readLastHeartbeat(heartbeatPath = DEFAULT_HEARTBEAT_PATH) {
|
|
|
79
76
|
* Returns the `ts` field (epoch ms) from the last heartbeat entry.
|
|
80
77
|
* Returns null on missing / empty / unparseable file or missing ts field.
|
|
81
78
|
*/
|
|
82
|
-
function readLastHeartbeatTs(heartbeatPath =
|
|
79
|
+
function readLastHeartbeatTs(heartbeatPath = schedulerPaths.heartbeatPath()) {
|
|
83
80
|
const entry = readLastHeartbeat(heartbeatPath);
|
|
84
81
|
return (entry !== null && typeof entry.ts === 'number') ? entry.ts : null;
|
|
85
82
|
}
|
|
@@ -88,12 +85,43 @@ function readLastHeartbeatTs(heartbeatPath = DEFAULT_HEARTBEAT_PATH) {
|
|
|
88
85
|
* heartbeatFresh(heartbeatPath?, maxAgeMs?) → boolean
|
|
89
86
|
*
|
|
90
87
|
* Returns true iff the last heartbeat ts is within maxAgeMs of `now`.
|
|
91
|
-
* Missing / empty / unparseable file → false.
|
|
88
|
+
* Missing / empty / unparseable file → false. A `degraded: true` line (a
|
|
89
|
+
* heartbeat subsystem threw — see scheduler.cjs heartbeatTick) is NOT fresh:
|
|
90
|
+
* the loop ran but could not read state, so it must not disarm the watchdog.
|
|
92
91
|
*/
|
|
93
|
-
function heartbeatFresh(heartbeatPath =
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
96
|
-
return (Date.now() - ts) < maxAgeMs;
|
|
92
|
+
function heartbeatFresh(heartbeatPath = schedulerPaths.heartbeatPath(), maxAgeMs = DEFAULT_MAX_AGE_MS) {
|
|
93
|
+
const entry = readLastHeartbeat(heartbeatPath);
|
|
94
|
+
if (entry === null || entry.degraded === true || typeof entry.ts !== 'number') return false;
|
|
95
|
+
return (Date.now() - entry.ts) < maxAgeMs;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const DEFAULT_DISPATCH_DEAD_MS = 30 * 60_000;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* evaluateDispatchLiveness(entry, now, { deadMs }?) → { dead, reason }
|
|
102
|
+
*
|
|
103
|
+
* Pure. Observability only — a logically-dead scheduler (wedged tick chain,
|
|
104
|
+
* leaked slots) still writes fresh heartbeats, so freshness alone can't see
|
|
105
|
+
* it. `dead` only when ALL hold: heartbeat fresh (not degraded, within
|
|
106
|
+
* DEFAULT_MAX_AGE_MS), dispatch.lastRunAt older than deadMs (absent/unparseable
|
|
107
|
+
* counts as older), pendingDispatchable > 0, runningCount === 0, not paused.
|
|
108
|
+
* Callers must NOT relaunch on this: the process is alive, and a relaunch
|
|
109
|
+
* would spawn a second app on top of it.
|
|
110
|
+
*/
|
|
111
|
+
function evaluateDispatchLiveness(entry, now = Date.now(), { deadMs = DEFAULT_DISPATCH_DEAD_MS } = {}) {
|
|
112
|
+
if (!entry || entry.degraded === true || typeof entry.ts !== 'number') {
|
|
113
|
+
return { dead: false, reason: 'no-fresh-heartbeat' };
|
|
114
|
+
}
|
|
115
|
+
if (now - entry.ts >= DEFAULT_MAX_AGE_MS) return { dead: false, reason: 'heartbeat-stale' };
|
|
116
|
+
const d = entry.dispatch;
|
|
117
|
+
if (!d || typeof d !== 'object') return { dead: false, reason: 'no-dispatch-field' };
|
|
118
|
+
if (d.paused) return { dead: false, reason: 'paused' };
|
|
119
|
+
if (d.drain) return { dead: false, reason: 'draining' };
|
|
120
|
+
if (!(d.pendingDispatchable > 0)) return { dead: false, reason: 'nothing-dispatchable' };
|
|
121
|
+
if (d.runningCount !== 0) return { dead: false, reason: 'jobs-running' };
|
|
122
|
+
const lastRunMs = Date.parse(d.lastRunAt ?? '');
|
|
123
|
+
if (Number.isFinite(lastRunMs) && now - lastRunMs <= deadMs) return { dead: false, reason: 'recent-dispatch' };
|
|
124
|
+
return { dead: true, reason: 'dispatch-dead' };
|
|
97
125
|
}
|
|
98
126
|
|
|
99
127
|
/**
|
|
@@ -132,12 +160,6 @@ function isPidAlive(pid) {
|
|
|
132
160
|
// 60 s by scheduler.cjs's heartbeatInterval regardless of pause state) as the
|
|
133
161
|
// liveness signal — no second heartbeat file.
|
|
134
162
|
|
|
135
|
-
const DEFAULT_RELAUNCH_STATE_PATH = path.join(
|
|
136
|
-
os.homedir(), '.claude', 'session-manager', 'watchdog-relaunch-state.json',
|
|
137
|
-
);
|
|
138
|
-
const DEFAULT_RELAUNCH_LOG_PATH = path.join(
|
|
139
|
-
os.homedir(), '.claude', 'logs', 'scheduler-watchdog-relaunch.log',
|
|
140
|
-
);
|
|
141
163
|
const DEFAULT_RELAUNCH_DEBOUNCE_MS = 90_000;
|
|
142
164
|
const DEFAULT_MAX_RELAUNCH_ATTEMPTS = 3;
|
|
143
165
|
|
|
@@ -150,7 +172,7 @@ const DEFAULT_MAX_RELAUNCH_ATTEMPTS = 3;
|
|
|
150
172
|
* rather than relaunching on top of a live process.
|
|
151
173
|
*/
|
|
152
174
|
function checkAppLiveness({
|
|
153
|
-
heartbeatPath =
|
|
175
|
+
heartbeatPath = schedulerPaths.heartbeatPath(),
|
|
154
176
|
maxAgeMs = DEFAULT_MAX_AGE_MS,
|
|
155
177
|
} = {}) {
|
|
156
178
|
if (heartbeatFresh(heartbeatPath, maxAgeMs)) {
|
|
@@ -164,7 +186,7 @@ function checkAppLiveness({
|
|
|
164
186
|
}
|
|
165
187
|
|
|
166
188
|
/** Default { lastAttemptTs: null, attemptCount: 0 } on missing/unparseable state file. */
|
|
167
|
-
function readRelaunchState(statePath =
|
|
189
|
+
function readRelaunchState(statePath = schedulerPaths.watchdogRelaunchStatePath()) {
|
|
168
190
|
try {
|
|
169
191
|
const raw = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
170
192
|
return {
|
|
@@ -203,7 +225,7 @@ function logRelaunchLine(logPath, message) {
|
|
|
203
225
|
* (short-lived) process doesn't block on the launched app and the app
|
|
204
226
|
* survives the watchdog exiting.
|
|
205
227
|
*/
|
|
206
|
-
function defaultSpawnRelaunch({ logPath =
|
|
228
|
+
function defaultSpawnRelaunch({ logPath = schedulerPaths.watchdogRelaunchLogPath() } = {}) {
|
|
207
229
|
const { spawn } = require('node:child_process');
|
|
208
230
|
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
209
231
|
const fd = fs.openSync(logPath, 'a');
|
|
@@ -236,14 +258,15 @@ function defaultSpawnRelaunch({ logPath = DEFAULT_RELAUNCH_LOG_PATH } = {}) {
|
|
|
236
258
|
* intervenes or the app comes up some other way.
|
|
237
259
|
*/
|
|
238
260
|
function maybeRelaunchApp({
|
|
239
|
-
heartbeatPath =
|
|
261
|
+
heartbeatPath = schedulerPaths.heartbeatPath(),
|
|
240
262
|
maxAgeMs = DEFAULT_MAX_AGE_MS,
|
|
241
|
-
statePath =
|
|
242
|
-
logPath =
|
|
263
|
+
statePath = schedulerPaths.watchdogRelaunchStatePath(),
|
|
264
|
+
logPath = schedulerPaths.watchdogRelaunchLogPath(),
|
|
243
265
|
debounceMs = DEFAULT_RELAUNCH_DEBOUNCE_MS,
|
|
244
266
|
maxAttempts = DEFAULT_MAX_RELAUNCH_ATTEMPTS,
|
|
245
267
|
now = Date.now(),
|
|
246
268
|
spawnFn = defaultSpawnRelaunch,
|
|
269
|
+
restartingMarkerPath = schedulerPaths.restartingMarkerPath(),
|
|
247
270
|
} = {}) {
|
|
248
271
|
const liveness = checkAppLiveness({ heartbeatPath, maxAgeMs });
|
|
249
272
|
const state = readRelaunchState(statePath);
|
|
@@ -255,6 +278,14 @@ function maybeRelaunchApp({
|
|
|
255
278
|
return { relaunched: false, reason: 'alive', attemptCount: 0 };
|
|
256
279
|
}
|
|
257
280
|
|
|
281
|
+
// A deliberate drain-restart is mid-exit: the old process is going away ON
|
|
282
|
+
// PURPOSE and its successor is booting. Relaunching now would race the
|
|
283
|
+
// single-instance lock. The marker's lifetime is bounded, so a restart that
|
|
284
|
+
// never comes up is picked up again once it expires.
|
|
285
|
+
if (isRestartingMarkerActive({ file: restartingMarkerPath, now })) {
|
|
286
|
+
return { relaunched: false, reason: 'restarting', attemptCount: state.attemptCount };
|
|
287
|
+
}
|
|
288
|
+
|
|
258
289
|
if (state.attemptCount >= maxAttempts) {
|
|
259
290
|
logRelaunchLine(
|
|
260
291
|
logPath,
|
|
@@ -286,12 +317,6 @@ function maybeRelaunchApp({
|
|
|
286
317
|
// walk/persist logic — this is just the once-per-day scheduling + lock
|
|
287
318
|
// wrapper around it, tailored to being invoked repeatedly by a systemd timer.
|
|
288
319
|
|
|
289
|
-
const DEFAULT_STAMP_PATH = path.join(
|
|
290
|
-
os.homedir(), '.claude', 'session-manager', 'history-rollup.stamp',
|
|
291
|
-
);
|
|
292
|
-
const DEFAULT_LOCK_PATH = path.join(
|
|
293
|
-
os.homedir(), '.claude', 'session-manager', 'history-rollup.lock',
|
|
294
|
-
);
|
|
295
320
|
const DEFAULT_LOCK_STALE_MS = 10 * 60 * 1000; // 10 min
|
|
296
321
|
const DEFAULT_FINALIZE_BUDGET_MS = 60_000;
|
|
297
322
|
|
|
@@ -384,8 +409,8 @@ function defaultFinalizeClosedDays(opts) {
|
|
|
384
409
|
* finalizeFn — injectable finalizeClosedDays for testing
|
|
385
410
|
*/
|
|
386
411
|
async function maybeFinalizeHistory({
|
|
387
|
-
stampPath =
|
|
388
|
-
lockPath =
|
|
412
|
+
stampPath = schedulerPaths.historyRollupStampPath(),
|
|
413
|
+
lockPath = schedulerPaths.historyRollupLockPath(),
|
|
389
414
|
staleLockMs = DEFAULT_LOCK_STALE_MS,
|
|
390
415
|
budgetMs = DEFAULT_FINALIZE_BUDGET_MS,
|
|
391
416
|
dryRun = process.env.SM_WATCHDOG_DRYRUN === '1',
|
|
@@ -423,6 +448,7 @@ module.exports = {
|
|
|
423
448
|
readLastHeartbeat,
|
|
424
449
|
readLastHeartbeatTs,
|
|
425
450
|
heartbeatFresh,
|
|
451
|
+
evaluateDispatchLiveness,
|
|
426
452
|
isPidAlive,
|
|
427
453
|
localDateStr,
|
|
428
454
|
maybeFinalizeHistory,
|
|
@@ -433,14 +459,21 @@ module.exports = {
|
|
|
433
459
|
writeRelaunchState,
|
|
434
460
|
defaultSpawnRelaunch,
|
|
435
461
|
maybeRelaunchApp,
|
|
436
|
-
DEFAULT_HEARTBEAT_PATH,
|
|
437
462
|
DEFAULT_MAX_AGE_MS,
|
|
438
|
-
|
|
439
|
-
DEFAULT_LOCK_PATH,
|
|
463
|
+
DEFAULT_DISPATCH_DEAD_MS,
|
|
440
464
|
DEFAULT_LOCK_STALE_MS,
|
|
441
465
|
DEFAULT_FINALIZE_BUDGET_MS,
|
|
442
|
-
DEFAULT_RELAUNCH_STATE_PATH,
|
|
443
|
-
DEFAULT_RELAUNCH_LOG_PATH,
|
|
444
466
|
DEFAULT_RELAUNCH_DEBOUNCE_MS,
|
|
445
467
|
DEFAULT_MAX_RELAUNCH_ATTEMPTS,
|
|
446
468
|
};
|
|
469
|
+
|
|
470
|
+
// Lazy default-path getters (SM_SCHEDULER_HOME resolved at read, never at require).
|
|
471
|
+
for (const [name, resolve] of [
|
|
472
|
+
['DEFAULT_HEARTBEAT_PATH', schedulerPaths.heartbeatPath],
|
|
473
|
+
['DEFAULT_STAMP_PATH', schedulerPaths.historyRollupStampPath],
|
|
474
|
+
['DEFAULT_LOCK_PATH', schedulerPaths.historyRollupLockPath],
|
|
475
|
+
['DEFAULT_RELAUNCH_STATE_PATH', schedulerPaths.watchdogRelaunchStatePath],
|
|
476
|
+
['DEFAULT_RELAUNCH_LOG_PATH', schedulerPaths.watchdogRelaunchLogPath],
|
|
477
|
+
]) {
|
|
478
|
+
Object.defineProperty(module.exports, name, { get: resolve, enumerable: true });
|
|
479
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* withTimeout.cjs — bound an async body with a wall-clock budget.
|
|
3
|
+
*
|
|
4
|
+
* `withTimeout(promiseFactory, ms, onTimeout)` starts `promiseFactory()` and
|
|
5
|
+
* resolves with its result. If it has not settled after `ms`, `onTimeout()`
|
|
6
|
+
* is called and ITS return value becomes the resolved value; the original
|
|
7
|
+
* promise is abandoned (never cancelled — callers that must neutralise a
|
|
8
|
+
* late-resuming body do so with their own generation fence). The timer is
|
|
9
|
+
* always cleared on settle, and unref'd so it can never hold the process open.
|
|
10
|
+
* `ms <= 0` (or non-finite) disables the bound entirely.
|
|
11
|
+
*
|
|
12
|
+
* Plain Node module (no Electron deps).
|
|
13
|
+
*/
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
function withTimeout(promiseFactory, ms, onTimeout) {
|
|
17
|
+
if (!Number.isFinite(ms) || ms <= 0) return Promise.resolve().then(promiseFactory);
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
let done = false;
|
|
20
|
+
const timer = setTimeout(() => {
|
|
21
|
+
if (done) return;
|
|
22
|
+
done = true;
|
|
23
|
+
try { resolve(onTimeout()); } catch (e) { reject(e); }
|
|
24
|
+
}, ms);
|
|
25
|
+
if (typeof timer.unref === 'function') timer.unref();
|
|
26
|
+
Promise.resolve().then(promiseFactory).then(
|
|
27
|
+
(v) => { if (done) return; done = true; clearTimeout(timer); resolve(v); },
|
|
28
|
+
(e) => { if (done) return; done = true; clearTimeout(timer); reject(e); },
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = { withTimeout };
|
package/src/main/mcpStatus.cjs
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const { spawn } = require('node:child_process');
|
|
13
|
-
const { resolveClaudeBin } = require('./lib/claudeBin.cjs');
|
|
13
|
+
const { resolveClaudeBin, claudeSpawnTarget } = require('./lib/claudeBin.cjs');
|
|
14
|
+
const { withProcRole } = require('./lib/cleanEnv.cjs');
|
|
14
15
|
|
|
15
16
|
const PROBE_TIMEOUT_MS = 30_000;
|
|
16
17
|
|
|
@@ -56,7 +57,8 @@ function runProbe() {
|
|
|
56
57
|
}
|
|
57
58
|
let child;
|
|
58
59
|
try {
|
|
59
|
-
|
|
60
|
+
const target = claudeSpawnTarget('aux', 'mcp-list', bin);
|
|
61
|
+
child = spawn(target.command, ['mcp', 'list'], { env: withProcRole(process.env, 'aux'), stdio: ['ignore', 'pipe', 'pipe'], ...(target.argv0 ? { argv0: target.argv0 } : {}) });
|
|
60
62
|
} catch (e) {
|
|
61
63
|
resolve({ ok: false, servers: [], error: e?.message || 'spawn error', checkedAt: Date.now() });
|
|
62
64
|
return;
|
|
@@ -31,7 +31,7 @@ const path = require('node:path');
|
|
|
31
31
|
const os = require('node:os');
|
|
32
32
|
const fs = require('node:fs');
|
|
33
33
|
const { cleanChildEnv, pathWithUserBins } = require('./lib/cleanEnv.cjs');
|
|
34
|
-
const { resolveClaudeBin } = require('./lib/claudeBin.cjs');
|
|
34
|
+
const { resolveClaudeBin, claudeSpawnTarget } = require('./lib/claudeBin.cjs');
|
|
35
35
|
const { sendIfAlive } = require('./lib/sendToRenderer.cjs');
|
|
36
36
|
const { schemas } = require('./ipcSchemas.cjs');
|
|
37
37
|
|
|
@@ -88,9 +88,13 @@ function runStep({ slug, args, register, unregister }) {
|
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
const claudeBin = resolveClaudeBin();
|
|
91
|
+
// node-pty has NO `argv0` option, so the alias symlink is the only naming
|
|
92
|
+
// mechanism here — the comm is set, argv0 stays the alias path (which still
|
|
93
|
+
// contains the word `claude`). Do not try to pass argv0.
|
|
94
|
+
const { command } = claudeSpawnTarget('aux', 'plugin', claudeBin);
|
|
91
95
|
let proc;
|
|
92
96
|
try {
|
|
93
|
-
proc = pty.spawn(
|
|
97
|
+
proc = pty.spawn(command, args, {
|
|
94
98
|
name: 'xterm-256color',
|
|
95
99
|
cols: 120,
|
|
96
100
|
rows: 30,
|