@adhdev/daemon-core 0.9.82-rc.47 → 0.9.82-rc.470
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 +25 -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 +64 -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 +48 -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 +152 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router-aggregate-status.d.ts +24 -0
- package/dist/commands/router-mesh-session-owner.d.ts +59 -0
- package/dist/commands/router-refine.d.ts +137 -0
- package/dist/commands/router-worktree-cleanup.d.ts +133 -0
- package/dist/commands/router.d.ts +204 -15
- package/dist/commands/upgrade-helper.d.ts +41 -1
- package/dist/config/chat-history.d.ts +9 -0
- package/dist/config/config.d.ts +19 -0
- package/dist/config/mesh-config.d.ts +136 -1
- package/dist/config/mesh-json-config.d.ts +199 -0
- package/dist/config/registry-resolver.d.ts +54 -0
- package/dist/config/repo-settings.d.ts +77 -0
- package/dist/daemon/dev-server.d.ts +0 -2
- package/dist/detection/cli-detector.d.ts +17 -0
- 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 +26 -2
- 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 +70 -16
- package/dist/index.js +58255 -24541
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59189 -25650
- 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/debug-config.d.ts +16 -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 +230 -0
- package/dist/mesh/coordinator-prompt.d.ts +76 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +203 -0
- package/dist/mesh/mesh-clone-grace.d.ts +8 -0
- package/dist/mesh/mesh-completion-synthesis.d.ts +4 -0
- package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +104 -0
- package/dist/mesh/mesh-event-classify.d.ts +7 -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 +246 -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 +139 -1
- package/dist/mesh/mesh-magi-status.d.ts +63 -0
- package/dist/mesh/mesh-missions.d.ts +226 -0
- package/dist/mesh/mesh-node-identity.d.ts +310 -0
- package/dist/mesh/mesh-queue-assignment.d.ts +158 -0
- package/dist/mesh/mesh-reconcile-acked-hold.d.ts +17 -0
- package/dist/mesh/mesh-reconcile-config.d.ts +6 -0
- package/dist/mesh/mesh-reconcile-identity.d.ts +6 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +80 -0
- package/dist/mesh/mesh-reconcile-v2-backstop.d.ts +16 -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-remote-event-pull.d.ts +15 -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 +508 -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 +363 -5
- package/dist/mesh/preview-freshness.d.ts +28 -0
- package/dist/mesh/refine-config.d.ts +216 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +219 -0
- package/dist/providers/acp-provider-instance.d.ts +5 -0
- package/dist/providers/approval-utils.d.ts +46 -0
- package/dist/providers/chat-message-normalization.d.ts +58 -1
- package/dist/providers/cli-provider-effect-format.d.ts +30 -0
- package/dist/providers/cli-provider-history-dedup.d.ts +17 -0
- package/dist/providers/cli-provider-input-prompt.d.ts +12 -0
- package/dist/providers/cli-provider-instance-types.d.ts +45 -0
- package/dist/providers/cli-provider-instance.d.ts +340 -30
- package/dist/providers/cli-provider-status-helpers.d.ts +46 -0
- package/dist/providers/cli-provider-transcript-merge.d.ts +7 -0
- package/dist/providers/contracts.d.ts +149 -6
- package/dist/providers/external-sources.d.ts +71 -0
- package/dist/providers/manual-attendance.d.ts +79 -0
- package/dist/providers/native-history/antigravity-claim-registry.d.ts +28 -0
- package/dist/providers/native-history/antigravity-cli-transcript.d.ts +137 -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 +31 -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 +30 -1
- package/dist/providers/provider-loader.d.ts +42 -5
- 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 +98 -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 +449 -0
- package/dist/providers/spec/fsm-evaluator.d.ts +93 -0
- package/dist/providers/spec/fsm-loader.d.ts +14 -0
- package/dist/providers/spec/fsm-types.d.ts +202 -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 +244 -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 +629 -12
- package/dist/runtime-defaults.d.ts +2 -0
- package/dist/session-host/managed-host.d.ts +64 -0
- package/dist/session-host/runtime-surface.d.ts +10 -16
- package/dist/sessions/registry.d.ts +6 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +86 -55
- 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 +11 -4
- package/src/agent-stream/poller.ts +2 -3
- package/src/agent-stream/provider-adapter.ts +1 -1
- package/src/boot/daemon-lifecycle.ts +80 -14
- 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/chat-commands-debug-bundle.ts +398 -0
- package/src/commands/chat-commands-read.ts +2488 -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 +596 -27
- package/src/commands/handler.ts +845 -2
- package/src/commands/high-family/index.ts +28 -0
- package/src/commands/high-family/mesh-coordinator-launch.ts +680 -0
- package/src/commands/high-family/mesh-events.ts +102 -0
- package/src/commands/high-family/mesh-status.ts +849 -0
- package/src/commands/high-family/types.ts +80 -0
- package/src/commands/low-family/coordinator-prompt.ts +72 -0
- package/src/commands/low-family/daemon-lifecycle.ts +120 -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 +241 -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 +1287 -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 +153 -0
- package/src/commands/mesh-coordinator.ts +334 -124
- package/src/commands/router-aggregate-status.ts +209 -0
- package/src/commands/router-mesh-session-owner.ts +114 -0
- package/src/commands/router-refine.ts +1711 -0
- package/src/commands/router-worktree-cleanup.ts +870 -0
- package/src/commands/router.ts +795 -4143
- 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 +30 -0
- package/src/config/mesh-config.ts +632 -23
- package/src/config/mesh-json-config.ts +376 -0
- package/src/config/recent-activity.ts +8 -2
- package/src/config/registry-resolver.ts +100 -0
- 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 +94 -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 +112 -16
- 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 +207 -13
- 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/debug-config.ts +25 -0
- package/src/logging/debug-trace.ts +7 -2
- 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 +469 -0
- package/src/mesh/coordinator-prompt.ts +572 -34
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +706 -0
- package/src/mesh/mesh-clone-grace.ts +68 -0
- package/src/mesh/mesh-completion-synthesis.ts +398 -0
- package/src/mesh/mesh-coordinator-config.ts +97 -0
- package/src/mesh/mesh-delivery-policy.ts +284 -0
- package/src/mesh/mesh-event-classify.ts +78 -0
- package/src/mesh/mesh-event-forwarding.ts +1964 -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 +1494 -0
- package/src/mesh/mesh-events-stale.ts +440 -0
- package/src/mesh/mesh-events-utils.ts +443 -0
- package/src/mesh/mesh-events.ts +43 -1035
- package/src/mesh/mesh-fast-forward.ts +856 -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 +898 -102
- package/src/mesh/mesh-magi-status.ts +223 -0
- package/src/mesh/mesh-missions.ts +568 -0
- package/src/mesh/mesh-node-identity.ts +2065 -0
- package/src/mesh/mesh-queue-assignment.ts +2247 -0
- package/src/mesh/mesh-reconcile-acked-hold.ts +230 -0
- package/src/mesh/mesh-reconcile-config.ts +66 -0
- package/src/mesh/mesh-reconcile-identity.ts +103 -0
- package/src/mesh/mesh-reconcile-loop.ts +1473 -0
- package/src/mesh/mesh-reconcile-v2-backstop.ts +62 -0
- package/src/mesh/mesh-refine-batch.ts +205 -0
- package/src/mesh/mesh-refine-gates.ts +1686 -0
- package/src/mesh/mesh-refine-status.ts +231 -0
- package/src/mesh/mesh-remote-event-pull.ts +279 -0
- package/src/mesh/mesh-review-inbox.ts +308 -0
- package/src/mesh/mesh-routing.ts +291 -0
- package/src/mesh/mesh-runtime-store.ts +2150 -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 +1437 -147
- package/src/mesh/preview-freshness.ts +163 -0
- package/src/mesh/refine-config.ts +423 -0
- package/src/mesh/worktree-bootstrap-config.ts +599 -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 +100 -6
- package/src/providers/chat-message-normalization.ts +126 -4
- package/src/providers/cli-provider-effect-format.ts +53 -0
- package/src/providers/cli-provider-history-dedup.ts +75 -0
- package/src/providers/cli-provider-input-prompt.ts +133 -0
- package/src/providers/cli-provider-instance-types.ts +131 -0
- package/src/providers/cli-provider-instance.ts +2500 -497
- package/src/providers/cli-provider-status-helpers.ts +123 -0
- package/src/providers/cli-provider-transcript-merge.ts +114 -0
- 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 +105 -0
- package/src/providers/native-history/antigravity-claim-registry.ts +131 -0
- package/src/providers/native-history/antigravity-cli-transcript.ts +1193 -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 +503 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +312 -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 +24 -1
- package/src/providers/provider-loader.ts +700 -55
- 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 +261 -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 +246 -0
- package/src/providers/spec/cli-adapter.ts +1064 -0
- package/src/providers/spec/evaluator.ts +407 -0
- package/src/providers/spec/fsm-driver.ts +1528 -0
- package/src/providers/spec/fsm-evaluator.ts +290 -0
- package/src/providers/spec/fsm-loader.ts +128 -0
- package/src/providers/spec/fsm-types.ts +301 -0
- package/src/providers/spec/native-history-executor.ts +1241 -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 +284 -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 +868 -13
- package/src/runtime-defaults.ts +39 -0
- package/src/session-host/managed-host.ts +218 -0
- package/src/session-host/runtime-surface.ts +20 -80
- 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 +124 -55
- 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,536 @@
|
|
|
1
|
+
export interface InteractivePrompt {
|
|
2
|
+
promptId: string;
|
|
3
|
+
origin: 'cli' | 'mcp' | 'agent';
|
|
4
|
+
providerType: string;
|
|
5
|
+
createdAt: number;
|
|
6
|
+
questions: InteractiveQuestion[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface InteractiveQuestion {
|
|
10
|
+
questionId: string;
|
|
11
|
+
question: string;
|
|
12
|
+
header?: string;
|
|
13
|
+
multiSelect: boolean;
|
|
14
|
+
options: InteractiveOption[];
|
|
15
|
+
allowFreeform?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface InteractiveOption {
|
|
19
|
+
label: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
preview?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface InteractivePromptResponse {
|
|
25
|
+
promptId: string;
|
|
26
|
+
answers: Record<string, InteractiveAnswer>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface InteractiveAnswer {
|
|
30
|
+
selectedLabels: string[];
|
|
31
|
+
freeformText?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readString(value: unknown): string | undefined {
|
|
35
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readStringArray(value: unknown): string[] {
|
|
39
|
+
return Array.isArray(value)
|
|
40
|
+
? value.map((item) => readString(item)).filter((item): item is string => !!item)
|
|
41
|
+
: [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function normalizeOption(raw: unknown): InteractiveOption | null {
|
|
45
|
+
if (typeof raw === 'string') {
|
|
46
|
+
const label = raw.trim();
|
|
47
|
+
return label ? { label } : null;
|
|
48
|
+
}
|
|
49
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
50
|
+
const record = raw as Record<string, unknown>;
|
|
51
|
+
const label = readString(record.label);
|
|
52
|
+
if (!label) return null;
|
|
53
|
+
const description = readString(record.description);
|
|
54
|
+
const preview = readString(record.preview);
|
|
55
|
+
return {
|
|
56
|
+
label,
|
|
57
|
+
...(description ? { description } : {}),
|
|
58
|
+
...(preview ? { preview } : {}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function normalizeQuestion(raw: unknown, index: number): InteractiveQuestion | null {
|
|
63
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
64
|
+
const record = raw as Record<string, unknown>;
|
|
65
|
+
const question = readString(record.question);
|
|
66
|
+
if (!question) return null;
|
|
67
|
+
const questionId = readString(record.questionId) || readString(record.id) || `q${index + 1}`;
|
|
68
|
+
const options = Array.isArray(record.options)
|
|
69
|
+
? record.options.map(normalizeOption).filter((item): item is InteractiveOption => !!item)
|
|
70
|
+
: [];
|
|
71
|
+
const header = readString(record.header);
|
|
72
|
+
return {
|
|
73
|
+
questionId,
|
|
74
|
+
question,
|
|
75
|
+
...(header ? { header } : {}),
|
|
76
|
+
multiSelect: record.multiSelect === true,
|
|
77
|
+
options,
|
|
78
|
+
...(record.allowFreeform === true ? { allowFreeform: true } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function normalizeInteractivePrompt(raw: unknown): InteractivePrompt | null {
|
|
83
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
84
|
+
const record = raw as Record<string, unknown>;
|
|
85
|
+
const promptId = readString(record.promptId);
|
|
86
|
+
const providerType = readString(record.providerType);
|
|
87
|
+
const origin = record.origin === 'mcp' || record.origin === 'agent' ? record.origin : 'cli';
|
|
88
|
+
const questions = Array.isArray(record.questions)
|
|
89
|
+
? record.questions.map(normalizeQuestion).filter((item): item is InteractiveQuestion => !!item)
|
|
90
|
+
: [];
|
|
91
|
+
if (!promptId || !providerType || questions.length === 0) return null;
|
|
92
|
+
const createdAt = typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
|
|
93
|
+
? record.createdAt
|
|
94
|
+
: Date.now();
|
|
95
|
+
return { promptId, origin, providerType, createdAt, questions };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function normalizeInteractivePromptResponse(raw: unknown): InteractivePromptResponse {
|
|
99
|
+
if (!raw || typeof raw !== 'object') throw new Error('Interactive prompt response must be an object');
|
|
100
|
+
const record = raw as Record<string, unknown>;
|
|
101
|
+
const promptId = readString(record.promptId);
|
|
102
|
+
if (!promptId) throw new Error('promptId must be a non-empty string');
|
|
103
|
+
if (!record.answers || typeof record.answers !== 'object' || Array.isArray(record.answers)) {
|
|
104
|
+
throw new Error('answers must be an object');
|
|
105
|
+
}
|
|
106
|
+
const answers: Record<string, InteractiveAnswer> = {};
|
|
107
|
+
for (const [questionId, answerRaw] of Object.entries(record.answers as Record<string, unknown>)) {
|
|
108
|
+
if (!answerRaw || typeof answerRaw !== 'object' || Array.isArray(answerRaw)) continue;
|
|
109
|
+
const answer = answerRaw as Record<string, unknown>;
|
|
110
|
+
const selectedLabels = readStringArray(answer.selectedLabels);
|
|
111
|
+
const freeformText = readString(answer.freeformText);
|
|
112
|
+
answers[questionId] = {
|
|
113
|
+
selectedLabels,
|
|
114
|
+
...(freeformText ? { freeformText } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return { promptId, answers };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function buildClaudeInteractiveToolResult(response: InteractivePromptResponse): string {
|
|
121
|
+
return JSON.stringify({
|
|
122
|
+
type: 'user',
|
|
123
|
+
message: {
|
|
124
|
+
role: 'user',
|
|
125
|
+
content: [{
|
|
126
|
+
type: 'tool_result',
|
|
127
|
+
tool_use_id: response.promptId,
|
|
128
|
+
content: JSON.stringify({ answers: response.answers }),
|
|
129
|
+
is_error: false,
|
|
130
|
+
}],
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface ClaudeInteractiveTuiPage {
|
|
136
|
+
screenText: string;
|
|
137
|
+
header?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Option rows look like "❯ 1. Label". The multi-select picker additionally
|
|
141
|
+
// draws a checkbox marker that can sit before or after the number
|
|
142
|
+
// ("❯ [ ] 1. Label" / "❯ 1. [x] Label" / "☐ 1. Label"); the optional,
|
|
143
|
+
// non-capturing checkbox groups absorb it so the captured label stays clean.
|
|
144
|
+
const CLAUDE_TUI_OPTION_CHECKBOX = '(?:\\[[ xX]\\]|[☐☒◻◼])';
|
|
145
|
+
const CLAUDE_TUI_OPTION_PATTERN = new RegExp(
|
|
146
|
+
`^\\s*(?:[❯›>]\\s*)?(?:${CLAUDE_TUI_OPTION_CHECKBOX}\\s*)?(\\d+)\\.\\s+(?:${CLAUDE_TUI_OPTION_CHECKBOX}\\s*)?(.+?)\\s*$`,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
function claudeTuiQuestionHeaders(screenText: string): string[] {
|
|
150
|
+
const navLine = screenText.split(/\r?\n/).find(line => line.includes('✔ Submit') && /[☐☒]/.test(line));
|
|
151
|
+
if (!navLine) return [];
|
|
152
|
+
const headers: string[] = [];
|
|
153
|
+
const pattern = /[☐☒]\s+(.+?)(?=\s+[☐☒]|\s+✔\s+Submit)/g;
|
|
154
|
+
for (const match of navLine.matchAll(pattern)) {
|
|
155
|
+
const header = readString(match[1]);
|
|
156
|
+
if (header) headers.push(header);
|
|
157
|
+
}
|
|
158
|
+
return headers;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function isClaudeTuiSelectFooter(text: string): boolean {
|
|
162
|
+
return /Enter to select/i.test(text) && /Esc to cancel/i.test(text);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Decide whether a captured claude-cli AskUserQuestion TUI page is multi-select.
|
|
167
|
+
*
|
|
168
|
+
* The original heuristic only matched the footer hint `/Space to select|toggle
|
|
169
|
+
* selections/i`. That string drifts between claude-cli versions, so when it
|
|
170
|
+
* changed the dashboard silently fell back to multiSelect:false and rendered
|
|
171
|
+
* single-select (radio) controls even though the on-screen picker showed
|
|
172
|
+
* checkboxes — the user could not check more than one box. (The CLI's own
|
|
173
|
+
* terminal still rendered `[ ]` correctly because it never depends on this
|
|
174
|
+
* parse.)
|
|
175
|
+
*
|
|
176
|
+
* Make detection robust by ALSO recognising the actual checkbox markers the
|
|
177
|
+
* multi-select picker draws on its option rows (`[ ]` / `[x]` / `☐` / `☒` /
|
|
178
|
+
* `◻` / `◼`). Single-select rows are drawn with a `❯`/number cursor only and
|
|
179
|
+
* carry none of these box glyphs, so their presence is a reliable signal. The
|
|
180
|
+
* broadened footer patterns ("Space to", "toggle", "select multiple") are kept
|
|
181
|
+
* as a secondary signal for layouts that render markers differently.
|
|
182
|
+
*/
|
|
183
|
+
export function detectClaudeTuiMultiSelect(screenText: string): boolean {
|
|
184
|
+
if (/Space to (?:select|toggle)|toggle selection|select multiple|select all that apply/i.test(screenText)) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
// A checkbox glyph on a NUMBERED option row only appears in the multi-select
|
|
188
|
+
// picker. The glyph sits EITHER before the number ("❯ [ ] 1. TypeScript" /
|
|
189
|
+
// "☐ 2. Python") OR after it ("❯ 1. [ ] 계란말이" — claude-cli >=2.1's layout).
|
|
190
|
+
// We require the numbered "N." option marker either way so we don't
|
|
191
|
+
// false-positive on the `✔ Submit` nav line (per-question answered-state
|
|
192
|
+
// ☐/☒) or on the headerless variant where the QUESTION line itself begins
|
|
193
|
+
// with `☐ ` (single-select).
|
|
194
|
+
const optionCheckbox = `(?:\\[[ xX]\\]|[☐☒◻◼])`;
|
|
195
|
+
const beforeNumber = new RegExp(`^\\s*(?:[❯›>]\\s*)?${optionCheckbox}\\s*\\d+\\.\\s+\\S`);
|
|
196
|
+
const afterNumber = new RegExp(`^\\s*(?:[❯›>]\\s*)?\\d+\\.\\s*${optionCheckbox}\\s+\\S`);
|
|
197
|
+
for (const line of screenText.split(/\r?\n/)) {
|
|
198
|
+
if (line.includes('✔ Submit')) continue; // header/nav line
|
|
199
|
+
if (beforeNumber.test(line) || afterNumber.test(line)) return true;
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function readClaudeHeaderLine(lines: string[], beforeIndex: number): string | undefined {
|
|
205
|
+
for (let i = beforeIndex; i >= 0; i -= 1) {
|
|
206
|
+
const candidate = lines[i].trim();
|
|
207
|
+
if (!candidate) continue;
|
|
208
|
+
const match = candidate.match(/^[☐☒]\s+(.+?)\s*$/);
|
|
209
|
+
if (match?.[1]) return readString(match[1]);
|
|
210
|
+
if (/^─+$/.test(candidate)) break;
|
|
211
|
+
}
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function readClaudeOptionDescription(lines: string[], optionLineIndex: number): string | undefined {
|
|
216
|
+
const nextLine = lines[optionLineIndex + 1];
|
|
217
|
+
const next = nextLine?.trim();
|
|
218
|
+
if (!next
|
|
219
|
+
|| CLAUDE_TUI_OPTION_PATTERN.test(nextLine)
|
|
220
|
+
|| /^─+$/.test(next)
|
|
221
|
+
|| /^Enter to select\b/i.test(next)
|
|
222
|
+
|| /^[☐☒]\s+/.test(next)) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
return next;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function parseClaudeHeaderlessInteractiveTuiQuestion(page: ClaudeInteractiveTuiPage, index: number): InteractiveQuestion | null {
|
|
229
|
+
if (!isClaudeTuiSelectFooter(page.screenText)) return null;
|
|
230
|
+
if (!/Type something\.?|Chat about this/i.test(page.screenText)) return null;
|
|
231
|
+
|
|
232
|
+
const lines = page.screenText.split(/\r?\n/);
|
|
233
|
+
let footerIndex = -1;
|
|
234
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
235
|
+
if (/Enter to select/i.test(lines[i])) {
|
|
236
|
+
footerIndex = i;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (footerIndex < 0) return null;
|
|
241
|
+
|
|
242
|
+
let optionBlockEnd = footerIndex - 1;
|
|
243
|
+
for (let i = footerIndex - 1; i >= 0; i -= 1) {
|
|
244
|
+
if (/^─+$/.test(lines[i].trim())) {
|
|
245
|
+
optionBlockEnd = i - 1;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const optionLineIndexes: number[] = [];
|
|
251
|
+
for (let i = optionBlockEnd; i >= 0; i -= 1) {
|
|
252
|
+
const line = lines[i];
|
|
253
|
+
if (CLAUDE_TUI_OPTION_PATTERN.test(line)) {
|
|
254
|
+
optionLineIndexes.push(i);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (optionLineIndexes.length > 0 && (!line.trim() || /^─+$/.test(line.trim()))) break;
|
|
258
|
+
}
|
|
259
|
+
optionLineIndexes.reverse();
|
|
260
|
+
if (optionLineIndexes.length === 0) return null;
|
|
261
|
+
|
|
262
|
+
const firstOptionIndex = optionLineIndexes[0];
|
|
263
|
+
let question = '';
|
|
264
|
+
for (let i = firstOptionIndex - 1; i >= 0; i -= 1) {
|
|
265
|
+
const candidate = lines[i].trim();
|
|
266
|
+
if (!candidate || /^─+$/.test(candidate)) continue;
|
|
267
|
+
// Standalone ☐/☒ markers (decorative section dividers in the headered
|
|
268
|
+
// variant) are not the question — keep skipping them.
|
|
269
|
+
if (/^[☐☒]\s*$/.test(candidate)) continue;
|
|
270
|
+
// The headerless variant introduced in claude-cli >=2.1 prefixes the
|
|
271
|
+
// actual question with `☐ ` (e.g. "☐ RPS R1 1라운드 — …"). Previously
|
|
272
|
+
// we skipped any ☐/☒ line and returned null, never opening the picker.
|
|
273
|
+
// Strip the marker so the dashboard label matches the on-screen text.
|
|
274
|
+
const markerMatch = candidate.match(/^[☐☒]\s+(.+)$/);
|
|
275
|
+
if (markerMatch) {
|
|
276
|
+
question = markerMatch[1].trim();
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
question = candidate;
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
if (!question) return null;
|
|
283
|
+
|
|
284
|
+
const options: InteractiveOption[] = [];
|
|
285
|
+
let allowFreeform = false;
|
|
286
|
+
for (const optionLineIndex of optionLineIndexes) {
|
|
287
|
+
const match = lines[optionLineIndex].match(CLAUDE_TUI_OPTION_PATTERN);
|
|
288
|
+
if (!match) continue;
|
|
289
|
+
const label = match[2].trim();
|
|
290
|
+
if (/^Chat about this$/i.test(label)) continue;
|
|
291
|
+
if (/^Type something\.?$/i.test(label)) allowFreeform = true;
|
|
292
|
+
|
|
293
|
+
const description = readClaudeOptionDescription(lines, optionLineIndex);
|
|
294
|
+
options.push({ label, ...(description ? { description } : {}) });
|
|
295
|
+
}
|
|
296
|
+
if (options.length === 0) return null;
|
|
297
|
+
|
|
298
|
+
const header = readString(page.header) || readClaudeHeaderLine(lines, firstOptionIndex - 1);
|
|
299
|
+
return {
|
|
300
|
+
questionId: `q${index + 1}`,
|
|
301
|
+
question,
|
|
302
|
+
...(header ? { header } : {}),
|
|
303
|
+
multiSelect: detectClaudeTuiMultiSelect(page.screenText),
|
|
304
|
+
options,
|
|
305
|
+
...(allowFreeform ? { allowFreeform: true } : {}),
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function parseClaudeInteractiveTuiQuestion(page: ClaudeInteractiveTuiPage, index: number): InteractiveQuestion | null {
|
|
310
|
+
const lines = page.screenText.split(/\r?\n/);
|
|
311
|
+
let navIndex = -1;
|
|
312
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
313
|
+
if (lines[i].includes('✔ Submit') && /[☐☒]/.test(lines[i])) {
|
|
314
|
+
navIndex = i;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (navIndex < 0) return parseClaudeHeaderlessInteractiveTuiQuestion(page, index);
|
|
319
|
+
if (!page.screenText.includes('Enter to select')) return null;
|
|
320
|
+
|
|
321
|
+
let question = '';
|
|
322
|
+
let questionLineIndex = -1;
|
|
323
|
+
for (let i = navIndex + 1; i < lines.length; i += 1) {
|
|
324
|
+
const candidate = lines[i].trim();
|
|
325
|
+
if (!candidate || /^─+$/.test(candidate)) continue;
|
|
326
|
+
if (candidate === 'Review your answers' || candidate === 'Ready to submit your answers?') return null;
|
|
327
|
+
question = candidate;
|
|
328
|
+
questionLineIndex = i;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
if (!question) return null;
|
|
332
|
+
|
|
333
|
+
const options: InteractiveOption[] = [];
|
|
334
|
+
let allowFreeform = false;
|
|
335
|
+
for (let i = questionLineIndex + 1; i < lines.length; i += 1) {
|
|
336
|
+
const match = lines[i].match(CLAUDE_TUI_OPTION_PATTERN);
|
|
337
|
+
if (!match) continue;
|
|
338
|
+
const label = match[2].trim();
|
|
339
|
+
if (/^Type something\.?$/i.test(label)) {
|
|
340
|
+
allowFreeform = true;
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (/^Chat about this$/i.test(label)) continue;
|
|
344
|
+
|
|
345
|
+
let description: string | undefined;
|
|
346
|
+
const nextLine = lines[i + 1]?.trim();
|
|
347
|
+
if (nextLine
|
|
348
|
+
&& !CLAUDE_TUI_OPTION_PATTERN.test(lines[i + 1])
|
|
349
|
+
&& !/^─+$/.test(nextLine)
|
|
350
|
+
&& !/^Enter to select\b/.test(nextLine)) {
|
|
351
|
+
description = nextLine;
|
|
352
|
+
}
|
|
353
|
+
options.push({ label, ...(description ? { description } : {}) });
|
|
354
|
+
}
|
|
355
|
+
if (options.length === 0) return null;
|
|
356
|
+
|
|
357
|
+
const header = readString(page.header);
|
|
358
|
+
return {
|
|
359
|
+
questionId: `q${index + 1}`,
|
|
360
|
+
question,
|
|
361
|
+
...(header ? { header } : {}),
|
|
362
|
+
multiSelect: detectClaudeTuiMultiSelect(page.screenText),
|
|
363
|
+
options,
|
|
364
|
+
...(allowFreeform ? { allowFreeform: true } : {}),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Read the question the live claude TUI picker is CURRENTLY focused on, plus
|
|
370
|
+
* whether that focused page renders multi-select checkbox markers.
|
|
371
|
+
*
|
|
372
|
+
* Used to repair a multi-question prompt after the fact: when the daemon
|
|
373
|
+
* Tab-captures pages 2..N it snapshots ~120ms after the Tab keypress, before
|
|
374
|
+
* the newly-focused page's option-row checkbox column has redrawn — so those
|
|
375
|
+
* questions get frozen as multiSelect:false even though the picker is
|
|
376
|
+
* multi-select. Re-reading the focused page on a later status tick (once it has
|
|
377
|
+
* settled) lets us attribute the now-visible glyphs to the matching question
|
|
378
|
+
* and upgrade just that one. Returns null when no picker question is on screen.
|
|
379
|
+
*/
|
|
380
|
+
export function readFocusedClaudeTuiQuestion(
|
|
381
|
+
screenText: string,
|
|
382
|
+
): { question: string; header?: string; multiSelect: boolean } | null {
|
|
383
|
+
if (!screenText.includes('Enter to select')) return null;
|
|
384
|
+
const parsed = parseClaudeInteractiveTuiQuestion({ screenText }, 0);
|
|
385
|
+
if (!parsed) return null;
|
|
386
|
+
return {
|
|
387
|
+
question: parsed.question,
|
|
388
|
+
...(parsed.header ? { header: parsed.header } : {}),
|
|
389
|
+
multiSelect: parsed.multiSelect,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function detectClaudeAskUserQuestionPromptFromTuiPages(
|
|
394
|
+
pages: ClaudeInteractiveTuiPage[],
|
|
395
|
+
options: { promptId: string; providerType?: string; createdAt?: number },
|
|
396
|
+
): InteractivePrompt | null {
|
|
397
|
+
if (pages.length === 0) return null;
|
|
398
|
+
const headers = claudeTuiQuestionHeaders(pages[0].screenText);
|
|
399
|
+
const questions = pages.map((page, index) => parseClaudeInteractiveTuiQuestion({
|
|
400
|
+
...page,
|
|
401
|
+
header: page.header || headers[index],
|
|
402
|
+
}, index)).filter((question): question is InteractiveQuestion => !!question);
|
|
403
|
+
if (questions.length !== pages.length) return null;
|
|
404
|
+
return {
|
|
405
|
+
promptId: options.promptId,
|
|
406
|
+
origin: 'cli',
|
|
407
|
+
providerType: options.providerType || 'claude-cli',
|
|
408
|
+
createdAt: options.createdAt || Date.now(),
|
|
409
|
+
questions,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function buildClaudeInteractiveTuiAnswerSteps(
|
|
414
|
+
prompt: InteractivePrompt,
|
|
415
|
+
response: InteractivePromptResponse,
|
|
416
|
+
): string[] {
|
|
417
|
+
if (response.promptId !== prompt.promptId) throw new Error('Interactive prompt response does not match active prompt');
|
|
418
|
+
const steps: string[] = [];
|
|
419
|
+
for (const question of prompt.questions) {
|
|
420
|
+
const answer = response.answers[question.questionId];
|
|
421
|
+
if (!answer) throw new Error(`Missing answer for ${question.questionId}`);
|
|
422
|
+
const freeformText = answer.freeformText?.trim() ?? '';
|
|
423
|
+
|
|
424
|
+
// Defensive multi-select fallback: a checkbox picker is the ONLY way an
|
|
425
|
+
// answer can carry more than one selected label, so treat any such answer
|
|
426
|
+
// as multi-select even when `question.multiSelect` was captured as false.
|
|
427
|
+
// This guards the multi-question capture race: pages 2..N can freeze as
|
|
428
|
+
// single-select (their glyph column hadn't redrawn at Tab-snapshot time),
|
|
429
|
+
// and the old single-select branch would then either throw on 2+ checked
|
|
430
|
+
// boxes or emit a bare digit (cursor move, no toggle) for 1 box — silently
|
|
431
|
+
// dropping that page's selection. Keying off the answer's label count makes
|
|
432
|
+
// the keystroke protocol correct regardless of the captured flag.
|
|
433
|
+
const treatAsMultiSelect = question.multiSelect || answer.selectedLabels.length > 1;
|
|
434
|
+
|
|
435
|
+
if (treatAsMultiSelect) {
|
|
436
|
+
// Multi-select: Claude TUI renders each option as a checkbox. The
|
|
437
|
+
// keystroke model here was reverse-engineered live against claude-cli
|
|
438
|
+
// v2.1.170 (do not "simplify" from the screen text — it lies):
|
|
439
|
+
//
|
|
440
|
+
// * A numeric digit key TOGGLES that option's checkbox directly and
|
|
441
|
+
// does NOT move the cursor. So a digit alone checks the option.
|
|
442
|
+
// * Space toggles whatever row the cursor is sitting on (the digit
|
|
443
|
+
// never moved it), so a trailing Space would spuriously toggle the
|
|
444
|
+
// cursor's row (usually option 1) — NEVER pair digit+Space here.
|
|
445
|
+
// * Enter does NOT advance the page; it toggles the cursor's row too.
|
|
446
|
+
// The ONLY key that commits this question and advances (to the next
|
|
447
|
+
// question, or to the final "Review your answers" screen for the
|
|
448
|
+
// last question) is Tab.
|
|
449
|
+
//
|
|
450
|
+
// So: one digit per selected label, then a single Tab to advance.
|
|
451
|
+
const labels = answer.selectedLabels;
|
|
452
|
+
if (labels.length === 0) {
|
|
453
|
+
throw new Error(`Expected at least one selected label for ${question.questionId}`);
|
|
454
|
+
}
|
|
455
|
+
for (const label of labels) {
|
|
456
|
+
const selectedIndex = question.options.findIndex(option => option.label === label);
|
|
457
|
+
if (selectedIndex < 0) throw new Error(`Unknown option for ${question.questionId}: ${label}`);
|
|
458
|
+
steps.push(String(selectedIndex + 1));
|
|
459
|
+
}
|
|
460
|
+
// Tab commits this question's checked set and advances. (Unlike
|
|
461
|
+
// single-select, where the digit auto-advances, a multi-select page
|
|
462
|
+
// stays put under digit input so the user can toggle multiple boxes.)
|
|
463
|
+
steps.push('\t');
|
|
464
|
+
} else if (freeformText) {
|
|
465
|
+
// Freeform: select the "Type something." option (always the last visible
|
|
466
|
+
// option before "Chat about this"), then type the text and confirm.
|
|
467
|
+
const typeOptionIndex = question.options.findIndex(o => /^Type something\.?$/i.test(o.label));
|
|
468
|
+
const optionNumber = typeOptionIndex >= 0 ? typeOptionIndex + 1 : question.options.length;
|
|
469
|
+
steps.push(String(optionNumber));
|
|
470
|
+
// Type the text character by character, then Enter to confirm.
|
|
471
|
+
for (const ch of freeformText) steps.push(ch);
|
|
472
|
+
steps.push('\r');
|
|
473
|
+
} else {
|
|
474
|
+
if (answer.selectedLabels.length !== 1) throw new Error(`Expected one selected label for ${question.questionId}`);
|
|
475
|
+
const selectedIndex = question.options.findIndex(option => option.label === answer.selectedLabels[0]);
|
|
476
|
+
if (selectedIndex < 0) throw new Error(`Unknown option for ${question.questionId}: ${answer.selectedLabels[0]}`);
|
|
477
|
+
// Use numeric key (1-based) to jump directly to the option. This avoids
|
|
478
|
+
// cursor-position drift between questions that arrow-key navigation suffers
|
|
479
|
+
// from — the TUI accepts a digit key to jump straight to that option index.
|
|
480
|
+
steps.push(String(selectedIndex + 1));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// After all questions are answered, Claude TUI shows a final confirm screen
|
|
484
|
+
// ("Submit answers" / "Cancel"). The first option is pre-selected, so a
|
|
485
|
+
// single Enter confirms and submits.
|
|
486
|
+
steps.push('\r');
|
|
487
|
+
return steps;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
export function interactivePromptFromClaudeAskUserQuestion(input: unknown, options: {
|
|
491
|
+
promptId: string;
|
|
492
|
+
providerType: string;
|
|
493
|
+
createdAt?: number;
|
|
494
|
+
origin?: InteractivePrompt['origin'];
|
|
495
|
+
}): InteractivePrompt | null {
|
|
496
|
+
if (!input || typeof input !== 'object') return null;
|
|
497
|
+
const record = input as Record<string, unknown>;
|
|
498
|
+
const questions = Array.isArray(record.questions)
|
|
499
|
+
? record.questions.map(normalizeQuestion).filter((item): item is InteractiveQuestion => !!item)
|
|
500
|
+
: [];
|
|
501
|
+
if (questions.length === 0) return null;
|
|
502
|
+
return {
|
|
503
|
+
promptId: options.promptId,
|
|
504
|
+
origin: options.origin || 'cli',
|
|
505
|
+
providerType: options.providerType,
|
|
506
|
+
createdAt: options.createdAt || Date.now(),
|
|
507
|
+
questions,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export function detectClaudeAskUserQuestionPromptFromJson(value: unknown, providerType = 'claude-cli'): InteractivePrompt | null {
|
|
512
|
+
if (!value || typeof value !== 'object') return null;
|
|
513
|
+
const record = value as Record<string, unknown>;
|
|
514
|
+
const blocks: unknown[] = [];
|
|
515
|
+
if (Array.isArray(record.content)) blocks.push(...record.content);
|
|
516
|
+
const message = record.message;
|
|
517
|
+
if (message && typeof message === 'object' && Array.isArray((message as Record<string, unknown>).content)) {
|
|
518
|
+
blocks.push(...((message as Record<string, unknown>).content as unknown[]));
|
|
519
|
+
}
|
|
520
|
+
if (record.type === 'tool_use') blocks.push(record);
|
|
521
|
+
|
|
522
|
+
for (const block of blocks) {
|
|
523
|
+
if (!block || typeof block !== 'object') continue;
|
|
524
|
+
const b = block as Record<string, unknown>;
|
|
525
|
+
const name = readString(b.name);
|
|
526
|
+
if (b.type !== 'tool_use' || name !== 'AskUserQuestion') continue;
|
|
527
|
+
const id = readString(b.id) || readString(record.id) || `ask-user-${Date.now()}`;
|
|
528
|
+
const prompt = interactivePromptFromClaudeAskUserQuestion(b.input, {
|
|
529
|
+
promptId: id,
|
|
530
|
+
providerType,
|
|
531
|
+
origin: 'cli',
|
|
532
|
+
});
|
|
533
|
+
if (prompt) return prompt;
|
|
534
|
+
}
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import * as os from 'os';
|
|
15
|
-
|
|
15
|
+
// Removed execSync import
|
|
16
16
|
import { platform } from 'os';
|
|
17
17
|
import type { ProviderLoader } from './provider-loader.js';
|
|
18
18
|
import type { ProviderModule } from './contracts.js';
|
|
19
|
+
import { isKnownWin32GuiExe, readWin32IdeVersionFromDisk } from '../detection/win32-ide-version.js';
|
|
19
20
|
|
|
20
21
|
// ─── Types ──────────────────────────────────────
|
|
21
22
|
|
|
@@ -117,22 +118,40 @@ export class VersionArchive {
|
|
|
117
118
|
|
|
118
119
|
// ─── Version Detection ──────────────────────────────
|
|
119
120
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
import { exec } from 'child_process';
|
|
122
|
+
|
|
123
|
+
async function runCommand(cmd: string, timeout = 10000): Promise<string | null> {
|
|
124
|
+
return new Promise((resolve) => {
|
|
125
|
+
exec(cmd, {
|
|
123
126
|
encoding: 'utf-8',
|
|
124
127
|
timeout,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
128
|
+
}, (error, stdout) => {
|
|
129
|
+
if (error) return resolve(null);
|
|
130
|
+
resolve(stdout.trim());
|
|
131
|
+
});
|
|
132
|
+
});
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
function findBinary(name: string): string | null {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
+
const isWin = platform() === 'win32';
|
|
137
|
+
const paths = (process.env.PATH || '').split(isWin ? ';' : ':');
|
|
138
|
+
const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
|
|
139
|
+
|
|
140
|
+
for (const p of paths) {
|
|
141
|
+
if (!p) continue;
|
|
142
|
+
for (const ext of exes) {
|
|
143
|
+
const fullPath = path.join(p, name + ext);
|
|
144
|
+
try {
|
|
145
|
+
if (fs.existsSync(fullPath)) {
|
|
146
|
+
const stat = fs.statSync(fullPath);
|
|
147
|
+
if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
|
|
148
|
+
return fullPath;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} catch { }
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
136
155
|
}
|
|
137
156
|
|
|
138
157
|
/** Extract version string from CLI output */
|
|
@@ -162,16 +181,16 @@ function getPlatformVersionCommand(
|
|
|
162
181
|
return undefined;
|
|
163
182
|
}
|
|
164
183
|
|
|
165
|
-
function getVersion(binary: string, versionCommand?: string): string | null {
|
|
184
|
+
async function getVersion(binary: string, versionCommand?: string): Promise<string | null> {
|
|
166
185
|
// Custom version command from provider.json
|
|
167
186
|
if (versionCommand) {
|
|
168
|
-
const raw = runCommand(versionCommand);
|
|
187
|
+
const raw = await runCommand(versionCommand);
|
|
169
188
|
return raw ? parseVersion(raw) : null;
|
|
170
189
|
}
|
|
171
190
|
|
|
172
191
|
// Default: try --version, then -V, then -v
|
|
173
192
|
for (const flag of ['--version', '-V', '-v']) {
|
|
174
|
-
const raw = runCommand(`"${binary}" ${flag}`);
|
|
193
|
+
const raw = await runCommand(`"${binary}" ${flag}`);
|
|
175
194
|
if (raw && raw.length < 500) return parseVersion(raw);
|
|
176
195
|
}
|
|
177
196
|
return null;
|
|
@@ -191,11 +210,11 @@ function checkPathExists(paths: string[]): string | null {
|
|
|
191
210
|
}
|
|
192
211
|
|
|
193
212
|
/** macOS: Get app version from Info.plist */
|
|
194
|
-
function getMacAppVersion(appPath: string): string | null {
|
|
213
|
+
async function getMacAppVersion(appPath: string): Promise<string | null> {
|
|
195
214
|
if (platform() !== 'darwin' || !appPath.endsWith('.app')) return null;
|
|
196
215
|
const plistPath = path.join(appPath, 'Contents', 'Info.plist');
|
|
197
216
|
if (!fs.existsSync(plistPath)) return null;
|
|
198
|
-
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
217
|
+
const raw = await runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
199
218
|
return raw || null;
|
|
200
219
|
}
|
|
201
220
|
|
|
@@ -208,6 +227,10 @@ export async function detectAllVersions(
|
|
|
208
227
|
): Promise<ProviderVersionInfo[]> {
|
|
209
228
|
const results: ProviderVersionInfo[] = [];
|
|
210
229
|
const currentOs = platform() as string;
|
|
230
|
+
// Map of provider type → GUI exe names (win32), used to refuse spawning a
|
|
231
|
+
// GUI executable for version detection (which would boot the IDE window).
|
|
232
|
+
const win32ProcessNames: Record<string, string[]> =
|
|
233
|
+
typeof loader.getWinProcessNames === 'function' ? loader.getWinProcessNames() : {};
|
|
211
234
|
|
|
212
235
|
for (const provider of loader.getAll()) {
|
|
213
236
|
const info: ProviderVersionInfo = {
|
|
@@ -240,12 +263,29 @@ export async function detectAllVersions(
|
|
|
240
263
|
info.path = appPath || null;
|
|
241
264
|
info.binary = resolvedBin || null;
|
|
242
265
|
|
|
243
|
-
// Version
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
266
|
+
// Version detection for IDEs must avoid spawning the GUI executable.
|
|
267
|
+
// On Windows the resolved binary is frequently the GUI Electron exe
|
|
268
|
+
// (case-insensitive FS), and `<exe> --version` boots the IDE window.
|
|
269
|
+
// Strategy (all spawn-free where possible):
|
|
270
|
+
// 1. win32: read bundled product.json/package.json next to the exe.
|
|
271
|
+
// 2. darwin: read Info.plist via PlistBuddy (read-only).
|
|
272
|
+
// 3. Fallback to `<bin> --version` ONLY when the binary is not a
|
|
273
|
+
// known GUI exe — the safety-net guard (#4).
|
|
274
|
+
if (currentOs === 'win32') {
|
|
275
|
+
info.version = readWin32IdeVersionFromDisk(resolvedBin || appPath || '');
|
|
276
|
+
if (!info.version && resolvedBin && !isKnownWin32GuiExe(resolvedBin, win32ProcessNames)) {
|
|
277
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
278
|
+
}
|
|
279
|
+
} else if (currentOs === 'darwin') {
|
|
280
|
+
if (appPath) info.version = await getMacAppVersion(appPath);
|
|
281
|
+
if (!info.version && resolvedBin) {
|
|
282
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
// linux and others: bundled CLI wrappers are real CLIs, safe to exec.
|
|
286
|
+
if (resolvedBin) {
|
|
287
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
288
|
+
}
|
|
249
289
|
}
|
|
250
290
|
|
|
251
291
|
} else if (provider.category === 'cli' || provider.category === 'acp') {
|
|
@@ -256,7 +296,7 @@ export async function detectAllVersions(
|
|
|
256
296
|
info.binary = binPath || null;
|
|
257
297
|
|
|
258
298
|
if (binPath) {
|
|
259
|
-
info.version = getVersion(binPath, versionCommand);
|
|
299
|
+
info.version = await getVersion(binPath, versionCommand);
|
|
260
300
|
}
|
|
261
301
|
|
|
262
302
|
} else if (provider.category === 'extension') {
|