@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +94 -91
- package/Dockerfile +5 -16
- package/README.md +7 -10
- package/bun.lock +0 -4
- package/docs/architecture/security.md +20 -20
- package/docs/stt-provider-onboarding.md +4 -5
- package/docs/trusted-contact-access.md +7 -7
- package/eslint-rules/cli-no-daemon-internals.js +4 -0
- package/eslint.config.mjs +7 -1
- package/knip.json +0 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
- package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
- package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
- package/openapi.yaml +1073 -225
- package/package.json +1 -4
- package/scripts/test.sh +35 -13
- package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
- package/src/__tests__/acp-session.test.ts +4 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
- package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
- package/src/__tests__/app-source-watcher.test.ts +11 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
- package/src/__tests__/assistant-attachments.test.ts +62 -4
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
- package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
- package/src/__tests__/attachments-store.test.ts +3 -0
- package/src/__tests__/background-shell-bash.test.ts +34 -0
- package/src/__tests__/background-shell-host-bash.test.ts +12 -0
- package/src/__tests__/background-tool-registry.test.ts +97 -0
- package/src/__tests__/background-tool-routes.test.ts +72 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/btw-routes.test.ts +57 -3
- package/src/__tests__/call-controller.test.ts +474 -84
- package/src/__tests__/call-domain.test.ts +48 -1
- package/src/__tests__/call-pointer-messages.test.ts +57 -19
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +15 -14
- package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
- package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
- package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
- package/src/__tests__/call-setup-flow.test.ts +311 -0
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -7
- package/src/__tests__/channel-readiness-service.test.ts +0 -6
- package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
- package/src/__tests__/channel-retry-sweep.test.ts +76 -64
- package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
- package/src/__tests__/clear-all-lexical.test.ts +90 -0
- package/src/__tests__/compactor-media-strip.test.ts +177 -0
- package/src/__tests__/config-loader-backfill.test.ts +5 -5
- package/src/__tests__/config-schema.test.ts +17 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
- package/src/__tests__/contacts-relay-reads.test.ts +188 -23
- package/src/__tests__/contacts-tools.test.ts +42 -1
- package/src/__tests__/contacts-write.test.ts +181 -0
- package/src/__tests__/context-search-conversations-source.test.ts +220 -81
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +39 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
- package/src/__tests__/conversation-clear-safety.test.ts +0 -1
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -0
- package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
- package/src/__tests__/conversation-error.test.ts +0 -18
- package/src/__tests__/conversation-fork-crud.test.ts +67 -0
- package/src/__tests__/conversation-history-web-search.test.ts +7 -137
- package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
- package/src/__tests__/conversation-process-callsite.test.ts +37 -0
- package/src/__tests__/conversation-queue.test.ts +149 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
- package/src/__tests__/conversation-skill-tools.test.ts +73 -0
- package/src/__tests__/conversation-wipe.test.ts +20 -5
- package/src/__tests__/credential-prompt-route.test.ts +69 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -3
- package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
- package/src/__tests__/edit-propagation.test.ts +56 -2
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
- package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
- package/src/__tests__/guardian-question-mode.test.ts +57 -0
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/guardian-wait-controller.test.ts +619 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
- package/src/__tests__/heic-fixture.ts +55 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
- package/src/__tests__/http-conversation-lineage.test.ts +6 -1
- package/src/__tests__/image-conversion.test.ts +170 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
- package/src/__tests__/introduction-card-resolver.test.ts +354 -0
- package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
- package/src/__tests__/invite-routes-http.test.ts +246 -420
- package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
- package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
- package/src/__tests__/list-messages-attachments.test.ts +159 -0
- package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
- package/src/__tests__/list-messages-queued.test.ts +25 -0
- package/src/__tests__/managed-store.test.ts +129 -1
- package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
- package/src/__tests__/media-stream-output.test.ts +350 -19
- package/src/__tests__/media-stream-server-integration.test.ts +943 -169
- package/src/__tests__/media-stream-stt-session.test.ts +498 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +19 -0
- package/src/__tests__/non-member-access-request.test.ts +349 -3
- package/src/__tests__/notification-decision-fallback.test.ts +104 -8
- package/src/__tests__/notification-decision-strategy.test.ts +57 -8
- package/src/__tests__/onboarding-template-contract.test.ts +27 -43
- package/src/__tests__/openai-provider.test.ts +33 -0
- package/src/__tests__/openai-responses-provider.test.ts +40 -0
- package/src/__tests__/persistence-layering-guard.test.ts +29 -20
- package/src/__tests__/persona-resolver.test.ts +56 -2
- package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
- package/src/__tests__/phone.test.ts +1 -15
- package/src/__tests__/plugin-bootstrap.test.ts +25 -196
- package/src/__tests__/plugin-disabled-state.test.ts +33 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
- package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
- package/src/__tests__/plugin-pipeline.test.ts +63 -1
- package/src/__tests__/plugin-route-contribution.test.ts +62 -115
- package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
- package/src/__tests__/plugin-types.test.ts +0 -1
- package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
- package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
- package/src/__tests__/public-ingress-urls.test.ts +0 -48
- package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
- package/src/__tests__/resolve-trust-class.test.ts +28 -10
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
- package/src/__tests__/schedule-retry.test.ts +38 -14
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
- package/src/__tests__/schedule-routes.test.ts +14 -6
- package/src/__tests__/schedule-store.test.ts +3 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
- package/src/__tests__/scheduler-recurrence.test.ts +57 -107
- package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
- package/src/__tests__/scheduler-wake.test.ts +13 -23
- package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/shell-observability.test.ts +1 -0
- package/src/__tests__/skill-boundary-guard.test.ts +3 -4
- package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
- package/src/__tests__/skill-script-runner-host.test.ts +53 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
- package/src/__tests__/skill-tool-factory.test.ts +73 -1
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
- package/src/__tests__/slack-inbound-verification.test.ts +36 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
- package/src/__tests__/stt-hints.test.ts +2 -256
- package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
- package/src/__tests__/subagent-persistence.test.ts +122 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +99 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
- package/src/__tests__/system-prompt.test.ts +17 -118
- package/src/__tests__/task-scheduler.test.ts +68 -89
- package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
- package/src/__tests__/telephony-tts-guard.test.ts +538 -0
- package/src/__tests__/title-generate-hook.test.ts +16 -0
- package/src/__tests__/tool-approval-handler.test.ts +87 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
- package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
- package/src/__tests__/trust-context-guards.test.ts +21 -10
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
- package/src/__tests__/twilio-provider.test.ts +17 -17
- package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
- package/src/__tests__/twilio-routes.test.ts +257 -387
- package/src/__tests__/twilio-validation.test.ts +1 -1
- package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
- package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
- package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
- package/src/__tests__/voice-quality.test.ts +2 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
- package/src/__tests__/voice-session-bridge.test.ts +1 -10
- package/src/__tests__/workspace-git-service.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
- package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
- package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
- package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
- package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
- package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
- package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
- package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
- package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
- package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
- package/src/acp/__tests__/session-manager.test.ts +6 -0
- package/src/acp/agent-process.test.ts +116 -0
- package/src/acp/agent-process.ts +71 -0
- package/src/acp/auto-install.ts +12 -8
- package/src/acp/failure-error.test.ts +109 -0
- package/src/acp/failure-error.ts +111 -0
- package/src/acp/prepare-agent-env.ts +0 -12
- package/src/acp/resolve-agent.test.ts +6 -45
- package/src/acp/resolve-agent.ts +2 -4
- package/src/acp/session-manager.test.ts +312 -0
- package/src/acp/session-manager.ts +102 -46
- package/src/agent/ax-tree-compaction.test.ts +4 -1
- package/src/agent/image-optimize.ts +17 -127
- package/src/agent/loop.ts +45 -192
- package/src/api/events/background-tool-completed.test.ts +51 -0
- package/src/api/events/background-tool-completed.ts +29 -0
- package/src/api/events/background-tool-started.test.ts +36 -0
- package/src/api/events/background-tool-started.ts +28 -0
- package/src/api/events/conversation-error.ts +0 -1
- package/src/api/events/open-panel.ts +33 -0
- package/src/api/events/subagent-status-changed.ts +4 -1
- package/src/api/index.ts +19 -0
- package/src/api/responses/conversation-message.ts +34 -0
- package/src/approvals/guardian-decision-primitive.ts +74 -24
- package/src/approvals/guardian-request-resolvers.ts +450 -122
- package/src/apps/app-store.ts +1 -0
- package/src/apps/shared-app-links-store.ts +1 -0
- package/src/avatar/identity-avatar.ts +3 -7
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
- package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
- package/src/calls/call-controller.ts +134 -48
- package/src/calls/call-domain.ts +18 -42
- package/src/calls/call-pointer-messages.ts +51 -67
- package/src/calls/call-setup-flow-types.ts +76 -0
- package/src/calls/call-setup-flow.ts +1743 -0
- package/src/calls/call-speech-output.ts +87 -23
- package/src/calls/call-store.ts +4 -0
- package/src/calls/call-transport.ts +22 -36
- package/src/calls/fish-audio-client.ts +3 -0
- package/src/calls/gateway-invite-reader.ts +98 -0
- package/src/calls/guardian-wait-controller.ts +451 -0
- package/src/calls/media-stream-audio-transcode.ts +82 -2
- package/src/calls/media-stream-output.ts +142 -36
- package/src/calls/media-stream-server.ts +297 -178
- package/src/calls/media-stream-stt-session.ts +393 -50
- package/src/calls/media-turn-detector.ts +4 -6
- package/src/calls/relay-access-wait.ts +3 -4
- package/src/calls/relay-setup-router.ts +22 -43
- package/src/calls/relay-verification.ts +17 -24
- package/src/calls/resolve-call-tts-provider.ts +96 -29
- package/src/calls/stt-hints.ts +24 -87
- package/src/calls/telephony-credential-preflight.ts +159 -0
- package/src/calls/telephony-tts-capability.ts +183 -0
- package/src/calls/tts-call-strategy.ts +18 -20
- package/src/calls/twilio-provider.ts +3 -2
- package/src/calls/twilio-routes.ts +47 -351
- package/src/calls/types.ts +5 -3
- package/src/calls/voice-ingress-preflight.ts +9 -0
- package/src/calls/voice-quality.ts +13 -18
- package/src/calls/voice-session-bridge.ts +25 -35
- package/src/channels/__tests__/types.test.ts +28 -0
- package/src/channels/channel-verification-sessions.ts +7 -2
- package/src/channels/config.ts +0 -42
- package/src/channels/slack-thread-store.ts +12 -0
- package/src/channels/types.ts +23 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
- package/src/cli/commands/__tests__/schedules.test.ts +83 -34
- package/src/cli/commands/__tests__/status.test.ts +42 -2
- package/src/cli/commands/contacts.ts +2 -2
- package/src/cli/commands/credentials.ts +17 -0
- package/src/cli/commands/monitoring.ts +191 -0
- package/src/cli/commands/schedules-worker.ts +175 -0
- package/src/cli/commands/schedules.ts +169 -43
- package/src/cli/commands/status.ts +12 -1
- package/src/cli/commands/tools.ts +5 -1
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
- package/src/cli/lib/search-plugins.ts +6 -0
- package/src/cli/lib/toggle-plugin.ts +21 -2
- package/src/cli/program.ts +3 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
- package/src/config/acp-defaults.test.ts +0 -10
- package/src/config/acp-defaults.ts +0 -6
- package/src/config/bundled-skills/acp/SKILL.md +13 -45
- package/src/config/bundled-skills/acp/TOOLS.json +3 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
- package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
- package/src/config/call-site-defaults.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -8
- package/src/config/loader.ts +11 -0
- package/src/config/schema.ts +9 -1
- package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
- package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
- package/src/config/schemas/call-site-catalog.ts +0 -12
- package/src/config/schemas/calls.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +1 -1
- package/src/config/schemas/llm.ts +0 -2
- package/src/config/schemas/memory-v2.ts +1 -1
- package/src/config/schemas/memory-v3.ts +82 -0
- package/src/config/schemas/monitoring.ts +61 -0
- package/src/config/schemas/schedules.ts +35 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills-plugin-filter.test.ts +96 -0
- package/src/config/skills.ts +26 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
- package/src/contacts/canonical-guardian-store.ts +5 -0
- package/src/contacts/contact-store.ts +81 -35
- package/src/contacts/contacts-write.ts +50 -25
- package/src/contacts/member-write-relay.ts +115 -31
- package/src/contacts/types.ts +0 -8
- package/src/context/compactor.ts +29 -15
- package/src/context/outbound-sanitize.ts +202 -0
- package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
- package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
- package/src/daemon/abort-watchdog.ts +7 -0
- package/src/daemon/app-source-watcher.ts +9 -0
- package/src/daemon/assistant-attachments.ts +42 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
- package/src/daemon/conversation-agent-loop.ts +61 -68
- package/src/daemon/conversation-error.ts +1 -15
- package/src/daemon/conversation-history.ts +32 -236
- package/src/daemon/conversation-initial-prompt.ts +77 -0
- package/src/daemon/conversation-lifecycle.ts +25 -1
- package/src/daemon/conversation-messaging.ts +2 -2
- package/src/daemon/conversation-plugin-scope.ts +38 -0
- package/src/daemon/conversation-process.ts +50 -14
- package/src/daemon/conversation-runtime-assembly.ts +36 -6
- package/src/daemon/conversation-skill-tools.ts +19 -3
- package/src/daemon/conversation-store.ts +3 -3
- package/src/daemon/conversation-surfaces.ts +171 -0
- package/src/daemon/conversation-tool-setup.test.ts +95 -0
- package/src/daemon/conversation-tool-setup.ts +116 -1
- package/src/daemon/conversation-turn-finalize.ts +211 -0
- package/src/daemon/conversation.ts +92 -1
- package/src/daemon/disk-pressure-policy.ts +2 -1
- package/src/daemon/event-loop-watchdog.ts +22 -6
- package/src/daemon/external-plugins-bootstrap.ts +47 -134
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
- package/src/daemon/handlers/config-a2a.ts +7 -14
- package/src/daemon/handlers/config-channels.ts +2 -10
- package/src/daemon/handlers/conversation-history.ts +3 -1
- package/src/daemon/handlers/conversations.ts +0 -52
- package/src/daemon/handlers/shared.ts +4 -24
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +59 -472
- package/src/daemon/message-protocol.ts +3 -3
- package/src/daemon/message-provenance.ts +12 -14
- package/src/daemon/message-types/background-tools.ts +28 -0
- package/src/daemon/message-types/contacts.ts +2 -10
- package/src/daemon/message-types/conversations.ts +10 -0
- package/src/daemon/message-types/integrations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pointer-conversation-trust.ts +23 -9
- package/src/daemon/pointer-turn-runner.ts +174 -0
- package/src/daemon/providers-setup.ts +16 -0
- package/src/daemon/shutdown-handlers.ts +139 -47
- package/src/daemon/skill-memory-refresh.ts +2 -2
- package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
- package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
- package/src/daemon/tool-setup-types.ts +8 -0
- package/src/daemon/trust-context.ts +21 -6
- package/src/daemon/turn-latency-tracker.test.ts +93 -0
- package/src/daemon/turn-latency-tracker.ts +38 -0
- package/src/daemon/wake-conversation-ops.ts +10 -8
- package/src/documents/document-comments-store.test.ts +7 -1
- package/src/documents/document-comments-store.ts +8 -0
- package/src/documents/document-store.ts +15 -0
- package/src/export/__tests__/transcript-formatter.test.ts +11 -0
- package/src/export/transcript-formatter.ts +49 -67
- package/src/home/__tests__/feed-writer.test.ts +247 -1
- package/src/home/conversation-starter-checkpoints.ts +1 -0
- package/src/home/feed-writer.ts +61 -0
- package/src/home/job-handlers/conversation-starters.ts +1 -0
- package/src/hooks/hook-loader.ts +12 -0
- package/src/hooks/registry.ts +32 -4
- package/src/inbound/public-ingress-urls.ts +0 -17
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
- package/src/ipc/assistant-server.ts +28 -7
- package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
- package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
- package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
- package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
- package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
- package/src/ipc/routes/db-proxy.ts +5 -2
- package/src/ipc/routes/invite-ipc-routes.ts +53 -39
- package/src/jobs/worker.ts +9 -2
- package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
- package/src/live-voice/live-voice-archive.ts +5 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
- package/src/messaging/providers/channel-transport.ts +6 -0
- package/src/messaging/providers/index.ts +3 -0
- package/src/messaging/providers/slack/api.test.ts +49 -1
- package/src/messaging/providers/slack/api.ts +110 -0
- package/src/messaging/providers/slack/send.test.ts +85 -0
- package/src/messaging/providers/slack/send.ts +100 -28
- package/src/messaging/providers/slack/transport.ts +7 -13
- package/src/messaging/providers/whatsapp/send.ts +29 -9
- package/src/monitoring/__tests__/control.test.ts +235 -0
- package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
- package/src/monitoring/control.ts +105 -0
- package/src/monitoring/resource-sampler.ts +258 -0
- package/src/monitoring/sample-ring-buffer.ts +108 -0
- package/src/monitoring/worker.ts +94 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/access-request-copy.ts +94 -23
- package/src/notifications/adapters/slack.ts +89 -21
- package/src/notifications/approval-card-builder.ts +33 -18
- package/src/notifications/approval-card-data.ts +48 -15
- package/src/notifications/broadcaster.ts +25 -16
- package/src/notifications/decision-engine.ts +131 -32
- package/src/notifications/guardian-question-mode.ts +58 -10
- package/src/permissions/approval-policy.ts +8 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/gateway-threshold-reader.ts +7 -6
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/secret-prompter.ts +11 -3
- package/src/permissions/types.ts +2 -2
- package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
- package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
- package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
- package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
- package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
- package/src/persistence/a2a-invite-store.ts +205 -0
- package/src/persistence/attachments-store.ts +94 -10
- package/src/persistence/checkpoints.ts +45 -0
- package/src/persistence/conversation-crud.ts +453 -260
- package/src/persistence/conversation-display-order-migration.ts +8 -2
- package/src/persistence/conversation-group-migration.test.ts +8 -0
- package/src/persistence/conversation-group-migration.ts +9 -0
- package/src/persistence/conversation-queries.ts +244 -125
- package/src/persistence/conversation-row-batch-delete.ts +9 -5
- package/src/persistence/conversation-search-lexical.ts +49 -0
- package/src/persistence/db-async-query.ts +42 -0
- package/src/persistence/db-connection.ts +13 -0
- package/src/persistence/delivery-channels.ts +0 -82
- package/src/persistence/delivery-crud.ts +27 -6
- package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
- package/src/persistence/embeddings/embedding-identity.ts +17 -5
- package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
- package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
- package/src/persistence/embeddings/qdrant-client.ts +81 -5
- package/src/persistence/group-crud.ts +13 -1
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
- package/src/persistence/job-handlers/cleanup.ts +57 -9
- package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
- package/src/persistence/job-handlers/message-lexical.ts +251 -0
- package/src/persistence/jobs-store.ts +102 -8
- package/src/persistence/jobs-worker.ts +68 -28
- package/src/persistence/llm-request-log-store.ts +35 -19
- package/src/persistence/llm-usage-store.ts +11 -0
- package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
- package/src/persistence/memory-lifecycle-hooks.ts +55 -1
- package/src/persistence/migrations/028-call-session-mode.ts +1 -1
- package/src/persistence/migrations/116-messages-fts.ts +8 -1
- package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
- package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
- package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
- package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
- package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
- package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
- package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
- package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
- package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
- package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
- package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
- package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
- package/src/persistence/raw-query.ts +50 -11
- package/src/persistence/schema/a2a.ts +14 -0
- package/src/persistence/schema/contacts.ts +0 -62
- package/src/persistence/schema/conversation-groups.ts +12 -0
- package/src/persistence/schema/conversations.ts +2 -0
- package/src/persistence/schema/documents.ts +65 -0
- package/src/persistence/schema/guardian.ts +4 -0
- package/src/persistence/schema/index.ts +4 -0
- package/src/persistence/schema/memory-injection.ts +62 -0
- package/src/persistence/schema/workflows.ts +55 -0
- package/src/persistence/slow-query-log.ts +437 -0
- package/src/persistence/slow-sync-log.ts +204 -0
- package/src/persistence/steps.ts +16 -0
- package/src/persistence/subagent-store.ts +125 -0
- package/src/persistence/worker-control.ts +45 -238
- package/src/plugin-api/event-hub-facade.ts +172 -0
- package/src/plugin-api/index.ts +9 -1
- package/src/plugin-api/types.ts +40 -9
- package/src/plugins/defaults/default-plugin-names.ts +60 -0
- package/src/plugins/defaults/index.ts +19 -29
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
- package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
- package/src/plugins/defaults/memory/config.ts +11 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
- package/src/plugins/defaults/memory/embeddings.ts +77 -0
- package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
- package/src/plugins/defaults/memory/frontmatter.ts +50 -0
- package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
- package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
- package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
- package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
- package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
- package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
- package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
- package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
- package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
- package/src/plugins/defaults/memory/graph/tools.ts +1 -1
- package/src/plugins/defaults/memory/hooks/init.ts +31 -5
- package/src/plugins/defaults/memory/indexer.ts +2 -3
- package/src/plugins/defaults/memory/injectors.ts +2 -2
- package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
- package/src/plugins/defaults/memory/job-handlers.ts +13 -12
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
- package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
- package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
- package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
- package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
- package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
- package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
- package/src/plugins/defaults/memory/search/semantic.ts +2 -2
- package/src/plugins/defaults/memory/startup.ts +244 -0
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
- package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
- package/src/plugins/defaults/memory/v2/activation.ts +2 -4
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
- package/src/plugins/defaults/memory/v2/migration.ts +2 -5
- package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
- package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
- package/src/plugins/defaults/memory/v2/router.ts +5 -5
- package/src/plugins/defaults/memory/v2/sim.ts +2 -4
- package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
- package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
- package/src/plugins/defaults/memory/v3/card.ts +1 -4
- package/src/plugins/defaults/memory/v3/dense.ts +60 -25
- package/src/plugins/defaults/memory/v3/edge.ts +1 -1
- package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
- package/src/plugins/defaults/memory/v3/gate.ts +158 -0
- package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
- package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
- package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
- package/src/plugins/defaults/memory/v3/prune.ts +2 -2
- package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
- package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
- package/src/plugins/defaults/turn-context/injectors.ts +1 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
- package/src/plugins/injector-registry.ts +13 -2
- package/src/plugins/mtime-cache.ts +36 -47
- package/src/plugins/pipeline.ts +15 -1
- package/src/plugins/types.ts +14 -23
- package/src/prompts/__tests__/system-prompt.test.ts +170 -32
- package/src/prompts/persona-resolver.ts +13 -9
- package/src/prompts/system-prompt.ts +30 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -119
- package/src/prompts/templates/SOUL.md +43 -13
- package/src/prompts/templates/system-sections.ts +32 -27
- package/src/prompts/templates/users/default.md +19 -0
- package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +14 -1
- package/src/providers/openai/responses-provider.ts +18 -0
- package/src/providers/placeholder-sentinels.ts +18 -8
- package/src/providers/retry.ts +1 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
- package/src/providers/speech-to-text/provider-catalog.ts +0 -89
- package/src/providers/speech-to-text/resolve.ts +55 -0
- package/src/providers/tool-progress-events.test.ts +50 -0
- package/src/providers/tool-progress-events.ts +99 -0
- package/src/providers/types.ts +1 -1
- package/src/providers/vellum-model-routing.test.ts +51 -0
- package/src/providers/vellum-model-routing.ts +84 -0
- package/src/runtime/AGENTS.md +5 -4
- package/src/runtime/__tests__/agent-wake.test.ts +158 -1
- package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
- package/src/runtime/access-request-helper.ts +154 -3
- package/src/runtime/actor-trust-resolver.ts +7 -21
- package/src/runtime/agent-wake.ts +41 -1
- package/src/runtime/assistant-event.ts +86 -12
- package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
- package/src/runtime/channel-approval-types.ts +52 -2
- package/src/runtime/channel-approvals.ts +23 -8
- package/src/runtime/channel-invite-transport.ts +2 -2
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-readiness-service.ts +3 -5
- package/src/runtime/channel-retry-sweep.ts +18 -24
- package/src/runtime/channel-verification-service.ts +9 -11
- package/src/runtime/finalize-event-delivery.ts +30 -16
- package/src/runtime/guardian-action-service.ts +10 -11
- package/src/runtime/guardian-reply-router.ts +122 -21
- package/src/runtime/http-server.ts +44 -101
- package/src/runtime/introduction-policy.test.ts +214 -0
- package/src/runtime/introduction-policy.ts +284 -0
- package/src/runtime/invite-service.ts +104 -361
- package/src/runtime/local-actor-identity.test.ts +38 -0
- package/src/runtime/local-actor-identity.ts +14 -0
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
- package/src/runtime/middleware/rate-limiter.ts +30 -0
- package/src/runtime/middleware/twilio-validation.ts +5 -7
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
- package/src/runtime/migrations/origin-mode.ts +6 -6
- package/src/runtime/pre-first-message-gate.ts +1 -0
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
- package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +15 -3
- package/src/runtime/routes/app-management-routes.ts +4 -7
- package/src/runtime/routes/approval-routes.ts +4 -0
- package/src/runtime/routes/attachment-routes.ts +54 -3
- package/src/runtime/routes/avatar-routes.ts +0 -4
- package/src/runtime/routes/background-tool-routes.ts +34 -5
- package/src/runtime/routes/btw-routes.ts +32 -4
- package/src/runtime/routes/channel-route-shared.ts +18 -14
- package/src/runtime/routes/channel-verification-routes.ts +0 -3
- package/src/runtime/routes/contact-routes.ts +298 -117
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +74 -37
- package/src/runtime/routes/conversation-query-routes.ts +5 -2
- package/src/runtime/routes/conversation-routes.ts +222 -82
- package/src/runtime/routes/conversations-import-routes.ts +8 -1
- package/src/runtime/routes/credential-prompt-routes.ts +20 -5
- package/src/runtime/routes/debug-routes.ts +1 -0
- package/src/runtime/routes/documents-routes.ts +5 -2
- package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
- package/src/runtime/routes/global-search-routes.ts +2 -1
- package/src/runtime/routes/guardian-approval-interception.ts +51 -0
- package/src/runtime/routes/home-feed-routes.ts +60 -1
- package/src/runtime/routes/identity-routes.ts +4 -87
- package/src/runtime/routes/inbound-message-handler.ts +82 -41
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
- package/src/runtime/routes/internal-twilio-routes.ts +0 -15
- package/src/runtime/routes/messages-lexical-routes.ts +75 -0
- package/src/runtime/routes/migration-routes.ts +69 -6
- package/src/runtime/routes/monitoring-routes.ts +237 -0
- package/src/runtime/routes/plugins-routes.ts +329 -8
- package/src/runtime/routes/schedule-routes.ts +49 -8
- package/src/runtime/routes/schedule-worker-routes.ts +210 -0
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
- package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
- package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
- package/src/runtime/services/analyze-conversation.ts +14 -4
- package/src/runtime/services/conversation-serializer.ts +5 -0
- package/src/runtime/slack-no-response.ts +47 -0
- package/src/runtime/slack-reply-session.test.ts +633 -0
- package/src/runtime/slack-reply-session.ts +382 -0
- package/src/runtime/slack-task-progress.ts +95 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/tool-grant-request-helper.ts +17 -1
- package/src/runtime/trust-class.test.ts +141 -0
- package/src/runtime/trust-class.ts +121 -0
- package/src/runtime/trust-verdict-consumer.ts +7 -6
- package/src/schedule/__tests__/run-script.test.ts +21 -0
- package/src/schedule/__tests__/worker-control.test.ts +241 -0
- package/src/schedule/run-script.ts +13 -6
- package/src/schedule/schedule-usage-store.ts +1 -0
- package/src/schedule/scheduler.ts +178 -127
- package/src/schedule/worker-control.ts +118 -0
- package/src/schedule/worker.ts +131 -0
- package/src/skills/__tests__/categories-cache.test.ts +38 -0
- package/src/skills/categories-cache.ts +40 -5
- package/src/skills/managed-store.ts +41 -6
- package/src/skills/validate-input.ts +47 -0
- package/src/stt/types.ts +5 -9
- package/src/subagent/manager.ts +267 -39
- package/src/subagent/types.ts +6 -2
- package/src/subagent/validate-allowlists.ts +65 -0
- package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
- package/src/telemetry/watchdog-direct-emit.ts +89 -0
- package/src/tools/acp/list-agents.test.ts +0 -6
- package/src/tools/background-tool-registry.ts +61 -0
- package/src/tools/document/document-comment-tool.test.ts +4 -0
- package/src/tools/host-terminal/host-shell.test.ts +397 -0
- package/src/tools/host-terminal/host-shell.ts +203 -14
- package/src/tools/skills/find-similar-skills.test.ts +152 -1
- package/src/tools/skills/find-similar-skills.ts +30 -4
- package/src/tools/skills/load.ts +36 -0
- package/src/tools/skills/scaffold-managed.ts +66 -34
- package/src/tools/skills/skill-script-runner.ts +17 -0
- package/src/tools/skills/skill-tool-factory.ts +5 -1
- package/src/tools/terminal/safe-env.ts +3 -0
- package/src/tools/terminal/shell.test.ts +177 -0
- package/src/tools/terminal/shell.ts +98 -4
- package/src/tools/tool-approval-handler.ts +106 -29
- package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
- package/src/tools/types.ts +29 -17
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tts/__tests__/provider-adapters.test.ts +37 -0
- package/src/tts/__tests__/provider-catalog.test.ts +21 -0
- package/src/tts/provider-catalog.ts +40 -9
- package/src/tts/providers/fish-audio-provider.ts +19 -10
- package/src/tts/types.ts +3 -4
- package/src/util/__tests__/process-tree.test.ts +10 -2
- package/src/util/__tests__/text-spacing.test.ts +53 -0
- package/src/util/cgroup-memory.ts +142 -0
- package/src/util/image-conversion.ts +281 -0
- package/src/util/phone.ts +1 -8
- package/src/util/platform.ts +33 -0
- package/src/util/process-tree.ts +10 -2
- package/src/util/text-spacing.ts +53 -0
- package/src/util/worker-process.ts +271 -0
- package/src/workflows/journal-store.ts +16 -1
- package/src/workflows/library.test.ts +35 -20
- package/src/workflows/library.ts +105 -66
- package/src/workspace/git-service.ts +1 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
- package/src/workspace/migrations/118-seed-now-md.ts +64 -0
- package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
- package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
- package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
- package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
- package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
- package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/drizzle/0000_dizzy_maggott.sql +0 -301
- package/drizzle/meta/0000_snapshot.json +0 -1933
- package/drizzle/meta/_journal.json +0 -13
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
- package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
- package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
- package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
- package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
- package/src/__tests__/invite-redemption-service.test.ts +0 -1180
- package/src/__tests__/invite-service-ipc.test.ts +0 -350
- package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
- package/src/__tests__/relay-server.test.ts +0 -6153
- package/src/__tests__/telephony-stt-routing.test.ts +0 -329
- package/src/__tests__/voice-invite-redemption.test.ts +0 -702
- package/src/calls/relay-server.ts +0 -2463
- package/src/calls/telephony-stt-routing.ts +0 -145
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
- package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
- package/src/daemon/daemon-skill-host.ts +0 -262
- package/src/daemon/message-types/meet.ts +0 -143
- package/src/daemon/shutdown-registry.ts +0 -40
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
- package/src/ipc/__tests__/skill-server.test.ts +0 -182
- package/src/ipc/skill-ipc-types.ts +0 -54
- package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
- package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
- package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
- package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
- package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
- package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
- package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
- package/src/ipc/skill-routes/config.ts +0 -47
- package/src/ipc/skill-routes/events.ts +0 -147
- package/src/ipc/skill-routes/identity.ts +0 -21
- package/src/ipc/skill-routes/index.ts +0 -37
- package/src/ipc/skill-routes/log.ts +0 -40
- package/src/ipc/skill-routes/memory.ts +0 -92
- package/src/ipc/skill-routes/platform.ts +0 -39
- package/src/ipc/skill-routes/providers.ts +0 -162
- package/src/ipc/skill-routes/registries.ts +0 -338
- package/src/ipc/skill-server.ts +0 -831
- package/src/ipc/skill-socket-path.ts +0 -20
- package/src/jobs/register-job-handlers.ts +0 -74
- package/src/persistence/invite-store.ts +0 -481
- package/src/plugins/job-handler-registry.ts +0 -94
- package/src/providers/cache-control.ts +0 -26
- package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
- package/src/runtime/invite-redemption-service.ts +0 -828
- package/src/runtime/invite-redemption-templates.ts +0 -46
- package/src/runtime/runtime-mode.ts +0 -40
- package/src/runtime/slack-dm-text-delivery.ts +0 -177
- package/src/util/voice-code.ts +0 -31
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Construction-time system-prompt resolution for a new conversation.
|
|
3
|
+
*
|
|
4
|
+
* The dependency seams (`fetchDelivery`, `deps.warm`, `deps.build`) exist so the
|
|
5
|
+
* warm-then-build sequencing can be unit-tested without mocking the
|
|
6
|
+
* widely-imported guardian-delivery / system-prompt modules — global module
|
|
7
|
+
* mocks of those leak across test files in the shared-process runner.
|
|
8
|
+
*/
|
|
9
|
+
import { getGuardianDeliveryFresh } from "../contacts/guardian-delivery-reader.js";
|
|
10
|
+
import { buildSystemPrompt } from "../prompts/system-prompt.js";
|
|
11
|
+
import type { ConversationCreateOptions } from "./handlers/shared.js";
|
|
12
|
+
import type { TrustContext } from "./trust-context.js";
|
|
13
|
+
|
|
14
|
+
type GuardianDeliveryFetch = (input?: {
|
|
15
|
+
channelTypes?: string[];
|
|
16
|
+
}) => Promise<unknown>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Warm both guardian-binding cache keys the desktop/native persona resolver
|
|
20
|
+
* reads: the `"vellum"`-channel key for `peekGuardianForChannel("vellum")` and
|
|
21
|
+
* the unfiltered key for its `peekAnyGuardian()` fallback. Warming only one
|
|
22
|
+
* would still freeze `users/default.md` when the guardian lives on a non-vellum
|
|
23
|
+
* channel (phone / Telegram).
|
|
24
|
+
*
|
|
25
|
+
* Uses the FRESH reader so warmup bypasses a stale/empty cached entry: a
|
|
26
|
+
* gateway-side binding write (onboarding, rebind) does not invalidate the daemon
|
|
27
|
+
* cache, so a non-fresh read could return an empty binding cached before the
|
|
28
|
+
* guardian existed and freeze `users/default.md` until the TTL expires. The
|
|
29
|
+
* fresh read repopulates the cache the sync `peek*` resolvers then read.
|
|
30
|
+
* Best-effort — the reader swallows failures.
|
|
31
|
+
*/
|
|
32
|
+
export async function warmGuardianBindings(
|
|
33
|
+
fetchDelivery: GuardianDeliveryFetch = getGuardianDeliveryFresh,
|
|
34
|
+
): Promise<void> {
|
|
35
|
+
await Promise.all([
|
|
36
|
+
fetchDelivery({ channelTypes: ["vellum"] }),
|
|
37
|
+
fetchDelivery(),
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the system prompt to freeze onto a newly constructed conversation.
|
|
43
|
+
*
|
|
44
|
+
* The conversation's prompt is built once here and reused for every turn (the
|
|
45
|
+
* agent loop never re-resolves it), so the persona slot must resolve correctly
|
|
46
|
+
* at construction.
|
|
47
|
+
*
|
|
48
|
+
* - An explicit `systemPromptOverride` (including an empty string) is used
|
|
49
|
+
* verbatim.
|
|
50
|
+
* - A channel-routed conversation that already carries the requester's
|
|
51
|
+
* `trustContext` (e.g. Slack / Telegram inbound) builds with it, so the
|
|
52
|
+
* persona resolves the *requester's* `users/<slug>.md` (a DB contact lookup)
|
|
53
|
+
* rather than the guardian/default profile.
|
|
54
|
+
* - Otherwise (no construction-time identity — the local vellum app sets trust
|
|
55
|
+
* after creation) the guardian binding is warmed first so the persona slot
|
|
56
|
+
* resolves the guardian's `users/<slug>.md` instead of `users/default.md` on
|
|
57
|
+
* a cold cache.
|
|
58
|
+
*/
|
|
59
|
+
export async function resolveInitialSystemPrompt(
|
|
60
|
+
storedOptions: ConversationCreateOptions | undefined,
|
|
61
|
+
deps: {
|
|
62
|
+
warm?: () => Promise<void>;
|
|
63
|
+
build?: (trustContext: TrustContext | undefined) => string;
|
|
64
|
+
} = {},
|
|
65
|
+
): Promise<string> {
|
|
66
|
+
if (storedOptions?.systemPromptOverride !== undefined) {
|
|
67
|
+
return storedOptions.systemPromptOverride;
|
|
68
|
+
}
|
|
69
|
+
const trustContext = storedOptions?.trustContext;
|
|
70
|
+
if (trustContext === undefined) {
|
|
71
|
+
await (deps.warm ?? warmGuardianBindings)();
|
|
72
|
+
}
|
|
73
|
+
const build =
|
|
74
|
+
deps.build ??
|
|
75
|
+
((tc: TrustContext | undefined) => buildSystemPrompt({ trustContext: tc }));
|
|
76
|
+
return build(trustContext);
|
|
77
|
+
}
|
|
@@ -69,6 +69,7 @@ export function reinjectImageSourcePaths(
|
|
|
69
69
|
export interface AbortContext {
|
|
70
70
|
readonly conversationId: string;
|
|
71
71
|
isProcessing(): boolean;
|
|
72
|
+
setProcessing(value: boolean): void;
|
|
72
73
|
abortController: AbortController | null;
|
|
73
74
|
prompter: PermissionPrompter;
|
|
74
75
|
secretPrompter: SecretPrompter;
|
|
@@ -125,7 +126,30 @@ export function abortConversation(
|
|
|
125
126
|
{ conversationId: ctx.conversationId, abortReason: effectiveReason },
|
|
126
127
|
"Aborting in-flight processing",
|
|
127
128
|
);
|
|
128
|
-
ctx.abortController
|
|
129
|
+
if (ctx.abortController) {
|
|
130
|
+
// A live turn owns this controller. Signal it and let the agent loop's
|
|
131
|
+
// own `finally` observe the abort, unwind, and clear the processing flag
|
|
132
|
+
// — that path clears it with the correct sync-invalidation ordering
|
|
133
|
+
// (after the awaited turn-boundary commit), so we deliberately do NOT
|
|
134
|
+
// clear it here and risk clobbering a client's optimistic state.
|
|
135
|
+
ctx.abortController.abort(effectiveReason);
|
|
136
|
+
} else {
|
|
137
|
+
// The flag is set but there is no live controller to signal: the turn
|
|
138
|
+
// that owned it already tore its controller down (the agent-loop
|
|
139
|
+
// `finally` nulls `abortController` before clearing the flag) or died
|
|
140
|
+
// without ever installing one. Either way no agent-loop `finally` is
|
|
141
|
+
// going to run to clear the flag. Without this branch the abort is a
|
|
142
|
+
// silent no-op — `?.abort()` does nothing — and the conversation stays
|
|
143
|
+
// wedged: every later submit is rejected with "already processing" and
|
|
144
|
+
// Stop appears dead. Force-clear the flag directly so the conversation
|
|
145
|
+
// frees up. `setProcessing(false)` also nulls the persisted column and
|
|
146
|
+
// emits the metadata invalidation that drives clients to idle.
|
|
147
|
+
log.warn(
|
|
148
|
+
{ conversationId: ctx.conversationId },
|
|
149
|
+
"Abort requested while processing but no live abort controller — force-clearing stale processing flag",
|
|
150
|
+
);
|
|
151
|
+
ctx.setProcessing(false);
|
|
152
|
+
}
|
|
129
153
|
ctx.prompter.dispose();
|
|
130
154
|
ctx.secretPrompter.dispose();
|
|
131
155
|
ctx.pendingSurfaceActions.clear();
|
|
@@ -551,7 +551,7 @@ export async function persistQueuedMessageBody(
|
|
|
551
551
|
ctx.conversationId,
|
|
552
552
|
"user",
|
|
553
553
|
contentToPersist,
|
|
554
|
-
{ metadata: mergedMetadata, clientMessageId },
|
|
554
|
+
{ metadata: mergedMetadata, clientMessageId, id: requestId },
|
|
555
555
|
);
|
|
556
556
|
|
|
557
557
|
if (persistedUserMessage.deduplicated) {
|
|
@@ -613,7 +613,7 @@ export async function persistQueuedMessageBody(
|
|
|
613
613
|
a.filename,
|
|
614
614
|
a.mimeType,
|
|
615
615
|
a.data,
|
|
616
|
-
{ sourcePath: a.filePath },
|
|
616
|
+
{ sourcePath: a.filePath, normalizeImage: true },
|
|
617
617
|
);
|
|
618
618
|
} catch (err) {
|
|
619
619
|
if (err instanceof AttachmentUploadError) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a conversation's effective plugin scope for the hook pipeline.
|
|
3
|
+
*
|
|
4
|
+
* The hook pipeline calls this by `conversationId` so lifecycle hooks honor
|
|
5
|
+
* the per-chat plugin selection. Resolution is memory-then-DB: prefer the live
|
|
6
|
+
* conversation/subagent (so a mid-conversation selection change applies to the
|
|
7
|
+
* next turn's hooks), falling back to the persisted `enabled_plugins` row when
|
|
8
|
+
* no live instance is resident. `null` means no per-chat restriction — every
|
|
9
|
+
* globally-enabled plugin's hooks run.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { getConversationEnabledPlugins } from "../persistence/conversation-crud.js";
|
|
13
|
+
import { getLogger } from "../util/logger.js";
|
|
14
|
+
import { findConversationOrSubagent } from "./conversation-registry.js";
|
|
15
|
+
import { getEffectiveEnabledPluginSet } from "./conversation-tool-setup.js";
|
|
16
|
+
|
|
17
|
+
const log = getLogger("conversation-plugin-scope");
|
|
18
|
+
|
|
19
|
+
/** Resolve `conversationId`'s effective plugin scope; `null` = no restriction. */
|
|
20
|
+
export function resolveConversationPluginScope(
|
|
21
|
+
conversationId: string,
|
|
22
|
+
): Set<string> | null {
|
|
23
|
+
const live = findConversationOrSubagent(conversationId);
|
|
24
|
+
if (live) return getEffectiveEnabledPluginSet(live);
|
|
25
|
+
// Fall back to the persisted row for a non-resident conversation. A failure
|
|
26
|
+
// here must not break hook discovery — fail open to no restriction so the
|
|
27
|
+
// turn's hooks still run, rather than dropping every plugin's lifecycle hook.
|
|
28
|
+
try {
|
|
29
|
+
const enabledPlugins = getConversationEnabledPlugins(conversationId);
|
|
30
|
+
return getEffectiveEnabledPluginSet({ enabledPlugins });
|
|
31
|
+
} catch (err) {
|
|
32
|
+
log.debug(
|
|
33
|
+
{ err, conversationId },
|
|
34
|
+
"Failed to resolve per-chat plugin scope from DB; applying no restriction",
|
|
35
|
+
);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -23,6 +23,7 @@ import { extractPreferences } from "../notifications/preference-extractor.js";
|
|
|
23
23
|
import { createPreference } from "../notifications/preferences-store.js";
|
|
24
24
|
import {
|
|
25
25
|
addMessage,
|
|
26
|
+
isHiddenMessageMetadata,
|
|
26
27
|
provenanceFromTrustContext,
|
|
27
28
|
setConversationOriginChannelIfUnset,
|
|
28
29
|
setConversationOriginInterfaceIfUnset,
|
|
@@ -61,19 +62,30 @@ import { resolveVerificationSessionIntent } from "./verification-session-intent.
|
|
|
61
62
|
const log = getLogger("conversation-process");
|
|
62
63
|
|
|
63
64
|
/**
|
|
64
|
-
* Daemon-injected run lifecycle notifications — subagent (`subagentNotification`)
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* the
|
|
65
|
+
* Daemon-injected run lifecycle notifications — subagent (`subagentNotification`),
|
|
66
|
+
* ACP run (`acpNotification`), and any wake trigger (the persisted
|
|
67
|
+
* `<background_event source="...">` row every wake reads) — are persisted into
|
|
68
|
+
* the parent conversation so the orchestrator wakes and reads the trigger, but
|
|
69
|
+
* they are internal scaffolding: the user sees the wake through its inline card
|
|
70
|
+
* ("Conversation Woke", or a terminal card for a backgrounded bash run), not a
|
|
71
|
+
* chat turn. Skip the `user_message_echo` broadcast for these so they never
|
|
72
|
+
* render as a live user bubble; the persisted row is filtered from the rendered
|
|
73
|
+
* transcript on the client.
|
|
74
|
+
*
|
|
75
|
+
* Messages explicitly flagged `hidden` (a hidden `POST /messages` send that
|
|
76
|
+
* queued behind an in-flight turn, e.g. the channel-setup wizard-close
|
|
77
|
+
* marker) are suppressed the same way — the immediate route path already
|
|
78
|
+
* skips their echo, and the persisted `hidden` metadata keeps them out of
|
|
79
|
+
* the fetched transcript.
|
|
71
80
|
*/
|
|
72
|
-
function
|
|
81
|
+
function isEchoSuppressedUserMessage(
|
|
73
82
|
metadata: Record<string, unknown> | undefined,
|
|
74
83
|
): boolean {
|
|
75
84
|
return (
|
|
76
|
-
metadata
|
|
85
|
+
isHiddenMessageMetadata(metadata) ||
|
|
86
|
+
metadata?.subagentNotification != null ||
|
|
87
|
+
metadata?.acpNotification != null ||
|
|
88
|
+
typeof metadata?.backgroundEventSource === "string"
|
|
77
89
|
);
|
|
78
90
|
}
|
|
79
91
|
|
|
@@ -242,6 +254,11 @@ async function buildPassthroughBatch(
|
|
|
242
254
|
// otherwise diverge.
|
|
243
255
|
if (candIf?.userMessageInterface !== headInterface?.userMessageInterface)
|
|
244
256
|
break;
|
|
257
|
+
// The batched turn applies only the head's `clientOs`, so messages from a
|
|
258
|
+
// different OS surface must not coalesce. The web, iOS, and macOS apps all
|
|
259
|
+
// report `interfaceId: "web"`, so the interface check above no longer
|
|
260
|
+
// separates them — split on the reported OS explicitly.
|
|
261
|
+
if (candidate.transport?.clientOs !== head.transport?.clientOs) break;
|
|
245
262
|
if (candidate.sourceActorPrincipalId !== head.sourceActorPrincipalId) break;
|
|
246
263
|
if (classifySlash(candidate.content) !== "passthrough") break;
|
|
247
264
|
if (
|
|
@@ -441,6 +458,7 @@ async function drainSingleMessage(
|
|
|
441
458
|
// and queue-drain stay in sync without duplicating the gate logic.
|
|
442
459
|
conversation.applyHostEnvFromTransport(next.transport);
|
|
443
460
|
conversation.applyClientTimezoneFromTransport(next.transport);
|
|
461
|
+
conversation.applyClientOsFromTransport(next.transport);
|
|
444
462
|
}
|
|
445
463
|
|
|
446
464
|
conversation.currentTurnAuthContext = next.authContext;
|
|
@@ -512,6 +530,7 @@ async function drainSingleMessage(
|
|
|
512
530
|
}
|
|
513
531
|
: {}),
|
|
514
532
|
...(next.metadata?.automated ? { automated: true } : {}),
|
|
533
|
+
...(next.metadata?.hidden === true ? { hidden: true } : {}),
|
|
515
534
|
...(Object.keys(drainImageSourcePaths).length > 0
|
|
516
535
|
? { imageSourcePaths: drainImageSourcePaths }
|
|
517
536
|
: {}),
|
|
@@ -870,7 +889,7 @@ async function drainSingleMessage(
|
|
|
870
889
|
|
|
871
890
|
// Broadcast the user message to all hub subscribers so passive devices
|
|
872
891
|
// see the user turn before the assistant reply starts streaming.
|
|
873
|
-
if (!
|
|
892
|
+
if (!isEchoSuppressedUserMessage(next.metadata)) {
|
|
874
893
|
next.onEvent({
|
|
875
894
|
type: "user_message_echo",
|
|
876
895
|
text: resolvedContent,
|
|
@@ -888,7 +907,10 @@ async function drainSingleMessage(
|
|
|
888
907
|
|
|
889
908
|
// Fire-and-forget: detect notification preferences in the queued message
|
|
890
909
|
// and persist any that are found, mirroring the logic in processMessage.
|
|
891
|
-
|
|
910
|
+
// Hidden rows are machine signals, not user speech — running the detector
|
|
911
|
+
// on them burns an LLM call per signal and risks persisting a bogus
|
|
912
|
+
// preference from text the user never typed.
|
|
913
|
+
if (conversation.assistantId && !isHiddenMessageMetadata(next.metadata)) {
|
|
892
914
|
extractPreferences(resolvedContent)
|
|
893
915
|
.then((result) => {
|
|
894
916
|
if (!result.detected) return;
|
|
@@ -923,11 +945,14 @@ async function drainSingleMessage(
|
|
|
923
945
|
isInteractive?: boolean;
|
|
924
946
|
isUserMessage?: boolean;
|
|
925
947
|
titleText?: string;
|
|
948
|
+
isHiddenPrompt?: boolean;
|
|
926
949
|
} = { isUserMessage: true };
|
|
927
950
|
if (next.isInteractive !== undefined)
|
|
928
951
|
drainLoopOptions.isInteractive = next.isInteractive;
|
|
929
952
|
if (agentLoopContent !== resolvedContent)
|
|
930
953
|
drainLoopOptions.titleText = resolvedContent;
|
|
954
|
+
if (isHiddenMessageMetadata(next.metadata))
|
|
955
|
+
drainLoopOptions.isHiddenPrompt = true;
|
|
931
956
|
|
|
932
957
|
conversation
|
|
933
958
|
.runAgentLoop(agentLoopContent, userMessageId, {
|
|
@@ -1002,6 +1027,7 @@ async function drainBatch(
|
|
|
1002
1027
|
conversation.setTransportHints(buildTransportHints(head.transport));
|
|
1003
1028
|
conversation.applyHostEnvFromTransport(head.transport);
|
|
1004
1029
|
conversation.applyClientTimezoneFromTransport(head.transport);
|
|
1030
|
+
conversation.applyClientOsFromTransport(head.transport);
|
|
1005
1031
|
}
|
|
1006
1032
|
|
|
1007
1033
|
conversation.currentTurnAuthContext = head.authContext;
|
|
@@ -1223,7 +1249,7 @@ async function drainBatch(
|
|
|
1223
1249
|
|
|
1224
1250
|
// Broadcast the user message to all hub subscribers so passive devices
|
|
1225
1251
|
// see each batched user turn before the assistant reply starts streaming.
|
|
1226
|
-
if (!
|
|
1252
|
+
if (!isEchoSuppressedUserMessage(qm.metadata)) {
|
|
1227
1253
|
qm.onEvent({
|
|
1228
1254
|
type: "user_message_echo",
|
|
1229
1255
|
text: qmContent,
|
|
@@ -1244,8 +1270,9 @@ async function drainBatch(
|
|
|
1244
1270
|
successfulBatch.push(qm);
|
|
1245
1271
|
|
|
1246
1272
|
// Fire-and-forget: detect notification preferences in each batched user
|
|
1247
|
-
// message and persist any that are found, mirroring drainSingleMessage
|
|
1248
|
-
|
|
1273
|
+
// message and persist any that are found, mirroring drainSingleMessage
|
|
1274
|
+
// (including its hidden-row exclusion).
|
|
1275
|
+
if (conversation.assistantId && !isHiddenMessageMetadata(qm.metadata)) {
|
|
1249
1276
|
extractPreferences(qmContent)
|
|
1250
1277
|
.then((result) => {
|
|
1251
1278
|
if (!result.detected) return;
|
|
@@ -1332,6 +1359,7 @@ async function drainBatch(
|
|
|
1332
1359
|
isInteractive?: boolean;
|
|
1333
1360
|
isUserMessage?: boolean;
|
|
1334
1361
|
titleText?: string;
|
|
1362
|
+
isHiddenPrompt?: boolean;
|
|
1335
1363
|
} = { isUserMessage: true };
|
|
1336
1364
|
// Source interactive flag from the last successfully-persisted sibling so
|
|
1337
1365
|
// a trailing failed tail doesn't flip the agent loop's interactivity.
|
|
@@ -1341,6 +1369,14 @@ async function drainBatch(
|
|
|
1341
1369
|
: undefined;
|
|
1342
1370
|
if (lastSuccessfulBatchEntry?.isInteractive !== undefined)
|
|
1343
1371
|
drainLoopOptions.isInteractive = lastSuccessfulBatchEntry.isInteractive;
|
|
1372
|
+
// A batch counts as a hidden turn only when every message in it is a
|
|
1373
|
+
// hidden machine signal — one genuine user prompt justifies the
|
|
1374
|
+
// prompt-as-user-speech consumers (title generation).
|
|
1375
|
+
if (
|
|
1376
|
+
successfulBatch.length > 0 &&
|
|
1377
|
+
successfulBatch.every((qm) => isHiddenMessageMetadata(qm.metadata))
|
|
1378
|
+
)
|
|
1379
|
+
drainLoopOptions.isHiddenPrompt = true;
|
|
1344
1380
|
|
|
1345
1381
|
// Fire-and-forget: runAgentLoop's finally block recursively calls drainQueue
|
|
1346
1382
|
// when this run completes. Mirrors drainSingleMessage.
|
|
@@ -71,6 +71,7 @@ import type { SubagentState } from "../subagent/types.js";
|
|
|
71
71
|
import { TERMINAL_STATUSES } from "../subagent/types.js";
|
|
72
72
|
import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
|
|
73
73
|
import { findConversationOrSubagent } from "./conversation-registry.js";
|
|
74
|
+
import { getEffectiveEnabledPluginSet } from "./conversation-tool-setup.js";
|
|
74
75
|
import { canonicalizeTimeZone, formatTurnTimestamp } from "./date-context.js";
|
|
75
76
|
import type {
|
|
76
77
|
DynamicPageSurfaceData,
|
|
@@ -165,9 +166,10 @@ export function inboundActorContextFromTrustContext(
|
|
|
165
166
|
*
|
|
166
167
|
* Returns `null` when there is no trust context and on guardian (owner) turns —
|
|
167
168
|
* the actor section is suppressed for the owner. ACL fields (trust class,
|
|
168
|
-
* member status/policy, guardian binding)
|
|
169
|
-
*
|
|
170
|
-
* contact ID. Derives purely from the passed trust context,
|
|
169
|
+
* member status/policy, guardian binding) and the gateway-owned interaction
|
|
170
|
+
* count come from the verdict-derived trust context; the INFO `notes` field is
|
|
171
|
+
* joined locally by contact ID. Derives purely from the passed trust context,
|
|
172
|
+
* so callers
|
|
171
173
|
* self-resolve it from the live conversation rather than threading it.
|
|
172
174
|
*/
|
|
173
175
|
export function resolveTurnInboundActorContext(
|
|
@@ -180,11 +182,13 @@ export function resolveTurnInboundActorContext(
|
|
|
180
182
|
if (resolved.trustClass === "guardian") {
|
|
181
183
|
return null;
|
|
182
184
|
}
|
|
185
|
+
// Interaction count is gateway-owned telemetry, carried on the verdict-derived
|
|
186
|
+
// trust context; notes remain an INFO field joined locally by contact ID.
|
|
187
|
+
resolved.contactInteractionCount = trustContext.requesterInteractionCount;
|
|
183
188
|
if (trustContext.requesterContactId) {
|
|
184
189
|
const info = findContactInfoById(trustContext.requesterContactId);
|
|
185
190
|
if (info) {
|
|
186
191
|
resolved.contactNotes = info.notes ?? undefined;
|
|
187
|
-
resolved.contactInteractionCount = info.interactionCount;
|
|
188
192
|
}
|
|
189
193
|
}
|
|
190
194
|
return resolved;
|
|
@@ -1592,13 +1596,19 @@ export interface RuntimeInjectionResult {
|
|
|
1592
1596
|
* preserves ascending-`order` sort so downstream callers (notably
|
|
1593
1597
|
* {@link applyRuntimeInjections}) can group blocks by `placement` and apply
|
|
1594
1598
|
* them declaratively without losing per-injector ordering within each slot.
|
|
1599
|
+
*
|
|
1600
|
+
* `effectiveEnabledPlugins` carries the conversation's per-chat plugin scope:
|
|
1601
|
+
* when non-null, injectors contributed by a plugin outside the set are excluded
|
|
1602
|
+
* for this turn (see {@link getRegisteredInjectors}). `null`/omitted means no
|
|
1603
|
+
* per-chat restriction.
|
|
1595
1604
|
*/
|
|
1596
1605
|
async function collectInjectorBlocks(
|
|
1597
1606
|
ctx: TurnContext,
|
|
1598
1607
|
runMessages?: Message[],
|
|
1608
|
+
effectiveEnabledPlugins?: Set<string> | null,
|
|
1599
1609
|
): Promise<InjectionBlock[]> {
|
|
1600
1610
|
const out: InjectionBlock[] = [];
|
|
1601
|
-
for (const injector of getRegisteredInjectors()) {
|
|
1611
|
+
for (const injector of getRegisteredInjectors(effectiveEnabledPlugins)) {
|
|
1602
1612
|
const block = await injector.produce(ctx, runMessages);
|
|
1603
1613
|
if (block) out.push(block);
|
|
1604
1614
|
}
|
|
@@ -1937,6 +1947,14 @@ export async function applyRuntimeInjections(
|
|
|
1937
1947
|
// field below from it rather than from orchestrator-computed options.
|
|
1938
1948
|
const liveConversation = findConversationOrSubagent(conversationId);
|
|
1939
1949
|
|
|
1950
|
+
// Per-chat plugin scope for this turn: when the conversation restricts its
|
|
1951
|
+
// plugins (`enabledPlugins` non-null), injectors contributed by a plugin
|
|
1952
|
+
// outside the set are excluded below. `null` (no live conversation, or no
|
|
1953
|
+
// restriction) leaves the injector chain unchanged.
|
|
1954
|
+
const effectiveEnabledPlugins = liveConversation
|
|
1955
|
+
? getEffectiveEnabledPluginSet(liveConversation)
|
|
1956
|
+
: null;
|
|
1957
|
+
|
|
1940
1958
|
const channelCapabilities = liveConversation?.channelCapabilities ?? null;
|
|
1941
1959
|
const slackConversation = channelCapabilities?.channel === "slack";
|
|
1942
1960
|
|
|
@@ -1951,6 +1969,13 @@ export async function applyRuntimeInjections(
|
|
|
1951
1969
|
liveConversation.originInterface ??
|
|
1952
1970
|
"web")
|
|
1953
1971
|
: undefined;
|
|
1972
|
+
// OS surface reported by the client, independent of the transport interface
|
|
1973
|
+
// above. Drives the per-turn `client_os:` line so the model knows whether it
|
|
1974
|
+
// is talking to the web, iOS, or macOS app (all sharing the `"web"`
|
|
1975
|
+
// transport interface). Read the frozen per-turn snapshot (not the live
|
|
1976
|
+
// `clientOs`) so a queued message from another surface can't perturb the
|
|
1977
|
+
// in-flight turn — same anti-race pattern as `clientTimezone`.
|
|
1978
|
+
const clientOs = liveConversation?.currentTurnClientOs ?? undefined;
|
|
1954
1979
|
const channelName = liveConversation
|
|
1955
1980
|
? (liveConversation.currentTurnChannelContext?.userMessageChannel ??
|
|
1956
1981
|
liveConversation.originChannel ??
|
|
@@ -2059,6 +2084,7 @@ export async function applyRuntimeInjections(
|
|
|
2059
2084
|
activeDocuments,
|
|
2060
2085
|
timestamp,
|
|
2061
2086
|
interfaceName,
|
|
2087
|
+
clientOs,
|
|
2062
2088
|
channelName,
|
|
2063
2089
|
actorContext: options.actorContext,
|
|
2064
2090
|
configuredUserTimezone,
|
|
@@ -2080,7 +2106,11 @@ export async function applyRuntimeInjections(
|
|
|
2080
2106
|
...injectionInputs,
|
|
2081
2107
|
};
|
|
2082
2108
|
|
|
2083
|
-
const chainBlocks = await collectInjectorBlocks(
|
|
2109
|
+
const chainBlocks = await collectInjectorBlocks(
|
|
2110
|
+
turnCtx,
|
|
2111
|
+
runMessages,
|
|
2112
|
+
effectiveEnabledPlugins,
|
|
2113
|
+
);
|
|
2084
2114
|
|
|
2085
2115
|
// Split the chain output by placement so the downstream assembly can
|
|
2086
2116
|
// process each slot with the correct ordering rule.
|
|
@@ -15,7 +15,10 @@ import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags
|
|
|
15
15
|
import { getConfig } from "../config/loader.js";
|
|
16
16
|
import { skillFlagKey } from "../config/skill-state.js";
|
|
17
17
|
import type { SkillSummary, SkillToolManifest } from "../config/skills.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
filterSkillsByEnabledPlugins,
|
|
20
|
+
loadSkillCatalog,
|
|
21
|
+
} from "../config/skills.js";
|
|
19
22
|
import type { Message, ToolDefinition } from "../providers/types.js";
|
|
20
23
|
import type { ActiveSkillEntry } from "../skills/active-skill-tools.js";
|
|
21
24
|
import { deriveActiveSkills } from "../skills/active-skill-tools.js";
|
|
@@ -114,6 +117,14 @@ export interface ProjectSkillToolsOptions {
|
|
|
114
117
|
* reads across agent turns.
|
|
115
118
|
*/
|
|
116
119
|
cache?: SkillProjectionCache;
|
|
120
|
+
/**
|
|
121
|
+
* The conversation's effective per-chat plugin scope from
|
|
122
|
+
* `getEffectiveEnabledPluginSet`. `null`/absent means no per-chat restriction
|
|
123
|
+
* (all globally-enabled plugins apply). When a set is given, plugin-owned
|
|
124
|
+
* skills whose owning plugin id is outside it are dropped from this
|
|
125
|
+
* conversation's resolution; non-plugin skills are unaffected.
|
|
126
|
+
*/
|
|
127
|
+
effectiveEnabledPluginSet?: Set<string> | null;
|
|
117
128
|
/** Telemetry context for skill_loaded events; absent disables recording. */
|
|
118
129
|
telemetry?: {
|
|
119
130
|
conversationId: string;
|
|
@@ -339,8 +350,13 @@ export function projectSkillTools(
|
|
|
339
350
|
const contextIds = contextEntries.map((e) => e.id);
|
|
340
351
|
const allCandidateIds = new Set<string>([...contextIds, ...preactivated]);
|
|
341
352
|
|
|
342
|
-
// Load the catalog (cached for conversation lifetime)
|
|
343
|
-
|
|
353
|
+
// Load the catalog (cached for conversation lifetime), then scope it to the
|
|
354
|
+
// conversation's per-chat plugin selection so plugin-contributed skills from
|
|
355
|
+
// unselected plugins are not resolvable for this run (null = no restriction).
|
|
356
|
+
const catalog = filterSkillsByEnabledPlugins(
|
|
357
|
+
getCachedCatalog(options?.cache),
|
|
358
|
+
options?.effectiveEnabledPluginSet ?? null,
|
|
359
|
+
);
|
|
344
360
|
const catalogById = new Map<string, SkillSummary>();
|
|
345
361
|
for (const skill of catalog) {
|
|
346
362
|
catalogById.set(skill.id, skill);
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
16
16
|
import { getConfig } from "../config/loader.js";
|
|
17
|
-
import { buildSystemPrompt } from "../prompts/system-prompt.js";
|
|
18
17
|
import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
|
|
19
18
|
import { resolveDefaultProvider } from "../providers/connection-resolution.js";
|
|
20
19
|
import { RateLimitProvider } from "../providers/ratelimit.js";
|
|
@@ -27,6 +26,7 @@ import {
|
|
|
27
26
|
removeFromEvictor,
|
|
28
27
|
touchConversation,
|
|
29
28
|
} from "./conversation-evictor.js";
|
|
29
|
+
import { resolveInitialSystemPrompt } from "./conversation-initial-prompt.js";
|
|
30
30
|
import {
|
|
31
31
|
allConversations,
|
|
32
32
|
clearConversations,
|
|
@@ -76,6 +76,7 @@ function applyTransportMetadata(
|
|
|
76
76
|
conversation.setTransportHints(buildTransportHints(transport));
|
|
77
77
|
conversation.applyHostEnvFromTransport(transport);
|
|
78
78
|
conversation.applyClientTimezoneFromTransport(transport);
|
|
79
|
+
conversation.applyClientOsFromTransport(transport);
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
/**
|
|
@@ -144,8 +145,7 @@ export async function getOrCreateConversation(
|
|
|
144
145
|
}
|
|
145
146
|
const workingDir = getSandboxWorkingDir();
|
|
146
147
|
|
|
147
|
-
const systemPrompt =
|
|
148
|
-
storedOptions?.systemPromptOverride ?? buildSystemPrompt();
|
|
148
|
+
const systemPrompt = await resolveInitialSystemPrompt(storedOptions);
|
|
149
149
|
const maxTokens = storedOptions?.maxResponseTokens;
|
|
150
150
|
|
|
151
151
|
const newConversation = new Conversation(
|