@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
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound-request history sanitization shared by every provider call that
|
|
3
|
+
* sends conversation history: the agent loop's model calls and the
|
|
4
|
+
* compactor's summary calls. Each transform derives a sanitized projection of
|
|
5
|
+
* the outbound copy only — durable history keeps the rich originals, and every
|
|
6
|
+
* transform is idempotent so each send re-derives the same projection.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { stripHistoricalWebSearchResults } from "../daemon/web-search-history.js";
|
|
10
|
+
import type {
|
|
11
|
+
ContentBlock,
|
|
12
|
+
Message,
|
|
13
|
+
ToolResultContent,
|
|
14
|
+
} from "../providers/types.js";
|
|
15
|
+
|
|
16
|
+
/** Number of most-recent AX tree snapshots to keep in conversation history. */
|
|
17
|
+
const MAX_AX_TREES_IN_HISTORY = 2;
|
|
18
|
+
|
|
19
|
+
/** Regex that matches the `<ax-tree>...</ax-tree>` markers. */
|
|
20
|
+
const AX_TREE_PATTERN = /<ax-tree>[\s\S]*?<\/ax-tree>/g;
|
|
21
|
+
const AX_TREE_PLACEHOLDER = "<ax_tree_omitted />";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Escapes any literal `</ax-tree>` occurrences inside AX tree content so
|
|
25
|
+
* that the non-greedy compaction regex (`AX_TREE_PATTERN`) does not stop
|
|
26
|
+
* prematurely when the user happens to be viewing XML/HTML source that
|
|
27
|
+
* contains the closing tag. The escaped content does not need to be
|
|
28
|
+
* unescaped because compaction replaces the entire block with a placeholder.
|
|
29
|
+
*/
|
|
30
|
+
export function escapeAxTreeContent(content: string): string {
|
|
31
|
+
return content.replace(/<\/ax-tree>/gi, "</ax-tree>");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns a shallow copy of `messages` where all but the most recent
|
|
36
|
+
* `MAX_AX_TREES_IN_HISTORY` `<ax-tree>` blocks have been replaced with a
|
|
37
|
+
* short placeholder. This keeps the conversation context small so that
|
|
38
|
+
* TTFT does not grow linearly with step count in computer-use sessions.
|
|
39
|
+
*
|
|
40
|
+
* Counting is per-block, not per-message — a single user message can
|
|
41
|
+
* contain multiple tool_result blocks each with their own AX tree snapshot.
|
|
42
|
+
*/
|
|
43
|
+
export function compactAxTreeHistory(messages: Message[]): Message[] {
|
|
44
|
+
// Collect (messageIndex, blockIndex) for every tool_result block with <ax-tree>
|
|
45
|
+
const axBlocks: Array<{ msgIdx: number; blockIdx: number }> = [];
|
|
46
|
+
for (let i = 0; i < messages.length; i++) {
|
|
47
|
+
const msg = messages[i];
|
|
48
|
+
if (msg.role !== "user") {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
for (let j = 0; j < msg.content.length; j++) {
|
|
52
|
+
const block = msg.content[j];
|
|
53
|
+
if (
|
|
54
|
+
block.type === "tool_result" &&
|
|
55
|
+
typeof block.content === "string" &&
|
|
56
|
+
block.content.includes("<ax-tree>")
|
|
57
|
+
) {
|
|
58
|
+
axBlocks.push({ msgIdx: i, blockIdx: j });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (axBlocks.length <= MAX_AX_TREES_IN_HISTORY) {
|
|
64
|
+
return messages;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Build a set of "msgIdx:blockIdx" keys for blocks that should be stripped
|
|
68
|
+
const toStrip = new Set(
|
|
69
|
+
axBlocks
|
|
70
|
+
.slice(0, -MAX_AX_TREES_IN_HISTORY)
|
|
71
|
+
.map((b) => `${b.msgIdx}:${b.blockIdx}`),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return messages.map((msg, idx) => {
|
|
75
|
+
// Quick check: does this message have any blocks to strip?
|
|
76
|
+
const hasStripTarget = msg.content.some((_, j) =>
|
|
77
|
+
toStrip.has(`${idx}:${j}`),
|
|
78
|
+
);
|
|
79
|
+
if (!hasStripTarget) {
|
|
80
|
+
return msg;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
...msg,
|
|
85
|
+
content: msg.content.map((block, j) => {
|
|
86
|
+
if (
|
|
87
|
+
toStrip.has(`${idx}:${j}`) &&
|
|
88
|
+
block.type === "tool_result" &&
|
|
89
|
+
typeof block.content === "string"
|
|
90
|
+
) {
|
|
91
|
+
return {
|
|
92
|
+
...block,
|
|
93
|
+
content: block.content.replace(
|
|
94
|
+
AX_TREE_PATTERN,
|
|
95
|
+
AX_TREE_PLACEHOLDER,
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return block;
|
|
100
|
+
}),
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Strip image contentBlocks from all tool_result blocks except those in the
|
|
107
|
+
* most recent user message that contains tool_result blocks. This prevents
|
|
108
|
+
* screenshots from accumulating in the context window — each image is seen
|
|
109
|
+
* once by the LLM on the turn it was captured, then replaced with a text
|
|
110
|
+
* placeholder on subsequent turns.
|
|
111
|
+
*
|
|
112
|
+
* We target the last user message with tool_results (not just the last user
|
|
113
|
+
* message) because a plain-text user message may follow the tool-result
|
|
114
|
+
* turn. Using the last user message unconditionally would leave the most
|
|
115
|
+
* recent tool screenshots unprotected from stripping.
|
|
116
|
+
*/
|
|
117
|
+
function stripOldMediaBlocks(history: Message[]): Message[] {
|
|
118
|
+
// Find the last user message that contains tool_result blocks.
|
|
119
|
+
let lastToolResultUserIdx = -1;
|
|
120
|
+
for (let i = history.length - 1; i >= 0; i--) {
|
|
121
|
+
if (
|
|
122
|
+
history[i].role === "user" &&
|
|
123
|
+
history[i].content.some((b) => b.type === "tool_result")
|
|
124
|
+
) {
|
|
125
|
+
lastToolResultUserIdx = i;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return history.map((msg, idx) => {
|
|
131
|
+
// Keep the most recent tool-result user message intact (current turn)
|
|
132
|
+
if (idx === lastToolResultUserIdx || msg.role !== "user") {
|
|
133
|
+
return msg;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Check if any tool_result blocks carry embedded media (image or audio).
|
|
137
|
+
const isMedia = (cb: ContentBlock) =>
|
|
138
|
+
cb.type === "image" || cb.type === "file";
|
|
139
|
+
const hasMedia = msg.content.some(
|
|
140
|
+
(b) =>
|
|
141
|
+
b.type === "tool_result" &&
|
|
142
|
+
(b as ToolResultContent).contentBlocks?.some(isMedia),
|
|
143
|
+
);
|
|
144
|
+
if (!hasMedia) {
|
|
145
|
+
return msg;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Strip media from tool_result blocks, replacing with a text marker. The
|
|
149
|
+
// model already saw/heard the media in the turn it was captured; resending
|
|
150
|
+
// the bytes every turn (a 12 MB audio clip isn't optimized like images)
|
|
151
|
+
// bloats the request until compaction.
|
|
152
|
+
return {
|
|
153
|
+
...msg,
|
|
154
|
+
content: msg.content.map((b) => {
|
|
155
|
+
if (b.type !== "tool_result") {
|
|
156
|
+
return b;
|
|
157
|
+
}
|
|
158
|
+
const tr = b as ToolResultContent;
|
|
159
|
+
if (!tr.contentBlocks?.some(isMedia)) {
|
|
160
|
+
return b;
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
...tr,
|
|
164
|
+
contentBlocks: undefined,
|
|
165
|
+
content:
|
|
166
|
+
(tr.content || "") +
|
|
167
|
+
"\n[Media (image/audio) was captured and shown previously — binary data removed to save context.]",
|
|
168
|
+
};
|
|
169
|
+
}),
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Sanitize the outbound history immediately before a provider call, bundling
|
|
176
|
+
* the pre-send transforms applied to every request that carries conversation
|
|
177
|
+
* history:
|
|
178
|
+
* - {@link stripOldMediaBlocks} drops accumulated screenshot/audio bytes from
|
|
179
|
+
* older tool results — the model saw the media on the turn it was captured.
|
|
180
|
+
* Beyond context bloat, unstripped history can carry enough images to cross
|
|
181
|
+
* Anthropic's many-image threshold, where a stricter per-image dimension
|
|
182
|
+
* cap applies and a single large screenshot rejects the whole request.
|
|
183
|
+
* - {@link compactAxTreeHistory} collapses all but the most recent few
|
|
184
|
+
* `<ax-tree>` snapshots so TTFT does not grow linearly with step count.
|
|
185
|
+
* - {@link stripHistoricalWebSearchResults} converts historical
|
|
186
|
+
* `web_search_tool_result` blocks to text summaries; Anthropic's opaque
|
|
187
|
+
* `encrypted_content` tokens expire / are route-scoped, and replaying a stale
|
|
188
|
+
* one is rejected with `Invalid encrypted_content in search_result block`.
|
|
189
|
+
*
|
|
190
|
+
* Transforms the outbound copy only — the durable history keeps the rich
|
|
191
|
+
* originals and each send re-derives the sanitized projection (every transform
|
|
192
|
+
* is idempotent). Both the agent loop's model calls and the compactor's
|
|
193
|
+
* summary calls funnel through this bundle, so their request prefixes stay
|
|
194
|
+
* byte-aligned (the summary call reuses the agent's warm prompt cache) and
|
|
195
|
+
* oversized media and expired web-search tokens are guaranteed to be removed
|
|
196
|
+
* from every request.
|
|
197
|
+
*/
|
|
198
|
+
export function preModelCallSanitize(history: Message[]): Message[] {
|
|
199
|
+
const mediaStripped = stripOldMediaBlocks(history);
|
|
200
|
+
const axCompacted = compactAxTreeHistory(mediaStripped);
|
|
201
|
+
return stripHistoricalWebSearchResults(axCompacted).messages;
|
|
202
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abort contract when there is no live controller to signal.
|
|
3
|
+
*
|
|
4
|
+
* `abortConversation` signals `ctx.abortController?.abort()` and otherwise
|
|
5
|
+
* defers clearing the `processing` flag to the in-flight turn's `finally`.
|
|
6
|
+
* That deferral is only safe while a turn is actually live to reach its
|
|
7
|
+
* `finally`. The agent-loop `finally` nulls `abortController` *before* it
|
|
8
|
+
* clears the flag, and some paths set `processing` without ever installing a
|
|
9
|
+
* controller — so a conversation can be `isProcessing() === true` with a null
|
|
10
|
+
* `abortController`. In that state the old `?.abort()` was a silent no-op and
|
|
11
|
+
* nothing ever cleared the flag: every later submit was rejected with
|
|
12
|
+
* "already processing" and Stop did nothing.
|
|
13
|
+
*
|
|
14
|
+
* This pins the fix: when asked to abort while processing with no live
|
|
15
|
+
* controller, `abortConversation` force-clears the flag itself; when a
|
|
16
|
+
* controller IS live, it signals it and leaves the flag to the turn.
|
|
17
|
+
*/
|
|
18
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
19
|
+
|
|
20
|
+
// `conversation-lifecycle` transitively imports the messaging markdown
|
|
21
|
+
// renderers, which pull in `hast`/`mdast`/`remark`/`unified`. Those packages
|
|
22
|
+
// are declared in `assistant/package.json` but absent from this sandbox's
|
|
23
|
+
// partial node_modules install (CI has the full set). `abortConversation`
|
|
24
|
+
// never touches message rendering, so stub these leaf modules — the only ones
|
|
25
|
+
// importing the missing packages — with no-op named exports so the import
|
|
26
|
+
// graph resolves. Bun validates named imports statically, hence the explicit
|
|
27
|
+
// keys rather than a Proxy.
|
|
28
|
+
mock.module("../../messaging/content/parse.js", () => ({
|
|
29
|
+
parseMarkdown: () => ({}),
|
|
30
|
+
}));
|
|
31
|
+
mock.module("../../messaging/providers/slack/render.js", () => ({
|
|
32
|
+
renderSlackBlocks: () => undefined,
|
|
33
|
+
renderSlack: () => [],
|
|
34
|
+
}));
|
|
35
|
+
mock.module("../../messaging/providers/telegram-bot/render.js", () => ({
|
|
36
|
+
renderTelegramHtml: () => undefined,
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
const { abortConversation } = await import("../conversation-lifecycle.js");
|
|
40
|
+
import type { AbortContext } from "../conversation-lifecycle.js";
|
|
41
|
+
|
|
42
|
+
interface Harness {
|
|
43
|
+
ctx: AbortContext;
|
|
44
|
+
setProcessingCalls: boolean[];
|
|
45
|
+
prompterDisposed: () => boolean;
|
|
46
|
+
secretPrompterDisposed: () => boolean;
|
|
47
|
+
queueClearedCount: () => number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function makeContext(opts: {
|
|
51
|
+
processing: boolean;
|
|
52
|
+
controller: AbortController | null;
|
|
53
|
+
}): Harness {
|
|
54
|
+
let processing = opts.processing;
|
|
55
|
+
const setProcessingCalls: boolean[] = [];
|
|
56
|
+
let prompterDisposed = false;
|
|
57
|
+
let secretPrompterDisposed = false;
|
|
58
|
+
let queueCleared = 0;
|
|
59
|
+
|
|
60
|
+
const ctx = {
|
|
61
|
+
conversationId: "abort-null-controller-test",
|
|
62
|
+
isProcessing: () => processing,
|
|
63
|
+
setProcessing: (value: boolean) => {
|
|
64
|
+
setProcessingCalls.push(value);
|
|
65
|
+
processing = value;
|
|
66
|
+
},
|
|
67
|
+
abortController: opts.controller,
|
|
68
|
+
prompter: {
|
|
69
|
+
dispose: () => {
|
|
70
|
+
prompterDisposed = true;
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
secretPrompter: {
|
|
74
|
+
dispose: () => {
|
|
75
|
+
secretPrompterDisposed = true;
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
pendingSurfaceActions: new Map(),
|
|
79
|
+
surfaceActionRequestIds: new Set(),
|
|
80
|
+
surfaceState: new Map(),
|
|
81
|
+
accumulatedSurfaceState: new Map(),
|
|
82
|
+
queue: {
|
|
83
|
+
clear: () => {
|
|
84
|
+
queueCleared += 1;
|
|
85
|
+
},
|
|
86
|
+
[Symbol.iterator]: function* () {
|
|
87
|
+
// no queued messages
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
} as unknown as AbortContext;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
ctx,
|
|
94
|
+
setProcessingCalls,
|
|
95
|
+
prompterDisposed: () => prompterDisposed,
|
|
96
|
+
secretPrompterDisposed: () => secretPrompterDisposed,
|
|
97
|
+
queueClearedCount: () => queueCleared,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
describe("abortConversation", () => {
|
|
102
|
+
test("force-clears the flag when processing with no live controller", () => {
|
|
103
|
+
// GIVEN a conversation flagged processing but with no controller to signal
|
|
104
|
+
const h = makeContext({ processing: true, controller: null });
|
|
105
|
+
|
|
106
|
+
// WHEN an abort is requested
|
|
107
|
+
abortConversation(h.ctx);
|
|
108
|
+
|
|
109
|
+
// THEN the flag is force-cleared so the conversation is no longer wedged
|
|
110
|
+
expect(h.setProcessingCalls).toContain(false);
|
|
111
|
+
expect(h.ctx.isProcessing()).toBe(false);
|
|
112
|
+
// AND the rest of the teardown still ran
|
|
113
|
+
expect(h.prompterDisposed()).toBe(true);
|
|
114
|
+
expect(h.secretPrompterDisposed()).toBe(true);
|
|
115
|
+
expect(h.queueClearedCount()).toBe(1);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("signals a live controller and defers the flag to the turn's finally", () => {
|
|
119
|
+
// GIVEN a conversation with a live, un-aborted controller
|
|
120
|
+
const controller = new AbortController();
|
|
121
|
+
const h = makeContext({ processing: true, controller });
|
|
122
|
+
|
|
123
|
+
// WHEN an abort is requested
|
|
124
|
+
abortConversation(h.ctx);
|
|
125
|
+
|
|
126
|
+
// THEN the controller is signalled
|
|
127
|
+
expect(controller.signal.aborted).toBe(true);
|
|
128
|
+
// AND the flag is NOT force-cleared here — the turn's `finally` owns that
|
|
129
|
+
expect(h.setProcessingCalls).not.toContain(false);
|
|
130
|
+
expect(h.ctx.isProcessing()).toBe(true);
|
|
131
|
+
// AND the shared teardown still ran
|
|
132
|
+
expect(h.prompterDisposed()).toBe(true);
|
|
133
|
+
expect(h.queueClearedCount()).toBe(1);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("propagates the abort reason to the live controller", () => {
|
|
137
|
+
// GIVEN a live controller and an explicit abort reason
|
|
138
|
+
const controller = new AbortController();
|
|
139
|
+
const h = makeContext({ processing: true, controller });
|
|
140
|
+
let observedReason: unknown;
|
|
141
|
+
controller.signal.addEventListener("abort", () => {
|
|
142
|
+
observedReason = controller.signal.reason;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// WHEN aborting with no explicit reason (a default reason is synthesized)
|
|
146
|
+
abortConversation(h.ctx);
|
|
147
|
+
|
|
148
|
+
// THEN the controller's reason carries the tagged AbortReason
|
|
149
|
+
expect(observedReason).toBeDefined();
|
|
150
|
+
expect((observedReason as { kind?: string }).kind).toBe(
|
|
151
|
+
"preempted_by_new_message",
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("is a no-op when the conversation is not processing", () => {
|
|
156
|
+
// GIVEN a conversation that is not processing
|
|
157
|
+
const h = makeContext({ processing: false, controller: null });
|
|
158
|
+
|
|
159
|
+
// WHEN an abort is requested
|
|
160
|
+
abortConversation(h.ctx);
|
|
161
|
+
|
|
162
|
+
// THEN nothing is torn down and the flag is never touched
|
|
163
|
+
expect(h.setProcessingCalls).toEqual([]);
|
|
164
|
+
expect(h.prompterDisposed()).toBe(false);
|
|
165
|
+
expect(h.queueClearedCount()).toBe(0);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the per-chat plugin scope applied inside
|
|
3
|
+
* `createResolveToolsCallback`. When a conversation has an `enabledPlugins`
|
|
4
|
+
* set, only tools whose owning plugin id is in that set appear in the resolved
|
|
5
|
+
* per-turn tool list; core tools are unaffected. `null` (no per-chat
|
|
6
|
+
* restriction) leaves the list unchanged.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
10
|
+
|
|
11
|
+
import * as configLoader from "../../config/loader.js";
|
|
12
|
+
import type { AssistantConfig } from "../../config/schema.js";
|
|
13
|
+
import type { ToolDefinition } from "../../providers/types.js";
|
|
14
|
+
import {
|
|
15
|
+
__clearRegistryForTesting,
|
|
16
|
+
registerPluginTools,
|
|
17
|
+
} from "../../tools/registry.js";
|
|
18
|
+
import type { Tool } from "../../tools/types.js";
|
|
19
|
+
import { createResolveToolsCallback } from "../conversation-tool-setup.js";
|
|
20
|
+
|
|
21
|
+
type SkillProjectionContext =
|
|
22
|
+
import("../conversation-tool-setup.js").SkillProjectionContext;
|
|
23
|
+
type SkillProjectionCache =
|
|
24
|
+
import("../conversation-skill-tools.js").SkillProjectionCache;
|
|
25
|
+
|
|
26
|
+
function def(name: string): ToolDefinition {
|
|
27
|
+
return { name, description: name, input_schema: { type: "object" } };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function pluginTool(name: string): Tool {
|
|
31
|
+
return {
|
|
32
|
+
name,
|
|
33
|
+
description: name,
|
|
34
|
+
input_schema: def(name).input_schema,
|
|
35
|
+
} as unknown as Tool;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function makeCtx(
|
|
39
|
+
overrides: Partial<SkillProjectionContext> = {},
|
|
40
|
+
): SkillProjectionContext {
|
|
41
|
+
return {
|
|
42
|
+
skillProjectionState: new Map(),
|
|
43
|
+
skillProjectionCache: { fingerprints: new Map() } as SkillProjectionCache,
|
|
44
|
+
coreToolNames: new Set<string>(),
|
|
45
|
+
toolsDisabledDepth: 0,
|
|
46
|
+
...overrides,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let getConfigSpy: ReturnType<typeof spyOn> | undefined;
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
__clearRegistryForTesting();
|
|
54
|
+
// Resolver reads getConfig().tools.exclude; stub to an empty exclude so the
|
|
55
|
+
// test isolates the plugin-scope filter.
|
|
56
|
+
const stub: Partial<AssistantConfig> = { tools: { exclude: [] } };
|
|
57
|
+
getConfigSpy = spyOn(configLoader, "getConfig").mockReturnValue(
|
|
58
|
+
stub as AssistantConfig,
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
getConfigSpy?.mockRestore();
|
|
64
|
+
getConfigSpy = undefined;
|
|
65
|
+
__clearRegistryForTesting();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe("createResolveToolsCallback — per-chat plugin scope", () => {
|
|
69
|
+
test("set {a} keeps plugin a's tools and core tools, drops plugin b's", () => {
|
|
70
|
+
registerPluginTools("a", [pluginTool("a_tool")]);
|
|
71
|
+
registerPluginTools("b", [pluginTool("b_tool")]);
|
|
72
|
+
|
|
73
|
+
const resolver = createResolveToolsCallback(
|
|
74
|
+
[def("file_read")],
|
|
75
|
+
makeCtx({ enabledPlugins: ["a"] }),
|
|
76
|
+
);
|
|
77
|
+
const names = resolver!([]).map((d) => d.name);
|
|
78
|
+
|
|
79
|
+
expect(names).toContain("a_tool");
|
|
80
|
+
expect(names).toContain("file_read");
|
|
81
|
+
expect(names).not.toContain("b_tool");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("null scope leaves all plugin tools in the resolved list", () => {
|
|
85
|
+
registerPluginTools("a", [pluginTool("a_tool")]);
|
|
86
|
+
registerPluginTools("b", [pluginTool("b_tool")]);
|
|
87
|
+
|
|
88
|
+
const resolver = createResolveToolsCallback(
|
|
89
|
+
[def("file_read")],
|
|
90
|
+
makeCtx({ enabledPlugins: null }),
|
|
91
|
+
);
|
|
92
|
+
const names = resolver!([]).map((d) => d.name);
|
|
93
|
+
|
|
94
|
+
expect(names).toContain("a_tool");
|
|
95
|
+
expect(names).toContain("b_tool");
|
|
96
|
+
expect(names).toContain("file_read");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("absent enabledPlugins behaves like null (no restriction)", () => {
|
|
100
|
+
registerPluginTools("a", [pluginTool("a_tool")]);
|
|
101
|
+
registerPluginTools("b", [pluginTool("b_tool")]);
|
|
102
|
+
|
|
103
|
+
const resolver = createResolveToolsCallback([def("file_read")], makeCtx());
|
|
104
|
+
const names = resolver!([]).map((d) => d.name);
|
|
105
|
+
|
|
106
|
+
expect(names).toContain("a_tool");
|
|
107
|
+
expect(names).toContain("b_tool");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("empty scope drops every plugin tool but keeps core tools", () => {
|
|
111
|
+
registerPluginTools("a", [pluginTool("a_tool")]);
|
|
112
|
+
|
|
113
|
+
const resolver = createResolveToolsCallback(
|
|
114
|
+
[def("file_read")],
|
|
115
|
+
makeCtx({ enabledPlugins: [] }),
|
|
116
|
+
);
|
|
117
|
+
const names = resolver!([]).map((d) => d.name);
|
|
118
|
+
|
|
119
|
+
expect(names).not.toContain("a_tool");
|
|
120
|
+
expect(names).toContain("file_read");
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, mock, test } from "bun:test";
|
|
1
|
+
import { afterAll, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import type { AssistantConfig } from "../../config/types.js";
|
|
4
4
|
import type { ReconcileAction } from "../../persistence/embeddings/reconcile-decision.js";
|
|
@@ -7,6 +7,52 @@ import {
|
|
|
7
7
|
reconcileEmbeddingIdentity,
|
|
8
8
|
} from "../embedding-reconcile.js";
|
|
9
9
|
|
|
10
|
+
// Snapshot the real collaborator modules BEFORE any `mock.module` stub is
|
|
11
|
+
// installed in `withDefaultDepsMocks`. `mock.module` is process-global and Bun
|
|
12
|
+
// does not revert it (neither `mock.restore()` nor an `afterAll` re-mock) for
|
|
13
|
+
// test files that load LATER in the same `bun test` run — notably the v3
|
|
14
|
+
// `section-dense-store` suite, which imports the real module and asserts on its
|
|
15
|
+
// create/index call counts. So every stub below DELEGATES to the real
|
|
16
|
+
// implementation unless this file's default-deps tests are actively running
|
|
17
|
+
// (`defaultDepsMockActive`, cleared in the `afterAll` below). Mirrors
|
|
18
|
+
// `plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts`.
|
|
19
|
+
//
|
|
20
|
+
// Snapshot into plain objects NOW: a module namespace is a live view, so reading
|
|
21
|
+
// a real export AFTER its stub is installed would resolve back to the stub.
|
|
22
|
+
const realJobsStore = { ...(await import("../../persistence/jobs-store.js")) };
|
|
23
|
+
const realMemoryV3Gate = {
|
|
24
|
+
...(await import("../../config/memory-v3-gate.js")),
|
|
25
|
+
};
|
|
26
|
+
const realV2Qdrant = {
|
|
27
|
+
...(await import("../../plugins/defaults/memory/v2/qdrant.js")),
|
|
28
|
+
};
|
|
29
|
+
const realLoader = { ...(await import("../../config/loader.js")) };
|
|
30
|
+
const realSectionDenseStore = {
|
|
31
|
+
...(await import("../../plugins/defaults/memory/v3/section-dense-store.js")),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
let defaultDepsMockActive = false;
|
|
35
|
+
|
|
36
|
+
afterAll(() => {
|
|
37
|
+
// Deactivate the delegating stubs so sibling suites that load later in a
|
|
38
|
+
// shared `bun test` process (e.g. section-dense-store.test.ts) observe the
|
|
39
|
+
// real modules instead of these spies.
|
|
40
|
+
defaultDepsMockActive = false;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Wrap a collaborator export so it routes to `active` while this file's
|
|
45
|
+
* default-deps tests run and to the real implementation otherwise. The choice is
|
|
46
|
+
* made at CALL time, so the stub keeps delegating to the real module for sibling
|
|
47
|
+
* suites that captured their import bindings while it was installed.
|
|
48
|
+
*/
|
|
49
|
+
function delegate<F extends (...args: never[]) => unknown>(
|
|
50
|
+
active: (...args: Parameters<F>) => unknown,
|
|
51
|
+
real: F,
|
|
52
|
+
): (...args: Parameters<F>) => unknown {
|
|
53
|
+
return (...args) => (defaultDepsMockActive ? active(...args) : real(...args));
|
|
54
|
+
}
|
|
55
|
+
|
|
10
56
|
function fakeConfig(
|
|
11
57
|
provider = "auto",
|
|
12
58
|
opts: { enabled?: boolean; v2Enabled?: boolean } = {},
|
|
@@ -270,10 +316,16 @@ describe("reconcileEmbeddingIdentity", () => {
|
|
|
270
316
|
// section-collection lifecycle without touching Qdrant, a backend, or config I/O.
|
|
271
317
|
|
|
272
318
|
/**
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
319
|
+
* Install the collaborator-module stubs `defaultDeps` pulls in, then re-import
|
|
320
|
+
* the module under test so its default deps close over them. Returns the spies
|
|
321
|
+
* plus a `defaultDeps` factory bound to the re-imported module.
|
|
322
|
+
*
|
|
323
|
+
* Each stub DELEGATES to the real module unless this file's default-deps tests
|
|
324
|
+
* are actively running (`defaultDepsMockActive`, set here and cleared in the
|
|
325
|
+
* file-level `afterAll`), so the process-global `mock.module` overrides do not
|
|
326
|
+
* leak into sibling suites that load later in the same `bun test` run. The
|
|
327
|
+
* delegation is decided at CALL time, so it stays correct regardless of when a
|
|
328
|
+
* later file captured its import bindings.
|
|
277
329
|
*/
|
|
278
330
|
async function withDefaultDepsMocks(opts: {
|
|
279
331
|
v3Live: boolean;
|
|
@@ -289,28 +341,59 @@ async function withDefaultDepsMocks(opts: {
|
|
|
289
341
|
recreateConceptPageCollection: mock(async () => {}),
|
|
290
342
|
};
|
|
291
343
|
|
|
344
|
+
defaultDepsMockActive = true;
|
|
345
|
+
|
|
292
346
|
mock.module("../../persistence/jobs-store.js", () => ({
|
|
293
|
-
|
|
294
|
-
|
|
347
|
+
...realJobsStore,
|
|
348
|
+
enqueueMemoryJob: delegate(
|
|
349
|
+
spies.enqueueMemoryJob,
|
|
350
|
+
realJobsStore.enqueueMemoryJob,
|
|
351
|
+
),
|
|
352
|
+
hasActiveJobOfType: delegate(
|
|
353
|
+
spies.hasActiveJobOfType,
|
|
354
|
+
realJobsStore.hasActiveJobOfType,
|
|
355
|
+
),
|
|
295
356
|
}));
|
|
296
357
|
mock.module("../../config/memory-v3-gate.js", () => ({
|
|
297
|
-
|
|
358
|
+
...realMemoryV3Gate,
|
|
359
|
+
isMemoryV3Live: delegate(
|
|
360
|
+
() => opts.v3Live,
|
|
361
|
+
realMemoryV3Gate.isMemoryV3Live,
|
|
362
|
+
),
|
|
298
363
|
}));
|
|
299
364
|
mock.module("../../plugins/defaults/memory/v2/qdrant.js", () => ({
|
|
300
|
-
|
|
301
|
-
|
|
365
|
+
...realV2Qdrant,
|
|
366
|
+
ensureConceptPageCollection: delegate(
|
|
367
|
+
spies.ensureConceptPageCollection,
|
|
368
|
+
realV2Qdrant.ensureConceptPageCollection,
|
|
369
|
+
),
|
|
370
|
+
recreateConceptPageCollection: delegate(
|
|
371
|
+
spies.recreateConceptPageCollection,
|
|
372
|
+
realV2Qdrant.recreateConceptPageCollection,
|
|
373
|
+
),
|
|
302
374
|
}));
|
|
303
375
|
mock.module("../../config/loader.js", () => ({
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
376
|
+
...realLoader,
|
|
377
|
+
loadRawConfig: delegate(() => ({}), realLoader.loadRawConfig),
|
|
378
|
+
saveRawConfig: delegate(() => undefined, realLoader.saveRawConfig),
|
|
379
|
+
setNestedValue: delegate(() => undefined, realLoader.setNestedValue),
|
|
380
|
+
invalidateConfigCache: delegate(
|
|
381
|
+
() => undefined,
|
|
382
|
+
realLoader.invalidateConfigCache,
|
|
383
|
+
),
|
|
308
384
|
}));
|
|
309
385
|
mock.module(
|
|
310
386
|
"../../plugins/defaults/memory/v3/section-dense-store.js",
|
|
311
387
|
() => ({
|
|
312
|
-
|
|
313
|
-
|
|
388
|
+
...realSectionDenseStore,
|
|
389
|
+
ensureSectionCollection: delegate(
|
|
390
|
+
spies.ensureSectionCollection,
|
|
391
|
+
realSectionDenseStore.ensureSectionCollection,
|
|
392
|
+
),
|
|
393
|
+
recreateSectionCollection: delegate(
|
|
394
|
+
spies.recreateSectionCollection,
|
|
395
|
+
realSectionDenseStore.recreateSectionCollection,
|
|
396
|
+
),
|
|
314
397
|
}),
|
|
315
398
|
);
|
|
316
399
|
|