@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
|
@@ -7,6 +7,39 @@ mock.module("../util/logger.js", () => ({
|
|
|
7
7
|
}),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
+
// Mock the gateway IPC bridge used by the redemption service for the
|
|
11
|
+
// authoritative pre-mutation claim (record_invite_redemption). Tests drive the
|
|
12
|
+
// claim result via `gatewayIpc`.
|
|
13
|
+
const gatewayIpc = {
|
|
14
|
+
claim: { ok: true, updated: true, mirrored: true } as {
|
|
15
|
+
ok: boolean;
|
|
16
|
+
updated: boolean;
|
|
17
|
+
mirrored: boolean;
|
|
18
|
+
},
|
|
19
|
+
claimThrows: false,
|
|
20
|
+
calls: [] as { method: string; params?: Record<string, unknown> }[],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
mock.module("../ipc/gateway-client.js", () => ({
|
|
24
|
+
ipcCallPersistent: async (
|
|
25
|
+
method: string,
|
|
26
|
+
params?: Record<string, unknown>,
|
|
27
|
+
) => {
|
|
28
|
+
gatewayIpc.calls.push({ method, params });
|
|
29
|
+
if (method === "record_invite_redemption") {
|
|
30
|
+
if (gatewayIpc.claimThrows) throw new Error("gateway unreachable");
|
|
31
|
+
return gatewayIpc.claim;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
},
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
function resetGatewayIpc() {
|
|
38
|
+
gatewayIpc.claim = { ok: true, updated: true, mirrored: true };
|
|
39
|
+
gatewayIpc.claimThrows = false;
|
|
40
|
+
gatewayIpc.calls = [];
|
|
41
|
+
}
|
|
42
|
+
|
|
10
43
|
import {
|
|
11
44
|
findContactChannel,
|
|
12
45
|
getContact,
|
|
@@ -26,7 +59,7 @@ import {
|
|
|
26
59
|
} from "../runtime/invite-redemption-service.js";
|
|
27
60
|
import { hashVoiceCode } from "../util/voice-code.js";
|
|
28
61
|
|
|
29
|
-
initializeDb();
|
|
62
|
+
await initializeDb();
|
|
30
63
|
|
|
31
64
|
function resetTables() {
|
|
32
65
|
getSqlite().run("DELETE FROM assistant_ingress_invites");
|
|
@@ -40,9 +73,12 @@ function createTargetContact(displayName = "Target Contact"): string {
|
|
|
40
73
|
}
|
|
41
74
|
|
|
42
75
|
describe("invite-redemption-service", () => {
|
|
43
|
-
beforeEach(
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
resetTables();
|
|
78
|
+
resetGatewayIpc();
|
|
79
|
+
});
|
|
44
80
|
|
|
45
|
-
test("redeems a valid invite and returns typed outcome", () => {
|
|
81
|
+
test("redeems a valid invite and returns typed outcome", async () => {
|
|
46
82
|
const targetContactId = createTargetContact();
|
|
47
83
|
const { rawToken, invite } = createInvite({
|
|
48
84
|
sourceChannel: "telegram",
|
|
@@ -50,7 +86,7 @@ describe("invite-redemption-service", () => {
|
|
|
50
86
|
maxUses: 1,
|
|
51
87
|
});
|
|
52
88
|
|
|
53
|
-
const outcome = redeemInvite({
|
|
89
|
+
const outcome = await redeemInvite({
|
|
54
90
|
rawToken,
|
|
55
91
|
sourceChannel: "telegram",
|
|
56
92
|
externalUserId: "user-1",
|
|
@@ -65,7 +101,7 @@ describe("invite-redemption-service", () => {
|
|
|
65
101
|
});
|
|
66
102
|
});
|
|
67
103
|
|
|
68
|
-
test("marks channel as verified via invite on redemption", () => {
|
|
104
|
+
test("marks channel as verified via invite on redemption", async () => {
|
|
69
105
|
const targetContactId = createTargetContact();
|
|
70
106
|
const { rawToken } = createInvite({
|
|
71
107
|
sourceChannel: "telegram",
|
|
@@ -73,7 +109,7 @@ describe("invite-redemption-service", () => {
|
|
|
73
109
|
maxUses: 1,
|
|
74
110
|
});
|
|
75
111
|
|
|
76
|
-
const outcome = redeemInvite({
|
|
112
|
+
const outcome = await redeemInvite({
|
|
77
113
|
rawToken,
|
|
78
114
|
sourceChannel: "telegram",
|
|
79
115
|
externalUserId: "user-1",
|
|
@@ -92,7 +128,7 @@ describe("invite-redemption-service", () => {
|
|
|
92
128
|
expect(result!.channel.status).toBe("active");
|
|
93
129
|
});
|
|
94
130
|
|
|
95
|
-
test("marks channel as verified via invite on 6-digit code redemption", () => {
|
|
131
|
+
test("marks channel as verified via invite on 6-digit code redemption", async () => {
|
|
96
132
|
const targetContactId = createTargetContact();
|
|
97
133
|
const inviteCode = "123456";
|
|
98
134
|
createInvite({
|
|
@@ -102,7 +138,7 @@ describe("invite-redemption-service", () => {
|
|
|
102
138
|
inviteCodeHash: hashVoiceCode(inviteCode),
|
|
103
139
|
});
|
|
104
140
|
|
|
105
|
-
const outcome = redeemInviteByCode({
|
|
141
|
+
const outcome = await redeemInviteByCode({
|
|
106
142
|
code: inviteCode,
|
|
107
143
|
sourceChannel: "telegram",
|
|
108
144
|
externalUserId: "code-user-1",
|
|
@@ -121,8 +157,8 @@ describe("invite-redemption-service", () => {
|
|
|
121
157
|
expect(result!.channel.status).toBe("active");
|
|
122
158
|
});
|
|
123
159
|
|
|
124
|
-
test("returns invalid_token for a bogus token", () => {
|
|
125
|
-
const outcome = redeemInvite({
|
|
160
|
+
test("returns invalid_token for a bogus token", async () => {
|
|
161
|
+
const outcome = await redeemInvite({
|
|
126
162
|
rawToken: "totally-bogus-token",
|
|
127
163
|
sourceChannel: "telegram",
|
|
128
164
|
externalUserId: "user-1",
|
|
@@ -131,7 +167,7 @@ describe("invite-redemption-service", () => {
|
|
|
131
167
|
expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
|
|
132
168
|
});
|
|
133
169
|
|
|
134
|
-
test("returns expired for an expired invite", () => {
|
|
170
|
+
test("returns expired for an expired invite", async () => {
|
|
135
171
|
const targetContactId = createTargetContact();
|
|
136
172
|
// Create an invite that expired 1 ms ago
|
|
137
173
|
const { rawToken } = createInvite({
|
|
@@ -141,7 +177,7 @@ describe("invite-redemption-service", () => {
|
|
|
141
177
|
expiresInMs: -1,
|
|
142
178
|
});
|
|
143
179
|
|
|
144
|
-
const outcome = redeemInvite({
|
|
180
|
+
const outcome = await redeemInvite({
|
|
145
181
|
rawToken,
|
|
146
182
|
sourceChannel: "telegram",
|
|
147
183
|
externalUserId: "user-1",
|
|
@@ -150,7 +186,7 @@ describe("invite-redemption-service", () => {
|
|
|
150
186
|
expect(outcome).toEqual({ ok: false, reason: "expired" });
|
|
151
187
|
});
|
|
152
188
|
|
|
153
|
-
test("returns revoked for a revoked invite", () => {
|
|
189
|
+
test("returns revoked for a revoked invite", async () => {
|
|
154
190
|
const targetContactId = createTargetContact();
|
|
155
191
|
const { rawToken, invite } = createInvite({
|
|
156
192
|
sourceChannel: "telegram",
|
|
@@ -159,7 +195,7 @@ describe("invite-redemption-service", () => {
|
|
|
159
195
|
});
|
|
160
196
|
revokeStoreFn(invite.id);
|
|
161
197
|
|
|
162
|
-
const outcome = redeemInvite({
|
|
198
|
+
const outcome = await redeemInvite({
|
|
163
199
|
rawToken,
|
|
164
200
|
sourceChannel: "telegram",
|
|
165
201
|
externalUserId: "user-1",
|
|
@@ -168,7 +204,7 @@ describe("invite-redemption-service", () => {
|
|
|
168
204
|
expect(outcome).toEqual({ ok: false, reason: "revoked" });
|
|
169
205
|
});
|
|
170
206
|
|
|
171
|
-
test("returns max_uses_reached when invite is fully consumed", () => {
|
|
207
|
+
test("returns max_uses_reached when invite is fully consumed", async () => {
|
|
172
208
|
const targetContactId = createTargetContact();
|
|
173
209
|
const { rawToken } = createInvite({
|
|
174
210
|
sourceChannel: "telegram",
|
|
@@ -177,7 +213,7 @@ describe("invite-redemption-service", () => {
|
|
|
177
213
|
});
|
|
178
214
|
|
|
179
215
|
// First redemption should succeed
|
|
180
|
-
const first = redeemInvite({
|
|
216
|
+
const first = await redeemInvite({
|
|
181
217
|
rawToken,
|
|
182
218
|
sourceChannel: "telegram",
|
|
183
219
|
externalUserId: "user-1",
|
|
@@ -185,7 +221,7 @@ describe("invite-redemption-service", () => {
|
|
|
185
221
|
expect(first.ok).toBe(true);
|
|
186
222
|
|
|
187
223
|
// Second attempt should fail — the invite is now fully redeemed
|
|
188
|
-
const second = redeemInvite({
|
|
224
|
+
const second = await redeemInvite({
|
|
189
225
|
rawToken,
|
|
190
226
|
sourceChannel: "telegram",
|
|
191
227
|
externalUserId: "user-2",
|
|
@@ -194,7 +230,7 @@ describe("invite-redemption-service", () => {
|
|
|
194
230
|
expect(second).toEqual({ ok: false, reason: "max_uses_reached" });
|
|
195
231
|
});
|
|
196
232
|
|
|
197
|
-
test("returns channel_mismatch when redeeming on wrong channel", () => {
|
|
233
|
+
test("returns channel_mismatch when redeeming on wrong channel", async () => {
|
|
198
234
|
const targetContactId = createTargetContact();
|
|
199
235
|
const { rawToken } = createInvite({
|
|
200
236
|
sourceChannel: "telegram",
|
|
@@ -202,7 +238,7 @@ describe("invite-redemption-service", () => {
|
|
|
202
238
|
maxUses: 1,
|
|
203
239
|
});
|
|
204
240
|
|
|
205
|
-
const outcome = redeemInvite({
|
|
241
|
+
const outcome = await redeemInvite({
|
|
206
242
|
rawToken,
|
|
207
243
|
sourceChannel: "phone",
|
|
208
244
|
externalUserId: "user-1",
|
|
@@ -211,7 +247,7 @@ describe("invite-redemption-service", () => {
|
|
|
211
247
|
expect(outcome).toEqual({ ok: false, reason: "channel_mismatch" });
|
|
212
248
|
});
|
|
213
249
|
|
|
214
|
-
test("returns missing_identity when no externalUserId or externalChatId", () => {
|
|
250
|
+
test("returns missing_identity when no externalUserId or externalChatId", async () => {
|
|
215
251
|
const targetContactId = createTargetContact();
|
|
216
252
|
const { rawToken } = createInvite({
|
|
217
253
|
sourceChannel: "telegram",
|
|
@@ -219,7 +255,7 @@ describe("invite-redemption-service", () => {
|
|
|
219
255
|
maxUses: 1,
|
|
220
256
|
});
|
|
221
257
|
|
|
222
|
-
const outcome = redeemInvite({
|
|
258
|
+
const outcome = await redeemInvite({
|
|
223
259
|
rawToken,
|
|
224
260
|
sourceChannel: "telegram",
|
|
225
261
|
});
|
|
@@ -227,7 +263,7 @@ describe("invite-redemption-service", () => {
|
|
|
227
263
|
expect(outcome).toEqual({ ok: false, reason: "missing_identity" });
|
|
228
264
|
});
|
|
229
265
|
|
|
230
|
-
test("returns already_member when user is already an active member", () => {
|
|
266
|
+
test("returns already_member when user is already an active member", async () => {
|
|
231
267
|
// Pre-create an active member and find their contact
|
|
232
268
|
const member = upsertContactChannel({
|
|
233
269
|
sourceChannel: "telegram",
|
|
@@ -242,7 +278,7 @@ describe("invite-redemption-service", () => {
|
|
|
242
278
|
maxUses: 5,
|
|
243
279
|
});
|
|
244
280
|
|
|
245
|
-
const outcome = redeemInvite({
|
|
281
|
+
const outcome = await redeemInvite({
|
|
246
282
|
rawToken,
|
|
247
283
|
sourceChannel: "telegram",
|
|
248
284
|
externalUserId: "existing-user",
|
|
@@ -259,7 +295,7 @@ describe("invite-redemption-service", () => {
|
|
|
259
295
|
).toEqual(expect.any(String));
|
|
260
296
|
});
|
|
261
297
|
|
|
262
|
-
test("returns invalid_token for a blocked member to avoid leaking membership status", () => {
|
|
298
|
+
test("returns invalid_token for a blocked member to avoid leaking membership status", async () => {
|
|
263
299
|
// Pre-create a blocked member and find their contact
|
|
264
300
|
const member = upsertContactChannel({
|
|
265
301
|
sourceChannel: "telegram",
|
|
@@ -274,7 +310,7 @@ describe("invite-redemption-service", () => {
|
|
|
274
310
|
maxUses: 5,
|
|
275
311
|
});
|
|
276
312
|
|
|
277
|
-
const outcome = redeemInvite({
|
|
313
|
+
const outcome = await redeemInvite({
|
|
278
314
|
rawToken,
|
|
279
315
|
sourceChannel: "telegram",
|
|
280
316
|
externalUserId: "blocked-user",
|
|
@@ -283,7 +319,7 @@ describe("invite-redemption-service", () => {
|
|
|
283
319
|
expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
|
|
284
320
|
});
|
|
285
321
|
|
|
286
|
-
test("binds redeemer to the invite's target contact, not the guardian", () => {
|
|
322
|
+
test("binds redeemer to the invite's target contact, not the guardian", async () => {
|
|
287
323
|
// Pre-create a guardian contact with a revoked telegram channel
|
|
288
324
|
const guardianContact = upsertContact({
|
|
289
325
|
displayName: "Guardian",
|
|
@@ -311,7 +347,7 @@ describe("invite-redemption-service", () => {
|
|
|
311
347
|
});
|
|
312
348
|
|
|
313
349
|
// Redeem using the guardian's Telegram identity
|
|
314
|
-
const outcome = redeemInvite({
|
|
350
|
+
const outcome = await redeemInvite({
|
|
315
351
|
rawToken,
|
|
316
352
|
sourceChannel: "telegram",
|
|
317
353
|
externalUserId: "guardian-tg-id",
|
|
@@ -336,7 +372,7 @@ describe("invite-redemption-service", () => {
|
|
|
336
372
|
expect(guardian!.role).toBe("guardian");
|
|
337
373
|
});
|
|
338
374
|
|
|
339
|
-
test("downgrades guardian to contact when redeeming invite targeting own contact", () => {
|
|
375
|
+
test("downgrades guardian to contact when redeeming invite targeting own contact", async () => {
|
|
340
376
|
// Create a guardian contact with a revoked channel
|
|
341
377
|
const guardianContact = upsertContact({
|
|
342
378
|
displayName: "Guardian",
|
|
@@ -357,7 +393,7 @@ describe("invite-redemption-service", () => {
|
|
|
357
393
|
maxUses: 5,
|
|
358
394
|
});
|
|
359
395
|
|
|
360
|
-
const outcome = redeemInvite({
|
|
396
|
+
const outcome = await redeemInvite({
|
|
361
397
|
rawToken,
|
|
362
398
|
sourceChannel: "telegram",
|
|
363
399
|
externalUserId: "guardian-own-id",
|
|
@@ -370,7 +406,7 @@ describe("invite-redemption-service", () => {
|
|
|
370
406
|
expect(updated!.role).toBe("contact");
|
|
371
407
|
});
|
|
372
408
|
|
|
373
|
-
test("binds redeemer to the invite's target contact via 6-digit code, not the guardian", () => {
|
|
409
|
+
test("binds redeemer to the invite's target contact via 6-digit code, not the guardian", async () => {
|
|
374
410
|
// Pre-create a guardian contact with a revoked telegram channel
|
|
375
411
|
const guardianContact = upsertContact({
|
|
376
412
|
displayName: "Guardian",
|
|
@@ -401,7 +437,7 @@ describe("invite-redemption-service", () => {
|
|
|
401
437
|
});
|
|
402
438
|
|
|
403
439
|
// Redeem using the guardian's Telegram identity
|
|
404
|
-
const outcome = redeemInviteByCode({
|
|
440
|
+
const outcome = await redeemInviteByCode({
|
|
405
441
|
code,
|
|
406
442
|
sourceChannel: "telegram",
|
|
407
443
|
externalUserId: "guardian-code-id",
|
|
@@ -426,7 +462,7 @@ describe("invite-redemption-service", () => {
|
|
|
426
462
|
expect(guardian!.role).toBe("guardian");
|
|
427
463
|
});
|
|
428
464
|
|
|
429
|
-
test("does not return already_member for a revoked member", () => {
|
|
465
|
+
test("does not return already_member for a revoked member", async () => {
|
|
430
466
|
const targetContactId = createTargetContact();
|
|
431
467
|
const { rawToken } = createInvite({
|
|
432
468
|
sourceChannel: "telegram",
|
|
@@ -442,7 +478,7 @@ describe("invite-redemption-service", () => {
|
|
|
442
478
|
});
|
|
443
479
|
expect(member!.channel.status).toBe("revoked");
|
|
444
480
|
|
|
445
|
-
const outcome = redeemInvite({
|
|
481
|
+
const outcome = await redeemInvite({
|
|
446
482
|
rawToken,
|
|
447
483
|
sourceChannel: "telegram",
|
|
448
484
|
externalUserId: "revoked-user",
|
|
@@ -455,7 +491,7 @@ describe("invite-redemption-service", () => {
|
|
|
455
491
|
).toBe("redeemed");
|
|
456
492
|
});
|
|
457
493
|
|
|
458
|
-
test("raw token is not present in the outcome object", () => {
|
|
494
|
+
test("raw token is not present in the outcome object", async () => {
|
|
459
495
|
const targetContactId = createTargetContact();
|
|
460
496
|
const { rawToken } = createInvite({
|
|
461
497
|
sourceChannel: "telegram",
|
|
@@ -463,7 +499,7 @@ describe("invite-redemption-service", () => {
|
|
|
463
499
|
maxUses: 1,
|
|
464
500
|
});
|
|
465
501
|
|
|
466
|
-
const outcome = redeemInvite({
|
|
502
|
+
const outcome = await redeemInvite({
|
|
467
503
|
rawToken,
|
|
468
504
|
sourceChannel: "telegram",
|
|
469
505
|
externalUserId: "user-1",
|
|
@@ -474,7 +510,7 @@ describe("invite-redemption-service", () => {
|
|
|
474
510
|
expect(serialized).not.toContain(rawToken);
|
|
475
511
|
});
|
|
476
512
|
|
|
477
|
-
test("channel enforcement blocks cross-channel redemption (voice invite via slack)", () => {
|
|
513
|
+
test("channel enforcement blocks cross-channel redemption (voice invite via slack)", async () => {
|
|
478
514
|
const targetContactId = createTargetContact();
|
|
479
515
|
const { rawToken } = createInvite({
|
|
480
516
|
sourceChannel: "phone",
|
|
@@ -482,7 +518,7 @@ describe("invite-redemption-service", () => {
|
|
|
482
518
|
maxUses: 1,
|
|
483
519
|
});
|
|
484
520
|
|
|
485
|
-
const outcome = redeemInvite({
|
|
521
|
+
const outcome = await redeemInvite({
|
|
486
522
|
rawToken,
|
|
487
523
|
sourceChannel: "slack",
|
|
488
524
|
externalUserId: "user-1",
|
|
@@ -491,7 +527,7 @@ describe("invite-redemption-service", () => {
|
|
|
491
527
|
expect(outcome).toEqual({ ok: false, reason: "channel_mismatch" });
|
|
492
528
|
});
|
|
493
529
|
|
|
494
|
-
test("returns invalid_token for an active member with a bogus token (no membership probing)", () => {
|
|
530
|
+
test("returns invalid_token for an active member with a bogus token (no membership probing)", async () => {
|
|
495
531
|
// Pre-create an active member
|
|
496
532
|
upsertContactChannel({
|
|
497
533
|
sourceChannel: "telegram",
|
|
@@ -500,7 +536,7 @@ describe("invite-redemption-service", () => {
|
|
|
500
536
|
});
|
|
501
537
|
|
|
502
538
|
// Attempt to redeem with a bogus token — must NOT leak membership status
|
|
503
|
-
const outcome = redeemInvite({
|
|
539
|
+
const outcome = await redeemInvite({
|
|
504
540
|
rawToken: "completely-bogus-token",
|
|
505
541
|
sourceChannel: "telegram",
|
|
506
542
|
externalUserId: "probed-user",
|
|
@@ -509,7 +545,7 @@ describe("invite-redemption-service", () => {
|
|
|
509
545
|
expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
|
|
510
546
|
});
|
|
511
547
|
|
|
512
|
-
test("returns expired for an active member with an expired invite token", () => {
|
|
548
|
+
test("returns expired for an active member with an expired invite token", async () => {
|
|
513
549
|
const targetContactId = createTargetContact();
|
|
514
550
|
// Create an expired invite
|
|
515
551
|
const { rawToken } = createInvite({
|
|
@@ -527,7 +563,7 @@ describe("invite-redemption-service", () => {
|
|
|
527
563
|
});
|
|
528
564
|
|
|
529
565
|
// Expired token must return expired, not already_member
|
|
530
|
-
const outcome = redeemInvite({
|
|
566
|
+
const outcome = await redeemInvite({
|
|
531
567
|
rawToken,
|
|
532
568
|
sourceChannel: "telegram",
|
|
533
569
|
externalUserId: "expired-token-user",
|
|
@@ -536,7 +572,7 @@ describe("invite-redemption-service", () => {
|
|
|
536
572
|
expect(outcome).toEqual({ ok: false, reason: "expired" });
|
|
537
573
|
});
|
|
538
574
|
|
|
539
|
-
test("returns channel_mismatch for an active member with a valid token for a different channel", () => {
|
|
575
|
+
test("returns channel_mismatch for an active member with a valid token for a different channel", async () => {
|
|
540
576
|
const targetContactId = createTargetContact();
|
|
541
577
|
// Create an invite for voice
|
|
542
578
|
const { rawToken } = createInvite({
|
|
@@ -553,7 +589,7 @@ describe("invite-redemption-service", () => {
|
|
|
553
589
|
});
|
|
554
590
|
|
|
555
591
|
// Valid token for wrong channel must return channel_mismatch, not already_member
|
|
556
|
-
const outcome = redeemInvite({
|
|
592
|
+
const outcome = await redeemInvite({
|
|
557
593
|
rawToken,
|
|
558
594
|
sourceChannel: "telegram",
|
|
559
595
|
externalUserId: "cross-channel-user",
|
|
@@ -561,4 +597,169 @@ describe("invite-redemption-service", () => {
|
|
|
561
597
|
|
|
562
598
|
expect(outcome).toEqual({ ok: false, reason: "channel_mismatch" });
|
|
563
599
|
});
|
|
600
|
+
|
|
601
|
+
// ── Gateway lifecycle pre-check + redemption mirror ────────────────────
|
|
602
|
+
|
|
603
|
+
test("rejects redemption when the gateway claim is not consumable (no assistant mutation)", async () => {
|
|
604
|
+
const targetContactId = createTargetContact();
|
|
605
|
+
const { rawToken } = createInvite({
|
|
606
|
+
sourceChannel: "telegram",
|
|
607
|
+
contactId: targetContactId,
|
|
608
|
+
maxUses: 1,
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// Gateway row exists but was NOT consumable (revoked/exhausted/raced).
|
|
612
|
+
gatewayIpc.claim = { ok: true, updated: false, mirrored: true };
|
|
613
|
+
|
|
614
|
+
const outcome = await redeemInvite({
|
|
615
|
+
rawToken,
|
|
616
|
+
sourceChannel: "telegram",
|
|
617
|
+
externalUserId: "gw-revoked-user",
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
|
|
621
|
+
|
|
622
|
+
// No member was created — the assistant DB was never mutated.
|
|
623
|
+
expect(
|
|
624
|
+
findContactChannel({
|
|
625
|
+
channelType: "telegram",
|
|
626
|
+
address: "gw-revoked-user",
|
|
627
|
+
}),
|
|
628
|
+
).toBeNull();
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
test("proceeds and mutates when the gateway claim is consumed (updated:true)", async () => {
|
|
632
|
+
const targetContactId = createTargetContact();
|
|
633
|
+
const { rawToken, invite } = createInvite({
|
|
634
|
+
sourceChannel: "telegram",
|
|
635
|
+
contactId: targetContactId,
|
|
636
|
+
maxUses: 1,
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
gatewayIpc.claim = { ok: true, updated: true, mirrored: true };
|
|
640
|
+
|
|
641
|
+
const outcome = await redeemInvite({
|
|
642
|
+
rawToken,
|
|
643
|
+
sourceChannel: "telegram",
|
|
644
|
+
externalUserId: "gw-active-user",
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
expect(outcome.ok).toBe(true);
|
|
648
|
+
|
|
649
|
+
// The claim was performed against the resolved invite id.
|
|
650
|
+
const claim = gatewayIpc.calls.find(
|
|
651
|
+
(c) => c.method === "record_invite_redemption",
|
|
652
|
+
);
|
|
653
|
+
expect(claim).toBeDefined();
|
|
654
|
+
expect(claim!.params).toMatchObject({ inviteId: invite.id });
|
|
655
|
+
|
|
656
|
+
// The assistant DB was mutated.
|
|
657
|
+
expect(
|
|
658
|
+
findContactChannel({ channelType: "telegram", address: "gw-active-user" }),
|
|
659
|
+
).not.toBeNull();
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
test("proceeds for a legacy invite the gateway has never seen (mirrored:false)", async () => {
|
|
663
|
+
const targetContactId = createTargetContact();
|
|
664
|
+
const { rawToken } = createInvite({
|
|
665
|
+
sourceChannel: "telegram",
|
|
666
|
+
contactId: targetContactId,
|
|
667
|
+
maxUses: 1,
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
gatewayIpc.claim = { ok: true, updated: false, mirrored: false };
|
|
671
|
+
|
|
672
|
+
const outcome = await redeemInvite({
|
|
673
|
+
rawToken,
|
|
674
|
+
sourceChannel: "telegram",
|
|
675
|
+
externalUserId: "legacy-user",
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
expect(outcome.ok).toBe(true);
|
|
679
|
+
expect(
|
|
680
|
+
findContactChannel({ channelType: "telegram", address: "legacy-user" }),
|
|
681
|
+
).not.toBeNull();
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
test("fails open when the gateway claim throws (assistant-side checks still apply)", async () => {
|
|
685
|
+
const targetContactId = createTargetContact();
|
|
686
|
+
const { rawToken } = createInvite({
|
|
687
|
+
sourceChannel: "telegram",
|
|
688
|
+
contactId: targetContactId,
|
|
689
|
+
maxUses: 1,
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
gatewayIpc.claimThrows = true;
|
|
693
|
+
|
|
694
|
+
const outcome = await redeemInvite({
|
|
695
|
+
rawToken,
|
|
696
|
+
sourceChannel: "telegram",
|
|
697
|
+
externalUserId: "failopen-user",
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
expect(outcome.ok).toBe(true);
|
|
701
|
+
expect(
|
|
702
|
+
findContactChannel({ channelType: "telegram", address: "failopen-user" }),
|
|
703
|
+
).not.toBeNull();
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
test("does not claim the gateway row for an already-active member", async () => {
|
|
707
|
+
const targetContactId = createTargetContact();
|
|
708
|
+
const { rawToken } = createInvite({
|
|
709
|
+
sourceChannel: "telegram",
|
|
710
|
+
contactId: targetContactId,
|
|
711
|
+
maxUses: 1,
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
// Seed an already-active member bound to the invite's target contact.
|
|
715
|
+
upsertContactChannel({
|
|
716
|
+
sourceChannel: "telegram",
|
|
717
|
+
externalUserId: "already-member-user",
|
|
718
|
+
role: "contact",
|
|
719
|
+
status: "active",
|
|
720
|
+
policy: "allow",
|
|
721
|
+
contactId: targetContactId,
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
const outcome = await redeemInvite({
|
|
725
|
+
rawToken,
|
|
726
|
+
sourceChannel: "telegram",
|
|
727
|
+
externalUserId: "already-member-user",
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
expect(outcome.ok).toBe(true);
|
|
731
|
+
expect((outcome as { type: string }).type).toBe("already_member");
|
|
732
|
+
|
|
733
|
+
// No gateway claim was made — no use must be consumed for a non-redemption.
|
|
734
|
+
expect(
|
|
735
|
+
gatewayIpc.calls.some((c) => c.method === "record_invite_redemption"),
|
|
736
|
+
).toBe(false);
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
test("rejects 6-digit code redemption when the gateway claim is not consumable", async () => {
|
|
740
|
+
const targetContactId = createTargetContact();
|
|
741
|
+
const code = "654321";
|
|
742
|
+
createInvite({
|
|
743
|
+
sourceChannel: "telegram",
|
|
744
|
+
contactId: targetContactId,
|
|
745
|
+
maxUses: 1,
|
|
746
|
+
inviteCodeHash: hashVoiceCode(code),
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
gatewayIpc.claim = { ok: true, updated: false, mirrored: true };
|
|
750
|
+
|
|
751
|
+
const outcome = await redeemInviteByCode({
|
|
752
|
+
code,
|
|
753
|
+
sourceChannel: "telegram",
|
|
754
|
+
externalUserId: "gw-revoked-code-user",
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
|
|
758
|
+
expect(
|
|
759
|
+
findContactChannel({
|
|
760
|
+
channelType: "telegram",
|
|
761
|
+
address: "gw-revoked-code-user",
|
|
762
|
+
}),
|
|
763
|
+
).toBeNull();
|
|
764
|
+
});
|
|
564
765
|
});
|