@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
|
@@ -709,7 +709,7 @@ describe("HostTransferProxy — targetClientId", () => {
|
|
|
709
709
|
);
|
|
710
710
|
|
|
711
711
|
expect(result.isError).toBe(true);
|
|
712
|
-
expect(result.content).toContain("
|
|
712
|
+
expect(result.content).toContain("signed in as a different user");
|
|
713
713
|
expect(sentMessages).toHaveLength(0);
|
|
714
714
|
});
|
|
715
715
|
|
|
@@ -738,7 +738,7 @@ describe("HostTransferProxy — targetClientId", () => {
|
|
|
738
738
|
);
|
|
739
739
|
|
|
740
740
|
expect(result.isError).toBe(true);
|
|
741
|
-
expect(result.content).toContain("
|
|
741
|
+
expect(result.content).toContain("no authenticated actor");
|
|
742
742
|
expect(sentMessages).toHaveLength(0);
|
|
743
743
|
});
|
|
744
744
|
|
|
@@ -767,7 +767,9 @@ describe("HostTransferProxy — targetClientId", () => {
|
|
|
767
767
|
);
|
|
768
768
|
|
|
769
769
|
expect(result.isError).toBe(true);
|
|
770
|
-
expect(result.content).toContain(
|
|
770
|
+
expect(result.content).toContain(
|
|
771
|
+
"registered without an authenticated user",
|
|
772
|
+
);
|
|
771
773
|
expect(sentMessages).toHaveLength(0);
|
|
772
774
|
});
|
|
773
775
|
|
|
@@ -863,7 +865,7 @@ describe("HostTransferProxy — targetClientId", () => {
|
|
|
863
865
|
);
|
|
864
866
|
|
|
865
867
|
expect(result.isError).toBe(true);
|
|
866
|
-
expect(result.content).toContain("
|
|
868
|
+
expect(result.content).toContain("signed in as a different user");
|
|
867
869
|
expect(sentMessages).toHaveLength(0);
|
|
868
870
|
});
|
|
869
871
|
|
|
@@ -13,7 +13,7 @@ mock.module("../config/env.js", () => ({
|
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
-
|
|
16
|
+
batchSetConversationPlacement,
|
|
17
17
|
createConversation,
|
|
18
18
|
updateConversationTitle,
|
|
19
19
|
} from "../persistence/conversation-crud.js";
|
|
@@ -100,9 +100,7 @@ describe("conversation lineage in HTTP reads", () => {
|
|
|
100
100
|
|
|
101
101
|
test("GET /v1/conversations/:id includes pin metadata when present", async () => {
|
|
102
102
|
const conversation = createConversation("Pinned conversation");
|
|
103
|
-
|
|
104
|
-
{ id: conversation.id, displayOrder: 7, isPinned: true },
|
|
105
|
-
]);
|
|
103
|
+
batchSetConversationPlacement([{ id: conversation.id, isPinned: true }]);
|
|
106
104
|
await startServer();
|
|
107
105
|
|
|
108
106
|
const response = await fetch(url(`/conversations/${conversation.id}`));
|
|
@@ -115,7 +113,6 @@ describe("conversation lineage in HTTP reads", () => {
|
|
|
115
113
|
expect(body.conversation).toMatchObject({
|
|
116
114
|
id: conversation.id,
|
|
117
115
|
title: conversation.title ?? "Untitled",
|
|
118
|
-
displayOrder: 7,
|
|
119
116
|
isPinned: true,
|
|
120
117
|
});
|
|
121
118
|
});
|
|
@@ -650,6 +650,50 @@ describe("HTTP POST /v1/messages client metadata headers", () => {
|
|
|
650
650
|
];
|
|
651
651
|
expect(persistOptions.metadata).toBeUndefined();
|
|
652
652
|
});
|
|
653
|
+
|
|
654
|
+
// Persistence merges the row's `client.os` from two sources and only one of
|
|
655
|
+
// them is this row's own: the request. Threading the body's `clientOs` is
|
|
656
|
+
// what lets it tell a reported OS apart from the one a transport-less turn
|
|
657
|
+
// inherits off the live conversation.
|
|
658
|
+
test("threads the body clientOs as this row's own OS evidence", async () => {
|
|
659
|
+
const persistUserMessage = mock(
|
|
660
|
+
async (_options: { requestClientOs?: string }) => ({
|
|
661
|
+
id: "persisted-msg-id",
|
|
662
|
+
deduplicated: false,
|
|
663
|
+
}),
|
|
664
|
+
);
|
|
665
|
+
const runAgentLoop = mock(async () => undefined);
|
|
666
|
+
const conversation = makeConversation({ persistUserMessage, runAgentLoop });
|
|
667
|
+
|
|
668
|
+
const res = await sendMessage("hello", conversation, {
|
|
669
|
+
clientOs: "macos",
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
expect(res.status).toBe(202);
|
|
673
|
+
const [persistOptions] = persistUserMessage.mock.calls[0] as unknown as [
|
|
674
|
+
{ requestClientOs?: string },
|
|
675
|
+
];
|
|
676
|
+
expect(persistOptions.requestClientOs).toBe("macos");
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
test("omits the OS evidence when the body reports no clientOs", async () => {
|
|
680
|
+
const persistUserMessage = mock(
|
|
681
|
+
async (_options: { requestClientOs?: string }) => ({
|
|
682
|
+
id: "persisted-msg-id",
|
|
683
|
+
deduplicated: false,
|
|
684
|
+
}),
|
|
685
|
+
);
|
|
686
|
+
const runAgentLoop = mock(async () => undefined);
|
|
687
|
+
const conversation = makeConversation({ persistUserMessage, runAgentLoop });
|
|
688
|
+
|
|
689
|
+
const res = await sendMessage("hello", conversation);
|
|
690
|
+
|
|
691
|
+
expect(res.status).toBe(202);
|
|
692
|
+
const [persistOptions] = persistUserMessage.mock.calls[0] as unknown as [
|
|
693
|
+
{ requestClientOs?: string },
|
|
694
|
+
];
|
|
695
|
+
expect(persistOptions.requestClientOs).toBeUndefined();
|
|
696
|
+
});
|
|
653
697
|
});
|
|
654
698
|
|
|
655
699
|
// ============================================================================
|
|
@@ -151,7 +151,7 @@ afterEach(() => {
|
|
|
151
151
|
describe("identity routes — health endpoint", () => {
|
|
152
152
|
describe("backward compatibility (profiler disabled)", () => {
|
|
153
153
|
test("/v1/health returns expected shape without profiler key when env vars are absent", async () => {
|
|
154
|
-
const res = handleDetailedHealth();
|
|
154
|
+
const res = await handleDetailedHealth();
|
|
155
155
|
expect(res.status).toBe(200);
|
|
156
156
|
|
|
157
157
|
const body = (await res.json()) as Record<string, unknown>;
|
|
@@ -179,7 +179,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
179
179
|
|
|
180
180
|
test("/v1/healthz returns the same shape as /v1/health", async () => {
|
|
181
181
|
// Both endpoints call handleDetailedHealth, so the shape must match
|
|
182
|
-
const res = handleDetailedHealth();
|
|
182
|
+
const res = await handleDetailedHealth();
|
|
183
183
|
const body = (await res.json()) as Record<string, unknown>;
|
|
184
184
|
|
|
185
185
|
expect(body.status).toBe("healthy");
|
|
@@ -188,7 +188,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
test("includes ces.connected=false when no CES client is registered", async () => {
|
|
191
|
-
const res = handleDetailedHealth();
|
|
191
|
+
const res = await handleDetailedHealth();
|
|
192
192
|
const body = (await res.json()) as Record<string, unknown>;
|
|
193
193
|
|
|
194
194
|
expect(body.ces).toBeDefined();
|
|
@@ -197,7 +197,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
197
197
|
|
|
198
198
|
test("detailed health reports MIGRATING while DB migrations are running", async () => {
|
|
199
199
|
setDbMigrating();
|
|
200
|
-
const res = handleDetailedHealth();
|
|
200
|
+
const res = await handleDetailedHealth();
|
|
201
201
|
expect(res.status).toBe(200);
|
|
202
202
|
|
|
203
203
|
const body = (await res.json()) as Record<string, unknown>;
|
|
@@ -229,7 +229,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
229
229
|
close: () => {},
|
|
230
230
|
} as unknown as import("../credential-execution/client.js").CesClient;
|
|
231
231
|
setCesClient(mockClient);
|
|
232
|
-
const res = handleDetailedHealth();
|
|
232
|
+
const res = await handleDetailedHealth();
|
|
233
233
|
const body = (await res.json()) as Record<string, unknown>;
|
|
234
234
|
|
|
235
235
|
expect(body.ces).toBeDefined();
|
|
@@ -242,7 +242,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
242
242
|
close: () => {},
|
|
243
243
|
} as unknown as import("../credential-execution/client.js").CesClient;
|
|
244
244
|
setCesClient(mockClient);
|
|
245
|
-
const res = handleDetailedHealth();
|
|
245
|
+
const res = await handleDetailedHealth();
|
|
246
246
|
const body = (await res.json()) as Record<string, unknown>;
|
|
247
247
|
|
|
248
248
|
expect(body.ces).toBeDefined();
|
|
@@ -258,7 +258,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
258
258
|
});
|
|
259
259
|
ensureProfilerRunDir("run-health-test-1");
|
|
260
260
|
|
|
261
|
-
const res = handleDetailedHealth();
|
|
261
|
+
const res = await handleDetailedHealth();
|
|
262
262
|
const body = (await res.json()) as Record<string, unknown>;
|
|
263
263
|
|
|
264
264
|
expect(body.profiler).toBeDefined();
|
|
@@ -278,7 +278,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
278
278
|
});
|
|
279
279
|
ensureProfilerRunDir("run-budget-test");
|
|
280
280
|
|
|
281
|
-
const res = handleDetailedHealth();
|
|
281
|
+
const res = await handleDetailedHealth();
|
|
282
282
|
const body = (await res.json()) as Record<string, unknown>;
|
|
283
283
|
const profiler = body.profiler as Record<string, unknown>;
|
|
284
284
|
const budget = profiler.budget as Record<string, unknown>;
|
|
@@ -301,7 +301,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
301
301
|
// Non-artifact file should not count
|
|
302
302
|
writeArtifactFile("run-artifact-count", "log.txt", 512);
|
|
303
303
|
|
|
304
|
-
const res = handleDetailedHealth();
|
|
304
|
+
const res = await handleDetailedHealth();
|
|
305
305
|
const body = (await res.json()) as Record<string, unknown>;
|
|
306
306
|
const profiler = body.profiler as Record<string, unknown>;
|
|
307
307
|
|
|
@@ -316,7 +316,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
316
316
|
// Write a file larger than the budget
|
|
317
317
|
writeArtifactFile("run-over-budget", "big.cpuprofile", 5000);
|
|
318
318
|
|
|
319
|
-
const res = handleDetailedHealth();
|
|
319
|
+
const res = await handleDetailedHealth();
|
|
320
320
|
const body = (await res.json()) as Record<string, unknown>;
|
|
321
321
|
const profiler = body.profiler as Record<string, unknown>;
|
|
322
322
|
const budget = profiler.budget as Record<string, unknown>;
|
|
@@ -334,7 +334,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
334
334
|
});
|
|
335
335
|
ensureProfilerRunDir("run-no-completed");
|
|
336
336
|
|
|
337
|
-
const res = handleDetailedHealth();
|
|
337
|
+
const res = await handleDetailedHealth();
|
|
338
338
|
const body = (await res.json()) as Record<string, unknown>;
|
|
339
339
|
const profiler = body.profiler as Record<string, unknown>;
|
|
340
340
|
|
|
@@ -361,7 +361,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
361
361
|
writeArtifactFile(completedId, "profile.cpuprofile", 3072);
|
|
362
362
|
writeArtifactFile(completedId, "summary.md", 256);
|
|
363
363
|
|
|
364
|
-
const res = handleDetailedHealth();
|
|
364
|
+
const res = await handleDetailedHealth();
|
|
365
365
|
const body = (await res.json()) as Record<string, unknown>;
|
|
366
366
|
const profiler = body.profiler as Record<string, unknown>;
|
|
367
367
|
const last = profiler.lastCompletedRun as Record<string, unknown>;
|
|
@@ -398,7 +398,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
398
398
|
});
|
|
399
399
|
writeArtifactFile("newer-completed", "new.heapsnapshot", 1024);
|
|
400
400
|
|
|
401
|
-
const res = handleDetailedHealth();
|
|
401
|
+
const res = await handleDetailedHealth();
|
|
402
402
|
const body = (await res.json()) as Record<string, unknown>;
|
|
403
403
|
const profiler = body.profiler as Record<string, unknown>;
|
|
404
404
|
const last = profiler.lastCompletedRun as Record<string, unknown>;
|
|
@@ -132,17 +132,17 @@ describe("sniffImageMimeType", () => {
|
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
describe("normalizeImageBytes passthrough", () => {
|
|
135
|
-
test("non-HEIF bytes pass through untouched", () => {
|
|
136
|
-
const result = normalizeImageBytes("image/png", PNG_1PX_BYTES);
|
|
135
|
+
test("non-HEIF bytes pass through untouched", async () => {
|
|
136
|
+
const result = await normalizeImageBytes("image/png", PNG_1PX_BYTES);
|
|
137
137
|
expect(result.converted).toBe(false);
|
|
138
138
|
expect(result.mimeType).toBe("image/png");
|
|
139
139
|
expect(result.bytes).toBe(PNG_1PX_BYTES);
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
test("HEIF header with undecodable payload passes through", () => {
|
|
142
|
+
test("HEIF header with undecodable payload passes through", async () => {
|
|
143
143
|
// sips fails (or is absent off-macOS) → the original bytes are kept.
|
|
144
144
|
const fake = fakeHeifHeaderBytes();
|
|
145
|
-
const result = normalizeImageBytes("image/heic", fake);
|
|
145
|
+
const result = await normalizeImageBytes("image/heic", fake);
|
|
146
146
|
expect(result.converted).toBe(false);
|
|
147
147
|
expect(result.mimeType).toBe("image/heic");
|
|
148
148
|
expect(result.bytes).toBe(fake);
|
|
@@ -150,35 +150,35 @@ describe("normalizeImageBytes passthrough", () => {
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
describe("normalizeImageBase64 passthrough", () => {
|
|
153
|
-
test("non-HEIF payloads skip conversion", () => {
|
|
153
|
+
test("non-HEIF payloads skip conversion", async () => {
|
|
154
154
|
const b64 = PNG_1PX_BYTES.toString("base64");
|
|
155
|
-
const result = normalizeImageBase64("image/png", b64);
|
|
155
|
+
const result = await normalizeImageBase64("image/png", b64);
|
|
156
156
|
expect(result.converted).toBe(false);
|
|
157
157
|
expect(result.dataBase64).toBe(b64);
|
|
158
158
|
});
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
describe("declared-MIME correction from sniffed bytes", () => {
|
|
162
|
-
test("normalizeImageBytes relabels a mislabeled image, bytes untouched", () => {
|
|
162
|
+
test("normalizeImageBytes relabels a mislabeled image, bytes untouched", async () => {
|
|
163
163
|
// A JPEG renamed to .png arrives declared as image/png; providers reject
|
|
164
164
|
// the mismatch, so the sniffed format wins.
|
|
165
|
-
const result = normalizeImageBytes("image/png", JPEG_HEADER_BYTES);
|
|
165
|
+
const result = await normalizeImageBytes("image/png", JPEG_HEADER_BYTES);
|
|
166
166
|
expect(result.converted).toBe(false);
|
|
167
167
|
expect(result.mimeType).toBe("image/jpeg");
|
|
168
168
|
expect(result.bytes).toBe(JPEG_HEADER_BYTES);
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
test("normalizeImageBase64 relabels a mislabeled image, payload untouched", () => {
|
|
171
|
+
test("normalizeImageBase64 relabels a mislabeled image, payload untouched", async () => {
|
|
172
172
|
const b64 = PNG_1PX_BYTES.toString("base64");
|
|
173
|
-
const result = normalizeImageBase64("image/jpeg", b64);
|
|
173
|
+
const result = await normalizeImageBase64("image/jpeg", b64);
|
|
174
174
|
expect(result.converted).toBe(false);
|
|
175
175
|
expect(result.mimeType).toBe("image/png");
|
|
176
176
|
expect(result.dataBase64).toBe(b64);
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
-
test("unrecognized bytes keep the declared MIME", () => {
|
|
179
|
+
test("unrecognized bytes keep the declared MIME", async () => {
|
|
180
180
|
const bytes = Buffer.from("plain text content");
|
|
181
|
-
const result = normalizeImageBytes("text/plain", bytes);
|
|
181
|
+
const result = await normalizeImageBytes("text/plain", bytes);
|
|
182
182
|
expect(result.mimeType).toBe("text/plain");
|
|
183
183
|
expect(result.bytes).toBe(bytes);
|
|
184
184
|
});
|
|
@@ -201,17 +201,17 @@ describe.skipIf(process.platform !== "darwin")(
|
|
|
201
201
|
expect(isHeifImage(heicBytes)).toBe(true);
|
|
202
202
|
});
|
|
203
203
|
|
|
204
|
-
test("convertImageToJpeg produces JPEG bytes", () => {
|
|
205
|
-
const converted = convertImageToJpeg(heicBytes);
|
|
204
|
+
test("convertImageToJpeg produces JPEG bytes", async () => {
|
|
205
|
+
const converted = await convertImageToJpeg(heicBytes);
|
|
206
206
|
expect(converted).not.toBeNull();
|
|
207
207
|
expect(startsWithJpegMagic(converted!)).toBe(true);
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
-
test("conversion options produce distinct outputs (cache key isolation)", () => {
|
|
210
|
+
test("conversion options produce distinct outputs (cache key isolation)", async () => {
|
|
211
211
|
// A hash-only cache key would make the second call return the first
|
|
212
212
|
// call's cached full-resolution output.
|
|
213
|
-
const fullRes = convertImageToJpeg(heicBytes, { quality: 90 });
|
|
214
|
-
const downscaled = convertImageToJpeg(heicBytes, {
|
|
213
|
+
const fullRes = await convertImageToJpeg(heicBytes, { quality: 90 });
|
|
214
|
+
const downscaled = await convertImageToJpeg(heicBytes, {
|
|
215
215
|
maxDimensionPx: 16,
|
|
216
216
|
quality: 90,
|
|
217
217
|
});
|
|
@@ -220,31 +220,34 @@ describe.skipIf(process.platform !== "darwin")(
|
|
|
220
220
|
expect(fullRes!.equals(downscaled!)).toBe(false);
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
-
test("repeated conversion is stable (cache round-trip)", () => {
|
|
224
|
-
const first = convertImageToJpeg(heicBytes, { quality: 90 });
|
|
225
|
-
const second = convertImageToJpeg(heicBytes, { quality: 90 });
|
|
223
|
+
test("repeated conversion is stable (cache round-trip)", async () => {
|
|
224
|
+
const first = await convertImageToJpeg(heicBytes, { quality: 90 });
|
|
225
|
+
const second = await convertImageToJpeg(heicBytes, { quality: 90 });
|
|
226
226
|
expect(first).not.toBeNull();
|
|
227
227
|
expect(second).not.toBeNull();
|
|
228
228
|
expect(first!.equals(second!)).toBe(true);
|
|
229
229
|
});
|
|
230
230
|
|
|
231
|
-
test("normalizeImageBytes converts to a JPEG master", () => {
|
|
232
|
-
const result = normalizeImageBytes("image/heic", heicBytes);
|
|
231
|
+
test("normalizeImageBytes converts to a JPEG master", async () => {
|
|
232
|
+
const result = await normalizeImageBytes("image/heic", heicBytes);
|
|
233
233
|
expect(result.converted).toBe(true);
|
|
234
234
|
expect(result.mimeType).toBe("image/jpeg");
|
|
235
235
|
expect(startsWithJpegMagic(result.bytes)).toBe(true);
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
-
test("normalizeImageBytes converts even when the declared mime is wrong", () => {
|
|
238
|
+
test("normalizeImageBytes converts even when the declared mime is wrong", async () => {
|
|
239
239
|
// Chromium reports empty file.type for .heic; clients coerce it to
|
|
240
240
|
// application/octet-stream. Detection is content-based.
|
|
241
|
-
const result = normalizeImageBytes(
|
|
241
|
+
const result = await normalizeImageBytes(
|
|
242
|
+
"application/octet-stream",
|
|
243
|
+
heicBytes,
|
|
244
|
+
);
|
|
242
245
|
expect(result.converted).toBe(true);
|
|
243
246
|
expect(result.mimeType).toBe("image/jpeg");
|
|
244
247
|
});
|
|
245
248
|
|
|
246
|
-
test("normalizeImageBase64 converts and re-encodes", () => {
|
|
247
|
-
const result = normalizeImageBase64(
|
|
249
|
+
test("normalizeImageBase64 converts and re-encodes", async () => {
|
|
250
|
+
const result = await normalizeImageBase64(
|
|
248
251
|
"image/heic",
|
|
249
252
|
heicBytes.toString("base64"),
|
|
250
253
|
);
|
|
@@ -233,7 +233,7 @@ describe("reinjectAttachmentPathAnnotations", () => {
|
|
|
233
233
|
);
|
|
234
234
|
});
|
|
235
235
|
|
|
236
|
-
test("rebuilds the exact annotation block enrichMessageWithSourcePaths appends", () => {
|
|
236
|
+
test("rebuilds the exact annotation block enrichMessageWithSourcePaths appends", async () => {
|
|
237
237
|
// Prefix-cache parity tripwire: the block appended at persist time (from
|
|
238
238
|
// live attachment inputs) and the block rebuilt on history reload (from
|
|
239
239
|
// persisted metadata) must be byte-identical.
|
|
@@ -253,7 +253,7 @@ describe("reinjectAttachmentPathAnnotations", () => {
|
|
|
253
253
|
},
|
|
254
254
|
];
|
|
255
255
|
const enriched = enrichMessageWithSourcePaths(
|
|
256
|
-
createUserMessage("compare", attachments),
|
|
256
|
+
await createUserMessage("compare", attachments),
|
|
257
257
|
attachments,
|
|
258
258
|
);
|
|
259
259
|
const liveBlock = enriched.content.at(-1) as {
|
|
@@ -24,6 +24,30 @@ mock.module("../runtime/assistant-event.js", () => ({
|
|
|
24
24
|
buildAssistantEvent: (event: unknown) => event,
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
|
+
// The default profiles used below (`balanced`, `cost-optimized`) route through
|
|
28
|
+
// the Vellum-managed connection, and the handler's availability guard judges
|
|
29
|
+
// that route for real. Stand in for a signed-in platform session so the pin
|
|
30
|
+
// path under test is the healthy one; `managedProxyEnabled` is flipped by the
|
|
31
|
+
// guard test.
|
|
32
|
+
let managedProxyEnabled = true;
|
|
33
|
+
mock.module("../providers/platform-proxy/context.js", () => ({
|
|
34
|
+
resolveManagedProxyContext: async () => ({
|
|
35
|
+
enabled: managedProxyEnabled,
|
|
36
|
+
platformBaseUrl: "https://platform.example",
|
|
37
|
+
assistantApiKey: managedProxyEnabled ? "key" : "",
|
|
38
|
+
}),
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
// Vault stand-in: tests that exercise BYOK availability drop the credential
|
|
42
|
+
// they need into this map and clean it up after.
|
|
43
|
+
const storedKeys: Record<string, string> = {};
|
|
44
|
+
mock.module("../security/secure-keys.js", () => ({
|
|
45
|
+
getSecureKeyResultAsync: async (key: string) => ({
|
|
46
|
+
value: storedKeys[key],
|
|
47
|
+
unreachable: false,
|
|
48
|
+
}),
|
|
49
|
+
}));
|
|
50
|
+
|
|
27
51
|
// The handler reads the real config: the "balanced" and "cost-optimized"
|
|
28
52
|
// profiles used below are code-default catalog entries that always resolve,
|
|
29
53
|
// and llm.profileSession's schema defaults (1800/43200) are what the TTL
|
|
@@ -44,9 +68,24 @@ import {
|
|
|
44
68
|
} from "../persistence/conversation-crud.js";
|
|
45
69
|
import { getDb } from "../persistence/db-connection.js";
|
|
46
70
|
import { initializeDb } from "../persistence/db-init.js";
|
|
71
|
+
import { providerConnections } from "../persistence/schema/inference.js";
|
|
72
|
+
import { setConfig } from "./helpers/set-config.js";
|
|
47
73
|
|
|
48
74
|
await initializeDb();
|
|
49
75
|
|
|
76
|
+
// The Vellum-managed connection row the default profiles resolve to.
|
|
77
|
+
getDb()
|
|
78
|
+
.insert(providerConnections)
|
|
79
|
+
.values({
|
|
80
|
+
name: "vellum",
|
|
81
|
+
provider: "vellum",
|
|
82
|
+
auth: JSON.stringify({ type: "platform" }),
|
|
83
|
+
createdAt: Date.now(),
|
|
84
|
+
updatedAt: Date.now(),
|
|
85
|
+
})
|
|
86
|
+
.onConflictDoNothing()
|
|
87
|
+
.run();
|
|
88
|
+
|
|
50
89
|
import {
|
|
51
90
|
closeInferenceProfileSession,
|
|
52
91
|
listInferenceProfileSessionsWithRemaining,
|
|
@@ -344,6 +383,62 @@ describe("setInferenceProfileSession", () => {
|
|
|
344
383
|
);
|
|
345
384
|
});
|
|
346
385
|
|
|
386
|
+
test("open with an unavailable profile — refuses the pin and names the fix", async () => {
|
|
387
|
+
const conv = createConversation("sess-handler-unavailable-profile");
|
|
388
|
+
managedProxyEnabled = false;
|
|
389
|
+
try {
|
|
390
|
+
const promise = setInferenceProfileSession({
|
|
391
|
+
conversationId: conv.id,
|
|
392
|
+
profile: "balanced",
|
|
393
|
+
ttlSeconds: 300,
|
|
394
|
+
});
|
|
395
|
+
await expect(promise).rejects.toThrow(/Not signed in to Vellum/);
|
|
396
|
+
await expect(promise).rejects.toThrow(
|
|
397
|
+
/assistant inference send --profile balanced "Reply with OK"/,
|
|
398
|
+
);
|
|
399
|
+
// Nothing was pinned.
|
|
400
|
+
expect(getConversation(conv.id)?.inferenceProfile).toBeNull();
|
|
401
|
+
} finally {
|
|
402
|
+
managedProxyEnabled = true;
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
test("BYOK default provider — pins a managed preset without a Vellum sign-in", async () => {
|
|
407
|
+
const conv = createConversation("sess-handler-byok-preset");
|
|
408
|
+
// Signed out of Vellum, but llm.defaultProvider points the managed
|
|
409
|
+
// presets at the user's own anthropic connection — the pin must judge
|
|
410
|
+
// that body, not the Vellum column.
|
|
411
|
+
managedProxyEnabled = false;
|
|
412
|
+
storedKeys["credential/anthropic/api_key"] = "test-key";
|
|
413
|
+
getDb()
|
|
414
|
+
.insert(providerConnections)
|
|
415
|
+
.values({
|
|
416
|
+
name: "anthropic-personal",
|
|
417
|
+
provider: "anthropic",
|
|
418
|
+
auth: JSON.stringify({
|
|
419
|
+
type: "api_key",
|
|
420
|
+
credential: "credential/anthropic/api_key",
|
|
421
|
+
}),
|
|
422
|
+
createdAt: Date.now(),
|
|
423
|
+
updatedAt: Date.now(),
|
|
424
|
+
})
|
|
425
|
+
.onConflictDoNothing()
|
|
426
|
+
.run();
|
|
427
|
+
setConfig("llm", { defaultProvider: { provider: "anthropic" } });
|
|
428
|
+
try {
|
|
429
|
+
const result = await setInferenceProfileSession({
|
|
430
|
+
conversationId: conv.id,
|
|
431
|
+
profile: "balanced",
|
|
432
|
+
ttlSeconds: 300,
|
|
433
|
+
});
|
|
434
|
+
expect(result.profile).toBe("balanced");
|
|
435
|
+
} finally {
|
|
436
|
+
managedProxyEnabled = true;
|
|
437
|
+
delete storedKeys["credential/anthropic/api_key"];
|
|
438
|
+
setConfig("llm", {});
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
|
|
347
442
|
test("open with ttlSeconds=null — expiresAt=null, sessionId=null, profile kept", async () => {
|
|
348
443
|
const conv = createConversation("sess-handler-null-ttl");
|
|
349
444
|
|
|
@@ -16,6 +16,17 @@ mock.module("../runtime/assistant-event.js", () => ({
|
|
|
16
16
|
buildAssistantEvent: (event: unknown) => event,
|
|
17
17
|
}));
|
|
18
18
|
|
|
19
|
+
// "balanced"/"cost-optimized" route through the Vellum-managed connection, and
|
|
20
|
+
// the open handler's availability guard judges that route for real. Stand in
|
|
21
|
+
// for a signed-in platform session so these tests exercise the healthy path.
|
|
22
|
+
mock.module("../providers/platform-proxy/context.js", () => ({
|
|
23
|
+
resolveManagedProxyContext: async () => ({
|
|
24
|
+
enabled: true,
|
|
25
|
+
platformBaseUrl: "https://platform.example",
|
|
26
|
+
assistantApiKey: "key",
|
|
27
|
+
}),
|
|
28
|
+
}));
|
|
29
|
+
|
|
19
30
|
// The handler resolves "balanced"/"cost-optimized" through the code-defined
|
|
20
31
|
// default profile catalog and reads `llm.profileSession` schema defaults
|
|
21
32
|
// (1800/43200), so real config with no seeding covers these tests.
|
|
@@ -23,11 +34,25 @@ mock.module("../runtime/assistant-event.js", () => ({
|
|
|
23
34
|
import { createConversation } from "../persistence/conversation-crud.js";
|
|
24
35
|
import { getDb } from "../persistence/db-connection.js";
|
|
25
36
|
import { initializeDb } from "../persistence/db-init.js";
|
|
37
|
+
import { providerConnections } from "../persistence/schema/inference.js";
|
|
26
38
|
import { ROUTES } from "../runtime/routes/inference-profile-session-routes.js";
|
|
27
39
|
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
28
40
|
|
|
29
41
|
await initializeDb();
|
|
30
42
|
|
|
43
|
+
// The Vellum-managed connection row the default profiles resolve to.
|
|
44
|
+
getDb()
|
|
45
|
+
.insert(providerConnections)
|
|
46
|
+
.values({
|
|
47
|
+
name: "vellum",
|
|
48
|
+
provider: "vellum",
|
|
49
|
+
auth: JSON.stringify({ type: "platform" }),
|
|
50
|
+
createdAt: Date.now(),
|
|
51
|
+
updatedAt: Date.now(),
|
|
52
|
+
})
|
|
53
|
+
.onConflictDoNothing()
|
|
54
|
+
.run();
|
|
55
|
+
|
|
31
56
|
const openRoute = ROUTES.find(
|
|
32
57
|
(r) => r.operationId === "inference_profile_open",
|
|
33
58
|
)!;
|
|
@@ -182,7 +182,12 @@ describe("introduction card decisions", () => {
|
|
|
182
182
|
expectedExternalUserId: "U-REQUESTER",
|
|
183
183
|
expectedChatId: "C-CHAT",
|
|
184
184
|
identityBindingStatus: "bound",
|
|
185
|
-
|
|
185
|
+
// The person, not the room. Slack delivers to a user id, and the room
|
|
186
|
+
// may hold an audience the code was never meant for. `expectedChatId`
|
|
187
|
+
// still carries the room because that is where the conversation is;
|
|
188
|
+
// with both identity fields set the consume path requires the user
|
|
189
|
+
// match, so the room is not a credential.
|
|
190
|
+
destinationAddress: "U-REQUESTER",
|
|
186
191
|
verificationPurpose: "trusted_contact",
|
|
187
192
|
});
|
|
188
193
|
expect(outcomesOfType("activate_member")).toHaveLength(0);
|