@adhdev/daemon-core 0.9.82-rc.44 → 0.9.82-rc.440
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 +120 -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 +50679 -20122
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47546 -17153
- 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 +29 -0
- package/dist/mesh/mesh-init.d.ts +128 -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 +300 -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 +252 -3
- package/dist/providers/contracts.d.ts +149 -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 +509 -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 +572 -27
- 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 +714 -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 +1242 -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 +2846 -3484
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +310 -45
- package/src/config/chat-history.ts +493 -24
- package/src/config/config.ts +12 -0
- package/src/config/mesh-config.ts +593 -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 +196 -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 +415 -34
- 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 +1897 -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 +111 -0
- package/src/mesh/mesh-init.ts +350 -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 +1924 -0
- package/src/mesh/mesh-reconcile-loop.ts +1997 -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 +1254 -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 +2001 -106
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +160 -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 +345 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +260 -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 +509 -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 +1143 -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 +748 -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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest validators — runtime JSON Schema check for v1 provider manifests.
|
|
3
|
+
*
|
|
4
|
+
* The schemas live under `schemas/{category}/provider.schema.json` and are
|
|
5
|
+
* the authoritative contract for what a v1 manifest may contain. Daemon
|
|
6
|
+
* code that loads a manifest at install or boot time runs it through
|
|
7
|
+
* `validateCliProviderManifest()` first; failures are reported back to
|
|
8
|
+
* the caller with structured paths so manifest authors can locate the
|
|
9
|
+
* offending field without guessing.
|
|
10
|
+
*
|
|
11
|
+
* Validation lives in the SDK layer (not in provider-loader) so dashboards,
|
|
12
|
+
* registry workers, and the provider publish flow can all reuse the
|
|
13
|
+
* same code path and produce identical error messages.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import Ajv2020, { type ErrorObject, type ValidateFunction } from 'ajv/dist/2020.js';
|
|
17
|
+
import addFormats from 'ajv-formats';
|
|
18
|
+
import cliProviderSchema from '../schemas/cli/provider.schema.json';
|
|
19
|
+
|
|
20
|
+
export interface ManifestValidationIssue {
|
|
21
|
+
/** JSON Pointer-style path into the manifest. Empty string for the root. */
|
|
22
|
+
path: string;
|
|
23
|
+
/** Schema-keyword that failed. */
|
|
24
|
+
keyword: string;
|
|
25
|
+
/** Human-readable explanation. */
|
|
26
|
+
message: string;
|
|
27
|
+
/** Allowed values when the failure is an `enum` / `const` / `additionalProperties`. */
|
|
28
|
+
allowed?: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ManifestValidationResult {
|
|
32
|
+
ok: boolean;
|
|
33
|
+
issues: ManifestValidationIssue[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let _ajv: Ajv2020 | null = null;
|
|
37
|
+
let _cliValidator: ValidateFunction | null = null;
|
|
38
|
+
|
|
39
|
+
function getAjv(): Ajv2020 {
|
|
40
|
+
if (_ajv) return _ajv;
|
|
41
|
+
// strict=false because the schema authors freely use schema-level
|
|
42
|
+
// `description`/`examples` fields that ajv would otherwise warn about.
|
|
43
|
+
// allErrors=true so a single validation run reports every problem at
|
|
44
|
+
// once instead of bailing on the first — that's what makes the
|
|
45
|
+
// structured-error output usable for manifest authors.
|
|
46
|
+
_ajv = new Ajv2020({
|
|
47
|
+
strict: false,
|
|
48
|
+
allErrors: true,
|
|
49
|
+
allowUnionTypes: true,
|
|
50
|
+
});
|
|
51
|
+
addFormats(_ajv);
|
|
52
|
+
return _ajv;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getCliValidator(): ValidateFunction {
|
|
56
|
+
if (_cliValidator) return _cliValidator;
|
|
57
|
+
_cliValidator = getAjv().compile(cliProviderSchema as unknown as object);
|
|
58
|
+
return _cliValidator;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function formatIssue(err: ErrorObject): ManifestValidationIssue {
|
|
62
|
+
const path = err.instancePath || '';
|
|
63
|
+
const params = err.params as Record<string, unknown>;
|
|
64
|
+
let message = err.message || 'validation failed';
|
|
65
|
+
let allowed: unknown;
|
|
66
|
+
|
|
67
|
+
if (err.keyword === 'additionalProperties') {
|
|
68
|
+
const extra = params.additionalProperty;
|
|
69
|
+
message = `unexpected property "${extra}"`;
|
|
70
|
+
} else if (err.keyword === 'required') {
|
|
71
|
+
message = `missing required property "${params.missingProperty}"`;
|
|
72
|
+
} else if (err.keyword === 'enum') {
|
|
73
|
+
allowed = params.allowedValues;
|
|
74
|
+
message = `must be one of ${JSON.stringify(allowed)}`;
|
|
75
|
+
} else if (err.keyword === 'const') {
|
|
76
|
+
allowed = params.allowedValue;
|
|
77
|
+
message = `must equal ${JSON.stringify(allowed)}`;
|
|
78
|
+
} else if (err.keyword === 'type') {
|
|
79
|
+
message = `must be ${params.type}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { path, keyword: err.keyword, message, ...(allowed !== undefined ? { allowed } : {}) };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Validate a CLI provider.v1.json manifest. Returns `{ ok: true, issues: [] }`
|
|
87
|
+
* on success and `{ ok: false, issues: [...] }` on failure with each issue
|
|
88
|
+
* pointing at the offending field. Never throws — manifest parse errors
|
|
89
|
+
* should be caught by the caller before this is called.
|
|
90
|
+
*/
|
|
91
|
+
export function validateCliProviderManifest(manifest: unknown): ManifestValidationResult {
|
|
92
|
+
const validator = getCliValidator();
|
|
93
|
+
const ok = validator(manifest) as boolean;
|
|
94
|
+
if (ok) return { ok: true, issues: [] };
|
|
95
|
+
const issues = (validator.errors || []).map(formatIssue);
|
|
96
|
+
return { ok: false, issues };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Render a list of validation issues as a single multi-line string,
|
|
101
|
+
* suitable for log lines or daemon command error fields.
|
|
102
|
+
*/
|
|
103
|
+
export function formatManifestValidationIssues(issues: ManifestValidationIssue[]): string {
|
|
104
|
+
return issues
|
|
105
|
+
.map((issue) => {
|
|
106
|
+
const where = issue.path || '<root>';
|
|
107
|
+
return ` - ${where}: ${issue.message} (${issue.keyword})`;
|
|
108
|
+
})
|
|
109
|
+
.join('\n');
|
|
110
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static taint analyzer for extended-tier override JS.
|
|
3
|
+
*
|
|
4
|
+
* Goal: classify the override JS shipped with an extended-tier provider into
|
|
5
|
+
* one of three risk tiers, so the dashboard + daemon trust prompt can
|
|
6
|
+
* surface accurate language to the operator instead of a single generic
|
|
7
|
+
* "this provider contains JS" warning.
|
|
8
|
+
*
|
|
9
|
+
* - clean : no flagged APIs at all. The override looks like pure string
|
|
10
|
+
* manipulation. Still extended-tier, but the warning copy is
|
|
11
|
+
* "this provider contains JS; nothing dangerous was detected".
|
|
12
|
+
* - elevated : touches process / dynamic codegen / dynamic require / eval
|
|
13
|
+
* / Function constructor / child_process. The warning copy is
|
|
14
|
+
* explicit ("this provider can run shell commands / dynamically
|
|
15
|
+
* load code").
|
|
16
|
+
* - hostile : combines elevated APIs with network egress, AND uses obvious
|
|
17
|
+
* obfuscation (base64-decoded strings fed into Function / eval).
|
|
18
|
+
* The publish endpoint should reject these.
|
|
19
|
+
*
|
|
20
|
+
* Implementation note: this is a *static* analyzer — string + light AST scan
|
|
21
|
+
* via Node's built-in parser. It is intentionally fail-loud: anything that
|
|
22
|
+
* looks suspicious is flagged. False positives are fine; this exists to gate
|
|
23
|
+
* the trust prompt, not to be a real sandbox. The real sandbox lives in
|
|
24
|
+
* Phase 5 (isolated-vm).
|
|
25
|
+
*
|
|
26
|
+
* Used by:
|
|
27
|
+
* - `adhdev provider validate` (CLI tier classification)
|
|
28
|
+
* - registry publish endpoint static-check
|
|
29
|
+
* - daemon at provider-load time, to size the warning
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
33
|
+
import { resolve, dirname, join } from 'node:path';
|
|
34
|
+
|
|
35
|
+
// ─── Findings ──────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
export type TaintLevel = 'clean' | 'elevated' | 'hostile';
|
|
38
|
+
|
|
39
|
+
export interface TaintFinding {
|
|
40
|
+
/** What was found, e.g. "child_process.exec". */
|
|
41
|
+
api: string;
|
|
42
|
+
/** Coarse category. */
|
|
43
|
+
category: TaintCategory;
|
|
44
|
+
/** File the finding came from. */
|
|
45
|
+
file: string;
|
|
46
|
+
/** Line number (1-indexed) of the first character of the matched token. */
|
|
47
|
+
line: number;
|
|
48
|
+
/** The surrounding source excerpt, trimmed. */
|
|
49
|
+
excerpt: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type TaintCategory =
|
|
53
|
+
| 'process-control' // process.exit, process.kill
|
|
54
|
+
| 'shell-exec' // child_process.{exec,execSync,spawn,spawnSync,fork}
|
|
55
|
+
| 'fs-write' // fs.writeFile / writeFileSync outside override dir
|
|
56
|
+
| 'fs-read' // fs.readFile / readFileSync
|
|
57
|
+
| 'network' // http(s).request, fetch, net.connect, dgram
|
|
58
|
+
| 'dynamic-codegen' // eval, new Function(), Function('...')
|
|
59
|
+
| 'dynamic-require' // require(variable), import(variable)
|
|
60
|
+
| 'obfuscation' // Buffer.from(...,'base64').toString + (eval|Function)
|
|
61
|
+
| 'global-mutation'; // mutating Object.prototype, process.env
|
|
62
|
+
|
|
63
|
+
export interface TaintResult {
|
|
64
|
+
level: TaintLevel;
|
|
65
|
+
findings: TaintFinding[];
|
|
66
|
+
files: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ─── Patterns ──────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
interface PatternRule {
|
|
72
|
+
category: TaintCategory;
|
|
73
|
+
/** Display label. */
|
|
74
|
+
label: string;
|
|
75
|
+
/** Regex applied per-line. */
|
|
76
|
+
pattern: RegExp;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const PATTERNS: PatternRule[] = [
|
|
80
|
+
{
|
|
81
|
+
category: 'shell-exec',
|
|
82
|
+
label: 'child_process.exec',
|
|
83
|
+
pattern: /\bchild_process\b[\s\S]{0,40}?\b(exec|execSync|spawn|spawnSync|fork|execFile)\b/,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
category: 'shell-exec',
|
|
87
|
+
label: 'require("child_process")',
|
|
88
|
+
pattern: /\brequire\s*\(\s*['"]child_process['"]\s*\)/,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
category: 'shell-exec',
|
|
92
|
+
label: 'import child_process',
|
|
93
|
+
pattern: /\bfrom\s+['"](?:node:)?child_process['"]/,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
category: 'process-control',
|
|
97
|
+
label: 'process.exit / kill',
|
|
98
|
+
pattern: /\bprocess\.(exit|kill|abort)\s*\(/,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
category: 'global-mutation',
|
|
102
|
+
label: 'process.env mutation',
|
|
103
|
+
pattern: /\bprocess\.env\.[A-Z_][A-Z0-9_]*\s*=/,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
category: 'global-mutation',
|
|
107
|
+
label: 'prototype pollution',
|
|
108
|
+
pattern: /\bObject\.prototype\b.*=/,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
category: 'dynamic-codegen',
|
|
112
|
+
label: 'eval()',
|
|
113
|
+
pattern: /(?<![A-Za-z0-9_$])eval\s*\(/,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
category: 'dynamic-codegen',
|
|
117
|
+
label: 'new Function()',
|
|
118
|
+
pattern: /\bnew\s+Function\s*\(/,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
category: 'dynamic-require',
|
|
122
|
+
label: 'require(variable)',
|
|
123
|
+
pattern: /\brequire\s*\(\s*(?!['"`])/,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
category: 'dynamic-require',
|
|
127
|
+
label: 'import(variable)',
|
|
128
|
+
pattern: /(?<![.\w])import\s*\(\s*(?!['"`])/,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
category: 'network',
|
|
132
|
+
label: 'fetch()',
|
|
133
|
+
pattern: /(?<![A-Za-z0-9_$])fetch\s*\(/,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
category: 'network',
|
|
137
|
+
label: 'http(s).request',
|
|
138
|
+
pattern: /\b(https?)\.(request|get)\s*\(/,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
category: 'network',
|
|
142
|
+
label: 'net.connect / Socket',
|
|
143
|
+
pattern: /\b(net\.connect|tls\.connect|new\s+net\.Socket)\b/,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
category: 'network',
|
|
147
|
+
label: 'dgram',
|
|
148
|
+
pattern: /\brequire\s*\(\s*['"](?:node:)?dgram['"]/,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
category: 'fs-write',
|
|
152
|
+
label: 'fs.writeFile / writeFileSync',
|
|
153
|
+
pattern: /\bfs\.(writeFile|writeFileSync|appendFile|appendFileSync|unlink|unlinkSync|rm|rmSync)\b/,
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
category: 'fs-read',
|
|
157
|
+
label: 'fs.readFile / readFileSync',
|
|
158
|
+
pattern: /\bfs\.(readFile|readFileSync|readdir|readdirSync|stat|statSync)\b/,
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
// Obfuscation heuristic: base64 / hex decode feeding into eval or Function.
|
|
163
|
+
const OBFUSCATION_PATTERN =
|
|
164
|
+
/Buffer\.from\s*\([^)]*['"](?:base64|hex)['"]\s*\)\s*\.toString\s*\([^)]*\)[\s\S]{0,80}?(eval|Function)\s*\(/;
|
|
165
|
+
|
|
166
|
+
// ─── File walker — picks up everything reachable from overrides ────────
|
|
167
|
+
|
|
168
|
+
function listOverrideJsFiles(manifestPath: string): string[] {
|
|
169
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as { overrides?: Record<string, unknown> };
|
|
170
|
+
if (!manifest.overrides) return [];
|
|
171
|
+
const base = dirname(manifestPath);
|
|
172
|
+
const out = new Set<string>();
|
|
173
|
+
for (const value of Object.values(manifest.overrides)) {
|
|
174
|
+
let rel: string | null = null;
|
|
175
|
+
if (typeof value === 'string') rel = value;
|
|
176
|
+
else if (value && typeof value === 'object' && 'path' in value && typeof (value as { path: unknown }).path === 'string') {
|
|
177
|
+
rel = (value as { path: string }).path;
|
|
178
|
+
}
|
|
179
|
+
if (!rel) continue;
|
|
180
|
+
const abs = resolve(base, rel);
|
|
181
|
+
if (existsSync(abs)) out.add(abs);
|
|
182
|
+
}
|
|
183
|
+
// Best-effort: also scan sibling scripts/ tree, since overrides commonly
|
|
184
|
+
// require() helpers from there.
|
|
185
|
+
for (const candidate of ['scripts']) {
|
|
186
|
+
const dir = join(base, candidate);
|
|
187
|
+
if (existsSync(dir)) {
|
|
188
|
+
try {
|
|
189
|
+
walk(dir, out);
|
|
190
|
+
} catch {
|
|
191
|
+
// Ignore individual unreadable files.
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return [...out];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function walk(dir: string, into: Set<string>): void {
|
|
199
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
200
|
+
const { readdirSync, statSync } = require('node:fs') as typeof import('node:fs');
|
|
201
|
+
for (const entry of readdirSync(dir)) {
|
|
202
|
+
const abs = join(dir, entry);
|
|
203
|
+
let st;
|
|
204
|
+
try { st = statSync(abs); } catch { continue; }
|
|
205
|
+
if (st.isDirectory()) walk(abs, into);
|
|
206
|
+
else if (st.isFile() && /\.(?:m|c)?js$/.test(entry)) into.add(abs);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ─── Scanner ───────────────────────────────────────────────────────────
|
|
211
|
+
|
|
212
|
+
function scanFile(file: string): TaintFinding[] {
|
|
213
|
+
const source = readFileSync(file, 'utf-8');
|
|
214
|
+
const findings: TaintFinding[] = [];
|
|
215
|
+
// Per-line scan keeps line numbers honest.
|
|
216
|
+
const lines = source.split('\n');
|
|
217
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
218
|
+
const line = lines[i];
|
|
219
|
+
for (const rule of PATTERNS) {
|
|
220
|
+
if (rule.pattern.test(line)) {
|
|
221
|
+
findings.push({
|
|
222
|
+
api: rule.label,
|
|
223
|
+
category: rule.category,
|
|
224
|
+
file,
|
|
225
|
+
line: i + 1,
|
|
226
|
+
excerpt: line.trim().slice(0, 200),
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Whole-file scan for obfuscation pattern (may span lines).
|
|
232
|
+
if (OBFUSCATION_PATTERN.test(source)) {
|
|
233
|
+
findings.push({
|
|
234
|
+
api: 'base64/hex → eval|Function',
|
|
235
|
+
category: 'obfuscation',
|
|
236
|
+
file,
|
|
237
|
+
line: 1,
|
|
238
|
+
excerpt: '<obfuscation pattern across multiple lines>',
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return findings;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ─── Classification ────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
const ELEVATED_CATEGORIES = new Set<TaintCategory>([
|
|
247
|
+
'shell-exec',
|
|
248
|
+
'process-control',
|
|
249
|
+
'dynamic-codegen',
|
|
250
|
+
'dynamic-require',
|
|
251
|
+
'fs-write',
|
|
252
|
+
'global-mutation',
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
const HOSTILE_REQUIRES = new Set<TaintCategory>([
|
|
256
|
+
'obfuscation',
|
|
257
|
+
]);
|
|
258
|
+
|
|
259
|
+
function classify(findings: TaintFinding[]): TaintLevel {
|
|
260
|
+
if (findings.length === 0) return 'clean';
|
|
261
|
+
const cats = new Set(findings.map((f) => f.category));
|
|
262
|
+
if ([...cats].some((c) => HOSTILE_REQUIRES.has(c))) return 'hostile';
|
|
263
|
+
// Hostile also: elevated + network combined.
|
|
264
|
+
const hasElevated = [...cats].some((c) => ELEVATED_CATEGORIES.has(c));
|
|
265
|
+
const hasNetwork = cats.has('network');
|
|
266
|
+
if (hasElevated && hasNetwork) return 'hostile';
|
|
267
|
+
if (hasElevated || hasNetwork) return 'elevated';
|
|
268
|
+
return 'clean'; // only fs-read on its own is fine.
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ─── Public API ────────────────────────────────────────────────────────
|
|
272
|
+
|
|
273
|
+
export function analyzeOverrideTaint(manifestPath: string): TaintResult {
|
|
274
|
+
const files = listOverrideJsFiles(manifestPath);
|
|
275
|
+
const findings: TaintFinding[] = [];
|
|
276
|
+
for (const f of files) findings.push(...scanFile(f));
|
|
277
|
+
return {
|
|
278
|
+
level: classify(findings),
|
|
279
|
+
findings,
|
|
280
|
+
files,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Format a result as a single CLI-friendly block. */
|
|
285
|
+
export function formatTaintResult(result: TaintResult): string {
|
|
286
|
+
const lines: string[] = [];
|
|
287
|
+
lines.push(`Tier: extended (override JS present)`);
|
|
288
|
+
lines.push(`Risk level: ${result.level}`);
|
|
289
|
+
lines.push(`Files scanned: ${result.files.length}`);
|
|
290
|
+
if (result.findings.length === 0) {
|
|
291
|
+
lines.push('No flagged APIs detected.');
|
|
292
|
+
return lines.join('\n');
|
|
293
|
+
}
|
|
294
|
+
// Group by category for a tighter report.
|
|
295
|
+
const byCat = new Map<TaintCategory, TaintFinding[]>();
|
|
296
|
+
for (const f of result.findings) {
|
|
297
|
+
const arr = byCat.get(f.category) ?? [];
|
|
298
|
+
arr.push(f);
|
|
299
|
+
byCat.set(f.category, arr);
|
|
300
|
+
}
|
|
301
|
+
for (const [cat, items] of byCat) {
|
|
302
|
+
lines.push(` ${cat}: ${items.length} occurrence(s)`);
|
|
303
|
+
for (const f of items.slice(0, 5)) {
|
|
304
|
+
lines.push(` ${f.file}:${f.line} ${f.api}`);
|
|
305
|
+
}
|
|
306
|
+
if (items.length > 5) lines.push(` …and ${items.length - 5} more`);
|
|
307
|
+
}
|
|
308
|
+
return lines.join('\n');
|
|
309
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PTY + terminal-screen adapter for the spec driver.
|
|
3
|
+
*
|
|
4
|
+
* Spawns a PTY, feeds bytes into a TerminalScreen (ghostty-vt when available,
|
|
5
|
+
* xterm fallback otherwise) so a visible-screen snapshot is always available,
|
|
6
|
+
* and exposes a small hook surface for the SpecDriver to consume:
|
|
7
|
+
*
|
|
8
|
+
* init({ pid }) — PTY spawned
|
|
9
|
+
* on_pty_data(chunk) — raw PTY byte chunk received
|
|
10
|
+
* on_screen_changed(snapshot) — coalesced visible-screen change
|
|
11
|
+
* on_exit({ exitCode }) — PTY exited
|
|
12
|
+
* tick() — periodic tick (if tickIntervalMs > 0)
|
|
13
|
+
*/
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
import { TerminalScreen } from '../../cli-adapters/terminal-screen.js';
|
|
17
|
+
import type { PtyTransportFactory } from '../../cli-adapters/pty-transport.js';
|
|
18
|
+
import type { PtyRuntimeTransport } from '../../cli-adapters/pty-transport.js';
|
|
19
|
+
import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from '@adhdev/session-host-core';
|
|
20
|
+
|
|
21
|
+
export type { PtyTransportFactory };
|
|
22
|
+
|
|
23
|
+
export interface TerminalAdapterOpts {
|
|
24
|
+
binary: string;
|
|
25
|
+
args?: string[];
|
|
26
|
+
cwd?: string;
|
|
27
|
+
env?: Record<string, string>;
|
|
28
|
+
/**
|
|
29
|
+
* When true, `env` is already a COMPLETE, sanitized environment (the spawn
|
|
30
|
+
* planner merged + stripped process.env already) and must be passed to the
|
|
31
|
+
* PTY verbatim — NOT overlaid on top of process.env. Overlaying would
|
|
32
|
+
* re-introduce the npm_/PNPM_/parent-session keys the planner explicitly
|
|
33
|
+
* stripped, so the spec path's spawn env would diverge from the legacy
|
|
34
|
+
* path's. Defaults to false (legacy overlay behaviour) for any caller that
|
|
35
|
+
* still passes a partial env.
|
|
36
|
+
*/
|
|
37
|
+
envIsComplete?: boolean;
|
|
38
|
+
cols?: number;
|
|
39
|
+
rows?: number;
|
|
40
|
+
/** Coalesce screen snapshots: emit on_screen_changed at most this often. */
|
|
41
|
+
screenChangeDebounceMs?: number;
|
|
42
|
+
tickIntervalMs?: number;
|
|
43
|
+
transportFactory?: PtyTransportFactory;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface TerminalAdapterHandlers {
|
|
47
|
+
init?(info: { pid: number }): void;
|
|
48
|
+
on_pty_data?(chunk: string): void;
|
|
49
|
+
on_screen_changed?(snapshot: string): void;
|
|
50
|
+
on_exit?(info: { exitCode: number }): void;
|
|
51
|
+
tick?(): void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* One entry in the PTY input/output event timeline (debug-only). Captured at
|
|
56
|
+
* the single common point every spec@4 provider funnels through — this adapter
|
|
57
|
+
* — so the Spec Debug Snapshot can answer "what input / output preceded a status
|
|
58
|
+
* transition?". Observation only; nothing here feeds the FSM decision.
|
|
59
|
+
*/
|
|
60
|
+
export interface SpecPtyEvent {
|
|
61
|
+
/** Wall-clock ms. */
|
|
62
|
+
ts: number;
|
|
63
|
+
kind: 'spawn' | 'input' | 'output' | 'resize' | 'cursor' | 'exit';
|
|
64
|
+
/** Human-readable, control-char-escaped, length-capped preview. */
|
|
65
|
+
content: string;
|
|
66
|
+
/** Raw byte length before truncation (output/input only). */
|
|
67
|
+
bytes?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const MAX_PTY_EVENTS = 300;
|
|
71
|
+
const EVENT_CONTENT_CAP = 240;
|
|
72
|
+
|
|
73
|
+
/** Escape control characters into a visible form so the timeline is readable
|
|
74
|
+
* (CR/LF/ESC/tab become \r \n \x1b \t; other C0 controls become \xNN). */
|
|
75
|
+
function escapeControl(text: string): string {
|
|
76
|
+
// eslint-disable-next-line no-control-regex
|
|
77
|
+
return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
|
|
78
|
+
const code = ch.charCodeAt(0);
|
|
79
|
+
if (ch === '\r') return '\\r';
|
|
80
|
+
if (ch === '\n') return '\\n';
|
|
81
|
+
if (ch === '\t') return '\\t';
|
|
82
|
+
if (code === 0x1b) return '\\x1b';
|
|
83
|
+
return '\\x' + code.toString(16).padStart(2, '0');
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function capPreview(text: string): string {
|
|
88
|
+
return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `…(+${text.length - EVENT_CONTENT_CAP})` : text;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export class TerminalAdapter {
|
|
92
|
+
private rows: number;
|
|
93
|
+
private cols: number;
|
|
94
|
+
private readonly screenDebounceMs: number;
|
|
95
|
+
private readonly tickIntervalMs: number;
|
|
96
|
+
private readonly factory: PtyTransportFactory;
|
|
97
|
+
private screen: TerminalScreen;
|
|
98
|
+
private pty: PtyRuntimeTransport | null = null;
|
|
99
|
+
private screenTimer: ReturnType<typeof setTimeout> | null = null;
|
|
100
|
+
private tickTimer: ReturnType<typeof setInterval> | null = null;
|
|
101
|
+
private lastScreen = '';
|
|
102
|
+
/** Debug-only ring buffer of PTY input/output/resize/cursor events. */
|
|
103
|
+
private events: SpecPtyEvent[] = [];
|
|
104
|
+
private lastCursorKey = '';
|
|
105
|
+
|
|
106
|
+
constructor(
|
|
107
|
+
private readonly opts: TerminalAdapterOpts,
|
|
108
|
+
private readonly handlers: TerminalAdapterHandlers,
|
|
109
|
+
) {
|
|
110
|
+
this.cols = opts.cols ?? DEFAULT_SESSION_HOST_COLS;
|
|
111
|
+
this.rows = opts.rows ?? DEFAULT_SESSION_HOST_ROWS;
|
|
112
|
+
this.screenDebounceMs = opts.screenChangeDebounceMs ?? 80;
|
|
113
|
+
this.tickIntervalMs = opts.tickIntervalMs ?? 0;
|
|
114
|
+
// Import NodePtyTransportFactory lazily to avoid loading node-pty in
|
|
115
|
+
// environments that don't need it (tests, fixture runners) — only when
|
|
116
|
+
// no transport factory was injected. Doing it unconditionally pulled in
|
|
117
|
+
// the node-pty module (and broke source-level test runs) even when a
|
|
118
|
+
// fake factory was supplied.
|
|
119
|
+
if (opts.transportFactory) {
|
|
120
|
+
this.factory = opts.transportFactory;
|
|
121
|
+
} else {
|
|
122
|
+
const { NodePtyTransportFactory } = require('../../cli-adapters/pty-transport.js');
|
|
123
|
+
this.factory = new NodePtyTransportFactory();
|
|
124
|
+
}
|
|
125
|
+
this.screen = new TerminalScreen(this.rows, this.cols);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
start(): void {
|
|
129
|
+
const env = this.opts.envIsComplete
|
|
130
|
+
? ((this.opts.env ?? {}) as Record<string, string>)
|
|
131
|
+
: ({ ...process.env, ...(this.opts.env ?? {}) } as Record<string, string>);
|
|
132
|
+
this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
|
|
133
|
+
cwd: this.opts.cwd ?? process.cwd(),
|
|
134
|
+
env,
|
|
135
|
+
cols: this.cols,
|
|
136
|
+
rows: this.rows,
|
|
137
|
+
});
|
|
138
|
+
this.recordEvent('spawn', `${this.opts.binary} (${this.cols}x${this.rows})`);
|
|
139
|
+
this.handlers.init?.({ pid: this.pty.pid });
|
|
140
|
+
this.pty.onData((chunk) => this.onChunk(chunk));
|
|
141
|
+
this.pty.onExit((info) => {
|
|
142
|
+
this.stopTimers();
|
|
143
|
+
this.recordEvent('exit', `exitCode=${typeof info.exitCode === 'number' ? info.exitCode : 0}`);
|
|
144
|
+
this.handlers.on_exit?.({ exitCode: typeof info.exitCode === 'number' ? info.exitCode : 0 });
|
|
145
|
+
this.pty = null;
|
|
146
|
+
});
|
|
147
|
+
if (this.tickIntervalMs > 0) {
|
|
148
|
+
this.tickTimer = setInterval(() => this.handlers.tick?.(), this.tickIntervalMs);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
resize(cols: number, rows: number): void {
|
|
153
|
+
this.cols = cols; this.rows = rows;
|
|
154
|
+
this.recordEvent('resize', `${cols}x${rows}`);
|
|
155
|
+
this.pty?.resize(cols, rows);
|
|
156
|
+
this.screen.resize(rows, cols);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
snapshot(): string {
|
|
160
|
+
return this.lastScreen || this.computeScreen();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Full-buffer snapshot including scrollback history. Unlike snapshot()
|
|
165
|
+
* (visible viewport only), this survives a tall prompt whose top has
|
|
166
|
+
* scrolled off-screen — used for content-pattern extraction (modal
|
|
167
|
+
* buttons / approval anchors), NOT for cursor-relative conditions.
|
|
168
|
+
*/
|
|
169
|
+
snapshotWithScrollback(): string {
|
|
170
|
+
return this.screen.getTextWithScrollback();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getCursorPosition(): { row: number; col: number } {
|
|
174
|
+
const pos = this.screen.getCursorPosition();
|
|
175
|
+
return { row: pos.row, col: pos.col };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
send_keys(text: string): void {
|
|
179
|
+
this.recordEvent('input', capPreview(escapeControl(text)), text.length);
|
|
180
|
+
this.pty?.write(text);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
|
|
184
|
+
* first. Pure observation — never consulted by the FSM. */
|
|
185
|
+
getEventTimeline(limit = MAX_PTY_EVENTS): SpecPtyEvent[] {
|
|
186
|
+
const n = Math.max(0, Math.min(limit, this.events.length));
|
|
187
|
+
return this.events.slice(this.events.length - n);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private recordEvent(kind: SpecPtyEvent['kind'], content: string, bytes?: number): void {
|
|
191
|
+
const ev: SpecPtyEvent = { ts: Date.now(), kind, content };
|
|
192
|
+
if (typeof bytes === 'number') ev.bytes = bytes;
|
|
193
|
+
this.events.push(ev);
|
|
194
|
+
if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
kill(): void {
|
|
198
|
+
this.stopTimers();
|
|
199
|
+
try { this.pty?.kill(); } catch { /* ignore */ }
|
|
200
|
+
this.pty = null;
|
|
201
|
+
this.screen.dispose();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private onChunk(chunk: string): void {
|
|
205
|
+
this.recordEvent('output', capPreview(escapeControl(chunk)), chunk.length);
|
|
206
|
+
try { this.handlers.on_pty_data?.(chunk); } catch { /* user side */ }
|
|
207
|
+
this.screen.write(chunk);
|
|
208
|
+
// Coalesce snapshot emission — rapid bursts shouldn't fire 200x.
|
|
209
|
+
if (this.screenTimer) return;
|
|
210
|
+
this.screenTimer = setTimeout(() => {
|
|
211
|
+
this.screenTimer = null;
|
|
212
|
+
const snap = this.computeScreen();
|
|
213
|
+
// Record cursor movement at the (debounced) screen-change boundary
|
|
214
|
+
// rather than per output chunk, so the timeline isn't flooded.
|
|
215
|
+
const cur = this.screen.getCursorPosition();
|
|
216
|
+
const curKey = `${cur.row},${cur.col}`;
|
|
217
|
+
if (curKey !== this.lastCursorKey) {
|
|
218
|
+
this.lastCursorKey = curKey;
|
|
219
|
+
this.recordEvent('cursor', `(${cur.row},${cur.col})`);
|
|
220
|
+
}
|
|
221
|
+
if (snap === this.lastScreen) return;
|
|
222
|
+
this.lastScreen = snap;
|
|
223
|
+
try { this.handlers.on_screen_changed?.(snap); } catch { /* user side */ }
|
|
224
|
+
}, this.screenDebounceMs);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private computeScreen(): string {
|
|
228
|
+
return this.screen.getText();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private stopTimers(): void {
|
|
232
|
+
if (this.screenTimer) { clearTimeout(this.screenTimer); this.screenTimer = null; }
|
|
233
|
+
if (this.tickTimer) { clearInterval(this.tickTimer); this.tickTimer = null; }
|
|
234
|
+
}
|
|
235
|
+
}
|