@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
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* When IS_PLATFORM=true and no config.json exists yet, loadConfig() must
|
|
3
|
-
* write all
|
|
4
|
-
* schema default
|
|
5
|
-
* config.json already exists, the schema defaults and existing values
|
|
6
|
-
* preserved unchanged
|
|
3
|
+
* write all managed-capable service modes as "managed" instead of the
|
|
4
|
+
* per-service schema default. When IS_PLATFORM is absent/false, or when
|
|
5
|
+
* config.json already exists, the Zod schema defaults and existing values
|
|
6
|
+
* are preserved unchanged — note that `google-oauth` and `notion-oauth`
|
|
7
|
+
* default to "managed" at the schema level (per JARVIS-966), while every
|
|
8
|
+
* other managed-capable service defaults to "your-own".
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
import {
|
|
@@ -59,7 +61,7 @@ afterAll(() => {
|
|
|
59
61
|
|
|
60
62
|
import { invalidateConfigCache, loadConfig } from "../config/loader.js";
|
|
61
63
|
import { applyContextDefaultsToRawConfig } from "../runtime/routes/conversation-query-routes.js";
|
|
62
|
-
import {
|
|
64
|
+
import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
|
|
63
65
|
|
|
64
66
|
// ---------------------------------------------------------------------------
|
|
65
67
|
// Helpers
|
|
@@ -91,6 +93,9 @@ function readConfig(): Record<string, unknown> {
|
|
|
91
93
|
return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
// When IS_PLATFORM=true, every managed-capable service defaults to "managed".
|
|
97
|
+
// Without IS_PLATFORM, services split by Zod schema default: google/notion-oauth
|
|
98
|
+
// resolve to "managed" (per JARVIS-966), the rest resolve to "your-own".
|
|
94
99
|
const MANAGED_SERVICES = [
|
|
95
100
|
"image-generation",
|
|
96
101
|
"web-search",
|
|
@@ -101,6 +106,28 @@ const MANAGED_SERVICES = [
|
|
|
101
106
|
"notion-oauth",
|
|
102
107
|
] as const;
|
|
103
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Services whose Zod schema default is `"managed"` rather than `"your-own"`.
|
|
111
|
+
* For these, the fresh-write and in-memory paths produce `"managed"` even
|
|
112
|
+
* when IS_PLATFORM is false/unset — the schema default applies regardless of
|
|
113
|
+
* deployment context. See `assistant/src/config/schemas/services.ts` and
|
|
114
|
+
* JARVIS-966: managed mode is the optimization target for new users on
|
|
115
|
+
* managed-capable infra, since the BYO flow requires a Google Cloud /
|
|
116
|
+
* Notion integration setup that most users never complete.
|
|
117
|
+
*/
|
|
118
|
+
const SCHEMA_MANAGED_DEFAULT_SERVICES = [
|
|
119
|
+
"google-oauth",
|
|
120
|
+
"notion-oauth",
|
|
121
|
+
] as const;
|
|
122
|
+
|
|
123
|
+
const SCHEMA_YOUR_OWN_DEFAULT_SERVICES = [
|
|
124
|
+
"image-generation",
|
|
125
|
+
"web-search",
|
|
126
|
+
"outlook-oauth",
|
|
127
|
+
"linear-oauth",
|
|
128
|
+
"github-oauth",
|
|
129
|
+
] as const;
|
|
130
|
+
|
|
104
131
|
// ---------------------------------------------------------------------------
|
|
105
132
|
// Tests
|
|
106
133
|
// ---------------------------------------------------------------------------
|
|
@@ -110,12 +137,12 @@ describe("platform-managed config defaults", () => {
|
|
|
110
137
|
|
|
111
138
|
beforeEach(() => {
|
|
112
139
|
resetWorkspace();
|
|
113
|
-
|
|
140
|
+
setStorePathForTesting(join(WORKSPACE_DIR, "keys.enc"));
|
|
114
141
|
invalidateConfigCache();
|
|
115
142
|
});
|
|
116
143
|
|
|
117
144
|
afterEach(() => {
|
|
118
|
-
|
|
145
|
+
setStorePathForTesting(null);
|
|
119
146
|
invalidateConfigCache();
|
|
120
147
|
// Restore env to its original value
|
|
121
148
|
if (originalIsPlatform === undefined) {
|
|
@@ -137,9 +164,12 @@ describe("platform-managed config defaults", () => {
|
|
|
137
164
|
for (const svc of MANAGED_SERVICES) {
|
|
138
165
|
expect((services[svc] as { mode?: string })?.mode).toBe("managed");
|
|
139
166
|
}
|
|
167
|
+
expect((services["web-search"] as { provider?: string })?.provider).toBe(
|
|
168
|
+
"inference-provider-native",
|
|
169
|
+
);
|
|
140
170
|
});
|
|
141
171
|
|
|
142
|
-
test("IS_PLATFORM=false, no config file →
|
|
172
|
+
test("IS_PLATFORM=false, no config file → service modes follow schema defaults (your-own except google/notion-oauth which are managed)", () => {
|
|
143
173
|
process.env.IS_PLATFORM = "false";
|
|
144
174
|
|
|
145
175
|
loadConfig();
|
|
@@ -148,12 +178,15 @@ describe("platform-managed config defaults", () => {
|
|
|
148
178
|
const written = readConfig() as { services?: Record<string, unknown> };
|
|
149
179
|
expect(written.services).toBeDefined();
|
|
150
180
|
const services = written.services!;
|
|
151
|
-
for (const svc of
|
|
181
|
+
for (const svc of SCHEMA_YOUR_OWN_DEFAULT_SERVICES) {
|
|
152
182
|
expect((services[svc] as { mode?: string })?.mode).toBe("your-own");
|
|
153
183
|
}
|
|
184
|
+
for (const svc of SCHEMA_MANAGED_DEFAULT_SERVICES) {
|
|
185
|
+
expect((services[svc] as { mode?: string })?.mode).toBe("managed");
|
|
186
|
+
}
|
|
154
187
|
});
|
|
155
188
|
|
|
156
|
-
test("IS_PLATFORM unset, no config file →
|
|
189
|
+
test("IS_PLATFORM unset, no config file → service modes follow schema defaults (your-own except google/notion-oauth which are managed)", () => {
|
|
157
190
|
delete process.env.IS_PLATFORM;
|
|
158
191
|
|
|
159
192
|
loadConfig();
|
|
@@ -162,9 +195,12 @@ describe("platform-managed config defaults", () => {
|
|
|
162
195
|
const written = readConfig() as { services?: Record<string, unknown> };
|
|
163
196
|
expect(written.services).toBeDefined();
|
|
164
197
|
const services = written.services!;
|
|
165
|
-
for (const svc of
|
|
198
|
+
for (const svc of SCHEMA_YOUR_OWN_DEFAULT_SERVICES) {
|
|
166
199
|
expect((services[svc] as { mode?: string })?.mode).toBe("your-own");
|
|
167
200
|
}
|
|
201
|
+
for (const svc of SCHEMA_MANAGED_DEFAULT_SERVICES) {
|
|
202
|
+
expect((services[svc] as { mode?: string })?.mode).toBe("managed");
|
|
203
|
+
}
|
|
168
204
|
});
|
|
169
205
|
|
|
170
206
|
test("IS_PLATFORM=true, config file already exists → existing service mode values are preserved", () => {
|
|
@@ -197,6 +233,37 @@ describe("platform-managed config defaults", () => {
|
|
|
197
233
|
expect(config.services["image-generation"].mode).toBe("your-own");
|
|
198
234
|
});
|
|
199
235
|
|
|
236
|
+
test("IS_PLATFORM=true, config file with explicit notion-oauth mode='your-own' → preserved (schema default is 'managed')", () => {
|
|
237
|
+
process.env.IS_PLATFORM = "true";
|
|
238
|
+
|
|
239
|
+
// notion-oauth's schema default is "managed" (per JARVIS-966), but an
|
|
240
|
+
// explicit user choice of "your-own" must win — the fill-defaults pass
|
|
241
|
+
// must never override an explicit value, even one that contradicts the
|
|
242
|
+
// schema default. Mirror of the image-generation "your-own preserved"
|
|
243
|
+
// test above, but for a service whose schema default is "managed".
|
|
244
|
+
writeFileSync(
|
|
245
|
+
CONFIG_PATH,
|
|
246
|
+
JSON.stringify(
|
|
247
|
+
{
|
|
248
|
+
services: {
|
|
249
|
+
"notion-oauth": { mode: "your-own" },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
null,
|
|
253
|
+
2,
|
|
254
|
+
) + "\n",
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const config = loadConfig();
|
|
258
|
+
|
|
259
|
+
const written = readConfig() as { services?: Record<string, unknown> };
|
|
260
|
+
expect(written.services).toBeDefined();
|
|
261
|
+
expect((written.services!["notion-oauth"] as { mode?: string })?.mode).toBe(
|
|
262
|
+
"your-own",
|
|
263
|
+
);
|
|
264
|
+
expect(config.services["notion-oauth"].mode).toBe("your-own");
|
|
265
|
+
});
|
|
266
|
+
|
|
200
267
|
test("IS_PLATFORM=true, config file exists without a services key → in-memory config has all managed modes", () => {
|
|
201
268
|
// Regression guard for the platform-managed boot order: by the time
|
|
202
269
|
// `loadConfig()` runs, lifecycle steps such as `seedInferenceProfiles`
|
|
@@ -228,12 +295,8 @@ describe("platform-managed config defaults", () => {
|
|
|
228
295
|
// missing service-mode fields.
|
|
229
296
|
for (const svc of MANAGED_SERVICES) {
|
|
230
297
|
expect(
|
|
231
|
-
(
|
|
232
|
-
|
|
233
|
-
string,
|
|
234
|
-
{ mode: string }
|
|
235
|
-
>
|
|
236
|
-
)[svc]!.mode,
|
|
298
|
+
(config.services as unknown as Record<string, { mode: string }>)[svc]!
|
|
299
|
+
.mode,
|
|
237
300
|
).toBe("managed");
|
|
238
301
|
}
|
|
239
302
|
|
|
@@ -277,9 +340,11 @@ describe("platform-managed config defaults", () => {
|
|
|
277
340
|
expect(imageGen.provider).toBe("openai");
|
|
278
341
|
});
|
|
279
342
|
|
|
280
|
-
test("IS_PLATFORM=false, config file exists without services key → in-memory config keeps schema your-own
|
|
343
|
+
test("IS_PLATFORM=false, config file exists without services key → in-memory config keeps schema defaults (your-own except google/notion-oauth which are managed)", () => {
|
|
281
344
|
// Sanity guard: deployment-context defaults are a no-op when IS_PLATFORM
|
|
282
|
-
// is not enabled, regardless of whether config.json existed.
|
|
345
|
+
// is not enabled, regardless of whether config.json existed. The Zod
|
|
346
|
+
// schema defaults still apply, so google-oauth and notion-oauth resolve
|
|
347
|
+
// to "managed" while the remaining services resolve to "your-own".
|
|
283
348
|
process.env.IS_PLATFORM = "false";
|
|
284
349
|
|
|
285
350
|
writeFileSync(
|
|
@@ -300,16 +365,18 @@ describe("platform-managed config defaults", () => {
|
|
|
300
365
|
|
|
301
366
|
const config = loadConfig();
|
|
302
367
|
|
|
303
|
-
for (const svc of
|
|
368
|
+
for (const svc of SCHEMA_YOUR_OWN_DEFAULT_SERVICES) {
|
|
304
369
|
expect(
|
|
305
|
-
(
|
|
306
|
-
|
|
307
|
-
string,
|
|
308
|
-
{ mode: string }
|
|
309
|
-
>
|
|
310
|
-
)[svc]!.mode,
|
|
370
|
+
(config.services as unknown as Record<string, { mode: string }>)[svc]!
|
|
371
|
+
.mode,
|
|
311
372
|
).toBe("your-own");
|
|
312
373
|
}
|
|
374
|
+
for (const svc of SCHEMA_MANAGED_DEFAULT_SERVICES) {
|
|
375
|
+
expect(
|
|
376
|
+
(config.services as unknown as Record<string, { mode: string }>)[svc]!
|
|
377
|
+
.mode,
|
|
378
|
+
).toBe("managed");
|
|
379
|
+
}
|
|
313
380
|
});
|
|
314
381
|
});
|
|
315
382
|
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
invalidateConfigCache,
|
|
29
29
|
loadConfig,
|
|
30
30
|
} from "../config/loader.js";
|
|
31
|
-
import {
|
|
31
|
+
import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
|
|
32
32
|
|
|
33
33
|
// ---------------------------------------------------------------------------
|
|
34
34
|
// Helpers
|
|
@@ -71,12 +71,12 @@ function listQuarantinedFiles(): string[] {
|
|
|
71
71
|
describe("config-quarantine UPDATES.md bulletin", () => {
|
|
72
72
|
beforeEach(() => {
|
|
73
73
|
resetWorkspace();
|
|
74
|
-
|
|
74
|
+
setStorePathForTesting(join(WORKSPACE_DIR, "keys.enc"));
|
|
75
75
|
invalidateConfigCache();
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
afterEach(() => {
|
|
79
|
-
|
|
79
|
+
setStorePathForTesting(null);
|
|
80
80
|
invalidateConfigCache();
|
|
81
81
|
});
|
|
82
82
|
|
|
@@ -68,7 +68,6 @@ mock.module("../config/assistant-feature-flags.js", () => ({
|
|
|
68
68
|
if (key === "managed-gemini-embeddings-enabled") return featureFlagEnabled;
|
|
69
69
|
return true;
|
|
70
70
|
},
|
|
71
|
-
_setOverridesForTesting: () => {},
|
|
72
71
|
clearFeatureFlagOverridesCache: () => {},
|
|
73
72
|
initFeatureFlagOverrides: async () => {},
|
|
74
73
|
getAssistantFeatureFlagDefaults: () => ({}),
|
|
@@ -81,7 +80,7 @@ afterAll(() => {
|
|
|
81
80
|
});
|
|
82
81
|
|
|
83
82
|
import { invalidateConfigCache, loadConfig } from "../config/loader.js";
|
|
84
|
-
import {
|
|
83
|
+
import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
|
|
85
84
|
|
|
86
85
|
// ---------------------------------------------------------------------------
|
|
87
86
|
// Helpers
|
|
@@ -117,7 +116,7 @@ describe("managed Gemini embedding defaults (via loadConfig)", () => {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
ensureTestDir();
|
|
120
|
-
|
|
119
|
+
setStorePathForTesting(join(WORKSPACE_DIR, "keys.enc"));
|
|
121
120
|
invalidateConfigCache();
|
|
122
121
|
|
|
123
122
|
// Reset mock state
|
|
@@ -127,7 +126,7 @@ describe("managed Gemini embedding defaults (via loadConfig)", () => {
|
|
|
127
126
|
});
|
|
128
127
|
|
|
129
128
|
afterEach(() => {
|
|
130
|
-
|
|
129
|
+
setStorePathForTesting(null);
|
|
131
130
|
invalidateConfigCache();
|
|
132
131
|
|
|
133
132
|
// Restore IS_PLATFORM
|
|
@@ -64,9 +64,9 @@ import {
|
|
|
64
64
|
VALID_TTS_PROVIDERS as VALID_TTS_SERVICE_PROVIDERS,
|
|
65
65
|
} from "../config/schemas/tts.js";
|
|
66
66
|
import type { AssistantConfig } from "../config/types.js";
|
|
67
|
-
import { _setStorePath } from "../security/encrypted-store.js";
|
|
68
67
|
import { listCatalogProviderIds } from "../tts/provider-catalog.js";
|
|
69
68
|
import { resolveTtsConfig } from "../tts/tts-config-resolver.js";
|
|
69
|
+
import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
|
|
70
70
|
|
|
71
71
|
// ---------------------------------------------------------------------------
|
|
72
72
|
// Helpers
|
|
@@ -87,7 +87,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
87
87
|
// llm.default.{provider,model}, auth routing via provider_connections.
|
|
88
88
|
expect(result.services.inference).toEqual({});
|
|
89
89
|
expect(result.llm.default.provider).toBe("anthropic");
|
|
90
|
-
expect(result.llm.default.model).toBe("claude-opus-4-
|
|
90
|
+
expect(result.llm.default.model).toBe("claude-opus-4-8");
|
|
91
91
|
expect(result.services["image-generation"].provider).toBe("gemini");
|
|
92
92
|
expect(result.services["image-generation"].model).toBe(
|
|
93
93
|
"gemini-3.1-flash-image-preview",
|
|
@@ -179,7 +179,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
179
179
|
expect(result.llm).toBeDefined();
|
|
180
180
|
expect(result.llm.default).toEqual({
|
|
181
181
|
provider: "anthropic",
|
|
182
|
-
model: "claude-opus-4-
|
|
182
|
+
model: "claude-opus-4-8",
|
|
183
183
|
maxTokens: 64000,
|
|
184
184
|
effort: "max",
|
|
185
185
|
speed: "standard",
|
|
@@ -318,7 +318,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
318
318
|
(result.services.inference as Record<string, unknown>).model,
|
|
319
319
|
).toBeUndefined();
|
|
320
320
|
expect(result.llm.default.provider).toBe("anthropic");
|
|
321
|
-
expect(result.llm.default.model).toBe("claude-opus-4-
|
|
321
|
+
expect(result.llm.default.model).toBe("claude-opus-4-8");
|
|
322
322
|
});
|
|
323
323
|
|
|
324
324
|
test("partial llm config (empty `llm: {}`) doesn't trigger full config reset", () => {
|
|
@@ -333,7 +333,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
333
333
|
});
|
|
334
334
|
expect(result.llm.default.maxTokens).toBe(32000);
|
|
335
335
|
expect(result.llm.default.provider).toBe("anthropic");
|
|
336
|
-
expect(result.llm.default.model).toBe("claude-opus-4-
|
|
336
|
+
expect(result.llm.default.model).toBe("claude-opus-4-8");
|
|
337
337
|
});
|
|
338
338
|
|
|
339
339
|
test("llm.default with one missing field still parses (defaults applied)", () => {
|
|
@@ -2068,12 +2068,12 @@ describe("loadConfig with schema validation", () => {
|
|
|
2068
2068
|
}
|
|
2069
2069
|
}
|
|
2070
2070
|
ensureTestDir();
|
|
2071
|
-
|
|
2071
|
+
setStorePathForTesting(join(WORKSPACE_DIR, "keys.enc"));
|
|
2072
2072
|
invalidateConfigCache();
|
|
2073
2073
|
});
|
|
2074
2074
|
|
|
2075
2075
|
afterEach(() => {
|
|
2076
|
-
|
|
2076
|
+
setStorePathForTesting(null);
|
|
2077
2077
|
invalidateConfigCache();
|
|
2078
2078
|
});
|
|
2079
2079
|
|
|
@@ -2096,7 +2096,7 @@ describe("loadConfig with schema validation", () => {
|
|
|
2096
2096
|
writeConfig({});
|
|
2097
2097
|
const config = loadConfig();
|
|
2098
2098
|
expect(config.llm.default.provider).toBe("anthropic");
|
|
2099
|
-
expect(config.llm.default.model).toBe("claude-opus-4-
|
|
2099
|
+
expect(config.llm.default.model).toBe("claude-opus-4-8");
|
|
2100
2100
|
expect(config.llm.default.maxTokens).toBe(64000);
|
|
2101
2101
|
expect(config.llm.default.thinking).toEqual({
|
|
2102
2102
|
enabled: true,
|
|
@@ -2350,12 +2350,12 @@ describe("Call entrypoint gating", () => {
|
|
|
2350
2350
|
}
|
|
2351
2351
|
}
|
|
2352
2352
|
ensureTestDir();
|
|
2353
|
-
|
|
2353
|
+
setStorePathForTesting(join(WORKSPACE_DIR, "keys.enc"));
|
|
2354
2354
|
invalidateConfigCache();
|
|
2355
2355
|
});
|
|
2356
2356
|
|
|
2357
2357
|
afterEach(() => {
|
|
2358
|
-
|
|
2358
|
+
setStorePathForTesting(null);
|
|
2359
2359
|
invalidateConfigCache();
|
|
2360
2360
|
});
|
|
2361
2361
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
describeSubscriptionModelIncompatibility,
|
|
5
|
+
isConnectionCompatibleWithModel,
|
|
6
|
+
} from "../providers/connection-model-compat.js";
|
|
7
|
+
|
|
8
|
+
describe("isConnectionCompatibleWithModel", () => {
|
|
9
|
+
test("non-oauth_subscription connections are always compatible", () => {
|
|
10
|
+
expect(
|
|
11
|
+
isConnectionCompatibleWithModel(
|
|
12
|
+
{ auth: { type: "api_key" } as never },
|
|
13
|
+
"o3",
|
|
14
|
+
),
|
|
15
|
+
).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("oauth_subscription is compatible with Codex models", () => {
|
|
19
|
+
expect(
|
|
20
|
+
isConnectionCompatibleWithModel(
|
|
21
|
+
{ auth: { type: "oauth_subscription" } as never },
|
|
22
|
+
"gpt-5.4",
|
|
23
|
+
),
|
|
24
|
+
).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("oauth_subscription is incompatible with non-Codex models", () => {
|
|
28
|
+
expect(
|
|
29
|
+
isConnectionCompatibleWithModel(
|
|
30
|
+
{ auth: { type: "oauth_subscription" } as never },
|
|
31
|
+
"o3",
|
|
32
|
+
),
|
|
33
|
+
).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("undefined model is always compatible", () => {
|
|
37
|
+
expect(
|
|
38
|
+
isConnectionCompatibleWithModel(
|
|
39
|
+
{ auth: { type: "oauth_subscription" } as never },
|
|
40
|
+
undefined,
|
|
41
|
+
),
|
|
42
|
+
).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("describeSubscriptionModelIncompatibility", () => {
|
|
47
|
+
const subscriptionConn = { auth: { type: "oauth_subscription" as const } as never };
|
|
48
|
+
const apiKeyConn = { auth: { type: "api_key" as const } as never };
|
|
49
|
+
|
|
50
|
+
test("returns message when all candidates are oauth_subscription and model is incompatible", () => {
|
|
51
|
+
const msg = describeSubscriptionModelIncompatibility(
|
|
52
|
+
[subscriptionConn],
|
|
53
|
+
"o3",
|
|
54
|
+
);
|
|
55
|
+
expect(msg).toContain("o3");
|
|
56
|
+
expect(msg).toContain("ChatGPT subscription");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("returns null when no candidates", () => {
|
|
60
|
+
expect(describeSubscriptionModelIncompatibility([], "o3")).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("returns null when model is undefined", () => {
|
|
64
|
+
expect(
|
|
65
|
+
describeSubscriptionModelIncompatibility([subscriptionConn], undefined),
|
|
66
|
+
).toBeNull();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("returns null when some candidates are compatible", () => {
|
|
70
|
+
expect(
|
|
71
|
+
describeSubscriptionModelIncompatibility(
|
|
72
|
+
[subscriptionConn, apiKeyConn],
|
|
73
|
+
"o3",
|
|
74
|
+
),
|
|
75
|
+
).toBeNull();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("returns null when model is Codex-compatible", () => {
|
|
79
|
+
expect(
|
|
80
|
+
describeSubscriptionModelIncompatibility([subscriptionConn], "gpt-5.4"),
|
|
81
|
+
).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -65,11 +65,12 @@ import { executeContactMerge } from "../config/bundled-skills/contacts/tools/con
|
|
|
65
65
|
import { executeContactSearch } from "../config/bundled-skills/contacts/tools/contact-search.js";
|
|
66
66
|
import { upsertContact } from "../contacts/contact-store.js";
|
|
67
67
|
import type { ContactWithChannels } from "../contacts/types.js";
|
|
68
|
-
import { getDb
|
|
68
|
+
import { getDb } from "../memory/db-connection.js";
|
|
69
69
|
import { initializeDb } from "../memory/db-init.js";
|
|
70
70
|
import { ROUTES } from "../runtime/routes/contact-routes.js";
|
|
71
71
|
import { RouteError } from "../runtime/routes/errors.js";
|
|
72
72
|
import type { ToolContext } from "../tools/types.js";
|
|
73
|
+
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
73
74
|
|
|
74
75
|
initializeDb();
|
|
75
76
|
|
|
@@ -127,7 +128,7 @@ beforeAll(() => {
|
|
|
127
128
|
|
|
128
129
|
afterAll(() => {
|
|
129
130
|
testServer?.stop(true);
|
|
130
|
-
|
|
131
|
+
resetDbForTesting();
|
|
131
132
|
});
|
|
132
133
|
|
|
133
134
|
function getRawDb(): Database {
|
|
@@ -367,6 +367,28 @@ describe("token estimator", () => {
|
|
|
367
367
|
expect(tokens).toBeLessThan(4_200);
|
|
368
368
|
});
|
|
369
369
|
|
|
370
|
+
test("Gemini preserves aspect ratio when resizing to the 3072px cap", () => {
|
|
371
|
+
// Gemini rescales BOTH dimensions by a single factor so the longest side
|
|
372
|
+
// becomes 3072px. A 10000x1000 image → 3072x307, i.e. ceil(3072/768)=4
|
|
373
|
+
// tiles wide * ceil(307/768)=1 tile high = 4 tiles (~1,032 tokens).
|
|
374
|
+
// Clamping each side independently would yield 4*2=8 tiles, over-counting
|
|
375
|
+
// by 2x and risking spurious compaction.
|
|
376
|
+
const tokens = estimateContentBlockTokens(
|
|
377
|
+
{
|
|
378
|
+
type: "image",
|
|
379
|
+
source: {
|
|
380
|
+
type: "base64",
|
|
381
|
+
media_type: "image/png",
|
|
382
|
+
data: makePngBase64(10000, 1000),
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
{ providerName: "gemini" },
|
|
386
|
+
);
|
|
387
|
+
// 4 tiles * 258 = 1,032 image tokens + 16 block overhead + 3 media type.
|
|
388
|
+
expect(tokens).toBeGreaterThanOrEqual(1_032);
|
|
389
|
+
expect(tokens).toBeLessThan(1_100);
|
|
390
|
+
});
|
|
391
|
+
|
|
370
392
|
test("Gemini images ≤384px on both sides count as a single 258-token tile", () => {
|
|
371
393
|
const tokens = estimateContentBlockTokens(
|
|
372
394
|
{
|
|
@@ -138,6 +138,8 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
138
138
|
updateConversationTitle: () => {},
|
|
139
139
|
getMessageById: () => null,
|
|
140
140
|
getLastUserTimestampBefore: () => 0,
|
|
141
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
142
|
+
updateMessageContent: mock(() => {}),
|
|
141
143
|
}));
|
|
142
144
|
|
|
143
145
|
mock.module("../memory/conversation-queries.js", () => ({
|
|
@@ -192,6 +194,9 @@ mock.module("../agent/loop.js", () => ({
|
|
|
192
194
|
onEvent: (event: AgentEvent) => void,
|
|
193
195
|
_signal?: AbortSignal,
|
|
194
196
|
): Promise<Message[]> {
|
|
197
|
+
// Prime the assistant row anchor — production code emits this from
|
|
198
|
+
// `AgentLoop.run` just before `provider.sendMessage`.
|
|
199
|
+
await onEvent({ type: "llm_call_started" });
|
|
195
200
|
const history = [...messages];
|
|
196
201
|
|
|
197
202
|
// Simulate provider response with 2 tool_use blocks
|
|
@@ -100,6 +100,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
100
100
|
setConversationHistoryStrippedAt: () => {},
|
|
101
101
|
updateConversationContextWindow: () => {},
|
|
102
102
|
updateConversationSlackContextWatermark: () => {},
|
|
103
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
103
104
|
}));
|
|
104
105
|
|
|
105
106
|
import { runAgentLoopImpl } from "../daemon/conversation-agent-loop.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { AgentEvent } from "../agent/loop.js";
|
|
4
|
+
import {
|
|
5
|
+
createEventHandlerState,
|
|
6
|
+
type EventHandlerDeps,
|
|
7
|
+
handleMaxTokensReached,
|
|
8
|
+
} from "../daemon/conversation-agent-loop-handlers.js";
|
|
9
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
10
|
+
|
|
11
|
+
describe("max tokens reached handler", () => {
|
|
12
|
+
test("emits and stores an inline continuation card", () => {
|
|
13
|
+
const sent: ServerMessage[] = [];
|
|
14
|
+
const ctx = {
|
|
15
|
+
conversationId: "conv-1",
|
|
16
|
+
surfaceState: new Map(),
|
|
17
|
+
currentTurnSurfaces: [],
|
|
18
|
+
};
|
|
19
|
+
const deps = {
|
|
20
|
+
ctx,
|
|
21
|
+
onEvent: (msg: ServerMessage) => sent.push(msg),
|
|
22
|
+
reqId: "req-1",
|
|
23
|
+
isFirstMessage: false,
|
|
24
|
+
shouldGenerateTitle: false,
|
|
25
|
+
rlog: { warn: () => {} },
|
|
26
|
+
turnChannelContext: {
|
|
27
|
+
userMessageChannel: "vellum",
|
|
28
|
+
assistantMessageChannel: "vellum",
|
|
29
|
+
},
|
|
30
|
+
turnInterfaceContext: {
|
|
31
|
+
userMessageInterface: "web",
|
|
32
|
+
assistantMessageInterface: "web",
|
|
33
|
+
},
|
|
34
|
+
} as unknown as EventHandlerDeps;
|
|
35
|
+
|
|
36
|
+
handleMaxTokensReached(createEventHandlerState(), deps, {
|
|
37
|
+
type: "max_tokens_reached",
|
|
38
|
+
stopReason: "max_tokens",
|
|
39
|
+
} as Extract<AgentEvent, { type: "max_tokens_reached" }>);
|
|
40
|
+
|
|
41
|
+
const show = sent.find((msg) => msg.type === "ui_surface_show");
|
|
42
|
+
expect(show).toBeDefined();
|
|
43
|
+
if (!show || show.type !== "ui_surface_show") return;
|
|
44
|
+
|
|
45
|
+
expect(show.surfaceType).toBe("card");
|
|
46
|
+
expect((show.data as { title?: unknown }).title).toBe(
|
|
47
|
+
"Response limit reached",
|
|
48
|
+
);
|
|
49
|
+
expect(show.actions?.[0]?.id).toBe("relay_prompt");
|
|
50
|
+
expect(show.actions?.[0]?.data?.prompt).toContain("Continue");
|
|
51
|
+
expect(show.actions?.[0]?.data?._completeSurface).toBe(true);
|
|
52
|
+
expect(ctx.currentTurnSurfaces).toHaveLength(1);
|
|
53
|
+
expect(ctx.surfaceState.has(show.surfaceId)).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -170,6 +170,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
170
170
|
getMessageById: () => null,
|
|
171
171
|
getLastUserTimestampBefore: () => 0,
|
|
172
172
|
setLastNotifiedInferenceProfile: () => {},
|
|
173
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
173
174
|
}));
|
|
174
175
|
|
|
175
176
|
mock.module("../memory/conversation-disk-view.js", () => ({
|