@adhdev/daemon-core 0.9.82-rc.49 → 0.9.82-rc.491
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 +220 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +137 -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 +23 -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 +71 -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 +151 -0
- package/dist/commands/router-worktree-cleanup.d.ts +133 -0
- package/dist/commands/router.d.ts +203 -15
- package/dist/commands/upgrade-helper.d.ts +41 -1
- package/dist/config/chat-history.d.ts +11 -0
- package/dist/config/config.d.ts +19 -0
- package/dist/config/mesh-config.d.ts +66 -0
- 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/config/state-store.d.ts +30 -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 +80 -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 -17
- package/dist/index.js +53556 -19074
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +53380 -19063
- 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 +256 -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 +58 -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 +258 -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 +21 -1
- 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 +281 -0
- package/dist/mesh/mesh-node-identity.d.ts +310 -0
- package/dist/mesh/mesh-queue-assignment.d.ts +162 -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 +84 -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 +457 -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 +567 -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 +34 -0
- package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
- package/dist/mesh/mesh-work-queue.d.ts +392 -1
- package/dist/mesh/preview-freshness.d.ts +28 -0
- package/dist/mesh/refine-config.d.ts +97 -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 +426 -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 +196 -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 +39 -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 +44 -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 +30 -0
- package/dist/providers/provider-instance.d.ts +31 -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 +616 -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 +26 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +110 -55
- package/dist/status/chat-tail-hot-sessions.d.ts +40 -0
- 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 +27 -0
- package/dist/system/hash.d.ts +8 -0
- package/dist/system/load-better-sqlite3.d.ts +21 -0
- package/dist/types.d.ts +20 -6
- 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 +1282 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +1048 -1143
- 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 +2788 -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.d.ts +2 -0
- package/src/commands/cli-manager.ts +724 -27
- package/src/commands/handler.ts +865 -2
- package/src/commands/high-family/index.ts +28 -0
- package/src/commands/high-family/mesh-coordinator-launch.ts +696 -0
- package/src/commands/high-family/mesh-events.ts +102 -0
- package/src/commands/high-family/mesh-status.ts +857 -0
- package/src/commands/high-family/types.ts +80 -0
- package/src/commands/low-family/coordinator-prompt.ts +125 -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 +282 -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 +270 -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 +1309 -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 +1794 -0
- package/src/commands/router-worktree-cleanup.ts +870 -0
- package/src/commands/router.ts +567 -4149
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +310 -45
- package/src/config/chat-history.ts +517 -24
- package/src/config/config.ts +30 -0
- package/src/config/mesh-config.ts +300 -24
- 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/config/state-store.ts +55 -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 +822 -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 +190 -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 +510 -0
- package/src/mesh/coordinator-prompt.ts +627 -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 +416 -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 +2030 -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 +1548 -0
- package/src/mesh/mesh-events-stale.ts +452 -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 +41 -3
- package/src/mesh/mesh-init.ts +350 -0
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
- package/src/mesh/mesh-ledger.ts +897 -102
- package/src/mesh/mesh-magi-status.ts +223 -0
- package/src/mesh/mesh-missions.ts +695 -0
- package/src/mesh/mesh-node-identity.ts +2065 -0
- package/src/mesh/mesh-queue-assignment.ts +2498 -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 +1696 -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 +1792 -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 +2292 -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 +215 -0
- package/src/mesh/mesh-warmup-deadline.ts +152 -0
- package/src/mesh/mesh-work-queue.ts +1489 -145
- package/src/mesh/preview-freshness.ts +163 -0
- package/src/mesh/refine-config.ts +129 -12
- 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 +2771 -499
- 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 +207 -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 +138 -0
- package/src/providers/native-history/antigravity-cli-transcript.ts +1275 -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 +617 -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 +93 -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 +538 -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 +861 -14
- 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 +44 -0
- package/src/shared-types-extra.ts +2 -4
- package/src/shared-types.d.ts +8 -0
- package/src/shared-types.ts +148 -55
- package/src/status/builders.ts +69 -6
- package/src/status/chat-tail-hot-sessions.ts +117 -2
- package/src/status/normalize.ts +2 -0
- package/src/status/reporter.ts +19 -1
- package/src/status/snapshot.ts +100 -27
- 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 +26 -6
- 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
|
@@ -51,7 +51,9 @@ import { normalizeContent, flattenContent, normalizeInputEnvelope } from './cont
|
|
|
51
51
|
import { assertProviderSupportsDeclaredInput, getEffectiveMessageInputSupport } from './provider-input-support.js';
|
|
52
52
|
import type { ProviderInstance, ProviderState, AcpProviderState, ProviderErrorReason, ProviderEvent, InstanceContext, SessionModalState } from './provider-instance.js';
|
|
53
53
|
import { StatusMonitor } from './status-monitor.js';
|
|
54
|
+
import { ManualAttendanceTracker } from './manual-attendance.js';
|
|
54
55
|
import { buildLegacyModelModeSummaryMetadata } from './summary-metadata.js';
|
|
56
|
+
import { workingDirBasename } from './working-dir.js';
|
|
55
57
|
import {
|
|
56
58
|
buildAssistantChatMessage,
|
|
57
59
|
buildChatMessage,
|
|
@@ -287,6 +289,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
287
289
|
private partialBlocks: ContentBlock[] = [];
|
|
288
290
|
/** Tool calls collected during current turn */
|
|
289
291
|
private turnToolCalls: ToolCallInfo[] = [];
|
|
292
|
+
/** Guard: prevent concurrent sendPrompt calls from racing on shared state */
|
|
293
|
+
private _sendPromptInFlight = false;
|
|
290
294
|
|
|
291
295
|
// Error tracking
|
|
292
296
|
private errorMessage: string | null = null;
|
|
@@ -326,8 +330,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
326
330
|
this.settings = context.settings || {};
|
|
327
331
|
this.monitor.updateConfig({
|
|
328
332
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
329
|
-
|
|
330
|
-
|
|
333
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
334
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180,
|
|
331
335
|
});
|
|
332
336
|
|
|
333
337
|
await this.spawnAgent();
|
|
@@ -343,7 +347,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
getSessionModalState(): SessionModalState {
|
|
346
|
-
const dirName = this.workingDir
|
|
350
|
+
const dirName = workingDirBasename(this.workingDir);
|
|
347
351
|
return {
|
|
348
352
|
id: this.instanceId,
|
|
349
353
|
status: this.currentStatus,
|
|
@@ -356,7 +360,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
356
360
|
}
|
|
357
361
|
|
|
358
362
|
getState(): AcpProviderState {
|
|
359
|
-
const dirName = this.workingDir
|
|
363
|
+
const dirName = workingDirBasename(this.workingDir);
|
|
360
364
|
|
|
361
365
|
const recentMessages = normalizeChatMessages(this.messages.map(m => {
|
|
362
366
|
const content = m.content;
|
|
@@ -671,8 +675,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
671
675
|
this.settings = { ...this.settings, ...newSettings };
|
|
672
676
|
this.monitor.updateConfig({
|
|
673
677
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
674
|
-
|
|
675
|
-
|
|
678
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
679
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180,
|
|
676
680
|
});
|
|
677
681
|
this.log.info(`[${this.type}] Settings updated: ${Object.keys(newSettings).join(', ')}`);
|
|
678
682
|
}
|
|
@@ -842,7 +846,12 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
842
846
|
}
|
|
843
847
|
|
|
844
848
|
// ─── Auto-approve: skip user confirmation ───
|
|
845
|
-
|
|
849
|
+
// Held while a human is actively attending this session (manual
|
|
850
|
+
// attendance) so they can decide the permission themselves; falls
|
|
851
|
+
// through to the waiting_approval manual path below. A background
|
|
852
|
+
// worker is never attended, so its delegated auto-approve fires
|
|
853
|
+
// as before.
|
|
854
|
+
if (this.settings.autoApprove !== false && !this.manualAttendance.isAttended()) {
|
|
846
855
|
const toolTitle = tc.title || tc.toolCallId || 'tool call';
|
|
847
856
|
this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
|
|
848
857
|
this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
|
|
@@ -1002,7 +1011,11 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1002
1011
|
}
|
|
1003
1012
|
} catch (e: any) {
|
|
1004
1013
|
this.log.warn(`[${this.type}] session/new failed: ${e?.message}`);
|
|
1005
|
-
this.
|
|
1014
|
+
if (!this.errorReason) {
|
|
1015
|
+
this.errorReason = 'init_failed';
|
|
1016
|
+
this.errorMessage = `ACP session creation failed: ${e?.message}`;
|
|
1017
|
+
}
|
|
1018
|
+
this.currentStatus = 'error';
|
|
1006
1019
|
}
|
|
1007
1020
|
}
|
|
1008
1021
|
|
|
@@ -1012,6 +1025,12 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1012
1025
|
return;
|
|
1013
1026
|
}
|
|
1014
1027
|
|
|
1028
|
+
if (this._sendPromptInFlight) {
|
|
1029
|
+
this.log.warn(`[${this.type}] sendPrompt already in flight — dropping concurrent request`);
|
|
1030
|
+
throw new Error('ACP sendPrompt already in flight');
|
|
1031
|
+
}
|
|
1032
|
+
this._sendPromptInFlight = true;
|
|
1033
|
+
|
|
1015
1034
|
// Build prompt content
|
|
1016
1035
|
const promptParts: any[] = contentBlocks && contentBlocks.length > 0
|
|
1017
1036
|
? contentBlocks.map((b) => {
|
|
@@ -1098,6 +1117,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1098
1117
|
this.finalizeAssistantMessage();
|
|
1099
1118
|
this.currentStatus = 'idle';
|
|
1100
1119
|
this.detectStatusTransition();
|
|
1120
|
+
} finally {
|
|
1121
|
+
this._sendPromptInFlight = false;
|
|
1101
1122
|
}
|
|
1102
1123
|
}
|
|
1103
1124
|
|
|
@@ -1113,6 +1134,17 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1113
1134
|
|
|
1114
1135
|
private permissionResolvers: ((approved: boolean) => void)[] = [];
|
|
1115
1136
|
|
|
1137
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
1138
|
+
// this session from the dashboard, auto-approve holds so they can decide on
|
|
1139
|
+
// the permission request themselves. Background workers are never attended →
|
|
1140
|
+
// delegated auto-approve is unaffected.
|
|
1141
|
+
private readonly manualAttendance = new ManualAttendanceTracker();
|
|
1142
|
+
|
|
1143
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
1144
|
+
noteManualInteraction(now = Date.now()): void {
|
|
1145
|
+
this.manualAttendance.note(now);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1116
1148
|
async resolvePermission(approved: boolean): Promise<void> {
|
|
1117
1149
|
const resolver = this.permissionResolvers.shift();
|
|
1118
1150
|
if (resolver) {
|
|
@@ -1490,7 +1522,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1490
1522
|
private detectStatusTransition(): void {
|
|
1491
1523
|
const now = Date.now();
|
|
1492
1524
|
const newStatus = this.currentStatus;
|
|
1493
|
-
const dirName = this.workingDir
|
|
1525
|
+
const dirName = workingDirBasename(this.workingDir);
|
|
1494
1526
|
const chatTitle = `${this.provider.name} · ${dirName}`;
|
|
1495
1527
|
const progressFingerprint = newStatus === 'generating'
|
|
1496
1528
|
? `${this.partialContent}::${JSON.stringify(this.partialBlocks)}::${JSON.stringify(this.activeToolCalls.map(t => ({ name: t.name, status: t.status })))}`.slice(-2000)
|
|
@@ -1518,7 +1550,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1518
1550
|
|
|
1519
1551
|
// Monitor check
|
|
1520
1552
|
const agentKey = `${this.type}:acp`;
|
|
1521
|
-
const
|
|
1553
|
+
const approvalPending = newStatus === 'waiting_approval';
|
|
1554
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint, approvalPending);
|
|
1522
1555
|
for (const me of monitorEvents) {
|
|
1523
1556
|
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
1524
1557
|
}
|
|
@@ -4,4 +4,9 @@ export declare function pickApprovalButton(buttons: string[] | null | undefined,
|
|
|
4
4
|
index: number;
|
|
5
5
|
label: string;
|
|
6
6
|
};
|
|
7
|
+
export declare function pickAutoApprovalButton(buttons: string[] | null | undefined): {
|
|
8
|
+
index: number;
|
|
9
|
+
label: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function hasNegativeApprovalOption(buttons: string[] | null | undefined): boolean;
|
|
7
12
|
export declare function formatAutoApprovalMessage(modalMessage?: string, buttonLabel?: string): string;
|
|
@@ -16,7 +16,7 @@ const DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
|
16
16
|
'always allow',
|
|
17
17
|
];
|
|
18
18
|
|
|
19
|
-
function normalizeApprovalLabel(value: string): string {
|
|
19
|
+
export function normalizeApprovalLabel(value: string): string {
|
|
20
20
|
return String(value || '')
|
|
21
21
|
.toLowerCase()
|
|
22
22
|
.replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, '')
|
|
@@ -24,6 +24,65 @@ function normalizeApprovalLabel(value: string): string {
|
|
|
24
24
|
.trim();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function isNegativeApprovalLabel(value: string): boolean {
|
|
28
|
+
const label = normalizeApprovalLabel(value);
|
|
29
|
+
return /^(no|deny|reject|cancel|skip|exit|stop)\b/.test(label)
|
|
30
|
+
|| /\bwithout\b/.test(label)
|
|
31
|
+
|| /\bdo not\b/.test(label);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* True when any of the given button labels reads as a decline/negative option
|
|
36
|
+
* (No / Deny / Cancel / Skip / …). Used as the second half of an approval-modal
|
|
37
|
+
* structural anchor: a real approval modal offers BOTH an affirmative and a
|
|
38
|
+
* decline, which distinguishes it from a generic numbered menu or prose list.
|
|
39
|
+
*/
|
|
40
|
+
export function hasNegativeApprovalOption(buttons: string[] | null | undefined): boolean {
|
|
41
|
+
return (buttons || []).some((button) => isNegativeApprovalLabel(String(button || '')));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* True when a button reliably identifies a tool-CONSENT modal on its own — a
|
|
46
|
+
* scoped permission-grant affirmative such as:
|
|
47
|
+
* - "Yes, allow all edits in tmp/ during this session"
|
|
48
|
+
* - "Yes, and don't ask again for example.com"
|
|
49
|
+
* - "Yes, allow reading from etc/ from this project"
|
|
50
|
+
* - "Always allow"
|
|
51
|
+
*
|
|
52
|
+
* These options only ever appear in a genuine approval/permission prompt; a
|
|
53
|
+
* /model or /mode picker ("1. Default 2. Opus 3. Sonnet") never offers a
|
|
54
|
+
* "grant this scope" choice. They therefore serve as a SECOND reliable
|
|
55
|
+
* structural anchor alongside {@link hasNegativeApprovalOption}.
|
|
56
|
+
*
|
|
57
|
+
* Why this exists (tall-diff fallback, #137): when a Write/Edit diff is tall,
|
|
58
|
+
* the trailing decline option ("3. No") can scroll off the bottom of the
|
|
59
|
+
* captured PTY frame, leaving only "1. Yes" + "2. Yes, allow … this session".
|
|
60
|
+
* hasNegativeApprovalOption then reads false and the auto-approve gate bails —
|
|
61
|
+
* a delegated worker sits forever on a modal it could safely have approved. The
|
|
62
|
+
* grant-scope affirmative lets the gate recognize the consent modal WITHOUT
|
|
63
|
+
* seeing the off-frame decline. The gate still selects the plain "Yes"
|
|
64
|
+
* (allow-once) via pickApprovalButton, never the broader grant, and the settle
|
|
65
|
+
* gate still requires a stable modal — so a half-rendered frame never fires.
|
|
66
|
+
* Kept deliberately narrow so no picker/confirm modal can trip it.
|
|
67
|
+
*/
|
|
68
|
+
export function hasReliableApprovalAffirmative(buttons: string[] | null | undefined): boolean {
|
|
69
|
+
return (buttons || []).some((button) => {
|
|
70
|
+
const label = normalizeApprovalLabel(String(button || ''));
|
|
71
|
+
if (!label) return false;
|
|
72
|
+
// "always allow …" as a standalone grant option.
|
|
73
|
+
if (/^always allow\b/.test(label)) return true;
|
|
74
|
+
// "yes, …" scoped grants: allow / always allow / don't ask again / etc.
|
|
75
|
+
// (normalizeApprovalLabel strips the apostrophe, so "don't" → "don t").
|
|
76
|
+
if (/^yes\b/.test(label)) {
|
|
77
|
+
if (/\ballow\b/.test(label)) return true;
|
|
78
|
+
if (/\bask again\b/.test(label)) return true;
|
|
79
|
+
if (/\bduring this session\b/.test(label)) return true;
|
|
80
|
+
if (/\bfrom this project\b/.test(label)) return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
27
86
|
export function getApprovalPositiveHints(provider?: Pick<ProviderModule, 'approvalPositiveHints'> | null): string[] {
|
|
28
87
|
const customHints = Array.isArray(provider?.approvalPositiveHints)
|
|
29
88
|
? provider.approvalPositiveHints
|
|
@@ -39,24 +98,32 @@ export function pickApprovalButton(
|
|
|
39
98
|
): { index: number; label: string } {
|
|
40
99
|
const labels = (buttons || []).map((button) => String(button || '').trim()).filter(Boolean);
|
|
41
100
|
if (labels.length === 0) {
|
|
42
|
-
return { index:
|
|
101
|
+
return { index: -1, label: '' };
|
|
43
102
|
}
|
|
44
103
|
|
|
45
104
|
const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
|
|
46
105
|
const hints = getApprovalPositiveHints(provider);
|
|
47
106
|
|
|
48
107
|
for (const hint of hints) {
|
|
49
|
-
const exactIndex = normalizedButtons.findIndex((label) => label === hint);
|
|
108
|
+
const exactIndex = normalizedButtons.findIndex((label, index) => label === hint && !isNegativeApprovalLabel(labels[index]));
|
|
50
109
|
if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
|
|
51
110
|
|
|
52
|
-
const prefixIndex = normalizedButtons.findIndex((label) => label.startsWith(hint));
|
|
111
|
+
const prefixIndex = normalizedButtons.findIndex((label, index) => label.startsWith(hint) && !isNegativeApprovalLabel(labels[index]));
|
|
53
112
|
if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
|
|
54
113
|
|
|
55
|
-
const includeIndex = normalizedButtons.findIndex((label) => label.includes(hint));
|
|
114
|
+
const includeIndex = normalizedButtons.findIndex((label, index) => label.includes(hint) && !isNegativeApprovalLabel(labels[index]));
|
|
56
115
|
if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
|
|
57
116
|
}
|
|
58
117
|
|
|
59
|
-
return { index:
|
|
118
|
+
return { index: -1, label: '' };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function pickAutoApprovalButton(
|
|
122
|
+
buttons: string[] | null | undefined,
|
|
123
|
+
): { index: number; label: string } {
|
|
124
|
+
const labels = (buttons || []).map((button) => String(button || '').trim());
|
|
125
|
+
const index = labels.findIndex(Boolean);
|
|
126
|
+
return index >= 0 ? { index, label: labels[index] } : { index: -1, label: '' };
|
|
60
127
|
}
|
|
61
128
|
|
|
62
129
|
export function formatAutoApprovalMessage(modalMessage?: string, buttonLabel?: string): string {
|
|
@@ -65,3 +132,30 @@ export function formatAutoApprovalMessage(modalMessage?: string, buttonLabel?: s
|
|
|
65
132
|
if (cleanMessage) lines.push(cleanMessage);
|
|
66
133
|
return lines.join('\n');
|
|
67
134
|
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns true when the given text (e.g. last assistant message content, or
|
|
138
|
+
* the tail of the PTY screen) looks like an active approval/input prompt
|
|
139
|
+
* rather than a completed assistant response. Used to prevent false
|
|
140
|
+
* idle/completion events when Claude Code surfaces a "Do you want to proceed?"
|
|
141
|
+
* style prompt that the PTY parser captures as an assistant turn while the
|
|
142
|
+
* session is still awaiting user input.
|
|
143
|
+
*/
|
|
144
|
+
export function looksLikeActiveApprovalPromptText(content: string): boolean {
|
|
145
|
+
const text = content.trim();
|
|
146
|
+
if (!text || text.length > 2000) return false;
|
|
147
|
+
const hasApprovalQuestion = /do you want to (?:proceed|allow|run|make this edit|create)/i.test(text)
|
|
148
|
+
|| /this command requires approval/i.test(text)
|
|
149
|
+
|| /quick safety check/i.test(text)
|
|
150
|
+
|| /is this a project you trust/i.test(text);
|
|
151
|
+
const hasNumberedChoices = /^\s*[❯›>]?\s*1[.)]\s+(?:yes|allow|proceed|run)/im.test(text)
|
|
152
|
+
|| /^\s*1[.)]\s+yes\b/im.test(text);
|
|
153
|
+
if (hasApprovalQuestion && hasNumberedChoices) return true;
|
|
154
|
+
const lastLines = text.split(/\r?\n/).slice(-12).join('\n');
|
|
155
|
+
const hasDontAskAgain = /yes.*don'?t ask again/i.test(lastLines)
|
|
156
|
+
|| /yes.*always allow/i.test(lastLines);
|
|
157
|
+
const hasNoOption = /^\s*[❯›>]?\s*\d+[.)]\s+no\b/im.test(lastLines);
|
|
158
|
+
if (hasDontAskAgain && hasNoOption) return true;
|
|
159
|
+
if (/what do you want to do\?/i.test(text) && /^\s*\d+[.)]\s+\S/m.test(text)) return true;
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChatMessage } from '../types.js';
|
|
2
2
|
import { flattenContent } from './contracts.js';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_FINAL_SUMMARY_MAX_CHARS =
|
|
4
|
+
export const DEFAULT_FINAL_SUMMARY_MAX_CHARS = 16_000;
|
|
5
5
|
|
|
6
6
|
export function extractFinalSummaryFromMessages(
|
|
7
7
|
messages: ChatMessage[] | null | undefined,
|
|
@@ -20,20 +20,142 @@ export function extractFinalSummaryFromMessages(
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Completion summaries must describe the assistant/model result. If no
|
|
24
|
+
// user-facing assistant/model message exists yet (for example, only the
|
|
25
|
+
// dispatched user prompt is visible), return empty instead of echoing the
|
|
26
|
+
// prompt as a misleading finalSummary.
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function readChatMessageTimestampMs(message: ChatMessage | null | undefined): number | undefined {
|
|
31
|
+
if (!message) return undefined;
|
|
32
|
+
const record = message as ChatMessage & Record<string, unknown>;
|
|
33
|
+
for (const value of [record.timestamp, record.createdAt, record.created_at, record.updatedAt, record.time, record.receivedAt]) {
|
|
34
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
35
|
+
// Heuristic seconds-vs-ms detection mirrors the mesh transcript reader.
|
|
36
|
+
return value > 10_000_000_000 ? value : value * 1000;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === 'string' && value.trim()) {
|
|
39
|
+
const ms = new Date(value.trim()).getTime();
|
|
40
|
+
if (Number.isFinite(ms)) return ms;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readChatMessageTimestampIso(message: ChatMessage | null | undefined): string | undefined {
|
|
47
|
+
const ms = readChatMessageTimestampMs(message);
|
|
48
|
+
return typeof ms === 'number' ? new Date(ms).toISOString() : undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Turn-scoped variant of extractFinalSummaryFromMessages. Selects the last
|
|
53
|
+
* user-facing assistant/model bubble whose own timestamp is at/after the
|
|
54
|
+
* producing turn's start (`minTimestampMs`). This is the NOTIF Defect-B fix:
|
|
55
|
+
* a completion event's finalSummary must describe the turn THAT completed, not
|
|
56
|
+
* the prior task's last bubble. For native-source providers (claude-cli) the
|
|
57
|
+
* external transcript holds the ENTIRE session history filtered only by session
|
|
58
|
+
* start, so a completion debounce that fires before the producing turn's final
|
|
59
|
+
* assistant bubble has landed would otherwise echo the previous task's tail.
|
|
60
|
+
* A message whose timestamp predates the turn start is skipped; if no in-turn
|
|
61
|
+
* assistant bubble exists yet, returns '' (weak/empty) — never the stale tail.
|
|
62
|
+
*
|
|
63
|
+
* Mirrors the reconcile path's transcriptAfterDispatch guard (mesh-events-stale):
|
|
64
|
+
* a bubble only counts if its timestamp proves it was produced after the turn began.
|
|
65
|
+
* When `minTimestampMs` is undefined the behaviour is identical to the unscoped
|
|
66
|
+
* extractor (no turn boundary known → no filtering).
|
|
67
|
+
*/
|
|
68
|
+
export function extractFinalSummaryFromMessagesAfter(
|
|
69
|
+
messages: ChatMessage[] | null | undefined,
|
|
70
|
+
minTimestampMs: number | undefined,
|
|
71
|
+
maxChars: number = DEFAULT_FINAL_SUMMARY_MAX_CHARS,
|
|
72
|
+
): string {
|
|
73
|
+
if (!Array.isArray(messages) || messages.length === 0) return '';
|
|
74
|
+
const hasBoundary = typeof minTimestampMs === 'number' && Number.isFinite(minTimestampMs);
|
|
75
|
+
|
|
24
76
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
25
77
|
const msg = messages[i];
|
|
26
78
|
if (!msg) continue;
|
|
79
|
+
if (hasBoundary) {
|
|
80
|
+
// A bubble carrying a timestamp BEFORE the producing turn's start belongs to
|
|
81
|
+
// a prior task — skip it. A bubble with no parseable timestamp cannot be
|
|
82
|
+
// proven stale, so it is kept (the unscoped fallback) rather than dropped.
|
|
83
|
+
const ts = readChatMessageTimestampMs(msg);
|
|
84
|
+
if (typeof ts === 'number' && ts < (minTimestampMs as number)) continue;
|
|
85
|
+
}
|
|
27
86
|
const classification = classifyChatMessageVisibility(msg);
|
|
28
|
-
if (classification.isUserFacing) {
|
|
87
|
+
if (classification.isUserFacing && (msg.role === 'assistant' || msg.role === 'model')) {
|
|
29
88
|
const text = flattenContent(msg.content).trim();
|
|
30
89
|
if (text) return text.slice(0, maxChars);
|
|
31
90
|
}
|
|
32
91
|
}
|
|
33
|
-
|
|
34
92
|
return '';
|
|
35
93
|
}
|
|
36
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Like extractFinalSummaryFromMessages but also returns the ISO timestamp of the
|
|
97
|
+
* selected final assistant/model message. Completion reconciliation needs the
|
|
98
|
+
* timestamp to prove the transcript was produced AFTER the dispatch — without it
|
|
99
|
+
* reconcileDirectDispatchCompletionFromTranscript rejects non-JSON summaries as
|
|
100
|
+
* "transcript_not_proven_after_dispatch". The summary selection is identical so the
|
|
101
|
+
* timestamp always belongs to the message whose text became the summary.
|
|
102
|
+
*/
|
|
103
|
+
export function extractFinalAssistantSummaryEvidence(
|
|
104
|
+
messages: ChatMessage[] | null | undefined,
|
|
105
|
+
maxChars: number = DEFAULT_FINAL_SUMMARY_MAX_CHARS,
|
|
106
|
+
): { finalSummary: string; transcriptMessageAt?: string } {
|
|
107
|
+
const turnEnd = selectFinalAssistantTurnEndMessage(messages);
|
|
108
|
+
if (!turnEnd) return { finalSummary: '' };
|
|
109
|
+
return {
|
|
110
|
+
finalSummary: flattenContent(turnEnd.content).trim().slice(0, maxChars),
|
|
111
|
+
transcriptMessageAt: readChatMessageTimestampIso(turnEnd),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* EARLYNOTIFY-GATEBYPASS (a)/(b) — the shared turn-finality selector for the completion
|
|
117
|
+
* final-assistant judgement, so the ~duplicated "which bubble is the turn's final answer"
|
|
118
|
+
* logic is decided ONE way (UNIFY A-6).
|
|
119
|
+
*
|
|
120
|
+
* Returns the message that qualifies as the turn's FINAL assistant bubble, or null when the
|
|
121
|
+
* transcript does not (yet) prove a turn end. The rule is a NON-EMPTY LATEST user-facing
|
|
122
|
+
* assistant/model bubble:
|
|
123
|
+
* - Scanning from the end, the FIRST user-facing assistant/model bubble encountered IS the
|
|
124
|
+
* turn-end candidate. If it is EMPTY (a streaming placeholder / mid-turn narration whose
|
|
125
|
+
* text has not landed), the turn is still in flight → return null. Crucially we do NOT walk
|
|
126
|
+
* back past that empty bubble to promote an EARLIER assistant narration to "final" (the
|
|
127
|
+
* Defect-B walk-back).
|
|
128
|
+
* - Trailing activity/internal bubbles (tool/thought/status) are skipped — they are not the
|
|
129
|
+
* assistant's user-facing answer.
|
|
130
|
+
* - A trailing user-facing USER message (a freshly dispatched task with no reply yet) means the
|
|
131
|
+
* assistant did not have the last word — no earlier bubble is promoted here; callers that must
|
|
132
|
+
* still reach a prior turn's tail use the timestamp-scoped extractor instead.
|
|
133
|
+
*
|
|
134
|
+
* A bare snapshot-idle with an arbitrary non-empty tail therefore does NOT qualify as a turn end;
|
|
135
|
+
* only a genuine latest-assistant bubble does. Turn-finality signals that live OUTSIDE the
|
|
136
|
+
* transcript (a committed generating→idle FSM transition, a self-attributing final_summary_json,
|
|
137
|
+
* or a continuous-idle streak) are enforced by the callers (the CLI completion gate, the reconcile
|
|
138
|
+
* grace gate) on top of this structural check.
|
|
139
|
+
*/
|
|
140
|
+
export function selectFinalAssistantTurnEndMessage(
|
|
141
|
+
messages: ChatMessage[] | null | undefined,
|
|
142
|
+
): ChatMessage | null {
|
|
143
|
+
if (!Array.isArray(messages) || messages.length === 0) return null;
|
|
144
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
145
|
+
const msg = messages[i];
|
|
146
|
+
if (!msg) continue;
|
|
147
|
+
const classification = classifyChatMessageVisibility(msg);
|
|
148
|
+
if (!classification.isUserFacing) continue; // skip tool/thought/status activity + internal
|
|
149
|
+
if (msg.role === 'assistant' || msg.role === 'model') {
|
|
150
|
+
// The latest user-facing assistant bubble: it is the turn end iff it has real text.
|
|
151
|
+
return flattenContent(msg.content).trim() ? msg : null;
|
|
152
|
+
}
|
|
153
|
+
// A user (or other role) had the last user-facing word → the assistant turn is not complete.
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
37
159
|
export const BUILTIN_CHAT_MESSAGE_KINDS = ['standard', 'thought', 'tool', 'terminal', 'system'] as const;
|
|
38
160
|
|
|
39
161
|
export type BuiltinChatMessageKind = typeof BUILTIN_CHAT_MESSAGE_KINDS[number];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Provider-effect dedup and message-formatting helpers extracted from
|
|
2
|
+
// cli-provider-instance.ts. Pure move — no behavior change. None of these used
|
|
3
|
+
// any instance state; they were private methods invoked only within the class.
|
|
4
|
+
|
|
5
|
+
export function getEffectDedupKey(effect: { id?: string; type: string; message?: { content?: unknown }; toast?: { message?: string }; notification?: { title?: string; body?: string } }): string {
|
|
6
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
7
|
+
if (effect.type === 'message') {
|
|
8
|
+
const content = typeof effect.message?.content === 'string'
|
|
9
|
+
? effect.message.content
|
|
10
|
+
: JSON.stringify(effect.message?.content || '');
|
|
11
|
+
return `provider_effect:message:${content}`;
|
|
12
|
+
}
|
|
13
|
+
if (effect.type === 'notification') {
|
|
14
|
+
return `provider_effect:notification:${effect.notification?.title || ''}:${effect.notification?.body || ''}`;
|
|
15
|
+
}
|
|
16
|
+
return `provider_effect:toast:${effect.toast?.message || ''}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getPersistedEffectContent(effect: { type: string; message?: { content?: unknown }; toast?: { message?: string }; notification?: { title?: string; body?: string; bubbleContent?: unknown } }): string | null {
|
|
20
|
+
if (effect.type === 'message') {
|
|
21
|
+
return typeof effect.message?.content === 'string'
|
|
22
|
+
? effect.message.content
|
|
23
|
+
: JSON.stringify(effect.message?.content || '');
|
|
24
|
+
}
|
|
25
|
+
if (effect.type === 'toast') {
|
|
26
|
+
return effect.toast?.message || null;
|
|
27
|
+
}
|
|
28
|
+
if (effect.type === 'notification') {
|
|
29
|
+
if (typeof effect.notification?.bubbleContent === 'string') return effect.notification.bubbleContent;
|
|
30
|
+
if (typeof effect.notification?.title === 'string' && effect.notification.title.trim()) {
|
|
31
|
+
return `${effect.notification.title}\n${effect.notification.body || ''}`.trim();
|
|
32
|
+
}
|
|
33
|
+
return effect.notification?.body || null;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function formatApprovalRequestMessage(modalMessage?: string, buttons?: string[]): string {
|
|
39
|
+
const lines = ['Approval requested'];
|
|
40
|
+
const cleanMessage = String(modalMessage || '').trim();
|
|
41
|
+
if (cleanMessage) lines.push(cleanMessage);
|
|
42
|
+
const labels = (buttons || []).map((button) => String(button || '').trim()).filter(Boolean);
|
|
43
|
+
if (labels.length > 0) {
|
|
44
|
+
lines.push(labels.map((label) => `[${label}]`).join(' '));
|
|
45
|
+
}
|
|
46
|
+
return lines.join('\n');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function formatMarkerTimestamp(timestamp: number): string {
|
|
50
|
+
const date = new Date(timestamp);
|
|
51
|
+
const pad = (value: number) => String(value).padStart(2, '0');
|
|
52
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
53
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI provider persisted-history dedup — incremental append computation.
|
|
3
|
+
*
|
|
4
|
+
* Pure move out of cli-provider-instance.ts (no behavior change): the
|
|
5
|
+
* shared-prefix diff that turns a full parsed transcript into the newly-added
|
|
6
|
+
* tail to append to the persisted chat history. cli-provider-instance
|
|
7
|
+
* re-exports buildIncrementalHistoryAppendMessages so existing importers/tests
|
|
8
|
+
* keep their path.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { flattenContent } from './contracts.js';
|
|
12
|
+
|
|
13
|
+
export type PersistableCliHistoryMessage = {
|
|
14
|
+
role: string;
|
|
15
|
+
content: string;
|
|
16
|
+
kind?: string;
|
|
17
|
+
senderName?: string;
|
|
18
|
+
receivedAt?: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function normalizePersistableCliHistoryContent(content: unknown): string {
|
|
22
|
+
return flattenContent(content as any).replace(/\s+/g, ' ').trim();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function buildPersistableCliHistorySignature(message: PersistableCliHistoryMessage): string {
|
|
26
|
+
return [
|
|
27
|
+
String(message.role || ''),
|
|
28
|
+
String(message.kind || ''),
|
|
29
|
+
String(message.senderName || ''),
|
|
30
|
+
normalizePersistableCliHistoryContent(message.content),
|
|
31
|
+
].join('|');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function hasSamePersistableCliHistoryIdentity(a: PersistableCliHistoryMessage, b: PersistableCliHistoryMessage): boolean {
|
|
35
|
+
return String(a?.role || '') === String(b?.role || '')
|
|
36
|
+
&& String(a?.kind || '') === String(b?.kind || '')
|
|
37
|
+
&& String(a?.senderName || '') === String(b?.senderName || '')
|
|
38
|
+
&& String(a?.content || '') === String(b?.content || '');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function buildIncrementalHistoryAppendMessages(
|
|
42
|
+
previousMessages: PersistableCliHistoryMessage[],
|
|
43
|
+
currentMessages: PersistableCliHistoryMessage[],
|
|
44
|
+
): PersistableCliHistoryMessage[] {
|
|
45
|
+
if (!Array.isArray(currentMessages) || currentMessages.length === 0) return [];
|
|
46
|
+
if (!Array.isArray(previousMessages) || previousMessages.length === 0) return currentMessages;
|
|
47
|
+
|
|
48
|
+
const comparableLength = Math.min(previousMessages.length, currentMessages.length);
|
|
49
|
+
let sharedPrefixLength = 0;
|
|
50
|
+
while (
|
|
51
|
+
sharedPrefixLength < comparableLength
|
|
52
|
+
&& hasSamePersistableCliHistoryIdentity(previousMessages[sharedPrefixLength], currentMessages[sharedPrefixLength])
|
|
53
|
+
) {
|
|
54
|
+
sharedPrefixLength += 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (sharedPrefixLength === currentMessages.length) return [];
|
|
58
|
+
if (sharedPrefixLength === previousMessages.length) return currentMessages.slice(sharedPrefixLength);
|
|
59
|
+
|
|
60
|
+
// Rare fallback: preserve the older whitespace-normalized behavior only when
|
|
61
|
+
// the cheap identity check detects a changed prefix. Recomputing normalized
|
|
62
|
+
// signatures for the full transcript on every idle status poll was a CPU
|
|
63
|
+
// hot path for long CLI sessions.
|
|
64
|
+
while (
|
|
65
|
+
sharedPrefixLength < comparableLength
|
|
66
|
+
&& buildPersistableCliHistorySignature(previousMessages[sharedPrefixLength])
|
|
67
|
+
=== buildPersistableCliHistorySignature(currentMessages[sharedPrefixLength])
|
|
68
|
+
) {
|
|
69
|
+
sharedPrefixLength += 1;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (sharedPrefixLength === currentMessages.length) return [];
|
|
73
|
+
if (sharedPrefixLength === previousMessages.length) return currentMessages.slice(sharedPrefixLength);
|
|
74
|
+
return currentMessages;
|
|
75
|
+
}
|