@vellumai/assistant 0.8.5 → 0.8.6
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/AGENTS.md +33 -1
- package/ARCHITECTURE.md +1 -1
- package/bunfig.toml +6 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +1900 -166
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- 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__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +3 -2
- package/src/__tests__/call-controller.test.ts +3 -2
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +3 -2
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +12 -12
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +12 -14
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
- package/src/__tests__/conversation-agent-loop.test.ts +488 -2
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +69 -8
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -5
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +26 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +5 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-resolver.test.ts +331 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +3 -2
- package/src/__tests__/openai-provider.test.ts +8 -9
- package/src/__tests__/openai-responses-provider.test.ts +70 -10
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/plugin-bootstrap.test.ts +9 -11
- package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +14 -16
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +38 -0
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/loop.ts +80 -0
- package/src/api/README.md +124 -2
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/{events → api/events}/relationship-state-updated.ts +3 -3
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +128 -3
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +687 -52
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/memory-v3-render.ts +147 -0
- package/src/cli/commands/memory-v3.ts +255 -4
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +23 -42
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +1 -1
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +90 -1
- package/src/config/schemas/memory-v2.ts +26 -0
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/token-estimator.ts +10 -5
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
- package/src/daemon/conversation-agent-loop.ts +132 -28
- package/src/daemon/conversation-error.ts +33 -5
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +29 -9
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +33 -48
- package/src/daemon/conversation.ts +26 -46
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +27 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/lifecycle.ts +12 -12
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- package/src/daemon/message-types/conversations.ts +20 -22
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -2
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +23 -38
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +28 -29
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +352 -112
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +4 -0
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-worker.ts +12 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
- package/src/memory/llm-request-log-source-local.ts +24 -0
- package/src/memory/llm-request-log-source.ts +31 -0
- package/src/memory/llm-request-log-store.ts +188 -3
- package/src/memory/memory-v2-activation-log-store.ts +95 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edges.test.ts +144 -1
- package/src/memory/v3/__tests__/filter.test.ts +48 -0
- package/src/memory/v3/__tests__/gate.test.ts +96 -33
- package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
- package/src/memory/v3/__tests__/loop.test.ts +250 -5
- package/src/memory/v3/__tests__/scouts.test.ts +49 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
- package/src/memory/v3/__tests__/traversal.test.ts +39 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
- package/src/memory/v3/__tests__/validate.test.ts +32 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edges.ts +58 -21
- package/src/memory/v3/filter.ts +27 -22
- package/src/memory/v3/gate.ts +51 -36
- package/src/memory/v3/index-composition.ts +18 -5
- package/src/memory/v3/loop.ts +65 -17
- package/src/memory/v3/scouts.ts +15 -4
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +44 -2
- package/src/memory/v3/traversal.ts +6 -1
- package/src/memory/v3/tree-walk.ts +6 -1
- package/src/memory/v3/validate.ts +56 -33
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugins/defaults/injectors.ts +2 -8
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/types.ts +57 -13
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +7 -11
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/call-site-routing.ts +33 -9
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +24 -3
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +110 -12
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +53 -53
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +18 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -4
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +9 -0
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/auth/route-policy.ts +10 -0
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/migrations/vbundle-builder.ts +3 -2
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/background-wake-routes.ts +188 -20
- package/src/runtime/routes/btw-routes.ts +4 -4
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +147 -0
- package/src/runtime/routes/conversation-management-routes.ts +39 -14
- package/src/runtime/routes/conversation-query-routes.ts +60 -10
- package/src/runtime/routes/conversation-routes.ts +186 -140
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/group-routes.ts +11 -0
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-v3-routes.ts +160 -2
- package/src/runtime/routes/migration-routes.ts +20 -13
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/tools/apps/definitions.ts +35 -21
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +268 -266
- package/src/tools/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +2 -5
- package/src/tools/executor.ts +18 -55
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-search.ts +199 -44
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +146 -103
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +17 -15
- package/src/tools/ui-surface/definitions.ts +98 -86
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/util/browser.ts +7 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -13,6 +13,8 @@ let connectionStore: Record<
|
|
|
13
13
|
> = {};
|
|
14
14
|
let deletedConnectionIds: string[] = [];
|
|
15
15
|
let createdConnections: Array<{ provider: string; accountInfo?: string }> = [];
|
|
16
|
+
let updatedConnections: Array<{ id: string; accountInfo?: string | null }> = [];
|
|
17
|
+
let telegramBotUsername: string | undefined;
|
|
16
18
|
const warnings: string[] = [];
|
|
17
19
|
|
|
18
20
|
// ---------------------------------------------------------------------------
|
|
@@ -41,6 +43,10 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
41
43
|
},
|
|
42
44
|
}));
|
|
43
45
|
|
|
46
|
+
mock.module("../telegram/bot-username.js", () => ({
|
|
47
|
+
getTelegramBotUsername: () => telegramBotUsername,
|
|
48
|
+
}));
|
|
49
|
+
|
|
44
50
|
mock.module("../oauth/oauth-store.js", () => ({
|
|
45
51
|
getConnectionByProvider: (provider: string) =>
|
|
46
52
|
connectionStore[provider] ?? undefined,
|
|
@@ -72,7 +78,16 @@ mock.module("../oauth/oauth-store.js", () => ({
|
|
|
72
78
|
};
|
|
73
79
|
return { id: `conn-${params.provider}` };
|
|
74
80
|
},
|
|
75
|
-
updateConnection: () => {
|
|
81
|
+
updateConnection: (id: string, updates: { accountInfo?: string | null }) => {
|
|
82
|
+
updatedConnections.push({ id, accountInfo: updates.accountInfo });
|
|
83
|
+
for (const conn of Object.values(connectionStore)) {
|
|
84
|
+
if (conn.id === id) {
|
|
85
|
+
conn.accountInfo = updates.accountInfo;
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
},
|
|
76
91
|
upsertApp: async (_provider: string, _clientId: string) => ({
|
|
77
92
|
id: "app-1",
|
|
78
93
|
}),
|
|
@@ -119,6 +134,8 @@ describe("syncManualTokenConnection", () => {
|
|
|
119
134
|
connectionStore = {};
|
|
120
135
|
deletedConnectionIds = [];
|
|
121
136
|
createdConnections = [];
|
|
137
|
+
updatedConnections = [];
|
|
138
|
+
telegramBotUsername = undefined;
|
|
122
139
|
warnings.length = 0;
|
|
123
140
|
});
|
|
124
141
|
|
|
@@ -291,6 +308,62 @@ describe("syncManualTokenConnection", () => {
|
|
|
291
308
|
{ provider: "telegram", accountInfo: undefined },
|
|
292
309
|
]);
|
|
293
310
|
});
|
|
311
|
+
|
|
312
|
+
test("creates telegram connection with configured bot username when account is omitted", async () => {
|
|
313
|
+
telegramBotUsername = "example_bot";
|
|
314
|
+
setCredentialResult("telegram", "bot_token", {
|
|
315
|
+
value: "bot-token",
|
|
316
|
+
unreachable: false,
|
|
317
|
+
});
|
|
318
|
+
setCredentialResult("telegram", "webhook_secret", {
|
|
319
|
+
value: "webhook-secret",
|
|
320
|
+
unreachable: false,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await syncManualTokenConnection("telegram");
|
|
324
|
+
|
|
325
|
+
expect(createdConnections).toEqual([
|
|
326
|
+
{ provider: "telegram", accountInfo: "@example_bot" },
|
|
327
|
+
]);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
test("updates existing telegram connection with configured bot username when account is omitted", async () => {
|
|
331
|
+
telegramBotUsername = "@example_bot";
|
|
332
|
+
seedConnection("telegram");
|
|
333
|
+
setCredentialResult("telegram", "bot_token", {
|
|
334
|
+
value: "bot-token",
|
|
335
|
+
unreachable: false,
|
|
336
|
+
});
|
|
337
|
+
setCredentialResult("telegram", "webhook_secret", {
|
|
338
|
+
value: "webhook-secret",
|
|
339
|
+
unreachable: false,
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
await syncManualTokenConnection("telegram");
|
|
343
|
+
|
|
344
|
+
expect(updatedConnections).toEqual([
|
|
345
|
+
{ id: "conn-telegram", accountInfo: "@example_bot" },
|
|
346
|
+
]);
|
|
347
|
+
expect(connectionStore["telegram"]?.accountInfo).toBe("@example_bot");
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
test("preserves existing telegram account label when deriving bot username lazily", async () => {
|
|
351
|
+
telegramBotUsername = "@example_bot";
|
|
352
|
+
seedConnection("telegram", { accountInfo: "@existing_bot" });
|
|
353
|
+
setCredentialResult("telegram", "bot_token", {
|
|
354
|
+
value: "bot-token",
|
|
355
|
+
unreachable: false,
|
|
356
|
+
});
|
|
357
|
+
setCredentialResult("telegram", "webhook_secret", {
|
|
358
|
+
value: "webhook-secret",
|
|
359
|
+
unreachable: false,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
await syncManualTokenConnection("telegram");
|
|
363
|
+
|
|
364
|
+
expect(updatedConnections).toEqual([]);
|
|
365
|
+
expect(connectionStore["telegram"]?.accountInfo).toBe("@existing_bot");
|
|
366
|
+
});
|
|
294
367
|
});
|
|
295
368
|
|
|
296
369
|
describe("backfillManualTokenConnections", () => {
|
|
@@ -299,6 +372,8 @@ describe("backfillManualTokenConnections", () => {
|
|
|
299
372
|
connectionStore = {};
|
|
300
373
|
deletedConnectionIds = [];
|
|
301
374
|
createdConnections = [];
|
|
375
|
+
updatedConnections = [];
|
|
376
|
+
telegramBotUsername = undefined;
|
|
302
377
|
warnings.length = 0;
|
|
303
378
|
});
|
|
304
379
|
|
|
@@ -8,7 +8,21 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
10
|
mock.module("../config/env-registry.js", () => ({
|
|
11
|
+
getDebugStdoutLogs: () => false,
|
|
12
|
+
getIsContainerized: () => false,
|
|
11
13
|
getIsPlatform: () => false,
|
|
14
|
+
isPlatformRemote: () => false,
|
|
15
|
+
getWorkspaceDirOverride: () => undefined,
|
|
16
|
+
getBackupDirOverride: () => undefined,
|
|
17
|
+
getBackupKeyPathOverride: () => undefined,
|
|
18
|
+
getCpuLimit: () => undefined,
|
|
19
|
+
getMinikubeStorageSize: () => undefined,
|
|
20
|
+
getProfilerRunId: () => undefined,
|
|
21
|
+
getProfilerMode: () => undefined,
|
|
22
|
+
getProfilerMaxBytes: () => undefined,
|
|
23
|
+
getProfilerMaxRuns: () => undefined,
|
|
24
|
+
getProfilerMinFreeMb: () => undefined,
|
|
25
|
+
checkUnrecognizedEnvVars: () => [],
|
|
12
26
|
}));
|
|
13
27
|
|
|
14
28
|
const { McpClient } = await import("../mcp/client.js");
|
|
@@ -8,7 +8,21 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
10
|
mock.module("../config/env-registry.js", () => ({
|
|
11
|
+
getDebugStdoutLogs: () => false,
|
|
12
|
+
getIsContainerized: () => false,
|
|
11
13
|
getIsPlatform: () => false,
|
|
14
|
+
isPlatformRemote: () => false,
|
|
15
|
+
getWorkspaceDirOverride: () => undefined,
|
|
16
|
+
getBackupDirOverride: () => undefined,
|
|
17
|
+
getBackupKeyPathOverride: () => undefined,
|
|
18
|
+
getCpuLimit: () => undefined,
|
|
19
|
+
getMinikubeStorageSize: () => undefined,
|
|
20
|
+
getProfilerRunId: () => undefined,
|
|
21
|
+
getProfilerMode: () => undefined,
|
|
22
|
+
getProfilerMaxBytes: () => undefined,
|
|
23
|
+
getProfilerMaxRuns: () => undefined,
|
|
24
|
+
getProfilerMinFreeMb: () => undefined,
|
|
25
|
+
checkUnrecognizedEnvVars: () => [],
|
|
12
26
|
}));
|
|
13
27
|
|
|
14
28
|
const { McpClient } = await import("../mcp/client.js");
|
|
@@ -79,6 +79,7 @@ const getBindingByChannelChatMock = mock(
|
|
|
79
79
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
80
80
|
addMessage: addMessageMock,
|
|
81
81
|
getConversation: getConversationMock,
|
|
82
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
82
83
|
}));
|
|
83
84
|
|
|
84
85
|
mock.module("../memory/conversation-disk-view.js", () => ({
|
|
@@ -118,13 +118,13 @@ mock.module("../config/env.js", () => ({
|
|
|
118
118
|
// Imports (after mocks so module-level code picks up the stubs)
|
|
119
119
|
// ---------------------------------------------------------------------------
|
|
120
120
|
|
|
121
|
-
import { resetDb } from "../memory/db-connection.js";
|
|
122
121
|
import { defaultV1Options } from "../runtime/migrations/__tests__/v1-test-helpers.js";
|
|
123
122
|
import { buildVBundle } from "../runtime/migrations/vbundle-builder.js";
|
|
124
123
|
import {
|
|
125
124
|
_setUrlImportValidatorOptionsForTests,
|
|
126
125
|
handleMigrationImport,
|
|
127
126
|
} from "../runtime/routes/migration-routes.js";
|
|
127
|
+
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
128
128
|
import { callHandler } from "./helpers/call-route-handler.js";
|
|
129
129
|
// ---------------------------------------------------------------------------
|
|
130
130
|
// Local http fixture server
|
|
@@ -448,7 +448,7 @@ describe("handleMigrationImport — no-swap path omits newer-migration warning",
|
|
|
448
448
|
|
|
449
449
|
// Drop any cached Drizzle singleton so getDb() re-opens from the
|
|
450
450
|
// seeded path above when the handler calls it post-import.
|
|
451
|
-
|
|
451
|
+
resetDbForTesting();
|
|
452
452
|
|
|
453
453
|
// All-`vellum:*` credentials bundle: the streaming importer returns
|
|
454
454
|
// ok=true with zero files_created/overwritten (no-swap success),
|
|
@@ -505,7 +505,7 @@ describe("handleMigrationImport — no-swap path omits newer-migration warning",
|
|
|
505
505
|
await fixture.close();
|
|
506
506
|
// Close the cached DB handle before the workspace dir gets rm'd
|
|
507
507
|
// in afterEach so we don't leak WAL/SHM files across tests.
|
|
508
|
-
|
|
508
|
+
resetDbForTesting();
|
|
509
509
|
}
|
|
510
510
|
});
|
|
511
511
|
});
|
|
@@ -56,7 +56,9 @@ class FakePersistentIpcClient extends EventEmitter {
|
|
|
56
56
|
if (simulateError) {
|
|
57
57
|
throw new Error("Mock IPC socket error");
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
if (method in ipcResults) return ipcResults[method];
|
|
60
|
+
if (method === "get_feature_flags") return GET_FEATURE_FLAGS_DEFAULT;
|
|
61
|
+
return undefined;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
destroy(): void {
|
|
@@ -68,6 +70,18 @@ class FakePersistentIpcClient extends EventEmitter {
|
|
|
68
70
|
// Register the mock (called once from test-preload.ts)
|
|
69
71
|
// ---------------------------------------------------------------------------
|
|
70
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Sentinel returned by the mock for `get_feature_flags` when a test has not
|
|
75
|
+
* explicitly configured a result. Keeps the response non-empty so
|
|
76
|
+
* `initFeatureFlagOverrides()` does not enter its 7.75 s empty-result retry
|
|
77
|
+
* loop during tests that build the CLI program or otherwise trigger flag
|
|
78
|
+
* initialization. The sentinel key starts with a double underscore so it
|
|
79
|
+
* cannot collide with any real registry-declared flag.
|
|
80
|
+
*/
|
|
81
|
+
const GET_FEATURE_FLAGS_DEFAULT: Record<string, boolean> = {
|
|
82
|
+
__test_default__: false,
|
|
83
|
+
};
|
|
84
|
+
|
|
71
85
|
export function installGatewayIpcMock(): void {
|
|
72
86
|
mock.module("@vellumai/gateway-client/ipc-client", () => ({
|
|
73
87
|
ipcCall: async (
|
|
@@ -79,7 +93,9 @@ export function installGatewayIpcMock(): void {
|
|
|
79
93
|
// Real ipcCall returns undefined on failure — mirror that behavior.
|
|
80
94
|
return undefined;
|
|
81
95
|
}
|
|
82
|
-
|
|
96
|
+
if (method in ipcResults) return ipcResults[method];
|
|
97
|
+
if (method === "get_feature_flags") return GET_FEATURE_FLAGS_DEFAULT;
|
|
98
|
+
return undefined;
|
|
83
99
|
},
|
|
84
100
|
PersistentIpcClient: FakePersistentIpcClient,
|
|
85
101
|
}));
|
|
@@ -20,7 +20,7 @@ describe("model intents", () => {
|
|
|
20
20
|
"claude-haiku-4-5-20251001",
|
|
21
21
|
);
|
|
22
22
|
expect(resolveModelIntent("anthropic", "quality-optimized")).toBe(
|
|
23
|
-
"claude-opus-4-
|
|
23
|
+
"claude-opus-4-8",
|
|
24
24
|
);
|
|
25
25
|
expect(resolveModelIntent("anthropic", "vision-optimized")).toBe(
|
|
26
26
|
"claude-opus-4-6",
|
|
@@ -44,9 +44,9 @@ describe("model intents", () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test("falls back to provider default for unknown providers", () => {
|
|
47
|
-
expect(getProviderDefaultModel("unknown-provider")).toBe("claude-opus-4-
|
|
47
|
+
expect(getProviderDefaultModel("unknown-provider")).toBe("claude-opus-4-8");
|
|
48
48
|
expect(resolveModelIntent("unknown-provider", "quality-optimized")).toBe(
|
|
49
|
-
"claude-opus-4-
|
|
49
|
+
"claude-opus-4-8",
|
|
50
50
|
);
|
|
51
51
|
});
|
|
52
52
|
});
|
|
@@ -51,8 +51,7 @@ mock.module("@anthropic-ai/sdk", () => ({
|
|
|
51
51
|
_options?: Record<string, unknown>,
|
|
52
52
|
) => {
|
|
53
53
|
lastStreamParams = JSON.parse(JSON.stringify(params));
|
|
54
|
-
const handlers: Record<string, ((...args: unknown[]) => void)[]> =
|
|
55
|
-
{};
|
|
54
|
+
const handlers: Record<string, ((...args: unknown[]) => void)[]> = {};
|
|
56
55
|
return {
|
|
57
56
|
on(event: string, cb: (...args: unknown[]) => void) {
|
|
58
57
|
(handlers[event] ??= []).push(cb);
|
|
@@ -74,6 +73,7 @@ mock.module("@anthropic-ai/sdk", () => ({
|
|
|
74
73
|
|
|
75
74
|
// Import after mocking
|
|
76
75
|
import { AnthropicProvider } from "../providers/anthropic/client.js";
|
|
76
|
+
import { isNativeWebSearchCapableProvider } from "../providers/registry.js";
|
|
77
77
|
|
|
78
78
|
// ---------------------------------------------------------------------------
|
|
79
79
|
// Helpers
|
|
@@ -99,6 +99,34 @@ const sampleTools: ToolDefinition[] = [
|
|
|
99
99
|
},
|
|
100
100
|
];
|
|
101
101
|
|
|
102
|
+
describe("Native Web Search — Selection Semantics", () => {
|
|
103
|
+
test("only native-capable inference providers/models request provider-native web search", () => {
|
|
104
|
+
expect(
|
|
105
|
+
isNativeWebSearchCapableProvider("anthropic", "claude-opus-4-7"),
|
|
106
|
+
).toBe(true);
|
|
107
|
+
expect(isNativeWebSearchCapableProvider("openai", "gpt-5")).toBe(true);
|
|
108
|
+
expect(
|
|
109
|
+
isNativeWebSearchCapableProvider(
|
|
110
|
+
"openrouter",
|
|
111
|
+
"anthropic/claude-opus-4-7",
|
|
112
|
+
),
|
|
113
|
+
).toBe(true);
|
|
114
|
+
|
|
115
|
+
expect(
|
|
116
|
+
isNativeWebSearchCapableProvider(
|
|
117
|
+
"fireworks",
|
|
118
|
+
"accounts/fireworks/models/kimi-k2p6",
|
|
119
|
+
),
|
|
120
|
+
).toBe(false);
|
|
121
|
+
expect(isNativeWebSearchCapableProvider("gemini", "gemini-3.1-pro")).toBe(
|
|
122
|
+
false,
|
|
123
|
+
);
|
|
124
|
+
expect(isNativeWebSearchCapableProvider("openrouter", "openai/gpt-5")).toBe(
|
|
125
|
+
false,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
102
130
|
// ---------------------------------------------------------------------------
|
|
103
131
|
// Tests — Round-trip: fromAnthropicBlock
|
|
104
132
|
// ---------------------------------------------------------------------------
|
|
@@ -38,6 +38,13 @@ mock.module("../notifications/deliveries-store.js", () => ({
|
|
|
38
38
|
findDeliveryByDecisionAndChannel: () => undefined,
|
|
39
39
|
}));
|
|
40
40
|
|
|
41
|
+
// Mock conversation-crud so the broadcaster's source-context fallback lookup
|
|
42
|
+
// can be driven from tests without DB access.
|
|
43
|
+
let mockExistingConversations: Record<string, { id: string }> = {};
|
|
44
|
+
mock.module("../memory/conversation-crud.js", () => ({
|
|
45
|
+
getConversation: (id: string) => mockExistingConversations[id] ?? null,
|
|
46
|
+
}));
|
|
47
|
+
|
|
41
48
|
// Configurable mock for conversation-pairing
|
|
42
49
|
let nextPairingResult:
|
|
43
50
|
| import("../notifications/conversation-pairing.js").PairingResult
|
|
@@ -141,6 +148,7 @@ class MockAdapter implements ChannelAdapter {
|
|
|
141
148
|
describe("notification deep-link metadata", () => {
|
|
142
149
|
beforeEach(() => {
|
|
143
150
|
nextPairingResult = null;
|
|
151
|
+
mockExistingConversations = {};
|
|
144
152
|
});
|
|
145
153
|
|
|
146
154
|
describe("VellumAdapter", () => {
|
|
@@ -600,5 +608,59 @@ describe("notification deep-link metadata", () => {
|
|
|
600
608
|
expect(deepLink1!.messageId).toBe("msg-delivery-1");
|
|
601
609
|
expect(deepLink2!.messageId).toBe("msg-delivery-2");
|
|
602
610
|
});
|
|
611
|
+
|
|
612
|
+
// ── Source-context fallback when pairing yields no conversation ──
|
|
613
|
+
|
|
614
|
+
test("falls back to signal.sourceContextId for deep link when pairing returns no conversation and sourceContextId resolves", async () => {
|
|
615
|
+
const vellumAdapter = new MockAdapter("vellum");
|
|
616
|
+
const broadcaster = new NotificationBroadcaster([vellumAdapter]);
|
|
617
|
+
|
|
618
|
+
// Passive vellum signal: pairing skips creation, returns null.
|
|
619
|
+
nextPairingResult = {
|
|
620
|
+
conversationId: null,
|
|
621
|
+
messageId: null,
|
|
622
|
+
strategy: "start_new_conversation" as const,
|
|
623
|
+
createdNewConversation: false,
|
|
624
|
+
conversationFallbackUsed: false,
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
const originConvId = "conv-origin-of-event";
|
|
628
|
+
mockExistingConversations[originConvId] = { id: originConvId };
|
|
629
|
+
|
|
630
|
+
const signal = makeSignal({ sourceContextId: originConvId });
|
|
631
|
+
const decision = makeDecision();
|
|
632
|
+
|
|
633
|
+
await broadcaster.broadcastDecision(signal, decision);
|
|
634
|
+
|
|
635
|
+
expect(vellumAdapter.sent).toHaveLength(1);
|
|
636
|
+
const deepLink = vellumAdapter.sent[0].deepLinkTarget;
|
|
637
|
+
expect(deepLink).toBeDefined();
|
|
638
|
+
expect(deepLink!.conversationId).toBe(originConvId);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
test("omits conversationId from deep link when pairing returns no conversation and sourceContextId is a sentinel", async () => {
|
|
642
|
+
const vellumAdapter = new MockAdapter("vellum");
|
|
643
|
+
const broadcaster = new NotificationBroadcaster([vellumAdapter]);
|
|
644
|
+
|
|
645
|
+
nextPairingResult = {
|
|
646
|
+
conversationId: null,
|
|
647
|
+
messageId: null,
|
|
648
|
+
strategy: "start_new_conversation" as const,
|
|
649
|
+
createdNewConversation: false,
|
|
650
|
+
conversationFallbackUsed: false,
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
// Sentinel sourceContextId (job ID, access-req-*, etc.) — getConversation returns null.
|
|
654
|
+
const signal = makeSignal({ sourceContextId: "access-req-sentinel-xyz" });
|
|
655
|
+
const decision = makeDecision();
|
|
656
|
+
|
|
657
|
+
await broadcaster.broadcastDecision(signal, decision);
|
|
658
|
+
|
|
659
|
+
expect(vellumAdapter.sent).toHaveLength(1);
|
|
660
|
+
const deepLink = vellumAdapter.sent[0].deepLinkTarget;
|
|
661
|
+
// Decision did not carry a deepLinkTarget either — the resulting
|
|
662
|
+
// deep link should be undefined or have no conversationId.
|
|
663
|
+
expect(deepLink?.conversationId).toBeUndefined();
|
|
664
|
+
});
|
|
603
665
|
});
|
|
604
666
|
});
|
|
@@ -21,6 +21,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
21
21
|
|
|
22
22
|
interface MockProviderRow {
|
|
23
23
|
provider: string;
|
|
24
|
+
authorizeUrl: string;
|
|
24
25
|
managedServiceConfigKey: string | null;
|
|
25
26
|
baseUrl: string | null;
|
|
26
27
|
injectionTemplates: string | null;
|
|
@@ -32,6 +33,7 @@ interface MockProviderRow {
|
|
|
32
33
|
|
|
33
34
|
const baseProvider: MockProviderRow = {
|
|
34
35
|
provider: "google",
|
|
36
|
+
authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
35
37
|
managedServiceConfigKey: "google-oauth",
|
|
36
38
|
baseUrl: "https://api.google.com",
|
|
37
39
|
injectionTemplates: null,
|
|
@@ -69,6 +71,7 @@ let mockResolveResponse: {
|
|
|
69
71
|
body: unknown;
|
|
70
72
|
} = { status: 200, headers: {}, body: { ok: true } };
|
|
71
73
|
let mockResolveRequests: unknown[] = [];
|
|
74
|
+
let mockSyncManualTokenCalls: string[] = [];
|
|
72
75
|
|
|
73
76
|
const mockDisconnectOAuthProvider = mock(() => Promise.resolve());
|
|
74
77
|
const mockSaveRawConfig = mock(() => undefined);
|
|
@@ -117,6 +120,12 @@ mock.module("../oauth/connection-resolver.js", () => ({
|
|
|
117
120
|
}),
|
|
118
121
|
}));
|
|
119
122
|
|
|
123
|
+
mock.module("../oauth/manual-token-connection.js", () => ({
|
|
124
|
+
syncManualTokenConnection: async (provider: string) => {
|
|
125
|
+
mockSyncManualTokenCalls.push(provider);
|
|
126
|
+
},
|
|
127
|
+
}));
|
|
128
|
+
|
|
120
129
|
mock.module("../platform/client.js", () => ({
|
|
121
130
|
VellumPlatformClient: {
|
|
122
131
|
create: async () => {
|
|
@@ -212,6 +221,7 @@ beforeEach(() => {
|
|
|
212
221
|
});
|
|
213
222
|
mockResolveResponse = { status: 200, headers: {}, body: { ok: true } };
|
|
214
223
|
mockResolveRequests = [];
|
|
224
|
+
mockSyncManualTokenCalls = [];
|
|
215
225
|
mockDisconnectOAuthProvider.mockClear();
|
|
216
226
|
mockSaveRawConfig.mockClear();
|
|
217
227
|
});
|
|
@@ -475,6 +485,33 @@ describe("GET oauth/status", () => {
|
|
|
475
485
|
expect(result.connections[0]!.grantedScopes).toEqual([]);
|
|
476
486
|
});
|
|
477
487
|
|
|
488
|
+
test("BYO mode reconciles manual-token providers before listing status", async () => {
|
|
489
|
+
mockProviders.telegram = {
|
|
490
|
+
...baseProvider,
|
|
491
|
+
provider: "telegram",
|
|
492
|
+
authorizeUrl: "urn:manual-token",
|
|
493
|
+
managedServiceConfigKey: null,
|
|
494
|
+
baseUrl: "https://api.telegram.org",
|
|
495
|
+
};
|
|
496
|
+
mockAllConnections.telegram = [
|
|
497
|
+
{
|
|
498
|
+
id: "conn-telegram",
|
|
499
|
+
accountInfo: "@example_bot",
|
|
500
|
+
grantedScopes: "[]",
|
|
501
|
+
status: "active",
|
|
502
|
+
hasRefreshToken: 0,
|
|
503
|
+
expiresAt: null,
|
|
504
|
+
},
|
|
505
|
+
];
|
|
506
|
+
|
|
507
|
+
const result = (await getRoute("GET", "oauth/status").handler(
|
|
508
|
+
makeArgs({ queryParams: { provider: "telegram" } }),
|
|
509
|
+
)) as { connections: Array<{ account: string | null }> };
|
|
510
|
+
|
|
511
|
+
expect(mockSyncManualTokenCalls).toEqual(["telegram"]);
|
|
512
|
+
expect(result.connections[0]!.account).toBe("@example_bot");
|
|
513
|
+
});
|
|
514
|
+
|
|
478
515
|
test("managed mode surfaces platform connections", async () => {
|
|
479
516
|
mockServiceModes["google-oauth"] = "managed";
|
|
480
517
|
mockFetchImpl = async () => ({
|
|
@@ -21,13 +21,13 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
21
21
|
getSecureKeyAsync: () => Promise.resolve(undefined),
|
|
22
22
|
}));
|
|
23
23
|
|
|
24
|
-
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
25
24
|
import type { AssistantConfig } from "../config/schema.js";
|
|
26
|
-
import { resetDb } from "../memory/db-connection.js";
|
|
27
25
|
import { initializeDb } from "../memory/db-init.js";
|
|
28
26
|
import { resetTestTables } from "../memory/raw-query.js";
|
|
29
27
|
import { listProviders, seedProviders } from "../oauth/oauth-store.js";
|
|
30
28
|
import { isProviderVisible } from "../oauth/provider-visibility.js";
|
|
29
|
+
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
30
|
+
import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
|
|
31
31
|
|
|
32
32
|
initializeDb();
|
|
33
33
|
|
|
@@ -38,15 +38,15 @@ function makeConfig(): AssistantConfig {
|
|
|
38
38
|
|
|
39
39
|
beforeEach(() => {
|
|
40
40
|
resetTestTables("oauth_connections", "oauth_apps", "oauth_providers");
|
|
41
|
-
|
|
41
|
+
setOverridesForTesting({});
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
afterEach(() => {
|
|
45
|
-
|
|
45
|
+
setOverridesForTesting({});
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
afterAll(() => {
|
|
49
|
-
|
|
49
|
+
resetDbForTesting();
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
describe("isProviderVisible", () => {
|
|
@@ -70,7 +70,7 @@ describe("isProviderVisible", () => {
|
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
test("returns true when featureFlag is set and the flag is enabled", () => {
|
|
73
|
-
|
|
73
|
+
setOverridesForTesting({ "test-gate": true });
|
|
74
74
|
|
|
75
75
|
seedProviders([
|
|
76
76
|
{
|
|
@@ -93,7 +93,7 @@ describe("isProviderVisible", () => {
|
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
test("returns false when featureFlag is set and the flag is disabled", () => {
|
|
96
|
-
|
|
96
|
+
setOverridesForTesting({ "test-gate": false });
|
|
97
97
|
|
|
98
98
|
seedProviders([
|
|
99
99
|
{
|
|
@@ -115,7 +115,7 @@ describe("isProviderVisible", () => {
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
test("listProviders returns all providers but isProviderVisible filters gated ones when flag is disabled", () => {
|
|
118
|
-
|
|
118
|
+
setOverridesForTesting({ "test-gate": false });
|
|
119
119
|
|
|
120
120
|
seedProviders([
|
|
121
121
|
{
|
|
@@ -42,7 +42,7 @@ mock.module("../oauth/credential-token-resolver.js", () => ({
|
|
|
42
42
|
|
|
43
43
|
import { eq } from "drizzle-orm";
|
|
44
44
|
|
|
45
|
-
import { getDb
|
|
45
|
+
import { getDb } from "../memory/db-connection.js";
|
|
46
46
|
import { getSqliteFrom } from "../memory/db-connection.js";
|
|
47
47
|
import { initializeDb } from "../memory/db-init.js";
|
|
48
48
|
import { migrateOAuthProvidersTokenAuthMethodDefault } from "../memory/migrations/216-oauth-providers-token-auth-method.js";
|
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
upsertApp,
|
|
71
71
|
} from "../oauth/oauth-store.js";
|
|
72
72
|
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
73
|
+
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
73
74
|
import { getMockFetchCalls, mockFetch, resetMockFetch } from "./mock-fetch.js";
|
|
74
75
|
|
|
75
76
|
initializeDb();
|
|
@@ -103,7 +104,7 @@ beforeEach(() => {
|
|
|
103
104
|
});
|
|
104
105
|
|
|
105
106
|
afterAll(() => {
|
|
106
|
-
|
|
107
|
+
resetDbForTesting();
|
|
107
108
|
});
|
|
108
109
|
|
|
109
110
|
// ---------------------------------------------------------------------------
|
|
@@ -111,8 +111,9 @@ describe("onboarding template contracts", () => {
|
|
|
111
111
|
expect(identity).toContain("**Emoji:**");
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
test("
|
|
115
|
-
expect(identity).toContain("
|
|
114
|
+
test("does not invite assistant-owned identity restructuring", () => {
|
|
115
|
+
expect(identity).not.toContain("This file is yours");
|
|
116
|
+
expect(identity).not.toContain("parsed by the app");
|
|
116
117
|
});
|
|
117
118
|
});
|
|
118
119
|
|
|
@@ -1557,32 +1557,32 @@ describe("OpenRouterProvider reasoning", () => {
|
|
|
1557
1557
|
});
|
|
1558
1558
|
});
|
|
1559
1559
|
|
|
1560
|
-
test("
|
|
1560
|
+
test("omits reasoning when thinking is explicitly disabled", async () => {
|
|
1561
1561
|
const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
|
|
1562
1562
|
await provider.sendMessage([userMsg("hi")], undefined, undefined, {
|
|
1563
1563
|
config: { thinking: { type: "disabled" } },
|
|
1564
1564
|
});
|
|
1565
1565
|
|
|
1566
1566
|
expect(lastCreateParams).toBeTruthy();
|
|
1567
|
-
expect(lastCreateParams!.reasoning).
|
|
1567
|
+
expect(lastCreateParams!.reasoning).toBeUndefined();
|
|
1568
1568
|
});
|
|
1569
1569
|
|
|
1570
|
-
test("
|
|
1570
|
+
test("omits reasoning when thinking config is absent", async () => {
|
|
1571
1571
|
const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
|
|
1572
1572
|
await provider.sendMessage([userMsg("hi")], undefined, undefined, {
|
|
1573
1573
|
config: {},
|
|
1574
1574
|
});
|
|
1575
1575
|
|
|
1576
1576
|
expect(lastCreateParams).toBeTruthy();
|
|
1577
|
-
expect(lastCreateParams!.reasoning).
|
|
1577
|
+
expect(lastCreateParams!.reasoning).toBeUndefined();
|
|
1578
1578
|
});
|
|
1579
1579
|
|
|
1580
|
-
test("
|
|
1580
|
+
test("omits reasoning when no options are provided", async () => {
|
|
1581
1581
|
const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
|
|
1582
1582
|
await provider.sendMessage([userMsg("hi")]);
|
|
1583
1583
|
|
|
1584
1584
|
expect(lastCreateParams).toBeTruthy();
|
|
1585
|
-
expect(lastCreateParams!.reasoning).
|
|
1585
|
+
expect(lastCreateParams!.reasoning).toBeUndefined();
|
|
1586
1586
|
});
|
|
1587
1587
|
|
|
1588
1588
|
test("sends OpenRouter app-attribution headers on OpenAI-compatible requests", async () => {
|
|
@@ -1623,15 +1623,14 @@ describe("OpenRouterProvider reasoning", () => {
|
|
|
1623
1623
|
});
|
|
1624
1624
|
});
|
|
1625
1625
|
|
|
1626
|
-
test("RetryProvider + OpenRouterProvider
|
|
1626
|
+
test("RetryProvider + OpenRouterProvider omits reasoning when thinking disabled", async () => {
|
|
1627
1627
|
const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
|
|
1628
1628
|
const retry = new RetryProvider(provider);
|
|
1629
1629
|
|
|
1630
|
-
// thinking disabled at loop-level can arrive as an explicit disabled config.
|
|
1631
1630
|
await retry.sendMessage([userMsg("hi")], undefined, undefined, {
|
|
1632
1631
|
config: { thinking: { type: "disabled" } },
|
|
1633
1632
|
});
|
|
1634
|
-
expect(lastCreateParams!.reasoning).
|
|
1633
|
+
expect(lastCreateParams!.reasoning).toBeUndefined();
|
|
1635
1634
|
});
|
|
1636
1635
|
|
|
1637
1636
|
test("nests effort under reasoning and omits top-level reasoning_effort", async () => {
|