@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
|
@@ -12,8 +12,6 @@ import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
|
|
|
12
12
|
import { notifyContactsChanged } from "./notify-contacts-changed.js";
|
|
13
13
|
import type {
|
|
14
14
|
AssistantContactMetadata,
|
|
15
|
-
ChannelPolicy,
|
|
16
|
-
ChannelStatus,
|
|
17
15
|
Contact,
|
|
18
16
|
ContactChannel,
|
|
19
17
|
ContactRole,
|
|
@@ -99,8 +97,6 @@ function parseContact(row: typeof contacts.$inferSelect): Contact {
|
|
|
99
97
|
// gateway-owned; the serve layer stamps the real role from the gateway
|
|
100
98
|
// guardian id set.
|
|
101
99
|
role: "contact",
|
|
102
|
-
lastInteraction: null,
|
|
103
|
-
interactionCount: 0,
|
|
104
100
|
createdAt: row.createdAt,
|
|
105
101
|
updatedAt: row.updatedAt,
|
|
106
102
|
contactType: row.contactType,
|
|
@@ -118,10 +114,6 @@ function parseChannel(
|
|
|
118
114
|
address: row.address,
|
|
119
115
|
isPrimary: row.isPrimary,
|
|
120
116
|
externalChatId: row.externalChatId,
|
|
121
|
-
inviteId: row.inviteId,
|
|
122
|
-
lastSeenAt: row.lastSeenAt,
|
|
123
|
-
interactionCount: row.interactionCount,
|
|
124
|
-
lastInteraction: row.lastInteraction,
|
|
125
117
|
updatedAt: row.updatedAt,
|
|
126
118
|
createdAt: row.createdAt,
|
|
127
119
|
};
|
|
@@ -140,32 +132,21 @@ function getChannelsForContact(contactId: string): ContactChannel[] {
|
|
|
140
132
|
|
|
141
133
|
function withChannels(contact: Contact): ContactWithChannels {
|
|
142
134
|
const channels = getChannelsForContact(contact.id);
|
|
143
|
-
|
|
144
|
-
// counts, take the most recent interaction across channels.
|
|
145
|
-
const interactionCount = channels.reduce(
|
|
146
|
-
(sum, ch) => sum + ch.interactionCount,
|
|
147
|
-
0,
|
|
148
|
-
);
|
|
149
|
-
const lastInteraction =
|
|
150
|
-
channels.reduce((max, ch) => Math.max(max, ch.lastInteraction ?? 0), 0) ||
|
|
151
|
-
null;
|
|
152
|
-
return { ...contact, interactionCount, lastInteraction, channels };
|
|
135
|
+
return { ...contact, channels };
|
|
153
136
|
}
|
|
154
137
|
|
|
155
138
|
// ── Channel data type for syncChannels ───────────────────────────────
|
|
156
139
|
|
|
157
140
|
interface SyncChannelData {
|
|
141
|
+
/** Explicit gateway-minted channel id. Lets the identity mirror key the
|
|
142
|
+
* channel identically in both stores; omit to mint one. When a row with this
|
|
143
|
+
* id already exists it is updated in place (address/owner rebind), so a
|
|
144
|
+
* gateway re-auth is mirrored rather than colliding on the id. */
|
|
145
|
+
id?: string;
|
|
158
146
|
type: string;
|
|
159
147
|
address: string;
|
|
160
148
|
isPrimary?: boolean;
|
|
161
149
|
externalChatId?: string | null;
|
|
162
|
-
status?: ChannelStatus;
|
|
163
|
-
policy?: ChannelPolicy;
|
|
164
|
-
verifiedAt?: number | null;
|
|
165
|
-
verifiedVia?: string | null;
|
|
166
|
-
inviteId?: string | null;
|
|
167
|
-
revokedReason?: string | null;
|
|
168
|
-
blockedReason?: string | null;
|
|
169
150
|
}
|
|
170
151
|
|
|
171
152
|
// ── CRUD ─────────────────────────────────────────────────────────────
|
|
@@ -184,21 +165,20 @@ export const getContactInternal = getContact;
|
|
|
184
165
|
/** INFO-only contact fields, joined locally by contact ID. */
|
|
185
166
|
export interface ContactInfo {
|
|
186
167
|
notes: string | null;
|
|
187
|
-
interactionCount: number;
|
|
188
168
|
}
|
|
189
169
|
|
|
190
170
|
/**
|
|
191
|
-
* Look up a contact's INFO
|
|
171
|
+
* Look up a contact's INFO `notes` field by ID.
|
|
192
172
|
*
|
|
193
|
-
* Carries no ACL state (status/policy/verification)
|
|
194
|
-
*
|
|
173
|
+
* Carries no ACL state (status/policy/verification) or interaction telemetry —
|
|
174
|
+
* those are owned by the gateway (ACL via the stamped trust verdict, telemetry
|
|
175
|
+
* via the verdict/rich reads). Returns null when the contact does not exist.
|
|
195
176
|
*/
|
|
196
177
|
export function findContactInfoById(contactId: string): ContactInfo | null {
|
|
197
178
|
const contact = getContact(contactId);
|
|
198
179
|
if (!contact) return null;
|
|
199
180
|
return {
|
|
200
181
|
notes: contact.notes,
|
|
201
|
-
interactionCount: contact.interactionCount,
|
|
202
182
|
};
|
|
203
183
|
}
|
|
204
184
|
|
|
@@ -223,6 +203,11 @@ export function upsertContact(params: {
|
|
|
223
203
|
role?: ContactRole;
|
|
224
204
|
contactType?: ContactType;
|
|
225
205
|
userFile?: string | null;
|
|
206
|
+
/** userFile to seed ONLY when inserting a new contact; ignored on update so
|
|
207
|
+
* an existing persona-file pointer is never clobbered. Used by the identity
|
|
208
|
+
* mirror to create faithful null-user_file stubs. `userFile` takes
|
|
209
|
+
* precedence when both are supplied. */
|
|
210
|
+
userFileOnCreate?: string | null;
|
|
226
211
|
channels?: SyncChannelData[];
|
|
227
212
|
/** When true, conflicting channels on other contacts are reassigned to this
|
|
228
213
|
* contact instead of being skipped. Used by invite redemption to bind a
|
|
@@ -312,7 +297,9 @@ export function upsertContact(params: {
|
|
|
312
297
|
const resolvedUserFile =
|
|
313
298
|
params.userFile !== undefined
|
|
314
299
|
? params.userFile
|
|
315
|
-
:
|
|
300
|
+
: params.userFileOnCreate !== undefined
|
|
301
|
+
? params.userFileOnCreate
|
|
302
|
+
: generateUserFileSlug(params.displayName);
|
|
316
303
|
db.insert(contacts)
|
|
317
304
|
.values({
|
|
318
305
|
id: contactId,
|
|
@@ -338,6 +325,16 @@ export function upsertContact(params: {
|
|
|
338
325
|
return { ...getContactInternal(contactId)!, created: true };
|
|
339
326
|
}
|
|
340
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Delete a contact row (channels cascade via FK). Info-only: the gateway DB is
|
|
330
|
+
* the ACL source of truth, so this only removes the local identity mirror. A
|
|
331
|
+
* missing row is a harmless no-op.
|
|
332
|
+
*/
|
|
333
|
+
export function deleteContact(id: string): void {
|
|
334
|
+
getDb().delete(contacts).where(eq(contacts.id, id)).run();
|
|
335
|
+
notifyContactsChanged();
|
|
336
|
+
}
|
|
337
|
+
|
|
341
338
|
/**
|
|
342
339
|
* Add new channels to a contact without removing existing ones.
|
|
343
340
|
* When a channel already exists (same type+address), updates access/verification
|
|
@@ -352,6 +349,57 @@ function syncChannels(
|
|
|
352
349
|
const db = getDb();
|
|
353
350
|
|
|
354
351
|
for (const ch of channels) {
|
|
352
|
+
// Identity-mirror update-by-id: when the caller supplies the gateway's
|
|
353
|
+
// authoritative channel id and that row already exists, update it in place.
|
|
354
|
+
// The gateway can rebind the row's address (guardian re-auth) or owner
|
|
355
|
+
// (claimed channel) under a stable id, so a match by (contactId,type,address)
|
|
356
|
+
// would miss it and a fresh insert would collide on the primary key.
|
|
357
|
+
if (ch.id) {
|
|
358
|
+
const byId = db
|
|
359
|
+
.select()
|
|
360
|
+
.from(contactChannels)
|
|
361
|
+
.where(eq(contactChannels.id, ch.id))
|
|
362
|
+
.get();
|
|
363
|
+
if (byId) {
|
|
364
|
+
const crossContact = byId.contactId !== contactId;
|
|
365
|
+
// Never steal a channel the gateway left under another contact unless
|
|
366
|
+
// the caller opts into reassignment (mirrors the address-conflict path).
|
|
367
|
+
if (crossContact && !reassignConflicting) continue;
|
|
368
|
+
|
|
369
|
+
const updateSet: Record<string, unknown> = { updatedAt: now };
|
|
370
|
+
if (byId.address !== ch.address) {
|
|
371
|
+
// Rebinding to a new address: a DIFFERENT row may already hold
|
|
372
|
+
// (type, new-address), and idx_contact_channels_type_address would
|
|
373
|
+
// reject the move. Resolve it the same way the (contactId,type,address)
|
|
374
|
+
// path does — findConflictingChannel + the reassign gate. When
|
|
375
|
+
// reassigning, adopt the (type,address) identity onto this
|
|
376
|
+
// gateway-keyed row by removing the stale duplicate; otherwise leave
|
|
377
|
+
// the address so the existing mapping stands (onConflictDoNothing).
|
|
378
|
+
const conflicting = findConflictingChannel(db, ch.type, ch.address);
|
|
379
|
+
if (conflicting && conflicting.id !== ch.id) {
|
|
380
|
+
if (reassignConflicting) {
|
|
381
|
+
db.delete(contactChannels)
|
|
382
|
+
.where(eq(contactChannels.id, conflicting.id))
|
|
383
|
+
.run();
|
|
384
|
+
updateSet.address = ch.address;
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
updateSet.address = ch.address;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (crossContact) updateSet.contactId = contactId;
|
|
391
|
+
if (ch.isPrimary !== undefined) updateSet.isPrimary = ch.isPrimary;
|
|
392
|
+
if (ch.externalChatId !== undefined)
|
|
393
|
+
updateSet.externalChatId = ch.externalChatId;
|
|
394
|
+
|
|
395
|
+
db.update(contactChannels)
|
|
396
|
+
.set(updateSet)
|
|
397
|
+
.where(eq(contactChannels.id, ch.id))
|
|
398
|
+
.run();
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
355
403
|
// Match by (type, address) — the canonical identity for all channel types.
|
|
356
404
|
// COLLATE NOCASE catches legacy rows that were lowercased by old write paths.
|
|
357
405
|
const existing = db
|
|
@@ -373,7 +421,6 @@ function syncChannels(
|
|
|
373
421
|
if (ch.isPrimary !== undefined) updateSet.isPrimary = ch.isPrimary;
|
|
374
422
|
if (ch.externalChatId !== undefined)
|
|
375
423
|
updateSet.externalChatId = ch.externalChatId;
|
|
376
|
-
if (ch.inviteId !== undefined) updateSet.inviteId = ch.inviteId;
|
|
377
424
|
|
|
378
425
|
if (Object.keys(updateSet).length > 0) {
|
|
379
426
|
updateSet.updatedAt = now;
|
|
@@ -398,7 +445,7 @@ function syncChannels(
|
|
|
398
445
|
};
|
|
399
446
|
if (ch.externalChatId !== undefined)
|
|
400
447
|
reassignSet.externalChatId = ch.externalChatId;
|
|
401
|
-
if (ch.
|
|
448
|
+
if (ch.isPrimary !== undefined) reassignSet.isPrimary = ch.isPrimary;
|
|
402
449
|
|
|
403
450
|
db.update(contactChannels)
|
|
404
451
|
.set(reassignSet)
|
|
@@ -412,13 +459,12 @@ function syncChannels(
|
|
|
412
459
|
|
|
413
460
|
db.insert(contactChannels)
|
|
414
461
|
.values({
|
|
415
|
-
id: uuid(),
|
|
462
|
+
id: ch.id ?? uuid(),
|
|
416
463
|
contactId,
|
|
417
464
|
type: ch.type,
|
|
418
465
|
address: ch.address,
|
|
419
466
|
isPrimary: ch.isPrimary ?? false,
|
|
420
467
|
externalChatId: ch.externalChatId ?? null,
|
|
421
|
-
inviteId: ch.inviteId ?? null,
|
|
422
468
|
createdAt: now,
|
|
423
469
|
updatedAt: now,
|
|
424
470
|
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Contacts write module.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Best-effort local mirror of contact identity/INFO fields. The gateway owns
|
|
5
|
+
* the ACL verdict (status, policy, verification); these writes never carry or
|
|
6
|
+
* mutate ACL state.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {
|
|
@@ -13,18 +13,7 @@ import {
|
|
|
13
13
|
getContactInternal,
|
|
14
14
|
upsertContact,
|
|
15
15
|
} from "./contact-store.js";
|
|
16
|
-
import type { ContactWriteResult } from "./types.js";
|
|
17
|
-
|
|
18
|
-
// ── Guardian operations ──────────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* No-op shim: the guardian channel ACL revoke is gateway-owned (relayed via
|
|
22
|
-
* mark_channel_revoked). Retained while callers still invoke it; the return is
|
|
23
|
-
* discarded.
|
|
24
|
-
*/
|
|
25
|
-
export function revokeGuardianBinding(_channel: string): boolean {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
16
|
+
import type { ContactType, ContactWriteResult } from "./types.js";
|
|
28
17
|
|
|
29
18
|
// ── Member operations ────────────────────────────────────────────────
|
|
30
19
|
|
|
@@ -40,8 +29,33 @@ export function upsertContactChannel(params: {
|
|
|
40
29
|
externalChatId?: string;
|
|
41
30
|
displayName?: string;
|
|
42
31
|
username?: string;
|
|
43
|
-
inviteId?: string;
|
|
44
32
|
contactId?: string;
|
|
33
|
+
/** Explicit channel id for a NEW channel (identity-mirror path): reuse the
|
|
34
|
+
* gateway-minted id so both stores key the channel identically. */
|
|
35
|
+
channelId?: string;
|
|
36
|
+
/** Classification for a newly created contact (e.g. 'assistant' for bots). */
|
|
37
|
+
contactType?: ContactType;
|
|
38
|
+
/** Notes seeded onto a newly created contact (e.g. bot/app provenance). */
|
|
39
|
+
notes?: string | null;
|
|
40
|
+
/** userFile to seed on contact CREATE only (identity-mirror stubs pass null
|
|
41
|
+
* for a faithful null-user_file replica); ignored on update. */
|
|
42
|
+
userFileOnCreate?: string | null;
|
|
43
|
+
/** Refresh the contact display name from the supplied identity even when a
|
|
44
|
+
* contactId is given. Used by the inbound identity-seed mirror, whose intent
|
|
45
|
+
* is to keep the mirror name in sync with the platform profile. Defaults to
|
|
46
|
+
* false: the invite-binding path preserves the guardian-curated name. */
|
|
47
|
+
refreshDisplayName?: boolean;
|
|
48
|
+
/** Reparent a conflicting existing channel (same (type,address) owned by a
|
|
49
|
+
* DIFFERENT contact) to this contact. Invite-binding only. The inbound
|
|
50
|
+
* identity-seed mirror must pass false so it matches the gateway insert's
|
|
51
|
+
* onConflictDoNothing and never steals a channel from its existing contact.
|
|
52
|
+
* Defaults to `!!contactId` to preserve the invite-binding callers that
|
|
53
|
+
* don't set it explicitly. */
|
|
54
|
+
reassignConflictingChannels?: boolean;
|
|
55
|
+
/** Mark the channel primary. Omit to leave an existing channel's flag intact
|
|
56
|
+
* and default a new channel to non-primary; the guardian-bootstrap mirror
|
|
57
|
+
* passes true so the guardian's sole channel stays primary. */
|
|
58
|
+
isPrimary?: boolean;
|
|
45
59
|
}): ContactWriteResult | null {
|
|
46
60
|
let address: string;
|
|
47
61
|
|
|
@@ -57,9 +71,10 @@ export function upsertContactChannel(params: {
|
|
|
57
71
|
let displayName = params.displayName ?? address;
|
|
58
72
|
|
|
59
73
|
// When binding a channel to a specific contact (invite redemption), preserve
|
|
60
|
-
// the target contact's curated displayName instead of overwriting it
|
|
61
|
-
//
|
|
62
|
-
|
|
74
|
+
// the target contact's curated displayName instead of overwriting it with the
|
|
75
|
+
// raw platform identity. The inbound identity-seed mirror opts out
|
|
76
|
+
// (refreshDisplayName) so a changed platform profile name refreshes the row.
|
|
77
|
+
if (params.contactId && !params.refreshDisplayName) {
|
|
63
78
|
const targetContact = getContact(params.contactId);
|
|
64
79
|
if (targetContact?.displayName?.trim().length) {
|
|
65
80
|
displayName = targetContact.displayName;
|
|
@@ -69,18 +84,28 @@ export function upsertContactChannel(params: {
|
|
|
69
84
|
upsertContact({
|
|
70
85
|
id: params.contactId,
|
|
71
86
|
displayName,
|
|
87
|
+
contactType: params.contactType,
|
|
88
|
+
notes: params.notes,
|
|
89
|
+
userFileOnCreate: params.userFileOnCreate,
|
|
72
90
|
channels: [
|
|
73
91
|
{
|
|
92
|
+
id: params.channelId,
|
|
74
93
|
type: params.sourceChannel,
|
|
75
94
|
address,
|
|
76
|
-
|
|
77
|
-
|
|
95
|
+
// Pass through undefined so syncChannels preserves an existing
|
|
96
|
+
// external_chat_id (COALESCE semantics); a new channel still defaults
|
|
97
|
+
// to null. An explicit value overwrites.
|
|
98
|
+
externalChatId: params.externalChatId,
|
|
99
|
+
isPrimary: params.isPrimary,
|
|
78
100
|
},
|
|
79
101
|
],
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
|
|
102
|
+
// Reassign a conflicting channel from another contact only when the caller
|
|
103
|
+
// explicitly asks (invite redemption binding a redeemer's existing channel
|
|
104
|
+
// to the invite's target). Defaults to `!!contactId` for legacy callers;
|
|
105
|
+
// the inbound-seed mirror passes false so a first-seen race does not steal
|
|
106
|
+
// the channel from the contact the gateway insert kept.
|
|
107
|
+
reassignConflictingChannels:
|
|
108
|
+
params.reassignConflictingChannels ?? !!params.contactId,
|
|
84
109
|
});
|
|
85
110
|
|
|
86
111
|
// NOTE: We intentionally do NOT seed `users/<slug>.md` here. This is the
|
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
+
CreateContactIpcResponseSchema,
|
|
10
11
|
MarkChannelRevokedIpcResponseSchema,
|
|
11
12
|
UpsertVerifiedChannelIpcResponseSchema,
|
|
12
13
|
} from "@vellumai/gateway-client/gateway-ipc-contracts";
|
|
13
14
|
|
|
14
15
|
import { log } from "../daemon/handlers/shared.js";
|
|
15
16
|
import { ipcCallPersistent } from "../ipc/gateway-client.js";
|
|
17
|
+
import { findContactChannel } from "./contact-store.js";
|
|
16
18
|
import { revokeMember, upsertContactChannel } from "./contacts-write.js";
|
|
17
19
|
import type { ContactWriteResult } from "./types.js";
|
|
18
20
|
|
|
@@ -25,8 +27,6 @@ export interface ActivateMemberChannelParams {
|
|
|
25
27
|
contactId?: string;
|
|
26
28
|
displayName?: string;
|
|
27
29
|
username?: string;
|
|
28
|
-
inviteId?: string;
|
|
29
|
-
verifiedAt?: number;
|
|
30
30
|
verifiedVia?: string;
|
|
31
31
|
policy?: string;
|
|
32
32
|
}
|
|
@@ -130,7 +130,6 @@ function mirrorLocalActivation(
|
|
|
130
130
|
externalChatId: params.externalChatId,
|
|
131
131
|
displayName: params.displayName,
|
|
132
132
|
username: params.username,
|
|
133
|
-
inviteId: params.inviteId,
|
|
134
133
|
contactId: params.contactId,
|
|
135
134
|
});
|
|
136
135
|
} catch (err) {
|
|
@@ -142,42 +141,127 @@ function mirrorLocalActivation(
|
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
|
|
145
|
-
// ──
|
|
144
|
+
// ── Block ────────────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
export interface BlockSenderChannelParams {
|
|
147
|
+
sourceChannel: string;
|
|
148
|
+
externalUserId: string;
|
|
149
|
+
displayName?: string;
|
|
150
|
+
/** Audit reason written to the gateway channel's revokedReason. */
|
|
151
|
+
reason?: string;
|
|
152
|
+
}
|
|
146
153
|
|
|
147
154
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
155
|
+
* Block a sender's channel gateway-first: ensure a contact/channel row exists
|
|
156
|
+
* for the (channel, address) pair, then mark it revoked so future inbound
|
|
157
|
+
* resolves as `unknown` and is hard-denied. Used by the introduction card's
|
|
158
|
+
* **Block** action for senders that may have no contact record yet.
|
|
151
159
|
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
160
|
+
* The gateway owns the verdict: `create_contact` preserves an existing row's
|
|
161
|
+
* status, and `mark_channel_revoked` is idempotent (already-revoked →
|
|
162
|
+
* didWrite:false) and refuses to downgrade a guardian channel. Fails closed —
|
|
163
|
+
* a relay failure surfaces as `revoked: false` so callers never report a block
|
|
164
|
+
* the gateway did not persist. The assistant-DB status update is a best-effort
|
|
165
|
+
* mirror.
|
|
155
166
|
*/
|
|
156
|
-
export async function
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
export async function blockSenderChannel(
|
|
168
|
+
params: BlockSenderChannelParams,
|
|
169
|
+
): Promise<{ revoked: boolean }> {
|
|
170
|
+
let channelId: string;
|
|
171
|
+
try {
|
|
172
|
+
const created = await ipcCallPersistent("create_contact", {
|
|
173
|
+
channelType: params.sourceChannel,
|
|
174
|
+
address: params.externalUserId,
|
|
175
|
+
...(params.displayName ? { displayName: params.displayName } : {}),
|
|
176
|
+
});
|
|
177
|
+
channelId = CreateContactIpcResponseSchema.parse(created).channelId;
|
|
178
|
+
} catch (err) {
|
|
179
|
+
log.warn(
|
|
180
|
+
{ err, sourceChannel: params.sourceChannel },
|
|
181
|
+
"create_contact relay failed — refusing block (no gateway channel row)",
|
|
182
|
+
);
|
|
183
|
+
return { revoked: false };
|
|
184
|
+
}
|
|
185
|
+
if (!channelId) {
|
|
186
|
+
log.error(
|
|
187
|
+
{ sourceChannel: params.sourceChannel },
|
|
188
|
+
"create_contact returned no channel id — refusing block",
|
|
189
|
+
);
|
|
190
|
+
return { revoked: false };
|
|
172
191
|
}
|
|
173
192
|
|
|
174
193
|
try {
|
|
175
|
-
|
|
194
|
+
const result = await ipcCallPersistent("mark_channel_revoked", {
|
|
195
|
+
contactChannelId: channelId,
|
|
196
|
+
reason: params.reason,
|
|
197
|
+
});
|
|
198
|
+
const parsed = MarkChannelRevokedIpcResponseSchema.parse(result);
|
|
199
|
+
if (!parsed.ok) {
|
|
200
|
+
return { revoked: false };
|
|
201
|
+
}
|
|
176
202
|
} catch (err) {
|
|
177
|
-
log.
|
|
178
|
-
{ err,
|
|
179
|
-
"
|
|
203
|
+
log.warn(
|
|
204
|
+
{ err, sourceChannel: params.sourceChannel },
|
|
205
|
+
"mark_channel_revoked relay failed — block did not land on the gateway",
|
|
206
|
+
);
|
|
207
|
+
return { revoked: false };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Best-effort local mirror so the Contacts page reflects the downgrade.
|
|
211
|
+
// Resolved by logical (type, address) key — the local mirror row's id is
|
|
212
|
+
// not guaranteed to match the gateway channel id.
|
|
213
|
+
try {
|
|
214
|
+
const local = findContactChannel({
|
|
215
|
+
channelType: params.sourceChannel,
|
|
216
|
+
address: params.externalUserId,
|
|
217
|
+
});
|
|
218
|
+
if (local) {
|
|
219
|
+
revokeMember(local.channel.id);
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
// The local row may not exist for a brand-new sender; the gateway
|
|
223
|
+
// outcome stands.
|
|
224
|
+
}
|
|
225
|
+
return { revoked: true };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── Seed unverified ──────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
export interface SeedUnverifiedMemberChannelParams {
|
|
231
|
+
sourceChannel: string;
|
|
232
|
+
externalUserId: string;
|
|
233
|
+
displayName?: string;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Seed a contact channel for a sender at the `unverified` admission tier,
|
|
238
|
+
* gateway-first. Used when the guardian denies an access request: the sender
|
|
239
|
+
* becomes a known `unverified_contact` — no longer an unknown stranger — so
|
|
240
|
+
* subsequent inbound resolves as `unverified_contact` instead of re-running
|
|
241
|
+
* discovery.
|
|
242
|
+
*
|
|
243
|
+
* Delegates to the gateway `create_contact` IPC, which upserts via
|
|
244
|
+
* `ContactStore.upsertContact` (gateway DB is the ACL source of truth, with a
|
|
245
|
+
* best-effort assistant-DB mirror). A brand-new channel lands at status
|
|
246
|
+
* `unverified`; an existing channel's status is preserved, so a blocked,
|
|
247
|
+
* revoked, or already-active row is never reactivated or downgraded.
|
|
248
|
+
*
|
|
249
|
+
* Best-effort: the gateway owns the ACL verdict, so a failed relay is logged
|
|
250
|
+
* and swallowed — it must never fail the guardian's deny decision.
|
|
251
|
+
*/
|
|
252
|
+
export async function seedUnverifiedMemberChannel(
|
|
253
|
+
params: SeedUnverifiedMemberChannelParams,
|
|
254
|
+
): Promise<void> {
|
|
255
|
+
try {
|
|
256
|
+
await ipcCallPersistent("create_contact", {
|
|
257
|
+
channelType: params.sourceChannel,
|
|
258
|
+
address: params.externalUserId,
|
|
259
|
+
...(params.displayName ? { displayName: params.displayName } : {}),
|
|
260
|
+
});
|
|
261
|
+
} catch (err) {
|
|
262
|
+
log.warn(
|
|
263
|
+
{ err, sourceChannel: params.sourceChannel },
|
|
264
|
+
"seed_unverified_channel relay failed (best-effort); sender not persisted as unverified_contact",
|
|
180
265
|
);
|
|
181
|
-
return null;
|
|
182
266
|
}
|
|
183
267
|
}
|
package/src/contacts/types.ts
CHANGED
|
@@ -31,8 +31,6 @@ export interface Contact {
|
|
|
31
31
|
/** Free-text notes about this contact (e.g. relationship, communication preferences). */
|
|
32
32
|
notes: string | null;
|
|
33
33
|
role: ContactRole;
|
|
34
|
-
lastInteraction: number | null;
|
|
35
|
-
interactionCount: number;
|
|
36
34
|
createdAt: number;
|
|
37
35
|
updatedAt: number;
|
|
38
36
|
contactType: ContactType;
|
|
@@ -55,12 +53,6 @@ export interface ContactChannel {
|
|
|
55
53
|
address: string;
|
|
56
54
|
isPrimary: boolean;
|
|
57
55
|
externalChatId: string | null;
|
|
58
|
-
inviteId: string | null;
|
|
59
|
-
// INFO telemetry (not ACL): interaction stats written locally by the gateway's
|
|
60
|
-
// handle-inbound mirror. Model-facing turn context reads these.
|
|
61
|
-
lastSeenAt: number | null;
|
|
62
|
-
interactionCount: number;
|
|
63
|
-
lastInteraction: number | null;
|
|
64
56
|
updatedAt: number | null;
|
|
65
57
|
createdAt: number;
|
|
66
58
|
}
|
package/src/context/compactor.ts
CHANGED
|
@@ -22,7 +22,6 @@ import { optimizeImageForTransport } from "../agent/image-optimize.js";
|
|
|
22
22
|
import type { CompactionConfig } from "../config/schemas/compaction.js";
|
|
23
23
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
24
24
|
import { filterMessagesForUntrustedActor } from "../daemon/message-provenance.js";
|
|
25
|
-
import { stripHistoricalWebSearchResults } from "../daemon/web-search-history.js";
|
|
26
25
|
import {
|
|
27
26
|
getAttachmentContent,
|
|
28
27
|
getAttachmentMetadataForMessage,
|
|
@@ -40,6 +39,7 @@ import type {
|
|
|
40
39
|
import { type TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
41
40
|
import { resolveCapabilities } from "../runtime/capabilities.js";
|
|
42
41
|
import { getLogger } from "../util/logger.js";
|
|
42
|
+
import { preModelCallSanitize } from "./outbound-sanitize.js";
|
|
43
43
|
import { stripInjectionsForCompaction } from "./strip-injections.js";
|
|
44
44
|
import {
|
|
45
45
|
estimatePromptTokens,
|
|
@@ -826,14 +826,20 @@ function extractTextFromResponse(content: ContentBlock[]): string {
|
|
|
826
826
|
.join("\n");
|
|
827
827
|
}
|
|
828
828
|
|
|
829
|
-
// Build the outbound message list for a compaction provider call:
|
|
830
|
-
//
|
|
831
|
-
//
|
|
829
|
+
// Build the outbound message list for a compaction provider call: apply the
|
|
830
|
+
// same pre-send sanitization bundle as the agent loop's model calls
|
|
831
|
+
// (`preModelCallSanitize` — old tool-result media stripped, AX trees
|
|
832
|
+
// collapsed, historical web-search results converted to text), then append
|
|
833
|
+
// the summarization instruction at the tail.
|
|
832
834
|
//
|
|
833
|
-
//
|
|
834
|
-
//
|
|
835
|
-
//
|
|
836
|
-
//
|
|
835
|
+
// Matching the loop's projection matters for two reasons. First, the summary
|
|
836
|
+
// call's prefix stays byte-aligned with the agent's warm prompt cache — an
|
|
837
|
+
// unsanitized history diverges from what the loop actually sent at the first
|
|
838
|
+
// stripped block. Second, an unsanitized history carries every screenshot in
|
|
839
|
+
// the conversation; enough images cross Anthropic's many-image threshold,
|
|
840
|
+
// where a stricter per-image dimension cap applies and a single large
|
|
841
|
+
// screenshot rejects the whole summary call. Sanitizing here — the single
|
|
842
|
+
// seam every compaction provider call funnels through — covers both the
|
|
837
843
|
// assistant-driven and emergency summarization calls. Only this outbound copy
|
|
838
844
|
// is sanitized; tail resolution and the persisted compaction result read the
|
|
839
845
|
// caller's original messages, so durable history keeps the rich blocks. The
|
|
@@ -842,7 +848,7 @@ function buildCompactionRequest(
|
|
|
842
848
|
history: Message[],
|
|
843
849
|
instruction: Message,
|
|
844
850
|
): Message[] {
|
|
845
|
-
return [...
|
|
851
|
+
return [...preModelCallSanitize(history), instruction];
|
|
846
852
|
}
|
|
847
853
|
|
|
848
854
|
// Token headroom a compaction summary call reserves on top of its history: room
|
|
@@ -945,11 +951,14 @@ export async function runAssistantDrivenCompaction(
|
|
|
945
951
|
// Bound the summary call's own input to the context window. With no tool
|
|
946
952
|
// pair to anchor an emergency split, an overflow recovery routes the full
|
|
947
953
|
// history straight here, so the summary call must front-truncate itself or
|
|
948
|
-
// it overflows in turn.
|
|
949
|
-
//
|
|
950
|
-
//
|
|
954
|
+
// it overflows in turn. Truncation operates on the sanitized projection
|
|
955
|
+
// (what the request actually carries) so the budget estimate is honest —
|
|
956
|
+
// estimating on raw history would count media bytes the request strips.
|
|
957
|
+
// `args.messages` stays intact for tail resolution below — only the
|
|
958
|
+
// outbound request is truncated. A below-budget history is returned
|
|
959
|
+
// untouched, keeping the prefix aligned with the agent's warm cache.
|
|
951
960
|
const summaryHistory = truncateHistoryToBudget({
|
|
952
|
-
messages: args.messages,
|
|
961
|
+
messages: preModelCallSanitize(args.messages),
|
|
953
962
|
systemPrompt: args.systemPrompt,
|
|
954
963
|
budgetTokens: compactionPrefixBudget(args.maxInputTokens),
|
|
955
964
|
providerName: args.provider.tokenEstimationProvider ?? args.provider.name,
|
|
@@ -1371,9 +1380,14 @@ export async function runEmergencyCompaction(
|
|
|
1371
1380
|
);
|
|
1372
1381
|
// Bound the prefix to the context window so the summary call fits, reserving
|
|
1373
1382
|
// budget for the instruction message and the emitted summary. Truncates from
|
|
1374
|
-
// the front, keeping the recent portion the summary most needs.
|
|
1383
|
+
// the front, keeping the recent portion the summary most needs. The prefix
|
|
1384
|
+
// is sliced from the sanitized projection (sanitize-then-slice, matching the
|
|
1385
|
+
// agent's own sends byte-for-byte for cache alignment) so the budget
|
|
1386
|
+
// estimate counts what the request actually carries. All sanitize
|
|
1387
|
+
// transforms are 1:1 per message, so `splitIndex` maps onto the sanitized
|
|
1388
|
+
// array unchanged.
|
|
1375
1389
|
const prefix = truncateHistoryToBudget({
|
|
1376
|
-
messages: args.messages.slice(0, splitIndex),
|
|
1390
|
+
messages: preModelCallSanitize(args.messages).slice(0, splitIndex),
|
|
1377
1391
|
systemPrompt: args.systemPrompt,
|
|
1378
1392
|
budgetTokens: compactionPrefixBudget(args.maxInputTokens),
|
|
1379
1393
|
providerName: args.provider.tokenEstimationProvider ?? args.provider.name,
|