@adhdev/daemon-core 0.9.82-rc.43 → 0.9.82-rc.431
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/dist/boot/daemon-lifecycle.d.ts +9 -0
- package/dist/boot/process-hardening.d.ts +50 -0
- package/dist/build-info.d.ts +37 -0
- package/dist/chat/source-machine.d.ts +166 -0
- package/dist/chat/source-resolver.d.ts +104 -0
- package/dist/chat/subscription-updates.d.ts +1 -0
- package/dist/cli-adapter-types.d.ts +68 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +200 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +126 -64
- package/dist/cli-adapters/provider-cli-parse.d.ts +5 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +74 -0
- package/dist/cli-adapters/pty-write-chunking.d.ts +34 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/cli-adapters/resolve-executable.d.ts +69 -0
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
- package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
- package/dist/cli-adapters/terminal-screen.d.ts +4 -11
- package/dist/commands/chat-commands-debug-bundle.d.ts +14 -0
- package/dist/commands/chat-commands-read.d.ts +7 -0
- package/dist/commands/chat-commands-scope.d.ts +39 -0
- package/dist/commands/chat-commands-shared.d.ts +33 -0
- package/dist/commands/chat-commands-write.d.ts +14 -0
- package/dist/commands/chat-commands.d.ts +10 -23
- package/dist/commands/cli-manager.d.ts +15 -1
- package/dist/commands/handler.d.ts +125 -0
- package/dist/commands/high-family/index.d.ts +3 -0
- package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
- package/dist/commands/high-family/mesh-events.d.ts +2 -0
- package/dist/commands/high-family/mesh-status.d.ts +2 -0
- package/dist/commands/high-family/types.d.ts +60 -0
- package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
- package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
- package/dist/commands/low-family/diagnostics.d.ts +2 -0
- package/dist/commands/low-family/index.d.ts +3 -0
- package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
- package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
- package/dist/commands/low-family/notification.d.ts +2 -0
- package/dist/commands/low-family/refine-config.d.ts +2 -0
- package/dist/commands/low-family/session-host.d.ts +2 -0
- package/dist/commands/low-family/spec-providerdev.d.ts +11 -0
- package/dist/commands/low-family/status-meta.d.ts +2 -0
- package/dist/commands/low-family/types.d.ts +33 -0
- package/dist/commands/med-family/cli-agent.d.ts +2 -0
- package/dist/commands/med-family/fast-forward.d.ts +2 -0
- package/dist/commands/med-family/ide.d.ts +10 -0
- package/dist/commands/med-family/index.d.ts +3 -0
- package/dist/commands/med-family/mesh-crud.d.ts +29 -0
- package/dist/commands/med-family/mesh-host-pairing.d.ts +2 -0
- package/dist/commands/med-family/mesh-queue.d.ts +2 -0
- package/dist/commands/med-family/mesh-restart.d.ts +2 -0
- package/dist/commands/med-family/types.d.ts +142 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router.d.ts +276 -2
- package/dist/commands/upgrade-helper.d.ts +41 -1
- package/dist/config/chat-history.d.ts +9 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/config/mesh-config.d.ts +100 -1
- package/dist/config/mesh-json-config.d.ts +199 -0
- package/dist/config/repo-settings.d.ts +77 -0
- package/dist/daemon/dev-server.d.ts +0 -2
- package/dist/detection/ide-detector.d.ts +13 -0
- package/dist/detection/win32-ide-version.d.ts +37 -0
- package/dist/git/change-impact-config.d.ts +159 -0
- package/dist/git/git-commands.d.ts +11 -1
- package/dist/git/git-diff.d.ts +6 -0
- package/dist/git/git-executor.d.ts +11 -0
- package/dist/git/git-status.d.ts +57 -0
- package/dist/git/git-types.d.ts +2 -50
- package/dist/git/git-worktree.d.ts +71 -1
- package/dist/git/index.d.ts +3 -1
- package/dist/index.d.ts +64 -14
- package/dist/index.js +49391 -19228
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +48574 -18570
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +1 -4
- package/dist/ipc/local-ipc-server.d.ts +91 -0
- package/dist/launch.d.ts +1 -1
- package/dist/logging/async-batch-writer.d.ts +10 -0
- package/dist/logging/log-redactor.d.ts +24 -0
- package/dist/logging/log-tail-reader.d.ts +81 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/mesh/contracts.d.ts +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +89 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +174 -0
- package/dist/mesh/mesh-clone-grace.d.ts +8 -0
- package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
- package/dist/mesh/mesh-event-classify.d.ts +5 -0
- package/dist/mesh/mesh-event-forwarding.d.ts +41 -0
- package/dist/mesh/mesh-event-trace.d.ts +21 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +4 -0
- package/dist/mesh/mesh-events-pending.d.ts +69 -0
- package/dist/mesh/mesh-events-stale.d.ts +61 -0
- package/dist/mesh/mesh-events-utils.d.ts +75 -0
- package/dist/mesh/mesh-events.d.ts +6 -49
- package/dist/mesh/mesh-fast-forward.d.ts +81 -0
- package/dist/mesh/mesh-host-ownership.d.ts +9 -0
- package/dist/mesh/mesh-init.d.ts +86 -0
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
- package/dist/mesh/mesh-ledger.d.ts +77 -1
- package/dist/mesh/mesh-magi-status.d.ts +63 -0
- package/dist/mesh/mesh-missions.d.ts +189 -0
- package/dist/mesh/mesh-node-identity.d.ts +289 -0
- package/dist/mesh/mesh-queue-assignment.d.ts +113 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +65 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -0
- package/dist/mesh/mesh-refine-gates.d.ts +428 -0
- package/dist/mesh/mesh-refine-status.d.ts +62 -0
- package/dist/mesh/mesh-review-inbox.d.ts +90 -0
- package/dist/mesh/mesh-routing.d.ts +70 -0
- package/dist/mesh/mesh-runtime-store.d.ts +450 -0
- package/dist/mesh/mesh-scheduling-runtime.d.ts +78 -0
- package/dist/mesh/mesh-task-inflight.d.ts +46 -0
- package/dist/mesh/mesh-task-stats.d.ts +49 -0
- package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
- package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
- package/dist/mesh/mesh-work-queue.d.ts +290 -5
- package/dist/mesh/preview-freshness.d.ts +18 -0
- package/dist/mesh/refine-config.d.ts +216 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +145 -0
- package/dist/providers/acp-provider-instance.d.ts +5 -0
- package/dist/providers/approval-utils.d.ts +20 -0
- package/dist/providers/chat-message-normalization.d.ts +31 -1
- package/dist/providers/cli-provider-instance.d.ts +221 -3
- package/dist/providers/contracts.d.ts +139 -6
- package/dist/providers/external-sources.d.ts +71 -0
- package/dist/providers/manual-attendance.d.ts +63 -0
- package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
- package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
- package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
- package/dist/providers/native-history/constants.d.ts +12 -0
- package/dist/providers/native-history/dispatcher.d.ts +27 -0
- package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
- package/dist/providers/native-history/index.d.ts +13 -0
- package/dist/providers/provider-instance-manager.d.ts +29 -0
- package/dist/providers/provider-instance.d.ts +23 -1
- package/dist/providers/provider-loader.d.ts +26 -4
- package/dist/providers/provider-trust.d.ts +31 -0
- package/dist/providers/read-chat-contract.d.ts +29 -0
- package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
- package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
- package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
- package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
- package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
- package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
- package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
- package/dist/providers/sdk/v1/index.d.ts +30 -0
- package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
- package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
- package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
- package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
- package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
- package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
- package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
- package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
- package/dist/providers/spec/adapter.d.ts +91 -0
- package/dist/providers/spec/cli-adapter.d.ts +223 -0
- package/dist/providers/spec/evaluator.d.ts +45 -0
- package/dist/providers/spec/fsm-driver.d.ts +422 -0
- package/dist/providers/spec/fsm-evaluator.d.ts +76 -0
- package/dist/providers/spec/fsm-loader.d.ts +14 -0
- package/dist/providers/spec/fsm-types.d.ts +174 -0
- package/dist/providers/spec/native-history-executor.d.ts +41 -0
- package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
- package/dist/providers/spec/route.d.ts +4 -0
- package/dist/providers/spec/types.d.ts +222 -0
- package/dist/providers/status-monitor.d.ts +7 -7
- package/dist/providers/transcript-v2.d.ts +176 -0
- package/dist/providers/types/interactive-prompt.d.ts +84 -0
- package/dist/providers/working-dir.d.ts +17 -0
- package/dist/repo-mesh-types.d.ts +501 -13
- package/dist/runtime-defaults.d.ts +2 -0
- package/dist/sessions/registry.d.ts +6 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +59 -2
- package/dist/status/normalize.d.ts +1 -1
- package/dist/status/normalize.js +1 -0
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +1 -0
- package/dist/status/normalize.mjs.map +1 -1
- package/dist/status/reporter.d.ts +2 -0
- package/dist/status/snapshot.d.ts +26 -0
- package/dist/system/hash.d.ts +8 -0
- package/dist/system/load-better-sqlite3.d.ts +21 -0
- package/dist/types.d.ts +5 -0
- package/package.json +7 -3
- package/src/agent-stream/poller.ts +2 -3
- package/src/agent-stream/provider-adapter.ts +1 -1
- package/src/boot/daemon-lifecycle.ts +63 -12
- package/src/boot/process-hardening.ts +89 -0
- package/src/build-info.ts +73 -0
- package/src/chat/source-machine.ts +534 -0
- package/src/chat/source-resolver.ts +0 -0
- package/src/chat/subscription-updates.ts +20 -1
- package/src/cli-adapter-types.d.ts +3 -1
- package/src/cli-adapter-types.ts +68 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1246 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +914 -1144
- package/src/cli-adapters/provider-cli-parse.d.ts +2 -0
- package/src/cli-adapters/provider-cli-parse.ts +19 -0
- package/src/cli-adapters/provider-cli-runtime.ts +56 -7
- package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
- package/src/cli-adapters/provider-cli-shared.ts +121 -11
- package/src/cli-adapters/pty-transport.ts +2 -1
- package/src/cli-adapters/pty-write-chunking.ts +106 -0
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/resolve-executable.ts +204 -0
- package/src/cli-adapters/session-host-transport.ts +2 -1
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +63 -29
- package/src/cli-adapters/terminal-backends/types.ts +10 -3
- package/src/cli-adapters/terminal-screen.ts +16 -81
- package/src/commands/WINDOWS-UPGRADE-LOCK-FAILURE.md +198 -0
- package/src/commands/chat-commands-debug-bundle.ts +398 -0
- package/src/commands/chat-commands-read.ts +2327 -0
- package/src/commands/chat-commands-scope.ts +54 -0
- package/src/commands/chat-commands-shared.ts +114 -0
- package/src/commands/chat-commands-write.ts +891 -0
- package/src/commands/chat-commands.ts +19 -1841
- package/src/commands/cli-manager.ts +544 -26
- package/src/commands/handler.ts +841 -2
- package/src/commands/high-family/index.ts +28 -0
- package/src/commands/high-family/mesh-coordinator-launch.ts +678 -0
- package/src/commands/high-family/mesh-events.ts +80 -0
- package/src/commands/high-family/mesh-status.ts +710 -0
- package/src/commands/high-family/types.ts +76 -0
- package/src/commands/low-family/coordinator-prompt.ts +72 -0
- package/src/commands/low-family/daemon-lifecycle.ts +107 -0
- package/src/commands/low-family/diagnostics.ts +57 -0
- package/src/commands/low-family/index.ts +37 -0
- package/src/commands/low-family/mesh-ledger.ts +62 -0
- package/src/commands/low-family/mesh-node-logs.ts +87 -0
- package/src/commands/low-family/notification.ts +116 -0
- package/src/commands/low-family/refine-config.ts +106 -0
- package/src/commands/low-family/session-host.ts +274 -0
- package/src/commands/low-family/spec-providerdev.ts +217 -0
- package/src/commands/low-family/status-meta.ts +112 -0
- package/src/commands/low-family/types.ts +39 -0
- package/src/commands/med-family/cli-agent.ts +238 -0
- package/src/commands/med-family/fast-forward.ts +230 -0
- package/src/commands/med-family/ide.ts +163 -0
- package/src/commands/med-family/index.ts +37 -0
- package/src/commands/med-family/mesh-crud.ts +1066 -0
- package/src/commands/med-family/mesh-host-pairing.ts +234 -0
- package/src/commands/med-family/mesh-queue.ts +167 -0
- package/src/commands/med-family/mesh-restart.ts +92 -0
- package/src/commands/med-family/types.ts +143 -0
- package/src/commands/mesh-coordinator.ts +334 -124
- package/src/commands/router.ts +2711 -3254
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +310 -45
- package/src/config/chat-history.ts +483 -24
- package/src/config/config.ts +12 -0
- package/src/config/mesh-config.ts +495 -22
- package/src/config/mesh-json-config.ts +376 -0
- package/src/config/recent-activity.ts +8 -2
- package/src/config/repo-settings.ts +111 -0
- package/src/daemon/dev-auto-implement.ts +3 -2
- package/src/daemon/dev-cli-debug.ts +10 -1
- package/src/daemon/dev-server.ts +0 -541
- package/src/detection/cli-detector.ts +28 -9
- package/src/detection/ide-detector.ts +55 -16
- package/src/detection/win32-ide-version.ts +106 -0
- package/src/git/change-impact-config.ts +354 -0
- package/src/git/git-commands.ts +59 -15
- package/src/git/git-diff.ts +81 -11
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +767 -48
- package/src/git/git-types.ts +14 -62
- package/src/git/git-worktree.ts +261 -4
- package/src/git/index.ts +17 -0
- package/src/index.ts +194 -12
- package/src/installer.d.ts +1 -1
- package/src/installer.ts +8 -6
- package/src/ipc/local-ipc-server.ts +278 -0
- package/src/launch.d.ts +1 -1
- package/src/launch.ts +37 -28
- package/src/logging/async-batch-writer.ts +55 -0
- package/src/logging/command-log.ts +7 -5
- package/src/logging/log-redactor.ts +100 -0
- package/src/logging/log-tail-reader.ts +341 -0
- package/src/logging/logger.ts +14 -7
- package/src/mesh/contracts.ts +338 -0
- package/src/mesh/coordinator-prompt.ts +381 -33
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +645 -0
- package/src/mesh/mesh-clone-grace.ts +68 -0
- package/src/mesh/mesh-coordinator-config.ts +97 -0
- package/src/mesh/mesh-delivery-policy.ts +315 -0
- package/src/mesh/mesh-event-classify.ts +51 -0
- package/src/mesh/mesh-event-forwarding.ts +1888 -0
- package/src/mesh/mesh-event-trace.ts +67 -0
- package/src/mesh/mesh-events-coordinator.ts +32 -0
- package/src/mesh/mesh-events-pending.ts +656 -0
- package/src/mesh/mesh-events-stale.ts +389 -0
- package/src/mesh/mesh-events-utils.ts +443 -0
- package/src/mesh/mesh-events.ts +33 -1035
- package/src/mesh/mesh-fast-forward.ts +843 -0
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-init.ts +260 -0
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
- package/src/mesh/mesh-ledger.ts +656 -102
- package/src/mesh/mesh-magi-status.ts +223 -0
- package/src/mesh/mesh-missions.ts +449 -0
- package/src/mesh/mesh-node-identity.ts +1887 -0
- package/src/mesh/mesh-queue-assignment.ts +1918 -0
- package/src/mesh/mesh-reconcile-loop.ts +1780 -0
- package/src/mesh/mesh-refine-batch.ts +205 -0
- package/src/mesh/mesh-refine-gates.ts +1673 -0
- package/src/mesh/mesh-refine-status.ts +231 -0
- package/src/mesh/mesh-review-inbox.ts +307 -0
- package/src/mesh/mesh-routing.ts +291 -0
- package/src/mesh/mesh-runtime-store.ts +1853 -0
- package/src/mesh/mesh-scheduling-runtime.ts +198 -0
- package/src/mesh/mesh-task-inflight.ts +70 -0
- package/src/mesh/mesh-task-stats.ts +161 -0
- package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
- package/src/mesh/mesh-warmup-deadline.ts +152 -0
- package/src/mesh/mesh-work-queue.ts +1243 -141
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +423 -0
- package/src/mesh/worktree-bootstrap-config.ts +450 -0
- package/src/providers/acp-provider-instance.ts +43 -10
- package/src/providers/approval-utils.d.ts +5 -0
- package/src/providers/approval-utils.ts +57 -5
- package/src/providers/chat-message-normalization.ts +92 -4
- package/src/providers/cli-provider-instance.ts +1933 -104
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +150 -6
- package/src/providers/extension-provider-instance.ts +12 -7
- package/src/providers/external-sources.ts +218 -0
- package/src/providers/ide-provider-instance.ts +35 -12
- package/src/providers/manual-attendance.ts +85 -0
- package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
- package/src/providers/native-history/claude-cli-transcript.ts +396 -0
- package/src/providers/native-history/codex-cli-transcript.ts +479 -0
- package/src/providers/native-history/constants.ts +19 -0
- package/src/providers/native-history/dispatcher.ts +339 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
- package/src/providers/native-history/index.ts +30 -0
- package/src/providers/provider-instance-manager.ts +71 -0
- package/src/providers/provider-instance.ts +19 -1
- package/src/providers/provider-loader.ts +668 -50
- package/src/providers/provider-schema.ts +87 -14
- package/src/providers/provider-trust.ts +114 -0
- package/src/providers/read-chat-contract.ts +76 -16
- package/src/providers/sdk/README.md +49 -0
- package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
- package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
- package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
- package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
- package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
- package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
- package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
- package/src/providers/sdk/v1/index.ts +152 -0
- package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
- package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
- package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
- package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
- package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
- package/src/providers/sdk/v1/types/cli/index.ts +365 -0
- package/src/providers/sdk/v1/types/common/index.ts +229 -0
- package/src/providers/sdk/v1/validators/index.ts +19 -0
- package/src/providers/sdk/v1/validators/manifest.ts +110 -0
- package/src/providers/sdk/v1/validators/taint.ts +309 -0
- package/src/providers/spec/adapter.ts +235 -0
- package/src/providers/spec/cli-adapter.ts +1056 -0
- package/src/providers/spec/evaluator.ts +407 -0
- package/src/providers/spec/fsm-driver.ts +1410 -0
- package/src/providers/spec/fsm-evaluator.ts +272 -0
- package/src/providers/spec/fsm-loader.ts +120 -0
- package/src/providers/spec/fsm-types.ts +273 -0
- package/src/providers/spec/native-history-executor.ts +1128 -0
- package/src/providers/spec/pre-launch-trust.ts +104 -0
- package/src/providers/spec/route.ts +51 -0
- package/src/providers/spec/types.ts +262 -0
- package/src/providers/status-monitor.d.ts +7 -7
- package/src/providers/status-monitor.ts +37 -22
- package/src/providers/transcript-v2.ts +567 -0
- package/src/providers/types/interactive-prompt.ts +536 -0
- package/src/providers/version-archive.ts +64 -24
- package/src/providers/working-dir.ts +23 -0
- package/src/repo-mesh-types.ts +740 -14
- package/src/runtime-defaults.ts +39 -0
- package/src/sessions/registry.ts +6 -0
- package/src/shared-types-extra.ts +2 -4
- package/src/shared-types.d.ts +8 -0
- package/src/shared-types.ts +64 -1
- package/src/status/builders.ts +26 -6
- package/src/status/normalize.ts +2 -0
- package/src/status/reporter.ts +19 -1
- package/src/status/snapshot.ts +95 -26
- package/src/system/hash.ts +23 -0
- package/src/system/host-memory.ts +29 -12
- package/src/system/load-better-sqlite3.ts +68 -0
- package/src/types.ts +5 -0
- package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
- package/dist/mesh/mesh-sync.d.ts +0 -53
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
- package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
- package/src/mesh/mesh-sync.ts +0 -111
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
10
10
|
import { join } from 'path';
|
|
11
|
-
import { randomUUID } from 'crypto';
|
|
11
|
+
import { randomBytes, randomUUID } from 'crypto';
|
|
12
|
+
import { shortHash } from '../system/hash.js';
|
|
12
13
|
import { getConfigDir } from './config.js';
|
|
13
14
|
import type {
|
|
14
15
|
LocalMeshConfig,
|
|
@@ -18,8 +19,12 @@ import type {
|
|
|
18
19
|
RepoMeshNodePolicy,
|
|
19
20
|
RepoMeshNodeCapabilities,
|
|
20
21
|
RepoMeshCoordinatorConfig,
|
|
22
|
+
RepoMeshHostMetadata,
|
|
23
|
+
RepoMeshDaemonRole,
|
|
21
24
|
} from '../repo-mesh-types.js';
|
|
22
|
-
import {
|
|
25
|
+
import type { MagiPanel, MagiPanelMember, MagiPanelDefaultKind } from '@adhdev/mesh-shared';
|
|
26
|
+
import { mergeAndNormalizePolicy } from '../repo-mesh-types.js';
|
|
27
|
+
import { createDefaultMeshHostMetadata } from '../mesh/mesh-host-ownership.js';
|
|
23
28
|
|
|
24
29
|
// ─── Persistence ────────────────────────────────
|
|
25
30
|
|
|
@@ -33,12 +38,85 @@ function loadMeshConfig(): LocalMeshConfig {
|
|
|
33
38
|
try {
|
|
34
39
|
const raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
35
40
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
36
|
-
|
|
41
|
+
const config = raw as LocalMeshConfig;
|
|
42
|
+
const migrated = migrateLoadedMeshConfig(config);
|
|
43
|
+
// Persist eagerly when the on-load migration changed anything, so the
|
|
44
|
+
// dead field is gone from disk even on a pure-read path (mesh_status /
|
|
45
|
+
// mesh_list_nodes) that never otherwise mutates the config. Best-effort:
|
|
46
|
+
// a write failure (e.g. read-only fs) must not break reads, so swallow.
|
|
47
|
+
if (migrated) {
|
|
48
|
+
try {
|
|
49
|
+
saveMeshConfig(config);
|
|
50
|
+
} catch {
|
|
51
|
+
// keep the in-memory strip; disk converges on the next mutating op
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return config;
|
|
37
55
|
} catch {
|
|
38
56
|
return { meshes: [] };
|
|
39
57
|
}
|
|
40
58
|
}
|
|
41
59
|
|
|
60
|
+
/**
|
|
61
|
+
* In-place migration applied to every loaded meshes.json. Strips data that
|
|
62
|
+
* outlived the feature that wrote it so the persisted config converges on the
|
|
63
|
+
* current schema the next time it is saved.
|
|
64
|
+
*
|
|
65
|
+
* Currently: drops the dead `role` field from each node policy's providerRoles
|
|
66
|
+
* entries. providerRoles is retained for its `maxParallel` per-(node, provider)
|
|
67
|
+
* cap, but the routing `role` was removed (routing is governed solely by
|
|
68
|
+
* required_tags). A meshes.json written before the removal still carries
|
|
69
|
+
* `role: "validator"` etc.; this drops it on load so mesh_status / mesh_list_nodes
|
|
70
|
+
* never surface the dead field and the next saveMeshConfig() persists it gone.
|
|
71
|
+
*
|
|
72
|
+
* Returns true when the config was mutated (caller may persist eagerly).
|
|
73
|
+
*/
|
|
74
|
+
function migrateLoadedMeshConfig(config: LocalMeshConfig): boolean {
|
|
75
|
+
let changed = false;
|
|
76
|
+
for (const mesh of config.meshes) {
|
|
77
|
+
if (!mesh || !Array.isArray(mesh.nodes)) continue;
|
|
78
|
+
for (const node of mesh.nodes) {
|
|
79
|
+
if (stripDeadRoleFromProviderRoles(node?.policy)) changed = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return changed;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Drop the legacy `role` field from each providerRoles entry of a node policy,
|
|
87
|
+
* in place. Keeps providerType + maxParallel (the still-meaningful per-(node,
|
|
88
|
+
* provider) cap). Defensive against malformed entries — non-object items are
|
|
89
|
+
* left untouched. Returns true when at least one `role` field was removed.
|
|
90
|
+
*/
|
|
91
|
+
function stripDeadRoleFromProviderRoles(policy: unknown): boolean {
|
|
92
|
+
if (!policy || typeof policy !== 'object') return false;
|
|
93
|
+
const roles = (policy as { providerRoles?: unknown }).providerRoles;
|
|
94
|
+
if (!Array.isArray(roles)) return false;
|
|
95
|
+
let changed = false;
|
|
96
|
+
for (const entry of roles) {
|
|
97
|
+
if (entry && typeof entry === 'object' && !Array.isArray(entry)
|
|
98
|
+
&& Object.prototype.hasOwnProperty.call(entry, 'role')) {
|
|
99
|
+
delete (entry as Record<string, unknown>).role;
|
|
100
|
+
changed = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return changed;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function normalizeCapabilityTags(value: unknown): string[] | undefined {
|
|
107
|
+
if (!Array.isArray(value)) return undefined;
|
|
108
|
+
const seen = new Set<string>();
|
|
109
|
+
const tags = value
|
|
110
|
+
.map(tag => typeof tag === 'string' ? tag.trim() : '')
|
|
111
|
+
.filter(Boolean)
|
|
112
|
+
.filter(tag => {
|
|
113
|
+
if (seen.has(tag)) return false;
|
|
114
|
+
seen.add(tag);
|
|
115
|
+
return true;
|
|
116
|
+
});
|
|
117
|
+
return tags.length ? tags : undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
42
120
|
function saveMeshConfig(config: LocalMeshConfig): void {
|
|
43
121
|
const path = getMeshConfigPath();
|
|
44
122
|
writeFileSync(path, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
@@ -74,24 +152,11 @@ export function normalizeRepoIdentity(remoteUrl: string): string {
|
|
|
74
152
|
|
|
75
153
|
// ─── CRUD Operations ────────────────────────────
|
|
76
154
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!['block', 'warn', 'checkpoint_then_continue'].includes(policy.dirtyWorkspaceBehavior)) {
|
|
83
|
-
policy.dirtyWorkspaceBehavior = 'warn';
|
|
84
|
-
}
|
|
85
|
-
const maxParallelTasks = Number(policy.maxParallelTasks);
|
|
86
|
-
policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
|
|
87
|
-
if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
|
|
88
|
-
policy.sessionCleanupOnNodeRemove = 'preserve';
|
|
89
|
-
}
|
|
90
|
-
if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
|
|
91
|
-
policy.spawnedSessionVisibility = 'visible';
|
|
92
|
-
}
|
|
93
|
-
return policy;
|
|
94
|
-
}
|
|
155
|
+
// Single source of truth for default+merge+per-field normalization is
|
|
156
|
+
// mergeAndNormalizePolicy in repo-mesh-types.ts. This thin alias keeps the local
|
|
157
|
+
// call sites (createMesh/updateMesh) reading naturally while ensuring config
|
|
158
|
+
// writes go through the exact same normalizer the scheduler/display paths use.
|
|
159
|
+
const mergeMeshPolicy = mergeAndNormalizePolicy;
|
|
95
160
|
|
|
96
161
|
export function listMeshes(): LocalMeshEntry[] {
|
|
97
162
|
return loadMeshConfig().meshes;
|
|
@@ -112,6 +177,7 @@ export interface CreateMeshOptions {
|
|
|
112
177
|
defaultBranch?: string;
|
|
113
178
|
policy?: Partial<RepoMeshPolicy>;
|
|
114
179
|
coordinator?: RepoMeshCoordinatorConfig;
|
|
180
|
+
meshHost?: RepoMeshHostMetadata;
|
|
115
181
|
}
|
|
116
182
|
|
|
117
183
|
export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
|
|
@@ -133,6 +199,7 @@ export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
|
|
|
133
199
|
defaultBranch: opts.defaultBranch,
|
|
134
200
|
policy: mergeMeshPolicy(undefined, opts.policy),
|
|
135
201
|
coordinator: opts.coordinator || {},
|
|
202
|
+
meshHost: opts.meshHost || createDefaultMeshHostMetadata(),
|
|
136
203
|
nodes: [],
|
|
137
204
|
createdAt: now,
|
|
138
205
|
updatedAt: now,
|
|
@@ -148,6 +215,7 @@ export interface UpdateMeshOptions {
|
|
|
148
215
|
defaultBranch?: string;
|
|
149
216
|
policy?: Partial<RepoMeshPolicy>;
|
|
150
217
|
coordinator?: RepoMeshCoordinatorConfig;
|
|
218
|
+
meshHost?: RepoMeshHostMetadata;
|
|
151
219
|
}
|
|
152
220
|
|
|
153
221
|
export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEntry | undefined {
|
|
@@ -159,6 +227,7 @@ export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEn
|
|
|
159
227
|
if (opts.defaultBranch !== undefined) mesh.defaultBranch = opts.defaultBranch;
|
|
160
228
|
if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
|
|
161
229
|
if (opts.coordinator) mesh.coordinator = opts.coordinator;
|
|
230
|
+
if (opts.meshHost) mesh.meshHost = opts.meshHost;
|
|
162
231
|
mesh.updatedAt = new Date().toISOString();
|
|
163
232
|
|
|
164
233
|
saveMeshConfig(config);
|
|
@@ -174,6 +243,240 @@ export function deleteMesh(meshId: string): boolean {
|
|
|
174
243
|
return true;
|
|
175
244
|
}
|
|
176
245
|
|
|
246
|
+
function normalizeManualHostAddress(hostAddress: string): string {
|
|
247
|
+
const normalized = hostAddress.trim().replace(/\/+$/, '');
|
|
248
|
+
if (!normalized) throw new Error('hostAddress required');
|
|
249
|
+
let parsed: URL;
|
|
250
|
+
try {
|
|
251
|
+
parsed = new URL(normalized);
|
|
252
|
+
} catch {
|
|
253
|
+
throw new Error('hostAddress must be a valid http(s) or ws(s) URL');
|
|
254
|
+
}
|
|
255
|
+
if (!['http:', 'https:', 'ws:', 'wss:'].includes(parsed.protocol)) {
|
|
256
|
+
throw new Error('hostAddress must use http, https, ws, or wss');
|
|
257
|
+
}
|
|
258
|
+
return normalized;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function tokenIdForManualPairing(token: string): string {
|
|
262
|
+
return `tok_${shortHash(token)}`;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function normalizeTokenExpiry(value: unknown): string | undefined {
|
|
266
|
+
if (typeof value !== 'string' || !value.trim()) return undefined;
|
|
267
|
+
const date = new Date(value);
|
|
268
|
+
if (Number.isNaN(date.getTime())) throw new Error('expiresAt must be a valid ISO date');
|
|
269
|
+
return date.toISOString();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function assertPairingTokenValid(pairing: RepoMeshHostMetadata['pairing'], rawToken: string, nowIso: string): { ok: true; tokenId: string } | { ok: false; reason: string; expectedTokenId?: string; presentedTokenId?: string } {
|
|
273
|
+
const token = rawToken.trim();
|
|
274
|
+
if (!token) return { ok: false, reason: 'token required' };
|
|
275
|
+
const presentedTokenId = tokenIdForManualPairing(token);
|
|
276
|
+
const expectedTokenId = pairing?.tokenId;
|
|
277
|
+
if (!expectedTokenId || pairing?.status === 'not_configured' || pairing?.status === 'revoked') {
|
|
278
|
+
return { ok: false, reason: 'host pairing token is not configured', presentedTokenId };
|
|
279
|
+
}
|
|
280
|
+
if (pairing.expiresAt && new Date(pairing.expiresAt).getTime() <= new Date(nowIso).getTime()) {
|
|
281
|
+
return { ok: false, reason: 'host pairing token expired', expectedTokenId, presentedTokenId };
|
|
282
|
+
}
|
|
283
|
+
if (presentedTokenId !== expectedTokenId) {
|
|
284
|
+
return { ok: false, reason: 'invalid pairing token', expectedTokenId, presentedTokenId };
|
|
285
|
+
}
|
|
286
|
+
return { ok: true, tokenId: presentedTokenId };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export interface ConfigureMeshHostPairingOptions {
|
|
290
|
+
hostAddress: string;
|
|
291
|
+
token: string;
|
|
292
|
+
now?: string;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function configureMeshHostPairing(
|
|
296
|
+
meshId: string,
|
|
297
|
+
opts: ConfigureMeshHostPairingOptions,
|
|
298
|
+
): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; hostAddress: string } | undefined {
|
|
299
|
+
const hostAddress = normalizeManualHostAddress(opts.hostAddress);
|
|
300
|
+
const token = opts.token.trim();
|
|
301
|
+
if (!token) throw new Error('token required');
|
|
302
|
+
|
|
303
|
+
const config = loadMeshConfig();
|
|
304
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
305
|
+
if (!mesh) return undefined;
|
|
306
|
+
|
|
307
|
+
const now = opts.now || new Date().toISOString();
|
|
308
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
309
|
+
const meshHost: RepoMeshHostMetadata = {
|
|
310
|
+
...previous,
|
|
311
|
+
role: 'member',
|
|
312
|
+
hostAddress,
|
|
313
|
+
pairing: {
|
|
314
|
+
status: 'pairing',
|
|
315
|
+
tokenId: tokenIdForManualPairing(token),
|
|
316
|
+
lastPairedAt: now,
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
mesh.meshHost = meshHost;
|
|
321
|
+
mesh.updatedAt = now;
|
|
322
|
+
saveMeshConfig(config);
|
|
323
|
+
return { mesh, meshHost, hostAddress };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface CreateMeshHostPairingTokenOptions {
|
|
327
|
+
token?: string;
|
|
328
|
+
expiresAt?: string;
|
|
329
|
+
now?: string;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function createMeshHostPairingToken(
|
|
333
|
+
meshId: string,
|
|
334
|
+
opts: CreateMeshHostPairingTokenOptions = {},
|
|
335
|
+
): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; token: string; tokenId: string; expiresAt?: string } | undefined {
|
|
336
|
+
const config = loadMeshConfig();
|
|
337
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
338
|
+
if (!mesh) return undefined;
|
|
339
|
+
const now = opts.now || new Date().toISOString();
|
|
340
|
+
const token = (opts.token || `mhj_${randomBytes(24).toString('base64url')}`).trim();
|
|
341
|
+
if (!token) throw new Error('token required');
|
|
342
|
+
const tokenId = tokenIdForManualPairing(token);
|
|
343
|
+
const expiresAt = normalizeTokenExpiry(opts.expiresAt);
|
|
344
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
345
|
+
if (previous.role === 'member') {
|
|
346
|
+
throw new Error('Mesh Host daemon required to create host pairing tokens; member daemons cannot mint host join tokens.');
|
|
347
|
+
}
|
|
348
|
+
const meshHost: RepoMeshHostMetadata = {
|
|
349
|
+
...previous,
|
|
350
|
+
role: 'host',
|
|
351
|
+
pairing: {
|
|
352
|
+
status: 'pairing',
|
|
353
|
+
tokenId,
|
|
354
|
+
lastPairedAt: now,
|
|
355
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
356
|
+
},
|
|
357
|
+
};
|
|
358
|
+
mesh.meshHost = meshHost;
|
|
359
|
+
mesh.updatedAt = now;
|
|
360
|
+
saveMeshConfig(config);
|
|
361
|
+
return { mesh, meshHost, token, tokenId, ...(expiresAt ? { expiresAt } : {}) };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export interface MeshHostJoinMemberNodeInput {
|
|
365
|
+
id?: string;
|
|
366
|
+
workspace: string;
|
|
367
|
+
repoRoot?: string;
|
|
368
|
+
daemonId?: string;
|
|
369
|
+
machineId?: string;
|
|
370
|
+
userOverrides?: Partial<RepoMeshNodeCapabilities>;
|
|
371
|
+
policy?: RepoMeshNodePolicy;
|
|
372
|
+
role?: RepoMeshDaemonRole;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export interface ApplyMeshHostJoinOptions {
|
|
376
|
+
token: string;
|
|
377
|
+
memberNode: MeshHostJoinMemberNodeInput;
|
|
378
|
+
memberMeshId?: string;
|
|
379
|
+
now?: string;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function applyMeshHostJoinRequest(
|
|
383
|
+
meshId: string,
|
|
384
|
+
opts: ApplyMeshHostJoinOptions,
|
|
385
|
+
): { accepted: true; mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; node: LocalMeshNodeEntry; tokenId: string } | { accepted: false; mesh?: LocalMeshEntry; meshHost?: RepoMeshHostMetadata; tokenId?: string; reason: string } | undefined {
|
|
386
|
+
const config = loadMeshConfig();
|
|
387
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
388
|
+
if (!mesh) return undefined;
|
|
389
|
+
const now = opts.now || new Date().toISOString();
|
|
390
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
391
|
+
if (previous.role === 'member') {
|
|
392
|
+
return { accepted: false, mesh, meshHost: previous, reason: 'Mesh Host daemon required to accept join requests' };
|
|
393
|
+
}
|
|
394
|
+
const meshHost: RepoMeshHostMetadata = { ...previous, role: 'host' };
|
|
395
|
+
const validation = assertPairingTokenValid(meshHost.pairing, opts.token, now);
|
|
396
|
+
if (!validation.ok) {
|
|
397
|
+
mesh.meshHost = {
|
|
398
|
+
...meshHost,
|
|
399
|
+
pairing: {
|
|
400
|
+
...(meshHost.pairing || { status: 'not_configured' as const }),
|
|
401
|
+
status: 'rejected',
|
|
402
|
+
lastRejectedAt: now,
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
mesh.updatedAt = now;
|
|
406
|
+
saveMeshConfig(config);
|
|
407
|
+
return { accepted: false, mesh, meshHost: mesh.meshHost, tokenId: validation.presentedTokenId, reason: validation.reason };
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const workspace = opts.memberNode.workspace.trim();
|
|
411
|
+
if (!workspace) throw new Error('memberNode.workspace required');
|
|
412
|
+
const memberId = opts.memberNode.id?.trim();
|
|
413
|
+
let node = mesh.nodes.find(n => (memberId && n.id === memberId) || n.workspace === workspace);
|
|
414
|
+
if (node) {
|
|
415
|
+
node.workspace = workspace;
|
|
416
|
+
node.repoRoot = opts.memberNode.repoRoot;
|
|
417
|
+
node.daemonId = opts.memberNode.daemonId;
|
|
418
|
+
node.machineId = opts.memberNode.machineId;
|
|
419
|
+
node.userOverrides = opts.memberNode.userOverrides || node.userOverrides || {};
|
|
420
|
+
node.policy = { ...(node.policy || {}), ...(opts.memberNode.policy || {}) };
|
|
421
|
+
node.role = 'member';
|
|
422
|
+
} else {
|
|
423
|
+
if (mesh.nodes.length >= 10) throw new Error('Maximum 10 nodes per mesh');
|
|
424
|
+
node = {
|
|
425
|
+
id: memberId || `node_${randomUUID().replace(/-/g, '')}`,
|
|
426
|
+
workspace,
|
|
427
|
+
repoRoot: opts.memberNode.repoRoot,
|
|
428
|
+
daemonId: opts.memberNode.daemonId,
|
|
429
|
+
machineId: opts.memberNode.machineId,
|
|
430
|
+
userOverrides: opts.memberNode.userOverrides || {},
|
|
431
|
+
policy: opts.memberNode.policy || {},
|
|
432
|
+
role: 'member',
|
|
433
|
+
};
|
|
434
|
+
mesh.nodes.push(node);
|
|
435
|
+
}
|
|
436
|
+
mesh.meshHost = {
|
|
437
|
+
...meshHost,
|
|
438
|
+
pairing: {
|
|
439
|
+
...(meshHost.pairing || {}),
|
|
440
|
+
status: 'paired',
|
|
441
|
+
tokenId: validation.tokenId,
|
|
442
|
+
joinedAt: now,
|
|
443
|
+
lastPairedAt: meshHost.pairing?.lastPairedAt || now,
|
|
444
|
+
...(meshHost.pairing?.expiresAt ? { expiresAt: meshHost.pairing.expiresAt } : {}),
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
mesh.updatedAt = now;
|
|
448
|
+
saveMeshConfig(config);
|
|
449
|
+
return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export function markMeshHostPairingJoined(
|
|
453
|
+
meshId: string,
|
|
454
|
+
opts: { hostDaemonId?: string; hostNodeId?: string; joinedAt?: string; token?: string; tokenId?: string },
|
|
455
|
+
): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata } | undefined {
|
|
456
|
+
const config = loadMeshConfig();
|
|
457
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
458
|
+
if (!mesh) return undefined;
|
|
459
|
+
const now = opts.joinedAt || new Date().toISOString();
|
|
460
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
461
|
+
const tokenId = opts.tokenId || (opts.token ? tokenIdForManualPairing(opts.token) : previous.pairing?.tokenId);
|
|
462
|
+
mesh.meshHost = {
|
|
463
|
+
...previous,
|
|
464
|
+
role: 'member',
|
|
465
|
+
...(opts.hostDaemonId ? { hostDaemonId: opts.hostDaemonId } : {}),
|
|
466
|
+
...(opts.hostNodeId ? { hostNodeId: opts.hostNodeId } : {}),
|
|
467
|
+
pairing: {
|
|
468
|
+
...(previous.pairing || {}),
|
|
469
|
+
status: 'paired',
|
|
470
|
+
...(tokenId ? { tokenId } : {}),
|
|
471
|
+
joinedAt: now,
|
|
472
|
+
lastPairedAt: previous.pairing?.lastPairedAt || now,
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
mesh.updatedAt = now;
|
|
476
|
+
saveMeshConfig(config);
|
|
477
|
+
return { mesh, meshHost: mesh.meshHost };
|
|
478
|
+
}
|
|
479
|
+
|
|
177
480
|
// ─── Node Operations ────────────────────────────
|
|
178
481
|
|
|
179
482
|
export interface AddNodeOptions {
|
|
@@ -181,11 +484,14 @@ export interface AddNodeOptions {
|
|
|
181
484
|
repoRoot?: string;
|
|
182
485
|
daemonId?: string;
|
|
183
486
|
machineId?: string;
|
|
487
|
+
capabilities?: string[];
|
|
184
488
|
userOverrides?: Partial<RepoMeshNodeCapabilities>;
|
|
185
489
|
policy?: RepoMeshNodePolicy;
|
|
186
490
|
isLocalWorktree?: boolean;
|
|
187
491
|
worktreeBranch?: string;
|
|
188
492
|
clonedFromNodeId?: string;
|
|
493
|
+
worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
|
|
494
|
+
role?: RepoMeshDaemonRole;
|
|
189
495
|
}
|
|
190
496
|
|
|
191
497
|
export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntry | undefined {
|
|
@@ -208,11 +514,14 @@ export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntr
|
|
|
208
514
|
repoRoot: opts.repoRoot,
|
|
209
515
|
daemonId: opts.daemonId,
|
|
210
516
|
machineId: opts.machineId,
|
|
517
|
+
capabilities: normalizeCapabilityTags(opts.capabilities),
|
|
211
518
|
userOverrides: opts.userOverrides || {},
|
|
212
519
|
policy: opts.policy || {},
|
|
213
520
|
isLocalWorktree: opts.isLocalWorktree,
|
|
214
521
|
worktreeBranch: opts.worktreeBranch,
|
|
215
522
|
clonedFromNodeId: opts.clonedFromNodeId,
|
|
523
|
+
worktreeBootstrap: opts.worktreeBootstrap,
|
|
524
|
+
role: opts.role,
|
|
216
525
|
};
|
|
217
526
|
|
|
218
527
|
mesh.nodes.push(node);
|
|
@@ -238,7 +547,19 @@ export function removeNode(meshId: string, nodeId: string): boolean {
|
|
|
238
547
|
export function updateNode(
|
|
239
548
|
meshId: string,
|
|
240
549
|
nodeId: string,
|
|
241
|
-
opts: {
|
|
550
|
+
opts: {
|
|
551
|
+
userOverrides?: Partial<RepoMeshNodeCapabilities>;
|
|
552
|
+
policy?: RepoMeshNodePolicy;
|
|
553
|
+
worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
|
|
554
|
+
/** Per-node instruction surfaced in the coordinator prompt. Pass an
|
|
555
|
+
* empty string or undefined to clear it. */
|
|
556
|
+
systemPrompt?: string;
|
|
557
|
+
/** Live self-reported platform/arch from the owning daemon's git_status
|
|
558
|
+
* envelope. Persisted distinctly from userOverrides (auto-detected, not
|
|
559
|
+
* operator intent) so capability-tag os=/arch= self-heals across loads. */
|
|
560
|
+
reportedPlatform?: string;
|
|
561
|
+
reportedArch?: string;
|
|
562
|
+
},
|
|
242
563
|
): LocalMeshNodeEntry | undefined {
|
|
243
564
|
const config = loadMeshConfig();
|
|
244
565
|
const mesh = config.meshes.find(m => m.id === meshId);
|
|
@@ -248,8 +569,160 @@ export function updateNode(
|
|
|
248
569
|
if (!node) return undefined;
|
|
249
570
|
|
|
250
571
|
if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
|
|
572
|
+
if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
|
|
573
|
+
if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
|
|
251
574
|
if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
|
|
575
|
+
if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
|
|
576
|
+
if (Object.prototype.hasOwnProperty.call(opts, 'systemPrompt')) {
|
|
577
|
+
// Honor explicit clears: { systemPrompt: undefined } drops the field.
|
|
578
|
+
if (opts.systemPrompt && opts.systemPrompt.trim()) {
|
|
579
|
+
node.systemPrompt = opts.systemPrompt;
|
|
580
|
+
} else {
|
|
581
|
+
delete node.systemPrompt;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
252
584
|
mesh.updatedAt = new Date().toISOString();
|
|
253
585
|
saveMeshConfig(config);
|
|
254
586
|
return node;
|
|
255
587
|
}
|
|
588
|
+
|
|
589
|
+
// ─── MAGI Panels (machine-local cross-verification quorums) ──
|
|
590
|
+
|
|
591
|
+
/** Hard cap on members per panel — a sanity bound, not the per-invocation replica cap. */
|
|
592
|
+
const MAX_MAGI_PANEL_MEMBERS = 24;
|
|
593
|
+
|
|
594
|
+
function normalizeReplicaCount(value: unknown): number | undefined {
|
|
595
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) return undefined;
|
|
596
|
+
const n = Math.floor(value);
|
|
597
|
+
return n >= 1 ? n : undefined;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Normalize a panel `defaultKind` (the non-binding default output kind). Returns
|
|
602
|
+
* undefined (drop, don't throw) for any absent / unknown value so a stray field
|
|
603
|
+
* never blocks a panel write. 'freeform' is explicitly DROPPED with a warning: a
|
|
604
|
+
* panel is a cross-verification tool and freeform contributes no structured claims
|
|
605
|
+
* (claims:[]), so defaulting to it would silently zero out the very thing the panel
|
|
606
|
+
* exists for. Only the evidence-bearing kinds (claim_audit / rca / design) survive.
|
|
607
|
+
*/
|
|
608
|
+
function normalizeMagiPanelDefaultKind(raw: unknown): MagiPanelDefaultKind | undefined {
|
|
609
|
+
if (raw == null) return undefined;
|
|
610
|
+
const s = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
|
|
611
|
+
if (s === 'claim_audit' || s === 'rca' || s === 'design') return s;
|
|
612
|
+
if (s === 'freeform') {
|
|
613
|
+
// eslint-disable-next-line no-console
|
|
614
|
+
console.warn(
|
|
615
|
+
"[magi] panel defaultKind='freeform' rejected — freeform contributes no structured claims to cross-verification; dropping (use claim_audit / rca / design, or omit).",
|
|
616
|
+
);
|
|
617
|
+
return undefined;
|
|
618
|
+
}
|
|
619
|
+
// Any other value (typo / unsupported kind): drop silently — the panel still
|
|
620
|
+
// resolves to the claim_audit fallback at review time.
|
|
621
|
+
return undefined;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Validate + normalize a panel config before persisting. Mirrors the node-config
|
|
626
|
+
* normalization style (mesh-config addNode/updateNode): trims strings, drops
|
|
627
|
+
* empties, requires a provider per member, clamps replica counts. Throws on
|
|
628
|
+
* structurally invalid input so the calling tool returns a clear error rather than
|
|
629
|
+
* writing a malformed panel.
|
|
630
|
+
*/
|
|
631
|
+
export function normalizeMagiPanel(config: unknown): MagiPanel {
|
|
632
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
633
|
+
throw new Error('invalid_magi_panel: config must be an object');
|
|
634
|
+
}
|
|
635
|
+
const raw = config as Record<string, unknown>;
|
|
636
|
+
const rawMembers = raw.members;
|
|
637
|
+
if (!Array.isArray(rawMembers) || rawMembers.length === 0) {
|
|
638
|
+
throw new Error('invalid_magi_panel: members must be a non-empty array');
|
|
639
|
+
}
|
|
640
|
+
if (rawMembers.length > MAX_MAGI_PANEL_MEMBERS) {
|
|
641
|
+
throw new Error(`invalid_magi_panel: too many members (max ${MAX_MAGI_PANEL_MEMBERS})`);
|
|
642
|
+
}
|
|
643
|
+
const members: MagiPanelMember[] = rawMembers.map((entry, idx) => {
|
|
644
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
645
|
+
throw new Error(`invalid_magi_panel: member[${idx}] must be an object`);
|
|
646
|
+
}
|
|
647
|
+
const m = entry as Record<string, unknown>;
|
|
648
|
+
const provider = typeof m.provider === 'string' ? m.provider.trim() : '';
|
|
649
|
+
if (!provider) {
|
|
650
|
+
throw new Error(`invalid_magi_panel: member[${idx}].provider is required`);
|
|
651
|
+
}
|
|
652
|
+
const nodeId = typeof m.nodeId === 'string' && m.nodeId.trim() ? m.nodeId.trim() : undefined;
|
|
653
|
+
const capabilityTags = normalizeCapabilityTags(m.capabilityTags);
|
|
654
|
+
const n = normalizeReplicaCount(m.n);
|
|
655
|
+
return {
|
|
656
|
+
provider,
|
|
657
|
+
...(nodeId ? { nodeId } : {}),
|
|
658
|
+
...(capabilityTags ? { capabilityTags } : {}),
|
|
659
|
+
...(n !== undefined ? { n } : {}),
|
|
660
|
+
};
|
|
661
|
+
});
|
|
662
|
+
const description = typeof raw.description === 'string' && raw.description.trim()
|
|
663
|
+
? raw.description.trim().slice(0, 200)
|
|
664
|
+
: undefined;
|
|
665
|
+
const defaultN = normalizeReplicaCount(raw.defaultN);
|
|
666
|
+
const defaultKind = normalizeMagiPanelDefaultKind(raw.defaultKind);
|
|
667
|
+
return {
|
|
668
|
+
...(description ? { description } : {}),
|
|
669
|
+
members,
|
|
670
|
+
...(defaultN !== undefined ? { defaultN } : {}),
|
|
671
|
+
...(defaultKind !== undefined ? { defaultKind } : {}),
|
|
672
|
+
// dedupExempt is always meaningful for a MAGI panel (intentional same-prompt
|
|
673
|
+
// fan-out). Persist it true unless the caller explicitly disables it.
|
|
674
|
+
dedupExempt: raw.dedupExempt === false ? false : true,
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function normalizePanelName(name: unknown): string {
|
|
679
|
+
const trimmed = typeof name === 'string' ? name.trim() : '';
|
|
680
|
+
if (!trimmed) throw new Error('invalid_magi_panel: panel name is required');
|
|
681
|
+
return trimmed.slice(0, 100);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/** All configured MAGI panels (machine-local), keyed by name. Empty when none. */
|
|
685
|
+
export function listMagiPanels(): Record<string, MagiPanel> {
|
|
686
|
+
return loadMeshConfig().magiPanels ?? {};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/** A single panel by name, or undefined when not configured. */
|
|
690
|
+
export function getMagiPanel(name: string): MagiPanel | undefined {
|
|
691
|
+
const key = typeof name === 'string' ? name.trim() : '';
|
|
692
|
+
if (!key) return undefined;
|
|
693
|
+
return loadMeshConfig().magiPanels?.[key];
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Upsert a named panel into meshes.json. Defaults to refusing to clobber an
|
|
698
|
+
* existing panel (overwrite=false) — mirrors the mesh_init write/overwrite
|
|
699
|
+
* precedent. Returns the normalized, persisted panel.
|
|
700
|
+
*/
|
|
701
|
+
export function upsertMagiPanel(
|
|
702
|
+
name: string,
|
|
703
|
+
config: unknown,
|
|
704
|
+
opts: { overwrite?: boolean } = {},
|
|
705
|
+
): MagiPanel {
|
|
706
|
+
const key = normalizePanelName(name);
|
|
707
|
+
const panel = normalizeMagiPanel(config);
|
|
708
|
+
const stored = loadMeshConfig();
|
|
709
|
+
const panels = stored.magiPanels ?? {};
|
|
710
|
+
if (panels[key] && opts.overwrite !== true) {
|
|
711
|
+
throw new Error(`magi_panel_exists: panel '${key}' already exists — pass overwrite=true to replace it`);
|
|
712
|
+
}
|
|
713
|
+
panels[key] = panel;
|
|
714
|
+
stored.magiPanels = panels;
|
|
715
|
+
saveMeshConfig(stored);
|
|
716
|
+
return panel;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/** Remove a named panel. Returns true when a panel was removed. */
|
|
720
|
+
export function removeMagiPanel(name: string): boolean {
|
|
721
|
+
const key = typeof name === 'string' ? name.trim() : '';
|
|
722
|
+
if (!key) return false;
|
|
723
|
+
const stored = loadMeshConfig();
|
|
724
|
+
if (!stored.magiPanels || !stored.magiPanels[key]) return false;
|
|
725
|
+
delete stored.magiPanels[key];
|
|
726
|
+
saveMeshConfig(stored);
|
|
727
|
+
return true;
|
|
728
|
+
}
|