@adhdev/daemon-core 0.9.82-rc.37 → 0.9.82-rc.371
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 +55 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +116 -64
- package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +63 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/cli-adapters/resolve-executable.d.ts +14 -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.d.ts +27 -0
- 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 +2 -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 +116 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router.d.ts +666 -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 +77 -1
- 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 +23 -0
- package/dist/git/git-types.d.ts +2 -50
- package/dist/git/index.d.ts +2 -0
- package/dist/index.d.ts +55 -13
- package/dist/index.js +46565 -19737
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43563 -16868
- 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 +46 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/mesh/contracts.d.ts +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +36 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +174 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
- package/dist/mesh/mesh-event-trace.d.ts +21 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +91 -0
- package/dist/mesh/mesh-events-pending.d.ts +55 -0
- package/dist/mesh/mesh-events-stale.d.ts +40 -0
- package/dist/mesh/mesh-events-utils.d.ts +61 -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 -3
- package/dist/mesh/mesh-ledger.d.ts +77 -1
- package/dist/mesh/mesh-missions.d.ts +164 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -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 +429 -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 +246 -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 +135 -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 +12 -0
- package/dist/providers/cli-provider-instance.d.ts +108 -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/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 +14 -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 +395 -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 +295 -13
- 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 +1 -0
- package/src/cli-adapter-types.ts +56 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1221 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +775 -1141
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +13 -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 +110 -11
- package/src/cli-adapters/pty-transport.ts +2 -1
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/resolve-executable.ts +90 -0
- package/src/cli-adapters/session-host-transport.ts +2 -1
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -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.ts +1917 -62
- package/src/commands/cli-manager.ts +502 -24
- 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 +592 -0
- package/src/commands/high-family/mesh-events.ts +47 -0
- package/src/commands/high-family/mesh-status.ts +642 -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 +81 -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 +218 -0
- package/src/commands/med-family/fast-forward.ts +198 -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 +788 -0
- package/src/commands/med-family/mesh-host-pairing.ts +234 -0
- package/src/commands/med-family/mesh-queue.ts +131 -0
- package/src/commands/med-family/mesh-restart.ts +92 -0
- package/src/commands/med-family/types.ts +120 -0
- package/src/commands/mesh-coordinator.ts +334 -124
- package/src/commands/router.ts +5121 -2369
- 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 +389 -6
- package/src/config/recent-activity.ts +8 -2
- 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 +55 -14
- package/src/git/git-diff.ts +81 -11
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +574 -43
- package/src/git/git-types.ts +14 -62
- package/src/git/git-worktree.ts +8 -1
- package/src/git/index.ts +16 -0
- package/src/index.ts +158 -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 +220 -0
- package/src/logging/logger.ts +14 -7
- package/src/mesh/contracts.ts +338 -0
- package/src/mesh/coordinator-prompt.ts +234 -31
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +645 -0
- package/src/mesh/mesh-delivery-policy.ts +315 -0
- package/src/mesh/mesh-event-trace.ts +67 -0
- package/src/mesh/mesh-events-coordinator.ts +2866 -0
- package/src/mesh/mesh-events-pending.ts +599 -0
- package/src/mesh/mesh-events-stale.ts +309 -0
- package/src/mesh/mesh-events-utils.ts +387 -0
- package/src/mesh/mesh-events.ts +30 -1035
- package/src/mesh/mesh-fast-forward.ts +839 -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 -5
- package/src/mesh/mesh-ledger.ts +591 -102
- package/src/mesh/mesh-missions.ts +322 -0
- package/src/mesh/mesh-reconcile-loop.ts +1134 -0
- package/src/mesh/mesh-refine-batch.ts +197 -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 +1697 -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 +997 -141
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +423 -0
- package/src/mesh/worktree-bootstrap-config.ts +331 -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 +45 -5
- package/src/providers/cli-provider-instance.ts +1310 -101
- 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/dispatcher.ts +340 -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 +30 -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 +1051 -0
- package/src/providers/spec/evaluator.ts +407 -0
- package/src/providers/spec/fsm-driver.ts +1305 -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 +1136 -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 +378 -14
- 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,11 @@ import type {
|
|
|
18
19
|
RepoMeshNodePolicy,
|
|
19
20
|
RepoMeshNodeCapabilities,
|
|
20
21
|
RepoMeshCoordinatorConfig,
|
|
22
|
+
RepoMeshHostMetadata,
|
|
23
|
+
RepoMeshDaemonRole,
|
|
21
24
|
} from '../repo-mesh-types.js';
|
|
22
|
-
import { DEFAULT_MESH_POLICY } from '../repo-mesh-types.js';
|
|
25
|
+
import { DEFAULT_MESH_POLICY, normalizeMeshSchedulingStrategy } from '../repo-mesh-types.js';
|
|
26
|
+
import { createDefaultMeshHostMetadata } from '../mesh/mesh-host-ownership.js';
|
|
23
27
|
|
|
24
28
|
// ─── Persistence ────────────────────────────────
|
|
25
29
|
|
|
@@ -33,12 +37,85 @@ function loadMeshConfig(): LocalMeshConfig {
|
|
|
33
37
|
try {
|
|
34
38
|
const raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
35
39
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
36
|
-
|
|
40
|
+
const config = raw as LocalMeshConfig;
|
|
41
|
+
const migrated = migrateLoadedMeshConfig(config);
|
|
42
|
+
// Persist eagerly when the on-load migration changed anything, so the
|
|
43
|
+
// dead field is gone from disk even on a pure-read path (mesh_status /
|
|
44
|
+
// mesh_list_nodes) that never otherwise mutates the config. Best-effort:
|
|
45
|
+
// a write failure (e.g. read-only fs) must not break reads, so swallow.
|
|
46
|
+
if (migrated) {
|
|
47
|
+
try {
|
|
48
|
+
saveMeshConfig(config);
|
|
49
|
+
} catch {
|
|
50
|
+
// keep the in-memory strip; disk converges on the next mutating op
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return config;
|
|
37
54
|
} catch {
|
|
38
55
|
return { meshes: [] };
|
|
39
56
|
}
|
|
40
57
|
}
|
|
41
58
|
|
|
59
|
+
/**
|
|
60
|
+
* In-place migration applied to every loaded meshes.json. Strips data that
|
|
61
|
+
* outlived the feature that wrote it so the persisted config converges on the
|
|
62
|
+
* current schema the next time it is saved.
|
|
63
|
+
*
|
|
64
|
+
* Currently: drops the dead `role` field from each node policy's providerRoles
|
|
65
|
+
* entries. providerRoles is retained for its `maxParallel` per-(node, provider)
|
|
66
|
+
* cap, but the routing `role` was removed (routing is governed solely by
|
|
67
|
+
* required_tags). A meshes.json written before the removal still carries
|
|
68
|
+
* `role: "validator"` etc.; this drops it on load so mesh_status / mesh_list_nodes
|
|
69
|
+
* never surface the dead field and the next saveMeshConfig() persists it gone.
|
|
70
|
+
*
|
|
71
|
+
* Returns true when the config was mutated (caller may persist eagerly).
|
|
72
|
+
*/
|
|
73
|
+
function migrateLoadedMeshConfig(config: LocalMeshConfig): boolean {
|
|
74
|
+
let changed = false;
|
|
75
|
+
for (const mesh of config.meshes) {
|
|
76
|
+
if (!mesh || !Array.isArray(mesh.nodes)) continue;
|
|
77
|
+
for (const node of mesh.nodes) {
|
|
78
|
+
if (stripDeadRoleFromProviderRoles(node?.policy)) changed = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return changed;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Drop the legacy `role` field from each providerRoles entry of a node policy,
|
|
86
|
+
* in place. Keeps providerType + maxParallel (the still-meaningful per-(node,
|
|
87
|
+
* provider) cap). Defensive against malformed entries — non-object items are
|
|
88
|
+
* left untouched. Returns true when at least one `role` field was removed.
|
|
89
|
+
*/
|
|
90
|
+
function stripDeadRoleFromProviderRoles(policy: unknown): boolean {
|
|
91
|
+
if (!policy || typeof policy !== 'object') return false;
|
|
92
|
+
const roles = (policy as { providerRoles?: unknown }).providerRoles;
|
|
93
|
+
if (!Array.isArray(roles)) return false;
|
|
94
|
+
let changed = false;
|
|
95
|
+
for (const entry of roles) {
|
|
96
|
+
if (entry && typeof entry === 'object' && !Array.isArray(entry)
|
|
97
|
+
&& Object.prototype.hasOwnProperty.call(entry, 'role')) {
|
|
98
|
+
delete (entry as Record<string, unknown>).role;
|
|
99
|
+
changed = true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return changed;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function normalizeCapabilityTags(value: unknown): string[] | undefined {
|
|
106
|
+
if (!Array.isArray(value)) return undefined;
|
|
107
|
+
const seen = new Set<string>();
|
|
108
|
+
const tags = value
|
|
109
|
+
.map(tag => typeof tag === 'string' ? tag.trim() : '')
|
|
110
|
+
.filter(Boolean)
|
|
111
|
+
.filter(tag => {
|
|
112
|
+
if (seen.has(tag)) return false;
|
|
113
|
+
seen.add(tag);
|
|
114
|
+
return true;
|
|
115
|
+
});
|
|
116
|
+
return tags.length ? tags : undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
42
119
|
function saveMeshConfig(config: LocalMeshConfig): void {
|
|
43
120
|
const path = getMeshConfigPath();
|
|
44
121
|
writeFileSync(path, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
@@ -78,21 +155,60 @@ const SESSION_CLEANUP_MODES = new Set(['preserve', 'stop', 'delete_stopped', 'st
|
|
|
78
155
|
const SPAWNED_SESSION_VISIBILITY_MODES = new Set(['visible', 'hidden']);
|
|
79
156
|
|
|
80
157
|
function mergeMeshPolicy(base: RepoMeshPolicy | undefined, patch: Partial<RepoMeshPolicy> | undefined): RepoMeshPolicy {
|
|
81
|
-
const
|
|
158
|
+
const autoFastForward = normalizeAutoFastForwardPolicy({
|
|
159
|
+
...DEFAULT_MESH_POLICY.autoFastForward,
|
|
160
|
+
...((base?.autoFastForward && typeof base.autoFastForward === 'object') ? base.autoFastForward : {}),
|
|
161
|
+
...((patch?.autoFastForward && typeof patch.autoFastForward === 'object') ? patch.autoFastForward : {}),
|
|
162
|
+
});
|
|
163
|
+
const policy: RepoMeshPolicy = {
|
|
164
|
+
...DEFAULT_MESH_POLICY,
|
|
165
|
+
...(base || {}),
|
|
166
|
+
...(patch || {}),
|
|
167
|
+
autoFastForward,
|
|
168
|
+
};
|
|
82
169
|
if (!['block', 'warn', 'checkpoint_then_continue'].includes(policy.dirtyWorkspaceBehavior)) {
|
|
83
170
|
policy.dirtyWorkspaceBehavior = 'warn';
|
|
84
171
|
}
|
|
85
172
|
const maxParallelTasks = Number(policy.maxParallelTasks);
|
|
86
173
|
policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
|
|
174
|
+
policy.allowAutoPublishSubmoduleMainCommits = policy.allowAutoPublishSubmoduleMainCommits === true;
|
|
87
175
|
if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
|
|
88
176
|
policy.sessionCleanupOnNodeRemove = 'preserve';
|
|
89
177
|
}
|
|
90
178
|
if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
|
|
91
|
-
policy.spawnedSessionVisibility =
|
|
179
|
+
policy.spawnedSessionVisibility = DEFAULT_MESH_POLICY.spawnedSessionVisibility;
|
|
180
|
+
}
|
|
181
|
+
// Load-balancing: normalize the scheduling strategy so an invalid/blank value
|
|
182
|
+
// falls back to 'first_eligible' (strict no-change). Only persist the field when
|
|
183
|
+
// it is explicitly a non-default value to keep existing meshes.json untouched.
|
|
184
|
+
const normalizedStrategy = normalizeMeshSchedulingStrategy(policy.schedulingStrategy);
|
|
185
|
+
if (normalizedStrategy === 'first_eligible') {
|
|
186
|
+
delete policy.schedulingStrategy;
|
|
187
|
+
} else {
|
|
188
|
+
policy.schedulingStrategy = normalizedStrategy;
|
|
189
|
+
}
|
|
190
|
+
// Convergence routing: strict opt-in (default false). Only persist when explicitly
|
|
191
|
+
// enabled so existing meshes.json stays byte-for-byte untouched.
|
|
192
|
+
if (policy.autoConvergeCodeChange === true) {
|
|
193
|
+
policy.autoConvergeCodeChange = true;
|
|
194
|
+
} else {
|
|
195
|
+
delete policy.autoConvergeCodeChange;
|
|
92
196
|
}
|
|
93
197
|
return policy;
|
|
94
198
|
}
|
|
95
199
|
|
|
200
|
+
function normalizeAutoFastForwardPolicy(value: unknown): NonNullable<RepoMeshPolicy['autoFastForward']> {
|
|
201
|
+
const record = value && typeof value === 'object' && !Array.isArray(value)
|
|
202
|
+
? value as Record<string, unknown>
|
|
203
|
+
: {};
|
|
204
|
+
const maxBehind = Number(record.maxBehind);
|
|
205
|
+
return {
|
|
206
|
+
enabled: record.enabled !== false,
|
|
207
|
+
...(Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {}),
|
|
208
|
+
requireCleanSubmodules: record.requireCleanSubmodules !== false,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
96
212
|
export function listMeshes(): LocalMeshEntry[] {
|
|
97
213
|
return loadMeshConfig().meshes;
|
|
98
214
|
}
|
|
@@ -112,6 +228,7 @@ export interface CreateMeshOptions {
|
|
|
112
228
|
defaultBranch?: string;
|
|
113
229
|
policy?: Partial<RepoMeshPolicy>;
|
|
114
230
|
coordinator?: RepoMeshCoordinatorConfig;
|
|
231
|
+
meshHost?: RepoMeshHostMetadata;
|
|
115
232
|
}
|
|
116
233
|
|
|
117
234
|
export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
|
|
@@ -133,6 +250,7 @@ export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
|
|
|
133
250
|
defaultBranch: opts.defaultBranch,
|
|
134
251
|
policy: mergeMeshPolicy(undefined, opts.policy),
|
|
135
252
|
coordinator: opts.coordinator || {},
|
|
253
|
+
meshHost: opts.meshHost || createDefaultMeshHostMetadata(),
|
|
136
254
|
nodes: [],
|
|
137
255
|
createdAt: now,
|
|
138
256
|
updatedAt: now,
|
|
@@ -148,6 +266,7 @@ export interface UpdateMeshOptions {
|
|
|
148
266
|
defaultBranch?: string;
|
|
149
267
|
policy?: Partial<RepoMeshPolicy>;
|
|
150
268
|
coordinator?: RepoMeshCoordinatorConfig;
|
|
269
|
+
meshHost?: RepoMeshHostMetadata;
|
|
151
270
|
}
|
|
152
271
|
|
|
153
272
|
export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEntry | undefined {
|
|
@@ -159,6 +278,7 @@ export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEn
|
|
|
159
278
|
if (opts.defaultBranch !== undefined) mesh.defaultBranch = opts.defaultBranch;
|
|
160
279
|
if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
|
|
161
280
|
if (opts.coordinator) mesh.coordinator = opts.coordinator;
|
|
281
|
+
if (opts.meshHost) mesh.meshHost = opts.meshHost;
|
|
162
282
|
mesh.updatedAt = new Date().toISOString();
|
|
163
283
|
|
|
164
284
|
saveMeshConfig(config);
|
|
@@ -174,6 +294,240 @@ export function deleteMesh(meshId: string): boolean {
|
|
|
174
294
|
return true;
|
|
175
295
|
}
|
|
176
296
|
|
|
297
|
+
function normalizeManualHostAddress(hostAddress: string): string {
|
|
298
|
+
const normalized = hostAddress.trim().replace(/\/+$/, '');
|
|
299
|
+
if (!normalized) throw new Error('hostAddress required');
|
|
300
|
+
let parsed: URL;
|
|
301
|
+
try {
|
|
302
|
+
parsed = new URL(normalized);
|
|
303
|
+
} catch {
|
|
304
|
+
throw new Error('hostAddress must be a valid http(s) or ws(s) URL');
|
|
305
|
+
}
|
|
306
|
+
if (!['http:', 'https:', 'ws:', 'wss:'].includes(parsed.protocol)) {
|
|
307
|
+
throw new Error('hostAddress must use http, https, ws, or wss');
|
|
308
|
+
}
|
|
309
|
+
return normalized;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function tokenIdForManualPairing(token: string): string {
|
|
313
|
+
return `tok_${shortHash(token)}`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function normalizeTokenExpiry(value: unknown): string | undefined {
|
|
317
|
+
if (typeof value !== 'string' || !value.trim()) return undefined;
|
|
318
|
+
const date = new Date(value);
|
|
319
|
+
if (Number.isNaN(date.getTime())) throw new Error('expiresAt must be a valid ISO date');
|
|
320
|
+
return date.toISOString();
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function assertPairingTokenValid(pairing: RepoMeshHostMetadata['pairing'], rawToken: string, nowIso: string): { ok: true; tokenId: string } | { ok: false; reason: string; expectedTokenId?: string; presentedTokenId?: string } {
|
|
324
|
+
const token = rawToken.trim();
|
|
325
|
+
if (!token) return { ok: false, reason: 'token required' };
|
|
326
|
+
const presentedTokenId = tokenIdForManualPairing(token);
|
|
327
|
+
const expectedTokenId = pairing?.tokenId;
|
|
328
|
+
if (!expectedTokenId || pairing?.status === 'not_configured' || pairing?.status === 'revoked') {
|
|
329
|
+
return { ok: false, reason: 'host pairing token is not configured', presentedTokenId };
|
|
330
|
+
}
|
|
331
|
+
if (pairing.expiresAt && new Date(pairing.expiresAt).getTime() <= new Date(nowIso).getTime()) {
|
|
332
|
+
return { ok: false, reason: 'host pairing token expired', expectedTokenId, presentedTokenId };
|
|
333
|
+
}
|
|
334
|
+
if (presentedTokenId !== expectedTokenId) {
|
|
335
|
+
return { ok: false, reason: 'invalid pairing token', expectedTokenId, presentedTokenId };
|
|
336
|
+
}
|
|
337
|
+
return { ok: true, tokenId: presentedTokenId };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export interface ConfigureMeshHostPairingOptions {
|
|
341
|
+
hostAddress: string;
|
|
342
|
+
token: string;
|
|
343
|
+
now?: string;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export function configureMeshHostPairing(
|
|
347
|
+
meshId: string,
|
|
348
|
+
opts: ConfigureMeshHostPairingOptions,
|
|
349
|
+
): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; hostAddress: string } | undefined {
|
|
350
|
+
const hostAddress = normalizeManualHostAddress(opts.hostAddress);
|
|
351
|
+
const token = opts.token.trim();
|
|
352
|
+
if (!token) throw new Error('token required');
|
|
353
|
+
|
|
354
|
+
const config = loadMeshConfig();
|
|
355
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
356
|
+
if (!mesh) return undefined;
|
|
357
|
+
|
|
358
|
+
const now = opts.now || new Date().toISOString();
|
|
359
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
360
|
+
const meshHost: RepoMeshHostMetadata = {
|
|
361
|
+
...previous,
|
|
362
|
+
role: 'member',
|
|
363
|
+
hostAddress,
|
|
364
|
+
pairing: {
|
|
365
|
+
status: 'pairing',
|
|
366
|
+
tokenId: tokenIdForManualPairing(token),
|
|
367
|
+
lastPairedAt: now,
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
mesh.meshHost = meshHost;
|
|
372
|
+
mesh.updatedAt = now;
|
|
373
|
+
saveMeshConfig(config);
|
|
374
|
+
return { mesh, meshHost, hostAddress };
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export interface CreateMeshHostPairingTokenOptions {
|
|
378
|
+
token?: string;
|
|
379
|
+
expiresAt?: string;
|
|
380
|
+
now?: string;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function createMeshHostPairingToken(
|
|
384
|
+
meshId: string,
|
|
385
|
+
opts: CreateMeshHostPairingTokenOptions = {},
|
|
386
|
+
): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; token: string; tokenId: string; expiresAt?: string } | undefined {
|
|
387
|
+
const config = loadMeshConfig();
|
|
388
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
389
|
+
if (!mesh) return undefined;
|
|
390
|
+
const now = opts.now || new Date().toISOString();
|
|
391
|
+
const token = (opts.token || `mhj_${randomBytes(24).toString('base64url')}`).trim();
|
|
392
|
+
if (!token) throw new Error('token required');
|
|
393
|
+
const tokenId = tokenIdForManualPairing(token);
|
|
394
|
+
const expiresAt = normalizeTokenExpiry(opts.expiresAt);
|
|
395
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
396
|
+
if (previous.role === 'member') {
|
|
397
|
+
throw new Error('Mesh Host daemon required to create host pairing tokens; member daemons cannot mint host join tokens.');
|
|
398
|
+
}
|
|
399
|
+
const meshHost: RepoMeshHostMetadata = {
|
|
400
|
+
...previous,
|
|
401
|
+
role: 'host',
|
|
402
|
+
pairing: {
|
|
403
|
+
status: 'pairing',
|
|
404
|
+
tokenId,
|
|
405
|
+
lastPairedAt: now,
|
|
406
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
407
|
+
},
|
|
408
|
+
};
|
|
409
|
+
mesh.meshHost = meshHost;
|
|
410
|
+
mesh.updatedAt = now;
|
|
411
|
+
saveMeshConfig(config);
|
|
412
|
+
return { mesh, meshHost, token, tokenId, ...(expiresAt ? { expiresAt } : {}) };
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export interface MeshHostJoinMemberNodeInput {
|
|
416
|
+
id?: string;
|
|
417
|
+
workspace: string;
|
|
418
|
+
repoRoot?: string;
|
|
419
|
+
daemonId?: string;
|
|
420
|
+
machineId?: string;
|
|
421
|
+
userOverrides?: Partial<RepoMeshNodeCapabilities>;
|
|
422
|
+
policy?: RepoMeshNodePolicy;
|
|
423
|
+
role?: RepoMeshDaemonRole;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export interface ApplyMeshHostJoinOptions {
|
|
427
|
+
token: string;
|
|
428
|
+
memberNode: MeshHostJoinMemberNodeInput;
|
|
429
|
+
memberMeshId?: string;
|
|
430
|
+
now?: string;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export function applyMeshHostJoinRequest(
|
|
434
|
+
meshId: string,
|
|
435
|
+
opts: ApplyMeshHostJoinOptions,
|
|
436
|
+
): { accepted: true; mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; node: LocalMeshNodeEntry; tokenId: string } | { accepted: false; mesh?: LocalMeshEntry; meshHost?: RepoMeshHostMetadata; tokenId?: string; reason: string } | undefined {
|
|
437
|
+
const config = loadMeshConfig();
|
|
438
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
439
|
+
if (!mesh) return undefined;
|
|
440
|
+
const now = opts.now || new Date().toISOString();
|
|
441
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
442
|
+
if (previous.role === 'member') {
|
|
443
|
+
return { accepted: false, mesh, meshHost: previous, reason: 'Mesh Host daemon required to accept join requests' };
|
|
444
|
+
}
|
|
445
|
+
const meshHost: RepoMeshHostMetadata = { ...previous, role: 'host' };
|
|
446
|
+
const validation = assertPairingTokenValid(meshHost.pairing, opts.token, now);
|
|
447
|
+
if (!validation.ok) {
|
|
448
|
+
mesh.meshHost = {
|
|
449
|
+
...meshHost,
|
|
450
|
+
pairing: {
|
|
451
|
+
...(meshHost.pairing || { status: 'not_configured' as const }),
|
|
452
|
+
status: 'rejected',
|
|
453
|
+
lastRejectedAt: now,
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
mesh.updatedAt = now;
|
|
457
|
+
saveMeshConfig(config);
|
|
458
|
+
return { accepted: false, mesh, meshHost: mesh.meshHost, tokenId: validation.presentedTokenId, reason: validation.reason };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const workspace = opts.memberNode.workspace.trim();
|
|
462
|
+
if (!workspace) throw new Error('memberNode.workspace required');
|
|
463
|
+
const memberId = opts.memberNode.id?.trim();
|
|
464
|
+
let node = mesh.nodes.find(n => (memberId && n.id === memberId) || n.workspace === workspace);
|
|
465
|
+
if (node) {
|
|
466
|
+
node.workspace = workspace;
|
|
467
|
+
node.repoRoot = opts.memberNode.repoRoot;
|
|
468
|
+
node.daemonId = opts.memberNode.daemonId;
|
|
469
|
+
node.machineId = opts.memberNode.machineId;
|
|
470
|
+
node.userOverrides = opts.memberNode.userOverrides || node.userOverrides || {};
|
|
471
|
+
node.policy = { ...(node.policy || {}), ...(opts.memberNode.policy || {}) };
|
|
472
|
+
node.role = 'member';
|
|
473
|
+
} else {
|
|
474
|
+
if (mesh.nodes.length >= 10) throw new Error('Maximum 10 nodes per mesh');
|
|
475
|
+
node = {
|
|
476
|
+
id: memberId || `node_${randomUUID().replace(/-/g, '')}`,
|
|
477
|
+
workspace,
|
|
478
|
+
repoRoot: opts.memberNode.repoRoot,
|
|
479
|
+
daemonId: opts.memberNode.daemonId,
|
|
480
|
+
machineId: opts.memberNode.machineId,
|
|
481
|
+
userOverrides: opts.memberNode.userOverrides || {},
|
|
482
|
+
policy: opts.memberNode.policy || {},
|
|
483
|
+
role: 'member',
|
|
484
|
+
};
|
|
485
|
+
mesh.nodes.push(node);
|
|
486
|
+
}
|
|
487
|
+
mesh.meshHost = {
|
|
488
|
+
...meshHost,
|
|
489
|
+
pairing: {
|
|
490
|
+
...(meshHost.pairing || {}),
|
|
491
|
+
status: 'paired',
|
|
492
|
+
tokenId: validation.tokenId,
|
|
493
|
+
joinedAt: now,
|
|
494
|
+
lastPairedAt: meshHost.pairing?.lastPairedAt || now,
|
|
495
|
+
...(meshHost.pairing?.expiresAt ? { expiresAt: meshHost.pairing.expiresAt } : {}),
|
|
496
|
+
},
|
|
497
|
+
};
|
|
498
|
+
mesh.updatedAt = now;
|
|
499
|
+
saveMeshConfig(config);
|
|
500
|
+
return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export function markMeshHostPairingJoined(
|
|
504
|
+
meshId: string,
|
|
505
|
+
opts: { hostDaemonId?: string; hostNodeId?: string; joinedAt?: string; token?: string; tokenId?: string },
|
|
506
|
+
): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata } | undefined {
|
|
507
|
+
const config = loadMeshConfig();
|
|
508
|
+
const mesh = config.meshes.find(m => m.id === meshId);
|
|
509
|
+
if (!mesh) return undefined;
|
|
510
|
+
const now = opts.joinedAt || new Date().toISOString();
|
|
511
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
512
|
+
const tokenId = opts.tokenId || (opts.token ? tokenIdForManualPairing(opts.token) : previous.pairing?.tokenId);
|
|
513
|
+
mesh.meshHost = {
|
|
514
|
+
...previous,
|
|
515
|
+
role: 'member',
|
|
516
|
+
...(opts.hostDaemonId ? { hostDaemonId: opts.hostDaemonId } : {}),
|
|
517
|
+
...(opts.hostNodeId ? { hostNodeId: opts.hostNodeId } : {}),
|
|
518
|
+
pairing: {
|
|
519
|
+
...(previous.pairing || {}),
|
|
520
|
+
status: 'paired',
|
|
521
|
+
...(tokenId ? { tokenId } : {}),
|
|
522
|
+
joinedAt: now,
|
|
523
|
+
lastPairedAt: previous.pairing?.lastPairedAt || now,
|
|
524
|
+
},
|
|
525
|
+
};
|
|
526
|
+
mesh.updatedAt = now;
|
|
527
|
+
saveMeshConfig(config);
|
|
528
|
+
return { mesh, meshHost: mesh.meshHost };
|
|
529
|
+
}
|
|
530
|
+
|
|
177
531
|
// ─── Node Operations ────────────────────────────
|
|
178
532
|
|
|
179
533
|
export interface AddNodeOptions {
|
|
@@ -181,11 +535,14 @@ export interface AddNodeOptions {
|
|
|
181
535
|
repoRoot?: string;
|
|
182
536
|
daemonId?: string;
|
|
183
537
|
machineId?: string;
|
|
538
|
+
capabilities?: string[];
|
|
184
539
|
userOverrides?: Partial<RepoMeshNodeCapabilities>;
|
|
185
540
|
policy?: RepoMeshNodePolicy;
|
|
186
541
|
isLocalWorktree?: boolean;
|
|
187
542
|
worktreeBranch?: string;
|
|
188
543
|
clonedFromNodeId?: string;
|
|
544
|
+
worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
|
|
545
|
+
role?: RepoMeshDaemonRole;
|
|
189
546
|
}
|
|
190
547
|
|
|
191
548
|
export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntry | undefined {
|
|
@@ -208,11 +565,14 @@ export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntr
|
|
|
208
565
|
repoRoot: opts.repoRoot,
|
|
209
566
|
daemonId: opts.daemonId,
|
|
210
567
|
machineId: opts.machineId,
|
|
568
|
+
capabilities: normalizeCapabilityTags(opts.capabilities),
|
|
211
569
|
userOverrides: opts.userOverrides || {},
|
|
212
570
|
policy: opts.policy || {},
|
|
213
571
|
isLocalWorktree: opts.isLocalWorktree,
|
|
214
572
|
worktreeBranch: opts.worktreeBranch,
|
|
215
573
|
clonedFromNodeId: opts.clonedFromNodeId,
|
|
574
|
+
worktreeBootstrap: opts.worktreeBootstrap,
|
|
575
|
+
role: opts.role,
|
|
216
576
|
};
|
|
217
577
|
|
|
218
578
|
mesh.nodes.push(node);
|
|
@@ -238,7 +598,19 @@ export function removeNode(meshId: string, nodeId: string): boolean {
|
|
|
238
598
|
export function updateNode(
|
|
239
599
|
meshId: string,
|
|
240
600
|
nodeId: string,
|
|
241
|
-
opts: {
|
|
601
|
+
opts: {
|
|
602
|
+
userOverrides?: Partial<RepoMeshNodeCapabilities>;
|
|
603
|
+
policy?: RepoMeshNodePolicy;
|
|
604
|
+
worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
|
|
605
|
+
/** Per-node instruction surfaced in the coordinator prompt. Pass an
|
|
606
|
+
* empty string or undefined to clear it. */
|
|
607
|
+
systemPrompt?: string;
|
|
608
|
+
/** Live self-reported platform/arch from the owning daemon's git_status
|
|
609
|
+
* envelope. Persisted distinctly from userOverrides (auto-detected, not
|
|
610
|
+
* operator intent) so capability-tag os=/arch= self-heals across loads. */
|
|
611
|
+
reportedPlatform?: string;
|
|
612
|
+
reportedArch?: string;
|
|
613
|
+
},
|
|
242
614
|
): LocalMeshNodeEntry | undefined {
|
|
243
615
|
const config = loadMeshConfig();
|
|
244
616
|
const mesh = config.meshes.find(m => m.id === meshId);
|
|
@@ -248,7 +620,18 @@ export function updateNode(
|
|
|
248
620
|
if (!node) return undefined;
|
|
249
621
|
|
|
250
622
|
if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
|
|
623
|
+
if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
|
|
624
|
+
if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
|
|
251
625
|
if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
|
|
626
|
+
if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
|
|
627
|
+
if (Object.prototype.hasOwnProperty.call(opts, 'systemPrompt')) {
|
|
628
|
+
// Honor explicit clears: { systemPrompt: undefined } drops the field.
|
|
629
|
+
if (opts.systemPrompt && opts.systemPrompt.trim()) {
|
|
630
|
+
node.systemPrompt = opts.systemPrompt;
|
|
631
|
+
} else {
|
|
632
|
+
delete node.systemPrompt;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
252
635
|
mesh.updatedAt = new Date().toISOString();
|
|
253
636
|
saveMeshConfig(config);
|
|
254
637
|
return node;
|
|
@@ -92,12 +92,18 @@ export function buildSessionReadStateKey(sessionId: string, providerSessionId?:
|
|
|
92
92
|
|
|
93
93
|
export function getSessionSeenAt(state: DaemonState, sessionId: string, providerSessionId?: string | null): number {
|
|
94
94
|
const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
|
|
95
|
-
return state.sessionReads?.[providerKey] || state.sessionReads?.[sessionId] || 0;
|
|
95
|
+
return Math.max(state.sessionReads?.[providerKey] || 0, state.sessionReads?.[sessionId] || 0);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export function getSessionSeenMarker(state: DaemonState, sessionId: string, providerSessionId?: string | null): string {
|
|
99
99
|
const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
|
|
100
|
-
|
|
100
|
+
const providerSeenAt = state.sessionReads?.[providerKey] || 0;
|
|
101
|
+
const sessionSeenAt = state.sessionReads?.[sessionId] || 0;
|
|
102
|
+
const providerMarker = state.sessionReadMarkers?.[providerKey] || '';
|
|
103
|
+
const sessionMarker = state.sessionReadMarkers?.[sessionId] || '';
|
|
104
|
+
if (sessionSeenAt > providerSeenAt && sessionMarker) return sessionMarker;
|
|
105
|
+
if (providerSeenAt > sessionSeenAt && providerMarker) return providerMarker;
|
|
106
|
+
return providerMarker || sessionMarker;
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
export function getSessionNotificationDismissal(state: DaemonState, sessionId: string, providerSessionId?: string | null): string {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as os from 'os';
|
|
12
|
+
import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from '@adhdev/session-host-core';
|
|
12
13
|
import type * as http from 'http';
|
|
13
14
|
import type { ChildProcess } from 'child_process';
|
|
14
15
|
import type { DevServerContext, ProviderCategory } from './dev-server-types.js';
|
|
@@ -482,8 +483,8 @@ export async function handleAutoImplement(ctx: DevServerContext, type: string, r
|
|
|
482
483
|
const isWin = os.platform() === 'win32';
|
|
483
484
|
child = pty.spawn(isWin ? 'cmd.exe' : (process.env.SHELL || '/bin/zsh'), [isWin ? '/c' : '-c', shellCmd], {
|
|
484
485
|
name: 'xterm-256color',
|
|
485
|
-
cols:
|
|
486
|
-
rows:
|
|
486
|
+
cols: DEFAULT_SESSION_HOST_COLS,
|
|
487
|
+
rows: DEFAULT_SESSION_HOST_ROWS,
|
|
487
488
|
cwd: providerDir,
|
|
488
489
|
env: { ...process.env, ...(spawn.env || {}) },
|
|
489
490
|
});
|
|
@@ -802,7 +802,16 @@ export async function handleCliSend(ctx: DevServerContext, req: http.IncomingMes
|
|
|
802
802
|
}
|
|
803
803
|
|
|
804
804
|
try {
|
|
805
|
-
|
|
805
|
+
if (target.category === 'cli') {
|
|
806
|
+
const bundle = getCliTargetBundle(ctx, type, instanceId);
|
|
807
|
+
if (!bundle) {
|
|
808
|
+
ctx.json(res, 404, { error: `No running CLI adapter found for: ${type || instanceId}` });
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
await bundle.adapter.sendMessage(text);
|
|
812
|
+
} else {
|
|
813
|
+
ctx.instanceManager!.sendEvent(target.instanceId, 'send_message', { text });
|
|
814
|
+
}
|
|
806
815
|
ctx.json(res, 200, { sent: true, type: target.type, instanceId: target.instanceId });
|
|
807
816
|
} catch (e: any) {
|
|
808
817
|
ctx.json(res, 500, { error: `Send failed: ${e.message}` });
|