@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
|
@@ -63,6 +63,26 @@ mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
|
63
63
|
},
|
|
64
64
|
}));
|
|
65
65
|
|
|
66
|
+
// Gateway relay mock — the revoke path relays the ACL downgrade over IPC and
|
|
67
|
+
// validates the response; return a well-formed mark_channel_revoked result.
|
|
68
|
+
mock.module("../ipc/gateway-client.js", () => ({
|
|
69
|
+
ipcCallPersistent: async (
|
|
70
|
+
_method: string,
|
|
71
|
+
params?: Record<string, unknown>,
|
|
72
|
+
) => ({
|
|
73
|
+
ok: true,
|
|
74
|
+
didWrite: true,
|
|
75
|
+
channel: {
|
|
76
|
+
id: (params?.contactChannelId as string) ?? "ch1",
|
|
77
|
+
contactId: "c1",
|
|
78
|
+
type: "phone",
|
|
79
|
+
address: "addr",
|
|
80
|
+
status: "revoked",
|
|
81
|
+
revokedReason: (params?.reason as string) ?? null,
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
}));
|
|
85
|
+
|
|
66
86
|
import { handleChannelVerificationSession } from "../daemon/handlers/config-channels.js";
|
|
67
87
|
import type {
|
|
68
88
|
ChannelVerificationSessionRequest,
|
|
@@ -84,12 +104,6 @@ import {
|
|
|
84
104
|
import { getDb } from "../memory/db-connection.js";
|
|
85
105
|
import { initializeDb } from "../memory/db-init.js";
|
|
86
106
|
import { upsertBinding as upsertExternalBinding } from "../memory/external-conversation-store.js";
|
|
87
|
-
import {
|
|
88
|
-
createApprovalRequest,
|
|
89
|
-
getPendingApprovalByGuardianChat,
|
|
90
|
-
getPendingApprovalForRequest,
|
|
91
|
-
updateApprovalDecision,
|
|
92
|
-
} from "../memory/guardian-approvals.js";
|
|
93
107
|
import {
|
|
94
108
|
getRateLimit,
|
|
95
109
|
recordInvalidAttempt,
|
|
@@ -133,7 +147,6 @@ afterAll(() => {
|
|
|
133
147
|
function resetTables(): void {
|
|
134
148
|
const db = getDb();
|
|
135
149
|
db.run("DELETE FROM channel_verification_sessions");
|
|
136
|
-
db.run("DELETE FROM channel_guardian_approval_requests");
|
|
137
150
|
db.run("DELETE FROM channel_guardian_rate_limits");
|
|
138
151
|
db.run("DELETE FROM contact_channels");
|
|
139
152
|
db.run("DELETE FROM contacts");
|
|
@@ -564,251 +577,6 @@ describe("guardian identity check", () => {
|
|
|
564
577
|
// 5. Approval Request CRUD (Store)
|
|
565
578
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
566
579
|
|
|
567
|
-
describe("guardian approval request CRUD", () => {
|
|
568
|
-
beforeEach(() => {
|
|
569
|
-
resetTables();
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
test("createApprovalRequest creates a pending request", () => {
|
|
573
|
-
const request = createApprovalRequest({
|
|
574
|
-
runId: "run-1",
|
|
575
|
-
requestId: "req-1",
|
|
576
|
-
conversationId: "conv-1",
|
|
577
|
-
channel: "telegram",
|
|
578
|
-
requesterExternalUserId: "user-99",
|
|
579
|
-
requesterChatId: "chat-99",
|
|
580
|
-
guardianExternalUserId: "user-42",
|
|
581
|
-
guardianChatId: "chat-42",
|
|
582
|
-
toolName: "shell",
|
|
583
|
-
riskLevel: "high",
|
|
584
|
-
reason: "Executing rm command",
|
|
585
|
-
expiresAt: Date.now() + 300_000,
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
expect(request.id).toBeDefined();
|
|
589
|
-
expect(request.runId).toBe("run-1");
|
|
590
|
-
expect(request.requestId).toBe("req-1");
|
|
591
|
-
expect(request.status).toBe("pending");
|
|
592
|
-
expect(request.toolName).toBe("shell");
|
|
593
|
-
expect(request.riskLevel).toBe("high");
|
|
594
|
-
expect(request.reason).toBe("Executing rm command");
|
|
595
|
-
expect(request.decidedByExternalUserId).toBeNull();
|
|
596
|
-
});
|
|
597
|
-
|
|
598
|
-
test("getPendingApprovalForRequest returns the pending request", () => {
|
|
599
|
-
createApprovalRequest({
|
|
600
|
-
runId: "run-1",
|
|
601
|
-
requestId: "req-1",
|
|
602
|
-
conversationId: "conv-1",
|
|
603
|
-
channel: "telegram",
|
|
604
|
-
requesterExternalUserId: "user-99",
|
|
605
|
-
requesterChatId: "chat-99",
|
|
606
|
-
guardianExternalUserId: "user-42",
|
|
607
|
-
guardianChatId: "chat-42",
|
|
608
|
-
toolName: "shell",
|
|
609
|
-
expiresAt: Date.now() + 300_000,
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
const found = getPendingApprovalForRequest("req-1");
|
|
613
|
-
expect(found).not.toBeNull();
|
|
614
|
-
expect(found!.requestId).toBe("req-1");
|
|
615
|
-
expect(found!.status).toBe("pending");
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
test("getPendingApprovalForRequest returns null when no pending request exists", () => {
|
|
619
|
-
const found = getPendingApprovalForRequest("req-nonexistent");
|
|
620
|
-
expect(found).toBeNull();
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
test("getPendingApprovalByGuardianChat returns pending request for guardian chat", () => {
|
|
624
|
-
createApprovalRequest({
|
|
625
|
-
runId: "run-1",
|
|
626
|
-
requestId: "req-1",
|
|
627
|
-
conversationId: "conv-1",
|
|
628
|
-
channel: "telegram",
|
|
629
|
-
requesterExternalUserId: "user-99",
|
|
630
|
-
requesterChatId: "chat-99",
|
|
631
|
-
guardianExternalUserId: "user-42",
|
|
632
|
-
guardianChatId: "chat-42",
|
|
633
|
-
toolName: "shell",
|
|
634
|
-
expiresAt: Date.now() + 300_000,
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
const found = getPendingApprovalByGuardianChat("telegram", "chat-42");
|
|
638
|
-
expect(found).not.toBeNull();
|
|
639
|
-
expect(found!.guardianChatId).toBe("chat-42");
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
test("getPendingApprovalByGuardianChat returns null for wrong channel", () => {
|
|
643
|
-
createApprovalRequest({
|
|
644
|
-
runId: "run-1",
|
|
645
|
-
requestId: "req-1",
|
|
646
|
-
conversationId: "conv-1",
|
|
647
|
-
channel: "telegram",
|
|
648
|
-
requesterExternalUserId: "user-99",
|
|
649
|
-
requesterChatId: "chat-99",
|
|
650
|
-
guardianExternalUserId: "user-42",
|
|
651
|
-
guardianChatId: "chat-42",
|
|
652
|
-
toolName: "shell",
|
|
653
|
-
expiresAt: Date.now() + 300_000,
|
|
654
|
-
});
|
|
655
|
-
|
|
656
|
-
const found = getPendingApprovalByGuardianChat("slack", "chat-42");
|
|
657
|
-
expect(found).toBeNull();
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
test("updateApprovalDecision updates status to approved", () => {
|
|
661
|
-
const request = createApprovalRequest({
|
|
662
|
-
runId: "run-1",
|
|
663
|
-
requestId: "req-1",
|
|
664
|
-
conversationId: "conv-1",
|
|
665
|
-
channel: "telegram",
|
|
666
|
-
requesterExternalUserId: "user-99",
|
|
667
|
-
requesterChatId: "chat-99",
|
|
668
|
-
guardianExternalUserId: "user-42",
|
|
669
|
-
guardianChatId: "chat-42",
|
|
670
|
-
toolName: "shell",
|
|
671
|
-
expiresAt: Date.now() + 300_000,
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
updateApprovalDecision(request.id, {
|
|
675
|
-
status: "approved",
|
|
676
|
-
decidedByExternalUserId: "user-42",
|
|
677
|
-
});
|
|
678
|
-
|
|
679
|
-
// After approval, getPendingApprovalForRequest should return null
|
|
680
|
-
const found = getPendingApprovalForRequest("req-1");
|
|
681
|
-
expect(found).toBeNull();
|
|
682
|
-
});
|
|
683
|
-
|
|
684
|
-
test("updateApprovalDecision updates status to denied", () => {
|
|
685
|
-
const request = createApprovalRequest({
|
|
686
|
-
runId: "run-1",
|
|
687
|
-
requestId: "req-1",
|
|
688
|
-
conversationId: "conv-1",
|
|
689
|
-
channel: "telegram",
|
|
690
|
-
requesterExternalUserId: "user-99",
|
|
691
|
-
requesterChatId: "chat-99",
|
|
692
|
-
guardianExternalUserId: "user-42",
|
|
693
|
-
guardianChatId: "chat-42",
|
|
694
|
-
toolName: "shell",
|
|
695
|
-
expiresAt: Date.now() + 300_000,
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
updateApprovalDecision(request.id, {
|
|
699
|
-
status: "denied",
|
|
700
|
-
decidedByExternalUserId: "user-42",
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
const found = getPendingApprovalForRequest("req-1");
|
|
704
|
-
expect(found).toBeNull();
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
test("multiple approval requests for different runs are independent", () => {
|
|
708
|
-
createApprovalRequest({
|
|
709
|
-
runId: "run-1",
|
|
710
|
-
requestId: "req-1",
|
|
711
|
-
conversationId: "conv-1",
|
|
712
|
-
channel: "telegram",
|
|
713
|
-
requesterExternalUserId: "user-99",
|
|
714
|
-
requesterChatId: "chat-99",
|
|
715
|
-
guardianExternalUserId: "user-42",
|
|
716
|
-
guardianChatId: "chat-42",
|
|
717
|
-
toolName: "shell",
|
|
718
|
-
expiresAt: Date.now() + 300_000,
|
|
719
|
-
});
|
|
720
|
-
|
|
721
|
-
createApprovalRequest({
|
|
722
|
-
runId: "run-2",
|
|
723
|
-
requestId: "req-2",
|
|
724
|
-
conversationId: "conv-2",
|
|
725
|
-
channel: "telegram",
|
|
726
|
-
requesterExternalUserId: "user-88",
|
|
727
|
-
requesterChatId: "chat-88",
|
|
728
|
-
guardianExternalUserId: "user-42",
|
|
729
|
-
guardianChatId: "chat-42",
|
|
730
|
-
toolName: "browser",
|
|
731
|
-
expiresAt: Date.now() + 300_000,
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
const found1 = getPendingApprovalForRequest("req-1");
|
|
735
|
-
const found2 = getPendingApprovalForRequest("req-2");
|
|
736
|
-
expect(found1).not.toBeNull();
|
|
737
|
-
expect(found2).not.toBeNull();
|
|
738
|
-
expect(found1!.toolName).toBe("shell");
|
|
739
|
-
expect(found2!.toolName).toBe("browser");
|
|
740
|
-
});
|
|
741
|
-
|
|
742
|
-
test("createApprovalRequest works for voice channel", () => {
|
|
743
|
-
const request = createApprovalRequest({
|
|
744
|
-
runId: "run-voice-1",
|
|
745
|
-
requestId: "req-voice-1",
|
|
746
|
-
conversationId: "conv-voice-1",
|
|
747
|
-
channel: "phone",
|
|
748
|
-
requesterExternalUserId: "phone-user-99",
|
|
749
|
-
requesterChatId: "voice-chat-99",
|
|
750
|
-
guardianExternalUserId: "phone-user-42",
|
|
751
|
-
guardianChatId: "voice-chat-42",
|
|
752
|
-
toolName: "shell",
|
|
753
|
-
expiresAt: Date.now() + 300_000,
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
expect(request.id).toBeDefined();
|
|
757
|
-
expect(request.runId).toBe("run-voice-1");
|
|
758
|
-
expect(request.requestId).toBe("req-voice-1");
|
|
759
|
-
expect(request.channel).toBe("phone");
|
|
760
|
-
expect(request.status).toBe("pending");
|
|
761
|
-
|
|
762
|
-
const found = getPendingApprovalForRequest("req-voice-1");
|
|
763
|
-
expect(found).not.toBeNull();
|
|
764
|
-
expect(found!.channel).toBe("phone");
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
test("getPendingApprovalByGuardianChat works for voice channel", () => {
|
|
768
|
-
createApprovalRequest({
|
|
769
|
-
runId: "run-voice-2",
|
|
770
|
-
requestId: "req-voice-2",
|
|
771
|
-
conversationId: "conv-voice-2",
|
|
772
|
-
channel: "phone",
|
|
773
|
-
requesterExternalUserId: "phone-user-99",
|
|
774
|
-
requesterChatId: "voice-chat-99",
|
|
775
|
-
guardianExternalUserId: "phone-user-42",
|
|
776
|
-
guardianChatId: "voice-chat-42",
|
|
777
|
-
toolName: "shell",
|
|
778
|
-
expiresAt: Date.now() + 300_000,
|
|
779
|
-
});
|
|
780
|
-
|
|
781
|
-
const found = getPendingApprovalByGuardianChat("phone", "voice-chat-42");
|
|
782
|
-
expect(found).not.toBeNull();
|
|
783
|
-
expect(found!.channel).toBe("phone");
|
|
784
|
-
|
|
785
|
-
// Should not find it under a different channel
|
|
786
|
-
const notFound = getPendingApprovalByGuardianChat(
|
|
787
|
-
"telegram",
|
|
788
|
-
"voice-chat-42",
|
|
789
|
-
);
|
|
790
|
-
expect(notFound).toBeNull();
|
|
791
|
-
});
|
|
792
|
-
|
|
793
|
-
test("createApprovalRequest with optional fields omitted defaults to null", () => {
|
|
794
|
-
const request = createApprovalRequest({
|
|
795
|
-
runId: "run-1",
|
|
796
|
-
requestId: "req-1",
|
|
797
|
-
conversationId: "conv-1",
|
|
798
|
-
channel: "telegram",
|
|
799
|
-
requesterExternalUserId: "user-99",
|
|
800
|
-
requesterChatId: "chat-99",
|
|
801
|
-
guardianExternalUserId: "user-42",
|
|
802
|
-
guardianChatId: "chat-42",
|
|
803
|
-
toolName: "shell",
|
|
804
|
-
expiresAt: Date.now() + 300_000,
|
|
805
|
-
});
|
|
806
|
-
|
|
807
|
-
expect(request.riskLevel).toBeNull();
|
|
808
|
-
expect(request.reason).toBeNull();
|
|
809
|
-
});
|
|
810
|
-
});
|
|
811
|
-
|
|
812
580
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
813
581
|
// 6. Verification Rate Limiting (Store)
|
|
814
582
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -1204,64 +972,6 @@ describe("channel-scoped guardian resolution", () => {
|
|
|
1204
972
|
// 9. Assistant-scoped approval request lookups
|
|
1205
973
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1206
974
|
|
|
1207
|
-
describe("assistant-scoped approval request lookups", () => {
|
|
1208
|
-
beforeEach(() => {
|
|
1209
|
-
resetTables();
|
|
1210
|
-
});
|
|
1211
|
-
|
|
1212
|
-
test("createApprovalRequest no longer exposes assistantId on the returned interface", () => {
|
|
1213
|
-
const req = createApprovalRequest({
|
|
1214
|
-
runId: "run-1",
|
|
1215
|
-
requestId: "req-1",
|
|
1216
|
-
conversationId: "conv-1",
|
|
1217
|
-
channel: "telegram",
|
|
1218
|
-
requesterExternalUserId: "user-99",
|
|
1219
|
-
requesterChatId: "chat-99",
|
|
1220
|
-
guardianExternalUserId: "user-42",
|
|
1221
|
-
guardianChatId: "chat-42",
|
|
1222
|
-
toolName: "shell",
|
|
1223
|
-
expiresAt: Date.now() + 300_000,
|
|
1224
|
-
});
|
|
1225
|
-
// assistantId is no longer on the public interface
|
|
1226
|
-
expect(req.id).toBeDefined();
|
|
1227
|
-
expect(req.toolName).toBe("shell");
|
|
1228
|
-
});
|
|
1229
|
-
|
|
1230
|
-
test("approval requests from different conversations are independent", () => {
|
|
1231
|
-
createApprovalRequest({
|
|
1232
|
-
runId: "run-A",
|
|
1233
|
-
requestId: "req-A",
|
|
1234
|
-
conversationId: "conv-A",
|
|
1235
|
-
channel: "telegram",
|
|
1236
|
-
requesterExternalUserId: "user-99",
|
|
1237
|
-
requesterChatId: "chat-99",
|
|
1238
|
-
guardianExternalUserId: "user-42",
|
|
1239
|
-
guardianChatId: "chat-42",
|
|
1240
|
-
toolName: "shell",
|
|
1241
|
-
expiresAt: Date.now() + 300_000,
|
|
1242
|
-
});
|
|
1243
|
-
createApprovalRequest({
|
|
1244
|
-
runId: "run-B",
|
|
1245
|
-
requestId: "req-B",
|
|
1246
|
-
conversationId: "conv-B",
|
|
1247
|
-
channel: "telegram",
|
|
1248
|
-
requesterExternalUserId: "user-88",
|
|
1249
|
-
requesterChatId: "chat-88",
|
|
1250
|
-
guardianExternalUserId: "user-42",
|
|
1251
|
-
guardianChatId: "chat-42",
|
|
1252
|
-
toolName: "browser",
|
|
1253
|
-
expiresAt: Date.now() + 300_000,
|
|
1254
|
-
});
|
|
1255
|
-
|
|
1256
|
-
const foundA = getPendingApprovalForRequest("req-A");
|
|
1257
|
-
const foundB = getPendingApprovalForRequest("req-B");
|
|
1258
|
-
expect(foundA).not.toBeNull();
|
|
1259
|
-
expect(foundB).not.toBeNull();
|
|
1260
|
-
expect(foundA!.toolName).toBe("shell");
|
|
1261
|
-
expect(foundB!.toolName).toBe("browser");
|
|
1262
|
-
});
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
975
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1266
976
|
// 10. HTTP handler — channel-aware guardian status response
|
|
1267
977
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -2588,24 +2298,20 @@ describe("outbound voice verification", () => {
|
|
|
2588
2298
|
test("resend_outbound before cooldown is rejected", async () => {
|
|
2589
2299
|
// Start an outbound session first
|
|
2590
2300
|
broadcastedMessages.length = 0;
|
|
2591
|
-
await handleChannelVerificationSession(
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
},
|
|
2598
|
-
);
|
|
2301
|
+
await handleChannelVerificationSession({
|
|
2302
|
+
type: "channel_verification_session",
|
|
2303
|
+
action: "create_session",
|
|
2304
|
+
channel: "phone",
|
|
2305
|
+
destination: "+15551234567",
|
|
2306
|
+
});
|
|
2599
2307
|
|
|
2600
2308
|
// Immediately try to resend (before cooldown)
|
|
2601
2309
|
const { lastResponse } = createResponseReader();
|
|
2602
|
-
await handleChannelVerificationSession(
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
},
|
|
2608
|
-
);
|
|
2310
|
+
await handleChannelVerificationSession({
|
|
2311
|
+
type: "channel_verification_session",
|
|
2312
|
+
action: "resend_session",
|
|
2313
|
+
channel: "phone",
|
|
2314
|
+
});
|
|
2609
2315
|
|
|
2610
2316
|
const resp = lastResponse();
|
|
2611
2317
|
expect(resp).not.toBeNull();
|
|
@@ -2616,14 +2322,12 @@ describe("outbound voice verification", () => {
|
|
|
2616
2322
|
test("resend_outbound after cooldown succeeds and increments sendCount", async () => {
|
|
2617
2323
|
// Start an outbound session
|
|
2618
2324
|
const { lastResponse: startResp } = createResponseReader();
|
|
2619
|
-
await handleChannelVerificationSession(
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
},
|
|
2626
|
-
);
|
|
2325
|
+
await handleChannelVerificationSession({
|
|
2326
|
+
type: "channel_verification_session",
|
|
2327
|
+
action: "create_session",
|
|
2328
|
+
channel: "phone",
|
|
2329
|
+
destination: "+15551234567",
|
|
2330
|
+
});
|
|
2627
2331
|
|
|
2628
2332
|
const startResponse = startResp();
|
|
2629
2333
|
expect(startResponse!.success).toBe(true);
|
|
@@ -2640,13 +2344,11 @@ describe("outbound voice verification", () => {
|
|
|
2640
2344
|
|
|
2641
2345
|
// Now resend should succeed
|
|
2642
2346
|
const { lastResponse } = createResponseReader();
|
|
2643
|
-
await handleChannelVerificationSession(
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
},
|
|
2649
|
-
);
|
|
2347
|
+
await handleChannelVerificationSession({
|
|
2348
|
+
type: "channel_verification_session",
|
|
2349
|
+
action: "resend_session",
|
|
2350
|
+
channel: "phone",
|
|
2351
|
+
});
|
|
2650
2352
|
|
|
2651
2353
|
const resp = lastResponse();
|
|
2652
2354
|
expect(resp).not.toBeNull();
|
|
@@ -2658,14 +2360,12 @@ describe("outbound voice verification", () => {
|
|
|
2658
2360
|
test("resend_outbound exceeding max sends is rejected", async () => {
|
|
2659
2361
|
// Start an outbound session
|
|
2660
2362
|
broadcastedMessages.length = 0;
|
|
2661
|
-
await handleChannelVerificationSession(
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
},
|
|
2668
|
-
);
|
|
2363
|
+
await handleChannelVerificationSession({
|
|
2364
|
+
type: "channel_verification_session",
|
|
2365
|
+
action: "create_session",
|
|
2366
|
+
channel: "phone",
|
|
2367
|
+
destination: "+15551234567",
|
|
2368
|
+
});
|
|
2669
2369
|
|
|
2670
2370
|
// Set the send count to MAX_SENDS_PER_SESSION and nextResendAt to the past
|
|
2671
2371
|
const session = serviceFindActiveSession("phone");
|
|
@@ -2679,13 +2379,11 @@ describe("outbound voice verification", () => {
|
|
|
2679
2379
|
|
|
2680
2380
|
// Resend should be rejected due to max sends
|
|
2681
2381
|
const { lastResponse } = createResponseReader();
|
|
2682
|
-
await handleChannelVerificationSession(
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
},
|
|
2688
|
-
);
|
|
2382
|
+
await handleChannelVerificationSession({
|
|
2383
|
+
type: "channel_verification_session",
|
|
2384
|
+
action: "resend_session",
|
|
2385
|
+
channel: "phone",
|
|
2386
|
+
});
|
|
2689
2387
|
|
|
2690
2388
|
const resp = lastResponse();
|
|
2691
2389
|
expect(resp).not.toBeNull();
|
|
@@ -2696,14 +2394,12 @@ describe("outbound voice verification", () => {
|
|
|
2696
2394
|
test("cancel_outbound revokes active session", async () => {
|
|
2697
2395
|
// Start an outbound session
|
|
2698
2396
|
broadcastedMessages.length = 0;
|
|
2699
|
-
await handleChannelVerificationSession(
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
},
|
|
2706
|
-
);
|
|
2397
|
+
await handleChannelVerificationSession({
|
|
2398
|
+
type: "channel_verification_session",
|
|
2399
|
+
action: "create_session",
|
|
2400
|
+
channel: "phone",
|
|
2401
|
+
destination: "+15551234567",
|
|
2402
|
+
});
|
|
2707
2403
|
|
|
2708
2404
|
// Verify session exists
|
|
2709
2405
|
const sessionBefore = serviceFindActiveSession("phone");
|
|
@@ -2711,13 +2407,11 @@ describe("outbound voice verification", () => {
|
|
|
2711
2407
|
|
|
2712
2408
|
// Cancel it
|
|
2713
2409
|
const { lastResponse } = createResponseReader();
|
|
2714
|
-
await handleChannelVerificationSession(
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
},
|
|
2720
|
-
);
|
|
2410
|
+
await handleChannelVerificationSession({
|
|
2411
|
+
type: "channel_verification_session",
|
|
2412
|
+
action: "cancel_session",
|
|
2413
|
+
channel: "phone",
|
|
2414
|
+
});
|
|
2721
2415
|
|
|
2722
2416
|
const resp = lastResponse();
|
|
2723
2417
|
expect(resp).not.toBeNull();
|
|
@@ -2780,14 +2474,12 @@ describe("outbound voice verification", () => {
|
|
|
2780
2474
|
|
|
2781
2475
|
test("start_outbound succeeds for email channel", async () => {
|
|
2782
2476
|
const { lastResponse } = createResponseReader();
|
|
2783
|
-
await handleChannelVerificationSession(
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
},
|
|
2790
|
-
);
|
|
2477
|
+
await handleChannelVerificationSession({
|
|
2478
|
+
type: "channel_verification_session",
|
|
2479
|
+
action: "create_session",
|
|
2480
|
+
channel: "email",
|
|
2481
|
+
destination: "user@example.com",
|
|
2482
|
+
});
|
|
2791
2483
|
|
|
2792
2484
|
const resp = lastResponse();
|
|
2793
2485
|
expect(resp).not.toBeNull();
|
|
@@ -2797,14 +2489,12 @@ describe("outbound voice verification", () => {
|
|
|
2797
2489
|
|
|
2798
2490
|
test("create_session without destination falls through to inbound challenge", async () => {
|
|
2799
2491
|
const { lastResponse } = createResponseReader();
|
|
2800
|
-
await handleChannelVerificationSession(
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
},
|
|
2807
|
-
);
|
|
2492
|
+
await handleChannelVerificationSession({
|
|
2493
|
+
type: "channel_verification_session",
|
|
2494
|
+
action: "create_session",
|
|
2495
|
+
channel: "phone",
|
|
2496
|
+
// no destination — unified create_session creates an inbound challenge
|
|
2497
|
+
});
|
|
2808
2498
|
|
|
2809
2499
|
const resp = lastResponse();
|
|
2810
2500
|
expect(resp).not.toBeNull();
|
|
@@ -2814,14 +2504,12 @@ describe("outbound voice verification", () => {
|
|
|
2814
2504
|
|
|
2815
2505
|
test("start_outbound rejects unparseable phone number", async () => {
|
|
2816
2506
|
const { lastResponse } = createResponseReader();
|
|
2817
|
-
await handleChannelVerificationSession(
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
},
|
|
2824
|
-
);
|
|
2507
|
+
await handleChannelVerificationSession({
|
|
2508
|
+
type: "channel_verification_session",
|
|
2509
|
+
action: "create_session",
|
|
2510
|
+
channel: "phone",
|
|
2511
|
+
destination: "not-a-phone",
|
|
2512
|
+
});
|
|
2825
2513
|
|
|
2826
2514
|
const resp = lastResponse();
|
|
2827
2515
|
expect(resp).not.toBeNull();
|
|
@@ -2831,14 +2519,12 @@ describe("outbound voice verification", () => {
|
|
|
2831
2519
|
|
|
2832
2520
|
test("start_outbound normalizes formatted phone number for voice", async () => {
|
|
2833
2521
|
const { lastResponse } = createResponseReader();
|
|
2834
|
-
await handleChannelVerificationSession(
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
},
|
|
2841
|
-
);
|
|
2522
|
+
await handleChannelVerificationSession({
|
|
2523
|
+
type: "channel_verification_session",
|
|
2524
|
+
action: "create_session",
|
|
2525
|
+
channel: "phone",
|
|
2526
|
+
destination: "(555) 123-4567",
|
|
2527
|
+
});
|
|
2842
2528
|
|
|
2843
2529
|
const resp = lastResponse();
|
|
2844
2530
|
expect(resp).not.toBeNull();
|
|
@@ -2863,13 +2549,11 @@ describe("outbound voice verification", () => {
|
|
|
2863
2549
|
|
|
2864
2550
|
test("cancel_session succeeds even when no active session (idempotent)", async () => {
|
|
2865
2551
|
const { lastResponse } = createResponseReader();
|
|
2866
|
-
await handleChannelVerificationSession(
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
},
|
|
2872
|
-
);
|
|
2552
|
+
await handleChannelVerificationSession({
|
|
2553
|
+
type: "channel_verification_session",
|
|
2554
|
+
action: "cancel_session",
|
|
2555
|
+
channel: "phone",
|
|
2556
|
+
});
|
|
2873
2557
|
|
|
2874
2558
|
const resp = lastResponse();
|
|
2875
2559
|
expect(resp).not.toBeNull();
|
|
@@ -2888,14 +2572,12 @@ describe("outbound Telegram verification", () => {
|
|
|
2888
2572
|
|
|
2889
2573
|
test("start_outbound for telegram with handle returns deep link URL, no outbound message", async () => {
|
|
2890
2574
|
const { lastResponse } = createResponseReader();
|
|
2891
|
-
await handleChannelVerificationSession(
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
},
|
|
2898
|
-
);
|
|
2575
|
+
await handleChannelVerificationSession({
|
|
2576
|
+
type: "channel_verification_session",
|
|
2577
|
+
action: "create_session",
|
|
2578
|
+
channel: "telegram",
|
|
2579
|
+
destination: "@someuser",
|
|
2580
|
+
});
|
|
2899
2581
|
|
|
2900
2582
|
const resp = lastResponse();
|
|
2901
2583
|
expect(resp).not.toBeNull();
|
|
@@ -2921,14 +2603,12 @@ describe("outbound Telegram verification", () => {
|
|
|
2921
2603
|
|
|
2922
2604
|
test("start_outbound for telegram with handle (no @ prefix) returns deep link", async () => {
|
|
2923
2605
|
const { lastResponse } = createResponseReader();
|
|
2924
|
-
await handleChannelVerificationSession(
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
},
|
|
2931
|
-
);
|
|
2606
|
+
await handleChannelVerificationSession({
|
|
2607
|
+
type: "channel_verification_session",
|
|
2608
|
+
action: "create_session",
|
|
2609
|
+
channel: "telegram",
|
|
2610
|
+
destination: "someuser",
|
|
2611
|
+
});
|
|
2932
2612
|
|
|
2933
2613
|
const resp = lastResponse();
|
|
2934
2614
|
expect(resp).not.toBeNull();
|
|
@@ -2941,14 +2621,12 @@ describe("outbound Telegram verification", () => {
|
|
|
2941
2621
|
|
|
2942
2622
|
test("start_outbound for telegram with known chat ID sends message, no deep link", async () => {
|
|
2943
2623
|
const { lastResponse } = createResponseReader();
|
|
2944
|
-
await handleChannelVerificationSession(
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
},
|
|
2951
|
-
);
|
|
2624
|
+
await handleChannelVerificationSession({
|
|
2625
|
+
type: "channel_verification_session",
|
|
2626
|
+
action: "create_session",
|
|
2627
|
+
channel: "telegram",
|
|
2628
|
+
destination: "123456789",
|
|
2629
|
+
});
|
|
2952
2630
|
|
|
2953
2631
|
const resp = lastResponse();
|
|
2954
2632
|
expect(resp).not.toBeNull();
|
|
@@ -2980,14 +2658,12 @@ describe("outbound Telegram verification", () => {
|
|
|
2980
2658
|
mockBotUsername = undefined;
|
|
2981
2659
|
|
|
2982
2660
|
const { lastResponse } = createResponseReader();
|
|
2983
|
-
await handleChannelVerificationSession(
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
},
|
|
2990
|
-
);
|
|
2661
|
+
await handleChannelVerificationSession({
|
|
2662
|
+
type: "channel_verification_session",
|
|
2663
|
+
action: "create_session",
|
|
2664
|
+
channel: "telegram",
|
|
2665
|
+
destination: "@someuser",
|
|
2666
|
+
});
|
|
2991
2667
|
|
|
2992
2668
|
const resp = lastResponse();
|
|
2993
2669
|
expect(resp).not.toBeNull();
|
|
@@ -3004,15 +2680,13 @@ describe("outbound Telegram verification", () => {
|
|
|
3004
2680
|
});
|
|
3005
2681
|
|
|
3006
2682
|
const { lastResponse } = createResponseReader();
|
|
3007
|
-
await handleChannelVerificationSession(
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
},
|
|
3015
|
-
);
|
|
2683
|
+
await handleChannelVerificationSession({
|
|
2684
|
+
type: "channel_verification_session",
|
|
2685
|
+
action: "create_session",
|
|
2686
|
+
channel: "telegram",
|
|
2687
|
+
destination: "@newuser",
|
|
2688
|
+
rebind: false,
|
|
2689
|
+
});
|
|
3016
2690
|
|
|
3017
2691
|
const resp = lastResponse();
|
|
3018
2692
|
expect(resp).not.toBeNull();
|
|
@@ -3166,14 +2840,12 @@ describe("outbound Telegram verification", () => {
|
|
|
3166
2840
|
test("resend_outbound for telegram works with known chat ID", async () => {
|
|
3167
2841
|
// Start an outbound session with a known chat ID
|
|
3168
2842
|
broadcastedMessages.length = 0;
|
|
3169
|
-
await handleChannelVerificationSession(
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
},
|
|
3176
|
-
);
|
|
2843
|
+
await handleChannelVerificationSession({
|
|
2844
|
+
type: "channel_verification_session",
|
|
2845
|
+
action: "create_session",
|
|
2846
|
+
channel: "telegram",
|
|
2847
|
+
destination: "123456789",
|
|
2848
|
+
});
|
|
3177
2849
|
|
|
3178
2850
|
// Fast-forward the cooldown
|
|
3179
2851
|
const session = serviceFindActiveSession("telegram");
|
|
@@ -3186,13 +2858,11 @@ describe("outbound Telegram verification", () => {
|
|
|
3186
2858
|
);
|
|
3187
2859
|
|
|
3188
2860
|
const { lastResponse } = createResponseReader();
|
|
3189
|
-
await handleChannelVerificationSession(
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
},
|
|
3195
|
-
);
|
|
2861
|
+
await handleChannelVerificationSession({
|
|
2862
|
+
type: "channel_verification_session",
|
|
2863
|
+
action: "resend_session",
|
|
2864
|
+
channel: "telegram",
|
|
2865
|
+
});
|
|
3196
2866
|
|
|
3197
2867
|
const resp = lastResponse();
|
|
3198
2868
|
expect(resp).not.toBeNull();
|
|
@@ -3208,23 +2878,19 @@ describe("outbound Telegram verification", () => {
|
|
|
3208
2878
|
test("resend_outbound for pending_bootstrap session is rejected", async () => {
|
|
3209
2879
|
// Start an outbound session with a handle (pending_bootstrap)
|
|
3210
2880
|
broadcastedMessages.length = 0;
|
|
3211
|
-
await handleChannelVerificationSession(
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
},
|
|
3218
|
-
);
|
|
2881
|
+
await handleChannelVerificationSession({
|
|
2882
|
+
type: "channel_verification_session",
|
|
2883
|
+
action: "create_session",
|
|
2884
|
+
channel: "telegram",
|
|
2885
|
+
destination: "@someuser",
|
|
2886
|
+
});
|
|
3219
2887
|
|
|
3220
2888
|
const { lastResponse } = createResponseReader();
|
|
3221
|
-
await handleChannelVerificationSession(
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
},
|
|
3227
|
-
);
|
|
2889
|
+
await handleChannelVerificationSession({
|
|
2890
|
+
type: "channel_verification_session",
|
|
2891
|
+
action: "resend_session",
|
|
2892
|
+
channel: "telegram",
|
|
2893
|
+
});
|
|
3228
2894
|
|
|
3229
2895
|
const resp = lastResponse();
|
|
3230
2896
|
expect(resp).not.toBeNull();
|
|
@@ -3235,26 +2901,22 @@ describe("outbound Telegram verification", () => {
|
|
|
3235
2901
|
test("cancel_outbound for telegram revokes session", async () => {
|
|
3236
2902
|
// Start an outbound session
|
|
3237
2903
|
broadcastedMessages.length = 0;
|
|
3238
|
-
await handleChannelVerificationSession(
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
},
|
|
3245
|
-
);
|
|
2904
|
+
await handleChannelVerificationSession({
|
|
2905
|
+
type: "channel_verification_session",
|
|
2906
|
+
action: "create_session",
|
|
2907
|
+
channel: "telegram",
|
|
2908
|
+
destination: "123456789",
|
|
2909
|
+
});
|
|
3246
2910
|
|
|
3247
2911
|
const session = serviceFindActiveSession("telegram");
|
|
3248
2912
|
expect(session).not.toBeNull();
|
|
3249
2913
|
|
|
3250
2914
|
const { lastResponse } = createResponseReader();
|
|
3251
|
-
await handleChannelVerificationSession(
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
},
|
|
3257
|
-
);
|
|
2915
|
+
await handleChannelVerificationSession({
|
|
2916
|
+
type: "channel_verification_session",
|
|
2917
|
+
action: "cancel_session",
|
|
2918
|
+
channel: "telegram",
|
|
2919
|
+
});
|
|
3258
2920
|
|
|
3259
2921
|
const resp = lastResponse();
|
|
3260
2922
|
expect(resp).not.toBeNull();
|
|
@@ -3295,13 +2957,11 @@ describe("outbound Telegram verification", () => {
|
|
|
3295
2957
|
|
|
3296
2958
|
test("create_session for telegram without destination falls through to inbound challenge", async () => {
|
|
3297
2959
|
const { lastResponse } = createResponseReader();
|
|
3298
|
-
await handleChannelVerificationSession(
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
},
|
|
3304
|
-
);
|
|
2960
|
+
await handleChannelVerificationSession({
|
|
2961
|
+
type: "channel_verification_session",
|
|
2962
|
+
action: "create_session",
|
|
2963
|
+
channel: "telegram",
|
|
2964
|
+
});
|
|
3305
2965
|
|
|
3306
2966
|
const resp = lastResponse();
|
|
3307
2967
|
expect(resp).not.toBeNull();
|
|
@@ -3312,14 +2972,12 @@ describe("outbound Telegram verification", () => {
|
|
|
3312
2972
|
test("rate limits apply to telegram outbound (per-session send cap)", async () => {
|
|
3313
2973
|
// Start an outbound session with a known chat ID
|
|
3314
2974
|
broadcastedMessages.length = 0;
|
|
3315
|
-
await handleChannelVerificationSession(
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
},
|
|
3322
|
-
);
|
|
2975
|
+
await handleChannelVerificationSession({
|
|
2976
|
+
type: "channel_verification_session",
|
|
2977
|
+
action: "create_session",
|
|
2978
|
+
channel: "telegram",
|
|
2979
|
+
destination: "123456789",
|
|
2980
|
+
});
|
|
3323
2981
|
|
|
3324
2982
|
// Set the send count to MAX_SENDS_PER_SESSION and nextResendAt to the past
|
|
3325
2983
|
const session = serviceFindActiveSession("telegram");
|
|
@@ -3333,13 +2991,11 @@ describe("outbound Telegram verification", () => {
|
|
|
3333
2991
|
|
|
3334
2992
|
// Resend should be rejected due to max sends
|
|
3335
2993
|
const { lastResponse } = createResponseReader();
|
|
3336
|
-
await handleChannelVerificationSession(
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
},
|
|
3342
|
-
);
|
|
2994
|
+
await handleChannelVerificationSession({
|
|
2995
|
+
type: "channel_verification_session",
|
|
2996
|
+
action: "resend_session",
|
|
2997
|
+
channel: "telegram",
|
|
2998
|
+
});
|
|
3343
2999
|
|
|
3344
3000
|
const resp = lastResponse();
|
|
3345
3001
|
expect(resp).not.toBeNull();
|
|
@@ -3350,24 +3006,20 @@ describe("outbound Telegram verification", () => {
|
|
|
3350
3006
|
test("rate limits apply to telegram outbound (cooldown)", async () => {
|
|
3351
3007
|
// Start an outbound session with a known chat ID
|
|
3352
3008
|
broadcastedMessages.length = 0;
|
|
3353
|
-
await handleChannelVerificationSession(
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
},
|
|
3360
|
-
);
|
|
3009
|
+
await handleChannelVerificationSession({
|
|
3010
|
+
type: "channel_verification_session",
|
|
3011
|
+
action: "create_session",
|
|
3012
|
+
channel: "telegram",
|
|
3013
|
+
destination: "123456789",
|
|
3014
|
+
});
|
|
3361
3015
|
|
|
3362
3016
|
// Immediately try to resend (before cooldown)
|
|
3363
3017
|
const { lastResponse } = createResponseReader();
|
|
3364
|
-
await handleChannelVerificationSession(
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
},
|
|
3370
|
-
);
|
|
3018
|
+
await handleChannelVerificationSession({
|
|
3019
|
+
type: "channel_verification_session",
|
|
3020
|
+
action: "resend_session",
|
|
3021
|
+
channel: "telegram",
|
|
3022
|
+
});
|
|
3371
3023
|
|
|
3372
3024
|
const resp = lastResponse();
|
|
3373
3025
|
expect(resp).not.toBeNull();
|
|
@@ -3387,14 +3039,12 @@ describe("outbound voice verification", () => {
|
|
|
3387
3039
|
|
|
3388
3040
|
test("start_outbound for voice creates session with 6-digit code and initiates call", async () => {
|
|
3389
3041
|
const { lastResponse } = createResponseReader();
|
|
3390
|
-
await handleChannelVerificationSession(
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
},
|
|
3397
|
-
);
|
|
3042
|
+
await handleChannelVerificationSession({
|
|
3043
|
+
type: "channel_verification_session",
|
|
3044
|
+
action: "create_session",
|
|
3045
|
+
channel: "phone",
|
|
3046
|
+
destination: "+15551234567",
|
|
3047
|
+
});
|
|
3398
3048
|
|
|
3399
3049
|
const resp = lastResponse();
|
|
3400
3050
|
expect(resp).not.toBeNull();
|
|
@@ -3427,14 +3077,12 @@ describe("outbound voice verification", () => {
|
|
|
3427
3077
|
|
|
3428
3078
|
test("start_outbound for voice rejects unparseable phone number", async () => {
|
|
3429
3079
|
const { lastResponse } = createResponseReader();
|
|
3430
|
-
await handleChannelVerificationSession(
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
},
|
|
3437
|
-
);
|
|
3080
|
+
await handleChannelVerificationSession({
|
|
3081
|
+
type: "channel_verification_session",
|
|
3082
|
+
action: "create_session",
|
|
3083
|
+
channel: "phone",
|
|
3084
|
+
destination: "not-a-phone",
|
|
3085
|
+
});
|
|
3438
3086
|
|
|
3439
3087
|
const resp = lastResponse();
|
|
3440
3088
|
expect(resp).not.toBeNull();
|
|
@@ -3444,14 +3092,12 @@ describe("outbound voice verification", () => {
|
|
|
3444
3092
|
|
|
3445
3093
|
test("start_outbound for voice normalizes formatted phone number", async () => {
|
|
3446
3094
|
const { lastResponse } = createResponseReader();
|
|
3447
|
-
await handleChannelVerificationSession(
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
},
|
|
3454
|
-
);
|
|
3095
|
+
await handleChannelVerificationSession({
|
|
3096
|
+
type: "channel_verification_session",
|
|
3097
|
+
action: "create_session",
|
|
3098
|
+
channel: "phone",
|
|
3099
|
+
destination: "555-123-4567",
|
|
3100
|
+
});
|
|
3455
3101
|
|
|
3456
3102
|
const resp = lastResponse();
|
|
3457
3103
|
expect(resp).not.toBeNull();
|
|
@@ -3485,15 +3131,13 @@ describe("outbound voice verification", () => {
|
|
|
3485
3131
|
});
|
|
3486
3132
|
|
|
3487
3133
|
const { lastResponse } = createResponseReader();
|
|
3488
|
-
await handleChannelVerificationSession(
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
},
|
|
3496
|
-
);
|
|
3134
|
+
await handleChannelVerificationSession({
|
|
3135
|
+
type: "channel_verification_session",
|
|
3136
|
+
action: "create_session",
|
|
3137
|
+
channel: "phone",
|
|
3138
|
+
destination: "+15559876543",
|
|
3139
|
+
rebind: false,
|
|
3140
|
+
});
|
|
3497
3141
|
|
|
3498
3142
|
const resp = lastResponse();
|
|
3499
3143
|
expect(resp).not.toBeNull();
|
|
@@ -3504,24 +3148,20 @@ describe("outbound voice verification", () => {
|
|
|
3504
3148
|
test("resend_outbound for voice initiates a new call with cooldown check", async () => {
|
|
3505
3149
|
// Start an outbound session first
|
|
3506
3150
|
broadcastedMessages.length = 0;
|
|
3507
|
-
await handleChannelVerificationSession(
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
},
|
|
3514
|
-
);
|
|
3151
|
+
await handleChannelVerificationSession({
|
|
3152
|
+
type: "channel_verification_session",
|
|
3153
|
+
action: "create_session",
|
|
3154
|
+
channel: "phone",
|
|
3155
|
+
destination: "+15551234567",
|
|
3156
|
+
});
|
|
3515
3157
|
|
|
3516
3158
|
// Immediately try to resend (before cooldown)
|
|
3517
3159
|
const { lastResponse } = createResponseReader();
|
|
3518
|
-
await handleChannelVerificationSession(
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
},
|
|
3524
|
-
);
|
|
3160
|
+
await handleChannelVerificationSession({
|
|
3161
|
+
type: "channel_verification_session",
|
|
3162
|
+
action: "resend_session",
|
|
3163
|
+
channel: "phone",
|
|
3164
|
+
});
|
|
3525
3165
|
|
|
3526
3166
|
const resp = lastResponse();
|
|
3527
3167
|
expect(resp).not.toBeNull();
|
|
@@ -3532,24 +3172,20 @@ describe("outbound voice verification", () => {
|
|
|
3532
3172
|
test("cancel_outbound for voice cancels session", async () => {
|
|
3533
3173
|
// Start an outbound session first
|
|
3534
3174
|
broadcastedMessages.length = 0;
|
|
3535
|
-
await handleChannelVerificationSession(
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
},
|
|
3542
|
-
);
|
|
3175
|
+
await handleChannelVerificationSession({
|
|
3176
|
+
type: "channel_verification_session",
|
|
3177
|
+
action: "create_session",
|
|
3178
|
+
channel: "phone",
|
|
3179
|
+
destination: "+15551234567",
|
|
3180
|
+
});
|
|
3543
3181
|
|
|
3544
3182
|
// Cancel the session
|
|
3545
3183
|
const { lastResponse } = createResponseReader();
|
|
3546
|
-
await handleChannelVerificationSession(
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
},
|
|
3552
|
-
);
|
|
3184
|
+
await handleChannelVerificationSession({
|
|
3185
|
+
type: "channel_verification_session",
|
|
3186
|
+
action: "cancel_session",
|
|
3187
|
+
channel: "phone",
|
|
3188
|
+
});
|
|
3553
3189
|
|
|
3554
3190
|
const resp = lastResponse();
|
|
3555
3191
|
expect(resp).not.toBeNull();
|
|
@@ -3583,14 +3219,12 @@ describe("outbound voice verification", () => {
|
|
|
3583
3219
|
}
|
|
3584
3220
|
|
|
3585
3221
|
const { lastResponse } = createResponseReader();
|
|
3586
|
-
await handleChannelVerificationSession(
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
},
|
|
3593
|
-
);
|
|
3222
|
+
await handleChannelVerificationSession({
|
|
3223
|
+
type: "channel_verification_session",
|
|
3224
|
+
action: "create_session",
|
|
3225
|
+
channel: "phone",
|
|
3226
|
+
destination: "+15551234567",
|
|
3227
|
+
});
|
|
3594
3228
|
|
|
3595
3229
|
const resp = lastResponse();
|
|
3596
3230
|
expect(resp).not.toBeNull();
|
|
@@ -3600,13 +3234,11 @@ describe("outbound voice verification", () => {
|
|
|
3600
3234
|
|
|
3601
3235
|
test("create_session for voice without destination falls through to inbound challenge", async () => {
|
|
3602
3236
|
const { lastResponse } = createResponseReader();
|
|
3603
|
-
await handleChannelVerificationSession(
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
},
|
|
3609
|
-
);
|
|
3237
|
+
await handleChannelVerificationSession({
|
|
3238
|
+
type: "channel_verification_session",
|
|
3239
|
+
action: "create_session",
|
|
3240
|
+
channel: "phone",
|
|
3241
|
+
});
|
|
3610
3242
|
|
|
3611
3243
|
const resp = lastResponse();
|
|
3612
3244
|
expect(resp).not.toBeNull();
|
|
@@ -3634,14 +3266,12 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3634
3266
|
|
|
3635
3267
|
test("start_outbound for voice response includes secret", async () => {
|
|
3636
3268
|
const { lastResponse } = createResponseReader();
|
|
3637
|
-
await handleChannelVerificationSession(
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
},
|
|
3644
|
-
);
|
|
3269
|
+
await handleChannelVerificationSession({
|
|
3270
|
+
type: "channel_verification_session",
|
|
3271
|
+
action: "create_session",
|
|
3272
|
+
channel: "phone",
|
|
3273
|
+
destination: "+15551234567",
|
|
3274
|
+
});
|
|
3645
3275
|
|
|
3646
3276
|
const resp = lastResponse();
|
|
3647
3277
|
expect(resp).not.toBeNull();
|
|
@@ -3656,14 +3286,12 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3656
3286
|
test("resend_outbound for voice response includes secret", async () => {
|
|
3657
3287
|
// Start a session first
|
|
3658
3288
|
broadcastedMessages.length = 0;
|
|
3659
|
-
await handleChannelVerificationSession(
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
},
|
|
3666
|
-
);
|
|
3289
|
+
await handleChannelVerificationSession({
|
|
3290
|
+
type: "channel_verification_session",
|
|
3291
|
+
action: "create_session",
|
|
3292
|
+
channel: "phone",
|
|
3293
|
+
destination: "+15551234567",
|
|
3294
|
+
});
|
|
3667
3295
|
|
|
3668
3296
|
// Move past cooldown
|
|
3669
3297
|
const session = serviceFindActiveSession("phone");
|
|
@@ -3677,13 +3305,11 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3677
3305
|
|
|
3678
3306
|
// Resend
|
|
3679
3307
|
const { lastResponse } = createResponseReader();
|
|
3680
|
-
await handleChannelVerificationSession(
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
},
|
|
3686
|
-
);
|
|
3308
|
+
await handleChannelVerificationSession({
|
|
3309
|
+
type: "channel_verification_session",
|
|
3310
|
+
action: "resend_session",
|
|
3311
|
+
channel: "phone",
|
|
3312
|
+
});
|
|
3687
3313
|
|
|
3688
3314
|
const resp = lastResponse();
|
|
3689
3315
|
expect(resp).not.toBeNull();
|
|
@@ -3697,14 +3323,12 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3697
3323
|
|
|
3698
3324
|
test("start_outbound for Telegram bootstrap (handle) does NOT return secret", async () => {
|
|
3699
3325
|
const { lastResponse } = createResponseReader();
|
|
3700
|
-
await handleChannelVerificationSession(
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
},
|
|
3707
|
-
);
|
|
3326
|
+
await handleChannelVerificationSession({
|
|
3327
|
+
type: "channel_verification_session",
|
|
3328
|
+
action: "create_session",
|
|
3329
|
+
channel: "telegram",
|
|
3330
|
+
destination: "@someuser",
|
|
3331
|
+
});
|
|
3708
3332
|
|
|
3709
3333
|
const resp = lastResponse();
|
|
3710
3334
|
expect(resp).not.toBeNull();
|