@vellumai/assistant 0.10.0 → 0.10.1-staging.1
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 +6 -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__/trust-verdict-contract.test.ts +65 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -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 +78 -0
- package/openapi.yaml +345 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- 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 +3 -3
- 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 +143 -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 +1 -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__/channel-approval-routes.test.ts +73 -1119
- package/src/__tests__/channel-delivery-store.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +265 -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 +183 -51
- package/src/__tests__/config-schema.test.ts +34 -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 +3 -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 +6 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- 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 +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- 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 +26 -8
- 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__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +83 -0
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -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 +1 -1
- 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 +1 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -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 +98 -0
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- 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-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-usage-store.test.ts +40 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- 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 +1 -2
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -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__/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 +1 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/relay-server.test.ts +357 -56
- package/src/__tests__/runtime-attachment-metadata.test.ts +10 -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-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +1 -1
- 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__/slack-inbound-verification.test.ts +1 -3
- 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__/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 +32 -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 +2 -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/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.ts +45 -27
- package/src/api/index.ts +0 -6
- 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 +88 -62
- package/src/calls/inbound-trust-reader.ts +40 -0
- package/src/calls/relay-server.ts +65 -23
- package/src/calls/relay-setup-router.ts +20 -6
- package/src/calls/relay-verification.ts +7 -7
- 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/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/index.ts +2 -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/plugins.ts +268 -11
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- 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/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__/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/profile-dispatchability.ts +11 -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 +5 -3
- package/src/config/schemas/timeouts.ts +24 -0
- package/src/config/seed-inference-profiles.ts +133 -45
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/contact-store.ts +21 -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 +9 -36
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-tool-setup.ts +20 -63
- package/src/daemon/conversation.ts +144 -52
- 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 +32 -18
- package/src/daemon/handlers/conversations.ts +7 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +16 -3
- 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 +18 -8
- package/src/daemon/server.ts +0 -4
- package/src/daemon/tool-setup-types.ts +0 -7
- 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__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +8 -0
- 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__/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/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 +31 -1
- 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/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 +227 -230
- 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 +50 -57
- 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__/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/validate-migration-state.ts +50 -145
- 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__/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__/sweep-job.test.ts +2 -2
- 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/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +14 -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__/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/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/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +29 -1
- 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 +146 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +21 -0
- 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 +149 -0
- package/src/plugin-api/vision-support.ts +78 -0
- 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 +302 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +103 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +59 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +23 -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/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 +254 -185
- package/src/providers/call-site-routing.ts +10 -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 +37 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +10 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +417 -0
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/guardian-decision-types.ts +3 -22
- 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/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- 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/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 +12 -1
- 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 +24 -3
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/inbound-message-handler.ts +20 -15
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +285 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +45 -34
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/log-export-routes.ts +2 -2
- 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/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 +172 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +60 -52
- package/src/tools/ask-question/ask-question-tool.ts +14 -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/types.ts +1 -0
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -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
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for the inbound admission-floor enforcement in `routeSetup`.
|
|
3
3
|
*
|
|
4
|
-
* `routeSetup`
|
|
5
|
-
*
|
|
6
|
-
* are mocked so the
|
|
7
|
-
* challenge,
|
|
4
|
+
* `routeSetup` reads several module-level singletons (config, trust resolver,
|
|
5
|
+
* pending verification session, invite store, contact store). Those I/O
|
|
6
|
+
* collaborators are mocked so the tables below can drive trust class, member
|
|
7
|
+
* status, pending challenge, active invites, and the bound invite contact
|
|
8
|
+
* directly — no database is touched.
|
|
8
9
|
*
|
|
9
|
-
* The floor
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* enforced).
|
|
10
|
+
* The admission floor is exercised through the REAL, pure `enforceAdmissionPolicy`:
|
|
11
|
+
* `phone` is an enforced (non-exempt) channel, so the real function applies the
|
|
12
|
+
* true `rank >= floor` semantics. We deliberately do not reimplement the floor
|
|
13
|
+
* here — a test-local copy of production logic would silently drift from it.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
ADMISSION_FLOOR,
|
|
20
|
-
type AdmissionPolicy,
|
|
21
|
-
} from "@vellumai/gateway-client";
|
|
18
|
+
import type { AdmissionPolicy } from "@vellumai/gateway-client";
|
|
22
19
|
|
|
23
20
|
import type {
|
|
24
21
|
ChannelPolicy,
|
|
25
22
|
ChannelStatus,
|
|
23
|
+
ContactChannel,
|
|
24
|
+
ContactRole,
|
|
25
|
+
ContactWithChannels,
|
|
26
26
|
} from "../../contacts/types.js";
|
|
27
27
|
import type {
|
|
28
28
|
ActorTrustContext,
|
|
29
29
|
TrustClass,
|
|
30
30
|
} from "../../runtime/actor-trust-resolver.js";
|
|
31
|
-
import { TRUST_CLASS_RANK } from "../../runtime/actor-trust-resolver.js";
|
|
32
31
|
|
|
33
32
|
mock.module("../../util/logger.js", () => ({
|
|
34
33
|
getLogger: () =>
|
|
@@ -43,8 +42,6 @@ mock.module("../../config/loader.js", () => ({
|
|
|
43
42
|
let nextTrust: ActorTrustContext;
|
|
44
43
|
mock.module("../../runtime/actor-trust-resolver.js", () => ({
|
|
45
44
|
resolveActorTrust: () => nextTrust,
|
|
46
|
-
// Re-export the real rank table; the floor mock below consumes it.
|
|
47
|
-
TRUST_CLASS_RANK,
|
|
48
45
|
}));
|
|
49
46
|
|
|
50
47
|
// Controllable pending verification challenge.
|
|
@@ -55,6 +52,7 @@ mock.module("../../runtime/channel-verification-service.js", () => ({
|
|
|
55
52
|
|
|
56
53
|
// Controllable active voice invites.
|
|
57
54
|
let activeInvites: Array<{
|
|
55
|
+
contactId: string;
|
|
58
56
|
friendName: string | null;
|
|
59
57
|
guardianName: string | null;
|
|
60
58
|
expiresAt?: number;
|
|
@@ -63,38 +61,11 @@ mock.module("../../memory/invite-store.js", () => ({
|
|
|
63
61
|
findActiveVoiceInvites: () => activeInvites,
|
|
64
62
|
}));
|
|
65
63
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
() =>
|
|
70
|
-
|
|
71
|
-
trustClass: TrustClass;
|
|
72
|
-
memberStatus: ChannelStatus | undefined;
|
|
73
|
-
policy: AdmissionPolicy;
|
|
74
|
-
}) => {
|
|
75
|
-
if (input.memberStatus === "blocked" || input.memberStatus === "revoked") {
|
|
76
|
-
return {
|
|
77
|
-
admitted: false,
|
|
78
|
-
reason:
|
|
79
|
-
input.memberStatus === "blocked"
|
|
80
|
-
? "member_blocked"
|
|
81
|
-
: "member_revoked",
|
|
82
|
-
shouldChallenge: false,
|
|
83
|
-
effectivePolicy: input.policy,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
const rank = TRUST_CLASS_RANK[input.trustClass];
|
|
87
|
-
const floor = ADMISSION_FLOOR[input.policy];
|
|
88
|
-
if (rank >= floor) return { admitted: true };
|
|
89
|
-
return {
|
|
90
|
-
admitted: false,
|
|
91
|
-
reason: `admission_policy_${input.policy}`,
|
|
92
|
-
shouldChallenge: false,
|
|
93
|
-
effectivePolicy: input.policy,
|
|
94
|
-
};
|
|
95
|
-
},
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
64
|
+
// Controllable bound contact for invite-redemption name resolution.
|
|
65
|
+
let boundContact: { displayName?: string | null } | null = null;
|
|
66
|
+
mock.module("../../contacts/contact-store.js", () => ({
|
|
67
|
+
getContact: () => boundContact,
|
|
68
|
+
}));
|
|
98
69
|
|
|
99
70
|
const { routeSetup } = await import("../relay-setup-router.js");
|
|
100
71
|
|
|
@@ -102,30 +73,74 @@ const { routeSetup } = await import("../relay-setup-router.js");
|
|
|
102
73
|
// Fixtures
|
|
103
74
|
// ---------------------------------------------------------------------------
|
|
104
75
|
|
|
76
|
+
function makeChannel(overrides: Partial<ContactChannel> = {}): ContactChannel {
|
|
77
|
+
return {
|
|
78
|
+
id: "ch_1",
|
|
79
|
+
contactId: "ct_1",
|
|
80
|
+
type: "phone",
|
|
81
|
+
address: "+12025550142",
|
|
82
|
+
isPrimary: true,
|
|
83
|
+
externalChatId: null,
|
|
84
|
+
status: "active",
|
|
85
|
+
policy: "allow",
|
|
86
|
+
verifiedAt: null,
|
|
87
|
+
verifiedVia: null,
|
|
88
|
+
inviteId: null,
|
|
89
|
+
revokedReason: null,
|
|
90
|
+
blockedReason: null,
|
|
91
|
+
lastSeenAt: null,
|
|
92
|
+
interactionCount: 0,
|
|
93
|
+
lastInteraction: null,
|
|
94
|
+
updatedAt: null,
|
|
95
|
+
createdAt: 0,
|
|
96
|
+
...overrides,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function makeContact(
|
|
101
|
+
overrides: Partial<ContactWithChannels> = {},
|
|
102
|
+
): ContactWithChannels {
|
|
103
|
+
return {
|
|
104
|
+
id: "ct_1",
|
|
105
|
+
displayName: "Test Caller",
|
|
106
|
+
notes: null,
|
|
107
|
+
lastInteraction: null,
|
|
108
|
+
interactionCount: 0,
|
|
109
|
+
createdAt: 0,
|
|
110
|
+
updatedAt: 0,
|
|
111
|
+
role: "contact",
|
|
112
|
+
contactType: "human",
|
|
113
|
+
principalId: null,
|
|
114
|
+
userFile: null,
|
|
115
|
+
channels: [],
|
|
116
|
+
...overrides,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
105
120
|
function makeTrust(
|
|
106
121
|
trustClass: TrustClass,
|
|
107
|
-
channel?: {
|
|
122
|
+
channel?: {
|
|
123
|
+
status: ChannelStatus;
|
|
124
|
+
policy?: ChannelPolicy;
|
|
125
|
+
role?: ContactRole;
|
|
126
|
+
},
|
|
108
127
|
): ActorTrustContext {
|
|
109
128
|
const memberRecord = channel
|
|
110
129
|
? {
|
|
111
|
-
contact: {
|
|
112
|
-
|
|
113
|
-
role: channel.role ?? "trusted_contact",
|
|
114
|
-
} as never,
|
|
115
|
-
channel: {
|
|
116
|
-
id: "ch_1",
|
|
130
|
+
contact: makeContact({ role: channel.role ?? "contact" }),
|
|
131
|
+
channel: makeChannel({
|
|
117
132
|
status: channel.status,
|
|
118
133
|
policy: channel.policy ?? "allow",
|
|
119
|
-
}
|
|
134
|
+
}),
|
|
120
135
|
}
|
|
121
136
|
: null;
|
|
122
137
|
return {
|
|
123
|
-
canonicalSenderId: "+
|
|
138
|
+
canonicalSenderId: "+12025550142",
|
|
124
139
|
guardianBindingMatch: null,
|
|
125
140
|
memberRecord,
|
|
126
141
|
trustClass,
|
|
127
142
|
actorMetadata: {
|
|
128
|
-
identifier: "+
|
|
143
|
+
identifier: "+12025550142",
|
|
129
144
|
displayName: undefined,
|
|
130
145
|
senderDisplayName: undefined,
|
|
131
146
|
memberDisplayName: undefined,
|
|
@@ -133,15 +148,15 @@ function makeTrust(
|
|
|
133
148
|
channel: "phone",
|
|
134
149
|
trustStatus: trustClass,
|
|
135
150
|
},
|
|
136
|
-
}
|
|
151
|
+
};
|
|
137
152
|
}
|
|
138
153
|
|
|
139
154
|
function route(admissionPolicy?: AdmissionPolicy | null) {
|
|
140
155
|
return routeSetup({
|
|
141
156
|
callSessionId: "cs_1",
|
|
142
157
|
session: null, // inbound
|
|
143
|
-
from: "+
|
|
144
|
-
to: "+
|
|
158
|
+
from: "+12025550142",
|
|
159
|
+
to: "+12025550199",
|
|
145
160
|
admissionPolicy,
|
|
146
161
|
});
|
|
147
162
|
}
|
|
@@ -149,6 +164,7 @@ function route(admissionPolicy?: AdmissionPolicy | null) {
|
|
|
149
164
|
beforeEach(() => {
|
|
150
165
|
pendingChallenge = null;
|
|
151
166
|
activeInvites = [];
|
|
167
|
+
boundContact = null;
|
|
152
168
|
});
|
|
153
169
|
|
|
154
170
|
// ---------------------------------------------------------------------------
|
|
@@ -334,9 +350,19 @@ describe("routeSetup — permissive floor admits to normal_call", () => {
|
|
|
334
350
|
describe("routeSetup — floor bypasses", () => {
|
|
335
351
|
test("active voice invite bypasses the floor (no_one policy)", () => {
|
|
336
352
|
nextTrust = makeTrust("unknown");
|
|
337
|
-
activeInvites = [
|
|
353
|
+
activeInvites = [
|
|
354
|
+
{
|
|
355
|
+
contactId: "contact-123",
|
|
356
|
+
friendName: "Friend",
|
|
357
|
+
guardianName: "Guardian",
|
|
358
|
+
},
|
|
359
|
+
];
|
|
360
|
+
boundContact = { displayName: "Friend Name" };
|
|
338
361
|
const { outcome } = route("no_one");
|
|
339
362
|
expect(outcome.action).toBe("invite_redemption");
|
|
363
|
+
if (outcome.action === "invite_redemption") {
|
|
364
|
+
expect(outcome.inviteeName).toBe("Friend Name");
|
|
365
|
+
}
|
|
340
366
|
});
|
|
341
367
|
|
|
342
368
|
test("pending verification challenge bypasses the floor (no_one policy)", () => {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway-backed per-actor inbound trust verdict reader.
|
|
3
|
+
*
|
|
4
|
+
* Resolves the inbound sender's {@link TrustVerdict} from the gateway via the
|
|
5
|
+
* `resolve_inbound_trust` IPC route. Unlike the channel-admission reader this
|
|
6
|
+
* is per-actor, NOT per-channel, so there is NO caching.
|
|
7
|
+
*
|
|
8
|
+
* Returns `null` on ANY failure (transport failure, `undefined`, malformed
|
|
9
|
+
* shape, or thrown error). The caller owns the deny policy (fail-open vs
|
|
10
|
+
* fail-closed); this reader only reports the verdict or `null`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { type TrustVerdict, TrustVerdictSchema } from "@vellumai/gateway-client";
|
|
14
|
+
|
|
15
|
+
import type { ChannelId } from "../channels/types.js";
|
|
16
|
+
import { ipcCall } from "../ipc/gateway-client.js";
|
|
17
|
+
|
|
18
|
+
// Short IPC timeout so the read resolves promptly rather than stalling call
|
|
19
|
+
// setup on a gateway that accepts the socket but hangs.
|
|
20
|
+
const TRUST_IPC_TIMEOUT_MS = 2_000;
|
|
21
|
+
|
|
22
|
+
export async function getInboundTrustVerdict(input: {
|
|
23
|
+
channelType: ChannelId;
|
|
24
|
+
actorExternalId?: string;
|
|
25
|
+
}): Promise<TrustVerdict | null> {
|
|
26
|
+
try {
|
|
27
|
+
const result = (await ipcCall(
|
|
28
|
+
"resolve_inbound_trust",
|
|
29
|
+
input,
|
|
30
|
+
TRUST_IPC_TIMEOUT_MS,
|
|
31
|
+
)) as { verdict?: unknown } | null | undefined;
|
|
32
|
+
|
|
33
|
+
if (!result) return null;
|
|
34
|
+
|
|
35
|
+
const parsed = TrustVerdictSchema.safeParse(result.verdict);
|
|
36
|
+
return parsed.success ? parsed.data : null;
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -71,6 +71,17 @@ const log = getLogger("relay-server");
|
|
|
71
71
|
const UUID_SHAPED_NAME =
|
|
72
72
|
/^[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
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Return the first whitespace-delimited token of a name, or `null` when the
|
|
76
|
+
* input is null/blank. Used for greetings so "Carolina Flaherty" -> "Carolina".
|
|
77
|
+
*/
|
|
78
|
+
function firstToken(name: string | null | undefined): string | null {
|
|
79
|
+
if (!name) return null;
|
|
80
|
+
const trimmed = name.trim();
|
|
81
|
+
if (!trimmed) return null;
|
|
82
|
+
return trimmed.split(/\s+/)[0] ?? null;
|
|
83
|
+
}
|
|
84
|
+
|
|
74
85
|
// ── ConversationRelay message types ──────────────────────────────────
|
|
75
86
|
|
|
76
87
|
// Messages FROM Twilio
|
|
@@ -213,11 +224,14 @@ export class RelayConnection {
|
|
|
213
224
|
|
|
214
225
|
// Inbound voice invite redemption state
|
|
215
226
|
private inviteRedemptionActive = false;
|
|
227
|
+
// In-flight guard: true while an async redemption attempt is awaiting the
|
|
228
|
+
// gateway-backed claim, so a rapidly-repeated code is deduped rather than
|
|
229
|
+
// launching a second concurrent redeemVoiceInviteCode.
|
|
230
|
+
private inviteRedemptionInFlight = false;
|
|
216
231
|
private inviteRedemptionAssistantId: string | null = null;
|
|
217
232
|
private inviteRedemptionFromNumber: string | null = null;
|
|
218
233
|
private inviteRedemptionCodeLength = 6;
|
|
219
|
-
private
|
|
220
|
-
private inviteRedemptionGuardianName: string | null = null;
|
|
234
|
+
private inviteRedemptionInviteeName: string | null = null;
|
|
221
235
|
|
|
222
236
|
// In-call guardian approval wait state (friend-initiated)
|
|
223
237
|
private accessRequestWaitActive = false;
|
|
@@ -646,8 +660,7 @@ export class RelayConnection {
|
|
|
646
660
|
this.startInviteRedemption(
|
|
647
661
|
outcome.assistantId,
|
|
648
662
|
outcome.fromNumber,
|
|
649
|
-
outcome.
|
|
650
|
-
outcome.guardianName,
|
|
663
|
+
outcome.inviteeName,
|
|
651
664
|
!resolved.isInbound,
|
|
652
665
|
);
|
|
653
666
|
return;
|
|
@@ -872,8 +885,14 @@ export class RelayConnection {
|
|
|
872
885
|
| "invite_redeemed"
|
|
873
886
|
| "access_approved"
|
|
874
887
|
| "trusted_contact_verified";
|
|
875
|
-
|
|
876
|
-
|
|
888
|
+
/**
|
|
889
|
+
* Display name resolved from the bound contact (or, for outbound invite
|
|
890
|
+
* calls, the session's recorded invitee name). Greeting uses only the
|
|
891
|
+
* first whitespace-delimited token; an empty/blank value triggers the
|
|
892
|
+
* neutral "Hi there" greeting rather than substituting the channel
|
|
893
|
+
* address.
|
|
894
|
+
*/
|
|
895
|
+
inviteeName?: string | null;
|
|
877
896
|
}): void {
|
|
878
897
|
const { assistantId, fromNumber } = params;
|
|
879
898
|
|
|
@@ -898,17 +917,16 @@ export class RelayConnection {
|
|
|
898
917
|
let handoffText: string;
|
|
899
918
|
|
|
900
919
|
if (params.activationReason === "invite_redeemed") {
|
|
901
|
-
const
|
|
920
|
+
const firstName = firstToken(params.inviteeName);
|
|
902
921
|
const assistantName = this.resolveAssistantLabel();
|
|
903
|
-
|
|
904
|
-
if (name) {
|
|
922
|
+
if (firstName) {
|
|
905
923
|
handoffText = assistantName
|
|
906
|
-
? `Great, I've verified that you are ${
|
|
907
|
-
: `Great, I've verified that you are ${
|
|
924
|
+
? `Great, I've verified that you are ${firstName}. It's nice to meet you! I'm ${assistantName}, ${guardianLabel}'s assistant. How can I help?`
|
|
925
|
+
: `Great, I've verified that you are ${firstName}. It's nice to meet you! How can I help?`;
|
|
908
926
|
} else {
|
|
909
927
|
handoffText = assistantName
|
|
910
|
-
? `
|
|
911
|
-
: `
|
|
928
|
+
? `Hi there! I'm ${assistantName}, ${guardianLabel}'s assistant. How can I help?`
|
|
929
|
+
: `Hi there! How can I help?`;
|
|
912
930
|
}
|
|
913
931
|
} else {
|
|
914
932
|
handoffText = `Great! ${guardianLabel} said I can speak with you. How can I help?`;
|
|
@@ -1195,15 +1213,14 @@ export class RelayConnection {
|
|
|
1195
1213
|
private startInviteRedemption(
|
|
1196
1214
|
assistantId: string,
|
|
1197
1215
|
fromNumber: string,
|
|
1198
|
-
|
|
1199
|
-
guardianName: string | null,
|
|
1216
|
+
inviteeName: string | null,
|
|
1200
1217
|
isOutbound: boolean,
|
|
1201
1218
|
): void {
|
|
1202
1219
|
this.inviteRedemptionActive = true;
|
|
1220
|
+
this.inviteRedemptionInFlight = false;
|
|
1203
1221
|
this.inviteRedemptionAssistantId = assistantId;
|
|
1204
1222
|
this.inviteRedemptionFromNumber = fromNumber;
|
|
1205
|
-
this.
|
|
1206
|
-
this.inviteRedemptionGuardianName = guardianName;
|
|
1223
|
+
this.inviteRedemptionInviteeName = inviteeName;
|
|
1207
1224
|
this.connectionState = "verification_pending";
|
|
1208
1225
|
this.verificationAttempts = 0;
|
|
1209
1226
|
this.verificationMaxAttempts = 1;
|
|
@@ -1216,8 +1233,8 @@ export class RelayConnection {
|
|
|
1216
1233
|
maxAttempts: this.verificationMaxAttempts,
|
|
1217
1234
|
});
|
|
1218
1235
|
|
|
1219
|
-
const displayFriend =
|
|
1220
|
-
const displayGuardian =
|
|
1236
|
+
const displayFriend = firstToken(inviteeName) ?? "there";
|
|
1237
|
+
const displayGuardian = this.resolveGuardianLabel();
|
|
1221
1238
|
|
|
1222
1239
|
let promptText: string;
|
|
1223
1240
|
if (isOutbound) {
|
|
@@ -1620,11 +1637,37 @@ export class RelayConnection {
|
|
|
1620
1637
|
return;
|
|
1621
1638
|
}
|
|
1622
1639
|
|
|
1623
|
-
|
|
1640
|
+
// Dedup concurrent attempts: a repeated code (re-spoken / re-entered)
|
|
1641
|
+
// arriving while the async gateway-backed claim is still in flight is
|
|
1642
|
+
// ignored, so we never run a second redeemVoiceInviteCode that would see
|
|
1643
|
+
// the invite already consumed and wrongly mark the call failed. The flag
|
|
1644
|
+
// is set synchronously before awaiting and cleared in finally.
|
|
1645
|
+
if (this.inviteRedemptionInFlight) {
|
|
1646
|
+
log.info(
|
|
1647
|
+
{ callSessionId: this.callSessionId },
|
|
1648
|
+
"Ignoring repeated invite code — redemption already in flight",
|
|
1649
|
+
);
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
this.inviteRedemptionInFlight = true;
|
|
1653
|
+
|
|
1654
|
+
try {
|
|
1655
|
+
await this.runInviteCodeRedemption(enteredCode);
|
|
1656
|
+
} finally {
|
|
1657
|
+
this.inviteRedemptionInFlight = false;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
private async runInviteCodeRedemption(enteredCode: string): Promise<void> {
|
|
1662
|
+
if (!this.inviteRedemptionAssistantId || !this.inviteRedemptionFromNumber) {
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
const result = await attemptInviteCodeRedemption({
|
|
1624
1667
|
inviteRedemptionAssistantId: this.inviteRedemptionAssistantId,
|
|
1625
1668
|
inviteRedemptionFromNumber: this.inviteRedemptionFromNumber,
|
|
1626
1669
|
enteredCode,
|
|
1627
|
-
|
|
1670
|
+
guardianLabel: this.resolveGuardianLabel(),
|
|
1628
1671
|
});
|
|
1629
1672
|
|
|
1630
1673
|
if (result.outcome === "success") {
|
|
@@ -1649,8 +1692,7 @@ export class RelayConnection {
|
|
|
1649
1692
|
assistantId: this.inviteRedemptionAssistantId,
|
|
1650
1693
|
fromNumber: this.inviteRedemptionFromNumber,
|
|
1651
1694
|
activationReason: "invite_redeemed",
|
|
1652
|
-
|
|
1653
|
-
guardianName: this.inviteRedemptionGuardianName ?? undefined,
|
|
1695
|
+
inviteeName: this.inviteRedemptionInviteeName,
|
|
1654
1696
|
});
|
|
1655
1697
|
} else {
|
|
1656
1698
|
this.inviteRedemptionActive = false;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { AdmissionPolicy } 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,
|
|
@@ -64,8 +65,15 @@ type SetupOutcome =
|
|
|
64
65
|
action: "invite_redemption";
|
|
65
66
|
assistantId: string;
|
|
66
67
|
fromNumber: string;
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Display name of the invitee. For inbound redemptions, resolved from the
|
|
70
|
+
* bound contact's `displayName`; falls back to the legacy `friend_name`
|
|
71
|
+
* column for pre-contact-binding invites. For outbound invite calls,
|
|
72
|
+
* carries the session-recorded `inviteFriendName`. When null/empty, the
|
|
73
|
+
* relay uses a neutral "Hi there" greeting instead of substituting the
|
|
74
|
+
* channel address.
|
|
75
|
+
*/
|
|
76
|
+
inviteeName: string | null;
|
|
69
77
|
}
|
|
70
78
|
| { action: "name_capture"; assistantId: string; fromNumber: string }
|
|
71
79
|
| {
|
|
@@ -128,8 +136,7 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
128
136
|
action: "invite_redemption" as const,
|
|
129
137
|
assistantId,
|
|
130
138
|
fromNumber: ctx.to,
|
|
131
|
-
|
|
132
|
-
guardianName: ctx.session?.inviteGuardianName ?? null,
|
|
139
|
+
inviteeName: ctx.session?.inviteFriendName ?? null,
|
|
133
140
|
},
|
|
134
141
|
resolved,
|
|
135
142
|
};
|
|
@@ -289,13 +296,20 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
289
296
|
{ callSessionId: ctx.callSessionId, from: ctx.from },
|
|
290
297
|
"Inbound voice ACL: unknown caller has active voice invite — entering redemption flow",
|
|
291
298
|
);
|
|
299
|
+
// Resolve the invitee's name from the bound contact's displayName so
|
|
300
|
+
// the post-redemption greeting matches what the guardian sees in the
|
|
301
|
+
// contact graph. `contact_id` is NOT NULL on the invite row, so every
|
|
302
|
+
// invite is bound — when the contact has no displayName the greeting
|
|
303
|
+
// falls through to the neutral "Hi there" copy in relay-server.ts
|
|
304
|
+
// rather than a stale free-text `friend_name` label.
|
|
305
|
+
const boundContact = getContact(matchedInvite.contactId);
|
|
306
|
+
const inviteeName = boundContact?.displayName?.trim() || null;
|
|
292
307
|
return {
|
|
293
308
|
outcome: {
|
|
294
309
|
action: "invite_redemption",
|
|
295
310
|
assistantId,
|
|
296
311
|
fromNumber: ctx.from,
|
|
297
|
-
|
|
298
|
-
guardianName: matchedInvite.guardianName,
|
|
312
|
+
inviteeName: inviteeName ?? null,
|
|
299
313
|
},
|
|
300
314
|
resolved,
|
|
301
315
|
};
|
|
@@ -224,7 +224,8 @@ interface InviteRedemptionParams {
|
|
|
224
224
|
inviteRedemptionAssistantId: string;
|
|
225
225
|
inviteRedemptionFromNumber: string;
|
|
226
226
|
enteredCode: string;
|
|
227
|
-
|
|
227
|
+
/** Resolved guardian label used in the failure TTS message. */
|
|
228
|
+
guardianLabel: string;
|
|
228
229
|
}
|
|
229
230
|
|
|
230
231
|
type InviteRedemptionResult =
|
|
@@ -244,17 +245,17 @@ type InviteRedemptionResult =
|
|
|
244
245
|
* caller. Returns a structured result so the caller can handle state
|
|
245
246
|
* mutations and session updates.
|
|
246
247
|
*/
|
|
247
|
-
export function attemptInviteCodeRedemption(
|
|
248
|
+
export async function attemptInviteCodeRedemption(
|
|
248
249
|
params: InviteRedemptionParams,
|
|
249
|
-
): InviteRedemptionResult {
|
|
250
|
+
): Promise<InviteRedemptionResult> {
|
|
250
251
|
const {
|
|
251
252
|
inviteRedemptionAssistantId,
|
|
252
253
|
inviteRedemptionFromNumber,
|
|
253
254
|
enteredCode,
|
|
254
|
-
|
|
255
|
+
guardianLabel,
|
|
255
256
|
} = params;
|
|
256
257
|
|
|
257
|
-
const result = redeemVoiceInviteCode({
|
|
258
|
+
const result = await redeemVoiceInviteCode({
|
|
258
259
|
assistantId: inviteRedemptionAssistantId,
|
|
259
260
|
callerExternalUserId: inviteRedemptionFromNumber,
|
|
260
261
|
sourceChannel: "phone",
|
|
@@ -270,9 +271,8 @@ export function attemptInviteCodeRedemption(
|
|
|
270
271
|
};
|
|
271
272
|
}
|
|
272
273
|
|
|
273
|
-
const displayGuardian = inviteRedemptionGuardianName ?? "your contact";
|
|
274
274
|
return {
|
|
275
275
|
outcome: "failure",
|
|
276
|
-
ttsMessage: `Sorry, the code you provided is incorrect or has since expired. Please ask ${
|
|
276
|
+
ttsMessage: `Sorry, the code you provided is incorrect or has since expired. Please ask ${guardianLabel} for a new code. Goodbye.`,
|
|
277
277
|
};
|
|
278
278
|
}
|
|
@@ -614,22 +614,10 @@ Examples:
|
|
|
614
614
|
.option("--note <note>", "Optional note")
|
|
615
615
|
.option("--max-uses <n>", "Max redemptions")
|
|
616
616
|
.option("--expires-in-ms <ms>", "Expiry duration in milliseconds")
|
|
617
|
-
.option(
|
|
618
|
-
"--contact-name <name>",
|
|
619
|
-
"Contact name for personalizing instructions",
|
|
620
|
-
)
|
|
621
617
|
.option(
|
|
622
618
|
"--expected-external-user-id <id>",
|
|
623
619
|
"E.164 phone number (required for voice invites)",
|
|
624
620
|
)
|
|
625
|
-
.option(
|
|
626
|
-
"--friend-name <name>",
|
|
627
|
-
"Friend name (required for voice invites)",
|
|
628
|
-
)
|
|
629
|
-
.option(
|
|
630
|
-
"--guardian-name <name>",
|
|
631
|
-
"Guardian name (required for voice invites)",
|
|
632
|
-
)
|
|
633
621
|
.requiredOption(
|
|
634
622
|
"--contact-id <id>",
|
|
635
623
|
"Contact ID to bind the invite to",
|
|
@@ -640,20 +628,20 @@ Examples:
|
|
|
640
628
|
Creates a new invite token for the specified source channel. The --source-channel
|
|
641
629
|
flag is required and must be one of: telegram, phone, email, whatsapp.
|
|
642
630
|
|
|
631
|
+
The invitee's display name is read from the bound contact (--contact-id);
|
|
632
|
+
the guardian label is resolved at runtime. There are no free-text name flags.
|
|
633
|
+
|
|
643
634
|
Optional fields:
|
|
644
635
|
--note Free-text note attached to the invite
|
|
645
636
|
--max-uses Maximum number of times the invite can be redeemed
|
|
646
637
|
--expires-in-ms Expiry duration in milliseconds from creation
|
|
647
|
-
--contact-name Name used to personalize invite instructions
|
|
648
638
|
|
|
649
|
-
Voice invites require
|
|
639
|
+
Voice invites also require:
|
|
650
640
|
--expected-external-user-id E.164 phone number of the expected caller (e.g. +15551234567)
|
|
651
|
-
--friend-name Name the contact uses for the assistant's owner
|
|
652
|
-
--guardian-name Name of the guardian associated with this invite
|
|
653
641
|
|
|
654
642
|
Examples:
|
|
655
|
-
$ assistant contacts invites create --source-channel telegram --note "For Alice" --max-uses 1
|
|
656
|
-
$ assistant contacts invites create --source-channel phone --expected-external-user-id "+15551234567"
|
|
643
|
+
$ assistant contacts invites create --source-channel telegram --contact-id <id> --note "For Alice" --max-uses 1
|
|
644
|
+
$ assistant contacts invites create --source-channel phone --contact-id <id> --expected-external-user-id "+15551234567"`,
|
|
657
645
|
)
|
|
658
646
|
.action(
|
|
659
647
|
async (
|
|
@@ -662,10 +650,7 @@ Examples:
|
|
|
662
650
|
note?: string;
|
|
663
651
|
maxUses?: string;
|
|
664
652
|
expiresInMs?: string;
|
|
665
|
-
contactName?: string;
|
|
666
653
|
expectedExternalUserId?: string;
|
|
667
|
-
friendName?: string;
|
|
668
|
-
guardianName?: string;
|
|
669
654
|
contactId: string;
|
|
670
655
|
},
|
|
671
656
|
cmd: Command,
|
|
@@ -704,10 +689,7 @@ Examples:
|
|
|
704
689
|
note: opts.note,
|
|
705
690
|
maxUses,
|
|
706
691
|
expiresInMs,
|
|
707
|
-
contactName: opts.contactName,
|
|
708
692
|
expectedExternalUserId: opts.expectedExternalUserId,
|
|
709
|
-
friendName: opts.friendName,
|
|
710
|
-
guardianName: opts.guardianName,
|
|
711
693
|
contactId: opts.contactId,
|
|
712
694
|
},
|
|
713
695
|
});
|
|
@@ -431,20 +431,29 @@ async function initSchema(): Promise<void> {
|
|
|
431
431
|
// The repair step opens its own bun:sqlite handle but expects the schema
|
|
432
432
|
// to already exist (production-wise, the daemon creates it). Touching the
|
|
433
433
|
// global init triggers schema creation against the env-isolated path.
|
|
434
|
-
const { initializeDb } = await import("../../../../memory/db-init.js");
|
|
435
|
-
initializeDb();
|
|
436
|
-
// Close the singleton so backfill can open its own handle without
|
|
437
|
-
// collision. WAL allows concurrent handles but cleaner ownership avoids
|
|
438
|
-
// test cross-talk through the in-process cache.
|
|
439
434
|
const { getDb, getSqliteFrom } =
|
|
440
435
|
await import("../../../../memory/db-connection.js");
|
|
441
436
|
const { clearStoredDb } = await import("../../../../memory/db-singleton.js");
|
|
437
|
+
// Drop any connections a prior test (or test file) left open against a
|
|
438
|
+
// now-deleted workspace, so init below opens fresh handles — main and the
|
|
439
|
+
// dedicated logs/memory connections — at THIS test's workspace.
|
|
440
|
+
clearStoredDb("main");
|
|
441
|
+
clearStoredDb("logs");
|
|
442
|
+
clearStoredDb("memory");
|
|
443
|
+
|
|
444
|
+
const { initializeDb } = await import("../../../../memory/db-init.js");
|
|
445
|
+
await initializeDb();
|
|
446
|
+
// Close the singletons so backfill can open its own handle without
|
|
447
|
+
// collision. WAL allows concurrent handles but cleaner ownership avoids
|
|
448
|
+
// test cross-talk through the in-process cache.
|
|
442
449
|
try {
|
|
443
450
|
getSqliteFrom(getDb()).close();
|
|
444
451
|
} catch {
|
|
445
452
|
/* already closed */
|
|
446
453
|
}
|
|
447
|
-
clearStoredDb();
|
|
454
|
+
clearStoredDb("main");
|
|
455
|
+
clearStoredDb("logs");
|
|
456
|
+
clearStoredDb("memory");
|
|
448
457
|
}
|
|
449
458
|
|
|
450
459
|
describe("assistant db repair — conversation-backfill step", () => {
|