@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
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
23
23
|
import { join } from "node:path";
|
|
24
24
|
|
|
25
|
-
import { registerShutdownHook } from "../daemon/shutdown-registry.js";
|
|
26
25
|
import {
|
|
27
26
|
clearPluginHooks,
|
|
28
27
|
collectUserHooks,
|
|
@@ -35,7 +34,7 @@ import {
|
|
|
35
34
|
runShutdownHook,
|
|
36
35
|
WORKSPACE_HOOKS_OWNER,
|
|
37
36
|
} from "../hooks/hook-loader.js";
|
|
38
|
-
import type { HookFunction,
|
|
37
|
+
import type { HookFunction, ShutdownReason } from "../plugin-api/types.js";
|
|
39
38
|
import {
|
|
40
39
|
registerPluginTools,
|
|
41
40
|
unregisterPluginTools,
|
|
@@ -178,12 +177,21 @@ const disabledPluginDirs = new Set<string>();
|
|
|
178
177
|
* workspace hooks. Refreshes plugin discovery first, then delegates the actual
|
|
179
178
|
* hook resolution to the hook loader. Plugin hooks run in install-date order,
|
|
180
179
|
* the workspace hook runs last.
|
|
180
|
+
*
|
|
181
|
+
* `effectiveEnabledPlugins` carries the per-chat plugin scope: when non-null,
|
|
182
|
+
* user plugins outside the set are skipped (standalone workspace hooks always
|
|
183
|
+
* run). `null`/omitted means no per-chat restriction.
|
|
181
184
|
*/
|
|
182
185
|
export async function getUserHooksFor<TCtx = unknown>(
|
|
183
186
|
hookName: string,
|
|
187
|
+
effectiveEnabledPlugins?: Set<string> | null,
|
|
184
188
|
): Promise<HookFunction<TCtx>[]> {
|
|
185
189
|
await scanPlugins();
|
|
186
|
-
return collectUserHooks<TCtx>(
|
|
190
|
+
return collectUserHooks<TCtx>(
|
|
191
|
+
hookName,
|
|
192
|
+
discoveredPluginDirs,
|
|
193
|
+
effectiveEnabledPlugins,
|
|
194
|
+
);
|
|
187
195
|
}
|
|
188
196
|
|
|
189
197
|
// ─── Tool cache ──────────────────────────────────────────────────────────────
|
|
@@ -320,7 +328,7 @@ async function scanPlugins(): Promise<void> {
|
|
|
320
328
|
const manifest = await parsePluginManifest(pluginDir);
|
|
321
329
|
const pluginName = manifest?.name ?? entry;
|
|
322
330
|
if (discoveredPluginDirs.has(pluginDir)) {
|
|
323
|
-
await deactivatePlugin(pluginName);
|
|
331
|
+
await deactivatePlugin(pluginName, "disable");
|
|
324
332
|
await evictPlugin(pluginDir, pluginName);
|
|
325
333
|
}
|
|
326
334
|
if (!disabledPluginDirs.has(pluginDir)) {
|
|
@@ -351,7 +359,7 @@ async function scanPlugins(): Promise<void> {
|
|
|
351
359
|
// Deactivate and evict cache entries for deleted plugins.
|
|
352
360
|
for (const [pluginDir, pluginName] of discoveredPluginDirs) {
|
|
353
361
|
if (!currentDirs.has(pluginDir)) {
|
|
354
|
-
await deactivatePlugin(pluginName);
|
|
362
|
+
await deactivatePlugin(pluginName, "uninstall");
|
|
355
363
|
await evictPlugin(pluginDir, pluginName);
|
|
356
364
|
}
|
|
357
365
|
}
|
|
@@ -422,8 +430,10 @@ async function evictAll(): Promise<void> {
|
|
|
422
430
|
|
|
423
431
|
/**
|
|
424
432
|
* Plugins (and the workspace-hooks pseudo-owner) fully activated (tools
|
|
425
|
-
* registered + `init` hook run) within this process, in activation order.
|
|
426
|
-
*
|
|
433
|
+
* registered + `init` hook run) within this process, in activation order. A
|
|
434
|
+
* runtime uninstall/disable tears a single entry down via
|
|
435
|
+
* {@link deactivatePlugin}; at daemon shutdown the owners' `shutdown` hooks
|
|
436
|
+
* fire through the unified `runHook(HOOKS.SHUTDOWN)` pipeline.
|
|
427
437
|
*/
|
|
428
438
|
const activatedPlugins: Array<{ name: string }> = [];
|
|
429
439
|
|
|
@@ -436,16 +446,12 @@ const activatedPlugins: Array<{ name: string }> = [];
|
|
|
436
446
|
*/
|
|
437
447
|
const activatedNames = new Set<string>();
|
|
438
448
|
|
|
439
|
-
const shutdownContext: ShutdownContext = {
|
|
440
|
-
assistantVersion: APP_VERSION,
|
|
441
|
-
};
|
|
442
|
-
|
|
443
449
|
/**
|
|
444
450
|
* Activate a single discovered plugin: pre-import its hooks, register its tools
|
|
445
451
|
* into the global tool registry, and run its `init` hook. Idempotent — a plugin
|
|
446
452
|
* already activated (or mid-activation) is skipped. Never throws; per-surface
|
|
447
453
|
* failures are logged and the plugin still counts as activated so the shutdown
|
|
448
|
-
*
|
|
454
|
+
* teardown handles whatever came up (mirrors boot semantics).
|
|
449
455
|
*
|
|
450
456
|
* Called from `scanPlugins`, which runs both at boot and on every subsequent
|
|
451
457
|
* scan — so a plugin whose files appear at runtime (installed via the CLI or
|
|
@@ -491,12 +497,16 @@ async function activatePlugin(
|
|
|
491
497
|
}
|
|
492
498
|
|
|
493
499
|
/**
|
|
494
|
-
* Deactivate a plugin whose directory was removed or disabled
|
|
495
|
-
* unregister its tools and run its `shutdown` hook
|
|
496
|
-
*
|
|
497
|
-
*
|
|
500
|
+
* Deactivate a plugin whose directory was removed (`uninstall`) or disabled
|
|
501
|
+
* (`disable`) at runtime: unregister its tools and run its `shutdown` hook with
|
|
502
|
+
* the matching {@link ShutdownReason}. Must run *before* `evictPlugin` clears
|
|
503
|
+
* the hook cache, since the shutdown hook is read from it. Idempotent — a plugin
|
|
504
|
+
* that was never activated is a no-op.
|
|
498
505
|
*/
|
|
499
|
-
async function deactivatePlugin(
|
|
506
|
+
async function deactivatePlugin(
|
|
507
|
+
pluginName: string,
|
|
508
|
+
reason: ShutdownReason,
|
|
509
|
+
): Promise<void> {
|
|
500
510
|
if (!activatedNames.has(pluginName)) return;
|
|
501
511
|
activatedNames.delete(pluginName);
|
|
502
512
|
const idx = activatedPlugins.findIndex((p) => p.name === pluginName);
|
|
@@ -513,7 +523,11 @@ async function deactivatePlugin(pluginName: string): Promise<void> {
|
|
|
513
523
|
);
|
|
514
524
|
}
|
|
515
525
|
|
|
516
|
-
await runShutdownHook(
|
|
526
|
+
await runShutdownHook(
|
|
527
|
+
pluginName,
|
|
528
|
+
{ assistantVersion: APP_VERSION, reason },
|
|
529
|
+
reason,
|
|
530
|
+
);
|
|
517
531
|
}
|
|
518
532
|
|
|
519
533
|
// ─── Boot population ─────────────────────────────────────────────────────────
|
|
@@ -521,8 +535,10 @@ async function deactivatePlugin(pluginName: string): Promise<void> {
|
|
|
521
535
|
/**
|
|
522
536
|
* Populate the caches at boot by scanning the plugins directory once (which
|
|
523
537
|
* imports surfaces, registers tools, and runs `init` hooks via `activatePlugin`
|
|
524
|
-
* inside `scanPlugins`)
|
|
525
|
-
*
|
|
538
|
+
* inside `scanPlugins`) and activating standalone workspace hooks. At daemon
|
|
539
|
+
* shutdown these owners' `shutdown` hooks fire through the unified
|
|
540
|
+
* `runHook(HOOKS.SHUTDOWN)` pipeline; a runtime uninstall/disable tears a single
|
|
541
|
+
* owner down via {@link deactivatePlugin}.
|
|
526
542
|
*
|
|
527
543
|
* This replaces the old `loadExternalPlugin` → `registerPlugin` →
|
|
528
544
|
* `bootstrapPlugins` path for user plugins. Instead of registering whole
|
|
@@ -555,33 +571,6 @@ export async function populateCacheAtBoot(
|
|
|
555
571
|
await runInitHook(WORKSPACE_HOOKS_OWNER);
|
|
556
572
|
activatedPlugins.push({ name: WORKSPACE_HOOKS_OWNER });
|
|
557
573
|
}
|
|
558
|
-
|
|
559
|
-
// Register a single shutdown hook that walks all activated owners in reverse
|
|
560
|
-
// order, unregistering tools and running shutdown hooks. It reads the live
|
|
561
|
-
// `activatedPlugins` array at teardown time, so plugins activated after boot
|
|
562
|
-
// (runtime installs) are torn down too.
|
|
563
|
-
registerShutdownHook("user-plugins", async (reason) => {
|
|
564
|
-
for (let i = activatedPlugins.length - 1; i >= 0; i--) {
|
|
565
|
-
const entry = activatedPlugins[i];
|
|
566
|
-
if (entry === undefined) continue;
|
|
567
|
-
const { name } = entry;
|
|
568
|
-
|
|
569
|
-
// Unregister tools before running shutdown so onShutdown sees a
|
|
570
|
-
// clean model-visible surface. (No-op for the workspace-hooks owner,
|
|
571
|
-
// which registers no tools.)
|
|
572
|
-
try {
|
|
573
|
-
unregisterPluginTools(name);
|
|
574
|
-
} catch (err) {
|
|
575
|
-
log.warn(
|
|
576
|
-
{ err, plugin: name, reason },
|
|
577
|
-
"user plugin tool unregister failed (continuing)",
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// Run the `shutdown` hook if present.
|
|
582
|
-
await runShutdownHook(name, shutdownContext, reason);
|
|
583
|
-
}
|
|
584
|
-
});
|
|
585
574
|
}
|
|
586
575
|
|
|
587
576
|
// ─── Test hooks ──────────────────────────────────────────────────────────────
|
package/src/plugins/pipeline.ts
CHANGED
|
@@ -107,6 +107,12 @@ function cloneHookValue<T>(value: T, seen = new WeakMap<object, unknown>()): T {
|
|
|
107
107
|
* successfully committed context. The final context after the chain settles is
|
|
108
108
|
* returned.
|
|
109
109
|
*
|
|
110
|
+
* When `initialCtx` carries a `conversationId`, it is passed to
|
|
111
|
+
* {@link getHooksFor}, which resolves the conversation's per-chat plugin scope
|
|
112
|
+
* (memory, then DB) and skips a hook whose contributing plugin is outside the
|
|
113
|
+
* effective set. Contexts without a `conversationId` impose no restriction —
|
|
114
|
+
* every globally-enabled plugin's hook runs.
|
|
115
|
+
*
|
|
110
116
|
* @param name The hook identifier — pick one from {@link HOOKS}.
|
|
111
117
|
* @param initialCtx Context the first hook receives.
|
|
112
118
|
* @returns The final context after the chain settles. Same reference as
|
|
@@ -116,9 +122,10 @@ export async function runHook<TCtx>(
|
|
|
116
122
|
name: HookName,
|
|
117
123
|
initialCtx: TCtx,
|
|
118
124
|
): Promise<TCtx> {
|
|
125
|
+
const conversationId = extractConversationId(initialCtx);
|
|
119
126
|
let hooks: HookFunction<TCtx>[];
|
|
120
127
|
try {
|
|
121
|
-
hooks = await getHooksFor<TCtx>(name);
|
|
128
|
+
hooks = await getHooksFor<TCtx>(name, { conversationId });
|
|
122
129
|
} catch (err) {
|
|
123
130
|
log.error(
|
|
124
131
|
{ err, hookName: name },
|
|
@@ -146,3 +153,10 @@ export async function runHook<TCtx>(
|
|
|
146
153
|
}
|
|
147
154
|
return active;
|
|
148
155
|
}
|
|
156
|
+
|
|
157
|
+
/** The `conversationId` off a hook context, when it carries one as a string. */
|
|
158
|
+
function extractConversationId(ctx: unknown): string | undefined {
|
|
159
|
+
const conversationId = (ctx as { conversationId?: unknown } | null)
|
|
160
|
+
?.conversationId;
|
|
161
|
+
return typeof conversationId === "string" ? conversationId : undefined;
|
|
162
|
+
}
|
package/src/plugins/types.ts
CHANGED
|
@@ -48,13 +48,6 @@ export interface PluginManifest {
|
|
|
48
48
|
* own version at load time.
|
|
49
49
|
*/
|
|
50
50
|
version: string;
|
|
51
|
-
/**
|
|
52
|
-
* Assistant feature-flag keys that must all be enabled for this plugin to
|
|
53
|
-
* activate. Checked by `bootstrapPlugins` via `isAssistantFeatureFlagEnabled`
|
|
54
|
-
* — if any listed flag is disabled, the plugin is skipped entirely for the
|
|
55
|
-
* boot (no `init()`, no tool/route/skill contributions, no shutdown hook).
|
|
56
|
-
*/
|
|
57
|
-
requiresFlag?: string[];
|
|
58
51
|
/**
|
|
59
52
|
* Zod-compatible validator (or any parser-like object) for the plugin's
|
|
60
53
|
* config block under `plugins.<name>`. Typed as `unknown` here — concrete
|
|
@@ -71,6 +64,7 @@ export type {
|
|
|
71
64
|
HookFunction,
|
|
72
65
|
InitContext,
|
|
73
66
|
ShutdownContext,
|
|
67
|
+
ShutdownReason,
|
|
74
68
|
} from "../plugin-api/types.js";
|
|
75
69
|
|
|
76
70
|
// ─── Memory-graph result ─────────────────────────────────────────────────────
|
|
@@ -143,6 +137,13 @@ export interface TurnContext {
|
|
|
143
137
|
readonly timestamp?: string;
|
|
144
138
|
/** Human-readable interface label (e.g. "vellum", "telegram"). */
|
|
145
139
|
readonly interfaceName?: string;
|
|
140
|
+
/**
|
|
141
|
+
* Client OS surface ("web" | "ios" | "macos"), reported independently of
|
|
142
|
+
* the transport interface. Rendered as the `client_os:` line so the model
|
|
143
|
+
* knows the platform even though the web/iOS/macOS apps share one `"web"`
|
|
144
|
+
* transport interface.
|
|
145
|
+
*/
|
|
146
|
+
readonly clientOs?: string;
|
|
146
147
|
/** Channel label gating response-discretion guidance in `<turn_context>`. */
|
|
147
148
|
readonly channelName?: string;
|
|
148
149
|
/**
|
|
@@ -335,13 +336,12 @@ export interface Injector {
|
|
|
335
336
|
export type PluginRouteRegistration = SkillRoute;
|
|
336
337
|
|
|
337
338
|
/**
|
|
338
|
-
* A single background-job-handler
|
|
339
|
-
*
|
|
340
|
-
* `
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
* keyed lookup. See `plugins/job-handler-registry.ts`.
|
|
339
|
+
* A single background-job-handler entry: a job `type` string paired with the
|
|
340
|
+
* {@link JobHandler} that processes it. The memory plugin's handler list
|
|
341
|
+
* (`plugins/defaults/memory/job-handlers.ts`) is an array of these, registered
|
|
342
|
+
* directly into the worker's dispatch table from the plugin's `init` hook.
|
|
343
|
+
* `type` must be globally unique across every registered handler — dispatch is a
|
|
344
|
+
* keyed lookup.
|
|
345
345
|
*/
|
|
346
346
|
export interface JobHandlerEntry {
|
|
347
347
|
/** The job-queue type string this handler processes (globally unique). */
|
|
@@ -400,15 +400,6 @@ export interface Plugin {
|
|
|
400
400
|
* injectors sharing an `order`. See `plugins/injector-registry.ts`.
|
|
401
401
|
*/
|
|
402
402
|
injectors?: readonly Injector[];
|
|
403
|
-
/**
|
|
404
|
-
* Background-job handlers contributed to the general job worker. Bootstrap
|
|
405
|
-
* registers these into the global job-handler registry before `init()` runs,
|
|
406
|
-
* symmetric with `tools`/`routes`/`injectors`; the general worker's
|
|
407
|
-
* registration entry (`jobs/register-job-handlers.ts`) forwards the union into
|
|
408
|
-
* the worker dispatch table. Each `type` must be globally unique across every
|
|
409
|
-
* plugin. See `plugins/job-handler-registry.ts`.
|
|
410
|
-
*/
|
|
411
|
-
jobHandlers?: readonly JobHandlerEntry[];
|
|
412
403
|
}
|
|
413
404
|
|
|
414
405
|
// ─── Errors ──────────────────────────────────────────────────────────────────
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { join } from "node:path";
|
|
11
|
-
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
11
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
12
|
|
|
13
13
|
const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
14
14
|
|
|
@@ -125,50 +125,188 @@ describe("buildSystemPrompt — persona override", () => {
|
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
describe("buildSystemPrompt —
|
|
129
|
-
// Marker
|
|
130
|
-
|
|
131
|
-
const
|
|
128
|
+
describe("buildSystemPrompt — default persona trust-class guardrail", () => {
|
|
129
|
+
// Marker strings from the bundled users/default.md template.
|
|
130
|
+
const GUARDRAIL = "Protect your guardian's privacy";
|
|
131
|
+
const TRUSTED_GREETING = "You're talking with a trusted contact";
|
|
132
|
+
const STRANGER_GREETING = "You're talking with someone you don't recognize";
|
|
133
|
+
|
|
134
|
+
const templatesDir = join(import.meta.dirname!, "..", "templates");
|
|
135
|
+
let priorAuthEnv: string | undefined;
|
|
132
136
|
|
|
133
137
|
beforeEach(() => {
|
|
134
|
-
|
|
138
|
+
// Captured so the DISABLE_HTTP_AUTH regression test below can restore it.
|
|
139
|
+
priorAuthEnv = process.env.DISABLE_HTTP_AUTH;
|
|
140
|
+
|
|
141
|
+
mkdirSync(join(TEST_DIR, "users"), { recursive: true });
|
|
142
|
+
// Render the real shipped template, not a sentinel.
|
|
143
|
+
copyFileSync(
|
|
144
|
+
join(templatesDir, "users", "default.md"),
|
|
145
|
+
join(TEST_DIR, "users", "default.md"),
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
afterEach(() => {
|
|
150
|
+
if (priorAuthEnv === undefined) delete process.env.DISABLE_HTTP_AUTH;
|
|
151
|
+
else process.env.DISABLE_HTTP_AUTH = priorAuthEnv;
|
|
135
152
|
});
|
|
136
153
|
|
|
137
|
-
test("
|
|
138
|
-
|
|
139
|
-
|
|
154
|
+
test("stranger (unknown) sees the guardrail and the stranger greeting", () => {
|
|
155
|
+
const result = buildSystemPrompt({
|
|
156
|
+
trustContext: { sourceChannel: "slack", trustClass: "unknown" },
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
expect(result).toContain(GUARDRAIL);
|
|
160
|
+
expect(result).toContain(STRANGER_GREETING);
|
|
161
|
+
expect(result).not.toContain(TRUSTED_GREETING);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("trusted contact sees the guardrail and the trusted greeting", () => {
|
|
165
|
+
const result = buildSystemPrompt({
|
|
166
|
+
trustContext: { sourceChannel: "slack", trustClass: "trusted_contact" },
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
expect(result).toContain(GUARDRAIL);
|
|
170
|
+
expect(result).toContain(TRUSTED_GREETING);
|
|
171
|
+
expect(result).not.toContain(STRANGER_GREETING);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("unverified contact is framed like a trusted contact", () => {
|
|
175
|
+
const result = buildSystemPrompt({
|
|
176
|
+
trustContext: {
|
|
177
|
+
sourceChannel: "slack",
|
|
178
|
+
trustClass: "unverified_contact",
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
expect(result).toContain(GUARDRAIL);
|
|
183
|
+
expect(result).toContain(TRUSTED_GREETING);
|
|
184
|
+
expect(result).not.toContain(STRANGER_GREETING);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("guardian trust class gates the whole default persona off", () => {
|
|
188
|
+
// A guardian normally renders their own users/<slug>.md; if they ever fall
|
|
189
|
+
// back to default.md, every section is gated off and nothing leaks.
|
|
190
|
+
const result = buildSystemPrompt({
|
|
191
|
+
trustContext: { sourceChannel: "vellum", trustClass: "guardian" },
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(result).not.toContain(GUARDRAIL);
|
|
195
|
+
expect(result).not.toContain(TRUSTED_GREETING);
|
|
196
|
+
expect(result).not.toContain(STRANGER_GREETING);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("renders for a non-guardian even when HTTP auth is disabled", () => {
|
|
200
|
+
// Platform-managed deployments run with DISABLE_HTTP_AUTH=true. A *present*
|
|
201
|
+
// trustContext must keep the actor's real class under that posture
|
|
202
|
+
// (resolveTrustClass only fail-safes *unresolved* actors), or the guardrail
|
|
203
|
+
// would silently switch off for the non-guardian channel actors it exists
|
|
204
|
+
// to protect.
|
|
205
|
+
process.env.DISABLE_HTTP_AUTH = "true";
|
|
206
|
+
const result = buildSystemPrompt({
|
|
207
|
+
trustContext: { sourceChannel: "slack", trustClass: "unknown" },
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
expect(result).toContain(GUARDRAIL);
|
|
211
|
+
expect(result).toContain(STRANGER_GREETING);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("gates off for an unresolved local build when HTTP auth is disabled", () => {
|
|
215
|
+
// Initial-prompt warming, home generation, and btw sidechains build
|
|
216
|
+
// prompts with NO trustContext on behalf of the owner. In an auth-disabled
|
|
217
|
+
// (local / platform-managed) deployment that unresolved actor is the
|
|
218
|
+
// guardian, so the guardrail must not render into those guardian-facing
|
|
219
|
+
// prompts (fail-stranger would stonewall the owner about their own data).
|
|
220
|
+
process.env.DISABLE_HTTP_AUTH = "true";
|
|
221
|
+
const result = buildSystemPrompt({});
|
|
222
|
+
|
|
223
|
+
expect(result).not.toContain(GUARDRAIL);
|
|
224
|
+
expect(result).not.toContain(TRUSTED_GREETING);
|
|
225
|
+
expect(result).not.toContain(STRANGER_GREETING);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("fails closed to the guardrail for an unresolved build when auth is enabled", () => {
|
|
229
|
+
// With auth enabled there is no basis to assume the unresolved actor is
|
|
230
|
+
// the guardian, so an unclassifiable build keeps the boundary.
|
|
231
|
+
delete process.env.DISABLE_HTTP_AUTH;
|
|
232
|
+
const result = buildSystemPrompt({});
|
|
233
|
+
|
|
234
|
+
expect(result).toContain(GUARDRAIL);
|
|
235
|
+
expect(result).toContain(STRANGER_GREETING);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test("boundary survives a per-contact persona file replacing default.md", () => {
|
|
239
|
+
// Every contact already has a `users/<slug>.md` filename reserved on
|
|
240
|
+
// their contact record; the moment that file exists with content it
|
|
241
|
+
// replaces `default.md` in the `10-user-persona` section. The privacy
|
|
242
|
+
// boundary must render regardless — it lives in the always-on
|
|
243
|
+
// `10a-non-guardian-boundary` section, not in the fallback file.
|
|
244
|
+
writeFileSync(
|
|
245
|
+
join(TEST_DIR, "users", "jane.md"),
|
|
246
|
+
"# Jane\n\nJane likes concise answers.\n",
|
|
247
|
+
"utf-8",
|
|
140
248
|
);
|
|
141
|
-
|
|
142
|
-
|
|
249
|
+
const result = buildSystemPrompt({
|
|
250
|
+
trustContext: { sourceChannel: "slack", trustClass: "trusted_contact" },
|
|
251
|
+
personaOverride: { userSlug: "jane" },
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// The contact's own persona replaced the default greetings...
|
|
255
|
+
expect(result).toContain("Jane likes concise answers.");
|
|
256
|
+
expect(result).not.toContain(TRUSTED_GREETING);
|
|
257
|
+
// ...but the boundary still renders.
|
|
258
|
+
expect(result).toContain(GUARDRAIL);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("boundary is omitted for a guardian rendering their own persona file", () => {
|
|
262
|
+
writeFileSync(
|
|
263
|
+
join(TEST_DIR, "users", "owner.md"),
|
|
264
|
+
"# Owner\n\nThe guardian's own profile.\n",
|
|
265
|
+
"utf-8",
|
|
143
266
|
);
|
|
267
|
+
const result = buildSystemPrompt({
|
|
268
|
+
trustContext: { sourceChannel: "vellum", trustClass: "guardian" },
|
|
269
|
+
personaOverride: { userSlug: "owner" },
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
expect(result).toContain("The guardian's own profile.");
|
|
273
|
+
expect(result).not.toContain(GUARDRAIL);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test("never leaks literal mustache tags or comment lines", () => {
|
|
277
|
+
for (const trustClass of [
|
|
278
|
+
"unknown",
|
|
279
|
+
"trusted_contact",
|
|
280
|
+
"unverified_contact",
|
|
281
|
+
"guardian",
|
|
282
|
+
] as const) {
|
|
283
|
+
const result = buildSystemPrompt({
|
|
284
|
+
trustContext: { sourceChannel: "slack", trustClass },
|
|
285
|
+
});
|
|
286
|
+
expect(result).not.toContain("{{");
|
|
287
|
+
expect(result).not.toContain("}}");
|
|
288
|
+
expect(result).not.toContain("Lines starting with");
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe("buildSystemPrompt — hasNoClient no longer affects the prompt", () => {
|
|
294
|
+
beforeEach(() => {
|
|
295
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
144
296
|
});
|
|
145
297
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
298
|
+
// No system-prompt section branches on hasNoClient, so neither the flag nor
|
|
299
|
+
// the SystemPromptPersonaOverride.hasNoClient pin changes prompt output.
|
|
300
|
+
// Guards against a future section re-coupling to the flag.
|
|
301
|
+
test("output is identical regardless of the flag or its pin", () => {
|
|
302
|
+
const base = buildSystemPrompt({ hasNoClient: false });
|
|
303
|
+
expect(buildSystemPrompt({ hasNoClient: true })).toBe(base);
|
|
150
304
|
expect(
|
|
151
305
|
buildSystemPrompt({
|
|
152
306
|
hasNoClient: true,
|
|
153
307
|
personaOverride: { hasNoClient: false },
|
|
154
308
|
}),
|
|
155
|
-
).
|
|
156
|
-
// And the pin wins in the other direction too.
|
|
157
|
-
expect(
|
|
158
|
-
buildSystemPrompt({
|
|
159
|
-
hasNoClient: false,
|
|
160
|
-
personaOverride: { hasNoClient: true },
|
|
161
|
-
}),
|
|
162
|
-
).not.toContain(WITH_CLIENT_MARKER);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
test("a personaOverride without the pin leaves the conversation-derived flag untouched", () => {
|
|
166
|
-
expect(
|
|
167
|
-
buildSystemPrompt({ hasNoClient: true, personaOverride: {} }),
|
|
168
|
-
).not.toContain(WITH_CLIENT_MARKER);
|
|
169
|
-
expect(
|
|
170
|
-
buildSystemPrompt({ hasNoClient: false, personaOverride: {} }),
|
|
171
|
-
).toContain(WITH_CLIENT_MARKER);
|
|
309
|
+
).toBe(base);
|
|
172
310
|
});
|
|
173
311
|
});
|
|
174
312
|
|
|
@@ -91,7 +91,9 @@ function resolveGuardianUserFile(trustContext: TrustContext): string | null {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
const guardian = peekGuardianForChannel(trustContext.sourceChannel);
|
|
94
|
-
return guardian
|
|
94
|
+
return guardian
|
|
95
|
+
? (guardianDeliveryUserFile(guardian) ?? "guardian.md")
|
|
96
|
+
: null;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
/**
|
|
@@ -103,10 +105,7 @@ function resolveGuardianUserFile(trustContext: TrustContext): string | null {
|
|
|
103
105
|
function guardianDeliveryUserFile(
|
|
104
106
|
guardian: GuardianDelivery,
|
|
105
107
|
): string | undefined {
|
|
106
|
-
const contact = findContactByAddress(
|
|
107
|
-
guardian.channelType,
|
|
108
|
-
guardian.address,
|
|
109
|
-
);
|
|
108
|
+
const contact = findContactByAddress(guardian.channelType, guardian.address);
|
|
110
109
|
return contact?.userFile ?? undefined;
|
|
111
110
|
}
|
|
112
111
|
|
|
@@ -147,13 +146,18 @@ function resolveUserFilename(
|
|
|
147
146
|
trustContext.sourceChannel,
|
|
148
147
|
trustContext.requesterExternalUserId,
|
|
149
148
|
);
|
|
150
|
-
if (contactWithChannels) {
|
|
151
|
-
filename = contactWithChannels.userFile
|
|
149
|
+
if (contactWithChannels?.userFile) {
|
|
150
|
+
filename = contactWithChannels.userFile;
|
|
152
151
|
} else if (trustContext.trustClass === "guardian") {
|
|
153
152
|
// Managed desktop: the JWT principal ID used as requesterExternalUserId
|
|
154
153
|
// may differ from the contact channel's address (they are separate
|
|
155
|
-
// identity concepts)
|
|
156
|
-
//
|
|
154
|
+
// identity concepts) — OR the guardian's contact row exists but carries
|
|
155
|
+
// no explicit userFile yet (the normal post-hatch state, since the
|
|
156
|
+
// guardian contact is created with a null userFile and onboarding
|
|
157
|
+
// writes the file on disk, not the column). Either way, read the
|
|
158
|
+
// guardian's user file keyed by the verdict-bound guardian identity so
|
|
159
|
+
// the onboarding profile (written to guardian.md) loads instead of
|
|
160
|
+
// falling through to users/default.md.
|
|
157
161
|
filename = resolveGuardianUserFile(trustContext);
|
|
158
162
|
}
|
|
159
163
|
} else if (trustContext.trustClass === "guardian") {
|
|
@@ -10,8 +10,12 @@ import { join } from "node:path";
|
|
|
10
10
|
|
|
11
11
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
12
12
|
import type { ChannelCapabilities } from "../daemon/conversation-runtime-assembly.js";
|
|
13
|
-
import
|
|
13
|
+
import {
|
|
14
|
+
resolveTrustClass,
|
|
15
|
+
type TrustContext,
|
|
16
|
+
} from "../daemon/trust-context.js";
|
|
14
17
|
import { markActivationSession } from "../plugins/defaults/memory/activation-session-store.js";
|
|
18
|
+
import { derivePersonaTrustFlags } from "../runtime/trust-class.js";
|
|
15
19
|
import { ACTIVATION_RAIL_BOOTSTRAP_TEMPLATE } from "../telemetry/activation-funnel.js";
|
|
16
20
|
import type { OnboardingContext } from "../types/onboarding-context.js";
|
|
17
21
|
import { resolveBundledDir } from "../util/bundled-asset.js";
|
|
@@ -319,14 +323,12 @@ export interface SystemPromptPersonaOverride {
|
|
|
319
323
|
/**
|
|
320
324
|
* Pins the `hasNoClient` flag for the prompt build, taking precedence over
|
|
321
325
|
* the top-level `BuildSystemPromptOptions.hasNoClient` (which mirrors the
|
|
322
|
-
* conversation's live client state).
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
* interfaces, `true` for channel-routed sources) — the pin carries that
|
|
329
|
-
* live-turn value.
|
|
326
|
+
* conversation's live client state). No system-prompt section branches on
|
|
327
|
+
* `hasNoClient`, so this pin does not affect prompt output; it is retained
|
|
328
|
+
* so fork-based memory retrospectives can thread the source conversation's
|
|
329
|
+
* live-turn value (`false` for interactive interfaces, `true` for
|
|
330
|
+
* channel-routed sources) through the build without depending on the fork's
|
|
331
|
+
* clientless hydration default.
|
|
330
332
|
*/
|
|
331
333
|
hasNoClient?: boolean;
|
|
332
334
|
}
|
|
@@ -395,6 +397,21 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
395
397
|
const hasNoClient =
|
|
396
398
|
options?.personaOverride?.hasNoClient ?? options?.hasNoClient;
|
|
397
399
|
|
|
400
|
+
// Trust flags for the current actor, lifted onto the render context so
|
|
401
|
+
// persona sections — notably `users/default.md`, the persona rendered for
|
|
402
|
+
// non-guardian actors — can gate privacy guardrails on who is being spoken
|
|
403
|
+
// to. The class is resolved through `resolveTrustClass` first: a *present*
|
|
404
|
+
// trustContext always keeps the actor's real class (a resolved non-guardian
|
|
405
|
+
// channel actor is never elevated, even under DISABLE_HTTP_AUTH), while an
|
|
406
|
+
// *absent* one follows the actor-resolution contract — guardian for
|
|
407
|
+
// local/native builds in an auth-disabled deployment (initial-prompt
|
|
408
|
+
// warming, home generation, and btw sidechains build prompts with no
|
|
409
|
+
// trustContext for the owner), unknown otherwise so an unclassifiable turn
|
|
410
|
+
// still fails closed to the guardrail. The flag grouping itself lives on
|
|
411
|
+
// {@link derivePersonaTrustFlags}.
|
|
412
|
+
const { trustClass, isGuardian, isTrustedContact, isStranger } =
|
|
413
|
+
derivePersonaTrustFlags(resolveTrustClass(options?.trustContext));
|
|
414
|
+
|
|
398
415
|
// Section render context. Workspace section frontmatter `enabled:`
|
|
399
416
|
// predicates, `{{key}}` / `{{#flag}}...{{/flag}}` body interpolation,
|
|
400
417
|
// and `{{key}}` paths inside `workspacePath` all resolve against this
|
|
@@ -411,6 +428,10 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
411
428
|
workspaceDir: getWorkspaceDir(),
|
|
412
429
|
userSlug,
|
|
413
430
|
channelSlug,
|
|
431
|
+
trustClass,
|
|
432
|
+
isGuardian,
|
|
433
|
+
isTrustedContact,
|
|
434
|
+
isStranger,
|
|
414
435
|
};
|
|
415
436
|
|
|
416
437
|
// Every system-prompt block flows through the bundled section
|