@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
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* A plugin may declare an `injectors` array on its {@link Plugin} shape; after
|
|
5
5
|
* its model-visible surface is wired and before `init()` succeeds, bootstrap
|
|
6
6
|
* registers each entry into the global injector registry via
|
|
7
|
-
* {@link registerPluginInjectors}
|
|
7
|
+
* {@link registerPluginInjectors}. A plugin rolled back after a failed bring-up
|
|
8
|
+
* (or uninstalled/disabled at runtime) is unregistered via
|
|
8
9
|
* {@link unregisterPluginInjectors}. This mirrors the tools/routes contribution
|
|
9
10
|
* path (see `plugin-route-contribution.test.ts`).
|
|
10
11
|
*
|
|
@@ -12,8 +13,7 @@
|
|
|
12
13
|
*
|
|
13
14
|
* 1. Bootstrap → the contributed injector appears in
|
|
14
15
|
* {@link getRegisteredInjectors}, and `init()` ran.
|
|
15
|
-
* 2.
|
|
16
|
-
* 3. A plugin without `injectors` bootstraps and shuts down cleanly.
|
|
16
|
+
* 2. A plugin without `injectors` bootstraps cleanly.
|
|
17
17
|
*
|
|
18
18
|
* `getRegisteredInjectors()` after `bootstrapPlugins()` also contains the
|
|
19
19
|
* first-party defaults (bootstrap registers `default-memory`'s injectors), so
|
|
@@ -26,7 +26,6 @@ import { join } from "node:path";
|
|
|
26
26
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
27
27
|
|
|
28
28
|
import { bootstrapPlugins } from "../daemon/external-plugins-bootstrap.js";
|
|
29
|
-
import { runShutdownHooks } from "../daemon/shutdown-registry.js";
|
|
30
29
|
import {
|
|
31
30
|
clearInjectorRegistry,
|
|
32
31
|
getRegisteredInjectors,
|
|
@@ -122,27 +121,12 @@ describe("plugin injector contributions", () => {
|
|
|
122
121
|
expect(isTestInjectorRegistered()).toBe(true);
|
|
123
122
|
});
|
|
124
123
|
|
|
125
|
-
test("
|
|
126
|
-
registerPlugin(
|
|
127
|
-
buildPlugin("injector-plugin", { injectors: [makeTestInjector()] }),
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
await bootstrapPlugins();
|
|
131
|
-
expect(isTestInjectorRegistered()).toBe(true);
|
|
132
|
-
|
|
133
|
-
// Shutdown runs the reverse-order teardown hook registered by bootstrap.
|
|
134
|
-
await runShutdownHooks("test-shutdown");
|
|
135
|
-
|
|
136
|
-
expect(isTestInjectorRegistered()).toBe(false);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("plugin with no injectors bootstraps and shuts down cleanly", async () => {
|
|
124
|
+
test("plugin with no injectors bootstraps cleanly", async () => {
|
|
140
125
|
// Declaring no `injectors` field is the common case; bootstrap must skip
|
|
141
126
|
// injector handling entirely (the guard is `if plugin.injectors && length`).
|
|
142
127
|
registerPlugin(buildPlugin("no-injectors-plugin", { async init() {} }));
|
|
143
128
|
|
|
144
129
|
await bootstrapPlugins();
|
|
145
|
-
await runShutdownHooks("test-shutdown");
|
|
146
130
|
|
|
147
131
|
expect(isTestInjectorRegistered()).toBe(false);
|
|
148
132
|
});
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test } from "bun:test";
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
// Stub the conversation scope resolver so the pipeline's conversationId-based
|
|
4
|
+
// scoping can be exercised without a live conversation or DB row.
|
|
5
|
+
const resolveScopeMock = mock(
|
|
6
|
+
(_conversationId: string): Set<string> | null => null,
|
|
7
|
+
);
|
|
8
|
+
mock.module("../daemon/conversation-plugin-scope.js", () => ({
|
|
9
|
+
resolveConversationPluginScope: (id: string) => resolveScopeMock(id),
|
|
10
|
+
}));
|
|
2
11
|
|
|
3
12
|
import { runHook } from "../plugins/pipeline.js";
|
|
4
13
|
import {
|
|
@@ -8,6 +17,8 @@ import {
|
|
|
8
17
|
|
|
9
18
|
beforeEach(() => {
|
|
10
19
|
resetPluginRegistryForTests();
|
|
20
|
+
resolveScopeMock.mockReset();
|
|
21
|
+
resolveScopeMock.mockImplementation(() => null);
|
|
11
22
|
});
|
|
12
23
|
|
|
13
24
|
describe("plugin pipeline", () => {
|
|
@@ -94,3 +105,54 @@ describe("plugin pipeline", () => {
|
|
|
94
105
|
expect(result.items).toEqual(["first", "final"]);
|
|
95
106
|
});
|
|
96
107
|
});
|
|
108
|
+
|
|
109
|
+
describe("plugin pipeline — per-conversation scope", () => {
|
|
110
|
+
function registerSeenHook(name: string) {
|
|
111
|
+
registerPlugin({
|
|
112
|
+
manifest: { name, version: "1.0.0" },
|
|
113
|
+
hooks: {
|
|
114
|
+
"user-prompt-submit": async (ctx: { seen: string[] }) => {
|
|
115
|
+
ctx.seen.push(name);
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
test("scopes hooks to the resolved set when the context has a conversationId", async () => {
|
|
122
|
+
registerSeenHook("in-scope");
|
|
123
|
+
registerSeenHook("out-scope");
|
|
124
|
+
resolveScopeMock.mockImplementation((conversationId: string) =>
|
|
125
|
+
conversationId === "c1" ? new Set(["in-scope"]) : null,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// A context carrying conversationId resolves the scope and skips the
|
|
129
|
+
// out-of-scope plugin's hook.
|
|
130
|
+
const scoped = await runHook<{ conversationId: string; seen: string[] }>(
|
|
131
|
+
"user-prompt-submit",
|
|
132
|
+
{ conversationId: "c1", seen: [] },
|
|
133
|
+
);
|
|
134
|
+
expect(scoped.seen).toEqual(["in-scope"]);
|
|
135
|
+
expect(resolveScopeMock).toHaveBeenCalledWith("c1");
|
|
136
|
+
|
|
137
|
+
// A context without a conversationId is never resolved and imposes no
|
|
138
|
+
// restriction.
|
|
139
|
+
resolveScopeMock.mockClear();
|
|
140
|
+
const unscoped = await runHook<{ seen: string[] }>("user-prompt-submit", {
|
|
141
|
+
seen: [],
|
|
142
|
+
});
|
|
143
|
+
expect(unscoped.seen).toEqual(["in-scope", "out-scope"]);
|
|
144
|
+
expect(resolveScopeMock).not.toHaveBeenCalled();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("imposes no restriction when the resolver returns null", async () => {
|
|
148
|
+
registerSeenHook("plugin-a");
|
|
149
|
+
registerSeenHook("plugin-b");
|
|
150
|
+
resolveScopeMock.mockImplementation(() => null);
|
|
151
|
+
|
|
152
|
+
const result = await runHook<{ conversationId: string; seen: string[] }>(
|
|
153
|
+
"user-prompt-submit",
|
|
154
|
+
{ conversationId: "c1", seen: [] },
|
|
155
|
+
);
|
|
156
|
+
expect(result.seen).toEqual(["plugin-a", "plugin-b"]);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A plugin may declare a `routes` array on its {@link Plugin} shape; after
|
|
5
5
|
* `init()` succeeds, bootstrap wires each entry into the skill-route registry
|
|
6
|
-
* via {@link registerSkillRoute}
|
|
7
|
-
* it receives back
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
6
|
+
* via {@link registerSkillRoute} and retains the opaque {@link SkillRouteHandle}
|
|
7
|
+
* it receives back. A plugin rolled back after a failed bring-up (or a user
|
|
8
|
+
* plugin uninstalled/disabled at runtime) is unregistered with that exact handle
|
|
9
|
+
* via {@link unregisterSkillRoute}. Handle-keyed unregistration ensures that two
|
|
10
|
+
* owners (e.g. a plugin and a skill) that legitimately register the same regex
|
|
11
|
+
* cannot have one owner's teardown silently evict another owner's route. At
|
|
12
|
+
* daemon shutdown the plugins' `shutdown` hooks fire through the unified
|
|
13
|
+
* `runHook(HOOKS.SHUTDOWN, …)` pipeline (surfaces are not unregistered — the
|
|
14
|
+
* process is exiting).
|
|
13
15
|
*
|
|
14
16
|
* The registry doesn't own HTTP itself — the tests here exercise:
|
|
15
17
|
*
|
|
16
18
|
* 1. Bootstrap → `registerSkillRoute` → `matchSkillRoute` returns the plugin's
|
|
17
19
|
* handler, and the handler responds as expected.
|
|
18
|
-
* 2.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* 4.
|
|
22
|
-
* each plugin's shutdown only removes its own route — the other plugin's
|
|
23
|
-
* route stays live until its own teardown runs.
|
|
20
|
+
* 2. Plugins without `routes` (or with an empty array) bootstrap cleanly.
|
|
21
|
+
* 3. Handle-keyed unregistration: unregistering one route's handle leaves a
|
|
22
|
+
* sibling's identical-pattern route live until its own handle is dropped.
|
|
23
|
+
* 4. Every contributing plugin's `shutdown` hook fires via `runHook`.
|
|
24
24
|
*
|
|
25
25
|
* `resetPluginRegistryForTests()` isolates plugin-registry state and
|
|
26
26
|
* `resetSkillRoutesForTests()` isolates skill-route-registry state between
|
|
@@ -33,7 +33,8 @@ import { join } from "node:path";
|
|
|
33
33
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
34
34
|
|
|
35
35
|
import { bootstrapPlugins } from "../daemon/external-plugins-bootstrap.js";
|
|
36
|
-
import {
|
|
36
|
+
import { HOOKS } from "../plugin-api/constants.js";
|
|
37
|
+
import { runHook } from "../plugins/pipeline.js";
|
|
37
38
|
import {
|
|
38
39
|
registerPlugin,
|
|
39
40
|
resetPluginRegistryForTests,
|
|
@@ -41,9 +42,10 @@ import {
|
|
|
41
42
|
import type { InitContext, Plugin } from "../plugins/types.js";
|
|
42
43
|
import {
|
|
43
44
|
matchSkillRoute,
|
|
45
|
+
registerSkillRoute,
|
|
44
46
|
resetSkillRoutesForTests,
|
|
45
47
|
type SkillRoute,
|
|
46
|
-
|
|
48
|
+
unregisterSkillRoute,
|
|
47
49
|
} from "../runtime/skill-route-registry.js";
|
|
48
50
|
|
|
49
51
|
// Redirect plugin storage creation into a per-process temp tree so the test
|
|
@@ -147,96 +149,59 @@ describe("plugin route contributions", () => {
|
|
|
147
149
|
expect(await res.text()).toBe("echo");
|
|
148
150
|
});
|
|
149
151
|
|
|
150
|
-
test("
|
|
151
|
-
const route: SkillRoute = {
|
|
152
|
-
pattern: echoPattern,
|
|
153
|
-
methods: ["GET"],
|
|
154
|
-
handler: async () => new Response("echo", { status: 200 }),
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
registerPlugin(buildPlugin("echo-plugin", { routes: [route] }));
|
|
158
|
-
|
|
159
|
-
await bootstrapPlugins();
|
|
160
|
-
|
|
161
|
-
// Sanity: route is live after bootstrap.
|
|
162
|
-
expect(matchSkillRoute("/_plugin/echo", "GET")).not.toBeNull();
|
|
163
|
-
|
|
164
|
-
// Shutdown runs the reverse-order teardown hook registered by bootstrap.
|
|
165
|
-
await runShutdownHooks("test-shutdown");
|
|
166
|
-
|
|
167
|
-
// Route is gone — matchSkillRoute returns null because no pattern
|
|
168
|
-
// matches the path at all anymore.
|
|
169
|
-
expect(matchSkillRoute("/_plugin/echo", "GET")).toBeNull();
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
test("plugin with no routes bootstraps and shuts down cleanly", async () => {
|
|
152
|
+
test("plugin with no routes bootstraps and tears down cleanly", async () => {
|
|
173
153
|
// Declaring no `routes` field is the common case; bootstrap must skip
|
|
174
154
|
// route handling entirely (the guard is `if plugin.routes && length > 0`).
|
|
175
155
|
registerPlugin(buildPlugin("no-routes-plugin", { async init() {} }));
|
|
176
156
|
|
|
177
157
|
await bootstrapPlugins();
|
|
178
|
-
await
|
|
158
|
+
await runHook(HOOKS.SHUTDOWN, {
|
|
159
|
+
assistantVersion: "test",
|
|
160
|
+
reason: "shutdown",
|
|
161
|
+
});
|
|
179
162
|
|
|
180
163
|
// Nothing to verify beyond "neither throws" — an empty `routes` must not
|
|
181
164
|
// regress existing no-op bootstrap semantics.
|
|
182
165
|
expect(true).toBe(true);
|
|
183
166
|
});
|
|
184
167
|
|
|
185
|
-
test("
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
},
|
|
205
|
-
}),
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
await bootstrapPlugins();
|
|
168
|
+
test("unregistering one route handle leaves a sibling's identical-pattern route live", async () => {
|
|
169
|
+
// Regression for the reviewer-flagged invariant: keying unregistration on
|
|
170
|
+
// `pattern.source + flags` would let one owner's teardown drop another
|
|
171
|
+
// owner's route when both declared regex with identical text. The plugin
|
|
172
|
+
// surface teardown unregisters routes by the opaque handle retained at
|
|
173
|
+
// registration time (`unregisterSkillRoute(handle)`), so that is the
|
|
174
|
+
// mechanism keeping sibling routes intact. Exercise it directly: two routes
|
|
175
|
+
// with byte-identical patterns, drop one handle, and the other must still
|
|
176
|
+
// match until its own handle is dropped too.
|
|
177
|
+
const handleA = registerSkillRoute({
|
|
178
|
+
pattern: /^\/_plugin\/echo$/,
|
|
179
|
+
methods: ["GET"],
|
|
180
|
+
handler: async () => new Response("a", { status: 200 }),
|
|
181
|
+
});
|
|
182
|
+
const handleB = registerSkillRoute({
|
|
183
|
+
pattern: /^\/_plugin\/echo$/,
|
|
184
|
+
methods: ["GET"],
|
|
185
|
+
handler: async () => new Response("b", { status: 200 }),
|
|
186
|
+
});
|
|
209
187
|
|
|
210
|
-
|
|
211
|
-
// different subsystem calling `resetSkillRoutesForTests` or a hot-reload
|
|
212
|
-
// flow clearing the registry. The plugin's retained handle is now stale.
|
|
213
|
-
resetSkillRoutesForTests();
|
|
188
|
+
expect(matchSkillRoute("/_plugin/echo", "GET")).not.toBeNull();
|
|
214
189
|
|
|
215
|
-
|
|
190
|
+
// Drop B (reverse-order teardown drops the last-registered owner first).
|
|
191
|
+
expect(unregisterSkillRoute(handleB)).toBe(true);
|
|
192
|
+
// A's identical-pattern route must still be live.
|
|
193
|
+
expect(matchSkillRoute("/_plugin/echo", "GET")).not.toBeNull();
|
|
216
194
|
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
expect(
|
|
195
|
+
// Only once A's own handle is dropped does the route disappear.
|
|
196
|
+
expect(unregisterSkillRoute(handleA)).toBe(true);
|
|
197
|
+
expect(matchSkillRoute("/_plugin/echo", "GET")).toBeNull();
|
|
220
198
|
});
|
|
221
199
|
|
|
222
|
-
test("
|
|
223
|
-
//
|
|
224
|
-
// `
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
//
|
|
228
|
-
// We simulate this by wiring two plugins that both contribute a route
|
|
229
|
-
// matching `/^\/_plugin\/echo$/`. Teardown runs in reverse registration
|
|
230
|
-
// order, so plugin-B is torn down first; plugin-A's route must still
|
|
231
|
-
// match afterwards, and only disappear once plugin-A's own teardown
|
|
232
|
-
// runs.
|
|
233
|
-
let pluginAShutdown = false;
|
|
234
|
-
let pluginBShutdown = false;
|
|
235
|
-
// Capture the match result from inside plugin-B's onShutdown so assertions
|
|
236
|
-
// run after runShutdownHooks returns. teardownPlugin wraps onShutdown in a
|
|
237
|
-
// try/catch that swallows thrown assertion errors, so asserting inline
|
|
238
|
-
// would let a failing match silently pass the test.
|
|
239
|
-
let pluginBOnShutdownMatch: SkillRouteMatch | null = null;
|
|
200
|
+
test("every contributing plugin's shutdown hook fires through the runHook pipeline", async () => {
|
|
201
|
+
// At daemon shutdown the plugins' `shutdown` hooks fire through the unified
|
|
202
|
+
// `runHook` pipeline — the same dispatch path every other lifecycle hook
|
|
203
|
+
// uses. Two plugins prove each one's hook fires exactly once.
|
|
204
|
+
const pluginsThatShutDown: string[] = [];
|
|
240
205
|
|
|
241
206
|
registerPlugin(
|
|
242
207
|
buildPlugin("plugin-a", {
|
|
@@ -248,16 +213,10 @@ describe("plugin route contributions", () => {
|
|
|
248
213
|
},
|
|
249
214
|
],
|
|
250
215
|
async onShutdown() {
|
|
251
|
-
|
|
252
|
-
// down — but plugin-A's route must still be live because
|
|
253
|
-
// `onShutdown` fires *after* the route-unregister step for this
|
|
254
|
-
// plugin but *before* it leaves teardownPlugin. We check liveness
|
|
255
|
-
// from plugin-B's teardown instead (see below).
|
|
256
|
-
pluginAShutdown = true;
|
|
216
|
+
pluginsThatShutDown.push("plugin-a");
|
|
257
217
|
},
|
|
258
218
|
}),
|
|
259
219
|
);
|
|
260
|
-
|
|
261
220
|
registerPlugin(
|
|
262
221
|
buildPlugin("plugin-b", {
|
|
263
222
|
routes: [
|
|
@@ -268,31 +227,19 @@ describe("plugin route contributions", () => {
|
|
|
268
227
|
},
|
|
269
228
|
],
|
|
270
229
|
async onShutdown() {
|
|
271
|
-
|
|
272
|
-
// this fires, but plugin-A's route is still live — it only gets
|
|
273
|
-
// torn down after this hook returns and the loop moves on to
|
|
274
|
-
// plugin-A. Confirm the registry still has a matching route.
|
|
275
|
-
pluginBShutdown = true;
|
|
276
|
-
pluginBOnShutdownMatch = matchSkillRoute("/_plugin/echo", "GET");
|
|
230
|
+
pluginsThatShutDown.push("plugin-b");
|
|
277
231
|
},
|
|
278
232
|
}),
|
|
279
233
|
);
|
|
280
234
|
|
|
281
235
|
await bootstrapPlugins();
|
|
282
236
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
await runShutdownHooks("test-shutdown");
|
|
237
|
+
await runHook(HOOKS.SHUTDOWN, {
|
|
238
|
+
assistantVersion: "test",
|
|
239
|
+
reason: "shutdown",
|
|
240
|
+
});
|
|
289
241
|
|
|
290
|
-
|
|
291
|
-
expect(
|
|
292
|
-
expect(pluginBOnShutdownMatch).not.toBeNull();
|
|
293
|
-
expect(pluginBOnShutdownMatch!.kind).toBe("match");
|
|
294
|
-
|
|
295
|
-
// After both plugins shut down, no routes remain.
|
|
296
|
-
expect(matchSkillRoute("/_plugin/echo", "GET")).toBeNull();
|
|
242
|
+
// Both plugins' hooks fired exactly once.
|
|
243
|
+
expect(pluginsThatShutDown.sort()).toEqual(["plugin-a", "plugin-b"]);
|
|
297
244
|
});
|
|
298
245
|
});
|
|
@@ -27,7 +27,6 @@ import { join } from "node:path";
|
|
|
27
27
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
28
28
|
|
|
29
29
|
import { bootstrapPlugins } from "../daemon/external-plugins-bootstrap.js";
|
|
30
|
-
import { runShutdownHooks } from "../daemon/shutdown-registry.js";
|
|
31
30
|
import { RiskLevel } from "../permissions/types.js";
|
|
32
31
|
import {
|
|
33
32
|
registerPlugin,
|
|
@@ -154,22 +153,6 @@ describe("plugin tool contributions", () => {
|
|
|
154
153
|
expect(names).toContain("plugin-contrib-tool");
|
|
155
154
|
});
|
|
156
155
|
|
|
157
|
-
test("plugin tools are unregistered when shutdown hooks run", async () => {
|
|
158
|
-
const plugin = buildPlugin("bravo-contributor", {
|
|
159
|
-
async init() {},
|
|
160
|
-
tools: [makeFakeTool("bravo-tool")],
|
|
161
|
-
});
|
|
162
|
-
registerPlugin(plugin);
|
|
163
|
-
|
|
164
|
-
await bootstrapPlugins();
|
|
165
|
-
expect(getTool("bravo-tool")).toBeDefined();
|
|
166
|
-
|
|
167
|
-
await runShutdownHooks("test-shutdown");
|
|
168
|
-
|
|
169
|
-
expect(getTool("bravo-tool")).toBeUndefined();
|
|
170
|
-
expect(getPluginRefCount("bravo-contributor")).toBe(0);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
156
|
test("bootstrap is a no-op for plugins that declare no tools", async () => {
|
|
174
157
|
const plugin = buildPlugin("no-tools", { async init() {} });
|
|
175
158
|
registerPlugin(plugin);
|
|
@@ -180,11 +163,6 @@ describe("plugin tool contributions", () => {
|
|
|
180
163
|
// empty. What matters here is that the no-tools plugin contributed nothing
|
|
181
164
|
// of its own — its tool refcount stays at zero.
|
|
182
165
|
expect(getPluginRefCount("no-tools")).toBe(0);
|
|
183
|
-
|
|
184
|
-
// Shutdown must also be safe — `unregisterPluginTools` is idempotent for
|
|
185
|
-
// plugins that never contributed any tools.
|
|
186
|
-
await runShutdownHooks("test-shutdown");
|
|
187
|
-
expect(getPluginRefCount("no-tools")).toBe(0);
|
|
188
166
|
});
|
|
189
167
|
|
|
190
168
|
test("tools declared before init() runs are only visible after bootstrap", async () => {
|
|
@@ -55,7 +55,12 @@ class FakeConversation {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const
|
|
58
|
+
const TRUSTED_CONTACT_CONTEXT: TrustContext = {
|
|
59
|
+
sourceChannel: "vellum",
|
|
60
|
+
trustClass: "trusted_contact",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const UNVERIFIED_CONTACT_CONTEXT: TrustContext = {
|
|
59
64
|
sourceChannel: "vellum",
|
|
60
65
|
trustClass: "unverified_contact",
|
|
61
66
|
};
|
|
@@ -82,16 +87,43 @@ describe("elevatePointerConversationToGuardian", () => {
|
|
|
82
87
|
expect(conv.trustContext).toBeUndefined();
|
|
83
88
|
});
|
|
84
89
|
|
|
85
|
-
test("
|
|
86
|
-
const conv = new FakeConversation({
|
|
90
|
+
test("does not elevate a trusted_contact context (no guardian history leak)", async () => {
|
|
91
|
+
const conv = new FakeConversation({
|
|
92
|
+
trustContext: TRUSTED_CONTACT_CONTEXT,
|
|
93
|
+
});
|
|
94
|
+
// A contact load filters guardian history to empty; it must stay empty.
|
|
87
95
|
expect(conv.visibleHistory).toEqual([]);
|
|
88
96
|
|
|
89
97
|
const restore = await elevatePointerConversationToGuardian(conv);
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
|
|
99
|
+
// No elevation and no rehydration — guardian-only history is never
|
|
100
|
+
// surfaced into a contact conversation.
|
|
101
|
+
expect(conv.setTrustContextCalls).toEqual([]);
|
|
102
|
+
expect(conv.ensureCalls).toBe(0);
|
|
103
|
+
expect(conv.trustContext).toBe(TRUSTED_CONTACT_CONTEXT);
|
|
104
|
+
expect(conv.visibleHistory).toEqual([]);
|
|
105
|
+
|
|
106
|
+
restore();
|
|
107
|
+
expect(conv.setTrustContextCalls).toEqual([]);
|
|
108
|
+
expect(conv.trustContext).toBe(TRUSTED_CONTACT_CONTEXT);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("does not elevate an unverified_contact context (no guardian history leak)", async () => {
|
|
112
|
+
const conv = new FakeConversation({
|
|
113
|
+
trustContext: UNVERIFIED_CONTACT_CONTEXT,
|
|
114
|
+
});
|
|
115
|
+
expect(conv.visibleHistory).toEqual([]);
|
|
116
|
+
|
|
117
|
+
const restore = await elevatePointerConversationToGuardian(conv);
|
|
118
|
+
|
|
119
|
+
expect(conv.setTrustContextCalls).toEqual([]);
|
|
120
|
+
expect(conv.ensureCalls).toBe(0);
|
|
121
|
+
expect(conv.trustContext).toBe(UNVERIFIED_CONTACT_CONTEXT);
|
|
122
|
+
expect(conv.visibleHistory).toEqual([]);
|
|
92
123
|
|
|
93
124
|
restore();
|
|
94
|
-
expect(conv.
|
|
125
|
+
expect(conv.setTrustContextCalls).toEqual([]);
|
|
126
|
+
expect(conv.trustContext).toBe(UNVERIFIED_CONTACT_CONTEXT);
|
|
95
127
|
});
|
|
96
128
|
|
|
97
129
|
test("no-ops for a conversation that already has memory access", async () => {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
// Silence the logger.
|
|
4
|
+
mock.module("../util/logger.js", () => ({
|
|
5
|
+
getLogger: () =>
|
|
6
|
+
new Proxy({} as Record<string, unknown>, {
|
|
7
|
+
get: () => () => {},
|
|
8
|
+
}),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
import type { AssistantConfig } from "../config/schema.js";
|
|
12
|
+
import { getDb } from "../persistence/db-connection.js";
|
|
13
|
+
import { initializeDb } from "../persistence/db-init.js";
|
|
14
|
+
import { pruneOldToolInvocationsJob } from "../persistence/job-handlers/cleanup.js";
|
|
15
|
+
import type { MemoryJob } from "../persistence/jobs-store.js";
|
|
16
|
+
import { conversations, toolInvocations } from "../persistence/schema/index.js";
|
|
17
|
+
|
|
18
|
+
await initializeDb();
|
|
19
|
+
|
|
20
|
+
const DAY_MS = 86_400_000;
|
|
21
|
+
|
|
22
|
+
function seedInvocation(id: string, createdAt: number): void {
|
|
23
|
+
getDb()
|
|
24
|
+
.insert(toolInvocations)
|
|
25
|
+
.values({
|
|
26
|
+
id,
|
|
27
|
+
conversationId: "conv-1",
|
|
28
|
+
toolName: "bash",
|
|
29
|
+
input: "{}",
|
|
30
|
+
result: "{}",
|
|
31
|
+
decision: "allow",
|
|
32
|
+
riskLevel: "low",
|
|
33
|
+
durationMs: 5,
|
|
34
|
+
createdAt,
|
|
35
|
+
})
|
|
36
|
+
.run();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function remainingIds(): string[] {
|
|
40
|
+
return getDb()
|
|
41
|
+
.select()
|
|
42
|
+
.from(toolInvocations)
|
|
43
|
+
.all()
|
|
44
|
+
.map((r) => r.id)
|
|
45
|
+
.sort();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function job(payload: Record<string, unknown> = {}): MemoryJob {
|
|
49
|
+
return { payload } as unknown as MemoryJob;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function config(retentionDays: number): AssistantConfig {
|
|
53
|
+
return { auditLog: { retentionDays } } as unknown as AssistantConfig;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe("pruneOldToolInvocationsJob", () => {
|
|
57
|
+
beforeEach(() => {
|
|
58
|
+
const db = getDb();
|
|
59
|
+
db.delete(toolInvocations).run();
|
|
60
|
+
db.delete(conversations).run();
|
|
61
|
+
// tool_invocations.conversation_id is an FK into conversations.
|
|
62
|
+
db.insert(conversations)
|
|
63
|
+
.values({
|
|
64
|
+
id: "conv-1",
|
|
65
|
+
title: "test",
|
|
66
|
+
createdAt: Date.now(),
|
|
67
|
+
updatedAt: Date.now(),
|
|
68
|
+
})
|
|
69
|
+
.run();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("deletes audit rows older than auditLog.retentionDays, keeps recent ones", async () => {
|
|
73
|
+
seedInvocation("old", Date.now() - 60 * DAY_MS);
|
|
74
|
+
seedInvocation("fresh", Date.now());
|
|
75
|
+
|
|
76
|
+
await pruneOldToolInvocationsJob(job(), config(30));
|
|
77
|
+
|
|
78
|
+
expect(remainingIds()).toEqual(["fresh"]);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("payload retentionDays overrides the config window", async () => {
|
|
82
|
+
seedInvocation("ten-days", Date.now() - 10 * DAY_MS);
|
|
83
|
+
|
|
84
|
+
// Config would keep it (30d), but the payload tightens to 7d.
|
|
85
|
+
await pruneOldToolInvocationsJob(job({ retentionDays: 7 }), config(30));
|
|
86
|
+
|
|
87
|
+
expect(remainingIds()).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("retentionDays of 0 is a no-op (keep forever)", async () => {
|
|
91
|
+
seedInvocation("ancient", Date.now() - 999 * DAY_MS);
|
|
92
|
+
|
|
93
|
+
await pruneOldToolInvocationsJob(job(), config(0));
|
|
94
|
+
|
|
95
|
+
expect(remainingIds()).toEqual(["ancient"]);
|
|
96
|
+
});
|
|
97
|
+
});
|