@vellumai/assistant 0.10.0 → 0.10.1-dev.202606240317.ea25efe
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 +36 -37
- package/bun.lock +3 -0
- package/docs/workflows.md +12 -7
- package/eslint-rules/cli-no-daemon-internals.js +12 -0
- package/node_modules/@slack/types/LICENSE +23 -0
- package/node_modules/@slack/types/README.md +32 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
- package/node_modules/@slack/types/dist/calls.d.ts +26 -0
- package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/calls.js +6 -0
- package/node_modules/@slack/types/dist/calls.js.map +1 -0
- package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
- package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/chunk.js +3 -0
- package/node_modules/@slack/types/dist/chunk.js.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
- package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
- package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/dialog.js +3 -0
- package/node_modules/@slack/types/dist/dialog.js.map +1 -0
- package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
- package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/app.js +3 -0
- package/node_modules/@slack/types/dist/events/app.js.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.js +3 -0
- package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
- package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/call.js +3 -0
- package/node_modules/@slack/types/dist/events/call.js.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.js +3 -0
- package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.js +3 -0
- package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
- package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
- package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/email.js +3 -0
- package/node_modules/@slack/types/dist/events/email.js.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.js +3 -0
- package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
- package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/file.js +4 -0
- package/node_modules/@slack/types/dist/events/file.js.map +1 -0
- package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
- package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/function.js +3 -0
- package/node_modules/@slack/types/dist/events/function.js.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
- package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
- package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/group.js +3 -0
- package/node_modules/@slack/types/dist/events/group.js.map +1 -0
- package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
- package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/im.js +3 -0
- package/node_modules/@slack/types/dist/events/im.js.map +1 -0
- package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/index.js +43 -0
- package/node_modules/@slack/types/dist/events/index.js.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.js +3 -0
- package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
- package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
- package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
- package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/member.js +3 -0
- package/node_modules/@slack/types/dist/events/member.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
- package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message.js +3 -0
- package/node_modules/@slack/types/dist/events/message.js.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.js +3 -0
- package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.js +3 -0
- package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
- package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/star.js +3 -0
- package/node_modules/@slack/types/dist/events/star.js.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.js +3 -0
- package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
- package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
- package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/team.js +3 -0
- package/node_modules/@slack/types/dist/events/team.js.map +1 -0
- package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/token.js +3 -0
- package/node_modules/@slack/types/dist/events/token.js.map +1 -0
- package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
- package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/user.js +3 -0
- package/node_modules/@slack/types/dist/events/user.js.map +1 -0
- package/node_modules/@slack/types/dist/index.d.ts +12 -0
- package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/index.js +28 -0
- package/node_modules/@slack/types/dist/index.js.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.js +3 -0
- package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.js +27 -0
- package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/views.d.ts +71 -0
- package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/views.js +3 -0
- package/node_modules/@slack/types/dist/views.js.map +1 -0
- package/node_modules/@slack/types/package.json +47 -0
- package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +96 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +28 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +95 -0
- package/openapi.yaml +458 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- package/scripts/test.sh +36 -15
- package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
- package/src/__tests__/activation-early-marking.test.ts +1 -1
- package/src/__tests__/actor-token-service.test.ts +39 -17
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
- package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
- package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/anthropic-provider.test.ts +210 -9
- package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
- package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
- package/src/__tests__/app-source-watcher.test.ts +30 -10
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
- package/src/__tests__/approval-primitive.test.ts +1 -1
- package/src/__tests__/approval-routes-http.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +155 -0
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
- package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
- package/src/__tests__/attachments-store.test.ts +1 -1
- package/src/__tests__/audit-log-rotation.test.ts +50 -54
- package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
- package/src/__tests__/background-shell-bash.test.ts +4 -1
- package/src/__tests__/background-shell-host-bash.test.ts +17 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-controller.test.ts +20 -1
- package/src/__tests__/call-conversation-messages.test.ts +1 -1
- package/src/__tests__/call-domain.test.ts +1 -1
- package/src/__tests__/call-pointer-messages.test.ts +3 -4
- package/src/__tests__/call-recovery.test.ts +1 -1
- package/src/__tests__/call-routes-http.test.ts +1 -1
- package/src/__tests__/call-store.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/canonical-guardian-store.test.ts +24 -1
- package/src/__tests__/card-surface-data.test.ts +60 -0
- package/src/__tests__/channel-approval-routes.test.ts +73 -1119
- package/src/__tests__/channel-delivery-store.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +291 -641
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
- package/src/__tests__/channel-retry-sweep.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compaction-trail-store.test.ts +6 -5
- package/src/__tests__/compaction.benchmark.test.ts +0 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +188 -52
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
- package/src/__tests__/contact-store-user-file.test.ts +2 -2
- package/src/__tests__/contacts-relay-reads.test.ts +409 -0
- package/src/__tests__/contacts-tools.test.ts +4 -4
- package/src/__tests__/contacts-write.test.ts +1 -2
- package/src/__tests__/context-search-conversations-source.test.ts +1 -1
- package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop.test.ts +7 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -5
- package/src/__tests__/conversation-attention-store.test.ts +1 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
- package/src/__tests__/conversation-clear-safety.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +10 -8
- package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
- package/src/__tests__/conversation-fork-route.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +117 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -3
- package/src/__tests__/conversation-process-callsite.test.ts +6 -14
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +95 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +12 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +12 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-starter-routes.test.ts +5 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +4 -4
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +352 -0
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-wipe.test.ts +9 -8
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/db-acp-history.test.ts +2 -2
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
- package/src/__tests__/db-migration-rollback.test.ts +129 -39
- package/src/__tests__/db-proxy-transaction.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
- package/src/__tests__/db-test-helpers.ts +36 -19
- package/src/__tests__/delete-propagation.test.ts +1 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +28 -8
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/dm-backfill.test.ts +1 -1
- package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
- package/src/__tests__/dynamic-page-surface.test.ts +0 -94
- package/src/__tests__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +93 -5
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -1
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/followup-tools.test.ts +1 -1
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-action-sweep.test.ts +9 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +76 -11
- package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +96 -2
- package/src/__tests__/guardian-outbound-http.test.ts +20 -12
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/guardian-routing-state.test.ts +1 -2
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +2 -2
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +6 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +92 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- package/src/__tests__/http-user-message-parity.test.ts +165 -8
- package/src/__tests__/image-recovery-hook.test.ts +1 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
- package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
- package/src/__tests__/inference-profile-reaper.test.ts +1 -1
- package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
- package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +11 -6
- package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
- package/src/__tests__/invite-redemption-service.test.ts +244 -43
- package/src/__tests__/invite-routes-http.test.ts +35 -186
- package/src/__tests__/invite-service-ipc.test.ts +287 -0
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
- package/src/__tests__/list-messages-attachments.test.ts +42 -1
- package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
- package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
- package/src/__tests__/list-messages-page-latest.test.ts +1 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-context-route-provider.test.ts +69 -4
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
- package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
- package/src/__tests__/llm-resolver.test.ts +205 -5
- package/src/__tests__/llm-usage-store.test.ts +65 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
- package/src/__tests__/memory-recall-log-store.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
- package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +375 -0
- package/src/__tests__/non-member-access-request.test.ts +190 -19
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +4 -0
- package/src/__tests__/notification-guardian-path.test.ts +20 -1
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +1 -1
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
- package/src/__tests__/persist-unsendable-image.test.ts +1 -1
- package/src/__tests__/persona-resolver.test.ts +39 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/playbook-execution.test.ts +1 -1
- package/src/__tests__/playbook-tools.test.ts +1 -1
- package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
- package/src/__tests__/plugin-bootstrap.test.ts +78 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
- package/src/__tests__/provider-usage-tracking.test.ts +40 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/registry.test.ts +3 -0
- package/src/__tests__/relay-server.test.ts +1026 -73
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -1
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-retry.test.ts +1 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +1 -1
- package/src/__tests__/schedule-store.test.ts +1 -1
- package/src/__tests__/schedule-tools.test.ts +1 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +1 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
- package/src/__tests__/scheduler-wake.test.ts +2 -1
- package/src/__tests__/scoped-approval-grants.test.ts +1 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
- package/src/__tests__/secret-ingress-http.test.ts +12 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +31 -9
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +40 -1
- package/src/__tests__/settings-routes.test.ts +11 -10
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +48 -5
- package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +102 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +44 -13
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
- package/src/__tests__/subagent-tools.test.ts +1 -31
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/task-management-tools.test.ts +1 -1
- package/src/__tests__/task-memory-cleanup.test.ts +9 -6
- package/src/__tests__/task-scheduler.test.ts +1 -1
- package/src/__tests__/thread-backfill.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +37 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
- package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
- package/src/__tests__/turn-events-store.test.ts +1 -1
- package/src/__tests__/twilio-routes.test.ts +98 -3
- package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
- package/src/__tests__/usage-routes.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +34 -29
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/voice-invite-redemption.test.ts +134 -36
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
- package/src/__tests__/voice-session-bridge.test.ts +1 -1
- package/src/__tests__/workspace-git-service.test.ts +114 -1
- package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
- package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
- package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
- package/src/__tests__/workspace-tool-loader.test.ts +3 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
- package/src/a2a/__tests__/task-store.test.ts +1 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
- package/src/acp/__tests__/session-manager.test.ts +72 -1
- package/src/acp/index.ts +10 -0
- package/src/acp/session-manager.ts +35 -0
- package/src/agent/loop-exclusive-tool.test.ts +150 -0
- package/src/agent/loop.ts +101 -27
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/ui-surface-show.ts +8 -3
- package/src/api/index.ts +7 -6
- package/src/api/responses/conversation-message.ts +4 -0
- package/src/api/responses/llm-request-log-entry.ts +25 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +33 -0
- package/src/approvals/AGENTS.md +1 -2
- package/src/approvals/guardian-decision-primitive.ts +13 -210
- package/src/approvals/guardian-request-resolvers.ts +104 -58
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +349 -65
- package/src/calls/guardian-dispatch.ts +10 -8
- package/src/calls/inbound-trust-reader.ts +56 -0
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-server.ts +231 -72
- package/src/calls/relay-setup-router.ts +57 -13
- package/src/calls/relay-verification.ts +7 -7
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +13 -3
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/contacts.ts +6 -24
- package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
- package/src/cli/commands/db/__tests__/status.test.ts +7 -3
- package/src/cli/commands/db/status.ts +212 -33
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
- package/src/cli/commands/memory/index.ts +4 -0
- package/src/cli/commands/memory/memory-retrospective.ts +129 -0
- package/src/cli/commands/memory/memory-v3.ts +176 -4
- package/src/cli/commands/memory/worker.ts +175 -0
- package/src/cli/commands/plugins.ts +343 -14
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
- package/src/cli/lib/install-from-github.ts +47 -6
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/toggle-plugin.ts +146 -0
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
- package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
- package/src/config/bundled-skills/contacts/SKILL.md +7 -12
- package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +4 -3
- package/src/config/call-site-defaults.ts +11 -2
- package/src/config/feature-flag-registry.json +0 -8
- package/src/config/llm-resolver.ts +151 -14
- package/src/config/loader.ts +36 -5
- package/src/config/profile-dispatchability.ts +11 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +17 -3
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +32 -0
- package/src/config/seed-inference-profiles.ts +147 -50
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/contact-store.ts +21 -0
- package/src/contacts/contacts-write.ts +3 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/contacts/member-status.ts +9 -0
- package/src/credential-health/credential-health-service.ts +1 -5
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/app-source-watcher.ts +31 -18
- package/src/daemon/assistant-attachments.ts +94 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
- package/src/daemon/conversation-agent-loop.ts +18 -36
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-surfaces.ts +273 -18
- package/src/daemon/conversation-tool-setup.ts +24 -64
- package/src/daemon/conversation.ts +149 -53
- package/src/daemon/disk-pressure-guard.ts +12 -2
- package/src/daemon/event-loop-watchdog.test.ts +85 -0
- package/src/daemon/event-loop-watchdog.ts +133 -0
- package/src/daemon/external-plugins-bootstrap.ts +26 -80
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
- package/src/daemon/handlers/config-channels.ts +41 -27
- package/src/daemon/handlers/conversations.ts +84 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +44 -5
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/message-types/inbox.ts +0 -6
- package/src/daemon/message-types/messages.ts +0 -4
- package/src/daemon/message-types/surfaces.ts +12 -11
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +7 -5
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-conversation-ops.ts +70 -0
- package/src/daemon/workspace-tools-watcher.ts +7 -3
- package/src/documents/document-comments-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
- package/src/heartbeat/heartbeat-service.ts +3 -4
- package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +10 -2
- package/src/ipc/gateway-client.ts +2 -1
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
- package/src/ipc/routes/invite-ipc-routes.ts +66 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
- package/src/memory/__tests__/activation-session-store.test.ts +1 -1
- package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
- package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
- package/src/memory/__tests__/conversation-queries.test.ts +1 -1
- package/src/memory/__tests__/db-async-query.test.ts +1 -1
- package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
- package/src/memory/__tests__/db-maintenance.test.ts +28 -36
- package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
- package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
- package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
- package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
- package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/table-relocation.test.ts +129 -0
- package/src/memory/conversation-crud.ts +461 -152
- package/src/memory/db-async-query.ts +89 -5
- package/src/memory/db-connection.ts +101 -18
- package/src/memory/db-init.ts +409 -234
- package/src/memory/db-maintenance.ts +43 -38
- package/src/memory/db-singleton.ts +45 -19
- package/src/memory/embedding-gemini.test.ts +3 -1
- package/src/memory/embedding-gemini.ts +18 -2
- package/src/memory/fork-message-copy.ts +170 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
- package/src/memory/graph/bootstrap.test.ts +6 -3
- package/src/memory/graph/retriever.test.ts +12 -12
- package/src/memory/graph/store.test.ts +15 -25
- package/src/memory/graph/store.ts +23 -14
- package/src/memory/graph/tool-handlers.ts +34 -5
- package/src/memory/graph/tools.ts +5 -2
- package/src/memory/indexer.ts +21 -9
- package/src/memory/job-handlers/cleanup.ts +10 -3
- package/src/memory/job-handlers/embedding.test.ts +4 -4
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
- package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
- package/src/memory/jobs-store.ts +36 -24
- package/src/memory/llm-request-log-store.ts +51 -19
- package/src/memory/llm-usage-store.ts +79 -21
- package/src/memory/memory-retrospective-job.ts +27 -19
- package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
- package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +13 -3
- package/src/memory/migrations/104-core-indexes.ts +1 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
- package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +241 -219
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
- package/src/memory/migrations/141-rename-verification-table.ts +45 -48
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
- package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
- package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
- package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
- package/src/memory/migrations/157-invite-contact-id.ts +73 -76
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
- package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
- package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
- package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
- package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
- package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
- package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
- package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +135 -68
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
- package/src/memory/migrations/217-conversation-host-access.ts +13 -18
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
- package/src/memory/migrations/230-acp-session-history.ts +23 -28
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
- package/src/memory/migrations/232-activation-state.ts +11 -16
- package/src/memory/migrations/233-document-conversations.ts +20 -25
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
- package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
- package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
- package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
- package/src/memory/migrations/242-message-bookmarks.ts +17 -22
- package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
- package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
- package/src/memory/migrations/251-a2a-tasks.ts +27 -32
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
- package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
- package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
- package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
- package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
- package/src/memory/migrations/270-schedule-description.ts +7 -12
- package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
- package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
- package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
- package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
- package/src/memory/migrations/__tests__/014-backfill-inbox-thread-state.test.ts +108 -0
- package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -0
- package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
- package/src/memory/migrations/helpers/relocation.ts +227 -0
- package/src/memory/migrations/registry.ts +63 -0
- package/src/memory/migrations/run-migrations.ts +187 -16
- package/src/memory/migrations/schema-introspection.ts +14 -0
- package/src/memory/migrations/validate-migration-state.ts +50 -145
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/raw-query.ts +47 -2
- package/src/memory/skill-loaded-events-store.test.ts +1 -1
- package/src/memory/task-memory-cleanup.ts +62 -41
- package/src/memory/tool-executed-events-store.test.ts +1 -1
- package/src/memory/turn-trace-store.test.ts +1 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
- package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
- package/src/memory/v3-eval/eval-packets.ts +197 -12
- package/src/memory/v3-eval/eval-tally.ts +234 -0
- package/src/memory/worker-control.ts +118 -0
- package/src/memory/worker-process.ts +72 -0
- package/src/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +13 -0
- package/src/messaging/providers/index.ts +1 -1
- package/src/messaging/providers/slack/send.test.ts +87 -39
- package/src/messaging/providers/slack/send.ts +84 -105
- package/src/notifications/README.md +9 -5
- package/src/notifications/__tests__/broadcaster.test.ts +16 -8
- package/src/notifications/__tests__/connected-channels.test.ts +114 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
- package/src/notifications/adapters/slack.ts +12 -10
- package/src/notifications/approval-card-builder.ts +81 -20
- package/src/notifications/approval-card-data.ts +8 -5
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/canonical-delivery-recorder.ts +7 -5
- package/src/notifications/conversation-candidates.ts +24 -59
- package/src/notifications/copy-composer.ts +48 -68
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +68 -24
- package/src/notifications/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +68 -15
- package/src/notifications/trusted-contact-payloads.ts +70 -0
- package/src/oauth/byo-connection.test.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +174 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +39 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +9 -4
- package/src/plugin-api/model-profiles.test.ts +123 -0
- package/src/plugin-api/model-profiles.ts +5 -1
- package/src/plugin-api/vision-support.test.ts +173 -0
- package/src/plugin-api/vision-support.ts +113 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +90 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
- package/src/plugins/defaults/advisor/consult.ts +65 -6
- package/src/plugins/defaults/advisor/context-pack.ts +288 -0
- package/src/plugins/defaults/advisor/steering.ts +14 -2
- package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
- package/src/plugins/defaults/compaction/window-manager.ts +45 -64
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +441 -0
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +57 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +61 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +108 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +56 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +27 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +134 -5
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +246 -19
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
- package/src/plugins/external-plugin-loader.ts +47 -6
- package/src/plugins/mtime-cache.ts +772 -0
- package/src/plugins/pipeline.ts +7 -2
- package/src/plugins/registry.ts +16 -5
- package/src/plugins/user-loader.ts +22 -76
- package/src/prompts/persona-resolver.ts +29 -11
- package/src/prompts/system-prompt.ts +1 -1
- package/src/prompts/templates/system-sections.ts +4 -4
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/anthropic/client.ts +290 -185
- package/src/providers/call-site-routing.ts +14 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +6 -1
- package/src/providers/model-catalog.ts +53 -0
- package/src/providers/openai/responses-provider.ts +5 -0
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/provider-send-message.ts +4 -0
- package/src/providers/ratelimit.ts +13 -0
- package/src/providers/retry.ts +14 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +11 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +64 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +670 -0
- package/src/runtime/access-request-helper.ts +19 -39
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/anchored-guardian.test.ts +156 -0
- package/src/runtime/anchored-guardian.ts +135 -0
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/channel-verification-service.ts +24 -0
- package/src/runtime/guardian-decision-types.ts +3 -22
- package/src/runtime/guardian-vellum-migration.ts +66 -7
- package/src/runtime/http-server.ts +1 -15
- package/src/runtime/invite-redemption-service.ts +155 -6
- package/src/runtime/invite-service.ts +113 -62
- package/src/runtime/local-actor-identity.ts +76 -11
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +163 -0
- package/src/runtime/routes/acp-routes-list.test.ts +4 -0
- package/src/runtime/routes/acp-routes.test.ts +5 -6
- package/src/runtime/routes/attachment-routes.ts +21 -17
- package/src/runtime/routes/browser-routes.ts +19 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
- package/src/runtime/routes/channel-verification-routes.ts +13 -2
- package/src/runtime/routes/contact-routes.ts +275 -164
- package/src/runtime/routes/conversation-query-routes.ts +15 -5
- package/src/runtime/routes/conversation-routes.ts +80 -66
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/inbound-message-handler.ts +21 -16
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +376 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +86 -64
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/llm-context-normalization.ts +71 -0
- package/src/runtime/routes/log-export-routes.ts +2 -2
- package/src/runtime/routes/mcp-auth-routes.ts +38 -15
- package/src/runtime/routes/memory-eval-routes.ts +92 -0
- package/src/runtime/routes/memory-item-routes.test.ts +12 -11
- package/src/runtime/routes/migration-routes.ts +51 -40
- package/src/runtime/routes/plugins-routes.ts +164 -8
- package/src/runtime/routes/schedule-routes.ts +1 -0
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +39 -51
- package/src/runtime/routes/usage-routes.ts +3 -0
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/slack-block-formatting.ts +46 -48
- package/src/runtime/trust-verdict-consumer.ts +210 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/manager.ts +9 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +89 -52
- package/src/tools/ask-question/ask-question-tool.ts +27 -73
- package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
- package/src/tools/browser/browser-execution.ts +16 -4
- package/src/tools/document/document-comment-tool.test.ts +1 -1
- package/src/tools/executor.ts +15 -3
- package/src/tools/host-terminal/host-shell.ts +28 -9
- package/src/tools/memory/register.test.ts +32 -0
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +4 -10
- package/src/tools/terminal/shell.ts +16 -5
- package/src/tools/tool-defaults.ts +2 -0
- package/src/tools/types.ts +18 -2
- package/src/tools/ui-surface/definitions.ts +0 -43
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/log-redact.ts +2 -4
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -0
- package/src/util/platform.ts +5 -0
- package/src/watcher/providers/gmail.ts +7 -2
- package/src/workflows/engine-integration.test.ts +1 -1
- package/src/workflows/engine.test.ts +1 -1
- package/src/workflows/engine.ts +22 -0
- package/src/workflows/fanout-load.test.ts +1 -1
- package/src/workflows/journal-store.test.ts +1 -1
- package/src/workflows/leaf-runner.test.ts +40 -1
- package/src/workflows/leaf-runner.ts +26 -1
- package/src/workspace/git-service.ts +144 -29
- package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
- package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/migrations/runner.ts +32 -2
- package/src/__tests__/access-request-decision.test.ts +0 -375
- package/src/__tests__/guardian-grant-minting.test.ts +0 -607
- package/src/__tests__/plugin-source-watcher.test.ts +0 -302
- package/src/api/events/turn-profile-auto-routed.ts +0 -28
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
- package/src/daemon/plugin-source-watcher.ts +0 -278
- package/src/daemon/switch-inference-profile-tool.ts +0 -62
- package/src/memory/guardian-approvals.ts +0 -361
- package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
- package/src/memory/migrations/038-actor-token-records.ts +0 -45
- package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
- package/src/memory/migrations/103-complex-migrations.ts +0 -23
- package/src/memory/migrations/113-late-migrations.ts +0 -30
- package/src/memory/migrations/index.ts +0 -301
- package/src/runtime/routes/access-request-decision.ts +0 -297
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
- package/src/runtime/routes/channel-guardian-routes.ts +0 -19
- package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
|
|
9
9
|
import { randomInt } from "node:crypto";
|
|
10
10
|
|
|
11
|
-
import type { AdmissionPolicy } from "@vellumai/gateway-client";
|
|
11
|
+
import type { AdmissionPolicy, TrustVerdict } from "@vellumai/gateway-client";
|
|
12
12
|
import type { ServerWebSocket } from "bun";
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from "../contacts/
|
|
15
|
+
getGuardianDelivery,
|
|
16
|
+
voiceGuardianDisplayName,
|
|
17
|
+
} from "../contacts/guardian-delivery-reader.js";
|
|
18
18
|
import { getAssistantName } from "../daemon/identity-helpers.js";
|
|
19
19
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
20
|
+
import type { TrustContext } from "../daemon/trust-context.js";
|
|
20
21
|
import { getCanonicalGuardianRequest } from "../memory/canonical-guardian-store.js";
|
|
21
22
|
import { addMessage } from "../memory/conversation-crud.js";
|
|
22
23
|
import { revokeScopedApprovalGrantsForContext } from "../memory/scoped-approval-grants.js";
|
|
@@ -26,6 +27,11 @@ import {
|
|
|
26
27
|
resolveActorTrust,
|
|
27
28
|
toTrustContext,
|
|
28
29
|
} from "../runtime/actor-trust-resolver.js";
|
|
30
|
+
import {
|
|
31
|
+
trustContextFromVerdict,
|
|
32
|
+
verdictHasMemberIdentity,
|
|
33
|
+
verdictMemberUnresolvable,
|
|
34
|
+
} from "../runtime/trust-verdict-consumer.js";
|
|
29
35
|
import {
|
|
30
36
|
composeVerificationVoice,
|
|
31
37
|
GUARDIAN_VERIFY_TEMPLATE_KEYS,
|
|
@@ -50,6 +56,10 @@ import {
|
|
|
50
56
|
import { ConversationRelayTransport } from "./call-transport.js";
|
|
51
57
|
import { getChannelAdmissionPolicy } from "./channel-admission-reader.js";
|
|
52
58
|
import { finalizeCall } from "./finalize-call.js";
|
|
59
|
+
import {
|
|
60
|
+
getInboundTrustVerdict,
|
|
61
|
+
getPhoneCallerVerdict,
|
|
62
|
+
} from "./inbound-trust-reader.js";
|
|
53
63
|
import {
|
|
54
64
|
classifyWaitUtterance,
|
|
55
65
|
emitAccessRequestCallbackHandoff,
|
|
@@ -71,6 +81,17 @@ const log = getLogger("relay-server");
|
|
|
71
81
|
const UUID_SHAPED_NAME =
|
|
72
82
|
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
73
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Return the first whitespace-delimited token of a name, or `null` when the
|
|
86
|
+
* input is null/blank. Used for greetings so "Carolina Flaherty" -> "Carolina".
|
|
87
|
+
*/
|
|
88
|
+
function firstToken(name: string | null | undefined): string | null {
|
|
89
|
+
if (!name) return null;
|
|
90
|
+
const trimmed = name.trim();
|
|
91
|
+
if (!trimmed) return null;
|
|
92
|
+
return trimmed.split(/\s+/)[0] ?? null;
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
// ── ConversationRelay message types ──────────────────────────────────
|
|
75
96
|
|
|
76
97
|
// Messages FROM Twilio
|
|
@@ -213,11 +234,14 @@ export class RelayConnection {
|
|
|
213
234
|
|
|
214
235
|
// Inbound voice invite redemption state
|
|
215
236
|
private inviteRedemptionActive = false;
|
|
237
|
+
// In-flight guard: true while an async redemption attempt is awaiting the
|
|
238
|
+
// gateway-backed claim, so a rapidly-repeated code is deduped rather than
|
|
239
|
+
// launching a second concurrent redeemVoiceInviteCode.
|
|
240
|
+
private inviteRedemptionInFlight = false;
|
|
216
241
|
private inviteRedemptionAssistantId: string | null = null;
|
|
217
242
|
private inviteRedemptionFromNumber: string | null = null;
|
|
218
243
|
private inviteRedemptionCodeLength = 6;
|
|
219
|
-
private
|
|
220
|
-
private inviteRedemptionGuardianName: string | null = null;
|
|
244
|
+
private inviteRedemptionInviteeName: string | null = null;
|
|
221
245
|
|
|
222
246
|
// In-call guardian approval wait state (friend-initiated)
|
|
223
247
|
private accessRequestWaitActive = false;
|
|
@@ -238,6 +262,10 @@ export class RelayConnection {
|
|
|
238
262
|
private accessRequestWaitStartedAt: number = 0;
|
|
239
263
|
private heartbeatSequence = 0;
|
|
240
264
|
|
|
265
|
+
// Guardian displayName primed from the gateway binding at setup, read
|
|
266
|
+
// synchronously by the heartbeat-driven wait-label path.
|
|
267
|
+
private primedGuardianDisplayName: string | undefined;
|
|
268
|
+
|
|
241
269
|
// In-wait prompt handling state
|
|
242
270
|
private lastInWaitReplyAt = 0;
|
|
243
271
|
private static readonly IN_WAIT_REPLY_COOLDOWN_MS = 3000;
|
|
@@ -247,6 +275,12 @@ export class RelayConnection {
|
|
|
247
275
|
private callbackOptIn = false;
|
|
248
276
|
private callbackHandoffNotified = false;
|
|
249
277
|
|
|
278
|
+
// True while mid-call trust is being re-resolved (async). handlePrompt defers
|
|
279
|
+
// prompts to trustReResolvePending so a verified caller can't start a turn
|
|
280
|
+
// under the stale pre-verification trust context during the await window.
|
|
281
|
+
private trustReResolving = false;
|
|
282
|
+
private trustReResolvePending: RelayPromptMessage[] = [];
|
|
283
|
+
|
|
250
284
|
constructor(ws: ServerWebSocket<RelayWebSocketData>, callSessionId: string) {
|
|
251
285
|
this.ws = ws;
|
|
252
286
|
this.callSessionId = callSessionId;
|
|
@@ -567,12 +601,21 @@ export class RelayConnection {
|
|
|
567
601
|
const session = getCallSession(this.callSessionId);
|
|
568
602
|
this.recordSetupBookkeeping(session, msg);
|
|
569
603
|
|
|
604
|
+
await this.primeGuardianDisplayName();
|
|
605
|
+
|
|
570
606
|
// Resolve the phone channel's inbound admission floor. The reader fails
|
|
571
607
|
// open to `null` by contract, so a transport hiccup admits the caller.
|
|
572
608
|
const admissionPolicy = await getChannelAdmissionPolicy("phone");
|
|
573
609
|
|
|
610
|
+
// Verdict-first caller trust. routeSetup uses it when present and not
|
|
611
|
+
// resolutionFailed, else falls back to local resolution. The reader
|
|
612
|
+
// returns null on failure, so a gateway blip keeps the local path.
|
|
613
|
+
const isInbound = session?.initiatedFromConversationId == null;
|
|
614
|
+
const otherPartyNumber = isInbound ? msg.from : msg.to;
|
|
615
|
+
const verdict = await getPhoneCallerVerdict(otherPartyNumber);
|
|
616
|
+
|
|
574
617
|
try {
|
|
575
|
-
await this.routeSetupOutcome(msg, session, admissionPolicy);
|
|
618
|
+
await this.routeSetupOutcome(msg, session, admissionPolicy, verdict);
|
|
576
619
|
} catch (err) {
|
|
577
620
|
// Never leave the connection stranded in "setting_up": a setup that
|
|
578
621
|
// throws before reaching a terminal outcome would otherwise drop every
|
|
@@ -601,6 +644,7 @@ export class RelayConnection {
|
|
|
601
644
|
msg: RelaySetupMessage,
|
|
602
645
|
session: ReturnType<typeof getCallSession>,
|
|
603
646
|
admissionPolicy: AdmissionPolicy | null,
|
|
647
|
+
verdict: TrustVerdict | null,
|
|
604
648
|
): Promise<void> {
|
|
605
649
|
const { outcome, resolved } = routeSetup({
|
|
606
650
|
callSessionId: this.callSessionId,
|
|
@@ -609,6 +653,7 @@ export class RelayConnection {
|
|
|
609
653
|
to: msg.to,
|
|
610
654
|
customParameters: msg.customParameters,
|
|
611
655
|
admissionPolicy,
|
|
656
|
+
verdict,
|
|
612
657
|
});
|
|
613
658
|
|
|
614
659
|
const initialTrustContext = toTrustContext(
|
|
@@ -646,8 +691,7 @@ export class RelayConnection {
|
|
|
646
691
|
this.startInviteRedemption(
|
|
647
692
|
outcome.assistantId,
|
|
648
693
|
outcome.fromNumber,
|
|
649
|
-
outcome.
|
|
650
|
-
outcome.guardianName,
|
|
694
|
+
outcome.inviteeName,
|
|
651
695
|
!resolved.isInbound,
|
|
652
696
|
);
|
|
653
697
|
return;
|
|
@@ -858,6 +902,95 @@ export class RelayConnection {
|
|
|
858
902
|
);
|
|
859
903
|
}
|
|
860
904
|
|
|
905
|
+
/**
|
|
906
|
+
* Re-resolve caller trust after a mid-call verification/activation. Prefers
|
|
907
|
+
* the gateway verdict (authoritative right after the gateway updated the
|
|
908
|
+
* binding); falls back to local resolution on a missing/failed/unusable
|
|
909
|
+
* verdict so a blip never drops the call. Mirrors the setup path's
|
|
910
|
+
* verdict-first-with-fallback condition.
|
|
911
|
+
*/
|
|
912
|
+
private async resolveMidCallTrustContext(
|
|
913
|
+
assistantId: string,
|
|
914
|
+
fromNumber: string,
|
|
915
|
+
): Promise<TrustContext> {
|
|
916
|
+
const verdict = await getInboundTrustVerdict({
|
|
917
|
+
channelType: "phone",
|
|
918
|
+
actorExternalId: fromNumber,
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
// Only a MEMBERLESS unknown verdict is treated as a stale gateway view and
|
|
922
|
+
// falls back to local: the caller was just activated, and invite redemption
|
|
923
|
+
// writes the channel assistant-side, so the gateway may not see the member
|
|
924
|
+
// yet — local resolution has it. A MEMBERFUL unknown verdict (blocked/revoked
|
|
925
|
+
// member, carrying contactId/channelId) is honored so its deny ACL is
|
|
926
|
+
// enforced; falling back could lose the gateway's member status if local
|
|
927
|
+
// state is stale.
|
|
928
|
+
const memberlessUnknown =
|
|
929
|
+
verdict?.trustClass === "unknown" && !verdictHasMemberIdentity(verdict);
|
|
930
|
+
const usable =
|
|
931
|
+
verdict &&
|
|
932
|
+
!verdict.resolutionFailed &&
|
|
933
|
+
!verdictMemberUnresolvable(verdict) &&
|
|
934
|
+
!memberlessUnknown;
|
|
935
|
+
|
|
936
|
+
if (usable) {
|
|
937
|
+
return trustContextFromVerdict(verdict, {
|
|
938
|
+
sourceChannel: "phone",
|
|
939
|
+
conversationExternalId: fromNumber,
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
return toTrustContext(
|
|
944
|
+
resolveActorTrust({
|
|
945
|
+
assistantId,
|
|
946
|
+
sourceChannel: "phone",
|
|
947
|
+
conversationExternalId: fromNumber,
|
|
948
|
+
actorExternalId: fromNumber,
|
|
949
|
+
}),
|
|
950
|
+
fromNumber,
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* Re-resolve mid-call trust and install it on the controller, deferring any
|
|
956
|
+
* prompt that arrives during the async window. Guards the gap between
|
|
957
|
+
* connectionState flipping to "connected" and the upgraded context landing so
|
|
958
|
+
* a verified caller never starts a turn under the stale pre-verification
|
|
959
|
+
* trust. Clears the guard in a finally and flushes buffered prompts under the
|
|
960
|
+
* new context, so an IPC error can't wedge the call.
|
|
961
|
+
*/
|
|
962
|
+
private async reResolveAndApplyTrustContext(
|
|
963
|
+
assistantId: string,
|
|
964
|
+
fromNumber: string,
|
|
965
|
+
): Promise<void> {
|
|
966
|
+
if (!this.controller) return;
|
|
967
|
+
this.trustReResolving = true;
|
|
968
|
+
try {
|
|
969
|
+
const context = await this.resolveMidCallTrustContext(
|
|
970
|
+
assistantId,
|
|
971
|
+
fromNumber,
|
|
972
|
+
);
|
|
973
|
+
this.controller.setTrustContext(context);
|
|
974
|
+
} finally {
|
|
975
|
+
this.trustReResolving = false;
|
|
976
|
+
this.flushDeferredPrompts();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Replay prompts buffered while trust was re-resolving. Runs after the
|
|
982
|
+
* upgraded context is installed so deferred utterances are answered under the
|
|
983
|
+
* correct trust.
|
|
984
|
+
*/
|
|
985
|
+
private flushDeferredPrompts(): void {
|
|
986
|
+
if (this.trustReResolvePending.length === 0) return;
|
|
987
|
+
const pending = this.trustReResolvePending;
|
|
988
|
+
this.trustReResolvePending = [];
|
|
989
|
+
for (const msg of pending) {
|
|
990
|
+
void this.handlePrompt(msg);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
861
994
|
/**
|
|
862
995
|
* Shared post-activation handoff for all trusted-contact success paths
|
|
863
996
|
* (access-request approval, invite redemption, verification code).
|
|
@@ -865,50 +998,54 @@ export class RelayConnection {
|
|
|
865
998
|
* transition copy, and marks the next utterance as opening-ack so the
|
|
866
999
|
* LLM continues naturally.
|
|
867
1000
|
*/
|
|
868
|
-
private continueCallAfterTrustedContactActivation(params: {
|
|
1001
|
+
private async continueCallAfterTrustedContactActivation(params: {
|
|
869
1002
|
assistantId: string;
|
|
870
1003
|
fromNumber: string;
|
|
871
1004
|
activationReason?:
|
|
872
1005
|
| "invite_redeemed"
|
|
873
1006
|
| "access_approved"
|
|
874
1007
|
| "trusted_contact_verified";
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1008
|
+
/**
|
|
1009
|
+
* Display name resolved from the bound contact (or, for outbound invite
|
|
1010
|
+
* calls, the session's recorded invitee name). Greeting uses only the
|
|
1011
|
+
* first whitespace-delimited token; an empty/blank value triggers the
|
|
1012
|
+
* neutral "Hi there" greeting rather than substituting the channel
|
|
1013
|
+
* address.
|
|
1014
|
+
*/
|
|
1015
|
+
inviteeName?: string | null;
|
|
1016
|
+
}): Promise<void> {
|
|
878
1017
|
const { assistantId, fromNumber } = params;
|
|
879
1018
|
|
|
880
1019
|
// Contact activation is handled by the gateway — the assistant no
|
|
881
1020
|
// longer writes contact/channel records on inbound voice calls.
|
|
882
1021
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1022
|
+
// Reach connected and clear wait/verification flags before re-resolving
|
|
1023
|
+
// trust, so a prompt buffered during re-resolution flushes onto the
|
|
1024
|
+
// real-turn path, not the verification/wait branches.
|
|
1025
|
+
this.connectionState = "connected";
|
|
1026
|
+
this.verificationSessionActive = false;
|
|
1027
|
+
this.inviteRedemptionActive = false;
|
|
1028
|
+
this.accessRequestWaitActive = false;
|
|
1029
|
+
updateCallSession(this.callSessionId, { status: "in_progress" });
|
|
889
1030
|
|
|
890
1031
|
if (this.controller) {
|
|
891
|
-
this.
|
|
1032
|
+
await this.reResolveAndApplyTrustContext(assistantId, fromNumber);
|
|
892
1033
|
}
|
|
893
1034
|
|
|
894
|
-
this.connectionState = "connected";
|
|
895
|
-
updateCallSession(this.callSessionId, { status: "in_progress" });
|
|
896
|
-
|
|
897
1035
|
const guardianLabel = this.resolveGuardianLabel();
|
|
898
1036
|
let handoffText: string;
|
|
899
1037
|
|
|
900
1038
|
if (params.activationReason === "invite_redeemed") {
|
|
901
|
-
const
|
|
1039
|
+
const firstName = firstToken(params.inviteeName);
|
|
902
1040
|
const assistantName = this.resolveAssistantLabel();
|
|
903
|
-
|
|
904
|
-
if (name) {
|
|
1041
|
+
if (firstName) {
|
|
905
1042
|
handoffText = assistantName
|
|
906
|
-
? `Great, I've verified that you are ${
|
|
907
|
-
: `Great, I've verified that you are ${
|
|
1043
|
+
? `Great, I've verified that you are ${firstName}. It's nice to meet you! I'm ${assistantName}, ${guardianLabel}'s assistant. How can I help?`
|
|
1044
|
+
: `Great, I've verified that you are ${firstName}. It's nice to meet you! How can I help?`;
|
|
908
1045
|
} else {
|
|
909
1046
|
handoffText = assistantName
|
|
910
|
-
? `
|
|
911
|
-
: `
|
|
1047
|
+
? `Hi there! I'm ${assistantName}, ${guardianLabel}'s assistant. How can I help?`
|
|
1048
|
+
: `Hi there! How can I help?`;
|
|
912
1049
|
}
|
|
913
1050
|
} else {
|
|
914
1051
|
handoffText = `Great! ${guardianLabel} said I can speak with you. How can I help?`;
|
|
@@ -1073,15 +1210,7 @@ export class RelayConnection {
|
|
|
1073
1210
|
|
|
1074
1211
|
// Update trust context on the controller so the LLM knows this is the guardian
|
|
1075
1212
|
if (this.controller) {
|
|
1076
|
-
|
|
1077
|
-
assistantId,
|
|
1078
|
-
sourceChannel: "phone",
|
|
1079
|
-
conversationExternalId: fromNumber,
|
|
1080
|
-
actorExternalId: fromNumber,
|
|
1081
|
-
});
|
|
1082
|
-
this.controller.setTrustContext(
|
|
1083
|
-
toTrustContext(verifiedActorTrust, fromNumber),
|
|
1084
|
-
);
|
|
1213
|
+
await this.reResolveAndApplyTrustContext(assistantId, fromNumber);
|
|
1085
1214
|
}
|
|
1086
1215
|
|
|
1087
1216
|
// Mark session as in-progress and transition to guardian conversation
|
|
@@ -1098,7 +1227,7 @@ export class RelayConnection {
|
|
|
1098
1227
|
);
|
|
1099
1228
|
}
|
|
1100
1229
|
} else if (result.verificationType === "trusted_contact") {
|
|
1101
|
-
this.continueCallAfterTrustedContactActivation({
|
|
1230
|
+
await this.continueCallAfterTrustedContactActivation({
|
|
1102
1231
|
assistantId,
|
|
1103
1232
|
fromNumber,
|
|
1104
1233
|
activationReason: "trusted_contact_verified",
|
|
@@ -1107,15 +1236,7 @@ export class RelayConnection {
|
|
|
1107
1236
|
// Inbound guardian verification: binding already handled above,
|
|
1108
1237
|
// proceed to normal call flow.
|
|
1109
1238
|
if (this.controller) {
|
|
1110
|
-
|
|
1111
|
-
assistantId,
|
|
1112
|
-
sourceChannel: "phone",
|
|
1113
|
-
conversationExternalId: fromNumber,
|
|
1114
|
-
actorExternalId: fromNumber,
|
|
1115
|
-
});
|
|
1116
|
-
this.controller.setTrustContext(
|
|
1117
|
-
toTrustContext(verifiedActorTrust, fromNumber),
|
|
1118
|
-
);
|
|
1239
|
+
await this.reResolveAndApplyTrustContext(assistantId, fromNumber);
|
|
1119
1240
|
this.startNormalCallFlow(this.controller, true);
|
|
1120
1241
|
}
|
|
1121
1242
|
}
|
|
@@ -1195,15 +1316,14 @@ export class RelayConnection {
|
|
|
1195
1316
|
private startInviteRedemption(
|
|
1196
1317
|
assistantId: string,
|
|
1197
1318
|
fromNumber: string,
|
|
1198
|
-
|
|
1199
|
-
guardianName: string | null,
|
|
1319
|
+
inviteeName: string | null,
|
|
1200
1320
|
isOutbound: boolean,
|
|
1201
1321
|
): void {
|
|
1202
1322
|
this.inviteRedemptionActive = true;
|
|
1323
|
+
this.inviteRedemptionInFlight = false;
|
|
1203
1324
|
this.inviteRedemptionAssistantId = assistantId;
|
|
1204
1325
|
this.inviteRedemptionFromNumber = fromNumber;
|
|
1205
|
-
this.
|
|
1206
|
-
this.inviteRedemptionGuardianName = guardianName;
|
|
1326
|
+
this.inviteRedemptionInviteeName = inviteeName;
|
|
1207
1327
|
this.connectionState = "verification_pending";
|
|
1208
1328
|
this.verificationAttempts = 0;
|
|
1209
1329
|
this.verificationMaxAttempts = 1;
|
|
@@ -1216,8 +1336,8 @@ export class RelayConnection {
|
|
|
1216
1336
|
maxAttempts: this.verificationMaxAttempts,
|
|
1217
1337
|
});
|
|
1218
1338
|
|
|
1219
|
-
const displayFriend =
|
|
1220
|
-
const displayGuardian =
|
|
1339
|
+
const displayFriend = firstToken(inviteeName) ?? "there";
|
|
1340
|
+
const displayGuardian = this.resolveGuardianLabel();
|
|
1221
1341
|
|
|
1222
1342
|
let promptText: string;
|
|
1223
1343
|
if (isOutbound) {
|
|
@@ -1279,7 +1399,7 @@ export class RelayConnection {
|
|
|
1279
1399
|
* Creates a canonical access request, notifies the guardian, and
|
|
1280
1400
|
* enters the bounded wait loop for the guardian decision.
|
|
1281
1401
|
*/
|
|
1282
|
-
private handleNameCaptureResponse(callerName: string): void {
|
|
1402
|
+
private async handleNameCaptureResponse(callerName: string): Promise<void> {
|
|
1283
1403
|
if (!this.accessRequestAssistantId || !this.accessRequestFromNumber) {
|
|
1284
1404
|
return;
|
|
1285
1405
|
}
|
|
@@ -1300,7 +1420,7 @@ export class RelayConnection {
|
|
|
1300
1420
|
// Create canonical access request and notify the guardian, including
|
|
1301
1421
|
// the caller's spoken name and voice channel metadata.
|
|
1302
1422
|
try {
|
|
1303
|
-
const accessResult = notifyGuardianOfAccessRequest({
|
|
1423
|
+
const accessResult = await notifyGuardianOfAccessRequest({
|
|
1304
1424
|
canonicalAssistantId: this.accessRequestAssistantId,
|
|
1305
1425
|
sourceChannel: "phone",
|
|
1306
1426
|
conversationExternalId: this.accessRequestFromNumber,
|
|
@@ -1393,7 +1513,7 @@ export class RelayConnection {
|
|
|
1393
1513
|
}
|
|
1394
1514
|
|
|
1395
1515
|
if (request.status === "approved") {
|
|
1396
|
-
this.handleAccessRequestApproved();
|
|
1516
|
+
void this.handleAccessRequestApproved();
|
|
1397
1517
|
} else if (request.status === "denied") {
|
|
1398
1518
|
void this.handleAccessRequestDenied();
|
|
1399
1519
|
}
|
|
@@ -1445,7 +1565,7 @@ export class RelayConnection {
|
|
|
1445
1565
|
* Handle an approved access request: activate the caller as a trusted
|
|
1446
1566
|
* contact, update runtime context, and continue with normal call flow.
|
|
1447
1567
|
*/
|
|
1448
|
-
private handleAccessRequestApproved(): void {
|
|
1568
|
+
private async handleAccessRequestApproved(): Promise<void> {
|
|
1449
1569
|
this.clearAccessRequestWait();
|
|
1450
1570
|
|
|
1451
1571
|
const assistantId = this.accessRequestAssistantId!;
|
|
@@ -1463,7 +1583,7 @@ export class RelayConnection {
|
|
|
1463
1583
|
"Access request approved — caller activated and continuing call",
|
|
1464
1584
|
);
|
|
1465
1585
|
|
|
1466
|
-
this.continueCallAfterTrustedContactActivation({
|
|
1586
|
+
await this.continueCallAfterTrustedContactActivation({
|
|
1467
1587
|
assistantId,
|
|
1468
1588
|
fromNumber,
|
|
1469
1589
|
activationReason: "access_approved",
|
|
@@ -1620,11 +1740,37 @@ export class RelayConnection {
|
|
|
1620
1740
|
return;
|
|
1621
1741
|
}
|
|
1622
1742
|
|
|
1623
|
-
|
|
1743
|
+
// Dedup concurrent attempts: a repeated code (re-spoken / re-entered)
|
|
1744
|
+
// arriving while the async gateway-backed claim is still in flight is
|
|
1745
|
+
// ignored, so we never run a second redeemVoiceInviteCode that would see
|
|
1746
|
+
// the invite already consumed and wrongly mark the call failed. The flag
|
|
1747
|
+
// is set synchronously before awaiting and cleared in finally.
|
|
1748
|
+
if (this.inviteRedemptionInFlight) {
|
|
1749
|
+
log.info(
|
|
1750
|
+
{ callSessionId: this.callSessionId },
|
|
1751
|
+
"Ignoring repeated invite code — redemption already in flight",
|
|
1752
|
+
);
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
this.inviteRedemptionInFlight = true;
|
|
1756
|
+
|
|
1757
|
+
try {
|
|
1758
|
+
await this.runInviteCodeRedemption(enteredCode);
|
|
1759
|
+
} finally {
|
|
1760
|
+
this.inviteRedemptionInFlight = false;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
private async runInviteCodeRedemption(enteredCode: string): Promise<void> {
|
|
1765
|
+
if (!this.inviteRedemptionAssistantId || !this.inviteRedemptionFromNumber) {
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
const result = await attemptInviteCodeRedemption({
|
|
1624
1770
|
inviteRedemptionAssistantId: this.inviteRedemptionAssistantId,
|
|
1625
1771
|
inviteRedemptionFromNumber: this.inviteRedemptionFromNumber,
|
|
1626
1772
|
enteredCode,
|
|
1627
|
-
|
|
1773
|
+
guardianLabel: this.resolveGuardianLabel(),
|
|
1628
1774
|
});
|
|
1629
1775
|
|
|
1630
1776
|
if (result.outcome === "success") {
|
|
@@ -1645,12 +1791,11 @@ export class RelayConnection {
|
|
|
1645
1791
|
"Voice invite redemption succeeded",
|
|
1646
1792
|
);
|
|
1647
1793
|
|
|
1648
|
-
this.continueCallAfterTrustedContactActivation({
|
|
1794
|
+
await this.continueCallAfterTrustedContactActivation({
|
|
1649
1795
|
assistantId: this.inviteRedemptionAssistantId,
|
|
1650
1796
|
fromNumber: this.inviteRedemptionFromNumber,
|
|
1651
1797
|
activationReason: "invite_redeemed",
|
|
1652
|
-
|
|
1653
|
-
guardianName: this.inviteRedemptionGuardianName ?? undefined,
|
|
1798
|
+
inviteeName: this.inviteRedemptionInviteeName,
|
|
1654
1799
|
});
|
|
1655
1800
|
} else {
|
|
1656
1801
|
this.inviteRedemptionActive = false;
|
|
@@ -1689,15 +1834,20 @@ export class RelayConnection {
|
|
|
1689
1834
|
* Resolve a human-readable guardian label for voice wait copy.
|
|
1690
1835
|
* Delegates to the shared resolveGuardianName() which checks the
|
|
1691
1836
|
* guardian's per-user persona file (users/<slug>.md) first, then falls
|
|
1692
|
-
* back to
|
|
1837
|
+
* back to the primed gateway-binding displayName, then
|
|
1838
|
+
* DEFAULT_USER_REFERENCE.
|
|
1693
1839
|
*/
|
|
1694
1840
|
private resolveGuardianLabel(): string {
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
const guardianChannels = voiceGuardian ? null : listGuardianChannels();
|
|
1698
|
-
const guardianContact = voiceGuardian?.contact ?? guardianChannels?.contact;
|
|
1841
|
+
return resolveGuardianName(this.primedGuardianDisplayName);
|
|
1842
|
+
}
|
|
1699
1843
|
|
|
1700
|
-
|
|
1844
|
+
/**
|
|
1845
|
+
* Prime the guardian displayName from the gateway binding so the
|
|
1846
|
+
* synchronous wait-label path can read it without an IPC round-trip.
|
|
1847
|
+
*/
|
|
1848
|
+
private async primeGuardianDisplayName(): Promise<void> {
|
|
1849
|
+
const list = await getGuardianDelivery();
|
|
1850
|
+
this.primedGuardianDisplayName = voiceGuardianDisplayName(list);
|
|
1701
1851
|
}
|
|
1702
1852
|
|
|
1703
1853
|
/**
|
|
@@ -1875,6 +2025,15 @@ export class RelayConnection {
|
|
|
1875
2025
|
return;
|
|
1876
2026
|
}
|
|
1877
2027
|
|
|
2028
|
+
// Defer (don't drop) prompts while trust is being re-resolved mid-call so a
|
|
2029
|
+
// verified caller's first utterance runs under the upgraded context, not the
|
|
2030
|
+
// stale pre-verification one. flushDeferredPrompts replays them in order
|
|
2031
|
+
// once the new context lands.
|
|
2032
|
+
if (this.trustReResolving) {
|
|
2033
|
+
this.trustReResolvePending.push(msg);
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
|
|
1878
2037
|
// Prompts arriving before setup routing/ACL completes are dropped — never
|
|
1879
2038
|
// persisted or emitted — so a not-yet-authorized caller's speech can't be
|
|
1880
2039
|
// stored ahead of the admission floor / trust ACL decision.
|
|
@@ -1900,7 +2059,7 @@ export class RelayConnection {
|
|
|
1900
2059
|
{ callSessionId: this.callSessionId, callerName },
|
|
1901
2060
|
"Name captured from unknown inbound caller",
|
|
1902
2061
|
);
|
|
1903
|
-
this.handleNameCaptureResponse(callerName);
|
|
2062
|
+
await this.handleNameCaptureResponse(callerName);
|
|
1904
2063
|
return;
|
|
1905
2064
|
}
|
|
1906
2065
|
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
* next — without performing any side effects itself.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type { AdmissionPolicy } from "@vellumai/gateway-client";
|
|
9
|
+
import type { AdmissionPolicy, TrustVerdict } from "@vellumai/gateway-client";
|
|
10
10
|
|
|
11
11
|
import { getConfig } from "../config/loader.js";
|
|
12
|
+
import { getContact } from "../contacts/contact-store.js";
|
|
12
13
|
import { findActiveVoiceInvites } from "../memory/invite-store.js";
|
|
13
14
|
import {
|
|
14
15
|
type ActorTrustContext,
|
|
@@ -20,6 +21,10 @@ import {
|
|
|
20
21
|
type AdmissionPolicyResult,
|
|
21
22
|
enforceAdmissionPolicy,
|
|
22
23
|
} from "../runtime/routes/inbound-stages/admission-policy.js";
|
|
24
|
+
import {
|
|
25
|
+
actorTrustContextFromVerdict,
|
|
26
|
+
verdictMemberUnresolvable,
|
|
27
|
+
} from "../runtime/trust-verdict-consumer.js";
|
|
23
28
|
import { getLogger } from "../util/logger.js";
|
|
24
29
|
import type { CallSession } from "./types.js";
|
|
25
30
|
|
|
@@ -39,6 +44,12 @@ interface SetupContext {
|
|
|
39
44
|
* preserving all pre-admission behavior.
|
|
40
45
|
*/
|
|
41
46
|
admissionPolicy?: AdmissionPolicy | null;
|
|
47
|
+
/**
|
|
48
|
+
* Gateway-stamped caller trust verdict. When present and not
|
|
49
|
+
* `resolutionFailed`, the caller's trust is built from it; otherwise the
|
|
50
|
+
* router falls back to local resolution.
|
|
51
|
+
*/
|
|
52
|
+
verdict?: TrustVerdict | null;
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
// ── Setup outcomes ───────────────────────────────────────────────────
|
|
@@ -64,8 +75,15 @@ type SetupOutcome =
|
|
|
64
75
|
action: "invite_redemption";
|
|
65
76
|
assistantId: string;
|
|
66
77
|
fromNumber: string;
|
|
67
|
-
|
|
68
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Display name of the invitee. For inbound redemptions, resolved from the
|
|
80
|
+
* bound contact's `displayName`; falls back to the legacy `friend_name`
|
|
81
|
+
* column for pre-contact-binding invites. For outbound invite calls,
|
|
82
|
+
* carries the session-recorded `inviteFriendName`. When null/empty, the
|
|
83
|
+
* relay uses a neutral "Hi there" greeting instead of substituting the
|
|
84
|
+
* channel address.
|
|
85
|
+
*/
|
|
86
|
+
inviteeName: string | null;
|
|
69
87
|
}
|
|
70
88
|
| { action: "name_capture"; assistantId: string; fromNumber: string }
|
|
71
89
|
| {
|
|
@@ -104,12 +122,32 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
104
122
|
const isInbound = ctx.session?.initiatedFromConversationId == null;
|
|
105
123
|
const otherPartyNumber = isInbound ? ctx.from : ctx.to;
|
|
106
124
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
125
|
+
// Verdict-first: build caller trust from the gateway verdict when present.
|
|
126
|
+
// Voice falls back to local resolution on a missing/failed verdict so a
|
|
127
|
+
// gateway blip does not drop a known guardian's call — the deliberate
|
|
128
|
+
// difference from the fail-closed text path.
|
|
129
|
+
//
|
|
130
|
+
// A verdict that claims a member (contactId/channelId) but whose ACL can't be
|
|
131
|
+
// reassembled (malformed/mixed-version status·policy) also falls back to local
|
|
132
|
+
// resolution, so voice never trusts a member it cannot ACL-check. A real
|
|
133
|
+
// stranger verdict (no member identity) still takes the verdict path —
|
|
134
|
+
// memberRecord null is correct there.
|
|
135
|
+
const usable =
|
|
136
|
+
ctx.verdict &&
|
|
137
|
+
!ctx.verdict.resolutionFailed &&
|
|
138
|
+
!verdictMemberUnresolvable(ctx.verdict);
|
|
139
|
+
const actorTrust = usable
|
|
140
|
+
? actorTrustContextFromVerdict(ctx.verdict!, {
|
|
141
|
+
sourceChannel: "phone",
|
|
142
|
+
conversationExternalId: otherPartyNumber,
|
|
143
|
+
actorDisplayName: undefined,
|
|
144
|
+
})
|
|
145
|
+
: resolveActorTrust({
|
|
146
|
+
assistantId,
|
|
147
|
+
sourceChannel: "phone",
|
|
148
|
+
conversationExternalId: otherPartyNumber,
|
|
149
|
+
actorExternalId: otherPartyNumber || undefined,
|
|
150
|
+
});
|
|
113
151
|
|
|
114
152
|
const resolved: SetupResolved = {
|
|
115
153
|
assistantId,
|
|
@@ -128,8 +166,7 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
128
166
|
action: "invite_redemption" as const,
|
|
129
167
|
assistantId,
|
|
130
168
|
fromNumber: ctx.to,
|
|
131
|
-
|
|
132
|
-
guardianName: ctx.session?.inviteGuardianName ?? null,
|
|
169
|
+
inviteeName: ctx.session?.inviteFriendName ?? null,
|
|
133
170
|
},
|
|
134
171
|
resolved,
|
|
135
172
|
};
|
|
@@ -289,13 +326,20 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
289
326
|
{ callSessionId: ctx.callSessionId, from: ctx.from },
|
|
290
327
|
"Inbound voice ACL: unknown caller has active voice invite — entering redemption flow",
|
|
291
328
|
);
|
|
329
|
+
// Resolve the invitee's name from the bound contact's displayName so
|
|
330
|
+
// the post-redemption greeting matches what the guardian sees in the
|
|
331
|
+
// contact graph. `contact_id` is NOT NULL on the invite row, so every
|
|
332
|
+
// invite is bound — when the contact has no displayName the greeting
|
|
333
|
+
// falls through to the neutral "Hi there" copy in relay-server.ts
|
|
334
|
+
// rather than a stale free-text `friend_name` label.
|
|
335
|
+
const boundContact = getContact(matchedInvite.contactId);
|
|
336
|
+
const inviteeName = boundContact?.displayName?.trim() || null;
|
|
292
337
|
return {
|
|
293
338
|
outcome: {
|
|
294
339
|
action: "invite_redemption",
|
|
295
340
|
assistantId,
|
|
296
341
|
fromNumber: ctx.from,
|
|
297
|
-
|
|
298
|
-
guardianName: matchedInvite.guardianName,
|
|
342
|
+
inviteeName: inviteeName ?? null,
|
|
299
343
|
},
|
|
300
344
|
resolved,
|
|
301
345
|
};
|