@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f
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/ARCHITECTURE.md +94 -91
- package/Dockerfile +5 -16
- package/README.md +7 -10
- package/bun.lock +0 -4
- package/docs/architecture/security.md +20 -20
- package/docs/stt-provider-onboarding.md +4 -5
- package/docs/trusted-contact-access.md +7 -7
- package/eslint-rules/cli-no-daemon-internals.js +4 -0
- package/eslint.config.mjs +7 -1
- package/knip.json +0 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
- package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
- package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
- package/openapi.yaml +1073 -225
- package/package.json +1 -4
- package/scripts/test.sh +35 -13
- package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
- package/src/__tests__/acp-session.test.ts +4 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
- package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
- package/src/__tests__/app-source-watcher.test.ts +11 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
- package/src/__tests__/assistant-attachments.test.ts +62 -4
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
- package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
- package/src/__tests__/attachments-store.test.ts +3 -0
- package/src/__tests__/background-shell-bash.test.ts +34 -0
- package/src/__tests__/background-shell-host-bash.test.ts +12 -0
- package/src/__tests__/background-tool-registry.test.ts +97 -0
- package/src/__tests__/background-tool-routes.test.ts +72 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/btw-routes.test.ts +57 -3
- package/src/__tests__/call-controller.test.ts +474 -84
- package/src/__tests__/call-domain.test.ts +48 -1
- package/src/__tests__/call-pointer-messages.test.ts +57 -19
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +15 -14
- package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
- package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
- package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
- package/src/__tests__/call-setup-flow.test.ts +311 -0
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -7
- package/src/__tests__/channel-readiness-service.test.ts +0 -6
- package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
- package/src/__tests__/channel-retry-sweep.test.ts +76 -64
- package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
- package/src/__tests__/clear-all-lexical.test.ts +90 -0
- package/src/__tests__/compactor-media-strip.test.ts +177 -0
- package/src/__tests__/config-loader-backfill.test.ts +5 -5
- package/src/__tests__/config-schema.test.ts +17 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
- package/src/__tests__/contacts-relay-reads.test.ts +188 -23
- package/src/__tests__/contacts-tools.test.ts +42 -1
- package/src/__tests__/contacts-write.test.ts +181 -0
- package/src/__tests__/context-search-conversations-source.test.ts +220 -81
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +39 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
- package/src/__tests__/conversation-clear-safety.test.ts +0 -1
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -0
- package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
- package/src/__tests__/conversation-error.test.ts +0 -18
- package/src/__tests__/conversation-fork-crud.test.ts +67 -0
- package/src/__tests__/conversation-history-web-search.test.ts +7 -137
- package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
- package/src/__tests__/conversation-process-callsite.test.ts +37 -0
- package/src/__tests__/conversation-queue.test.ts +149 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
- package/src/__tests__/conversation-skill-tools.test.ts +73 -0
- package/src/__tests__/conversation-wipe.test.ts +20 -5
- package/src/__tests__/credential-prompt-route.test.ts +69 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -3
- package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
- package/src/__tests__/edit-propagation.test.ts +56 -2
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
- package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
- package/src/__tests__/guardian-question-mode.test.ts +57 -0
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/guardian-wait-controller.test.ts +619 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
- package/src/__tests__/heic-fixture.ts +55 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
- package/src/__tests__/http-conversation-lineage.test.ts +6 -1
- package/src/__tests__/image-conversion.test.ts +170 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
- package/src/__tests__/introduction-card-resolver.test.ts +354 -0
- package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
- package/src/__tests__/invite-routes-http.test.ts +246 -420
- package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
- package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
- package/src/__tests__/list-messages-attachments.test.ts +159 -0
- package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
- package/src/__tests__/list-messages-queued.test.ts +25 -0
- package/src/__tests__/managed-store.test.ts +129 -1
- package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
- package/src/__tests__/media-stream-output.test.ts +350 -19
- package/src/__tests__/media-stream-server-integration.test.ts +943 -169
- package/src/__tests__/media-stream-stt-session.test.ts +498 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +19 -0
- package/src/__tests__/non-member-access-request.test.ts +349 -3
- package/src/__tests__/notification-decision-fallback.test.ts +104 -8
- package/src/__tests__/notification-decision-strategy.test.ts +57 -8
- package/src/__tests__/onboarding-template-contract.test.ts +27 -43
- package/src/__tests__/openai-provider.test.ts +33 -0
- package/src/__tests__/openai-responses-provider.test.ts +40 -0
- package/src/__tests__/persistence-layering-guard.test.ts +29 -20
- package/src/__tests__/persona-resolver.test.ts +56 -2
- package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
- package/src/__tests__/phone.test.ts +1 -15
- package/src/__tests__/plugin-bootstrap.test.ts +25 -196
- package/src/__tests__/plugin-disabled-state.test.ts +33 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
- package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
- package/src/__tests__/plugin-pipeline.test.ts +63 -1
- package/src/__tests__/plugin-route-contribution.test.ts +62 -115
- package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
- package/src/__tests__/plugin-types.test.ts +0 -1
- package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
- package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
- package/src/__tests__/public-ingress-urls.test.ts +0 -48
- package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
- package/src/__tests__/resolve-trust-class.test.ts +28 -10
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
- package/src/__tests__/schedule-retry.test.ts +38 -14
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
- package/src/__tests__/schedule-routes.test.ts +14 -6
- package/src/__tests__/schedule-store.test.ts +3 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
- package/src/__tests__/scheduler-recurrence.test.ts +57 -107
- package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
- package/src/__tests__/scheduler-wake.test.ts +13 -23
- package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/shell-observability.test.ts +1 -0
- package/src/__tests__/skill-boundary-guard.test.ts +3 -4
- package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
- package/src/__tests__/skill-script-runner-host.test.ts +53 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
- package/src/__tests__/skill-tool-factory.test.ts +73 -1
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
- package/src/__tests__/slack-inbound-verification.test.ts +36 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
- package/src/__tests__/stt-hints.test.ts +2 -256
- package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
- package/src/__tests__/subagent-persistence.test.ts +122 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +99 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
- package/src/__tests__/system-prompt.test.ts +17 -118
- package/src/__tests__/task-scheduler.test.ts +68 -89
- package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
- package/src/__tests__/telephony-tts-guard.test.ts +538 -0
- package/src/__tests__/title-generate-hook.test.ts +16 -0
- package/src/__tests__/tool-approval-handler.test.ts +87 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
- package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
- package/src/__tests__/trust-context-guards.test.ts +21 -10
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
- package/src/__tests__/twilio-provider.test.ts +17 -17
- package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
- package/src/__tests__/twilio-routes.test.ts +257 -387
- package/src/__tests__/twilio-validation.test.ts +1 -1
- package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
- package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
- package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
- package/src/__tests__/voice-quality.test.ts +2 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
- package/src/__tests__/voice-session-bridge.test.ts +1 -10
- package/src/__tests__/workspace-git-service.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
- package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
- package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
- package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
- package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
- package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
- package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
- package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
- package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
- package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
- package/src/acp/__tests__/session-manager.test.ts +6 -0
- package/src/acp/agent-process.test.ts +116 -0
- package/src/acp/agent-process.ts +71 -0
- package/src/acp/auto-install.ts +12 -8
- package/src/acp/failure-error.test.ts +109 -0
- package/src/acp/failure-error.ts +111 -0
- package/src/acp/prepare-agent-env.ts +0 -12
- package/src/acp/resolve-agent.test.ts +6 -45
- package/src/acp/resolve-agent.ts +2 -4
- package/src/acp/session-manager.test.ts +312 -0
- package/src/acp/session-manager.ts +102 -46
- package/src/agent/ax-tree-compaction.test.ts +4 -1
- package/src/agent/image-optimize.ts +17 -127
- package/src/agent/loop.ts +45 -192
- package/src/api/events/background-tool-completed.test.ts +51 -0
- package/src/api/events/background-tool-completed.ts +29 -0
- package/src/api/events/background-tool-started.test.ts +36 -0
- package/src/api/events/background-tool-started.ts +28 -0
- package/src/api/events/conversation-error.ts +0 -1
- package/src/api/events/open-panel.ts +33 -0
- package/src/api/events/subagent-status-changed.ts +4 -1
- package/src/api/index.ts +19 -0
- package/src/api/responses/conversation-message.ts +34 -0
- package/src/approvals/guardian-decision-primitive.ts +74 -24
- package/src/approvals/guardian-request-resolvers.ts +450 -122
- package/src/apps/app-store.ts +1 -0
- package/src/apps/shared-app-links-store.ts +1 -0
- package/src/avatar/identity-avatar.ts +3 -7
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
- package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
- package/src/calls/call-controller.ts +134 -48
- package/src/calls/call-domain.ts +18 -42
- package/src/calls/call-pointer-messages.ts +51 -67
- package/src/calls/call-setup-flow-types.ts +76 -0
- package/src/calls/call-setup-flow.ts +1743 -0
- package/src/calls/call-speech-output.ts +87 -23
- package/src/calls/call-store.ts +4 -0
- package/src/calls/call-transport.ts +22 -36
- package/src/calls/fish-audio-client.ts +3 -0
- package/src/calls/gateway-invite-reader.ts +98 -0
- package/src/calls/guardian-wait-controller.ts +451 -0
- package/src/calls/media-stream-audio-transcode.ts +82 -2
- package/src/calls/media-stream-output.ts +142 -36
- package/src/calls/media-stream-server.ts +297 -178
- package/src/calls/media-stream-stt-session.ts +393 -50
- package/src/calls/media-turn-detector.ts +4 -6
- package/src/calls/relay-access-wait.ts +3 -4
- package/src/calls/relay-setup-router.ts +22 -43
- package/src/calls/relay-verification.ts +17 -24
- package/src/calls/resolve-call-tts-provider.ts +96 -29
- package/src/calls/stt-hints.ts +24 -87
- package/src/calls/telephony-credential-preflight.ts +159 -0
- package/src/calls/telephony-tts-capability.ts +183 -0
- package/src/calls/tts-call-strategy.ts +18 -20
- package/src/calls/twilio-provider.ts +3 -2
- package/src/calls/twilio-routes.ts +47 -351
- package/src/calls/types.ts +5 -3
- package/src/calls/voice-ingress-preflight.ts +9 -0
- package/src/calls/voice-quality.ts +13 -18
- package/src/calls/voice-session-bridge.ts +25 -35
- package/src/channels/__tests__/types.test.ts +28 -0
- package/src/channels/channel-verification-sessions.ts +7 -2
- package/src/channels/config.ts +0 -42
- package/src/channels/slack-thread-store.ts +12 -0
- package/src/channels/types.ts +23 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
- package/src/cli/commands/__tests__/schedules.test.ts +83 -34
- package/src/cli/commands/__tests__/status.test.ts +42 -2
- package/src/cli/commands/contacts.ts +2 -2
- package/src/cli/commands/credentials.ts +17 -0
- package/src/cli/commands/monitoring.ts +191 -0
- package/src/cli/commands/schedules-worker.ts +175 -0
- package/src/cli/commands/schedules.ts +169 -43
- package/src/cli/commands/status.ts +12 -1
- package/src/cli/commands/tools.ts +5 -1
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
- package/src/cli/lib/search-plugins.ts +6 -0
- package/src/cli/lib/toggle-plugin.ts +21 -2
- package/src/cli/program.ts +3 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
- package/src/config/acp-defaults.test.ts +0 -10
- package/src/config/acp-defaults.ts +0 -6
- package/src/config/bundled-skills/acp/SKILL.md +13 -45
- package/src/config/bundled-skills/acp/TOOLS.json +3 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
- package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
- package/src/config/call-site-defaults.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -8
- package/src/config/loader.ts +11 -0
- package/src/config/schema.ts +9 -1
- package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
- package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
- package/src/config/schemas/call-site-catalog.ts +0 -12
- package/src/config/schemas/calls.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +1 -1
- package/src/config/schemas/llm.ts +0 -2
- package/src/config/schemas/memory-v2.ts +1 -1
- package/src/config/schemas/memory-v3.ts +82 -0
- package/src/config/schemas/monitoring.ts +61 -0
- package/src/config/schemas/schedules.ts +35 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills-plugin-filter.test.ts +96 -0
- package/src/config/skills.ts +26 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
- package/src/contacts/canonical-guardian-store.ts +5 -0
- package/src/contacts/contact-store.ts +81 -35
- package/src/contacts/contacts-write.ts +50 -25
- package/src/contacts/member-write-relay.ts +115 -31
- package/src/contacts/types.ts +0 -8
- package/src/context/compactor.ts +29 -15
- package/src/context/outbound-sanitize.ts +202 -0
- package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
- package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
- package/src/daemon/abort-watchdog.ts +7 -0
- package/src/daemon/app-source-watcher.ts +9 -0
- package/src/daemon/assistant-attachments.ts +42 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
- package/src/daemon/conversation-agent-loop.ts +61 -68
- package/src/daemon/conversation-error.ts +1 -15
- package/src/daemon/conversation-history.ts +32 -236
- package/src/daemon/conversation-initial-prompt.ts +77 -0
- package/src/daemon/conversation-lifecycle.ts +25 -1
- package/src/daemon/conversation-messaging.ts +2 -2
- package/src/daemon/conversation-plugin-scope.ts +38 -0
- package/src/daemon/conversation-process.ts +50 -14
- package/src/daemon/conversation-runtime-assembly.ts +36 -6
- package/src/daemon/conversation-skill-tools.ts +19 -3
- package/src/daemon/conversation-store.ts +3 -3
- package/src/daemon/conversation-surfaces.ts +171 -0
- package/src/daemon/conversation-tool-setup.test.ts +95 -0
- package/src/daemon/conversation-tool-setup.ts +116 -1
- package/src/daemon/conversation-turn-finalize.ts +211 -0
- package/src/daemon/conversation.ts +92 -1
- package/src/daemon/disk-pressure-policy.ts +2 -1
- package/src/daemon/event-loop-watchdog.ts +22 -6
- package/src/daemon/external-plugins-bootstrap.ts +47 -134
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
- package/src/daemon/handlers/config-a2a.ts +7 -14
- package/src/daemon/handlers/config-channels.ts +2 -10
- package/src/daemon/handlers/conversation-history.ts +3 -1
- package/src/daemon/handlers/conversations.ts +0 -52
- package/src/daemon/handlers/shared.ts +4 -24
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +59 -472
- package/src/daemon/message-protocol.ts +3 -3
- package/src/daemon/message-provenance.ts +12 -14
- package/src/daemon/message-types/background-tools.ts +28 -0
- package/src/daemon/message-types/contacts.ts +2 -10
- package/src/daemon/message-types/conversations.ts +10 -0
- package/src/daemon/message-types/integrations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pointer-conversation-trust.ts +23 -9
- package/src/daemon/pointer-turn-runner.ts +174 -0
- package/src/daemon/providers-setup.ts +16 -0
- package/src/daemon/shutdown-handlers.ts +139 -47
- package/src/daemon/skill-memory-refresh.ts +2 -2
- package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
- package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
- package/src/daemon/tool-setup-types.ts +8 -0
- package/src/daemon/trust-context.ts +21 -6
- package/src/daemon/turn-latency-tracker.test.ts +93 -0
- package/src/daemon/turn-latency-tracker.ts +38 -0
- package/src/daemon/wake-conversation-ops.ts +10 -8
- package/src/documents/document-comments-store.test.ts +7 -1
- package/src/documents/document-comments-store.ts +8 -0
- package/src/documents/document-store.ts +15 -0
- package/src/export/__tests__/transcript-formatter.test.ts +11 -0
- package/src/export/transcript-formatter.ts +49 -67
- package/src/home/__tests__/feed-writer.test.ts +247 -1
- package/src/home/conversation-starter-checkpoints.ts +1 -0
- package/src/home/feed-writer.ts +61 -0
- package/src/home/job-handlers/conversation-starters.ts +1 -0
- package/src/hooks/hook-loader.ts +12 -0
- package/src/hooks/registry.ts +32 -4
- package/src/inbound/public-ingress-urls.ts +0 -17
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
- package/src/ipc/assistant-server.ts +28 -7
- package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
- package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
- package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
- package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
- package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
- package/src/ipc/routes/db-proxy.ts +5 -2
- package/src/ipc/routes/invite-ipc-routes.ts +53 -39
- package/src/jobs/worker.ts +9 -2
- package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
- package/src/live-voice/live-voice-archive.ts +5 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
- package/src/messaging/providers/channel-transport.ts +6 -0
- package/src/messaging/providers/index.ts +3 -0
- package/src/messaging/providers/slack/api.test.ts +49 -1
- package/src/messaging/providers/slack/api.ts +110 -0
- package/src/messaging/providers/slack/send.test.ts +85 -0
- package/src/messaging/providers/slack/send.ts +100 -28
- package/src/messaging/providers/slack/transport.ts +7 -13
- package/src/messaging/providers/whatsapp/send.ts +29 -9
- package/src/monitoring/__tests__/control.test.ts +235 -0
- package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
- package/src/monitoring/control.ts +105 -0
- package/src/monitoring/resource-sampler.ts +258 -0
- package/src/monitoring/sample-ring-buffer.ts +108 -0
- package/src/monitoring/worker.ts +94 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/access-request-copy.ts +94 -23
- package/src/notifications/adapters/slack.ts +89 -21
- package/src/notifications/approval-card-builder.ts +33 -18
- package/src/notifications/approval-card-data.ts +48 -15
- package/src/notifications/broadcaster.ts +25 -16
- package/src/notifications/decision-engine.ts +131 -32
- package/src/notifications/guardian-question-mode.ts +58 -10
- package/src/permissions/approval-policy.ts +8 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/gateway-threshold-reader.ts +7 -6
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/secret-prompter.ts +11 -3
- package/src/permissions/types.ts +2 -2
- package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
- package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
- package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
- package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
- package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
- package/src/persistence/a2a-invite-store.ts +205 -0
- package/src/persistence/attachments-store.ts +94 -10
- package/src/persistence/checkpoints.ts +45 -0
- package/src/persistence/conversation-crud.ts +453 -260
- package/src/persistence/conversation-display-order-migration.ts +8 -2
- package/src/persistence/conversation-group-migration.test.ts +8 -0
- package/src/persistence/conversation-group-migration.ts +9 -0
- package/src/persistence/conversation-queries.ts +244 -125
- package/src/persistence/conversation-row-batch-delete.ts +9 -5
- package/src/persistence/conversation-search-lexical.ts +49 -0
- package/src/persistence/db-async-query.ts +42 -0
- package/src/persistence/db-connection.ts +13 -0
- package/src/persistence/delivery-channels.ts +0 -82
- package/src/persistence/delivery-crud.ts +27 -6
- package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
- package/src/persistence/embeddings/embedding-identity.ts +17 -5
- package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
- package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
- package/src/persistence/embeddings/qdrant-client.ts +81 -5
- package/src/persistence/group-crud.ts +13 -1
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
- package/src/persistence/job-handlers/cleanup.ts +57 -9
- package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
- package/src/persistence/job-handlers/message-lexical.ts +251 -0
- package/src/persistence/jobs-store.ts +102 -8
- package/src/persistence/jobs-worker.ts +68 -28
- package/src/persistence/llm-request-log-store.ts +35 -19
- package/src/persistence/llm-usage-store.ts +11 -0
- package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
- package/src/persistence/memory-lifecycle-hooks.ts +55 -1
- package/src/persistence/migrations/028-call-session-mode.ts +1 -1
- package/src/persistence/migrations/116-messages-fts.ts +8 -1
- package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
- package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
- package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
- package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
- package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
- package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
- package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
- package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
- package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
- package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
- package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
- package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
- package/src/persistence/raw-query.ts +50 -11
- package/src/persistence/schema/a2a.ts +14 -0
- package/src/persistence/schema/contacts.ts +0 -62
- package/src/persistence/schema/conversation-groups.ts +12 -0
- package/src/persistence/schema/conversations.ts +2 -0
- package/src/persistence/schema/documents.ts +65 -0
- package/src/persistence/schema/guardian.ts +4 -0
- package/src/persistence/schema/index.ts +4 -0
- package/src/persistence/schema/memory-injection.ts +62 -0
- package/src/persistence/schema/workflows.ts +55 -0
- package/src/persistence/slow-query-log.ts +437 -0
- package/src/persistence/slow-sync-log.ts +204 -0
- package/src/persistence/steps.ts +16 -0
- package/src/persistence/subagent-store.ts +125 -0
- package/src/persistence/worker-control.ts +45 -238
- package/src/plugin-api/event-hub-facade.ts +172 -0
- package/src/plugin-api/index.ts +9 -1
- package/src/plugin-api/types.ts +40 -9
- package/src/plugins/defaults/default-plugin-names.ts +60 -0
- package/src/plugins/defaults/index.ts +19 -29
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
- package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
- package/src/plugins/defaults/memory/config.ts +11 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
- package/src/plugins/defaults/memory/embeddings.ts +77 -0
- package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
- package/src/plugins/defaults/memory/frontmatter.ts +50 -0
- package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
- package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
- package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
- package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
- package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
- package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
- package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
- package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
- package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
- package/src/plugins/defaults/memory/graph/tools.ts +1 -1
- package/src/plugins/defaults/memory/hooks/init.ts +31 -5
- package/src/plugins/defaults/memory/indexer.ts +2 -3
- package/src/plugins/defaults/memory/injectors.ts +2 -2
- package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
- package/src/plugins/defaults/memory/job-handlers.ts +13 -12
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
- package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
- package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
- package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
- package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
- package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
- package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
- package/src/plugins/defaults/memory/search/semantic.ts +2 -2
- package/src/plugins/defaults/memory/startup.ts +244 -0
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
- package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
- package/src/plugins/defaults/memory/v2/activation.ts +2 -4
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
- package/src/plugins/defaults/memory/v2/migration.ts +2 -5
- package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
- package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
- package/src/plugins/defaults/memory/v2/router.ts +5 -5
- package/src/plugins/defaults/memory/v2/sim.ts +2 -4
- package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
- package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
- package/src/plugins/defaults/memory/v3/card.ts +1 -4
- package/src/plugins/defaults/memory/v3/dense.ts +60 -25
- package/src/plugins/defaults/memory/v3/edge.ts +1 -1
- package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
- package/src/plugins/defaults/memory/v3/gate.ts +158 -0
- package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
- package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
- package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
- package/src/plugins/defaults/memory/v3/prune.ts +2 -2
- package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
- package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
- package/src/plugins/defaults/turn-context/injectors.ts +1 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
- package/src/plugins/injector-registry.ts +13 -2
- package/src/plugins/mtime-cache.ts +36 -47
- package/src/plugins/pipeline.ts +15 -1
- package/src/plugins/types.ts +14 -23
- package/src/prompts/__tests__/system-prompt.test.ts +170 -32
- package/src/prompts/persona-resolver.ts +13 -9
- package/src/prompts/system-prompt.ts +30 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -119
- package/src/prompts/templates/SOUL.md +43 -13
- package/src/prompts/templates/system-sections.ts +32 -27
- package/src/prompts/templates/users/default.md +19 -0
- package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +14 -1
- package/src/providers/openai/responses-provider.ts +18 -0
- package/src/providers/placeholder-sentinels.ts +18 -8
- package/src/providers/retry.ts +1 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
- package/src/providers/speech-to-text/provider-catalog.ts +0 -89
- package/src/providers/speech-to-text/resolve.ts +55 -0
- package/src/providers/tool-progress-events.test.ts +50 -0
- package/src/providers/tool-progress-events.ts +99 -0
- package/src/providers/types.ts +1 -1
- package/src/providers/vellum-model-routing.test.ts +51 -0
- package/src/providers/vellum-model-routing.ts +84 -0
- package/src/runtime/AGENTS.md +5 -4
- package/src/runtime/__tests__/agent-wake.test.ts +158 -1
- package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
- package/src/runtime/access-request-helper.ts +154 -3
- package/src/runtime/actor-trust-resolver.ts +7 -21
- package/src/runtime/agent-wake.ts +41 -1
- package/src/runtime/assistant-event.ts +86 -12
- package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
- package/src/runtime/channel-approval-types.ts +52 -2
- package/src/runtime/channel-approvals.ts +23 -8
- package/src/runtime/channel-invite-transport.ts +2 -2
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-readiness-service.ts +3 -5
- package/src/runtime/channel-retry-sweep.ts +18 -24
- package/src/runtime/channel-verification-service.ts +9 -11
- package/src/runtime/finalize-event-delivery.ts +30 -16
- package/src/runtime/guardian-action-service.ts +10 -11
- package/src/runtime/guardian-reply-router.ts +122 -21
- package/src/runtime/http-server.ts +44 -101
- package/src/runtime/introduction-policy.test.ts +214 -0
- package/src/runtime/introduction-policy.ts +284 -0
- package/src/runtime/invite-service.ts +104 -361
- package/src/runtime/local-actor-identity.test.ts +38 -0
- package/src/runtime/local-actor-identity.ts +14 -0
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
- package/src/runtime/middleware/rate-limiter.ts +30 -0
- package/src/runtime/middleware/twilio-validation.ts +5 -7
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
- package/src/runtime/migrations/origin-mode.ts +6 -6
- package/src/runtime/pre-first-message-gate.ts +1 -0
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
- package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +15 -3
- package/src/runtime/routes/app-management-routes.ts +4 -7
- package/src/runtime/routes/approval-routes.ts +4 -0
- package/src/runtime/routes/attachment-routes.ts +54 -3
- package/src/runtime/routes/avatar-routes.ts +0 -4
- package/src/runtime/routes/background-tool-routes.ts +34 -5
- package/src/runtime/routes/btw-routes.ts +32 -4
- package/src/runtime/routes/channel-route-shared.ts +18 -14
- package/src/runtime/routes/channel-verification-routes.ts +0 -3
- package/src/runtime/routes/contact-routes.ts +298 -117
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +74 -37
- package/src/runtime/routes/conversation-query-routes.ts +5 -2
- package/src/runtime/routes/conversation-routes.ts +222 -82
- package/src/runtime/routes/conversations-import-routes.ts +8 -1
- package/src/runtime/routes/credential-prompt-routes.ts +20 -5
- package/src/runtime/routes/debug-routes.ts +1 -0
- package/src/runtime/routes/documents-routes.ts +5 -2
- package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
- package/src/runtime/routes/global-search-routes.ts +2 -1
- package/src/runtime/routes/guardian-approval-interception.ts +51 -0
- package/src/runtime/routes/home-feed-routes.ts +60 -1
- package/src/runtime/routes/identity-routes.ts +4 -87
- package/src/runtime/routes/inbound-message-handler.ts +82 -41
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
- package/src/runtime/routes/internal-twilio-routes.ts +0 -15
- package/src/runtime/routes/messages-lexical-routes.ts +75 -0
- package/src/runtime/routes/migration-routes.ts +69 -6
- package/src/runtime/routes/monitoring-routes.ts +237 -0
- package/src/runtime/routes/plugins-routes.ts +329 -8
- package/src/runtime/routes/schedule-routes.ts +49 -8
- package/src/runtime/routes/schedule-worker-routes.ts +210 -0
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
- package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
- package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
- package/src/runtime/services/analyze-conversation.ts +14 -4
- package/src/runtime/services/conversation-serializer.ts +5 -0
- package/src/runtime/slack-no-response.ts +47 -0
- package/src/runtime/slack-reply-session.test.ts +633 -0
- package/src/runtime/slack-reply-session.ts +382 -0
- package/src/runtime/slack-task-progress.ts +95 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/tool-grant-request-helper.ts +17 -1
- package/src/runtime/trust-class.test.ts +141 -0
- package/src/runtime/trust-class.ts +121 -0
- package/src/runtime/trust-verdict-consumer.ts +7 -6
- package/src/schedule/__tests__/run-script.test.ts +21 -0
- package/src/schedule/__tests__/worker-control.test.ts +241 -0
- package/src/schedule/run-script.ts +13 -6
- package/src/schedule/schedule-usage-store.ts +1 -0
- package/src/schedule/scheduler.ts +178 -127
- package/src/schedule/worker-control.ts +118 -0
- package/src/schedule/worker.ts +131 -0
- package/src/skills/__tests__/categories-cache.test.ts +38 -0
- package/src/skills/categories-cache.ts +40 -5
- package/src/skills/managed-store.ts +41 -6
- package/src/skills/validate-input.ts +47 -0
- package/src/stt/types.ts +5 -9
- package/src/subagent/manager.ts +267 -39
- package/src/subagent/types.ts +6 -2
- package/src/subagent/validate-allowlists.ts +65 -0
- package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
- package/src/telemetry/watchdog-direct-emit.ts +89 -0
- package/src/tools/acp/list-agents.test.ts +0 -6
- package/src/tools/background-tool-registry.ts +61 -0
- package/src/tools/document/document-comment-tool.test.ts +4 -0
- package/src/tools/host-terminal/host-shell.test.ts +397 -0
- package/src/tools/host-terminal/host-shell.ts +203 -14
- package/src/tools/skills/find-similar-skills.test.ts +152 -1
- package/src/tools/skills/find-similar-skills.ts +30 -4
- package/src/tools/skills/load.ts +36 -0
- package/src/tools/skills/scaffold-managed.ts +66 -34
- package/src/tools/skills/skill-script-runner.ts +17 -0
- package/src/tools/skills/skill-tool-factory.ts +5 -1
- package/src/tools/terminal/safe-env.ts +3 -0
- package/src/tools/terminal/shell.test.ts +177 -0
- package/src/tools/terminal/shell.ts +98 -4
- package/src/tools/tool-approval-handler.ts +106 -29
- package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
- package/src/tools/types.ts +29 -17
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tts/__tests__/provider-adapters.test.ts +37 -0
- package/src/tts/__tests__/provider-catalog.test.ts +21 -0
- package/src/tts/provider-catalog.ts +40 -9
- package/src/tts/providers/fish-audio-provider.ts +19 -10
- package/src/tts/types.ts +3 -4
- package/src/util/__tests__/process-tree.test.ts +10 -2
- package/src/util/__tests__/text-spacing.test.ts +53 -0
- package/src/util/cgroup-memory.ts +142 -0
- package/src/util/image-conversion.ts +281 -0
- package/src/util/phone.ts +1 -8
- package/src/util/platform.ts +33 -0
- package/src/util/process-tree.ts +10 -2
- package/src/util/text-spacing.ts +53 -0
- package/src/util/worker-process.ts +271 -0
- package/src/workflows/journal-store.ts +16 -1
- package/src/workflows/library.test.ts +35 -20
- package/src/workflows/library.ts +105 -66
- package/src/workspace/git-service.ts +1 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
- package/src/workspace/migrations/118-seed-now-md.ts +64 -0
- package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
- package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
- package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
- package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
- package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
- package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/drizzle/0000_dizzy_maggott.sql +0 -301
- package/drizzle/meta/0000_snapshot.json +0 -1933
- package/drizzle/meta/_journal.json +0 -13
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
- package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
- package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
- package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
- package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
- package/src/__tests__/invite-redemption-service.test.ts +0 -1180
- package/src/__tests__/invite-service-ipc.test.ts +0 -350
- package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
- package/src/__tests__/relay-server.test.ts +0 -6153
- package/src/__tests__/telephony-stt-routing.test.ts +0 -329
- package/src/__tests__/voice-invite-redemption.test.ts +0 -702
- package/src/calls/relay-server.ts +0 -2463
- package/src/calls/telephony-stt-routing.ts +0 -145
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
- package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
- package/src/daemon/daemon-skill-host.ts +0 -262
- package/src/daemon/message-types/meet.ts +0 -143
- package/src/daemon/shutdown-registry.ts +0 -40
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
- package/src/ipc/__tests__/skill-server.test.ts +0 -182
- package/src/ipc/skill-ipc-types.ts +0 -54
- package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
- package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
- package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
- package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
- package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
- package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
- package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
- package/src/ipc/skill-routes/config.ts +0 -47
- package/src/ipc/skill-routes/events.ts +0 -147
- package/src/ipc/skill-routes/identity.ts +0 -21
- package/src/ipc/skill-routes/index.ts +0 -37
- package/src/ipc/skill-routes/log.ts +0 -40
- package/src/ipc/skill-routes/memory.ts +0 -92
- package/src/ipc/skill-routes/platform.ts +0 -39
- package/src/ipc/skill-routes/providers.ts +0 -162
- package/src/ipc/skill-routes/registries.ts +0 -338
- package/src/ipc/skill-server.ts +0 -831
- package/src/ipc/skill-socket-path.ts +0 -20
- package/src/jobs/register-job-handlers.ts +0 -74
- package/src/persistence/invite-store.ts +0 -481
- package/src/plugins/job-handler-registry.ts +0 -94
- package/src/providers/cache-control.ts +0 -26
- package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
- package/src/runtime/invite-redemption-service.ts +0 -828
- package/src/runtime/invite-redemption-templates.ts +0 -46
- package/src/runtime/runtime-mode.ts +0 -40
- package/src/runtime/slack-dm-text-delivery.ts +0 -177
- package/src/util/voice-code.ts +0 -31
package/src/acp/resolve-agent.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `resolveAcpAgent(id)` merges user-provided `config.acp.agents[id]` (wins on
|
|
5
5
|
* overlap) with the bundled `DEFAULT_ACP_AGENT_PROFILES` so common agents like
|
|
6
6
|
* `claude` and `codex` Just Work with no per-user config required. Natural
|
|
7
|
-
* names ("claude code", "
|
|
7
|
+
* names ("claude code", "OpenAI Codex") resolve via `AGENT_ID_ALIASES` when the
|
|
8
8
|
* raw id misses both maps. The result is a discriminated union covering every
|
|
9
9
|
* reason a spawn might fail before we even start the agent process: unknown
|
|
10
10
|
* agent id, or binary missing from PATH. Callers (acp_spawn, acp_list_agents,
|
|
@@ -132,8 +132,6 @@ const AGENT_ID_ALIASES: Record<string, string> = {
|
|
|
132
132
|
claudecode: "claude",
|
|
133
133
|
codexcli: "codex",
|
|
134
134
|
openaicodex: "codex",
|
|
135
|
-
geminicli: "gemini",
|
|
136
|
-
googlegemini: "gemini",
|
|
137
135
|
};
|
|
138
136
|
|
|
139
137
|
/**
|
|
@@ -151,7 +149,7 @@ function normalizeAgentId(id: string): string {
|
|
|
151
149
|
* vs bundled default" without re-deriving it.
|
|
152
150
|
*
|
|
153
151
|
* When the raw id misses both maps, fall back to `AGENT_ID_ALIASES` so
|
|
154
|
-
* natural names like "claude code" or "
|
|
152
|
+
* natural names like "claude code" or "OpenAI Codex" resolve to the canonical
|
|
155
153
|
* id. The alias is consulted ONLY after both direct lookups miss, so a user
|
|
156
154
|
* config entry literally keyed "claude code" always wins over the alias.
|
|
157
155
|
*/
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { Conversation } from "../daemon/conversation.js";
|
|
4
|
+
import {
|
|
5
|
+
deleteConversation,
|
|
6
|
+
setConversation,
|
|
7
|
+
} from "../daemon/conversation-registry.js";
|
|
8
|
+
import { VellumAcpClientHandler } from "./client-handler.js";
|
|
9
|
+
import { AcpSessionManager } from "./session-manager.js";
|
|
10
|
+
|
|
11
|
+
// Parent conversations registered per test; torn down in afterEach so the
|
|
12
|
+
// shared registry does not leak state between cases.
|
|
13
|
+
const registered: string[] = [];
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
for (const id of registered.splice(0)) {
|
|
17
|
+
deleteConversation(id);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A duck-typed parent conversation exposing only the three methods
|
|
23
|
+
* `notifyParent` touches. `enqueueMessage` returns not-queued by default so the
|
|
24
|
+
* persist + runAgentLoop branch runs and the metadata can be asserted; pass
|
|
25
|
+
* `enqueueQueued: true` to exercise the enqueue branch instead.
|
|
26
|
+
*/
|
|
27
|
+
function mockConversation(opts?: { enqueueQueued?: boolean }) {
|
|
28
|
+
const enqueueMessage = mock(() => ({
|
|
29
|
+
queued: opts?.enqueueQueued ?? false,
|
|
30
|
+
requestId: "req-1",
|
|
31
|
+
rejected: false,
|
|
32
|
+
}));
|
|
33
|
+
const persistUserMessage = mock(async () => ({
|
|
34
|
+
id: "msg-1",
|
|
35
|
+
deduplicated: false,
|
|
36
|
+
}));
|
|
37
|
+
let resolveLoop!: () => void;
|
|
38
|
+
const loopRan = new Promise<void>((r) => {
|
|
39
|
+
resolveLoop = r;
|
|
40
|
+
});
|
|
41
|
+
const runAgentLoop = mock(async () => {
|
|
42
|
+
resolveLoop();
|
|
43
|
+
});
|
|
44
|
+
const conversation = {
|
|
45
|
+
enqueueMessage,
|
|
46
|
+
persistUserMessage,
|
|
47
|
+
runAgentLoop,
|
|
48
|
+
} as unknown as Conversation;
|
|
49
|
+
return {
|
|
50
|
+
conversation,
|
|
51
|
+
enqueueMessage,
|
|
52
|
+
persistUserMessage,
|
|
53
|
+
runAgentLoop,
|
|
54
|
+
loopRan,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Fake AcpAgentProcess covering only the calls firePromptInBackground makes. */
|
|
59
|
+
function fakeProcess(prompt: () => Promise<unknown>) {
|
|
60
|
+
return {
|
|
61
|
+
markStderr: () => 0,
|
|
62
|
+
stderrSince: () => "",
|
|
63
|
+
prompt,
|
|
64
|
+
kill: mock(() => {}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Injects a running session directly into the manager (no child process). */
|
|
69
|
+
function injectSession(
|
|
70
|
+
manager: AcpSessionManager,
|
|
71
|
+
acpSessionId: string,
|
|
72
|
+
parentConversationId: string,
|
|
73
|
+
process: ReturnType<typeof fakeProcess>,
|
|
74
|
+
) {
|
|
75
|
+
const sendToVellum = mock(() => {});
|
|
76
|
+
const clientHandler = new VellumAcpClientHandler(
|
|
77
|
+
acpSessionId,
|
|
78
|
+
sendToVellum,
|
|
79
|
+
parentConversationId,
|
|
80
|
+
);
|
|
81
|
+
const entry = {
|
|
82
|
+
process,
|
|
83
|
+
state: {
|
|
84
|
+
id: acpSessionId,
|
|
85
|
+
agentId: "claude",
|
|
86
|
+
acpSessionId: "proto-1",
|
|
87
|
+
parentConversationId,
|
|
88
|
+
status: "running" as string,
|
|
89
|
+
startedAt: Date.now(),
|
|
90
|
+
},
|
|
91
|
+
clientHandler,
|
|
92
|
+
sendToVellum,
|
|
93
|
+
currentPrompt: null as unknown,
|
|
94
|
+
parentConversationId,
|
|
95
|
+
cwd: "/tmp",
|
|
96
|
+
command: "noop",
|
|
97
|
+
};
|
|
98
|
+
(manager as any).sessions.set(acpSessionId, entry);
|
|
99
|
+
return entry;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function fire(
|
|
103
|
+
manager: AcpSessionManager,
|
|
104
|
+
acpSessionId: string,
|
|
105
|
+
entry: ReturnType<typeof injectSession>,
|
|
106
|
+
): Promise<unknown> {
|
|
107
|
+
const bg = (manager as any).firePromptInBackground(
|
|
108
|
+
acpSessionId,
|
|
109
|
+
entry,
|
|
110
|
+
"proto-1",
|
|
111
|
+
"do it",
|
|
112
|
+
);
|
|
113
|
+
entry.currentPrompt = bg;
|
|
114
|
+
return bg;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
describe("AcpSessionManager parent notification", () => {
|
|
118
|
+
test("prompt failure notifies the parent once with the failed message + acpNotification metadata", async () => {
|
|
119
|
+
const manager = new AcpSessionManager(1);
|
|
120
|
+
const {
|
|
121
|
+
conversation,
|
|
122
|
+
enqueueMessage,
|
|
123
|
+
persistUserMessage,
|
|
124
|
+
runAgentLoop,
|
|
125
|
+
loopRan,
|
|
126
|
+
} = mockConversation();
|
|
127
|
+
setConversation("parent-fail", conversation);
|
|
128
|
+
registered.push("parent-fail");
|
|
129
|
+
|
|
130
|
+
const proc = fakeProcess(() => Promise.reject(new Error("boom")));
|
|
131
|
+
const entry = injectSession(manager, "sess-fail", "parent-fail", proc);
|
|
132
|
+
|
|
133
|
+
await fire(manager, "sess-fail", entry);
|
|
134
|
+
await loopRan;
|
|
135
|
+
|
|
136
|
+
// Exactly one notification (enqueue returned not-queued, so persist+loop).
|
|
137
|
+
expect(enqueueMessage).toHaveBeenCalledTimes(1);
|
|
138
|
+
expect(persistUserMessage).toHaveBeenCalledTimes(1);
|
|
139
|
+
expect(runAgentLoop).toHaveBeenCalledTimes(1);
|
|
140
|
+
|
|
141
|
+
const persistArg = (
|
|
142
|
+
persistUserMessage.mock.calls as unknown as Array<
|
|
143
|
+
[{ content: string; metadata: unknown }]
|
|
144
|
+
>
|
|
145
|
+
)[0][0];
|
|
146
|
+
expect(persistArg.content).toBe('[ACP agent "claude" failed]\n\nboom');
|
|
147
|
+
expect(persistArg.metadata).toEqual({
|
|
148
|
+
acpNotification: { acpSessionId: "proto-1", agent: "claude" },
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Session was torn down on failure.
|
|
152
|
+
expect((manager.getStatus() as unknown[]).length).toBe(0);
|
|
153
|
+
expect(proc.kill).toHaveBeenCalled();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("prompt success still notifies the parent exactly once", async () => {
|
|
157
|
+
const manager = new AcpSessionManager(1);
|
|
158
|
+
const {
|
|
159
|
+
conversation,
|
|
160
|
+
enqueueMessage,
|
|
161
|
+
persistUserMessage,
|
|
162
|
+
runAgentLoop,
|
|
163
|
+
loopRan,
|
|
164
|
+
} = mockConversation();
|
|
165
|
+
setConversation("parent-ok", conversation);
|
|
166
|
+
registered.push("parent-ok");
|
|
167
|
+
|
|
168
|
+
const proc = fakeProcess(() => Promise.resolve({ stopReason: "end_turn" }));
|
|
169
|
+
const entry = injectSession(manager, "sess-ok", "parent-ok", proc);
|
|
170
|
+
|
|
171
|
+
await fire(manager, "sess-ok", entry);
|
|
172
|
+
await loopRan;
|
|
173
|
+
|
|
174
|
+
expect(enqueueMessage).toHaveBeenCalledTimes(1);
|
|
175
|
+
expect(persistUserMessage).toHaveBeenCalledTimes(1);
|
|
176
|
+
expect(runAgentLoop).toHaveBeenCalledTimes(1);
|
|
177
|
+
|
|
178
|
+
const persistArg = (
|
|
179
|
+
persistUserMessage.mock.calls as unknown as Array<
|
|
180
|
+
[{ content: string; metadata: unknown }]
|
|
181
|
+
>
|
|
182
|
+
)[0][0];
|
|
183
|
+
expect(
|
|
184
|
+
persistArg.content.startsWith('[ACP agent "claude" completed]'),
|
|
185
|
+
).toBe(true);
|
|
186
|
+
expect(persistArg.metadata).toEqual({
|
|
187
|
+
acpNotification: { acpSessionId: "proto-1", agent: "claude" },
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("a cancelled session does not notify the parent on failure", async () => {
|
|
192
|
+
const manager = new AcpSessionManager(1);
|
|
193
|
+
const { conversation, enqueueMessage } = mockConversation();
|
|
194
|
+
setConversation("parent-cancel", conversation);
|
|
195
|
+
registered.push("parent-cancel");
|
|
196
|
+
|
|
197
|
+
const proc = fakeProcess(() => Promise.reject(new Error("boom")));
|
|
198
|
+
const entry = injectSession(manager, "sess-cancel", "parent-cancel", proc);
|
|
199
|
+
// Simulate a user cancel landing before the rejection settles.
|
|
200
|
+
entry.state.status = "cancelled";
|
|
201
|
+
|
|
202
|
+
await fire(manager, "sess-cancel", entry);
|
|
203
|
+
// Any notification would have called enqueue synchronously inside the catch.
|
|
204
|
+
expect(enqueueMessage).not.toHaveBeenCalled();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("a cancelled session does not notify the parent on success", async () => {
|
|
208
|
+
// A prompt can win the cancel race by resolving normally; a user stop must
|
|
209
|
+
// still not wake the parent with a completion.
|
|
210
|
+
const manager = new AcpSessionManager(1);
|
|
211
|
+
const { conversation, enqueueMessage } = mockConversation();
|
|
212
|
+
setConversation("parent-cancel-ok", conversation);
|
|
213
|
+
registered.push("parent-cancel-ok");
|
|
214
|
+
|
|
215
|
+
const proc = fakeProcess(() => Promise.resolve({ stopReason: "end_turn" }));
|
|
216
|
+
const entry = injectSession(
|
|
217
|
+
manager,
|
|
218
|
+
"sess-cancel-ok",
|
|
219
|
+
"parent-cancel-ok",
|
|
220
|
+
proc,
|
|
221
|
+
);
|
|
222
|
+
entry.state.status = "cancelled";
|
|
223
|
+
|
|
224
|
+
await fire(manager, "sess-cancel-ok", entry);
|
|
225
|
+
expect(enqueueMessage).not.toHaveBeenCalled();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("cancel marks the session cancelled before the protocol cancel resolves", async () => {
|
|
229
|
+
// Guards the cancel race: if the in-flight prompt rejects while
|
|
230
|
+
// process.cancel is still pending, the failure gate must already see
|
|
231
|
+
// "cancelled" so it does not wake the parent after a user stop.
|
|
232
|
+
const manager = new AcpSessionManager(1);
|
|
233
|
+
let resolveCancel!: () => void;
|
|
234
|
+
const cancelPending = new Promise<void>((r) => {
|
|
235
|
+
resolveCancel = r;
|
|
236
|
+
});
|
|
237
|
+
const proc = {
|
|
238
|
+
markStderr: () => 0,
|
|
239
|
+
stderrSince: () => "",
|
|
240
|
+
prompt: () => new Promise(() => {}),
|
|
241
|
+
kill: mock(() => {}),
|
|
242
|
+
cancel: mock(() => cancelPending),
|
|
243
|
+
};
|
|
244
|
+
const entry = injectSession(
|
|
245
|
+
manager,
|
|
246
|
+
"sess-race",
|
|
247
|
+
"parent-race",
|
|
248
|
+
proc as unknown as ReturnType<typeof fakeProcess>,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
const cancelPromise = (manager as any).cancel("sess-race");
|
|
252
|
+
// Synchronously after kicking off cancel — before the protocol cancel
|
|
253
|
+
// resolves — the status is already "cancelled".
|
|
254
|
+
expect(entry.state.status).toBe("cancelled");
|
|
255
|
+
expect(proc.cancel).toHaveBeenCalled();
|
|
256
|
+
|
|
257
|
+
resolveCancel();
|
|
258
|
+
await cancelPromise;
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("cancel restores the previous status when the protocol cancel throws", async () => {
|
|
262
|
+
// If process.cancel rejects, the session was not actually cancelled, so the
|
|
263
|
+
// status must roll back to running (else the live prompt's eventual settle
|
|
264
|
+
// is wrongly suppressed) and the error must propagate to the caller.
|
|
265
|
+
const manager = new AcpSessionManager(1);
|
|
266
|
+
const proc = {
|
|
267
|
+
markStderr: () => 0,
|
|
268
|
+
stderrSince: () => "",
|
|
269
|
+
prompt: () => new Promise(() => {}),
|
|
270
|
+
kill: mock(() => {}),
|
|
271
|
+
cancel: mock(() => Promise.reject(new Error("adapter down"))),
|
|
272
|
+
};
|
|
273
|
+
const entry = injectSession(
|
|
274
|
+
manager,
|
|
275
|
+
"sess-cancel-throw",
|
|
276
|
+
"parent-cancel-throw",
|
|
277
|
+
proc as unknown as ReturnType<typeof fakeProcess>,
|
|
278
|
+
);
|
|
279
|
+
// A prompt is still in flight; cancel must not tear it down on failure.
|
|
280
|
+
entry.currentPrompt = new Promise(() => {});
|
|
281
|
+
|
|
282
|
+
await expect((manager as any).cancel("sess-cancel-throw")).rejects.toThrow(
|
|
283
|
+
"adapter down",
|
|
284
|
+
);
|
|
285
|
+
expect(entry.state.status).toBe("running");
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
test("a superseded prompt does not notify the parent", async () => {
|
|
289
|
+
const manager = new AcpSessionManager(1);
|
|
290
|
+
const { conversation, enqueueMessage } = mockConversation();
|
|
291
|
+
setConversation("parent-stale", conversation);
|
|
292
|
+
registered.push("parent-stale");
|
|
293
|
+
|
|
294
|
+
const proc = fakeProcess(() => Promise.reject(new Error("boom")));
|
|
295
|
+
const entry = injectSession(manager, "sess-stale", "parent-stale", proc);
|
|
296
|
+
|
|
297
|
+
const bg = (manager as any).firePromptInBackground(
|
|
298
|
+
entry.state.id,
|
|
299
|
+
entry,
|
|
300
|
+
"proto-1",
|
|
301
|
+
"do it",
|
|
302
|
+
);
|
|
303
|
+
// A concurrent steer superseded this prompt: currentPrompt no longer
|
|
304
|
+
// points at it, so the whole catch body (including notify) is skipped.
|
|
305
|
+
entry.currentPrompt = null;
|
|
306
|
+
await bg;
|
|
307
|
+
|
|
308
|
+
expect(enqueueMessage).not.toHaveBeenCalled();
|
|
309
|
+
// The stale catch left the session in place (no teardown).
|
|
310
|
+
expect((manager.getStatus() as unknown[]).length).toBe(1);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
@@ -18,6 +18,7 @@ import { getLogger } from "../util/logger.js";
|
|
|
18
18
|
import { AcpAgentProcess } from "./agent-process.js";
|
|
19
19
|
import { resolveAgentWithAutoInstall } from "./auto-install.js";
|
|
20
20
|
import { VellumAcpClientHandler } from "./client-handler.js";
|
|
21
|
+
import { deriveFailureError } from "./failure-error.js";
|
|
21
22
|
import { prepareAgentEnv } from "./prepare-agent-env.js";
|
|
22
23
|
import { formatResolveFailure } from "./resolve-agent.js";
|
|
23
24
|
import { claudeResumeHint } from "./resume-hint.js";
|
|
@@ -739,9 +740,28 @@ export class AcpSessionManager {
|
|
|
739
740
|
if (!entry) {
|
|
740
741
|
throw new AcpSessionNotFoundError(acpSessionId);
|
|
741
742
|
}
|
|
742
|
-
|
|
743
|
+
// Mark cancelled BEFORE awaiting the protocol cancel. If the in-flight
|
|
744
|
+
// prompt rejects during this window, its catch handler must already see
|
|
745
|
+
// "cancelled" so it neither overwrites the status with "failed" nor wakes
|
|
746
|
+
// the parent — no model activity may follow a user stop.
|
|
747
|
+
const prevStatus = entry.state.status;
|
|
748
|
+
const prevCompletedAt = entry.state.completedAt;
|
|
743
749
|
entry.state.status = "cancelled";
|
|
744
750
|
entry.state.completedAt = Date.now();
|
|
751
|
+
try {
|
|
752
|
+
await entry.process.cancel(entry.state.acpSessionId);
|
|
753
|
+
} catch (err) {
|
|
754
|
+
// The protocol cancel failed (e.g. the adapter connection is already
|
|
755
|
+
// down): the session was NOT actually cancelled, so restore the prior
|
|
756
|
+
// status. Otherwise the still-running prompt's eventual completion would
|
|
757
|
+
// be wrongly suppressed and persisted as cancelled. Rethrow so the caller
|
|
758
|
+
// reports failure and the client rolls back its optimistic cancel.
|
|
759
|
+
if (this.sessions.get(acpSessionId) === entry) {
|
|
760
|
+
entry.state.status = prevStatus;
|
|
761
|
+
entry.state.completedAt = prevCompletedAt;
|
|
762
|
+
}
|
|
763
|
+
throw err;
|
|
764
|
+
}
|
|
745
765
|
// Re-check the map after the await: the in-flight prompt's handler may
|
|
746
766
|
// have already torn the session down while process.cancel was pending.
|
|
747
767
|
if (!entry.currentPrompt && this.sessions.get(acpSessionId) === entry) {
|
|
@@ -963,6 +983,10 @@ export class AcpSessionManager {
|
|
|
963
983
|
message: string,
|
|
964
984
|
): Promise<unknown> {
|
|
965
985
|
log.info({ acpSessionId, messageLen: message.length }, "ACP firing prompt");
|
|
986
|
+
// Checkpoint stderr before the prompt so a failure derives only from stderr
|
|
987
|
+
// this prompt produced — not lines retained from startup, resume, or an
|
|
988
|
+
// earlier (possibly cancelled) prompt.
|
|
989
|
+
const stderrMark = entry.process.markStderr();
|
|
966
990
|
const promptPromise = entry.process
|
|
967
991
|
.prompt(acpProtocolSessionId, message)
|
|
968
992
|
.then((response) => {
|
|
@@ -1023,55 +1047,22 @@ export class AcpSessionManager {
|
|
|
1023
1047
|
// kill the agent process.
|
|
1024
1048
|
this.teardownSession(acpSessionId, current);
|
|
1025
1049
|
|
|
1026
|
-
// Notify parent session so the LLM sees the agent's output
|
|
1050
|
+
// Notify parent session so the LLM sees the agent's output.
|
|
1027
1051
|
const agentLabel = current.state.agentId;
|
|
1028
1052
|
const responseText = current.clientHandler.responseText;
|
|
1029
|
-
const sessionId = current.state.acpSessionId;
|
|
1030
1053
|
const hint = claudeResumeHint(
|
|
1031
1054
|
current.command,
|
|
1032
1055
|
current.cwd,
|
|
1033
|
-
|
|
1056
|
+
current.state.acpSessionId,
|
|
1034
1057
|
);
|
|
1035
1058
|
const resumeHint = hint ? `\n\n${hint}` : "";
|
|
1036
|
-
|
|
1037
|
-
//
|
|
1038
|
-
//
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
};
|
|
1044
|
-
const parentConversation = findConversation(
|
|
1045
|
-
current.parentConversationId,
|
|
1046
|
-
);
|
|
1047
|
-
if (parentConversation) {
|
|
1048
|
-
const enqueueResult = parentConversation.enqueueMessage({
|
|
1049
|
-
content: notifyMessage,
|
|
1050
|
-
metadata: { acpNotification },
|
|
1051
|
-
});
|
|
1052
|
-
if (!enqueueResult.queued && !enqueueResult.rejected) {
|
|
1053
|
-
parentConversation
|
|
1054
|
-
.persistUserMessage({
|
|
1055
|
-
content: notifyMessage,
|
|
1056
|
-
metadata: { acpNotification },
|
|
1057
|
-
})
|
|
1058
|
-
.then(({ id: messageId }) =>
|
|
1059
|
-
parentConversation.runAgentLoop(notifyMessage, messageId),
|
|
1060
|
-
)
|
|
1061
|
-
.catch((err) => {
|
|
1062
|
-
log.error(
|
|
1063
|
-
{
|
|
1064
|
-
parentConversationId: current.parentConversationId,
|
|
1065
|
-
err,
|
|
1066
|
-
},
|
|
1067
|
-
"Failed to process ACP notification in parent",
|
|
1068
|
-
);
|
|
1069
|
-
});
|
|
1070
|
-
}
|
|
1071
|
-
} else {
|
|
1072
|
-
log.warn(
|
|
1073
|
-
{ parentConversationId: current.parentConversationId },
|
|
1074
|
-
"ACP agent finished but parent conversation not found",
|
|
1059
|
+
// Skip when cancelled: a prompt can win the cancel race by resolving
|
|
1060
|
+
// normally, but a user stop must not enqueue a completion and wake the
|
|
1061
|
+
// parent (mirrors the failure-path gate below).
|
|
1062
|
+
if (current.state.status !== "cancelled") {
|
|
1063
|
+
this.notifyParent(
|
|
1064
|
+
current,
|
|
1065
|
+
`[ACP agent "${agentLabel}" completed]\n\n${responseText}${resumeHint}`,
|
|
1075
1066
|
);
|
|
1076
1067
|
}
|
|
1077
1068
|
}
|
|
@@ -1081,17 +1072,26 @@ export class AcpSessionManager {
|
|
|
1081
1072
|
// Same guards: entry must exist, prompt must be current, and status
|
|
1082
1073
|
// must not have been set to "cancelled".
|
|
1083
1074
|
if (current && current.currentPrompt === promptPromise) {
|
|
1075
|
+
// The ack message is often a generic "Internal error"; recover the
|
|
1076
|
+
// real cause from the adapter's retained stderr.
|
|
1077
|
+
const failureMessage = deriveFailureError(
|
|
1078
|
+
err.message,
|
|
1079
|
+
current.process.stderrSince(stderrMark),
|
|
1080
|
+
);
|
|
1084
1081
|
if (current.state.status !== "cancelled") {
|
|
1085
1082
|
current.state.status = "failed";
|
|
1086
1083
|
current.state.completedAt = Date.now();
|
|
1087
|
-
current.state.error =
|
|
1084
|
+
current.state.error = failureMessage;
|
|
1088
1085
|
}
|
|
1089
1086
|
current.currentPrompt = null;
|
|
1090
|
-
log.error(
|
|
1087
|
+
log.error(
|
|
1088
|
+
{ acpSessionId, error: err.message, failureMessage },
|
|
1089
|
+
"ACP prompt failed",
|
|
1090
|
+
);
|
|
1091
1091
|
current.sendToVellum({
|
|
1092
1092
|
type: "acp_session_error",
|
|
1093
1093
|
acpSessionId,
|
|
1094
|
-
error:
|
|
1094
|
+
error: failureMessage,
|
|
1095
1095
|
});
|
|
1096
1096
|
|
|
1097
1097
|
// Persist the terminal row before teardown clears the buffer.
|
|
@@ -1099,12 +1099,68 @@ export class AcpSessionManager {
|
|
|
1099
1099
|
|
|
1100
1100
|
// Free the session slot and deny any pending permissions.
|
|
1101
1101
|
this.teardownSession(acpSessionId, current);
|
|
1102
|
+
|
|
1103
|
+
// Wake the parent with the failure (mirrors the success path) so
|
|
1104
|
+
// the assistant reports it instead of silently re-spawning. Skip
|
|
1105
|
+
// when cancelled: a user-cancelled run tears down silently and must
|
|
1106
|
+
// not inject a turn. teardownSession leaves state intact, so the
|
|
1107
|
+
// agentId read below is still valid.
|
|
1108
|
+
if (current.state.status !== "cancelled") {
|
|
1109
|
+
this.notifyParent(
|
|
1110
|
+
current,
|
|
1111
|
+
`[ACP agent "${current.state.agentId}" failed]\n\n${failureMessage}`,
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1102
1114
|
}
|
|
1103
1115
|
});
|
|
1104
1116
|
|
|
1105
1117
|
return promptPromise;
|
|
1106
1118
|
}
|
|
1107
1119
|
|
|
1120
|
+
/**
|
|
1121
|
+
* Injects an ACP run's outcome into its parent conversation. Shared by the
|
|
1122
|
+
* success and failure paths of firePromptInBackground so a hard failure
|
|
1123
|
+
* reaches the parent (and its inline card) exactly like a completion does.
|
|
1124
|
+
*
|
|
1125
|
+
* The message carries `acpNotification` metadata so the daemon skips its
|
|
1126
|
+
* user_message_echo and the client filters it from the rendered transcript —
|
|
1127
|
+
* the user sees the run through its inline card, not a raw chat turn, while
|
|
1128
|
+
* the LLM still receives the text.
|
|
1129
|
+
*
|
|
1130
|
+
* Reads `entry.state.acpSessionId`/`agentId`, which teardownSession leaves
|
|
1131
|
+
* intact, so callers may invoke this after tearing the session down.
|
|
1132
|
+
*/
|
|
1133
|
+
private notifyParent(entry: SessionEntry, message: string): void {
|
|
1134
|
+
const acpNotification = {
|
|
1135
|
+
acpSessionId: entry.state.acpSessionId,
|
|
1136
|
+
agent: entry.state.agentId,
|
|
1137
|
+
};
|
|
1138
|
+
const parentConversation = findConversation(entry.parentConversationId);
|
|
1139
|
+
if (!parentConversation) {
|
|
1140
|
+
log.warn(
|
|
1141
|
+
{ parentConversationId: entry.parentConversationId },
|
|
1142
|
+
"ACP agent finished but parent conversation not found",
|
|
1143
|
+
);
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
const enqueueResult = parentConversation.enqueueMessage({
|
|
1147
|
+
content: message,
|
|
1148
|
+
metadata: { acpNotification },
|
|
1149
|
+
});
|
|
1150
|
+
if (enqueueResult.queued || enqueueResult.rejected) return;
|
|
1151
|
+
parentConversation
|
|
1152
|
+
.persistUserMessage({ content: message, metadata: { acpNotification } })
|
|
1153
|
+
.then(({ id: messageId }) =>
|
|
1154
|
+
parentConversation.runAgentLoop(message, messageId),
|
|
1155
|
+
)
|
|
1156
|
+
.catch((err) => {
|
|
1157
|
+
log.error(
|
|
1158
|
+
{ parentConversationId: entry.parentConversationId, err },
|
|
1159
|
+
"Failed to process ACP notification in parent",
|
|
1160
|
+
);
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1108
1164
|
/**
|
|
1109
1165
|
* Kills all processes on shutdown. Also flags the manager as disposed so
|
|
1110
1166
|
* resumes that are mid-await when shutdown happens abort before spawning
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
compactAxTreeHistory,
|
|
5
|
+
escapeAxTreeContent,
|
|
6
|
+
} from "../context/outbound-sanitize.js";
|
|
3
7
|
import type { Message } from "../providers/types.js";
|
|
4
|
-
import { compactAxTreeHistory, escapeAxTreeContent } from "./loop.js";
|
|
5
8
|
|
|
6
9
|
// ---------------------------------------------------------------------------
|
|
7
10
|
// Helpers
|