@vellumai/assistant 0.11.2 → 0.11.3-staging.2
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 +58 -3
- package/docs/trusted-contact-access.md +9 -5
- package/docs/vellum-doctor.md +195 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
- package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
- package/node_modules/@vellumai/environments/src/index.ts +17 -6
- package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
- package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
- package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
- package/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
- package/openapi.yaml +589 -30
- package/package.json +1 -1
- package/src/__tests__/agent-image-optimize.test.ts +4 -4
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
- package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
- package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/answered-question-persistence.test.ts +240 -0
- package/src/__tests__/anthropic-provider.test.ts +165 -30
- package/src/__tests__/app-control-flow.test.ts +9 -8
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
- package/src/__tests__/attachments-store.test.ts +130 -68
- package/src/__tests__/attachments.test.ts +36 -36
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
- package/src/__tests__/canned-reply-release.test.ts +86 -0
- package/src/__tests__/channel-guardian.test.ts +59 -29
- package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
- package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
- package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/consult-deadline.test.ts +65 -0
- package/src/__tests__/conversation-agent-loop.test.ts +438 -2
- package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
- package/src/__tests__/conversation-disk-view.test.ts +4 -4
- package/src/__tests__/conversation-error.test.ts +22 -3
- package/src/__tests__/conversation-fork-crud.test.ts +5 -1
- package/src/__tests__/conversation-fork-referential.test.ts +352 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
- package/src/__tests__/conversation-group-tools.test.ts +32 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
- package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
- package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
- package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
- package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
- package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
- package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
- package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
- package/src/__tests__/conversation-queue.test.ts +433 -1
- package/src/__tests__/conversation-retry-route.test.ts +3 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
- package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
- package/src/__tests__/conversation-store.test.ts +26 -10
- package/src/__tests__/conversation-summarize-route.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
- package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
- package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
- package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
- package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
- package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
- package/src/__tests__/credential-prompt-route.test.ts +57 -7
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +89 -28
- package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
- package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
- package/src/__tests__/disk-pressure-guard.test.ts +55 -55
- package/src/__tests__/disk-pressure-routes.test.ts +10 -10
- package/src/__tests__/disk-pressure-tools.test.ts +2 -2
- package/src/__tests__/disk-usage.test.ts +35 -20
- package/src/__tests__/document-sync-tags.test.ts +379 -0
- package/src/__tests__/document-update-default-surface.test.ts +28 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
- package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
- package/src/__tests__/events-dev-bypass-actor.test.ts +183 -1
- package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
- package/src/__tests__/file-list-tool.test.ts +12 -10
- package/src/__tests__/file-ops-service.test.ts +151 -44
- package/src/__tests__/file-read-container-boundary.test.ts +137 -0
- package/src/__tests__/file-read-tool.test.ts +21 -9
- package/src/__tests__/file-url-path-guard.test.ts +83 -0
- package/src/__tests__/filesystem-tools.test.ts +82 -66
- package/src/__tests__/guardian-outbound-http.test.ts +8 -8
- package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
- package/src/__tests__/helpers/hub-clients.ts +42 -0
- package/src/__tests__/helpers/mock-conversation.ts +46 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
- package/src/__tests__/history-repair.test.ts +112 -12
- package/src/__tests__/host-bash-proxy.test.ts +10 -5
- package/src/__tests__/host-bash-routes.test.ts +67 -0
- package/src/__tests__/host-browser-proxy.test.ts +2 -2
- package/src/__tests__/host-cu-proxy.test.ts +3 -7
- package/src/__tests__/host-file-proxy.test.ts +3 -7
- package/src/__tests__/host-file-read-tool.test.ts +5 -1
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
- package/src/__tests__/http-conversation-lineage.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +44 -0
- package/src/__tests__/identity-routes.test.ts +13 -13
- package/src/__tests__/image-conversion.test.ts +29 -26
- package/src/__tests__/image-source-path-reinject.test.ts +2 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
- package/src/__tests__/introduction-card-resolver.test.ts +6 -1
- package/src/__tests__/list-messages-attachments.test.ts +56 -32
- package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
- package/src/__tests__/list-messages-page-latest.test.ts +61 -61
- package/src/__tests__/list-messages-provider-error.test.ts +6 -6
- package/src/__tests__/list-messages-queued.test.ts +49 -6
- package/src/__tests__/list-messages-system-card.test.ts +4 -4
- package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
- package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
- package/src/__tests__/llm-usage-store.test.ts +55 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
- package/src/__tests__/media-stream-server-integration.test.ts +36 -0
- package/src/__tests__/migration-export-http.test.ts +1 -1
- package/src/__tests__/migration-import-commit-http.test.ts +1 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
- package/src/__tests__/migration-validate-http.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +65 -3
- package/src/__tests__/notification-platform-adapter.test.ts +104 -0
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
- package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
- package/src/__tests__/path-policy.test.ts +164 -1
- package/src/__tests__/persist-media-references.test.ts +2 -2
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
- package/src/__tests__/persist-unsendable-image.test.ts +23 -23
- package/src/__tests__/persona-resolver.test.ts +154 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
- package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
- package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
- package/src/__tests__/profiler-routes.test.ts +13 -13
- package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
- package/src/__tests__/proxy-approval-callback.test.ts +3 -3
- package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
- package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
- package/src/__tests__/resolve-trust-class.test.ts +20 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
- package/src/__tests__/run-due-schedules.test.ts +174 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
- package/src/__tests__/schedule-routes.test.ts +730 -8
- package/src/__tests__/schedule-store.test.ts +540 -0
- package/src/__tests__/schedule-tools.test.ts +103 -0
- package/src/__tests__/scheduler-wake.test.ts +5 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
- package/src/__tests__/secure-keys.test.ts +91 -0
- package/src/__tests__/server-history-render.test.ts +97 -7
- package/src/__tests__/size-guard.test.ts +8 -8
- package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
- package/src/__tests__/skill-tool-factory.test.ts +247 -0
- package/src/__tests__/skills-install-staging.test.ts +15 -6
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
- package/src/__tests__/slack-inbound-verification.test.ts +4 -1
- package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
- package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
- package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
- package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
- package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
- package/src/__tests__/subagent-disposal.test.ts +10 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
- package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
- package/src/__tests__/subagent-manager-notify.test.ts +148 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/subagent-persistence.test.ts +141 -0
- package/src/__tests__/subagent-role-registry.test.ts +172 -63
- package/src/__tests__/subagent-role-resolution.test.ts +88 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
- package/src/__tests__/subagent-terminal-message.test.ts +88 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
- package/src/__tests__/subagent-tools.test.ts +1901 -108
- package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
- package/src/__tests__/system-prompt.test.ts +82 -7
- package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
- package/src/__tests__/tool-result-spool.test.ts +74 -18
- package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
- package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
- package/src/__tests__/tools-audio-read.test.ts +10 -10
- package/src/__tests__/tools-get-route.test.ts +85 -12
- package/src/__tests__/tools-list-cli.test.ts +171 -0
- package/src/__tests__/top-level-renderer.test.ts +54 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
- package/src/__tests__/turn-tail-chain.test.ts +135 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
- package/src/__tests__/ui-visual-surface.test.ts +5 -4
- package/src/__tests__/ui-work-result-surface.test.ts +5 -4
- package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
- package/src/__tests__/usage-routes.test.ts +62 -0
- package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
- package/src/__tests__/visible-app-context.test.ts +20 -4
- package/src/__tests__/web-search-history.test.ts +96 -0
- package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
- package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
- package/src/acp/failure-error.ts +3 -5
- package/src/agent/attachments.ts +26 -24
- package/src/agent/history-repair/history-repair.ts +27 -26
- package/src/agent/image-optimize.ts +6 -6
- package/src/agent/loop.ts +40 -22
- package/src/agent/message-types.ts +3 -3
- package/src/api/constants/document-tools.ts +55 -0
- package/src/api/events/question-answered.ts +53 -0
- package/src/api/events/tool-result.ts +7 -0
- package/src/api/index.ts +13 -0
- package/src/api/responses/conversation-message.ts +11 -0
- package/src/api/surfaces-oauth-connect.test.ts +96 -0
- package/src/api/surfaces.ts +36 -8
- package/src/approvals/guardian-channel-delivery.ts +83 -0
- package/src/approvals/guardian-expiry-notifier.ts +13 -11
- package/src/approvals/guardian-request-resolvers.ts +222 -135
- package/src/calls/__tests__/voice-session-bridge.test.ts +50 -0
- package/src/calls/media-stream-server.ts +9 -1
- package/src/calls/voice-session-bridge.ts +38 -0
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
- package/src/channels/config.ts +7 -2
- package/src/channels/gateway-verification-sessions.ts +7 -2
- package/src/channels/types.ts +7 -1
- package/src/cli/commands/__tests__/cache.test.ts +7 -4
- package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
- package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
- package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
- package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
- package/src/cli/commands/__tests__/plugins.test.ts +692 -0
- package/src/cli/commands/__tests__/schedules.test.ts +136 -37
- package/src/cli/commands/conversations.ts +7 -3
- package/src/cli/commands/credentials.help.ts +7 -0
- package/src/cli/commands/inference-profiles.ts +9 -3
- package/src/cli/commands/inference.help.ts +16 -2
- package/src/cli/commands/mcp.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +18 -0
- package/src/cli/commands/notifications.ts +3 -6
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
- package/src/cli/commands/oauth/connect.test.ts +26 -1
- package/src/cli/commands/oauth/connect.ts +4 -1
- package/src/cli/commands/oauth/index.help.ts +3 -1
- package/src/cli/commands/oauth/providers.ts +3 -0
- package/src/cli/commands/plugins.help.ts +25 -2
- package/src/cli/commands/plugins.ts +289 -10
- package/src/cli/commands/schedules.help.ts +14 -12
- package/src/cli/commands/schedules.ts +19 -5
- package/src/cli/commands/tools.help.ts +4 -2
- package/src/cli/commands/tools.ts +38 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
- package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +122 -0
- package/src/cli/lib/install-from-github.ts +61 -0
- package/src/cli/lib/install-from-platform.ts +13 -2
- package/src/cli/lib/plugin-surfaces.ts +124 -4
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/cli.ts +1 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
- package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
- package/src/config/__tests__/profile-tool-support.test.ts +131 -0
- package/src/config/bundled-skills/AGENTS.md +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
- package/src/config/bundled-skills/schedule/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +53 -22
- package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
- package/src/config/bundled-skills/visualize/SKILL.md +1 -1
- package/src/config/default-profile-catalog.ts +6 -2
- package/src/config/feature-flag-registry.json +25 -17
- package/src/config/llm-resolver.ts +45 -15
- package/src/config/loader.ts +70 -1
- package/src/config/profile-tool-support.ts +110 -0
- package/src/config/sanitize-for-transfer.ts +11 -0
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/stt.test.ts +20 -5
- package/src/config/schemas/channels.ts +13 -0
- package/src/config/schemas/memory-retrospective.ts +25 -0
- package/src/config/schemas/plugin-updates.ts +55 -0
- package/src/config/schemas/services.ts +8 -4
- package/src/config/schemas/stt.ts +17 -5
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
- package/src/contacts/guardian-delivery-reader.ts +29 -2
- package/src/context/compactor.ts +4 -4
- package/src/context/post-turn-tool-result-truncation.ts +32 -16
- package/src/context/strip-injections.ts +42 -0
- package/src/context/tool-result-spool.ts +32 -18
- package/src/credential-execution/ces-runtime.ts +3 -0
- package/src/credential-execution/client.ts +22 -1
- package/src/credential-execution/process-manager.test.ts +99 -0
- package/src/credential-execution/process-manager.ts +62 -16
- package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
- package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
- package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
- package/src/daemon/channel-ui-capability.ts +4 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
- package/src/daemon/conversation-agent-loop.ts +318 -148
- package/src/daemon/conversation-attachments.ts +1 -1
- package/src/daemon/conversation-error.ts +8 -1
- package/src/daemon/conversation-initial-prompt.ts +16 -38
- package/src/daemon/conversation-lifecycle.ts +154 -32
- package/src/daemon/conversation-messaging.ts +106 -43
- package/src/daemon/conversation-process.ts +131 -33
- package/src/daemon/conversation-queue-manager.ts +10 -0
- package/src/daemon/conversation-runtime-assembly.ts +9 -4
- package/src/daemon/conversation-store.ts +52 -3
- package/src/daemon/conversation-surface-state.ts +9 -0
- package/src/daemon/conversation-surfaces.ts +403 -210
- package/src/daemon/conversation-tool-setup.ts +56 -7
- package/src/daemon/conversation-turn-finalize.ts +134 -89
- package/src/daemon/conversation.ts +111 -27
- package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
- package/src/daemon/disk-pressure-guard.ts +3 -3
- package/src/daemon/doordash-steps.ts +5 -5
- package/src/daemon/external-plugins-bootstrap.ts +7 -1
- package/src/daemon/handlers/config-channels.ts +48 -5
- package/src/daemon/handlers/conversation-history.ts +1 -1
- package/src/daemon/handlers/conversations.ts +62 -17
- package/src/daemon/handlers/shared.ts +12 -0
- package/src/daemon/handlers/skills.ts +11 -1
- package/src/daemon/identity-helpers.ts +38 -10
- package/src/daemon/install-assistant-command.ts +322 -0
- package/src/daemon/lifecycle.ts +14 -3
- package/src/daemon/message-types/conversations.ts +6 -7
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/persist-media-references.ts +23 -14
- package/src/daemon/process-message.ts +6 -6
- package/src/daemon/tool-setup-types.ts +19 -122
- package/src/daemon/tool-side-effects.ts +17 -94
- package/src/daemon/trust-context-types.ts +39 -0
- package/src/daemon/trust-context.ts +14 -6
- package/src/daemon/turn-tail-chain.ts +73 -0
- package/src/daemon/web-search-history.ts +47 -33
- package/src/heartbeat/heartbeat-service.ts +6 -6
- package/src/ipc/__tests__/socket-path.test.ts +21 -0
- package/src/ipc/assistant-server.ts +17 -10
- package/src/ipc/cli-client.ts +10 -1
- package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
- package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
- package/src/ipc/socket-cleanup.ts +9 -7
- package/src/ipc/socket-path.ts +4 -96
- package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
- package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
- package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
- package/src/live-voice/__tests__/live-voice-integration.test.ts +7 -5
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
- package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
- package/src/live-voice/__tests__/protocol.test.ts +52 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
- package/src/live-voice/live-voice-archive.ts +13 -13
- package/src/live-voice/live-voice-connection.ts +7 -1
- package/src/live-voice/live-voice-photo.ts +169 -0
- package/src/live-voice/live-voice-session.ts +108 -4
- package/src/live-voice/protocol.ts +89 -1
- package/src/mcp/client.ts +10 -0
- package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
- package/src/messaging/providers/callback-routing.ts +1 -0
- package/src/messaging/providers/discord/api.ts +312 -0
- package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
- package/src/messaging/providers/discord/render.test.ts +204 -0
- package/src/messaging/providers/discord/render.ts +195 -0
- package/src/messaging/providers/discord/send.test.ts +179 -0
- package/src/messaging/providers/discord/send.ts +212 -0
- package/src/messaging/providers/discord/transport.ts +81 -0
- package/src/messaging/providers/index.ts +3 -1
- package/src/messaging/providers/retry-policy.test.ts +247 -0
- package/src/messaging/providers/retry-policy.ts +206 -0
- package/src/messaging/providers/slack/mention-source.test.ts +285 -0
- package/src/messaging/providers/slack/mention-source.ts +287 -0
- package/src/messaging/providers/telegram-bot/api.ts +47 -130
- package/src/messaging/providers/whatsapp/api.ts +47 -136
- package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +332 -0
- package/src/monitoring/db-integrity-sample.ts +6 -1
- package/src/monitoring/plugin-auto-update.ts +359 -0
- package/src/monitoring/resource-sampler.ts +21 -5
- package/src/monitoring/worker.ts +13 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
- package/src/notifications/__tests__/broadcaster.test.ts +37 -1
- package/src/notifications/__tests__/copy-composer.test.ts +165 -0
- package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
- package/src/notifications/__tests__/notification-utils.test.ts +249 -0
- package/src/notifications/adapters/platform.ts +31 -2
- package/src/notifications/assistant-reply-producer.ts +79 -32
- package/src/notifications/broadcaster.ts +30 -10
- package/src/notifications/copy-composer.ts +69 -0
- package/src/notifications/emit-signal.ts +82 -15
- package/src/notifications/events-store.ts +10 -2
- package/src/notifications/home-feed-side-effect.ts +6 -3
- package/src/notifications/notification-utils.ts +173 -5
- package/src/notifications/signal.ts +12 -0
- package/src/oauth/AGENTS.md +4 -2
- package/src/oauth/byo-connection.ts +6 -1
- package/src/oauth/credential-token-resolver.ts +3 -10
- package/src/oauth/manual-token-connection.ts +29 -64
- package/src/oauth/manual-token-providers.ts +62 -0
- package/src/oauth/provider-serializer.ts +13 -0
- package/src/oauth/seed-providers.ts +62 -11
- package/src/onboarding/onboarding-events-store.ts +91 -1
- package/src/permissions/question-prompter.test.ts +4 -0
- package/src/permissions/question-prompter.ts +21 -4
- package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
- package/src/persistence/attachments-store.ts +15 -15
- package/src/persistence/conversation-attention-store.ts +30 -10
- package/src/persistence/conversation-bootstrap.ts +17 -0
- package/src/persistence/conversation-crud.ts +363 -97
- package/src/persistence/conversation-group-migration.ts +1 -1
- package/src/persistence/conversation-key-store.ts +38 -10
- package/src/persistence/conversation-lineage.ts +226 -0
- package/src/persistence/conversation-plugin-facade.ts +28 -3
- package/src/persistence/conversation-queries.ts +207 -33
- package/src/persistence/conversation-types.ts +107 -1
- package/src/persistence/jobs-store.ts +32 -8
- package/src/persistence/llm-usage-store.ts +22 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
- package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
- package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
- package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
- package/src/persistence/schema/conversations.ts +32 -0
- package/src/persistence/schema/infrastructure.ts +3 -0
- package/src/persistence/steps.ts +30 -0
- package/src/persistence/subagent-store.ts +148 -6
- package/src/platform/managed-speech.test.ts +20 -0
- package/src/platform/managed-speech.ts +9 -0
- package/src/plugin-api/index.ts +8 -0
- package/src/plugin-api/webhook-url.ts +151 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
- package/src/plugins/collect-source-versions.ts +4 -27
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
- package/src/plugins/defaults/exploration-drift/package.json +1 -1
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
- package/src/plugins/defaults/image-recovery/recover.ts +67 -57
- package/src/plugins/defaults/index.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
- package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
- package/src/plugins/defaults/memory/job-handlers.ts +87 -5
- package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
- package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
- package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
- package/src/plugins/defaults/memory/v2/router.ts +8 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
- package/src/plugins/external-plugin-loader.ts +17 -8
- package/src/plugins/installed-plugin-dirs.ts +101 -0
- package/src/plugins/mtime-cache.ts +34 -22
- package/src/plugins/types.ts +69 -8
- package/src/prompts/persona-resolver.ts +6 -2
- package/src/prompts/system-prompt.ts +72 -17
- package/src/providers/__tests__/inference.test.ts +40 -0
- package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
- package/src/providers/__tests__/retry-callsite.test.ts +67 -0
- package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
- package/src/providers/anthropic/client.ts +112 -95
- package/src/providers/connection-resolution.ts +35 -1
- package/src/providers/gemini/client.ts +5 -5
- package/src/providers/inference/adapter-factory.ts +16 -10
- package/src/providers/inference/auth.ts +16 -0
- package/src/providers/inference/connection-availability.ts +164 -12
- package/src/providers/inference/connections.ts +25 -1
- package/src/providers/media-resolve.ts +21 -11
- package/src/providers/model-catalog.ts +15 -0
- package/src/providers/openai/chat-completions-provider.ts +4 -4
- package/src/providers/openai/responses-provider.ts +12 -25
- package/src/providers/registry.ts +9 -4
- package/src/providers/retry.ts +25 -0
- package/src/providers/server-tool-pairing.ts +134 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +187 -6
- package/src/providers/speech-to-text/deepgram.ts +1 -0
- package/src/providers/speech-to-text/resolve.ts +80 -10
- package/src/providers/speech-to-text/vellum-managed.ts +7 -1
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
- package/src/providers/types.ts +26 -6
- package/src/providers/vellum-model-routing.ts +6 -7
- package/src/runtime/AGENTS.md +2 -0
- package/src/runtime/__tests__/agent-wake.test.ts +16 -16
- package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
- package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
- package/src/runtime/agent-wake.ts +63 -24
- package/src/runtime/assistant-event-hub.ts +87 -12
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
- package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
- package/src/runtime/auth/same-actor.ts +56 -8
- package/src/runtime/auth/scopes.ts +12 -0
- package/src/runtime/auth/types.ts +2 -0
- package/src/runtime/background-job-runner.ts +5 -27
- package/src/runtime/channel-readiness-service.ts +59 -3
- package/src/runtime/channel-readiness-types.ts +18 -0
- package/src/runtime/desktop-presence.ts +69 -0
- package/src/runtime/http-server.ts +12 -0
- package/src/runtime/local-actor-identity.ts +11 -9
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +173 -1
- package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
- package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
- package/src/runtime/routes/archive-utils.ts +16 -12
- package/src/runtime/routes/attachment-routes.ts +13 -6
- package/src/runtime/routes/canned-reply-release.ts +54 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -27
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
- package/src/runtime/routes/client-routes.ts +114 -2
- package/src/runtime/routes/conversation-cli-routes.ts +10 -12
- package/src/runtime/routes/conversation-list-routes.ts +59 -10
- package/src/runtime/routes/conversation-management-routes.ts +47 -18
- package/src/runtime/routes/conversation-query-routes.ts +32 -53
- package/src/runtime/routes/conversation-routes.ts +360 -293
- package/src/runtime/routes/credential-prompt-routes.ts +23 -2
- package/src/runtime/routes/debug-routes.ts +4 -1
- package/src/runtime/routes/default-provider-routes.ts +7 -11
- package/src/runtime/routes/documents-routes.ts +44 -1
- package/src/runtime/routes/events-routes.ts +28 -1
- package/src/runtime/routes/host-app-control-routes.ts +2 -0
- package/src/runtime/routes/host-bash-routes.ts +2 -0
- package/src/runtime/routes/host-browser-routes.ts +2 -0
- package/src/runtime/routes/host-cu-routes.ts +2 -0
- package/src/runtime/routes/host-file-routes.ts +2 -0
- package/src/runtime/routes/host-transfer-routes.ts +4 -0
- package/src/runtime/routes/identity-routes.ts +6 -6
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
- package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
- package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
- package/src/runtime/routes/inference-profiles-routes.ts +152 -73
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
- package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
- package/src/runtime/routes/log-export-routes.ts +1 -1
- package/src/runtime/routes/notification-routes.ts +0 -14
- package/src/runtime/routes/oauth-providers.ts +1 -0
- package/src/runtime/routes/plugins-routes.ts +106 -1
- package/src/runtime/routes/profiler-routes.ts +4 -2
- package/src/runtime/routes/question-routes.ts +28 -10
- package/src/runtime/routes/retrospective-routes.ts +9 -3
- package/src/runtime/routes/schedule-routes.ts +210 -12
- package/src/runtime/routes/secret-routes.ts +40 -23
- package/src/runtime/routes/settings-routes.ts +41 -13
- package/src/runtime/routes/skills-routes.ts +79 -0
- package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
- package/src/runtime/routes/wake-conversation-routes.ts +23 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +24 -9
- package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
- package/src/runtime/sync/resource-sync-events.ts +79 -1
- package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
- package/src/runtime/sync/worker-daemon-notify.ts +44 -6
- package/src/runtime/verification-outbound-actions.ts +250 -222
- package/src/runtime/verification-templates.ts +41 -30
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
- package/src/schedule/inference-profile.ts +64 -3
- package/src/schedule/plugin-schedule-declarations.ts +518 -0
- package/src/schedule/plugin-schedule-reconciler.ts +605 -0
- package/src/schedule/plugin-schedules-gate.ts +23 -0
- package/src/schedule/schedule-store.ts +520 -26
- package/src/schedule/scheduler.ts +38 -0
- package/src/security/credential-backend.ts +51 -4
- package/src/security/encrypted-store.ts +64 -42
- package/src/security/secure-keys.ts +55 -7
- package/src/skills/catalog-install.ts +20 -7
- package/src/skills/inline-command-runner.ts +2 -7
- package/src/skills/skill-history.test.ts +269 -0
- package/src/skills/skill-history.ts +250 -0
- package/src/skills/skillssh-registry.ts +1 -1
- package/src/stt/daemon-batch-transcriber.ts +8 -6
- package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
- package/src/subagent/consult-prompt.ts +3 -1
- package/src/subagent/consult-transcript.ts +1 -1
- package/src/subagent/manager.ts +304 -44
- package/src/subagent/progress-events.ts +35 -0
- package/src/subagent/role-resolution.ts +88 -0
- package/src/subagent/types.ts +302 -67
- package/src/subagent/validate-allowlists.ts +3 -4
- package/src/telegram/__tests__/webhook-health.test.ts +73 -1
- package/src/telegram/webhook-health.ts +101 -3
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
- package/src/telemetry/activation-funnel.ts +6 -1
- package/src/telemetry/live-voice-funnel.ts +75 -0
- package/src/telemetry/telemetry-event-sources.ts +6 -0
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire.generated.ts +2 -0
- package/src/telemetry/types.ts +23 -4
- package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
- package/src/tools/ask-question/ask-question-tool.ts +56 -2
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/calls/call-start.ts +8 -5
- package/src/tools/conversation-groups/move_to_group.ts +10 -12
- package/src/tools/document/document-tool.ts +11 -4
- package/src/tools/execution-timeout.ts +9 -2
- package/src/tools/executor.ts +7 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +7 -13
- package/src/tools/filesystem/search.ts +23 -21
- package/src/tools/filesystem/write.ts +4 -1
- package/src/tools/host-filesystem/edit.ts +7 -2
- package/src/tools/host-filesystem/read.ts +21 -8
- package/src/tools/host-filesystem/write.ts +10 -2
- package/src/tools/host-terminal/host-shell.ts +2 -2
- package/src/tools/mcp/mcp-tool-factory.ts +25 -1
- package/src/tools/permission-checker.ts +8 -3
- package/src/tools/schedule/delete.ts +13 -1
- package/src/tools/schedule/list.ts +14 -3
- package/src/tools/schedule/update.ts +56 -33
- package/src/tools/shared/filesystem/audio-read.ts +6 -4
- package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
- package/src/tools/shared/filesystem/image-read.ts +12 -12
- package/src/tools/shared/filesystem/path-policy.ts +70 -5
- package/src/tools/shared/filesystem/size-guard.ts +6 -6
- package/src/tools/shared/input-misuse.ts +72 -0
- package/src/tools/skills/scaffold-managed.ts +82 -0
- package/src/tools/skills/skill-tool-factory.ts +14 -1
- package/src/tools/subagent/consult-deadline.ts +12 -7
- package/src/tools/subagent/message.ts +3 -1
- package/src/tools/subagent/read.ts +66 -4
- package/src/tools/subagent/spawn.ts +500 -78
- package/src/tools/tool-approval-handler.ts +45 -4
- package/src/tools/types.ts +22 -3
- package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
- package/src/tools/ui-surface/visual-validation.ts +2 -0
- package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
- package/src/usage/subagent-attribution.ts +108 -0
- package/src/util/__tests__/sqlite-retry.test.ts +112 -0
- package/src/util/abort-reasons.ts +16 -0
- package/src/util/ansi.ts +44 -0
- package/src/util/disk-usage.ts +17 -13
- package/src/util/image-conversion.ts +20 -13
- package/src/util/schedule-source-key.ts +23 -0
- package/src/util/worker-process.ts +7 -1
- package/src/workspace/git-service.ts +33 -9
- package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
- package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/top-level-renderer.ts +15 -2
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
- package/src/daemon/install-symlink.ts +0 -207
- package/src/notifications/deferred-emit.ts +0 -147
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Shared outbound verification action logic.
|
|
3
3
|
*
|
|
4
4
|
* These functions encapsulate the business logic for starting, resending,
|
|
5
|
-
* and cancelling outbound verification flows (Telegram, voice, Slack,
|
|
5
|
+
* and cancelling outbound verification flows (Telegram, voice, Slack, Discord,
|
|
6
|
+
* email).
|
|
6
7
|
* They return transport-agnostic result objects and are consumed by both the
|
|
7
8
|
* message handler (config-channels.ts) and the HTTP route layer (channel-verification-routes.ts).
|
|
8
9
|
*
|
|
@@ -24,6 +25,8 @@ import {
|
|
|
24
25
|
updateSessionStatus,
|
|
25
26
|
} from "../channels/gateway-verification-sessions.js";
|
|
26
27
|
import type { ChannelId } from "../channels/types.js";
|
|
28
|
+
import { openDiscordDmChannel } from "../messaging/providers/discord/api.js";
|
|
29
|
+
import { sendDiscordReply } from "../messaging/providers/discord/send.js";
|
|
27
30
|
import { sendSlackReply } from "../messaging/providers/slack/send.js";
|
|
28
31
|
import { sendTelegramReply } from "../messaging/providers/telegram-bot/send.js";
|
|
29
32
|
import { getTelegramBotUsername } from "../telegram/bot-username.js";
|
|
@@ -32,10 +35,9 @@ import { normalizePhoneNumber } from "../util/phone.js";
|
|
|
32
35
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
|
|
33
36
|
import { isGuardianBoundForChannel } from "./channel-verification-service.js";
|
|
34
37
|
import {
|
|
35
|
-
|
|
36
|
-
composeVerificationSlack,
|
|
37
|
-
composeVerificationTelegram,
|
|
38
|
+
composeVerificationText,
|
|
38
39
|
GUARDIAN_VERIFY_TEMPLATE_KEYS,
|
|
40
|
+
type TextVerifyTemplateKey,
|
|
39
41
|
} from "./verification-templates.js";
|
|
40
42
|
|
|
41
43
|
const log = getLogger("verification-outbound-actions");
|
|
@@ -113,7 +115,7 @@ interface CancelOutboundParams {
|
|
|
113
115
|
* Maps 1:1 with the fields in ChannelVerificationSessionResponse minus the
|
|
114
116
|
* `type` discriminant.
|
|
115
117
|
*/
|
|
116
|
-
interface OutboundActionResult {
|
|
118
|
+
export interface OutboundActionResult {
|
|
117
119
|
success: boolean;
|
|
118
120
|
error?: string;
|
|
119
121
|
message?: string;
|
|
@@ -127,19 +129,6 @@ interface OutboundActionResult {
|
|
|
127
129
|
pendingBootstrap?: boolean;
|
|
128
130
|
/** Echoed back so consumers know which conversation to target for pointers. */
|
|
129
131
|
originConversationId?: string;
|
|
130
|
-
/** Internal: Slack DM delivery payload for the caller to dispatch.
|
|
131
|
-
* The shared startOutbound/resendOutbound functions no longer fire the
|
|
132
|
-
* delivery themselves because CLI subprocesses are sandboxed and cannot
|
|
133
|
-
* reach the gateway. The daemon HTTP route handler calls
|
|
134
|
-
* deliverVerificationSlack() after receiving this payload. */
|
|
135
|
-
_pendingSlackDm?: { userId: string; text: string; assistantId: string };
|
|
136
|
-
/** Internal: email delivery payload for the caller to dispatch (same pattern as Slack). */
|
|
137
|
-
_pendingEmail?: {
|
|
138
|
-
to: string;
|
|
139
|
-
text: string;
|
|
140
|
-
subject: string;
|
|
141
|
-
assistantId: string;
|
|
142
|
-
};
|
|
143
132
|
}
|
|
144
133
|
|
|
145
134
|
// ---------------------------------------------------------------------------
|
|
@@ -244,16 +233,12 @@ export async function startOutbound(
|
|
|
244
233
|
params.rebind,
|
|
245
234
|
originConversationId,
|
|
246
235
|
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
originConversationId,
|
|
254
|
-
);
|
|
255
|
-
} else if (channel === "email") {
|
|
256
|
-
return await startOutboundEmail(
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const spec = textChannelSpec(channel);
|
|
239
|
+
if (spec) {
|
|
240
|
+
return await startOutboundTextChannel(
|
|
241
|
+
spec,
|
|
257
242
|
params.destination,
|
|
258
243
|
assistantId,
|
|
259
244
|
channel,
|
|
@@ -265,7 +250,7 @@ export async function startOutbound(
|
|
|
265
250
|
return {
|
|
266
251
|
success: false,
|
|
267
252
|
error: "unsupported_channel",
|
|
268
|
-
message: `Outbound verification is not supported for ${channel}. Supported channels: Telegram, phone, Slack, email.`,
|
|
253
|
+
message: `Outbound verification is not supported for ${channel}. Supported channels: Telegram, phone, Slack, Discord, email.`,
|
|
269
254
|
channel,
|
|
270
255
|
};
|
|
271
256
|
}
|
|
@@ -335,7 +320,7 @@ async function startOutboundTelegram(
|
|
|
335
320
|
verificationPurpose: "guardian",
|
|
336
321
|
});
|
|
337
322
|
|
|
338
|
-
const telegramBody =
|
|
323
|
+
const telegramBody = composeVerificationText(
|
|
339
324
|
GUARDIAN_VERIFY_TEMPLATE_KEYS.TELEGRAM_CHALLENGE_REQUEST,
|
|
340
325
|
{
|
|
341
326
|
code: sessionResult.secret,
|
|
@@ -533,6 +518,38 @@ export function deliverVerificationSlack(
|
|
|
533
518
|
deliverVerificationSlackAsync(userId, text, assistantId);
|
|
534
519
|
}
|
|
535
520
|
|
|
521
|
+
// ---------------------------------------------------------------------------
|
|
522
|
+
// Discord delivery helper
|
|
523
|
+
// ---------------------------------------------------------------------------
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Deliver a verification Discord DM via the Discord REST API directly.
|
|
527
|
+
* Fire-and-forget wrapper for use in the daemon process (HTTP route handlers).
|
|
528
|
+
*
|
|
529
|
+
* The recipient is a Discord *user* snowflake. Discord has no route that looks
|
|
530
|
+
* up an existing DM by recipient, so the channel is opened on the way through
|
|
531
|
+
* (see `openDiscordDmChannel`), and a user with DMs closed to server members
|
|
532
|
+
* fails here rather than at the gate.
|
|
533
|
+
*/
|
|
534
|
+
export function deliverVerificationDiscord(
|
|
535
|
+
userId: string,
|
|
536
|
+
text: string,
|
|
537
|
+
assistantId: string,
|
|
538
|
+
): void {
|
|
539
|
+
(async () => {
|
|
540
|
+
try {
|
|
541
|
+
const channelId = await openDiscordDmChannel(userId);
|
|
542
|
+
await sendDiscordReply({ channelId }, text);
|
|
543
|
+
log.info({ userId, assistantId }, "Verification Discord DM delivered");
|
|
544
|
+
} catch (err) {
|
|
545
|
+
log.error(
|
|
546
|
+
{ err, userId, assistantId },
|
|
547
|
+
"Failed to deliver verification Discord DM",
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
})();
|
|
551
|
+
}
|
|
552
|
+
|
|
536
553
|
// ---------------------------------------------------------------------------
|
|
537
554
|
// Email delivery helper
|
|
538
555
|
// ---------------------------------------------------------------------------
|
|
@@ -610,106 +627,196 @@ export function deliverVerificationEmail(
|
|
|
610
627
|
})();
|
|
611
628
|
}
|
|
612
629
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
630
|
+
/**
|
|
631
|
+
* The per-channel differences between the text-channel verification starts.
|
|
632
|
+
*
|
|
633
|
+
* Slack, Discord and email run the identical sequence: refuse without a
|
|
634
|
+
* destination, refuse when a guardian is already bound, check the destination
|
|
635
|
+
* rate window, mint a session, compose from a template, stamp the delivery,
|
|
636
|
+
* send. The spec carries only the per-channel fields; the sequence itself
|
|
637
|
+
* lives once in `startOutboundTextChannel`.
|
|
638
|
+
*
|
|
639
|
+
* Telegram and voice are deliberately absent. Telegram forks on whether the
|
|
640
|
+
* destination is a chat id or a handle, and a handle mints a bootstrap session
|
|
641
|
+
* carrying no code at all; voice normalizes a phone number and places a call
|
|
642
|
+
* rather than composing a message. Folding either in would mean a spec field
|
|
643
|
+
* that only one channel ever sets.
|
|
644
|
+
*/
|
|
645
|
+
interface TextChannelVerificationSpec {
|
|
646
|
+
/** Rejection copy when the caller supplied no destination. */
|
|
647
|
+
missingDestination: string;
|
|
648
|
+
/** Rejection copy when the destination's rate window is exhausted. */
|
|
649
|
+
rateLimited: string;
|
|
650
|
+
/** Canonical form of the destination, for rate-limit keying and delivery. */
|
|
651
|
+
normalizeDestination?: (destination: string) => string;
|
|
652
|
+
/**
|
|
653
|
+
* Identity the consume path will require.
|
|
654
|
+
*
|
|
655
|
+
* Where a channel sets `expectedChatId`, it does no work: `checkIdentityMatch`
|
|
656
|
+
* requires the `expectedExternalUserId` match whenever both are set, and the
|
|
657
|
+
* resend path resolves its destination from `destinationAddress` first. See
|
|
658
|
+
* LUM-3110 for the wider question of session fields that record something
|
|
659
|
+
* nothing reads.
|
|
660
|
+
*/
|
|
661
|
+
sessionIdentity: (destination: string) => {
|
|
662
|
+
expectedExternalUserId: string;
|
|
663
|
+
expectedChatId?: string;
|
|
664
|
+
};
|
|
665
|
+
challengeTemplateKey: TextVerifyTemplateKey;
|
|
666
|
+
resendTemplateKey: TextVerifyTemplateKey;
|
|
667
|
+
/** Fire-and-forget delivery. Throwing is the transport's business, not this file's. */
|
|
668
|
+
deliver: (destination: string, text: string, assistantId: string) => void;
|
|
669
|
+
}
|
|
628
670
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
671
|
+
const TEXT_CHANNEL_VERIFICATION: Partial<
|
|
672
|
+
Record<ChannelId, TextChannelVerificationSpec>
|
|
673
|
+
> = {
|
|
674
|
+
slack: {
|
|
675
|
+
missingDestination:
|
|
676
|
+
"A Slack user ID is required for outbound Slack verification.",
|
|
677
|
+
rateLimited:
|
|
678
|
+
"Too many verification attempts to this Slack user. Please try again later.",
|
|
679
|
+
sessionIdentity: (destination) => ({
|
|
680
|
+
expectedExternalUserId: destination,
|
|
681
|
+
expectedChatId: destination,
|
|
682
|
+
}),
|
|
683
|
+
challengeTemplateKey: GUARDIAN_VERIFY_TEMPLATE_KEYS.SLACK_CHALLENGE_REQUEST,
|
|
684
|
+
resendTemplateKey: GUARDIAN_VERIFY_TEMPLATE_KEYS.SLACK_RESEND,
|
|
685
|
+
deliver: deliverVerificationSlack,
|
|
686
|
+
},
|
|
687
|
+
discord: {
|
|
688
|
+
missingDestination:
|
|
689
|
+
"A Discord user ID is required for outbound Discord verification.",
|
|
690
|
+
rateLimited:
|
|
691
|
+
"Too many verification attempts to this Discord user. Please try again later.",
|
|
692
|
+
// A Discord user snowflake is the session's only expected identity. There
|
|
693
|
+
// is no chat id to record: the DM channel does not exist until it is
|
|
694
|
+
// opened, and the guild channel the requester was seen in is a room rather
|
|
695
|
+
// than a person, so binding to it would accept the code from anyone
|
|
696
|
+
// standing in it.
|
|
697
|
+
sessionIdentity: (destination) => ({
|
|
698
|
+
expectedExternalUserId: destination,
|
|
699
|
+
}),
|
|
700
|
+
challengeTemplateKey:
|
|
701
|
+
GUARDIAN_VERIFY_TEMPLATE_KEYS.DISCORD_CHALLENGE_REQUEST,
|
|
702
|
+
resendTemplateKey: GUARDIAN_VERIFY_TEMPLATE_KEYS.DISCORD_RESEND,
|
|
703
|
+
deliver: deliverVerificationDiscord,
|
|
704
|
+
},
|
|
705
|
+
email: {
|
|
706
|
+
missingDestination:
|
|
707
|
+
"An email address is required for outbound email verification.",
|
|
708
|
+
rateLimited:
|
|
709
|
+
"Too many verification attempts to this email address. Please try again later.",
|
|
710
|
+
normalizeDestination: (destination) => destination.trim().toLowerCase(),
|
|
711
|
+
sessionIdentity: (destination) => ({
|
|
712
|
+
expectedExternalUserId: destination,
|
|
713
|
+
expectedChatId: destination,
|
|
714
|
+
}),
|
|
715
|
+
challengeTemplateKey: GUARDIAN_VERIFY_TEMPLATE_KEYS.EMAIL_CHALLENGE_REQUEST,
|
|
716
|
+
resendTemplateKey: GUARDIAN_VERIFY_TEMPLATE_KEYS.EMAIL_RESEND,
|
|
717
|
+
deliver: (to, text, assistantId) =>
|
|
718
|
+
deliverVerificationEmail(
|
|
719
|
+
to,
|
|
720
|
+
text,
|
|
721
|
+
EMAIL_VERIFICATION_SUBJECT,
|
|
722
|
+
assistantId,
|
|
723
|
+
),
|
|
724
|
+
},
|
|
725
|
+
};
|
|
639
726
|
|
|
640
|
-
|
|
727
|
+
/**
|
|
728
|
+
* The spec for a channel, or undefined when it has none.
|
|
729
|
+
*
|
|
730
|
+
* An own-property check rather than a bare index read: `channel` reaches here
|
|
731
|
+
* as a plain string, so `"constructor"`, `"toString"` and `"__proto__"` would
|
|
732
|
+
* otherwise resolve to inherited values, pass a truthy guard, and throw on the
|
|
733
|
+
* first spec field instead of falling through to `unsupported_channel`. Same
|
|
734
|
+
* fail-closed shape as `resolveCapabilities`.
|
|
735
|
+
*/
|
|
736
|
+
function textChannelSpec(
|
|
737
|
+
channel: ChannelId,
|
|
738
|
+
): TextChannelVerificationSpec | undefined {
|
|
739
|
+
return Object.prototype.hasOwnProperty.call(
|
|
740
|
+
TEXT_CHANNEL_VERIFICATION,
|
|
641
741
|
channel,
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
return {
|
|
647
|
-
success: false,
|
|
648
|
-
error: "rate_limited",
|
|
649
|
-
message:
|
|
650
|
-
"Too many verification attempts to this Slack user. Please try again later.",
|
|
651
|
-
channel,
|
|
652
|
-
};
|
|
653
|
-
}
|
|
742
|
+
)
|
|
743
|
+
? TEXT_CHANNEL_VERIFICATION[channel]
|
|
744
|
+
: undefined;
|
|
745
|
+
}
|
|
654
746
|
|
|
655
|
-
|
|
747
|
+
/**
|
|
748
|
+
* Mint a session, compose the message, stamp the delivery, and send it.
|
|
749
|
+
*
|
|
750
|
+
* Shared by the start and resend paths, which differ only in the template and
|
|
751
|
+
* in how the send counters advance.
|
|
752
|
+
*/
|
|
753
|
+
interface MintedSend {
|
|
754
|
+
sessionId: string;
|
|
755
|
+
secret: string;
|
|
756
|
+
expiresAt: number;
|
|
757
|
+
nextResendAt: number;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
async function mintAndSend(params: {
|
|
761
|
+
spec: TextChannelVerificationSpec;
|
|
762
|
+
channel: ChannelId;
|
|
763
|
+
destination: string;
|
|
764
|
+
templateKey: TextVerifyTemplateKey;
|
|
765
|
+
sendCount: number;
|
|
766
|
+
assistantId: string;
|
|
767
|
+
}): Promise<MintedSend> {
|
|
768
|
+
const { spec, channel, destination, templateKey, sendCount, assistantId } =
|
|
769
|
+
params;
|
|
770
|
+
|
|
771
|
+
const session = await createOutboundSession({
|
|
656
772
|
channel,
|
|
657
|
-
|
|
658
|
-
expectedChatId: destination,
|
|
773
|
+
...spec.sessionIdentity(destination),
|
|
659
774
|
identityBindingStatus: "bound",
|
|
660
775
|
destinationAddress: destination,
|
|
661
776
|
verificationPurpose: "guardian",
|
|
662
777
|
});
|
|
663
778
|
|
|
664
|
-
const
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
expiresInMinutes: Math.floor(SESSION_TTL_SECONDS / 60),
|
|
669
|
-
},
|
|
670
|
-
);
|
|
779
|
+
const body = composeVerificationText(templateKey, {
|
|
780
|
+
code: session.secret,
|
|
781
|
+
expiresInMinutes: Math.floor(SESSION_TTL_SECONDS / 60),
|
|
782
|
+
});
|
|
671
783
|
|
|
672
784
|
const now = Date.now();
|
|
673
785
|
const nextResendAt = now + RESEND_COOLDOWN_MS;
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
await updateSessionDelivery(
|
|
677
|
-
sessionResult.sessionId,
|
|
678
|
-
now,
|
|
679
|
-
sendCount,
|
|
680
|
-
nextResendAt,
|
|
681
|
-
);
|
|
786
|
+
await updateSessionDelivery(session.sessionId, now, sendCount, nextResendAt);
|
|
787
|
+
spec.deliver(destination, body, assistantId);
|
|
682
788
|
|
|
683
789
|
return {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
expiresAt: sessionResult.expiresAt,
|
|
790
|
+
sessionId: session.sessionId,
|
|
791
|
+
secret: session.secret,
|
|
792
|
+
expiresAt: session.expiresAt,
|
|
688
793
|
nextResendAt,
|
|
689
|
-
sendCount,
|
|
690
|
-
channel,
|
|
691
|
-
originConversationId,
|
|
692
|
-
_pendingSlackDm: { userId: destination, text: slackBody, assistantId },
|
|
693
794
|
};
|
|
694
795
|
}
|
|
695
796
|
|
|
696
|
-
|
|
697
|
-
|
|
797
|
+
/**
|
|
798
|
+
* Start outbound guardian verification on a channel that reaches its
|
|
799
|
+
* destination with one text message.
|
|
800
|
+
*/
|
|
801
|
+
async function startOutboundTextChannel(
|
|
802
|
+
spec: TextChannelVerificationSpec,
|
|
803
|
+
rawDestination: string | undefined,
|
|
698
804
|
assistantId: string,
|
|
699
805
|
channel: ChannelId,
|
|
700
806
|
rebind?: boolean,
|
|
701
807
|
originConversationId?: string,
|
|
702
808
|
): Promise<OutboundActionResult> {
|
|
703
|
-
if (!
|
|
809
|
+
if (!rawDestination) {
|
|
704
810
|
return {
|
|
705
811
|
success: false,
|
|
706
812
|
error: "missing_destination",
|
|
707
|
-
message:
|
|
813
|
+
message: spec.missingDestination,
|
|
708
814
|
channel,
|
|
709
815
|
};
|
|
710
816
|
}
|
|
711
|
-
|
|
712
|
-
|
|
817
|
+
const destination = spec.normalizeDestination
|
|
818
|
+
? spec.normalizeDestination(rawDestination)
|
|
819
|
+
: rawDestination;
|
|
713
820
|
|
|
714
821
|
const alreadyBound = await isGuardianBoundForChannel(channel);
|
|
715
822
|
if (alreadyBound && !rebind) {
|
|
@@ -724,62 +831,36 @@ async function startOutboundEmail(
|
|
|
724
831
|
|
|
725
832
|
const recentSendCount = await countRecentSendsToDestination(
|
|
726
833
|
channel,
|
|
727
|
-
|
|
834
|
+
destination,
|
|
728
835
|
DESTINATION_RATE_WINDOW_MS,
|
|
729
836
|
);
|
|
730
837
|
if (recentSendCount >= MAX_SENDS_PER_DESTINATION_WINDOW) {
|
|
731
838
|
return {
|
|
732
839
|
success: false,
|
|
733
840
|
error: "rate_limited",
|
|
734
|
-
message:
|
|
735
|
-
"Too many verification attempts to this email address. Please try again later.",
|
|
841
|
+
message: spec.rateLimited,
|
|
736
842
|
channel,
|
|
737
843
|
};
|
|
738
844
|
}
|
|
739
845
|
|
|
740
|
-
const
|
|
846
|
+
const sent = await mintAndSend({
|
|
847
|
+
spec,
|
|
741
848
|
channel,
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
verificationPurpose: "guardian",
|
|
849
|
+
destination,
|
|
850
|
+
templateKey: spec.challengeTemplateKey,
|
|
851
|
+
sendCount: 1,
|
|
852
|
+
assistantId,
|
|
747
853
|
});
|
|
748
854
|
|
|
749
|
-
const emailBody = composeVerificationEmail(
|
|
750
|
-
GUARDIAN_VERIFY_TEMPLATE_KEYS.EMAIL_CHALLENGE_REQUEST,
|
|
751
|
-
{
|
|
752
|
-
code: sessionResult.secret,
|
|
753
|
-
expiresInMinutes: Math.floor(SESSION_TTL_SECONDS / 60),
|
|
754
|
-
},
|
|
755
|
-
);
|
|
756
|
-
|
|
757
|
-
const now = Date.now();
|
|
758
|
-
const nextResendAt = now + RESEND_COOLDOWN_MS;
|
|
759
|
-
const sendCount = 1;
|
|
760
|
-
|
|
761
|
-
await updateSessionDelivery(
|
|
762
|
-
sessionResult.sessionId,
|
|
763
|
-
now,
|
|
764
|
-
sendCount,
|
|
765
|
-
nextResendAt,
|
|
766
|
-
);
|
|
767
|
-
|
|
768
855
|
return {
|
|
769
856
|
success: true,
|
|
770
|
-
verificationSessionId:
|
|
771
|
-
secret:
|
|
772
|
-
expiresAt:
|
|
773
|
-
nextResendAt,
|
|
774
|
-
sendCount,
|
|
857
|
+
verificationSessionId: sent.sessionId,
|
|
858
|
+
secret: sent.secret,
|
|
859
|
+
expiresAt: sent.expiresAt,
|
|
860
|
+
nextResendAt: sent.nextResendAt,
|
|
861
|
+
sendCount: 1,
|
|
775
862
|
channel,
|
|
776
863
|
originConversationId,
|
|
777
|
-
_pendingEmail: {
|
|
778
|
-
to: normalizedEmail,
|
|
779
|
-
text: emailBody,
|
|
780
|
-
subject: EMAIL_VERIFICATION_SUBJECT,
|
|
781
|
-
assistantId,
|
|
782
|
-
},
|
|
783
864
|
};
|
|
784
865
|
}
|
|
785
866
|
|
|
@@ -794,7 +875,13 @@ export async function resendOutbound(
|
|
|
794
875
|
const channel = params.channel;
|
|
795
876
|
const originConversationId = params.originConversationId;
|
|
796
877
|
|
|
797
|
-
|
|
878
|
+
// Scoped to the guardian's own flow. A channel can carry a live session per
|
|
879
|
+
// person verifying, so an unscoped lookup returns whoever started most
|
|
880
|
+
// recently, which on a busy channel is a requester rather than the guardian
|
|
881
|
+
// this resend is for.
|
|
882
|
+
const session = await findActiveSession(channel, {
|
|
883
|
+
verificationPurpose: "guardian",
|
|
884
|
+
});
|
|
798
885
|
if (!session) {
|
|
799
886
|
return {
|
|
800
887
|
success: false,
|
|
@@ -833,14 +920,15 @@ export async function resendOutbound(
|
|
|
833
920
|
};
|
|
834
921
|
}
|
|
835
922
|
|
|
836
|
-
const
|
|
923
|
+
const destination =
|
|
837
924
|
session.destinationAddress ??
|
|
838
925
|
session.expectedPhoneE164 ??
|
|
839
926
|
session.expectedChatId;
|
|
840
|
-
|
|
927
|
+
|
|
928
|
+
if (destination) {
|
|
841
929
|
const recentDestSends = await countRecentSendsToDestination(
|
|
842
930
|
channel,
|
|
843
|
-
|
|
931
|
+
destination,
|
|
844
932
|
DESTINATION_RATE_WINDOW_MS,
|
|
845
933
|
);
|
|
846
934
|
if (recentDestSends >= MAX_SENDS_PER_DESTINATION_WINDOW) {
|
|
@@ -854,10 +942,6 @@ export async function resendOutbound(
|
|
|
854
942
|
}
|
|
855
943
|
}
|
|
856
944
|
|
|
857
|
-
const destination =
|
|
858
|
-
session.destinationAddress ??
|
|
859
|
-
session.expectedPhoneE164 ??
|
|
860
|
-
session.expectedChatId;
|
|
861
945
|
if (!destination) {
|
|
862
946
|
return {
|
|
863
947
|
success: false,
|
|
@@ -876,7 +960,7 @@ export async function resendOutbound(
|
|
|
876
960
|
verificationPurpose: "guardian",
|
|
877
961
|
});
|
|
878
962
|
|
|
879
|
-
const telegramBody =
|
|
963
|
+
const telegramBody = composeVerificationText(
|
|
880
964
|
GUARDIAN_VERIFY_TEMPLATE_KEYS.TELEGRAM_RESEND,
|
|
881
965
|
{
|
|
882
966
|
code: newSession.secret,
|
|
@@ -941,95 +1025,35 @@ export async function resendOutbound(
|
|
|
941
1025
|
channel,
|
|
942
1026
|
originConversationId,
|
|
943
1027
|
};
|
|
944
|
-
}
|
|
945
|
-
const newSession = await createOutboundSession({
|
|
946
|
-
channel,
|
|
947
|
-
expectedExternalUserId: destination,
|
|
948
|
-
expectedChatId: destination,
|
|
949
|
-
identityBindingStatus: "bound",
|
|
950
|
-
destinationAddress: destination,
|
|
951
|
-
verificationPurpose: "guardian",
|
|
952
|
-
});
|
|
953
|
-
|
|
954
|
-
const slackBody = composeVerificationSlack(
|
|
955
|
-
GUARDIAN_VERIFY_TEMPLATE_KEYS.SLACK_RESEND,
|
|
956
|
-
{
|
|
957
|
-
code: newSession.secret,
|
|
958
|
-
expiresInMinutes: Math.floor(SESSION_TTL_SECONDS / 60),
|
|
959
|
-
},
|
|
960
|
-
);
|
|
1028
|
+
}
|
|
961
1029
|
|
|
962
|
-
|
|
1030
|
+
const spec = textChannelSpec(channel);
|
|
1031
|
+
if (spec) {
|
|
963
1032
|
const newSendCount = currentSendCount + 1;
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
await updateSessionDelivery(
|
|
967
|
-
newSession.sessionId,
|
|
968
|
-
now,
|
|
969
|
-
newSendCount,
|
|
970
|
-
nextResendAt,
|
|
971
|
-
);
|
|
972
|
-
|
|
973
|
-
return {
|
|
974
|
-
success: true,
|
|
975
|
-
verificationSessionId: newSession.sessionId,
|
|
976
|
-
secret: newSession.secret,
|
|
977
|
-
nextResendAt,
|
|
978
|
-
sendCount: newSendCount,
|
|
979
|
-
channel,
|
|
980
|
-
originConversationId,
|
|
981
|
-
_pendingSlackDm: { userId: destination, text: slackBody, assistantId },
|
|
982
|
-
};
|
|
983
|
-
} else if (channel === "email") {
|
|
984
|
-
const newSession = await createOutboundSession({
|
|
1033
|
+
const sent = await mintAndSend({
|
|
1034
|
+
spec,
|
|
985
1035
|
channel,
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
verificationPurpose: "guardian",
|
|
1036
|
+
destination,
|
|
1037
|
+
templateKey: spec.resendTemplateKey,
|
|
1038
|
+
sendCount: newSendCount,
|
|
1039
|
+
assistantId,
|
|
991
1040
|
});
|
|
992
1041
|
|
|
993
|
-
const emailBody = composeVerificationEmail(
|
|
994
|
-
GUARDIAN_VERIFY_TEMPLATE_KEYS.EMAIL_RESEND,
|
|
995
|
-
{
|
|
996
|
-
code: newSession.secret,
|
|
997
|
-
expiresInMinutes: Math.floor(SESSION_TTL_SECONDS / 60),
|
|
998
|
-
},
|
|
999
|
-
);
|
|
1000
|
-
|
|
1001
|
-
const now = Date.now();
|
|
1002
|
-
const newSendCount = currentSendCount + 1;
|
|
1003
|
-
const nextResendAt = now + RESEND_COOLDOWN_MS;
|
|
1004
|
-
|
|
1005
|
-
await updateSessionDelivery(
|
|
1006
|
-
newSession.sessionId,
|
|
1007
|
-
now,
|
|
1008
|
-
newSendCount,
|
|
1009
|
-
nextResendAt,
|
|
1010
|
-
);
|
|
1011
|
-
|
|
1012
1042
|
return {
|
|
1013
1043
|
success: true,
|
|
1014
|
-
verificationSessionId:
|
|
1015
|
-
secret:
|
|
1016
|
-
nextResendAt,
|
|
1044
|
+
verificationSessionId: sent.sessionId,
|
|
1045
|
+
secret: sent.secret,
|
|
1046
|
+
nextResendAt: sent.nextResendAt,
|
|
1017
1047
|
sendCount: newSendCount,
|
|
1018
1048
|
channel,
|
|
1019
1049
|
originConversationId,
|
|
1020
|
-
_pendingEmail: {
|
|
1021
|
-
to: destination,
|
|
1022
|
-
text: emailBody,
|
|
1023
|
-
subject: EMAIL_VERIFICATION_SUBJECT,
|
|
1024
|
-
assistantId,
|
|
1025
|
-
},
|
|
1026
1050
|
};
|
|
1027
1051
|
}
|
|
1028
1052
|
|
|
1029
1053
|
return {
|
|
1030
1054
|
success: false,
|
|
1031
1055
|
error: "unsupported_channel",
|
|
1032
|
-
message: `Resend is only supported for Telegram, phone, Slack, and email. Got: ${channel}`,
|
|
1056
|
+
message: `Resend is only supported for Telegram, phone, Slack, Discord, and email. Got: ${channel}`,
|
|
1033
1057
|
channel,
|
|
1034
1058
|
};
|
|
1035
1059
|
}
|
|
@@ -1043,7 +1067,11 @@ export async function cancelOutbound(
|
|
|
1043
1067
|
): Promise<OutboundActionResult> {
|
|
1044
1068
|
const channel = params.channel;
|
|
1045
1069
|
|
|
1046
|
-
|
|
1070
|
+
// Scoped the same way as resend: cancelling the guardian's verification must
|
|
1071
|
+
// not revoke a requester's live session.
|
|
1072
|
+
const session = await findActiveSession(channel, {
|
|
1073
|
+
verificationPurpose: "guardian",
|
|
1074
|
+
});
|
|
1047
1075
|
if (!session) {
|
|
1048
1076
|
return {
|
|
1049
1077
|
success: false,
|