@vellumai/assistant 0.8.6 → 0.8.7-dev.202606052118.34cd356
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/AGENTS.md +4 -4
- package/Dockerfile +21 -4
- package/bun.lock +13 -4
- package/docker-entrypoint.sh +12 -8
- package/docker-init-apt-root.sh +3 -1
- package/docker-kata-apt-env.sh +3 -1
- package/docker-kata-runtime-family.sh +12 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/plugins.md +110 -83
- package/examples/plugins/echo/README.md +13 -12
- package/examples/plugins/echo/register.ts +0 -54
- package/knip.json +1 -0
- package/node_modules/@vellumai/environments/bun.lock +24 -0
- package/node_modules/@vellumai/environments/package.json +18 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
- package/node_modules/@vellumai/environments/src/index.ts +11 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
- package/node_modules/@vellumai/environments/src/types.ts +70 -0
- package/node_modules/@vellumai/environments/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +13 -8
- package/openapi.yaml +6964 -539
- package/package.json +8 -4
- package/scripts/generate-openapi.ts +88 -54
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
- package/src/__tests__/agent-loop-exit-reason.test.ts +188 -45
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +7 -5
- package/src/__tests__/agent-loop-thinking.test.ts +17 -12
- package/src/__tests__/agent-loop.test.ts +238 -422
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +6 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
- package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -3
- package/src/__tests__/anthropic-provider.test.ts +296 -57
- package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
- package/src/__tests__/app-control-flow.test.ts +6 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +4 -11
- package/src/__tests__/approval-routes-http.test.ts +8 -3
- package/src/__tests__/assistant-event-hub.test.ts +25 -0
- package/src/__tests__/assistant-event.test.ts +15 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/assistant-stream-state.test.ts +645 -0
- package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
- package/src/__tests__/avatar-e2e.test.ts +7 -37
- package/src/__tests__/avatar-generator.test.ts +12 -42
- package/src/__tests__/avatar-identity-sync.test.ts +28 -3
- package/src/__tests__/background-shell-bash.test.ts +3 -7
- package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
- package/src/__tests__/btw-routes.test.ts +69 -15
- package/src/__tests__/build-persisted-content.test.ts +184 -0
- package/src/__tests__/call-pointer-messages.test.ts +5 -3
- package/src/__tests__/call-site-routing-provider.test.ts +22 -40
- package/src/__tests__/catalog-files.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +49 -21
- package/src/__tests__/channel-approvals.test.ts +4 -2
- package/src/__tests__/channel-invite-transport.test.ts +1 -5
- package/src/__tests__/channel-readiness-routes.test.ts +0 -4
- package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
- package/src/__tests__/channel-retry-sweep.test.ts +71 -79
- package/src/__tests__/clawhub-files.test.ts +1 -0
- package/src/__tests__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +132 -0
- package/src/__tests__/compaction-events.test.ts +5 -17
- package/src/__tests__/compaction-trail-store.test.ts +1 -79
- package/src/__tests__/compaction.benchmark.test.ts +0 -30
- package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
- package/src/__tests__/computer-use-tools.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +28 -0
- package/src/__tests__/context-search-agent-runner.test.ts +6 -3
- package/src/__tests__/context-token-estimator.test.ts +34 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +70 -25
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +9 -7
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -34
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +476 -963
- package/src/__tests__/conversation-agent-loop.test.ts +823 -1321
- package/src/__tests__/conversation-analysis-routes.test.ts +7 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-clear-safety.test.ts +20 -10
- package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-disk-view.test.ts +10 -17
- package/src/__tests__/conversation-fork-crud.test.ts +86 -172
- package/src/__tests__/conversation-fork-route.test.ts +16 -14
- package/src/__tests__/conversation-history-web-search.test.ts +11 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
- package/src/__tests__/conversation-lifecycle.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
- package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
- package/src/__tests__/conversation-pairing.test.ts +10 -7
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -0
- package/src/__tests__/conversation-process-callsite.test.ts +27 -30
- package/src/__tests__/conversation-provider-retry-repair.test.ts +80 -51
- package/src/__tests__/conversation-queue.test.ts +272 -164
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +8 -7
- package/src/__tests__/conversation-runtime-assembly.test.ts +317 -313
- package/src/__tests__/conversation-runtime-workspace.test.ts +114 -36
- package/src/__tests__/conversation-slash-commands.test.ts +8 -42
- package/src/__tests__/conversation-slash-queue.test.ts +42 -31
- package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
- package/src/__tests__/conversation-speed-override.test.ts +8 -22
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +90 -15
- package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
- package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
- package/src/__tests__/conversation-sync-tags.test.ts +27 -15
- package/src/__tests__/conversation-title-service.test.ts +135 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
- package/src/__tests__/conversation-unread-route.test.ts +14 -2
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-wipe.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +20 -17
- package/src/__tests__/conversation-workspace-injection.test.ts +114 -23
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +34 -13
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/credential-execution-tools.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/cross-provider-web-search.test.ts +220 -3
- package/src/__tests__/cu-unified-flow.test.ts +26 -1
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -0
- package/src/__tests__/disk-pressure-guard.test.ts +66 -0
- package/src/__tests__/disk-pressure-routes.test.ts +9 -2
- package/src/__tests__/dm-persistence.test.ts +12 -3
- package/src/__tests__/dynamic-page-surface.test.ts +99 -0
- package/src/__tests__/edit-propagation.test.ts +1 -2
- package/src/__tests__/empty-response-hook.test.ts +304 -0
- package/src/__tests__/feature-flag-test-helpers.ts +2 -2
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/filing-service.test.ts +2 -2
- package/src/__tests__/first-greeting.test.ts +55 -14
- package/src/__tests__/gemini-image-service.test.ts +13 -0
- package/src/__tests__/gemini-inline-media.test.ts +78 -0
- package/src/__tests__/gemini-provider.test.ts +351 -28
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/guardian-routing-state.test.ts +60 -71
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +10 -8
- package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
- package/src/__tests__/heartbeat-service.test.ts +3 -1
- package/src/__tests__/helpers/mock-provider.ts +110 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
- package/src/__tests__/history-repair-hook.test.ts +162 -0
- package/src/__tests__/history-repair-observability.test.ts +1 -1
- package/src/__tests__/history-repair.test.ts +2 -1
- package/src/__tests__/host-app-control-proxy.test.ts +2 -0
- package/src/__tests__/host-app-control-routes.test.ts +1 -1
- package/src/__tests__/host-cu-proxy.test.ts +2 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
- package/src/__tests__/host-file-edit-tool.test.ts +4 -2
- package/src/__tests__/host-file-proxy.test.ts +31 -0
- package/src/__tests__/host-file-read-tool.test.ts +4 -2
- package/src/__tests__/host-file-write-tool.test.ts +9 -3
- package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
- package/src/__tests__/host-shell-tool.test.ts +9 -4
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/identity-intro-cache.test.ts +47 -114
- package/src/__tests__/identity-routes.test.ts +248 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +12 -3
- package/src/__tests__/injector-background-turn.test.ts +3 -9
- package/src/__tests__/injector-chain.test.ts +139 -275
- package/src/__tests__/injector-disk-pressure.test.ts +75 -41
- package/src/__tests__/injector-document-comments.test.ts +3 -3
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
- package/src/__tests__/injector-v3-suppression.test.ts +214 -0
- package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
- package/src/__tests__/list-messages-attachments.test.ts +7 -8
- package/src/__tests__/list-messages-hidden-metadata.test.ts +55 -15
- package/src/__tests__/list-messages-page-latest.test.ts +60 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +56 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
- package/src/__tests__/llm-resolver.test.ts +23 -47
- package/src/__tests__/llm-usage-store.test.ts +268 -1
- package/src/__tests__/log-export-routes.test.ts +59 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
- package/src/__tests__/mcp-auth-routes.test.ts +15 -10
- package/src/__tests__/mcp-health-check.test.ts +18 -13
- package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
- package/src/__tests__/messaging-send-tool.test.ts +8 -4
- package/src/__tests__/migration-export-http.test.ts +12 -12
- package/src/__tests__/migration-import-commit-http.test.ts +8 -8
- package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +205 -20
- package/src/__tests__/notification-decision-identity.test.ts +9 -18
- package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
- package/src/__tests__/oauth-commands-routes.test.ts +1 -1
- package/src/__tests__/onboarding-template-contract.test.ts +12 -0
- package/src/__tests__/openai-image-service.test.ts +17 -0
- package/src/__tests__/openai-provider.test.ts +97 -71
- package/src/__tests__/openai-responses-provider.test.ts +21 -77
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
- package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -286
- package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
- package/src/__tests__/persist-unsendable-image.test.ts +215 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +3 -1
- package/src/__tests__/pipeline-runner.test.ts +31 -43
- package/src/__tests__/pkb-autoinject.test.ts +2 -5
- package/src/__tests__/plugin-bootstrap.test.ts +62 -51
- package/src/__tests__/plugin-registry.test.ts +0 -27
- package/src/__tests__/plugin-route-contribution.test.ts +6 -16
- package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
- package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
- package/src/__tests__/plugin-types.test.ts +8 -173
- package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
- package/src/__tests__/process-message-background-slack.test.ts +17 -16
- package/src/__tests__/process-message-display-content.test.ts +36 -44
- package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
- package/src/__tests__/provider-error-scenarios.test.ts +7 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
- package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
- package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
- package/src/__tests__/provider-usage-tracking.test.ts +0 -6
- package/src/__tests__/ratelimit.test.ts +9 -4
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
- package/src/__tests__/relay-server.test.ts +20 -13
- package/src/__tests__/resolve-trust-class.test.ts +4 -4
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
- package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
- package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +390 -0
- package/src/__tests__/schedule-routes.test.ts +683 -12
- package/src/__tests__/schedule-store.test.ts +108 -0
- package/src/__tests__/schedule-tools.test.ts +160 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
- package/src/__tests__/secret-response-routing.test.ts +13 -11
- package/src/__tests__/send-endpoint-busy.test.ts +6 -2
- package/src/__tests__/server-history-render.test.ts +314 -1
- package/src/__tests__/shell-observability.test.ts +249 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +44 -11
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
- package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
- package/src/__tests__/skillssh-files.test.ts +1 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -6
- package/src/__tests__/strip-memory-injections.test.ts +102 -14
- package/src/__tests__/subagent-call-site-routing.test.ts +3 -3
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
- package/src/__tests__/subagent-manager-notify.test.ts +1 -3
- package/src/__tests__/subagent-notify-parent.test.ts +1 -3
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +19 -16
- package/src/__tests__/system-prompt.test.ts +74 -0
- package/src/__tests__/task-scheduler.test.ts +162 -1
- package/src/__tests__/terminal-tools.test.ts +9 -25
- package/src/__tests__/thread-backfill.test.ts +4 -9
- package/src/__tests__/title-generate-hook.test.ts +319 -0
- package/src/__tests__/tool-error-hook.test.ts +278 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +481 -16
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
- package/src/__tests__/tool-result-truncation.test.ts +1 -1
- package/src/__tests__/tools-audio-read.test.ts +113 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
- package/src/__tests__/turn-events-store.test.ts +11 -7
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
- package/src/__tests__/ui-work-result-surface.test.ts +159 -0
- package/src/__tests__/usage-routes.test.ts +285 -1
- package/src/__tests__/user-plugin-loader.test.ts +2 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
- package/src/__tests__/voice-session-bridge.test.ts +19 -10
- package/src/__tests__/web-search-backend-failure.test.ts +166 -0
- package/src/acp/__tests__/agent-process.test.ts +161 -0
- package/src/acp/__tests__/client-handler.test.ts +40 -0
- package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +695 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +125 -0
- package/src/acp/auto-install.ts +174 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/feature-gate.test.ts +48 -0
- package/src/acp/feature-gate.ts +34 -0
- package/src/acp/prepare-agent-env.ts +52 -11
- package/src/acp/resolve-agent.test.ts +147 -6
- package/src/acp/resolve-agent.ts +81 -7
- package/src/acp/resume-hint.ts +22 -0
- package/src/acp/session-manager.ts +487 -71
- package/src/agent/compaction-circuit.ts +98 -0
- package/src/agent/loop.ts +651 -450
- package/src/api/README.md +19 -17
- package/src/api/constants/tool-execution.ts +21 -0
- package/src/api/events/assistant-activity-state.ts +75 -0
- package/src/api/events/assistant-outbound-attachment.ts +25 -27
- package/src/api/events/assistant-text-delta.ts +6 -8
- package/src/api/events/assistant-thinking-delta.ts +33 -0
- package/src/api/events/assistant-turn-start.ts +5 -7
- package/src/api/events/avatar-updated.ts +24 -0
- package/src/api/events/compaction-circuit-closed.ts +26 -0
- package/src/api/events/compaction-circuit-open.ts +28 -0
- package/src/api/events/confirmation-request.ts +114 -0
- package/src/api/events/contact-request.ts +33 -0
- package/src/api/events/conversation-error.ts +77 -0
- package/src/api/events/conversation-list-invalidated.ts +38 -0
- package/src/api/events/conversation-title-updated.ts +24 -0
- package/src/api/events/disk-pressure-status-changed.ts +61 -0
- package/src/api/events/document-comment-created.ts +24 -28
- package/src/api/events/document-comment-deleted.ts +6 -8
- package/src/api/events/document-comment-reopened.ts +6 -8
- package/src/api/events/document-comment-resolved.ts +8 -10
- package/src/api/events/document-editor-update.ts +27 -0
- package/src/api/events/error.ts +32 -0
- package/src/api/events/generation-cancelled.ts +4 -6
- package/src/api/events/generation-handoff.ts +13 -15
- package/src/api/events/home-feed-updated.ts +26 -0
- package/src/api/events/identity-changed.ts +32 -0
- package/src/api/events/interaction-resolved.ts +50 -0
- package/src/api/events/message-complete.ts +10 -12
- package/src/api/events/message-dequeued.ts +21 -0
- package/src/api/events/message-queued-deleted.ts +23 -0
- package/src/api/events/message-queued.ts +22 -0
- package/src/api/events/message-request-complete.ts +29 -0
- package/src/api/events/navigate-settings.ts +20 -0
- package/src/api/events/notification-intent.ts +33 -0
- package/src/api/events/open-url.ts +6 -8
- package/src/api/events/question-request.ts +67 -0
- package/src/api/events/relationship-state-updated.ts +4 -6
- package/src/api/events/secret-request.ts +42 -0
- package/src/api/events/subagent-event.ts +79 -0
- package/src/api/events/subagent-spawned.ts +40 -0
- package/src/api/events/subagent-status-changed.ts +65 -0
- package/src/api/events/sync-changed.ts +29 -0
- package/src/api/events/tool-output-chunk.ts +45 -0
- package/src/api/events/tool-result.ts +129 -0
- package/src/api/events/tool-use-preview-start.ts +32 -0
- package/src/api/events/tool-use-start.ts +8 -10
- package/src/api/events/trace-event.ts +69 -0
- package/src/api/events/turn-profile-auto-routed.ts +28 -0
- package/src/api/events/ui-surface-complete.ts +30 -0
- package/src/api/events/ui-surface-dismiss.ts +22 -0
- package/src/api/events/ui-surface-show.ts +67 -0
- package/src/api/events/ui-surface-update.ts +26 -0
- package/src/api/events/usage-update.ts +34 -0
- package/src/api/events/user-message-echo.ts +35 -0
- package/src/api/index.ts +389 -0
- package/src/api/requests/dictation.ts +45 -0
- package/src/api/responses/conversation-message.ts +374 -0
- package/src/api/responses/disk-pressure-status.ts +26 -0
- package/src/api/responses/home.ts +217 -0
- package/src/api/responses/llm-context-response.ts +2 -0
- package/src/api/responses/memory-v3-selection-log.ts +50 -0
- package/src/api/responses/subagent-detail.ts +48 -0
- package/src/approvals/guardian-decision-primitive.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +7 -10
- package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
- package/src/avatar/__tests__/avatar-store.test.ts +198 -0
- package/src/avatar/avatar-manifest.ts +195 -0
- package/src/avatar/avatar-store.ts +113 -0
- package/src/avatar/traits-png-sync.ts +8 -2
- package/src/background-wake/next-wake.test.ts +31 -1
- package/src/background-wake/next-wake.ts +5 -1
- package/src/calls/call-conversation-messages.ts +6 -4
- package/src/calls/guardian-action-sweep.ts +6 -4
- package/src/calls/relay-server.ts +12 -8
- package/src/calls/voice-session-bridge.ts +13 -27
- package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
- package/src/cli/commands/__tests__/notifications.test.ts +58 -14
- package/src/cli/commands/avatar.ts +17 -11
- package/src/cli/commands/conversations.ts +15 -1
- package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
- package/src/cli/commands/db/__tests__/status.test.ts +253 -0
- package/src/cli/commands/db/format.ts +48 -0
- package/src/cli/commands/db/index.ts +29 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
- package/src/cli/commands/db/repair-step-integrity.ts +146 -0
- package/src/cli/commands/db/repair-steps.ts +164 -0
- package/src/cli/commands/db/repair.ts +141 -0
- package/src/cli/commands/db/status.ts +366 -0
- package/src/cli/commands/memory-v3.ts +159 -445
- package/src/cli/commands/notifications.ts +112 -60
- package/src/cli/lib/cli-colors.ts +24 -6
- package/src/cli/program.ts +4 -5
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +4 -4
- package/src/config/acp-defaults.test.ts +10 -0
- package/src/config/acp-defaults.ts +6 -0
- package/src/config/assistant-feature-flags.ts +24 -13
- package/src/config/bundled-skills/acp/SKILL.md +64 -30
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -387
- package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
- package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
- package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
- package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
- package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
- package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
- package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
- package/src/config/bundled-skills/messaging/SKILL.md +0 -7
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +2 -7
- package/src/config/feature-flag-cache.ts +3 -3
- package/src/config/feature-flag-registry.json +68 -12
- package/src/config/schemas/__tests__/memory-v2.test.ts +2 -226
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
- package/src/config/schemas/call-site-catalog.ts +8 -15
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +3 -3
- package/src/config/schemas/memory-lifecycle.ts +24 -0
- package/src/config/schemas/memory-v2.ts +8 -253
- package/src/config/schemas/memory-v3.ts +47 -0
- package/src/config/schemas/memory.ts +6 -1
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/timeouts.ts +3 -1
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills.ts +13 -0
- package/src/context/compactor.ts +55 -32
- package/src/context/strip-injections.ts +128 -0
- package/src/context/token-estimator.ts +42 -0
- package/src/context/tool-result-truncation.ts +1 -66
- package/src/context/window-manager.ts +141 -26
- package/src/credential-execution/executable-discovery.ts +16 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
- package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
- package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
- package/src/daemon/approval-generators.ts +4 -4
- package/src/daemon/assistant-attachments.ts +1 -1
- package/src/daemon/config-watcher.ts +7 -1
- package/src/daemon/context-overflow-reducer.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +793 -215
- package/src/daemon/conversation-agent-loop.ts +487 -1478
- package/src/daemon/conversation-error.ts +7 -7
- package/src/daemon/conversation-history.ts +27 -10
- package/src/daemon/conversation-launch.ts +4 -8
- package/src/daemon/conversation-lifecycle.ts +13 -42
- package/src/daemon/conversation-messaging.ts +8 -9
- package/src/daemon/conversation-notifiers.ts +7 -5
- package/src/daemon/conversation-process.ts +109 -93
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +209 -382
- package/src/daemon/conversation-slash.ts +6 -25
- package/src/daemon/conversation-store.ts +15 -95
- package/src/daemon/conversation-surfaces.ts +277 -73
- package/src/daemon/conversation-tool-setup.ts +5 -29
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +123 -146
- package/src/daemon/daemon-skill-host.ts +2 -6
- package/src/daemon/disk-pressure-guard.ts +35 -29
- package/src/daemon/external-plugins-bootstrap.ts +53 -32
- package/src/daemon/first-greeting.ts +26 -4
- package/src/daemon/guardian-action-generators.ts +2 -2
- package/src/daemon/handlers/config-a2a.ts +51 -36
- package/src/daemon/handlers/config-slack-channel.ts +20 -14
- package/src/daemon/handlers/config-telegram.ts +16 -2
- package/src/daemon/handlers/conversations.ts +9 -23
- package/src/daemon/handlers/shared.ts +158 -82
- package/src/daemon/handlers/skills.ts +53 -20
- package/src/daemon/host-app-control-proxy.ts +54 -1
- package/src/daemon/host-cu-proxy.ts +46 -22
- package/src/daemon/host-file-proxy.ts +25 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -6
- package/src/daemon/lifecycle.ts +53 -55
- package/src/daemon/message-protocol.ts +2 -3
- package/src/daemon/message-provenance.ts +49 -0
- package/src/daemon/message-types/apps.ts +1 -29
- package/src/daemon/message-types/contacts.ts +3 -20
- package/src/daemon/message-types/conversations.ts +13 -111
- package/src/daemon/message-types/documents.ts +3 -9
- package/src/daemon/message-types/home.ts +4 -17
- package/src/daemon/message-types/integrations.ts +2 -6
- package/src/daemon/message-types/messages.ts +37 -400
- package/src/daemon/message-types/notifications.ts +2 -32
- package/src/daemon/message-types/settings.ts +3 -8
- package/src/daemon/message-types/skills.ts +4 -0
- package/src/daemon/message-types/surfaces.ts +138 -3
- package/src/daemon/message-types/sync.ts +12 -25
- package/src/daemon/message-types/workspace.ts +3 -11
- package/src/daemon/now-scratchpad.ts +21 -0
- package/src/daemon/orphan-reaper.test.ts +210 -0
- package/src/daemon/orphan-reaper.ts +240 -0
- package/src/daemon/overflow-reduction-loop.ts +230 -0
- package/src/daemon/persist-unsendable-image.ts +117 -0
- package/src/daemon/process-message.ts +50 -49
- package/src/daemon/server.ts +14 -0
- package/src/daemon/tool-side-effects.ts +10 -7
- package/src/daemon/trace-emitter.ts +6 -4
- package/src/daemon/trust-context.ts +32 -0
- package/src/daemon/wake-target-adapter.ts +14 -2
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -1
- package/src/heartbeat/heartbeat-run-store.ts +54 -1
- package/src/heartbeat/heartbeat-service.ts +42 -0
- package/src/home/feed-types.ts +36 -221
- package/src/home/home-greeting-cache.ts +24 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/email-ipc.test.ts +0 -9
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
- package/src/ipc/gateway-client.test.ts +2 -2
- package/src/ipc/gateway-client.ts +3 -3
- package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
- package/src/ipc/routes/route-adapter.ts +45 -6
- package/src/ipc/skill-routes/__tests__/memory.test.ts +33 -9
- package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
- package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
- package/src/ipc/skill-routes/memory.ts +29 -14
- package/src/ipc/skill-routes/providers.ts +5 -6
- package/src/ipc/skill-routes/registries.ts +13 -61
- package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
- package/src/media/gemini-image-service.ts +15 -0
- package/src/media/openai-image-service.ts +14 -0
- package/src/media/types.ts +34 -0
- package/src/memory/__tests__/conversation-queries.test.ts +192 -8
- package/src/memory/__tests__/db-maintenance.test.ts +128 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
- package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
- package/src/memory/auth-fallback-events-store.ts +94 -0
- package/src/memory/context-search/agent-runner.ts +2 -4
- package/src/memory/conversation-crud.ts +39 -8
- package/src/memory/conversation-queries.ts +78 -22
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/conversation-title-service.ts +65 -41
- package/src/memory/db-init.ts +14 -0
- package/src/memory/db-maintenance.ts +18 -2
- package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
- package/src/memory/graph/consolidation.ts +8 -11
- package/src/memory/graph/conversation-graph-memory.ts +106 -8
- package/src/memory/graph/extraction.ts +6 -9
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.ts +20 -26
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/job-handlers/conversation-starters.ts +45 -34
- package/src/memory/job-handlers/summarization.ts +1 -2
- package/src/memory/jobs-store.ts +36 -1
- package/src/memory/jobs-worker.ts +82 -43
- package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
- package/src/memory/llm-request-log-source-local.ts +0 -11
- package/src/memory/llm-request-log-source.ts +9 -25
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +234 -50
- package/src/memory/memory-marker.ts +17 -0
- package/src/memory/memory-retrospective-job.ts +6 -2
- package/src/memory/memory-v2-activation-log-store.ts +1 -83
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
- package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
- package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
- package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
- package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
- package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
- package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
- package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/pkb/autoinject.ts +61 -0
- package/src/memory/pkb/context.ts +50 -0
- package/src/memory/pkb/types.ts +14 -0
- package/src/memory/schedule-attribution-sql.ts +104 -0
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/schema/infrastructure.ts +27 -0
- package/src/memory/usage-grouped-buckets.ts +6 -1
- package/src/memory/v2/__tests__/consolidation-job.test.ts +125 -1
- package/src/memory/v2/__tests__/migration.test.ts +11 -3
- package/src/memory/v2/__tests__/page-index.test.ts +37 -1
- package/src/memory/v2/__tests__/router.test.ts +14 -4
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
- package/src/memory/v2/backfill-jobs.ts +6 -0
- package/src/memory/v2/consolidation-job.ts +99 -10
- package/src/memory/v2/migration.ts +5 -3
- package/src/memory/v2/page-index.ts +11 -0
- package/src/memory/v2/router.ts +8 -11
- package/src/memory/v2/sweep-job.ts +8 -11
- package/src/memory/v2/types.ts +1 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
- package/src/messaging/providers/slack/render-transcript.ts +2 -2
- package/src/messaging/style-analyzer.ts +8 -11
- package/src/notifications/conversation-pairing.ts +8 -13
- package/src/notifications/decision-engine.ts +16 -16
- package/src/notifications/home-feed-side-effect.ts +12 -1
- package/src/notifications/preference-extractor.ts +11 -14
- package/src/permissions/prompter.ts +46 -36
- package/src/permissions/question-prompter.test.ts +35 -26
- package/src/permissions/question-prompter.ts +6 -10
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +10 -1
- package/src/plugin-api/types.ts +176 -4
- package/src/plugins/defaults/compaction/compact.ts +59 -0
- package/src/plugins/defaults/compaction/package.json +15 -0
- package/src/plugins/defaults/compaction/register.ts +24 -0
- package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
- package/src/plugins/defaults/empty-response/package.json +15 -0
- package/src/plugins/defaults/empty-response/register.ts +23 -0
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/history-repair/package.json +15 -0
- package/src/plugins/defaults/history-repair/register.ts +24 -0
- package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
- package/src/plugins/defaults/index.ts +22 -49
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
- package/src/plugins/defaults/{injectors.ts → memory-retrieval/injectors.ts} +295 -112
- package/src/plugins/defaults/memory-v3-shadow/__tests__/assign.test.ts +242 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +118 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/core.test.ts +39 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +36 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +37 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/health.test.ts +219 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +330 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +288 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/needle.test.ts +107 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +436 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/reconcile.test.ts +274 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +61 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/router.test.ts +332 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +179 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selector.test.ts +470 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +432 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/snapshot.test.ts +168 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/tree.test.ts +192 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +54 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +106 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +44 -0
- package/src/plugins/defaults/memory-v3-shadow/assign.ts +268 -0
- package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +124 -0
- package/src/plugins/defaults/memory-v3-shadow/core.ts +26 -0
- package/src/plugins/defaults/memory-v3-shadow/data/README.md +84 -0
- package/src/plugins/defaults/memory-v3-shadow/data/assignments.json +5 -0
- package/src/plugins/defaults/memory-v3-shadow/data/core.json +1 -0
- package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-a/topic-x.md +9 -0
- package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-a/topic-y.md +9 -0
- package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-b/topic-z.md +9 -0
- package/src/plugins/defaults/memory-v3-shadow/health.ts +0 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
- package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +314 -0
- package/src/plugins/defaults/memory-v3-shadow/needle.ts +115 -0
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +126 -0
- package/src/plugins/defaults/memory-v3-shadow/package.json +15 -0
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +34 -0
- package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
- package/src/plugins/defaults/memory-v3-shadow/reconcile.ts +523 -0
- package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
- package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +32 -0
- package/src/plugins/defaults/memory-v3-shadow/router.ts +190 -0
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +84 -0
- package/src/plugins/defaults/memory-v3-shadow/selector.ts +226 -0
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +349 -0
- package/src/plugins/defaults/memory-v3-shadow/snapshot.ts +209 -0
- package/src/plugins/defaults/memory-v3-shadow/tree.ts +174 -0
- package/src/plugins/defaults/memory-v3-shadow/types.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/working-set.ts +88 -0
- package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/title-generate/package.json +15 -0
- package/src/plugins/defaults/title-generate/register.ts +35 -0
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
- package/src/plugins/defaults/tool-error/package.json +15 -0
- package/src/plugins/defaults/tool-error/register.ts +23 -0
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
- package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +24 -0
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +132 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/pipeline.ts +8 -35
- package/src/plugins/registry.ts +8 -25
- package/src/plugins/types.ts +62 -721
- package/src/plugins/user-loader.ts +4 -3
- package/src/proactive-artifact/aux-message-injector.ts +4 -5
- package/src/proactive-artifact/job.test.ts +28 -21
- package/src/proactive-artifact/job.ts +3 -1
- package/src/prompts/__tests__/system-prompt.test.ts +42 -0
- package/src/prompts/sections.ts +20 -7
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
- package/src/prompts/templates/BOOTSTRAP.md +7 -3
- package/src/prompts/templates/system-sections.ts +21 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -25
- package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
- package/src/providers/anthropic/client.ts +61 -34
- package/src/providers/call-site-routing.ts +1 -9
- package/src/providers/gemini/client.ts +152 -34
- package/src/providers/gemini/inline-media.ts +74 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -2
- package/src/providers/openai/chat-completions-provider.ts +45 -4
- package/src/providers/openai/responses-provider.ts +1 -4
- package/src/providers/openrouter/client.ts +2 -6
- package/src/providers/placeholder-sentinels.ts +35 -0
- package/src/providers/provider-send-message.ts +6 -6
- package/src/providers/ratelimit.ts +1 -9
- package/src/providers/retry.ts +0 -5
- package/src/providers/types.ts +11 -2
- package/src/providers/usage-tracking.ts +1 -9
- package/src/runtime/__tests__/agent-wake.test.ts +141 -32
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +95 -23
- package/src/runtime/assistant-event-hub.ts +38 -8
- package/src/runtime/assistant-stream-state.ts +368 -0
- package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
- package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
- package/src/runtime/auth/route-policy.ts +42 -1079
- package/src/runtime/background-job-runner.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -1
- package/src/runtime/channel-approvals.ts +4 -15
- package/src/runtime/channel-invite-transport.ts +5 -6
- package/src/runtime/channel-readiness-service.ts +2 -5
- package/src/runtime/channel-retry-sweep.ts +12 -16
- package/src/runtime/http-router.ts +35 -43
- package/src/runtime/http-types.ts +23 -71
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/invite-instruction-generator.ts +3 -3
- package/src/runtime/pending-interactions.ts +3 -2
- package/src/runtime/routes/__tests__/acp-routes.test.ts +253 -55
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
- package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +9 -5
- package/src/runtime/routes/acp-routes.test.ts +186 -100
- package/src/runtime/routes/acp-routes.ts +110 -35
- package/src/runtime/routes/app-management-routes.ts +93 -131
- package/src/runtime/routes/app-routes.ts +38 -20
- package/src/runtime/routes/approval-routes.ts +17 -5
- package/src/runtime/routes/attachment-routes.ts +51 -16
- package/src/runtime/routes/audio-routes.ts +1 -0
- package/src/runtime/routes/audit-routes.ts +5 -0
- package/src/runtime/routes/auth-routes.ts +5 -0
- package/src/runtime/routes/avatar-routes.ts +264 -59
- package/src/runtime/routes/background-tool-routes.ts +9 -0
- package/src/runtime/routes/background-wake-routes.ts +13 -3
- package/src/runtime/routes/backup-routes.ts +45 -0
- package/src/runtime/routes/bookmark-routes.ts +13 -0
- package/src/runtime/routes/brain-graph-routes.ts +9 -0
- package/src/runtime/routes/browser-routes.ts +6 -1
- package/src/runtime/routes/browser-tabs-routes.ts +11 -10
- package/src/runtime/routes/btw-routes.ts +34 -24
- package/src/runtime/routes/cache-routes.ts +13 -0
- package/src/runtime/routes/call-routes.ts +21 -10
- package/src/runtime/routes/channel-availability-routes.ts +5 -1
- package/src/runtime/routes/channel-readiness-routes.ts +37 -4
- package/src/runtime/routes/channel-route-definitions.ts +21 -0
- package/src/runtime/routes/channel-verification-routes.ts +21 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
- package/src/runtime/routes/client-routes.ts +9 -0
- package/src/runtime/routes/consolidation-routes.ts +133 -25
- package/src/runtime/routes/contact-prompt-routes.ts +9 -0
- package/src/runtime/routes/contact-routes.ts +90 -23
- package/src/runtime/routes/content-source-routes.ts +5 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
- package/src/runtime/routes/conversation-attention-routes.ts +5 -0
- package/src/runtime/routes/conversation-cli-routes.ts +54 -7
- package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
- package/src/runtime/routes/conversation-list-routes.ts +81 -12
- package/src/runtime/routes/conversation-management-routes.ts +57 -14
- package/src/runtime/routes/conversation-query-routes.ts +90 -41
- package/src/runtime/routes/conversation-routes.ts +446 -204
- package/src/runtime/routes/conversation-starter-routes.ts +35 -20
- package/src/runtime/routes/conversations-import-routes.ts +30 -8
- package/src/runtime/routes/credential-prompt-routes.ts +5 -0
- package/src/runtime/routes/credential-routes.ts +25 -6
- package/src/runtime/routes/debug-bash-routes.ts +5 -0
- package/src/runtime/routes/debug-routes.ts +11 -2
- package/src/runtime/routes/defer-routes.ts +13 -0
- package/src/runtime/routes/diagnostics-routes.ts +37 -46
- package/src/runtime/routes/disk-pressure-routes.ts +17 -31
- package/src/runtime/routes/document-comments-routes.ts +46 -27
- package/src/runtime/routes/documents-routes.ts +25 -10
- package/src/runtime/routes/domain-routes.ts +98 -51
- package/src/runtime/routes/email-routes.ts +33 -0
- package/src/runtime/routes/epoch-millis-range.ts +34 -0
- package/src/runtime/routes/events-routes.ts +107 -8
- package/src/runtime/routes/filing-routes.ts +9 -4
- package/src/runtime/routes/gateway-log-routes.ts +31 -4
- package/src/runtime/routes/global-search-routes.ts +53 -50
- package/src/runtime/routes/group-routes.ts +21 -5
- package/src/runtime/routes/guardian-action-routes.ts +9 -0
- package/src/runtime/routes/guardian-approval-interception.ts +0 -31
- package/src/runtime/routes/heartbeat-routes.ts +57 -21
- package/src/runtime/routes/home-feed-routes.ts +23 -19
- package/src/runtime/routes/home-state-routes.ts +8 -40
- package/src/runtime/routes/host-app-control-routes.ts +6 -1
- package/src/runtime/routes/host-bash-routes.ts +5 -0
- package/src/runtime/routes/host-browser-routes.ts +13 -0
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +26 -6
- package/src/runtime/routes/host-transfer-routes.ts +13 -2
- package/src/runtime/routes/http-adapter.ts +1 -2
- package/src/runtime/routes/identity-intro-cache.ts +28 -40
- package/src/runtime/routes/identity-routes.ts +236 -20
- package/src/runtime/routes/image-generation-routes.ts +45 -2
- package/src/runtime/routes/inbound-message-handler.ts +16 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
- package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
- package/src/runtime/routes/inference-send-routes.ts +11 -11
- package/src/runtime/routes/integrations/a2a.ts +32 -7
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
- package/src/runtime/routes/integrations/slack/channel.ts +23 -3
- package/src/runtime/routes/integrations/slack/share.ts +36 -8
- package/src/runtime/routes/integrations/telegram.ts +34 -9
- package/src/runtime/routes/integrations/twilio.ts +77 -7
- package/src/runtime/routes/integrations/vercel.ts +3 -3
- package/src/runtime/routes/internal-oauth-routes.ts +5 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
- package/src/runtime/routes/internal-twilio-routes.ts +13 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
- package/src/runtime/routes/log-export-routes.ts +36 -10
- package/src/runtime/routes/mcp-auth-routes.ts +25 -0
- package/src/runtime/routes/memory-item-routes.ts +21 -10
- package/src/runtime/routes/memory-v2-routes.ts +105 -44
- package/src/runtime/routes/memory-v3-routes.ts +306 -408
- package/src/runtime/routes/migration-rollback-routes.ts +5 -1
- package/src/runtime/routes/migration-routes.ts +29 -0
- package/src/runtime/routes/notification-routes.ts +17 -1
- package/src/runtime/routes/oauth-apps.ts +99 -23
- package/src/runtime/routes/oauth-commands-routes.ts +37 -14
- package/src/runtime/routes/oauth-connect-routes.ts +9 -0
- package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
- package/src/runtime/routes/oauth-providers.ts +79 -15
- package/src/runtime/routes/platform-routes.ts +102 -5
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +9 -6
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
- package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
- package/src/runtime/routes/playground/force-compact.ts +2 -2
- package/src/runtime/routes/playground/helpers.ts +1 -2
- package/src/runtime/routes/playground/inject-failures.ts +13 -8
- package/src/runtime/routes/playground/reset-circuit.ts +14 -9
- package/src/runtime/routes/playground/seed-conversation.ts +1 -1
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
- package/src/runtime/routes/playground/state.ts +4 -3
- package/src/runtime/routes/plugins-routes.ts +22 -19
- package/src/runtime/routes/profiler-routes.ts +17 -4
- package/src/runtime/routes/ps-routes.ts +5 -0
- package/src/runtime/routes/publish-routes.ts +13 -3
- package/src/runtime/routes/question-routes.ts +5 -0
- package/src/runtime/routes/recording-routes.ts +25 -12
- package/src/runtime/routes/rename-conversation-routes.ts +10 -0
- package/src/runtime/routes/sanity-routes.ts +9 -2
- package/src/runtime/routes/schedule-routes.ts +288 -88
- package/src/runtime/routes/secret-routes.ts +31 -6
- package/src/runtime/routes/sequence-routes.ts +33 -0
- package/src/runtime/routes/settings-routes.ts +65 -19
- package/src/runtime/routes/skills-routes.ts +166 -73
- package/src/runtime/routes/slack-channel-routes.ts +5 -0
- package/src/runtime/routes/stt-routes.ts +13 -6
- package/src/runtime/routes/subagents-routes.ts +24 -18
- package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
- package/src/runtime/routes/surface-action-routes.ts +9 -0
- package/src/runtime/routes/surface-content-routes.ts +10 -2
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/task-routes.ts +37 -0
- package/src/runtime/routes/telemetry-routes.ts +9 -0
- package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
- package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
- package/src/runtime/routes/trace-event-routes.ts +42 -1
- package/src/runtime/routes/trust-rules-routes.ts +31 -2
- package/src/runtime/routes/tts-routes.ts +48 -6
- package/src/runtime/routes/types.ts +83 -16
- package/src/runtime/routes/ui-request-routes.ts +5 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
- package/src/runtime/routes/usage-routes.ts +118 -42
- package/src/runtime/routes/user-routes-cli.ts +9 -0
- package/src/runtime/routes/user-routes.ts +5 -1
- package/src/runtime/routes/wake-conversation-routes.ts +5 -0
- package/src/runtime/routes/watcher-routes.ts +21 -0
- package/src/runtime/routes/webhook-routes.ts +50 -2
- package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
- package/src/runtime/routes/work-items-routes.ts +49 -23
- package/src/runtime/routes/workspace-commit-routes.ts +5 -0
- package/src/runtime/routes/workspace-routes.test.ts +42 -0
- package/src/runtime/routes/workspace-routes.ts +124 -9
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +8 -4
- package/src/runtime/services/analyze-conversation.ts +5 -8
- package/src/runtime/services/conversation-serializer.ts +24 -2
- package/src/runtime/sync/resource-sync-events.ts +16 -2
- package/src/runtime/sync/sync-publisher.ts +2 -2
- package/src/schedule/run-script.ts +28 -3
- package/src/schedule/schedule-store.ts +28 -1
- package/src/schedule/schedule-usage-store.ts +83 -0
- package/src/schedule/scheduler.ts +15 -6
- package/src/signals/cancel.ts +2 -4
- package/src/signals/user-message.ts +5 -8
- package/src/skills/catalog-files.ts +4 -1
- package/src/skills/catalog-install.ts +3 -0
- package/src/skills/categories-cache.ts +118 -0
- package/src/skills/clawhub-files.ts +1 -0
- package/src/skills/skillssh-files.ts +1 -0
- package/src/subagent/manager.ts +20 -11
- package/src/telemetry/types.ts +55 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +250 -4
- package/src/telemetry/usage-telemetry-reporter.ts +88 -2
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +7 -1
- package/src/tools/acp/spawn.test.ts +198 -93
- package/src/tools/acp/spawn.ts +32 -70
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/definitions.ts +8 -4
- package/src/tools/apps/executors.ts +13 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
- package/src/tools/ask-question/ask-question-tool.ts +85 -90
- package/src/tools/computer-use/definitions.ts +28 -24
- package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
- package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
- package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
- package/src/tools/credentials/vault.ts +112 -111
- package/src/tools/execution-target.ts +1 -1
- package/src/tools/execution-timeout.ts +3 -4
- package/src/tools/executor.ts +1 -53
- package/src/tools/filesystem/edit.ts +45 -42
- package/src/tools/filesystem/list.ts +33 -30
- package/src/tools/filesystem/read.ts +54 -35
- package/src/tools/filesystem/write.ts +69 -32
- package/src/tools/host-filesystem/edit.ts +44 -42
- package/src/tools/host-filesystem/read.ts +49 -35
- package/src/tools/host-filesystem/transfer.ts +121 -108
- package/src/tools/host-filesystem/write.ts +33 -31
- package/src/tools/host-terminal/host-shell.ts +50 -48
- package/src/tools/memory/register.ts +23 -24
- package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
- package/src/tools/network/__tests__/web-search.test.ts +11 -3
- package/src/tools/network/web-fetch.ts +49 -46
- package/src/tools/network/web-search-error.test.ts +248 -0
- package/src/tools/network/web-search-error.ts +267 -0
- package/src/tools/network/web-search.ts +223 -61
- package/src/tools/registry.ts +39 -16
- package/src/tools/schedule/create.ts +13 -0
- package/src/tools/schedule/update.ts +16 -0
- package/src/tools/shared/filesystem/audio-read.ts +122 -0
- package/src/tools/shared/filesystem/image-read.ts +1 -1
- package/src/tools/skills/execute.ts +34 -31
- package/src/tools/skills/load.ts +29 -23
- package/src/tools/subagent/notify-parent.ts +35 -32
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/system/avatar-generator.ts +13 -22
- package/src/tools/system/request-permission.ts +30 -27
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/terminal/shell.ts +190 -61
- package/src/tools/tool-defaults.ts +20 -9
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +74 -23
- package/src/tools/ui-surface/definitions.ts +99 -10
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
- package/src/tts/provider-catalog.ts +76 -1
- package/src/usage/types.ts +10 -0
- package/src/util/errors.ts +2 -2
- package/src/util/map-limit.ts +27 -0
- package/src/util/mutex.ts +47 -0
- package/src/util/platform.ts +15 -12
- package/src/work-items/work-item-runner.ts +7 -2
- package/src/workspace/git-service.ts +1 -42
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
- package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
- package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
- package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
- package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
- package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
- package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
- package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/src/workspace/provider-commit-message-generator.ts +15 -17
- package/tsconfig.json +4 -1
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
- package/src/__tests__/compaction-pipeline.test.ts +0 -210
- package/src/__tests__/compaction-timeout-recovery.test.ts +0 -262
- package/src/__tests__/empty-response-pipeline.test.ts +0 -301
- package/src/__tests__/history-repair-pipeline.test.ts +0 -396
- package/src/__tests__/llm-call-pipeline.test.ts +0 -281
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
- package/src/__tests__/persistence-pipeline.test.ts +0 -514
- package/src/__tests__/title-generate-pipeline.test.ts +0 -211
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -481
- package/src/__tests__/tool-error-pipeline.test.ts +0 -241
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -344
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
- package/src/cli/commands/memory-v3-render.ts +0 -491
- package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
- package/src/daemon/message-types/disk-pressure.ts +0 -9
- package/src/email/feature-gate.ts +0 -23
- package/src/gallery/default-gallery.ts +0 -1359
- package/src/gallery/gallery-manifest.ts +0 -28
- package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
- package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
- package/src/memory/v3/__tests__/edges.test.ts +0 -706
- package/src/memory/v3/__tests__/filter.test.ts +0 -560
- package/src/memory/v3/__tests__/gate.test.ts +0 -637
- package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
- package/src/memory/v3/__tests__/loop.test.ts +0 -775
- package/src/memory/v3/__tests__/retriever.test.ts +0 -226
- package/src/memory/v3/__tests__/scouts.test.ts +0 -489
- package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
- package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
- package/src/memory/v3/__tests__/traversal.test.ts +0 -508
- package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
- package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
- package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
- package/src/memory/v3/__tests__/validate.test.ts +0 -277
- package/src/memory/v3/auto-edges.ts +0 -223
- package/src/memory/v3/coactivation-store.ts +0 -124
- package/src/memory/v3/consolidation-job.ts +0 -323
- package/src/memory/v3/coretrieval-seed.ts +0 -240
- package/src/memory/v3/edge-learning-job.ts +0 -160
- package/src/memory/v3/edges.ts +0 -286
- package/src/memory/v3/filter.ts +0 -286
- package/src/memory/v3/gate.ts +0 -349
- package/src/memory/v3/index-composition.ts +0 -126
- package/src/memory/v3/llm-capture.ts +0 -46
- package/src/memory/v3/loop.ts +0 -430
- package/src/memory/v3/maintenance.ts +0 -144
- package/src/memory/v3/prompt-context.ts +0 -33
- package/src/memory/v3/prompts/consolidation.ts +0 -458
- package/src/memory/v3/prompts/system-prompts.ts +0 -196
- package/src/memory/v3/retriever.ts +0 -33
- package/src/memory/v3/scouts.ts +0 -431
- package/src/memory/v3/shadow-diff.ts +0 -287
- package/src/memory/v3/shadow-middleware.ts +0 -347
- package/src/memory/v3/traversal.ts +0 -211
- package/src/memory/v3/tree-index.ts +0 -237
- package/src/memory/v3/tree-store.ts +0 -394
- package/src/memory/v3/tree-walk.ts +0 -356
- package/src/memory/v3/types.ts +0 -65
- package/src/memory/v3/validate.ts +0 -323
- package/src/plugins/defaults/circuit-breaker.ts +0 -141
- package/src/plugins/defaults/compaction.ts +0 -141
- package/src/plugins/defaults/empty-response.ts +0 -124
- package/src/plugins/defaults/history-repair.ts +0 -83
- package/src/plugins/defaults/llm-call.ts +0 -77
- package/src/plugins/defaults/memory-retrieval.ts +0 -219
- package/src/plugins/defaults/overflow-reduce.ts +0 -185
- package/src/plugins/defaults/persistence.ts +0 -146
- package/src/plugins/defaults/title-generate.ts +0 -90
- package/src/plugins/defaults/token-estimate.ts +0 -101
- package/src/plugins/defaults/tool-error.ts +0 -119
- package/src/plugins/defaults/tool-execute.ts +0 -87
- package/src/plugins/defaults/tool-result-truncate.ts +0 -84
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
- package/src/skills/category-inference.ts +0 -111
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
|
|
8
|
-
import { inArray } from "drizzle-orm";
|
|
8
|
+
import { eq, inArray } from "drizzle-orm";
|
|
9
9
|
|
|
10
|
-
import { findConversation } from "../daemon/conversation-
|
|
10
|
+
import { findConversation } from "../daemon/conversation-registry.js";
|
|
11
11
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
12
12
|
import type { AcpSessionUpdate } from "../daemon/message-types/acp.js";
|
|
13
13
|
import { getDb } from "../memory/db-connection.js";
|
|
@@ -16,10 +16,39 @@ import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
|
16
16
|
import { getLogger } from "../util/logger.js";
|
|
17
17
|
import { AcpAgentProcess } from "./agent-process.js";
|
|
18
18
|
import { VellumAcpClientHandler } from "./client-handler.js";
|
|
19
|
+
import { prepareAgentEnv } from "./prepare-agent-env.js";
|
|
20
|
+
import { formatResolveFailure, resolveAcpAgent } from "./resolve-agent.js";
|
|
21
|
+
import { claudeResumeHint } from "./resume-hint.js";
|
|
19
22
|
import type { AcpAgentConfig, AcpSessionState } from "./types.js";
|
|
20
23
|
|
|
21
24
|
const log = getLogger("acp:session-manager");
|
|
22
25
|
|
|
26
|
+
/**
|
|
27
|
+
* The manager's "unknown session id" error. Thrown whenever an operation
|
|
28
|
+
* references an acpSessionId with no in-memory entry (and, for resume, no
|
|
29
|
+
* persisted history row). Callers (acp_steer tool, /v1/acp/:id/steer route)
|
|
30
|
+
* use `instanceof` checks to map this to their transport's not-found shape.
|
|
31
|
+
*/
|
|
32
|
+
export class AcpSessionNotFoundError extends Error {
|
|
33
|
+
constructor(public readonly acpSessionId: string) {
|
|
34
|
+
super(`ACP session "${acpSessionId}" not found`);
|
|
35
|
+
this.name = "AcpSessionNotFoundError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Wraps failures from the resume-then-steer phase of `steerOrResume` so
|
|
41
|
+
* transport callers can distinguish them (HTTP 424 with the actionable
|
|
42
|
+
* resume hint) from plain steer failures (404). The message mirrors the
|
|
43
|
+
* underlying error's message; the original error rides on `cause`.
|
|
44
|
+
*/
|
|
45
|
+
export class AcpResumeError extends Error {
|
|
46
|
+
constructor(cause: unknown) {
|
|
47
|
+
super(cause instanceof Error ? cause.message : String(cause), { cause });
|
|
48
|
+
this.name = "AcpResumeError";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
23
52
|
/** Maximum number of update events kept in a session's ring buffer. */
|
|
24
53
|
const MAX_BUFFER_EVENTS = 200;
|
|
25
54
|
/** Maximum aggregate JSON size of a session's ring buffer, in bytes. */
|
|
@@ -46,6 +75,15 @@ interface SessionEntry {
|
|
|
46
75
|
command: string;
|
|
47
76
|
}
|
|
48
77
|
|
|
78
|
+
/**
|
|
79
|
+
* An `acp_session_history` row that passed resumeFromHistory's validation
|
|
80
|
+
* guards: `cwd` (nullable in the schema for pre-resume-support rows) is
|
|
81
|
+
* guaranteed present.
|
|
82
|
+
*/
|
|
83
|
+
type ResumableHistoryRow = typeof acpSessionHistory.$inferSelect & {
|
|
84
|
+
cwd: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
49
87
|
export class AcpSessionManager {
|
|
50
88
|
private sessions = new Map<string, SessionEntry>();
|
|
51
89
|
/**
|
|
@@ -55,6 +93,25 @@ export class AcpSessionManager {
|
|
|
55
93
|
* `acp_session_history` on terminal transition, then cleared.
|
|
56
94
|
*/
|
|
57
95
|
private eventBuffers = new Map<string, BufferedAcpUpdate[]>();
|
|
96
|
+
/**
|
|
97
|
+
* In-flight resumes by session id, keyed to the promise of the resume's
|
|
98
|
+
* async body. Reserved SYNCHRONOUSLY before the first await so concurrent
|
|
99
|
+
* resumes of the same id cannot both pass the guards (the loser would
|
|
100
|
+
* overwrite the winner's map entry and leak its child process), and so N
|
|
101
|
+
* concurrent resumes of distinct ids cannot exceed maxConcurrent. The
|
|
102
|
+
* entry lives until the resume settles so `steerOrResume` can await a
|
|
103
|
+
* concurrent caller's resume instead of failing the already-active guard.
|
|
104
|
+
* The spawn path needs no such reservation: its check-then-register is
|
|
105
|
+
* synchronous.
|
|
106
|
+
*/
|
|
107
|
+
private pendingResumes = new Map<string, Promise<void>>();
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Set by dispose() (the daemon-shutdown path). Resumes that are mid-await
|
|
111
|
+
* when the manager is disposed re-check this flag before spawning a child
|
|
112
|
+
* process nothing would ever kill.
|
|
113
|
+
*/
|
|
114
|
+
private disposed = false;
|
|
58
115
|
|
|
59
116
|
constructor(private readonly maxConcurrent: number) {
|
|
60
117
|
this.cleanupStaleRunningRows();
|
|
@@ -91,6 +148,33 @@ export class AcpSessionManager {
|
|
|
91
148
|
}
|
|
92
149
|
}
|
|
93
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Ids that must be treated as live: registered sessions plus in-flight
|
|
153
|
+
* resume reservations (deduped, since a resuming session appears in both maps
|
|
154
|
+
* between registration and settle). Delete guards use this so a history
|
|
155
|
+
* row cannot be removed out from under a resume that is still awaiting
|
|
156
|
+
* env preparation; the later terminal upsert would resurrect it.
|
|
157
|
+
*/
|
|
158
|
+
getActiveAndPendingIds(): string[] {
|
|
159
|
+
return [
|
|
160
|
+
...new Set([...this.sessions.keys(), ...this.pendingResumes.keys()]),
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Concurrency guard shared by spawn() and resumeFromHistory(). Counts
|
|
166
|
+
* both registered sessions and in-flight resume reservations so the cap
|
|
167
|
+
* holds even while a resume is still awaiting prepareAgentEnv.
|
|
168
|
+
*/
|
|
169
|
+
private assertCapacity(): void {
|
|
170
|
+
if (this.getActiveAndPendingIds().length >= this.maxConcurrent) {
|
|
171
|
+
throw new Error(
|
|
172
|
+
`ACP concurrency limit reached (max ${this.maxConcurrent}). ` +
|
|
173
|
+
`Close an existing session before spawning a new one.`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
94
178
|
/**
|
|
95
179
|
* Spawns a new ACP agent session. Returns the generated acpSessionId.
|
|
96
180
|
*
|
|
@@ -105,12 +189,7 @@ export class AcpSessionManager {
|
|
|
105
189
|
parentConversationId: string,
|
|
106
190
|
sendToVellum: (msg: ServerMessage) => void,
|
|
107
191
|
): Promise<{ acpSessionId: string; protocolSessionId: string }> {
|
|
108
|
-
|
|
109
|
-
throw new Error(
|
|
110
|
-
`ACP concurrency limit reached (max ${this.maxConcurrent}). ` +
|
|
111
|
-
`Close an existing session before spawning a new one.`,
|
|
112
|
-
);
|
|
113
|
-
}
|
|
192
|
+
this.assertCapacity();
|
|
114
193
|
|
|
115
194
|
const acpSessionId = randomUUID();
|
|
116
195
|
log.info(
|
|
@@ -124,40 +203,103 @@ export class AcpSessionManager {
|
|
|
124
203
|
"ACP spawn requested",
|
|
125
204
|
);
|
|
126
205
|
|
|
206
|
+
const entry = this.registerSession({
|
|
207
|
+
acpSessionId,
|
|
208
|
+
agentId,
|
|
209
|
+
agentConfig,
|
|
210
|
+
parentConversationId,
|
|
211
|
+
cwd,
|
|
212
|
+
startedAt: Date.now(),
|
|
213
|
+
sendToVellum,
|
|
214
|
+
});
|
|
215
|
+
const { process: agentProcess, state } = entry;
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
log.info({ acpSessionId, agentId }, "ACP spawning child process");
|
|
219
|
+
agentProcess.spawn(cwd);
|
|
220
|
+
log.info(
|
|
221
|
+
{ acpSessionId, agentId },
|
|
222
|
+
"ACP initializing protocol connection",
|
|
223
|
+
);
|
|
224
|
+
await agentProcess.initialize();
|
|
225
|
+
log.info({ acpSessionId, agentId }, "ACP creating session");
|
|
226
|
+
const acpProtocolSessionId = await agentProcess.createSession(cwd);
|
|
227
|
+
state.acpSessionId = acpProtocolSessionId;
|
|
228
|
+
state.status = "running";
|
|
229
|
+
log.info(
|
|
230
|
+
{ acpSessionId, agentId, acpProtocolSessionId },
|
|
231
|
+
"ACP session running",
|
|
232
|
+
);
|
|
233
|
+
} catch (err) {
|
|
234
|
+
log.error({ acpSessionId, agentId, err }, "ACP spawn failed");
|
|
235
|
+
// No prompt has fired yet, so no permissions can be pending.
|
|
236
|
+
this.teardownSession(acpSessionId, entry);
|
|
237
|
+
throw err;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
this.sendSpawnedEvent(acpSessionId, entry);
|
|
241
|
+
|
|
242
|
+
// Fire prompt in the background — don't await
|
|
243
|
+
entry.currentPrompt = this.firePromptInBackground(
|
|
244
|
+
acpSessionId,
|
|
245
|
+
entry,
|
|
246
|
+
state.acpSessionId,
|
|
247
|
+
task,
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
return { acpSessionId, protocolSessionId: state.acpSessionId };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Wires up the in-memory plumbing shared by spawn() and
|
|
255
|
+
* resumeFromHistory(): the per-session ring buffer, the buffer-mirroring
|
|
256
|
+
* sender, the client handler, the agent process, and the SessionEntry.
|
|
257
|
+
* Registers the entry in the session map (reserving a concurrency slot
|
|
258
|
+
* before any async work) and returns it. Does NOT start the process.
|
|
259
|
+
*/
|
|
260
|
+
private registerSession(opts: {
|
|
261
|
+
acpSessionId: string;
|
|
262
|
+
agentId: string;
|
|
263
|
+
agentConfig: AcpAgentConfig;
|
|
264
|
+
parentConversationId: string;
|
|
265
|
+
cwd: string;
|
|
266
|
+
startedAt: number;
|
|
267
|
+
sendToVellum: (msg: ServerMessage) => void;
|
|
268
|
+
}): SessionEntry {
|
|
269
|
+
const { acpSessionId } = opts;
|
|
270
|
+
|
|
127
271
|
// Initialize the per-session ring buffer before any update can fire.
|
|
128
272
|
this.eventBuffers.set(acpSessionId, []);
|
|
129
273
|
|
|
130
274
|
// Wrap the sender so every emitted message is mirrored into the buffer
|
|
131
275
|
// when it's an `acp_session_update`. The wrapper preserves the original
|
|
132
|
-
// call semantics
|
|
276
|
+
// call semantics: it forwards every message unchanged.
|
|
133
277
|
const wrappedSend = (msg: ServerMessage) => {
|
|
134
278
|
if (msg.type === "acp_session_update") {
|
|
135
279
|
this.appendToBuffer(acpSessionId, msg);
|
|
136
280
|
}
|
|
137
|
-
sendToVellum(msg);
|
|
281
|
+
opts.sendToVellum(msg);
|
|
138
282
|
};
|
|
139
283
|
|
|
140
284
|
const clientHandler = new VellumAcpClientHandler(
|
|
141
285
|
acpSessionId,
|
|
142
286
|
wrappedSend,
|
|
143
|
-
parentConversationId,
|
|
287
|
+
opts.parentConversationId,
|
|
144
288
|
);
|
|
145
289
|
|
|
146
290
|
const agentProcess = new AcpAgentProcess(
|
|
147
|
-
agentId,
|
|
148
|
-
agentConfig,
|
|
291
|
+
opts.agentId,
|
|
292
|
+
opts.agentConfig,
|
|
149
293
|
(_agent) => clientHandler,
|
|
150
294
|
);
|
|
151
295
|
|
|
152
|
-
// Reserve a slot in the map before any async work to enforce the
|
|
153
|
-
// concurrency limit even when multiple spawn() calls race.
|
|
154
296
|
const state: AcpSessionState = {
|
|
155
297
|
id: acpSessionId,
|
|
156
|
-
agentId,
|
|
157
|
-
acpSessionId: "", // placeholder until createSession resolves
|
|
158
|
-
parentConversationId,
|
|
298
|
+
agentId: opts.agentId,
|
|
299
|
+
acpSessionId: "", // placeholder until createSession/resume resolves
|
|
300
|
+
parentConversationId: opts.parentConversationId,
|
|
159
301
|
status: "initializing",
|
|
160
|
-
startedAt:
|
|
302
|
+
startedAt: opts.startedAt,
|
|
161
303
|
};
|
|
162
304
|
|
|
163
305
|
const entry: SessionEntry = {
|
|
@@ -166,54 +308,208 @@ export class AcpSessionManager {
|
|
|
166
308
|
clientHandler,
|
|
167
309
|
sendToVellum: wrappedSend,
|
|
168
310
|
currentPrompt: null,
|
|
169
|
-
parentConversationId,
|
|
170
|
-
cwd,
|
|
171
|
-
command: agentConfig.command,
|
|
311
|
+
parentConversationId: opts.parentConversationId,
|
|
312
|
+
cwd: opts.cwd,
|
|
313
|
+
command: opts.agentConfig.command,
|
|
172
314
|
};
|
|
173
315
|
|
|
174
316
|
this.sessions.set(acpSessionId, entry);
|
|
317
|
+
return entry;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Notifies connected clients that a session is live. Shared by spawn()
|
|
322
|
+
* and the resume path (resumed sessions reuse the spawned event so
|
|
323
|
+
* clients render them; a dedicated acp_session_resumed event is a
|
|
324
|
+
* possible follow-up, not in scope here).
|
|
325
|
+
*/
|
|
326
|
+
private sendSpawnedEvent(acpSessionId: string, entry: SessionEntry): void {
|
|
327
|
+
entry.sendToVellum({
|
|
328
|
+
type: "acp_session_spawned",
|
|
329
|
+
acpSessionId,
|
|
330
|
+
agent: entry.state.agentId,
|
|
331
|
+
parentConversationId: entry.parentConversationId,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Resumes a terminal-state session from its persisted
|
|
337
|
+
* `acp_session_history` row, reattaching to the agent's stored
|
|
338
|
+
* conversation via ACP `session/resume` (preferred: no history replay) or
|
|
339
|
+
* `session/load` (replayed history is suppressed; see
|
|
340
|
+
* VellumAcpClientHandler.beginReplaySuppression).
|
|
341
|
+
*
|
|
342
|
+
* The resumed session reuses the original vellum session id,
|
|
343
|
+
* parentConversationId, and startedAt, and re-seeds its ring buffer from
|
|
344
|
+
* the persisted event log so the terminal upsert after the resumed run
|
|
345
|
+
* merges new events into the original row instead of losing them.
|
|
346
|
+
*
|
|
347
|
+
* Throws with an actionable message when the row is missing, was recorded
|
|
348
|
+
* before resume support (no cwd), the agent cannot be resolved, or the
|
|
349
|
+
* agent advertises neither resume capability.
|
|
350
|
+
*/
|
|
351
|
+
async resumeFromHistory(
|
|
352
|
+
acpSessionId: string,
|
|
353
|
+
sendToVellum: (msg: ServerMessage) => void,
|
|
354
|
+
): Promise<void> {
|
|
355
|
+
if (
|
|
356
|
+
this.sessions.has(acpSessionId) ||
|
|
357
|
+
this.pendingResumes.has(acpSessionId)
|
|
358
|
+
) {
|
|
359
|
+
throw new Error(`ACP session "${acpSessionId}" is already active`);
|
|
360
|
+
}
|
|
361
|
+
this.assertCapacity();
|
|
362
|
+
|
|
363
|
+
const row = getDb()
|
|
364
|
+
.select()
|
|
365
|
+
.from(acpSessionHistory)
|
|
366
|
+
.where(eq(acpSessionHistory.id, acpSessionId))
|
|
367
|
+
.get();
|
|
368
|
+
if (!row) {
|
|
369
|
+
throw new AcpSessionNotFoundError(acpSessionId);
|
|
370
|
+
}
|
|
371
|
+
if (!row.cwd) {
|
|
372
|
+
throw new Error(
|
|
373
|
+
`ACP session "${acpSessionId}" was recorded before resume support ` +
|
|
374
|
+
`(no working directory persisted) and cannot be resumed. ` +
|
|
375
|
+
`Spawn a new session instead.`,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
if (!row.acpSessionId) {
|
|
379
|
+
throw new Error(
|
|
380
|
+
`ACP session "${acpSessionId}" has no protocol session id ` +
|
|
381
|
+
`persisted and cannot be resumed. Spawn a new session instead.`,
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const resolved = resolveAcpAgent(row.agentId);
|
|
386
|
+
if (!resolved.ok) {
|
|
387
|
+
throw new Error(formatResolveFailure(row.agentId, resolved));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Everything up to here is synchronous. Reserve the id + concurrency
|
|
391
|
+
// slot BEFORE the first await so a concurrent resume of the same id
|
|
392
|
+
// (or a spawn racing the cap) fails the guards above instead of
|
|
393
|
+
// double-registering and leaking the first child process. The
|
|
394
|
+
// reservation holds the resume's promise until it settles so
|
|
395
|
+
// steerOrResume can await a concurrent caller's in-flight resume, and
|
|
396
|
+
// so the delete guards see the id as live while the row's terminal
|
|
397
|
+
// status still reflects the previous run.
|
|
398
|
+
const resumePromise = this.performResume(
|
|
399
|
+
acpSessionId,
|
|
400
|
+
row as ResumableHistoryRow,
|
|
401
|
+
resolved.agent,
|
|
402
|
+
sendToVellum,
|
|
403
|
+
);
|
|
404
|
+
this.pendingResumes.set(acpSessionId, resumePromise);
|
|
405
|
+
try {
|
|
406
|
+
await resumePromise;
|
|
407
|
+
} finally {
|
|
408
|
+
this.pendingResumes.delete(acpSessionId);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* The async body of resumeFromHistory, split out so the caller can store
|
|
414
|
+
* its promise in `pendingResumes` synchronously before the first await.
|
|
415
|
+
* All guards and row validation have already passed.
|
|
416
|
+
*/
|
|
417
|
+
private async performResume(
|
|
418
|
+
acpSessionId: string,
|
|
419
|
+
row: ResumableHistoryRow,
|
|
420
|
+
agent: AcpAgentConfig,
|
|
421
|
+
sendToVellum: (msg: ServerMessage) => void,
|
|
422
|
+
): Promise<void> {
|
|
423
|
+
const agentConfig = await prepareAgentEnv(agent);
|
|
424
|
+
|
|
425
|
+
// The daemon may have shut down while prepareAgentEnv was pending.
|
|
426
|
+
// Registering now would spawn a child process on a disposed manager
|
|
427
|
+
// that nothing would ever kill.
|
|
428
|
+
if (this.disposed) {
|
|
429
|
+
throw new Error(
|
|
430
|
+
`ACP session manager is disposed; cannot resume session "${acpSessionId}"`,
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const entry = this.registerSession({
|
|
435
|
+
acpSessionId,
|
|
436
|
+
agentId: row.agentId,
|
|
437
|
+
agentConfig,
|
|
438
|
+
parentConversationId: row.parentConversationId,
|
|
439
|
+
cwd: row.cwd,
|
|
440
|
+
startedAt: row.startedAt,
|
|
441
|
+
sendToVellum,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
log.info(
|
|
445
|
+
{ acpSessionId, agentId: row.agentId, cwd: row.cwd },
|
|
446
|
+
"ACP resume from history requested",
|
|
447
|
+
);
|
|
448
|
+
const { process: agentProcess, state } = entry;
|
|
449
|
+
|
|
450
|
+
// Re-seed the ring buffer from the persisted event log, routed through
|
|
451
|
+
// appendToBuffer so the count/byte caps still apply. The terminal
|
|
452
|
+
// upsert then persists the merged (old + new) log.
|
|
453
|
+
try {
|
|
454
|
+
const persisted = JSON.parse(row.eventLogJson) as unknown;
|
|
455
|
+
if (Array.isArray(persisted)) {
|
|
456
|
+
for (const update of persisted) {
|
|
457
|
+
this.appendToBuffer(acpSessionId, update as AcpSessionUpdate);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
} catch (err) {
|
|
461
|
+
log.warn(
|
|
462
|
+
{ acpSessionId, err },
|
|
463
|
+
"Failed to re-seed ACP event buffer from persisted history",
|
|
464
|
+
);
|
|
465
|
+
}
|
|
175
466
|
|
|
176
467
|
try {
|
|
177
|
-
log.info({ acpSessionId, agentId }, "ACP spawning child process");
|
|
178
|
-
agentProcess.spawn(cwd);
|
|
179
468
|
log.info(
|
|
180
|
-
{ acpSessionId, agentId },
|
|
181
|
-
"ACP
|
|
469
|
+
{ acpSessionId, agentId: row.agentId },
|
|
470
|
+
"ACP spawning child process for resume",
|
|
182
471
|
);
|
|
472
|
+
agentProcess.spawn(row.cwd);
|
|
183
473
|
await agentProcess.initialize();
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
474
|
+
if (agentProcess.supportsSessionResume) {
|
|
475
|
+
// session/resume reattaches without replaying history.
|
|
476
|
+
await agentProcess.resumeSession(row.acpSessionId, row.cwd);
|
|
477
|
+
} else if (agentProcess.supportsLoadSession) {
|
|
478
|
+
// session/load replays the full history as session/update
|
|
479
|
+
// notifications before resolving; suppress forwarding so the
|
|
480
|
+
// conversation and ring buffer don't receive duplicates.
|
|
481
|
+
entry.clientHandler.beginReplaySuppression();
|
|
482
|
+
try {
|
|
483
|
+
await agentProcess.loadSession(row.acpSessionId, row.cwd);
|
|
484
|
+
} finally {
|
|
485
|
+
entry.clientHandler.endReplaySuppression();
|
|
486
|
+
}
|
|
487
|
+
} else {
|
|
488
|
+
throw new Error(
|
|
489
|
+
`ACP agent "${row.agentId}" does not support session resume`,
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
state.acpSessionId = row.acpSessionId;
|
|
187
493
|
state.status = "running";
|
|
188
494
|
log.info(
|
|
189
|
-
{
|
|
190
|
-
|
|
495
|
+
{
|
|
496
|
+
acpSessionId,
|
|
497
|
+
agentId: row.agentId,
|
|
498
|
+
protocolSessionId: row.acpSessionId,
|
|
499
|
+
},
|
|
500
|
+
"ACP session resumed",
|
|
191
501
|
);
|
|
192
502
|
} catch (err) {
|
|
193
|
-
log.error(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
503
|
+
log.error(
|
|
504
|
+
{ acpSessionId, agentId: row.agentId, err },
|
|
505
|
+
"ACP resume failed",
|
|
506
|
+
);
|
|
507
|
+
// No prompt has fired yet, so no permissions can be pending.
|
|
508
|
+
this.teardownSession(acpSessionId, entry);
|
|
198
509
|
throw err;
|
|
199
510
|
}
|
|
200
511
|
|
|
201
|
-
|
|
202
|
-
type: "acp_session_spawned",
|
|
203
|
-
acpSessionId,
|
|
204
|
-
agent: agentId,
|
|
205
|
-
parentConversationId,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
// Fire prompt in the background — don't await
|
|
209
|
-
entry.currentPrompt = this.firePromptInBackground(
|
|
210
|
-
acpSessionId,
|
|
211
|
-
entry,
|
|
212
|
-
state.acpSessionId,
|
|
213
|
-
task,
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
return { acpSessionId, protocolSessionId: state.acpSessionId };
|
|
512
|
+
this.sendSpawnedEvent(acpSessionId, entry);
|
|
217
513
|
}
|
|
218
514
|
|
|
219
515
|
/**
|
|
@@ -225,7 +521,7 @@ export class AcpSessionManager {
|
|
|
225
521
|
async steer(acpSessionId: string, instruction: string): Promise<void> {
|
|
226
522
|
const entry = this.sessions.get(acpSessionId);
|
|
227
523
|
if (!entry) {
|
|
228
|
-
throw new
|
|
524
|
+
throw new AcpSessionNotFoundError(acpSessionId);
|
|
229
525
|
}
|
|
230
526
|
|
|
231
527
|
if (entry.state.status !== "running") {
|
|
@@ -258,22 +554,123 @@ export class AcpSessionManager {
|
|
|
258
554
|
);
|
|
259
555
|
}
|
|
260
556
|
|
|
557
|
+
/**
|
|
558
|
+
* Steers a session, transparently resuming it from persisted history
|
|
559
|
+
* first when it is no longer in memory (it completed, or the daemon
|
|
560
|
+
* restarted). The resume and the instruction prompt are atomic from the
|
|
561
|
+
* caller's perspective: a successfully resumed session immediately gets
|
|
562
|
+
* the instruction fired, so it never sits running-idle with no in-flight
|
|
563
|
+
* prompt (and therefore no teardown owner). If the post-resume steer
|
|
564
|
+
* fails, the freshly resumed session is closed (process killed, terminal
|
|
565
|
+
* row persisted, maps cleared) instead of being leaked.
|
|
566
|
+
*
|
|
567
|
+
* When a concurrent caller's resume of the same id is already in flight,
|
|
568
|
+
* this call awaits that resume and then retries the plain steer, so both
|
|
569
|
+
* callers' instructions land on the single resumed session.
|
|
570
|
+
*
|
|
571
|
+
* Error contract for transport callers (acp_steer tool, steer route):
|
|
572
|
+
* - `AcpSessionNotFoundError`: no in-memory session AND no history row.
|
|
573
|
+
* - `AcpResumeError`: the resume (own or a concurrent caller's awaited
|
|
574
|
+
* one, or the steer immediately after an own resume) failed; the
|
|
575
|
+
* message carries the actionable hint.
|
|
576
|
+
* - any other error: the plain steer on an in-memory session failed.
|
|
577
|
+
*/
|
|
578
|
+
async steerOrResume(
|
|
579
|
+
acpSessionId: string,
|
|
580
|
+
instruction: string,
|
|
581
|
+
sendToVellum: (msg: ServerMessage) => void,
|
|
582
|
+
): Promise<{ resumed: boolean }> {
|
|
583
|
+
try {
|
|
584
|
+
await this.steer(acpSessionId, instruction);
|
|
585
|
+
return { resumed: false };
|
|
586
|
+
} catch (err) {
|
|
587
|
+
// Fall through to the in-flight-resume handling both when the session
|
|
588
|
+
// is entirely unknown and when a concurrent resume has already
|
|
589
|
+
// registered its entry but is still initializing: steer rejects with a
|
|
590
|
+
// plain not-running error in that window, yet the resume reservation
|
|
591
|
+
// is live and the retry below will land once it settles.
|
|
592
|
+
if (
|
|
593
|
+
!(err instanceof AcpSessionNotFoundError) &&
|
|
594
|
+
!this.pendingResumes.has(acpSessionId)
|
|
595
|
+
) {
|
|
596
|
+
throw err;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Another caller's resume of this id may already be in flight (the
|
|
601
|
+
// session is not in memory yet, but its slot is reserved). Await that
|
|
602
|
+
// resume and retry the plain steer once instead of failing
|
|
603
|
+
// resumeFromHistory's already-active guard, which would surface a
|
|
604
|
+
// misleading resume error and drop this instruction.
|
|
605
|
+
const inFlightResume = this.pendingResumes.get(acpSessionId);
|
|
606
|
+
if (inFlightResume) {
|
|
607
|
+
try {
|
|
608
|
+
await inFlightResume;
|
|
609
|
+
} catch (err) {
|
|
610
|
+
throw new AcpResumeError(err);
|
|
611
|
+
}
|
|
612
|
+
// The resumed session is owned by the concurrent caller (its own
|
|
613
|
+
// post-resume steer handles teardown on failure), so a failure here
|
|
614
|
+
// propagates as a plain steer error without closing the session.
|
|
615
|
+
await this.steer(acpSessionId, instruction);
|
|
616
|
+
return { resumed: true };
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
try {
|
|
620
|
+
await this.resumeFromHistory(acpSessionId, sendToVellum);
|
|
621
|
+
} catch (err) {
|
|
622
|
+
// A missing history row keeps its not-found shape; everything else
|
|
623
|
+
// (legacy row without cwd, resolver failure, capability missing)
|
|
624
|
+
// is a resume failure with an actionable message.
|
|
625
|
+
if (err instanceof AcpSessionNotFoundError) throw err;
|
|
626
|
+
throw new AcpResumeError(err);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
try {
|
|
630
|
+
await this.steer(acpSessionId, instruction);
|
|
631
|
+
} catch (err) {
|
|
632
|
+
// Tear down the just-resumed session rather than leaving it
|
|
633
|
+
// running-idle with no prompt handler to own its cleanup.
|
|
634
|
+
try {
|
|
635
|
+
this.close(acpSessionId);
|
|
636
|
+
} catch (closeErr) {
|
|
637
|
+
log.warn(
|
|
638
|
+
{ acpSessionId, err: closeErr },
|
|
639
|
+
"Failed to close ACP session after post-resume steer failure",
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
throw new AcpResumeError(err);
|
|
643
|
+
}
|
|
644
|
+
return { resumed: true };
|
|
645
|
+
}
|
|
646
|
+
|
|
261
647
|
/**
|
|
262
648
|
* Cancels an ongoing prompt in the specified session.
|
|
263
649
|
*
|
|
264
|
-
*
|
|
265
|
-
* catch handler in `firePromptInBackground` performs the
|
|
266
|
-
* persistence + teardown
|
|
267
|
-
* preserves "cancelled" instead of overwriting with "failed".
|
|
650
|
+
* When a prompt is in flight, its `prompt()` call rejects in response
|
|
651
|
+
* and the catch handler in `firePromptInBackground` performs the
|
|
652
|
+
* terminal persistence + teardown; we just flip the status here so that
|
|
653
|
+
* handler preserves "cancelled" instead of overwriting with "failed".
|
|
654
|
+
*
|
|
655
|
+
* When NO prompt is in flight there is no handler to own cleanup, so
|
|
656
|
+
* cancel persists and tears down the session itself. (Sessions normally
|
|
657
|
+
* always have a prompt in flight, but a cancel can race the window in
|
|
658
|
+
* steer() between clearing the old prompt and firing the new one.)
|
|
268
659
|
*/
|
|
269
660
|
async cancel(acpSessionId: string): Promise<void> {
|
|
270
661
|
const entry = this.sessions.get(acpSessionId);
|
|
271
662
|
if (!entry) {
|
|
272
|
-
throw new
|
|
663
|
+
throw new AcpSessionNotFoundError(acpSessionId);
|
|
273
664
|
}
|
|
274
665
|
await entry.process.cancel(entry.state.acpSessionId);
|
|
275
666
|
entry.state.status = "cancelled";
|
|
276
667
|
entry.state.completedAt = Date.now();
|
|
668
|
+
// Re-check the map after the await: the in-flight prompt's handler may
|
|
669
|
+
// have already torn the session down while process.cancel was pending.
|
|
670
|
+
if (!entry.currentPrompt && this.sessions.get(acpSessionId) === entry) {
|
|
671
|
+
this.persistTerminal(acpSessionId, entry);
|
|
672
|
+
this.teardownSession(acpSessionId, entry);
|
|
673
|
+
}
|
|
277
674
|
}
|
|
278
675
|
|
|
279
676
|
/**
|
|
@@ -288,7 +685,7 @@ export class AcpSessionManager {
|
|
|
288
685
|
close(acpSessionId: string): void {
|
|
289
686
|
const entry = this.sessions.get(acpSessionId);
|
|
290
687
|
if (!entry) {
|
|
291
|
-
throw new
|
|
688
|
+
throw new AcpSessionNotFoundError(acpSessionId);
|
|
292
689
|
}
|
|
293
690
|
if (
|
|
294
691
|
entry.state.status === "running" ||
|
|
@@ -335,7 +732,7 @@ export class AcpSessionManager {
|
|
|
335
732
|
if (acpSessionId) {
|
|
336
733
|
const entry = this.sessions.get(acpSessionId);
|
|
337
734
|
if (!entry) {
|
|
338
|
-
throw new
|
|
735
|
+
throw new AcpSessionNotFoundError(acpSessionId);
|
|
339
736
|
}
|
|
340
737
|
return entry.state;
|
|
341
738
|
}
|
|
@@ -368,15 +765,18 @@ export class AcpSessionManager {
|
|
|
368
765
|
|
|
369
766
|
/**
|
|
370
767
|
* Persists the session's final state + buffered event log to
|
|
371
|
-
* `acp_session_history`, then frees the buffer entry.
|
|
372
|
-
*
|
|
373
|
-
*
|
|
768
|
+
* `acp_session_history`, then frees the buffer entry. Upserts on id:
|
|
769
|
+
* resumed runs reuse the original vellum session id, so their terminal
|
|
770
|
+
* write must update the existing row (status, event log, etc.) instead of
|
|
771
|
+
* being silently skipped. Best-effort: a DB failure is logged but does
|
|
772
|
+
* not propagate, since the session has already reached a terminal state
|
|
773
|
+
* and clients have been notified.
|
|
374
774
|
*/
|
|
375
775
|
private persistTerminal(acpSessionId: string, entry: SessionEntry): void {
|
|
376
776
|
const buffer = this.eventBuffers.get(acpSessionId) ?? [];
|
|
377
777
|
// Serialize only the wire-shaped updates — drop the byte-size accounting
|
|
378
778
|
// metadata so persisted rows match the protocol shape clients receive.
|
|
379
|
-
const
|
|
779
|
+
const eventLogJson = JSON.stringify(buffer.map((b) => b.update));
|
|
380
780
|
try {
|
|
381
781
|
getDb()
|
|
382
782
|
.insert(acpSessionHistory)
|
|
@@ -390,9 +790,20 @@ export class AcpSessionManager {
|
|
|
390
790
|
status: entry.state.status,
|
|
391
791
|
stopReason: entry.state.stopReason ?? null,
|
|
392
792
|
error: entry.state.error ?? null,
|
|
393
|
-
eventLogJson
|
|
793
|
+
eventLogJson,
|
|
794
|
+
cwd: entry.cwd,
|
|
795
|
+
})
|
|
796
|
+
.onConflictDoUpdate({
|
|
797
|
+
target: acpSessionHistory.id,
|
|
798
|
+
set: {
|
|
799
|
+
status: entry.state.status,
|
|
800
|
+
completedAt: entry.state.completedAt ?? null,
|
|
801
|
+
stopReason: entry.state.stopReason ?? null,
|
|
802
|
+
error: entry.state.error ?? null,
|
|
803
|
+
eventLogJson,
|
|
804
|
+
cwd: entry.cwd,
|
|
805
|
+
},
|
|
394
806
|
})
|
|
395
|
-
.onConflictDoNothing()
|
|
396
807
|
.run();
|
|
397
808
|
} catch (err) {
|
|
398
809
|
log.error(
|
|
@@ -451,10 +862,12 @@ export class AcpSessionManager {
|
|
|
451
862
|
const agentLabel = current.state.agentId;
|
|
452
863
|
const responseText = current.clientHandler.responseText;
|
|
453
864
|
const sessionId = current.state.acpSessionId;
|
|
454
|
-
const
|
|
455
|
-
current.command
|
|
456
|
-
|
|
457
|
-
|
|
865
|
+
const hint = claudeResumeHint(
|
|
866
|
+
current.command,
|
|
867
|
+
current.cwd,
|
|
868
|
+
sessionId,
|
|
869
|
+
);
|
|
870
|
+
const resumeHint = hint ? `\n\n${hint}` : "";
|
|
458
871
|
const notifyMessage = `[ACP agent "${agentLabel}" completed]\n\n${responseText}${resumeHint}`;
|
|
459
872
|
const parentConversation = findConversation(
|
|
460
873
|
current.parentConversationId,
|
|
@@ -517,9 +930,12 @@ export class AcpSessionManager {
|
|
|
517
930
|
}
|
|
518
931
|
|
|
519
932
|
/**
|
|
520
|
-
* Kills all processes on shutdown.
|
|
933
|
+
* Kills all processes on shutdown. Also flags the manager as disposed so
|
|
934
|
+
* resumes that are mid-await when shutdown happens abort before spawning
|
|
935
|
+
* a child process nothing would ever kill.
|
|
521
936
|
*/
|
|
522
937
|
dispose(): void {
|
|
938
|
+
this.disposed = true;
|
|
523
939
|
this.closeAll();
|
|
524
940
|
}
|
|
525
941
|
}
|