@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
|
@@ -12,6 +12,10 @@ import { credentialKey } from "../security/credential-key.js";
|
|
|
12
12
|
import { getSecureKeyResultAsync } from "../security/secure-keys.js";
|
|
13
13
|
import { getTelegramBotUsername } from "../telegram/bot-username.js";
|
|
14
14
|
import { getLogger } from "../util/logger.js";
|
|
15
|
+
import {
|
|
16
|
+
MANUAL_TOKEN_PROVIDERS,
|
|
17
|
+
manualTokenProvider,
|
|
18
|
+
} from "./manual-token-providers.js";
|
|
15
19
|
import {
|
|
16
20
|
createConnection,
|
|
17
21
|
deleteConnection,
|
|
@@ -135,69 +139,30 @@ export async function syncManualTokenConnection(
|
|
|
135
139
|
resolvedAccountInfo,
|
|
136
140
|
);
|
|
137
141
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
);
|
|
143
|
-
const webhookSecretResult = await getSecureKeyResultAsync(
|
|
144
|
-
credentialKey("telegram", "webhook_secret"),
|
|
145
|
-
);
|
|
146
|
-
if (botTokenResult.unreachable || webhookSecretResult.unreachable) {
|
|
147
|
-
log.warn(
|
|
148
|
-
"Skipping telegram manual-token reconciliation — credential backend unreachable",
|
|
149
|
-
);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
if (botTokenResult.value && webhookSecretResult.value) {
|
|
153
|
-
await ensureManualTokenConnection(provider, accountInfoToStore);
|
|
154
|
-
} else {
|
|
155
|
-
removeManualTokenConnection(provider);
|
|
156
|
-
}
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
case "slack_channel": {
|
|
161
|
-
const botTokenResult = await getSecureKeyResultAsync(
|
|
162
|
-
credentialKey("slack_channel", "bot_token"),
|
|
163
|
-
);
|
|
164
|
-
const appTokenResult = await getSecureKeyResultAsync(
|
|
165
|
-
credentialKey("slack_channel", "app_token"),
|
|
166
|
-
);
|
|
167
|
-
if (botTokenResult.unreachable || appTokenResult.unreachable) {
|
|
168
|
-
log.warn(
|
|
169
|
-
"Skipping slack_channel manual-token reconciliation — credential backend unreachable",
|
|
170
|
-
);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
if (botTokenResult.value && appTokenResult.value) {
|
|
174
|
-
await ensureManualTokenConnection(provider, accountInfoToStore);
|
|
175
|
-
} else {
|
|
176
|
-
removeManualTokenConnection(provider);
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
142
|
+
const spec = manualTokenProvider(provider);
|
|
143
|
+
if (!spec) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
180
146
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
147
|
+
// Every field must be present and readable. An unreachable backend is not
|
|
148
|
+
// evidence a credential was removed, so the row is left as it stands rather
|
|
149
|
+
// than being read as a disconnection.
|
|
150
|
+
const results = await Promise.all(
|
|
151
|
+
spec.fields.map((field) =>
|
|
152
|
+
getSecureKeyResultAsync(credentialKey(provider, field)),
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
if (results.some((r) => r.unreachable)) {
|
|
156
|
+
log.warn(
|
|
157
|
+
`Skipping ${provider} manual-token reconciliation: credential backend unreachable`,
|
|
158
|
+
);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
198
161
|
|
|
199
|
-
|
|
200
|
-
|
|
162
|
+
if (results.every((r) => r.value)) {
|
|
163
|
+
await ensureManualTokenConnection(provider, accountInfoToStore);
|
|
164
|
+
} else {
|
|
165
|
+
removeManualTokenConnection(provider);
|
|
201
166
|
}
|
|
202
167
|
}
|
|
203
168
|
|
|
@@ -214,7 +179,7 @@ export async function syncManualTokenConnection(
|
|
|
214
179
|
* connection row.
|
|
215
180
|
*/
|
|
216
181
|
export async function backfillManualTokenConnections(): Promise<void> {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
182
|
+
for (const provider of Object.keys(MANUAL_TOKEN_PROVIDERS)) {
|
|
183
|
+
await syncManualTokenConnection(provider);
|
|
184
|
+
}
|
|
220
185
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Providers whose credentials are pasted in rather than granted through a
|
|
3
|
+
* browser flow, and what each one stores.
|
|
4
|
+
*
|
|
5
|
+
* Two questions are answered together because they are the same fact seen from
|
|
6
|
+
* two sides, and answering them in separate tables lets them drift: which
|
|
7
|
+
* fields must be present for the provider to count as configured
|
|
8
|
+
* (reconciliation), and which single field an API request authenticates with
|
|
9
|
+
* (token resolution). Slack stores an app token and Telegram a webhook secret,
|
|
10
|
+
* and neither authenticates a request.
|
|
11
|
+
*
|
|
12
|
+
* `accessField` is named rather than taken as the first of `fields`, so
|
|
13
|
+
* reordering that list cannot silently change which secret gets sent.
|
|
14
|
+
*
|
|
15
|
+
* Channel bots are keyed off the shared channel contract, so adding a channel
|
|
16
|
+
* does not mean remembering this file exists. `sanity` is not in that contract
|
|
17
|
+
* because it is a user's own API token: manual to enter, but not a bot and not
|
|
18
|
+
* a channel.
|
|
19
|
+
*
|
|
20
|
+
* The gateway declares the same field sets for its own reading of these
|
|
21
|
+
* credentials (`gateway/src/credential-reader.ts`). One declaration serving
|
|
22
|
+
* both is worth doing and needs the specs hoisted into a shared package.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { CHANNEL_BOT_PROVIDER } from "@vellumai/service-contracts/channels";
|
|
26
|
+
|
|
27
|
+
export interface ManualTokenProviderSpec {
|
|
28
|
+
/** Every field that must be present for the provider to count as connected. */
|
|
29
|
+
fields: readonly string[];
|
|
30
|
+
/** The one field an API request authenticates with. */
|
|
31
|
+
accessField: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const MANUAL_TOKEN_PROVIDERS: Record<string, ManualTokenProviderSpec> = {
|
|
35
|
+
[CHANNEL_BOT_PROVIDER.slack]: {
|
|
36
|
+
fields: ["bot_token", "app_token"],
|
|
37
|
+
accessField: "bot_token",
|
|
38
|
+
},
|
|
39
|
+
[CHANNEL_BOT_PROVIDER.discord]: {
|
|
40
|
+
fields: ["bot_token"],
|
|
41
|
+
accessField: "bot_token",
|
|
42
|
+
},
|
|
43
|
+
[CHANNEL_BOT_PROVIDER.telegram]: {
|
|
44
|
+
fields: ["bot_token", "webhook_secret"],
|
|
45
|
+
accessField: "bot_token",
|
|
46
|
+
},
|
|
47
|
+
sanity: { fields: ["api_token"], accessField: "api_token" },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The spec for a provider, or undefined when it is not a manual-token one.
|
|
52
|
+
*
|
|
53
|
+
* Own-property lookup so an inherited key (`constructor`, `__proto__`) reads
|
|
54
|
+
* as absent rather than returning a function.
|
|
55
|
+
*/
|
|
56
|
+
export function manualTokenProvider(
|
|
57
|
+
provider: string,
|
|
58
|
+
): ManualTokenProviderSpec | undefined {
|
|
59
|
+
return Object.prototype.hasOwnProperty.call(MANUAL_TOKEN_PROVIDERS, provider)
|
|
60
|
+
? MANUAL_TOKEN_PROVIDERS[provider]
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
@@ -18,6 +18,8 @@ import type { OAuthProviderRow } from "./oauth-store.js";
|
|
|
18
18
|
export type SerializedProvider = ReturnType<typeof serializeProvider> &
|
|
19
19
|
Record<string, unknown>;
|
|
20
20
|
|
|
21
|
+
import { isChannelBotProvider } from "@vellumai/service-contracts/channels";
|
|
22
|
+
|
|
21
23
|
/**
|
|
22
24
|
* Lightweight summary projection of an OAuth provider, suitable for API
|
|
23
25
|
* list responses where full detail is not needed. All keys are snake_case
|
|
@@ -34,6 +36,16 @@ export interface SerializedProviderSummary {
|
|
|
34
36
|
supports_managed_mode: boolean;
|
|
35
37
|
managed_service_is_paid: boolean;
|
|
36
38
|
feature_flag: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Which sense of "connected" this provider represents: `assistant` for a bot
|
|
41
|
+
* credential people reach the assistant through, `user` for a grant letting
|
|
42
|
+
* it act as the person who authorized it.
|
|
43
|
+
*
|
|
44
|
+
* Derived rather than stored, because the provider key does not say: `slack`
|
|
45
|
+
* and `discord` name the user integration while their bots take a `_channel`
|
|
46
|
+
* suffix, yet `telegram` is the bot.
|
|
47
|
+
*/
|
|
48
|
+
acts_as: "user" | "assistant";
|
|
37
49
|
}
|
|
38
50
|
|
|
39
51
|
/**
|
|
@@ -152,5 +164,6 @@ export function serializeProviderSummary(
|
|
|
152
164
|
supports_managed_mode: !!row.managedServiceConfigKey,
|
|
153
165
|
managed_service_is_paid: !!row.managedServiceIsPaid,
|
|
154
166
|
feature_flag: row.featureFlag ?? null,
|
|
167
|
+
acts_as: isChannelBotProvider(row.provider) ? "assistant" : "user",
|
|
155
168
|
};
|
|
156
169
|
}
|
|
@@ -137,6 +137,18 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
137
137
|
headerName: "Authorization",
|
|
138
138
|
valuePrefix: "Bearer ",
|
|
139
139
|
},
|
|
140
|
+
{
|
|
141
|
+
hostPattern: "tasks.googleapis.com",
|
|
142
|
+
injectionType: "header",
|
|
143
|
+
headerName: "Authorization",
|
|
144
|
+
valuePrefix: "Bearer ",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
hostPattern: "calendar.googleapis.com",
|
|
148
|
+
injectionType: "header",
|
|
149
|
+
headerName: "Authorization",
|
|
150
|
+
valuePrefix: "Bearer ",
|
|
151
|
+
},
|
|
140
152
|
],
|
|
141
153
|
revokeUrl: "https://oauth2.googleapis.com/revoke",
|
|
142
154
|
revokeBodyTemplate: { token: "{access_token}" },
|
|
@@ -155,7 +167,8 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
155
167
|
description: "Workspace messaging",
|
|
156
168
|
dashboardUrl: "https://api.slack.com/apps",
|
|
157
169
|
clientIdPlaceholder: null,
|
|
158
|
-
logoUrl:
|
|
170
|
+
logoUrl:
|
|
171
|
+
"https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/slack/default.svg",
|
|
159
172
|
defaultScopes: [
|
|
160
173
|
"channels:join",
|
|
161
174
|
"channels:read",
|
|
@@ -442,16 +455,15 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
442
455
|
pingUrl: "https://discord.com/api/v10/users/@me",
|
|
443
456
|
baseUrl: "https://discord.com/api/v10",
|
|
444
457
|
displayLabel: "Discord",
|
|
445
|
-
|
|
458
|
+
// Your servers, not their contents. These scopes reach the guild list and
|
|
459
|
+
// your membership in one; reading messages is not among them. Discord
|
|
460
|
+
// documents `messages.read` as local RPC only, so requesting it would put
|
|
461
|
+
// a permission on the consent screen that grants nothing here.
|
|
462
|
+
description: "Your servers and profile",
|
|
446
463
|
dashboardUrl: "https://discord.com/developers/applications",
|
|
447
464
|
clientIdPlaceholder: null,
|
|
448
465
|
logoUrl: "https://cdn.simpleicons.org/discord",
|
|
449
|
-
defaultScopes: [
|
|
450
|
-
"identify",
|
|
451
|
-
"guilds",
|
|
452
|
-
"guilds.members.read",
|
|
453
|
-
"messages.read",
|
|
454
|
-
],
|
|
466
|
+
defaultScopes: ["identify", "guilds", "guilds.members.read"],
|
|
455
467
|
availableScopes:
|
|
456
468
|
"https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes",
|
|
457
469
|
loopbackPort: 17326,
|
|
@@ -699,7 +711,8 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
699
711
|
dashboardUrl:
|
|
700
712
|
"https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade",
|
|
701
713
|
clientIdPlaceholder: "Application (client) ID from Azure portal",
|
|
702
|
-
logoUrl:
|
|
714
|
+
logoUrl:
|
|
715
|
+
"https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/microsoft-outlook/default.svg",
|
|
703
716
|
defaultScopes: [
|
|
704
717
|
"openid",
|
|
705
718
|
"profile",
|
|
@@ -714,7 +727,15 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
714
727
|
],
|
|
715
728
|
availableScopes:
|
|
716
729
|
"https://learn.microsoft.com/en-us/graph/permissions-reference",
|
|
717
|
-
|
|
730
|
+
// `select_account`, not `consent`: the Microsoft identity platform accepts
|
|
731
|
+
// a single prompt value, and `consent` honours an existing session cookie —
|
|
732
|
+
// it re-asks for consent but never for *which* account, so a user who
|
|
733
|
+
// already signed in cannot connect a second mailbox. `select_account`
|
|
734
|
+
// always shows the account picker with its "Use another account" option.
|
|
735
|
+
// Consent is still collected for an account that has not granted it, and
|
|
736
|
+
// refresh tokens come from the `offline_access` scope above, so nothing is
|
|
737
|
+
// lost by dropping `consent`.
|
|
738
|
+
authorizeParams: { prompt: "select_account" },
|
|
718
739
|
tokenEndpointAuthMethod: "client_secret_post",
|
|
719
740
|
loopbackPort: 17334,
|
|
720
741
|
managedServiceConfigKey: "outlook-oauth",
|
|
@@ -745,7 +766,8 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
745
766
|
dashboardUrl: null,
|
|
746
767
|
clientIdPlaceholder: null,
|
|
747
768
|
requiresClientSecret: false,
|
|
748
|
-
logoUrl:
|
|
769
|
+
logoUrl:
|
|
770
|
+
"https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/slack/default.svg",
|
|
749
771
|
defaultScopes: [],
|
|
750
772
|
injectionTemplates: [
|
|
751
773
|
{
|
|
@@ -757,6 +779,35 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
757
779
|
],
|
|
758
780
|
},
|
|
759
781
|
|
|
782
|
+
// The bot that sits in a server and talks to people there, which is a
|
|
783
|
+
// different thing from the `discord` integration above and starts at the
|
|
784
|
+
// same Discord authorize URL. Both are reasonably called "connecting
|
|
785
|
+
// Discord", so each has to be nameable on its own. The bot token is already
|
|
786
|
+
// stored under this key by `skills/discord-app-setup`; seeding the provider
|
|
787
|
+
// is what lets the product tell the two apart.
|
|
788
|
+
discord_channel: {
|
|
789
|
+
provider: "discord_channel",
|
|
790
|
+
authorizeUrl: "urn:manual-token",
|
|
791
|
+
tokenExchangeUrl: "urn:manual-token",
|
|
792
|
+
pingUrl: "https://discord.com/api/v10/users/@me",
|
|
793
|
+
baseUrl: "https://discord.com/api/v10",
|
|
794
|
+
displayLabel: "Discord Server",
|
|
795
|
+
description: "A bot in your server",
|
|
796
|
+
dashboardUrl: "https://discord.com/developers/applications",
|
|
797
|
+
clientIdPlaceholder: null,
|
|
798
|
+
requiresClientSecret: false,
|
|
799
|
+
logoUrl: "https://cdn.simpleicons.org/discord",
|
|
800
|
+
defaultScopes: [],
|
|
801
|
+
injectionTemplates: [
|
|
802
|
+
{
|
|
803
|
+
hostPattern: "discord.com",
|
|
804
|
+
injectionType: "header",
|
|
805
|
+
headerName: "Authorization",
|
|
806
|
+
valuePrefix: "Bot ",
|
|
807
|
+
},
|
|
808
|
+
],
|
|
809
|
+
},
|
|
810
|
+
|
|
760
811
|
telegram: {
|
|
761
812
|
provider: "telegram",
|
|
762
813
|
authorizeUrl: "urn:manual-token",
|
|
@@ -5,10 +5,19 @@ import {
|
|
|
5
5
|
type ActivationStepName,
|
|
6
6
|
buildActivationDaemonEventId,
|
|
7
7
|
} from "../telemetry/activation-funnel.js";
|
|
8
|
+
import {
|
|
9
|
+
LIVE_VOICE_FUNNEL_VERSION,
|
|
10
|
+
LIVE_VOICE_STEPS,
|
|
11
|
+
type LiveVoiceSessionOutcome,
|
|
12
|
+
type LiveVoiceStepName,
|
|
13
|
+
} from "../telemetry/live-voice-funnel.js";
|
|
8
14
|
import { recordTelemetryOutboxEvent } from "../telemetry/telemetry-events-outbox.js";
|
|
9
15
|
import type { OnboardingTelemetryEvent } from "../telemetry/types.js";
|
|
16
|
+
import { getLogger } from "../util/logger.js";
|
|
10
17
|
import { APP_VERSION } from "../version.js";
|
|
11
18
|
|
|
19
|
+
const log = getLogger("onboarding-events-store");
|
|
20
|
+
|
|
12
21
|
/** Identity of a recorded outbox row; the full payload lives in the outbox. */
|
|
13
22
|
export interface OnboardingEvent {
|
|
14
23
|
id: string;
|
|
@@ -28,6 +37,7 @@ export interface RecordOnboardingEventParams {
|
|
|
28
37
|
stepIndex?: number | null;
|
|
29
38
|
completedAt?: string | null;
|
|
30
39
|
funnelVersion?: string | null;
|
|
40
|
+
outcome?: string | null;
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
/**
|
|
@@ -52,7 +62,7 @@ function buildOnboardingTelemetryEvent(
|
|
|
52
62
|
params.sessionId && params.stepName && params.funnelVersion
|
|
53
63
|
? buildActivationDaemonEventId(
|
|
54
64
|
params.sessionId,
|
|
55
|
-
params.stepName
|
|
65
|
+
params.stepName,
|
|
56
66
|
params.funnelVersion,
|
|
57
67
|
)
|
|
58
68
|
: id,
|
|
@@ -72,6 +82,7 @@ function buildOnboardingTelemetryEvent(
|
|
|
72
82
|
...(params.stepIndex != null ? { step_index: params.stepIndex } : {}),
|
|
73
83
|
...(params.completedAt ? { completed_at: params.completedAt } : {}),
|
|
74
84
|
...(params.funnelVersion ? { funnel_version: params.funnelVersion } : {}),
|
|
85
|
+
...(params.outcome ? { outcome: params.outcome } : {}),
|
|
75
86
|
assistant_version: APP_VERSION,
|
|
76
87
|
};
|
|
77
88
|
}
|
|
@@ -111,3 +122,82 @@ export function recordActivationEvent(params: {
|
|
|
111
122
|
}),
|
|
112
123
|
);
|
|
113
124
|
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Record a live-voice session milestone (started / ended). Reuses the same
|
|
128
|
+
* onboarding telemetry substrate as {@link recordActivationEvent}, keyed by the
|
|
129
|
+
* live-voice session id so the two events pair up downstream. See
|
|
130
|
+
* `telemetry/live-voice-funnel.ts` for why duration and turn count are derived
|
|
131
|
+
* from that pairing rather than carried as fields.
|
|
132
|
+
*
|
|
133
|
+
* `screen` carries the end reason on the ended event (the started event has no
|
|
134
|
+
* dimension beyond the step itself). Returns null when usage data collection is
|
|
135
|
+
* disabled or the telemetry database is unavailable.
|
|
136
|
+
*
|
|
137
|
+
* **Never throws.** These fire from `LiveVoiceSession.start()` and `.close()`,
|
|
138
|
+
* which are the user's call itself: the outbox insert raises on a telemetry DB
|
|
139
|
+
* that is missing, locked, or mid-migration, and an uncaught raise there would
|
|
140
|
+
* fail the session rather than the measurement. A dropped row costs a gap in a
|
|
141
|
+
* chart; a raised one costs the user their conversation.
|
|
142
|
+
*/
|
|
143
|
+
function recordLiveVoiceEventSafely(
|
|
144
|
+
record: () => OnboardingEvent | null,
|
|
145
|
+
): OnboardingEvent | null {
|
|
146
|
+
try {
|
|
147
|
+
return record();
|
|
148
|
+
} catch (err) {
|
|
149
|
+
log.warn(
|
|
150
|
+
{ err },
|
|
151
|
+
"Failed to record live-voice session telemetry; continuing",
|
|
152
|
+
);
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function recordLiveVoiceSessionEvent(params: {
|
|
158
|
+
stepName: LiveVoiceStepName;
|
|
159
|
+
stepIndex: number;
|
|
160
|
+
sessionId: string;
|
|
161
|
+
screen?: string;
|
|
162
|
+
outcome?: LiveVoiceSessionOutcome;
|
|
163
|
+
}): OnboardingEvent | null {
|
|
164
|
+
return recordLiveVoiceEventSafely(() =>
|
|
165
|
+
recordTelemetryOutboxEvent("onboarding", (id, createdAt) =>
|
|
166
|
+
buildOnboardingTelemetryEvent(id, createdAt, {
|
|
167
|
+
screen: params.screen ?? params.stepName,
|
|
168
|
+
sessionId: params.sessionId,
|
|
169
|
+
stepName: params.stepName,
|
|
170
|
+
stepIndex: params.stepIndex,
|
|
171
|
+
completedAt: new Date(createdAt).toISOString(),
|
|
172
|
+
funnelVersion: LIVE_VOICE_FUNNEL_VERSION,
|
|
173
|
+
...(params.outcome ? { outcome: params.outcome } : {}),
|
|
174
|
+
}),
|
|
175
|
+
),
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Record the "a live-voice session was attempted" milestone. */
|
|
180
|
+
export function recordLiveVoiceSessionStarted(
|
|
181
|
+
sessionId: string,
|
|
182
|
+
): OnboardingEvent | null {
|
|
183
|
+
return recordLiveVoiceSessionEvent({
|
|
184
|
+
stepName: LIVE_VOICE_STEPS.sessionStarted.stepName,
|
|
185
|
+
stepIndex: LIVE_VOICE_STEPS.sessionStarted.stepIndex,
|
|
186
|
+
sessionId,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Record the "a live-voice session ended" milestone, with how it ended. */
|
|
191
|
+
export function recordLiveVoiceSessionEnded(params: {
|
|
192
|
+
sessionId: string;
|
|
193
|
+
screen: string;
|
|
194
|
+
outcome: LiveVoiceSessionOutcome;
|
|
195
|
+
}): OnboardingEvent | null {
|
|
196
|
+
return recordLiveVoiceSessionEvent({
|
|
197
|
+
stepName: LIVE_VOICE_STEPS.sessionEnded.stepName,
|
|
198
|
+
stepIndex: LIVE_VOICE_STEPS.sessionEnded.stepIndex,
|
|
199
|
+
sessionId: params.sessionId,
|
|
200
|
+
screen: params.screen,
|
|
201
|
+
outcome: params.outcome,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
@@ -200,6 +200,8 @@ describe("QuestionPrompter", () => {
|
|
|
200
200
|
|
|
201
201
|
const result = await promise;
|
|
202
202
|
expect(result).toEqual({
|
|
203
|
+
requestId: req.requestId,
|
|
204
|
+
questions: req.questions,
|
|
203
205
|
entries: [{ questionId: "q1", decision: "option", optionId: "a" }],
|
|
204
206
|
overall: "completed",
|
|
205
207
|
});
|
|
@@ -255,6 +257,8 @@ describe("QuestionPrompter", () => {
|
|
|
255
257
|
|
|
256
258
|
const result = await promise;
|
|
257
259
|
expect(result).toEqual({
|
|
260
|
+
requestId: req.requestId,
|
|
261
|
+
questions: req.questions,
|
|
258
262
|
entries: [{ questionId: "q1", decision: "free_text", text: "Cherry" }],
|
|
259
263
|
overall: "completed",
|
|
260
264
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
+
QuestionEntry,
|
|
4
5
|
QuestionOption,
|
|
5
6
|
QuestionRequestEvent,
|
|
6
7
|
} from "../api/events/question-request.js";
|
|
@@ -59,6 +60,18 @@ export interface QuestionPromptResult {
|
|
|
59
60
|
overall: "completed" | "closed" | "timed_out" | "aborted";
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
/**
|
|
64
|
+
* What {@link QuestionPrompter.prompt} returns: the resolution plus the
|
|
65
|
+
* identity of the prompt that produced it. `requestId` and `questions` are
|
|
66
|
+
* known only to the prompter (it mints the id and assigns the per-question
|
|
67
|
+
* ids), and the `ask_question` executor needs both to record the durable
|
|
68
|
+
* answered-question payload against the questions as they were asked.
|
|
69
|
+
*/
|
|
70
|
+
export interface QuestionPromptOutcome extends QuestionPromptResult {
|
|
71
|
+
requestId: string;
|
|
72
|
+
questions: QuestionEntry[];
|
|
73
|
+
}
|
|
74
|
+
|
|
62
75
|
export interface QuestionPromptParamsEntry {
|
|
63
76
|
question: string;
|
|
64
77
|
description?: string;
|
|
@@ -170,7 +183,7 @@ export interface QuestionBatchMetadata {
|
|
|
170
183
|
* fires when a prompt is left open with no response and no follow-up message.
|
|
171
184
|
*/
|
|
172
185
|
export class QuestionPrompter {
|
|
173
|
-
async prompt(params: QuestionPromptParams): Promise<
|
|
186
|
+
async prompt(params: QuestionPromptParams): Promise<QuestionPromptOutcome> {
|
|
174
187
|
const { conversationId, questions, toolUseId, signal } = params;
|
|
175
188
|
|
|
176
189
|
if (questions.length === 0) {
|
|
@@ -195,8 +208,12 @@ export class QuestionPrompter {
|
|
|
195
208
|
optionsById[e.id] = e.options.map((o) => o.id);
|
|
196
209
|
}
|
|
197
210
|
|
|
211
|
+
const requestId = uuid();
|
|
212
|
+
|
|
198
213
|
if (signal?.aborted) {
|
|
199
214
|
return {
|
|
215
|
+
requestId,
|
|
216
|
+
questions: entries,
|
|
200
217
|
entries: orderedIds.map((id) => ({
|
|
201
218
|
questionId: id,
|
|
202
219
|
decision: "aborted",
|
|
@@ -205,9 +222,7 @@ export class QuestionPrompter {
|
|
|
205
222
|
};
|
|
206
223
|
}
|
|
207
224
|
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
return new Promise<QuestionPromptResult>((resolve, reject) => {
|
|
225
|
+
const settled = new Promise<QuestionPromptResult>((resolve, reject) => {
|
|
211
226
|
const timeoutMs = getConfig().timeouts.questionResponseTimeoutSec * 1000;
|
|
212
227
|
|
|
213
228
|
// Closure-scoped idempotency guard. Every resolution path (timeout,
|
|
@@ -318,5 +333,7 @@ export class QuestionPrompter {
|
|
|
318
333
|
// single-question batch) lives in the promotion module.
|
|
319
334
|
void createGuardianRequestForQuestion(msg, conversationId);
|
|
320
335
|
});
|
|
336
|
+
|
|
337
|
+
return { ...(await settled), requestId, questions: entries };
|
|
321
338
|
}
|
|
322
339
|
}
|