@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
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { ChannelId } from "../../channels/types.js";
|
|
5
5
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
6
|
-
import
|
|
7
|
-
ApprovalAction,
|
|
8
|
-
ApprovalDecisionResult,
|
|
9
|
-
ApprovalUIMetadata,
|
|
6
|
+
import {
|
|
7
|
+
type ApprovalAction,
|
|
8
|
+
type ApprovalDecisionResult,
|
|
9
|
+
type ApprovalUIMetadata,
|
|
10
|
+
isApprovalAction,
|
|
10
11
|
} from "../channel-approval-types.js";
|
|
11
12
|
|
|
12
13
|
/** Canonicalize assistantId for channel ingress paths. */
|
|
@@ -35,11 +36,6 @@ export function requiredDecisionKeywords(
|
|
|
35
36
|
// Callback data parser — format: "apr:<requestId>:<action>"
|
|
36
37
|
// ---------------------------------------------------------------------------
|
|
37
38
|
|
|
38
|
-
const VALID_ACTIONS: ReadonlySet<string> = new Set<string>([
|
|
39
|
-
"approve_once",
|
|
40
|
-
"reject",
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
39
|
/** Map legacy callback actions to canonical ones for in-flight buttons. */
|
|
44
40
|
const LEGACY_CALLBACK_MAP: Record<string, string> = {
|
|
45
41
|
approve_10m: "approve_once",
|
|
@@ -52,11 +48,15 @@ export function parseCallbackData(
|
|
|
52
48
|
sourceChannel?: string,
|
|
53
49
|
): ApprovalDecisionResult | null {
|
|
54
50
|
const parts = data.split(":");
|
|
55
|
-
if (parts.length < 3 || parts[0] !== "apr")
|
|
51
|
+
if (parts.length < 3 || parts[0] !== "apr") {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
56
54
|
const requestId = parts[1];
|
|
57
55
|
const rawAction = parts.slice(2).join(":");
|
|
58
56
|
const action = LEGACY_CALLBACK_MAP[rawAction] ?? rawAction;
|
|
59
|
-
if (!requestId || !
|
|
57
|
+
if (!requestId || !isApprovalAction(action)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
60
|
const source =
|
|
61
61
|
sourceChannel === "whatsapp"
|
|
62
62
|
? ("whatsapp_button" as const)
|
|
@@ -65,7 +65,7 @@ export function parseCallbackData(
|
|
|
65
65
|
: sourceChannel === "vellum"
|
|
66
66
|
? ("vellum_surface" as const)
|
|
67
67
|
: ("telegram_button" as const);
|
|
68
|
-
return { action
|
|
68
|
+
return { action, source, requestId };
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// ---------------------------------------------------------------------------
|
|
@@ -93,10 +93,14 @@ const REACTION_EMOJI_MAP: ReadonlyMap<string, ApprovalAction> = new Map([
|
|
|
93
93
|
export function parseReactionCallbackData(
|
|
94
94
|
data: string,
|
|
95
95
|
): ApprovalDecisionResult | null {
|
|
96
|
-
if (!data.startsWith("reaction:"))
|
|
96
|
+
if (!data.startsWith("reaction:")) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
97
99
|
const emoji = data.slice("reaction:".length);
|
|
98
100
|
const action = REACTION_EMOJI_MAP.get(emoji);
|
|
99
|
-
if (!action)
|
|
101
|
+
if (!action) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
100
104
|
return { action, source: "slack_reaction" };
|
|
101
105
|
}
|
|
102
106
|
|
|
@@ -14,9 +14,6 @@
|
|
|
14
14
|
* inbound code-match path (`gateway/src/verification/text-verification.ts`).
|
|
15
15
|
* - The revoke/downgrade OUTCOME is relayed from the daemon via
|
|
16
16
|
* `ipcCallPersistent("mark_channel_revoked", …)` to `ContactStore.markChannelRevoked`.
|
|
17
|
-
* - The `mark_channel_verified` IPC method exists as the daemon/CLI relay surface (symmetric with
|
|
18
|
-
* `mark_channel_revoked`) but has no caller: the trusted-contact CLI path sends codes only, and the
|
|
19
|
-
* outcome arrives via the inbound code-match path.
|
|
20
17
|
*/
|
|
21
18
|
|
|
22
19
|
import { z } from "zod";
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* they don't shadow more-specific sub-paths like contacts/invites.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import {
|
|
12
|
+
RedeemInviteByTokenRequestSchema,
|
|
13
|
+
RedeemVoiceInviteRequestSchema,
|
|
14
|
+
} from "@vellumai/gateway-client";
|
|
15
|
+
import type { ContactRead } from "@vellumai/gateway-client/gateway-ipc-contracts";
|
|
11
16
|
import {
|
|
12
17
|
GetContactIpcResponseSchema,
|
|
13
18
|
ListContactsIpcResponseSchema,
|
|
@@ -22,14 +27,19 @@ import {
|
|
|
22
27
|
searchContacts,
|
|
23
28
|
} from "../../contacts/contact-store.js";
|
|
24
29
|
import { getGuardianContactIds } from "../../contacts/guardian-contact-reader.js";
|
|
25
|
-
import type {
|
|
30
|
+
import type {
|
|
31
|
+
ContactChannel,
|
|
32
|
+
ContactRole,
|
|
33
|
+
ContactType,
|
|
34
|
+
ContactWithChannels,
|
|
35
|
+
} from "../../contacts/types.js";
|
|
26
36
|
import { ipcCallPersistent } from "../../ipc/gateway-client.js";
|
|
27
37
|
import { resolveGuardianName } from "../../prompts/user-reference.js";
|
|
28
38
|
import { getLogger } from "../../util/logger.js";
|
|
29
|
-
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
39
|
+
import { ACTOR_PRINCIPALS, GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
|
|
30
40
|
import {
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
composeInvitePresentation,
|
|
42
|
+
resolveInviteGuardianName,
|
|
33
43
|
triggerInviteCall,
|
|
34
44
|
} from "../invite-service.js";
|
|
35
45
|
import { BadRequestError, NotFoundError, RouteError } from "./errors.js";
|
|
@@ -147,9 +157,14 @@ function isContactType(value: string): value is ContactType {
|
|
|
147
157
|
// (search / contactType) omit them, so they are `.optional()`. Contact-level
|
|
148
158
|
// `role` is gateway-sourced: relayed reads trust the role on the `ContactRead`,
|
|
149
159
|
// while daemon-native reads derive it from the gateway guardian id set at the
|
|
150
|
-
// serve layer (see prepareContactResponse).
|
|
151
|
-
// (lastSeenAt/interactionCount/lastInteraction) is
|
|
152
|
-
//
|
|
160
|
+
// serve layer (see prepareContactResponse). Interaction telemetry
|
|
161
|
+
// (lastSeenAt/interactionCount/lastInteraction) is gateway-owned: relayed reads
|
|
162
|
+
// carry it directly, and daemon-native reads batch-hydrate it from the gateway
|
|
163
|
+
// (see hydrateTelemetryFromGateway). On a gateway fail-soft the count
|
|
164
|
+
// `interactionCount` defaults to 0 (never served as null, so callers render a
|
|
165
|
+
// real number); the `lastSeenAt`/`lastInteraction` timestamps degrade to null.
|
|
166
|
+
// The timestamp fields stay `.nullable()`; `interactionCount` is kept nullable
|
|
167
|
+
// defensively for the relay path, but is never emitted null.
|
|
153
168
|
const contactChannelSchema = z.object({
|
|
154
169
|
id: z.string(),
|
|
155
170
|
contactId: z.string(),
|
|
@@ -163,7 +178,7 @@ const contactChannelSchema = z.object({
|
|
|
163
178
|
verifiedAt: z.number().nullable().optional(),
|
|
164
179
|
verifiedVia: z.string().nullable().optional(),
|
|
165
180
|
lastSeenAt: z.number().nullable(),
|
|
166
|
-
interactionCount: z.number(),
|
|
181
|
+
interactionCount: z.number().nullable(),
|
|
167
182
|
lastInteraction: z.number().nullable(),
|
|
168
183
|
revokedReason: z.string().nullable().optional(),
|
|
169
184
|
blockedReason: z.string().nullable().optional(),
|
|
@@ -176,7 +191,7 @@ const contactSchema = z.object({
|
|
|
176
191
|
notes: z.string().nullable().optional(),
|
|
177
192
|
contactType: z.enum(["human", "assistant"]),
|
|
178
193
|
lastInteraction: z.number().nullable().optional(),
|
|
179
|
-
interactionCount: z.number(),
|
|
194
|
+
interactionCount: z.number().nullable(),
|
|
180
195
|
createdAt: z.number(),
|
|
181
196
|
updatedAt: z.number(),
|
|
182
197
|
channels: z.array(contactChannelSchema),
|
|
@@ -211,6 +226,97 @@ async function relayListContacts(limit: number, role: ContactRole | undefined) {
|
|
|
211
226
|
}
|
|
212
227
|
}
|
|
213
228
|
|
|
229
|
+
/**
|
|
230
|
+
* A daemon-native contact read whose gateway-owned interaction telemetry has
|
|
231
|
+
* been overlaid. `interactionCount` is a count, so it defaults to 0 on the
|
|
232
|
+
* gateway fail-soft/id-miss path (matching the gateway's NOT NULL DEFAULT 0
|
|
233
|
+
* column) — consumers never see `null` and render a real number. The
|
|
234
|
+
* `lastSeenAt`/`lastInteraction` timestamps stay nullable: a "never" timestamp
|
|
235
|
+
* is legitimately absent.
|
|
236
|
+
*/
|
|
237
|
+
type ContactWithGatewayTelemetry = Omit<ContactWithChannels, "channels"> & {
|
|
238
|
+
interactionCount: number;
|
|
239
|
+
lastInteraction: number | null;
|
|
240
|
+
channels: Array<
|
|
241
|
+
ContactChannel & {
|
|
242
|
+
lastSeenAt: number | null;
|
|
243
|
+
interactionCount: number;
|
|
244
|
+
lastInteraction: number | null;
|
|
245
|
+
}
|
|
246
|
+
>;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Key channels by (type, lower(address)) for the id-miss telemetry fallback.
|
|
251
|
+
* Matches the gateway's UNIQUE(type, address) NOCASE collation; the NUL
|
|
252
|
+
* delimiter cannot appear in either field, so keys never collide.
|
|
253
|
+
*/
|
|
254
|
+
function channelKey(type: string, address: string): string {
|
|
255
|
+
return `${type}\u0000${address.toLowerCase()}`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Overlay gateway-owned interaction telemetry onto daemon-native contact reads
|
|
260
|
+
* (search / contactType-filtered), which bypass the gateway list relay. The
|
|
261
|
+
* daemon still owns the FILTERING (gateway-native search/contactType is
|
|
262
|
+
* design-blocked), but telemetry (contact + channel
|
|
263
|
+
* interactionCount/lastInteraction, channel lastSeenAt) is gateway-owned — so
|
|
264
|
+
* batch-fetch it via `contacts_list_rich` keyed by the filtered id set and
|
|
265
|
+
* overlay it, keeping the local assistant-DB aggregation out of the served
|
|
266
|
+
* payload. Fail-soft: if the gateway read fails or omits a contact, its
|
|
267
|
+
* interaction counts degrade to 0 and its timestamps to null rather than
|
|
268
|
+
* falling back to the local assistant-DB aggregation.
|
|
269
|
+
*/
|
|
270
|
+
async function hydrateTelemetryFromGateway(
|
|
271
|
+
contacts: ContactWithChannels[],
|
|
272
|
+
): Promise<ContactWithGatewayTelemetry[]> {
|
|
273
|
+
if (contacts.length === 0) return [];
|
|
274
|
+
|
|
275
|
+
const gatewayById = new Map<string, ContactRead>();
|
|
276
|
+
try {
|
|
277
|
+
const result = await ipcCallPersistent("contacts_list_rich", {
|
|
278
|
+
ids: contacts.map((c) => c.id),
|
|
279
|
+
});
|
|
280
|
+
const { contacts: rich } = ListContactsIpcResponseSchema.parse(result);
|
|
281
|
+
for (const c of rich) gatewayById.set(c.id, c);
|
|
282
|
+
} catch (err) {
|
|
283
|
+
log.warn(
|
|
284
|
+
{ err },
|
|
285
|
+
"hydrateTelemetryFromGateway: gateway telemetry read failed; serving 0 counts / null timestamps",
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return contacts.map((c) => {
|
|
290
|
+
const gw = gatewayById.get(c.id);
|
|
291
|
+
const gwChannelById = new Map(
|
|
292
|
+
(gw?.channels ?? []).map((ch) => [ch.id, ch]),
|
|
293
|
+
);
|
|
294
|
+
// Local channel UUIDs can diverge from the gateway's for the same
|
|
295
|
+
// (type, address) (legacy pre-alignment channels), so an id-miss falls back
|
|
296
|
+
// to a (type, lower(address)) match — mirroring the gateway's
|
|
297
|
+
// overlayAclOntoContacts. UNIQUE(type, address) collates NOCASE gateway-side.
|
|
298
|
+
const gwChannelByTypeAddress = new Map(
|
|
299
|
+
(gw?.channels ?? []).map((ch) => [channelKey(ch.type, ch.address), ch]),
|
|
300
|
+
);
|
|
301
|
+
return {
|
|
302
|
+
...c,
|
|
303
|
+
interactionCount: gw?.interactionCount ?? 0,
|
|
304
|
+
lastInteraction: gw?.lastInteraction ?? null,
|
|
305
|
+
channels: c.channels.map((ch) => {
|
|
306
|
+
const gwCh =
|
|
307
|
+
gwChannelById.get(ch.id) ??
|
|
308
|
+
gwChannelByTypeAddress.get(channelKey(ch.type, ch.address));
|
|
309
|
+
return {
|
|
310
|
+
...ch,
|
|
311
|
+
lastSeenAt: gwCh?.lastSeenAt ?? null,
|
|
312
|
+
interactionCount: gwCh?.interactionCount ?? 0,
|
|
313
|
+
lastInteraction: gwCh?.lastInteraction ?? null,
|
|
314
|
+
};
|
|
315
|
+
}),
|
|
316
|
+
};
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
214
320
|
export async function handleListContacts(queryParams: Record<string, string>) {
|
|
215
321
|
const limit = Number(queryParams.limit ?? 50);
|
|
216
322
|
const role = (queryParams.role as ContactRole) || undefined;
|
|
@@ -234,15 +340,20 @@ export async function handleListContacts(queryParams: Record<string, string>) {
|
|
|
234
340
|
log.debug(
|
|
235
341
|
"handleListContacts: search served daemon-native (gateway-native search is design-blocked)",
|
|
236
342
|
);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
343
|
+
// Telemetry hydration and the guardian-id read (for role derivation) both
|
|
344
|
+
// hit the gateway and are independent — run them concurrently.
|
|
345
|
+
const [contacts, guardianIds] = await Promise.all([
|
|
346
|
+
hydrateTelemetryFromGateway(
|
|
347
|
+
searchContacts({
|
|
348
|
+
query,
|
|
349
|
+
channelAddress,
|
|
350
|
+
channelType,
|
|
351
|
+
contactType,
|
|
352
|
+
limit,
|
|
353
|
+
}),
|
|
354
|
+
),
|
|
355
|
+
getGuardianContactIds(),
|
|
356
|
+
]);
|
|
246
357
|
return {
|
|
247
358
|
ok: true,
|
|
248
359
|
contacts: contacts.map((c) => prepareContactResponse(c, guardianIds)),
|
|
@@ -257,9 +368,12 @@ export async function handleListContacts(queryParams: Record<string, string>) {
|
|
|
257
368
|
log.debug(
|
|
258
369
|
"handleListContacts: contactType-filtered read served daemon-native (gateway-native contactType filtering is design-blocked, pending ACL classification)",
|
|
259
370
|
);
|
|
260
|
-
|
|
261
|
-
//
|
|
262
|
-
const guardianIds = await
|
|
371
|
+
// Telemetry hydration and the guardian-id read (for role derivation) both
|
|
372
|
+
// hit the gateway and are independent — run them concurrently.
|
|
373
|
+
const [contacts, guardianIds] = await Promise.all([
|
|
374
|
+
hydrateTelemetryFromGateway(listContacts(limit, contactType)),
|
|
375
|
+
getGuardianContactIds(),
|
|
376
|
+
]);
|
|
263
377
|
return {
|
|
264
378
|
ok: true,
|
|
265
379
|
contacts: contacts.map((c) => prepareContactResponse(c, guardianIds)),
|
|
@@ -296,17 +410,10 @@ export async function handleGetContact(contactId: string) {
|
|
|
296
410
|
// Invite handlers (transport-agnostic)
|
|
297
411
|
// ---------------------------------------------------------------------------
|
|
298
412
|
|
|
299
|
-
// The gateway owns the canonical invite
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
// The invite-CREATE relay needs a generous timeout: the gateway's `invites_mint`
|
|
304
|
-
// handler calls `createIngressInvite` → `generateInviteInstruction`, which can spend
|
|
305
|
-
// up to GENERATION_TIMEOUT_MS (~5s) waiting on an LLM before falling back. The default
|
|
306
|
-
// 5s persistent-IPC timeout can fire mid-mint, so the caller sees a spurious failure
|
|
307
|
-
// even though the gateway is still writing the invite. 30s safely exceeds the inner
|
|
308
|
-
// ~5s fallback plus IPC overhead on both nested hops. (List/revoke keep the default.)
|
|
309
|
-
const INVITE_CREATE_RELAY_TIMEOUT_MS = 30_000;
|
|
413
|
+
// The gateway owns the canonical invite lifecycle: mint, list, revoke, and
|
|
414
|
+
// redemption. These CLI handlers relay via `ipcCallPersistent`; the daemon
|
|
415
|
+
// then layers the presentation fields (share link, LLM guardian instruction,
|
|
416
|
+
// channel handle) onto the gateway's one-time create payload.
|
|
310
417
|
|
|
311
418
|
export async function handleListInvites({
|
|
312
419
|
queryParams = {},
|
|
@@ -325,29 +432,41 @@ export async function handleListInvites({
|
|
|
325
432
|
}
|
|
326
433
|
|
|
327
434
|
export async function handleCreateInvite({ body = {} }: RouteHandlerArgs) {
|
|
435
|
+
const contactId = body.contactId as string;
|
|
436
|
+
const sourceChannel = body.sourceChannel as string | undefined;
|
|
437
|
+
// The guardian display label on voice invites is daemon-resolved and passed
|
|
438
|
+
// through to the gateway, which stores it and never interprets it.
|
|
439
|
+
const guardianName =
|
|
440
|
+
sourceChannel === "phone" ? resolveInviteGuardianName() : undefined;
|
|
441
|
+
let result: { invite: Record<string, unknown>; rawToken?: string };
|
|
328
442
|
try {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
)) as { invite: Record<string, unknown>; rawToken?: string };
|
|
343
|
-
return {
|
|
344
|
-
ok: true,
|
|
345
|
-
invite: result.invite,
|
|
346
|
-
...(result.rawToken ? { rawToken: result.rawToken } : {}),
|
|
347
|
-
};
|
|
443
|
+
result = (await ipcCallPersistent("invites_create", {
|
|
444
|
+
contactId,
|
|
445
|
+
sourceChannel,
|
|
446
|
+
note: body.note as string | undefined,
|
|
447
|
+
maxUses: body.maxUses as number | undefined,
|
|
448
|
+
expiresInMs: body.expiresInMs as number | undefined,
|
|
449
|
+
expectedExternalUserId: body.expectedExternalUserId as
|
|
450
|
+
| string
|
|
451
|
+
| undefined,
|
|
452
|
+
...(guardianName ? { guardianName } : {}),
|
|
453
|
+
...(typeof body.sourceConversationId === "string"
|
|
454
|
+
? { sourceConversationId: body.sourceConversationId }
|
|
455
|
+
: {}),
|
|
456
|
+
})) as { invite: Record<string, unknown>; rawToken?: string };
|
|
348
457
|
} catch (err) {
|
|
349
458
|
rethrowGatewayError(err);
|
|
350
459
|
}
|
|
460
|
+
const invite = await composeInvitePresentation({
|
|
461
|
+
contactId,
|
|
462
|
+
invite: result.invite,
|
|
463
|
+
rawToken: result.rawToken,
|
|
464
|
+
});
|
|
465
|
+
return {
|
|
466
|
+
ok: true,
|
|
467
|
+
invite,
|
|
468
|
+
...(result.rawToken ? { rawToken: result.rawToken } : {}),
|
|
469
|
+
};
|
|
351
470
|
}
|
|
352
471
|
|
|
353
472
|
export async function handleRevokeInvite({
|
|
@@ -366,58 +485,69 @@ export async function handleRevokeInvite({
|
|
|
366
485
|
/**
|
|
367
486
|
* Redeem a voice invite code.
|
|
368
487
|
*
|
|
369
|
-
* Backs the HTTP `invites_redeem` route (voice path)
|
|
370
|
-
* `
|
|
371
|
-
* `
|
|
488
|
+
* Backs the HTTP `invites_redeem` route (voice path). Parses the body with
|
|
489
|
+
* the shared `RedeemVoiceInviteRequestSchema` wire contract (plus the
|
|
490
|
+
* daemon-specific `assistantId` passthrough) and relays to the gateway's
|
|
491
|
+
* `invites_redeem` IPC — the gateway redemption engine owns validation, the
|
|
492
|
+
* atomic claim, and the ACL write. Fail-closed: a gateway relay failure
|
|
493
|
+
* surfaces as an error; there is no local redemption fallback.
|
|
372
494
|
*/
|
|
373
|
-
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (!callerExternalUserId || !code) {
|
|
495
|
+
async function handleRedeemVoiceInvite({ body = {} }: RouteHandlerArgs) {
|
|
496
|
+
const parsed = RedeemVoiceInviteRequestSchema.safeParse(body);
|
|
497
|
+
if (!parsed.success) {
|
|
378
498
|
throw new BadRequestError("callerExternalUserId and code are required");
|
|
379
499
|
}
|
|
380
500
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
501
|
+
try {
|
|
502
|
+
return (await ipcCallPersistent("invites_redeem", {
|
|
503
|
+
...parsed.data,
|
|
504
|
+
...(typeof body.assistantId === "string"
|
|
505
|
+
? { assistantId: body.assistantId }
|
|
506
|
+
: {}),
|
|
507
|
+
})) as { ok: true; type: string; memberId: string; inviteId?: string };
|
|
508
|
+
} catch (err) {
|
|
509
|
+
rethrowGatewayError(err);
|
|
390
510
|
}
|
|
511
|
+
}
|
|
391
512
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
513
|
+
/** Map a token-branch schema failure to the stable redeem error messages. */
|
|
514
|
+
function redeemTokenIssueMessage(error: z.ZodError): string {
|
|
515
|
+
for (const field of ["token", "sourceChannel"] as const) {
|
|
516
|
+
if (error.issues.some((issue) => issue.path[0] === field)) {
|
|
517
|
+
return `${field} is required`;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return error.issues[0]?.message ?? "Invalid redemption request";
|
|
398
521
|
}
|
|
399
522
|
|
|
400
523
|
/**
|
|
401
524
|
* Redeem a token invite.
|
|
402
525
|
*
|
|
403
|
-
* Backs the HTTP `invites_redeem` route (token path)
|
|
404
|
-
* `
|
|
405
|
-
*
|
|
526
|
+
* Backs the HTTP `invites_redeem` route (token path). Parses the body with
|
|
527
|
+
* the shared `RedeemInviteByTokenRequestSchema` wire contract and relays the
|
|
528
|
+
* parsed request verbatim — including the sender identity fields
|
|
529
|
+
* (`displayName` / `username`) the gateway engine stamps onto the new member —
|
|
530
|
+
* to the gateway's `invites_redeem` IPC. The gateway redemption engine owns
|
|
531
|
+
* validation, the atomic claim, and the ACL write. Fail-closed: a gateway
|
|
532
|
+
* relay failure surfaces as an error; there is no local redemption fallback.
|
|
406
533
|
*/
|
|
407
|
-
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
sourceChannel: body.sourceChannel as string | undefined,
|
|
413
|
-
});
|
|
534
|
+
async function handleRedeemTokenInvite({ body = {} }: RouteHandlerArgs) {
|
|
535
|
+
const parsed = RedeemInviteByTokenRequestSchema.safeParse(body);
|
|
536
|
+
if (!parsed.success) {
|
|
537
|
+
throw new BadRequestError(redeemTokenIssueMessage(parsed.error));
|
|
538
|
+
}
|
|
414
539
|
|
|
415
|
-
|
|
416
|
-
|
|
540
|
+
try {
|
|
541
|
+
// The `type` is surfaced so callers can tell a real redeem apart from an
|
|
542
|
+
// `already_member` no-op (which consumes no invite use).
|
|
543
|
+
return (await ipcCallPersistent("invites_redeem", parsed.data)) as {
|
|
544
|
+
ok: true;
|
|
545
|
+
invite: Record<string, unknown>;
|
|
546
|
+
type: string;
|
|
547
|
+
};
|
|
548
|
+
} catch (err) {
|
|
549
|
+
rethrowGatewayError(err);
|
|
417
550
|
}
|
|
418
|
-
// Surface the redemption `type` so the gateway can skip mirroring an
|
|
419
|
-
// `already_member` redeem (which consumes no invite use).
|
|
420
|
-
return { ok: true, invite: result.data.invite, type: result.data.type };
|
|
421
551
|
}
|
|
422
552
|
|
|
423
553
|
export async function handleRedeemInvite(args: RouteHandlerArgs) {
|
|
@@ -428,14 +558,17 @@ export async function handleRedeemInvite(args: RouteHandlerArgs) {
|
|
|
428
558
|
return handleRedeemTokenInvite(args);
|
|
429
559
|
}
|
|
430
560
|
|
|
431
|
-
// Stays daemon-local by design (like invites_redeem): the gateway
|
|
432
|
-
//
|
|
433
|
-
// ipcCallAssistant("invites_trigger_call")
|
|
434
|
-
//
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
561
|
+
// Stays daemon-local by design (like invites_redeem): the gateway validates
|
|
562
|
+
// its canonical invite row, then delegates the actual provider call to THIS
|
|
563
|
+
// handler via ipcCallAssistant("invites_trigger_call") with the resolved call
|
|
564
|
+
// fields in the body. Relaying back would loop gateway→assistant→gateway.
|
|
565
|
+
// The provider call is a daemon capability.
|
|
566
|
+
export async function handleTriggerInviteCall({ body = {} }: RouteHandlerArgs) {
|
|
567
|
+
const result = await triggerInviteCall({
|
|
568
|
+
phoneNumber: body.phoneNumber as string | undefined,
|
|
569
|
+
friendName: body.friendName as string | null | undefined,
|
|
570
|
+
guardianName: body.guardianName as string | null | undefined,
|
|
571
|
+
});
|
|
439
572
|
if (!result.ok) {
|
|
440
573
|
throw new BadRequestError(result.error);
|
|
441
574
|
}
|
|
@@ -561,6 +694,10 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
561
694
|
.string()
|
|
562
695
|
.describe("Expected user ID (E.164 for phone)")
|
|
563
696
|
.optional(),
|
|
697
|
+
sourceConversationId: z
|
|
698
|
+
.string()
|
|
699
|
+
.describe("Conversation the invite was created from (opaque)")
|
|
700
|
+
.optional(),
|
|
564
701
|
}),
|
|
565
702
|
responseBody: z.object({
|
|
566
703
|
ok: z.boolean(),
|
|
@@ -577,9 +714,9 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
577
714
|
},
|
|
578
715
|
},
|
|
579
716
|
{
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
//
|
|
717
|
+
// Relays to the gateway `invites_redeem` IPC: the gateway redemption
|
|
718
|
+
// engine is the single lifecycle authority (validation, atomic claim,
|
|
719
|
+
// ACL upsert). Fail-closed when the gateway is unreachable.
|
|
583
720
|
operationId: "invites_redeem",
|
|
584
721
|
endpoint: "contacts/invites/redeem",
|
|
585
722
|
method: "POST",
|
|
@@ -592,15 +729,33 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
592
729
|
description: "Redeem an invite by token or voice code.",
|
|
593
730
|
tags: ["contacts"],
|
|
594
731
|
requestBody: z.object({
|
|
595
|
-
token: z
|
|
596
|
-
|
|
732
|
+
token: z
|
|
733
|
+
.string()
|
|
734
|
+
.optional()
|
|
735
|
+
.describe("Invite token (token-based redemption)"),
|
|
736
|
+
code: z.string().optional().describe("Voice code (voice-code redemption)"),
|
|
597
737
|
callerExternalUserId: z
|
|
598
738
|
.string()
|
|
739
|
+
.optional()
|
|
599
740
|
.describe("Caller E.164 phone (voice-code)"),
|
|
600
|
-
externalUserId: z
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
741
|
+
externalUserId: z
|
|
742
|
+
.string()
|
|
743
|
+
.optional()
|
|
744
|
+
.describe("External user ID (token-based)"),
|
|
745
|
+
externalChatId: z
|
|
746
|
+
.string()
|
|
747
|
+
.optional()
|
|
748
|
+
.describe("External chat ID (token-based)"),
|
|
749
|
+
sourceChannel: z
|
|
750
|
+
.string()
|
|
751
|
+
.optional()
|
|
752
|
+
.describe("Source channel (token-based)"),
|
|
753
|
+
displayName: z
|
|
754
|
+
.string()
|
|
755
|
+
.optional()
|
|
756
|
+
.describe("Sender display name (token-based)"),
|
|
757
|
+
username: z.string().optional().describe("Sender username (token-based)"),
|
|
758
|
+
assistantId: z.string().optional().describe("Assistant ID (voice-code)"),
|
|
604
759
|
}),
|
|
605
760
|
responseBody: z.object({
|
|
606
761
|
ok: z.boolean(),
|
|
@@ -639,14 +794,33 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
639
794
|
operationId: "invites_trigger_call",
|
|
640
795
|
endpoint: "contacts/invites/:id/call",
|
|
641
796
|
method: "POST",
|
|
797
|
+
// Gateway-only: the handler dials whatever number is in the body — the
|
|
798
|
+
// invite validation in the gateway's triggerInviteCallNative is the sole
|
|
799
|
+
// gate, so an actor-reachable policy would be an arbitrary-dial primitive.
|
|
642
800
|
policy: {
|
|
643
|
-
requiredScopes: ["
|
|
644
|
-
allowedPrincipalTypes:
|
|
801
|
+
requiredScopes: ["internal.write"],
|
|
802
|
+
allowedPrincipalTypes: GATEWAY_PRINCIPALS,
|
|
645
803
|
},
|
|
646
804
|
handler: handleTriggerInviteCall,
|
|
647
805
|
summary: "Trigger invite call",
|
|
648
|
-
description:
|
|
806
|
+
description:
|
|
807
|
+
"Trigger an outbound call for a phone invite. Gateway-only: the gateway validates its canonical invite row and supplies the resolved call fields in the body.",
|
|
649
808
|
tags: ["contacts"],
|
|
809
|
+
requestBody: z.object({
|
|
810
|
+
phoneNumber: z
|
|
811
|
+
.string()
|
|
812
|
+
.describe("E.164 number the invite call dials (invite's bound caller)"),
|
|
813
|
+
friendName: z
|
|
814
|
+
.string()
|
|
815
|
+
.nullable()
|
|
816
|
+
.optional()
|
|
817
|
+
.describe("Invitee display name for the call greeting"),
|
|
818
|
+
guardianName: z
|
|
819
|
+
.string()
|
|
820
|
+
.nullable()
|
|
821
|
+
.optional()
|
|
822
|
+
.describe("Guardian display label recorded on the invite"),
|
|
823
|
+
}),
|
|
650
824
|
responseBody: z.object({
|
|
651
825
|
ok: z.boolean(),
|
|
652
826
|
callSid: z.string().describe("Call SID from the provider"),
|
|
@@ -706,11 +880,13 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
706
880
|
log.debug(
|
|
707
881
|
"search_contacts: search served daemon-native (gateway-native search is design-blocked)",
|
|
708
882
|
);
|
|
709
|
-
//
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
883
|
+
// Telemetry hydration and the guardian-id read (for role derivation) both
|
|
884
|
+
// hit the gateway and are independent — run them concurrently.
|
|
885
|
+
const [contacts, guardianIds] = await Promise.all([
|
|
886
|
+
hydrateTelemetryFromGateway(searchContacts(parsed)),
|
|
887
|
+
getGuardianContactIds(),
|
|
888
|
+
]);
|
|
889
|
+
return contacts.map((c) => prepareContactResponse(c, guardianIds));
|
|
714
890
|
},
|
|
715
891
|
},
|
|
716
892
|
|
|
@@ -806,11 +982,16 @@ async function handleMergeContactsRoute(args: RouteHandlerArgs) {
|
|
|
806
982
|
|
|
807
983
|
try {
|
|
808
984
|
const contact = mergeContacts(keepId, mergeId);
|
|
809
|
-
// Daemon-native read (assistant DB):
|
|
810
|
-
|
|
985
|
+
// Daemon-native read (assistant DB): telemetry is gateway-owned, so overlay
|
|
986
|
+
// it (fail-soft to null) and derive role from the guardian-id set. Both hit
|
|
987
|
+
// the gateway and are independent — run them concurrently.
|
|
988
|
+
const [[hydrated], guardianIds] = await Promise.all([
|
|
989
|
+
hydrateTelemetryFromGateway([contact]),
|
|
990
|
+
getGuardianContactIds(),
|
|
991
|
+
]);
|
|
811
992
|
return {
|
|
812
993
|
ok: true,
|
|
813
|
-
contact: prepareContactResponse(
|
|
994
|
+
contact: prepareContactResponse(hydrated, guardianIds),
|
|
814
995
|
};
|
|
815
996
|
} catch (err) {
|
|
816
997
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -117,6 +117,12 @@ export const conversationSummarySchema = z.object({
|
|
|
117
117
|
*/
|
|
118
118
|
surfacedAt: z.number().optional(),
|
|
119
119
|
inferenceProfile: z.string().optional(),
|
|
120
|
+
/**
|
|
121
|
+
* Plugin-id list scoping this chat to a subset of installed plugins.
|
|
122
|
+
* Absent when there is no per-chat restriction (default: all enabled
|
|
123
|
+
* plugins); an explicit `[]` means the user cleared all optional plugins.
|
|
124
|
+
*/
|
|
125
|
+
enabledPlugins: z.array(z.string()).nullable().optional(),
|
|
120
126
|
/**
|
|
121
127
|
* True when the agent loop is currently mid-turn for this conversation.
|
|
122
128
|
* Mirrors the in-memory `Conversation.isProcessing()` flag on the daemon
|