@vellumai/assistant 0.8.4 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +2 -2
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/openapi.yaml +809 -11
- package/package.json +1 -1
- package/src/__tests__/anthropic-provider.test.ts +34 -37
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
- package/src/__tests__/conversation-agent-loop.test.ts +163 -122
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +178 -15
- package/src/__tests__/conversation-lifecycle.test.ts +52 -11
- package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +77 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +46 -0
- package/src/__tests__/openai-responses-provider.test.ts +114 -12
- package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -2
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +145 -131
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +9 -62
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +6 -5
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/loop.ts +8 -0
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +176 -1
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +7 -6
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
- package/src/config/schemas/call-site-catalog.ts +21 -7
- package/src/config/schemas/llm.ts +12 -1
- package/src/config/schemas/memory-v2.ts +246 -0
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +52 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
- package/src/daemon/conversation-agent-loop.ts +126 -76
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +27 -22
- package/src/daemon/conversation-runtime-assembly.ts +10 -9
- package/src/daemon/conversation-tool-setup.ts +63 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +14 -29
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +11 -3
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +4 -4
- package/src/daemon/host-file-proxy.ts +4 -4
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +10 -10
- package/src/daemon/lifecycle.ts +23 -20
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-types/conversations.ts +6 -9
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +6 -14
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
- package/src/home/home-greeting.ts +0 -9
- package/src/home/suggested-prompts.ts +0 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +71 -70
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +10 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +55 -22
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-enqueue.ts +8 -1
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/memory-v2-activation-log-store.ts +15 -6
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +17 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/schema/conversations.ts +1 -1
- package/src/memory/schema/infrastructure.ts +21 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection.test.ts +127 -98
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +171 -3
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection.ts +21 -15
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +171 -18
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/emit-signal.ts +29 -49
- package/src/permissions/prompter.ts +3 -3
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +2 -2
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +18 -11
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +39 -7
- package/src/prompts/system-prompt.ts +50 -185
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +230 -8
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +32 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +43 -0
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +6 -3
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +78 -21
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/agent-wake.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +36 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +0 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +142 -36
- package/src/runtime/routes/conversation-routes.ts +252 -410
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/host-browser-routes.ts +10 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +215 -5
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +5 -4
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
- package/src/tools/browser/browser-execution.ts +16 -3
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
- package/src/tools/browser/cdp-client/factory.ts +100 -17
- package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
- package/src/tools/browser/cdp-client/types.ts +65 -0
- package/src/tools/browser/pinned-tabs.ts +96 -40
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-tool.ts +59 -0
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/web-fetch.ts +3 -9
- package/src/tools/network/web-search.ts +25 -32
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +27 -98
- package/src/tools/ui-surface/definitions.ts +6 -22
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -2
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/daemon/query-complexity-router.ts +0 -75
- package/src/prompts/cache-boundary.ts +0 -8
|
@@ -84,6 +84,7 @@ const SAMPLE_ROW = {
|
|
|
84
84
|
// ClickHouse emits Int64 as a quoted string under JSONEachRow by default.
|
|
85
85
|
created_at: "1778465138786",
|
|
86
86
|
agent_loop_exit_reason: "no_tool_calls",
|
|
87
|
+
call_site: "mainAgent",
|
|
87
88
|
};
|
|
88
89
|
|
|
89
90
|
describe("ClickHouseLlmRequestLogSource", () => {
|
|
@@ -104,6 +105,7 @@ describe("ClickHouseLlmRequestLogSource", () => {
|
|
|
104
105
|
responsePayload: '{"bar":2}',
|
|
105
106
|
createdAt: 1778465138786,
|
|
106
107
|
agentLoopExitReason: "no_tool_calls",
|
|
108
|
+
callSite: "mainAgent",
|
|
107
109
|
});
|
|
108
110
|
});
|
|
109
111
|
|
|
@@ -164,6 +166,30 @@ describe("ClickHouseLlmRequestLogSource", () => {
|
|
|
164
166
|
expect(rows).toEqual([]);
|
|
165
167
|
});
|
|
166
168
|
|
|
169
|
+
test("getRequestLogsByConversationId binds conversation id via parameterized placeholder", async () => {
|
|
170
|
+
// Regression guard: the conversation id flows from user-controlled
|
|
171
|
+
// input (conversationKey → conversations.id), so it must travel as a
|
|
172
|
+
// typed parameter, never as an inline string literal.
|
|
173
|
+
const recorder: FakeFetchCall[] = [];
|
|
174
|
+
const malicious = "conv-1' OR 1=1 --";
|
|
175
|
+
const src = makeSource({
|
|
176
|
+
body: JSON.stringify(SAMPLE_ROW) + "\n",
|
|
177
|
+
recorder,
|
|
178
|
+
});
|
|
179
|
+
const rows = await src.getRequestLogsByConversationId(malicious);
|
|
180
|
+
expect(rows).toHaveLength(1);
|
|
181
|
+
expect(recorder).toHaveLength(1);
|
|
182
|
+
const call = recorder[0]!;
|
|
183
|
+
const parsed = new URL(call.url);
|
|
184
|
+
expect(parsed.searchParams.get("param_assistant_id")).toBe(
|
|
185
|
+
"asst-fixture-001",
|
|
186
|
+
);
|
|
187
|
+
expect(parsed.searchParams.get("param_conversation_id")).toBe(malicious);
|
|
188
|
+
const body = String(call.init?.body ?? "");
|
|
189
|
+
expect(body).toContain("conversation_id = {conversation_id:String}");
|
|
190
|
+
expect(body).not.toContain(`'${malicious}'`);
|
|
191
|
+
});
|
|
192
|
+
|
|
167
193
|
test("getRequestLogsByMessageId binds message ids via parameterized placeholders", async () => {
|
|
168
194
|
// Regression for ATL-537. `getAssistantMessageIdsInTurn` returns the
|
|
169
195
|
// caller-supplied id straight through when the message lookup misses,
|
|
@@ -2,7 +2,10 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
resolveCallSiteConfig,
|
|
7
|
+
resolveDefaultProfileKey,
|
|
8
|
+
} from "../config/llm-resolver.js";
|
|
6
9
|
import { type LLMCallSite, LLMSchema } from "../config/schemas/llm.js";
|
|
7
10
|
|
|
8
11
|
const fullDefault = {
|
|
@@ -690,13 +693,28 @@ describe("resolveCallSiteConfig", () => {
|
|
|
690
693
|
});
|
|
691
694
|
|
|
692
695
|
const callSites: LLMCallSite[] = [
|
|
693
|
-
"mainAgent",
|
|
694
|
-
"
|
|
695
|
-
"
|
|
696
|
-
"
|
|
697
|
-
"
|
|
698
|
-
"
|
|
699
|
-
"
|
|
696
|
+
"mainAgent",
|
|
697
|
+
"subagentSpawn",
|
|
698
|
+
"heartbeatAgent",
|
|
699
|
+
"filingAgent",
|
|
700
|
+
"compactionAgent",
|
|
701
|
+
"analyzeConversation",
|
|
702
|
+
"callAgent",
|
|
703
|
+
"memoryExtraction",
|
|
704
|
+
"memoryConsolidation",
|
|
705
|
+
"memoryRetrieval",
|
|
706
|
+
"memoryRouter",
|
|
707
|
+
"recall",
|
|
708
|
+
"conversationSummarization",
|
|
709
|
+
"commitMessage",
|
|
710
|
+
"conversationStarters",
|
|
711
|
+
"replySuggestion",
|
|
712
|
+
"conversationTitle",
|
|
713
|
+
"identityIntro",
|
|
714
|
+
"emptyStateGreeting",
|
|
715
|
+
"notificationDecision",
|
|
716
|
+
"interactionClassifier",
|
|
717
|
+
"inference",
|
|
700
718
|
];
|
|
701
719
|
|
|
702
720
|
for (const cs of callSites) {
|
|
@@ -778,7 +796,10 @@ describe("resolveCallSiteConfig", () => {
|
|
|
778
796
|
provider_connection: "anthropic-managed",
|
|
779
797
|
},
|
|
780
798
|
profiles: {
|
|
781
|
-
fireworks: {
|
|
799
|
+
fireworks: {
|
|
800
|
+
provider: "fireworks",
|
|
801
|
+
model: "accounts/fireworks/models/kimi-k2p5",
|
|
802
|
+
},
|
|
782
803
|
},
|
|
783
804
|
activeProfile: "fireworks",
|
|
784
805
|
});
|
|
@@ -874,3 +895,50 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
874
895
|
);
|
|
875
896
|
});
|
|
876
897
|
});
|
|
898
|
+
|
|
899
|
+
describe("memory v3 call sites resolve through the standard resolver", () => {
|
|
900
|
+
const llm = LLMSchema.parse({
|
|
901
|
+
default: fullDefault,
|
|
902
|
+
profiles: {
|
|
903
|
+
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
904
|
+
"cost-optimized": {
|
|
905
|
+
provider: "anthropic",
|
|
906
|
+
model: "claude-haiku-4-5-20251001",
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
test("memoryV3Filter and memoryV3Descent resolve to the cost-optimized profile", () => {
|
|
912
|
+
expect(resolveDefaultProfileKey("memoryV3Filter", llm)).toBe(
|
|
913
|
+
"cost-optimized",
|
|
914
|
+
);
|
|
915
|
+
expect(resolveDefaultProfileKey("memoryV3Descent", llm)).toBe(
|
|
916
|
+
"cost-optimized",
|
|
917
|
+
);
|
|
918
|
+
expect(resolveCallSiteConfig("memoryV3Filter", llm).model).toBe(
|
|
919
|
+
"claude-haiku-4-5-20251001",
|
|
920
|
+
);
|
|
921
|
+
expect(resolveCallSiteConfig("memoryV3Descent", llm).model).toBe(
|
|
922
|
+
"claude-haiku-4-5-20251001",
|
|
923
|
+
);
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
test("memoryV3Gate resolves to the balanced (capable) profile", () => {
|
|
927
|
+
expect(resolveDefaultProfileKey("memoryV3Gate", llm)).toBe("balanced");
|
|
928
|
+
expect(resolveCallSiteConfig("memoryV3Gate", llm).model).toBe(
|
|
929
|
+
"claude-sonnet-4-7",
|
|
930
|
+
);
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
test("v3 call sites are addressable as call-site override keys", () => {
|
|
934
|
+
const overridden = LLMSchema.parse({
|
|
935
|
+
default: fullDefault,
|
|
936
|
+
callSites: {
|
|
937
|
+
memoryV3Gate: { model: "claude-opus-4-7" },
|
|
938
|
+
},
|
|
939
|
+
});
|
|
940
|
+
expect(resolveCallSiteConfig("memoryV3Gate", overridden).model).toBe(
|
|
941
|
+
"claude-opus-4-7",
|
|
942
|
+
);
|
|
943
|
+
});
|
|
944
|
+
});
|
|
@@ -31,6 +31,7 @@ function makeInput(overrides?: Partial<UsageEventInput>): UsageEventInput {
|
|
|
31
31
|
outputTokens: 500,
|
|
32
32
|
cacheCreationInputTokens: null,
|
|
33
33
|
cacheReadInputTokens: null,
|
|
34
|
+
rawUsage: null,
|
|
34
35
|
actor: "main_agent",
|
|
35
36
|
conversationId: null,
|
|
36
37
|
runId: null,
|
|
@@ -217,6 +218,44 @@ describe("recordUsageEvent", () => {
|
|
|
217
218
|
expect(events[0].cacheCreationInputTokens).toBe(200);
|
|
218
219
|
expect(events[0].cacheReadInputTokens).toBe(300);
|
|
219
220
|
});
|
|
221
|
+
|
|
222
|
+
test("round-trips the provider's raw_usage payload verbatim", () => {
|
|
223
|
+
// The `raw_usage` column carries the literal usage object the provider
|
|
224
|
+
// returned (Anthropic nests TTL breakdown under `cache_creation`,
|
|
225
|
+
// OpenAI nests cached-read details under `prompt_tokens_details`, etc.)
|
|
226
|
+
// It must round-trip from `recordUsageEvent` through SQLite back to
|
|
227
|
+
// `listUsageEvents` byte-for-byte so downstream consumers can extract
|
|
228
|
+
// any provider-specific detail without a schema change.
|
|
229
|
+
const rawUsage = {
|
|
230
|
+
input_tokens: 1000,
|
|
231
|
+
output_tokens: 500,
|
|
232
|
+
cache_creation_input_tokens: 500,
|
|
233
|
+
cache_creation: {
|
|
234
|
+
ephemeral_5m_input_tokens: 100,
|
|
235
|
+
ephemeral_1h_input_tokens: 400,
|
|
236
|
+
},
|
|
237
|
+
cache_read_input_tokens: 0,
|
|
238
|
+
service_tier: "standard",
|
|
239
|
+
};
|
|
240
|
+
recordUsageEvent(makeInput({ rawUsage }), pricedResult);
|
|
241
|
+
|
|
242
|
+
const [event] = listUsageEvents();
|
|
243
|
+
expect(event.rawUsage).toEqual(rawUsage);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("raw_usage defaults to null when the provider did not return one", () => {
|
|
247
|
+
// Providers that don't surface a usage block (or daemons predating
|
|
248
|
+
// migration 260) write null. Coercing to `{}` would be
|
|
249
|
+
// indistinguishable from a usage block that genuinely has no fields,
|
|
250
|
+
// so we preserve null as the "absent" signal.
|
|
251
|
+
recordUsageEvent(
|
|
252
|
+
makeInput({ provider: "openai", model: "gpt-4o", rawUsage: null }),
|
|
253
|
+
pricedResult,
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const [event] = listUsageEvents();
|
|
257
|
+
expect(event.rawUsage).toBeNull();
|
|
258
|
+
});
|
|
220
259
|
});
|
|
221
260
|
|
|
222
261
|
describe("listUsageEvents", () => {
|
|
@@ -1391,4 +1430,31 @@ describe("queryUnreportedUsageEvents", () => {
|
|
|
1391
1430
|
// Analytics can treat 0 as "pre-first-turn" if needed.
|
|
1392
1431
|
expect(events[0].turnIndex).toBe(0);
|
|
1393
1432
|
});
|
|
1433
|
+
|
|
1434
|
+
test("surfaces raw_usage on unreported events", () => {
|
|
1435
|
+
// The telemetry reporter consumes `queryUnreportedUsageEvents` output
|
|
1436
|
+
// directly and forwards it to BigQuery. If the SELECT projection
|
|
1437
|
+
// drops the `raw_usage` column, every provider-specific detail
|
|
1438
|
+
// (Anthropic TTL breakdown, OpenAI prompt-token details, etc.)
|
|
1439
|
+
// vanishes silently — covered here so a refactor of the projection
|
|
1440
|
+
// can't regress the wire shape.
|
|
1441
|
+
const rawUsage = {
|
|
1442
|
+
input_tokens: 1500,
|
|
1443
|
+
output_tokens: 600,
|
|
1444
|
+
cache_creation_input_tokens: 800,
|
|
1445
|
+
cache_creation: {
|
|
1446
|
+
ephemeral_5m_input_tokens: 300,
|
|
1447
|
+
ephemeral_1h_input_tokens: 500,
|
|
1448
|
+
},
|
|
1449
|
+
};
|
|
1450
|
+
insertEventAt(1000, {
|
|
1451
|
+
cacheCreationInputTokens: 800,
|
|
1452
|
+
rawUsage,
|
|
1453
|
+
});
|
|
1454
|
+
|
|
1455
|
+
const events = queryUnreportedUsageEvents(0, undefined, 100);
|
|
1456
|
+
expect(events).toHaveLength(1);
|
|
1457
|
+
expect(events[0].cacheCreationInputTokens).toBe(800);
|
|
1458
|
+
expect(events[0].rawUsage).toEqual(rawUsage);
|
|
1459
|
+
});
|
|
1394
1460
|
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterAll, describe, expect, test } from "bun:test";
|
|
5
|
+
|
|
6
|
+
import { getLogger, initLogger, LOG_FILE_PATTERN } from "../util/logger.js";
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Test rationale
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
//
|
|
12
|
+
// `getLogger()` returns a Proxy that lazily creates a pino child against the
|
|
13
|
+
// current rootLogger. Before this PR's refactor, the child was cached on
|
|
14
|
+
// first access and never re-evaluated — which meant that across:
|
|
15
|
+
//
|
|
16
|
+
// 1. day rollover (ensureCurrentDate rebuilds rootLogger past UTC midnight),
|
|
17
|
+
// 2. or a late `initLogger()` call (which swaps the rootLogger),
|
|
18
|
+
//
|
|
19
|
+
// previously-cached children kept writing to the OLD root's destination
|
|
20
|
+
// forever — silently misrouting logs into the wrong daily file.
|
|
21
|
+
//
|
|
22
|
+
// These tests pin the new contract: when the rootLogger changes, the proxy's
|
|
23
|
+
// next access rebuilds the child against the new root.
|
|
24
|
+
//
|
|
25
|
+
// We assert via file-system side effects (logs appearing in the expected
|
|
26
|
+
// directory). pino's `sync: false` default makes the fd open asynchronous,
|
|
27
|
+
// so we wait a tick before reading.
|
|
28
|
+
//
|
|
29
|
+
// NB: the file-creating fallback path itself is gated behind a BUN_TEST=1
|
|
30
|
+
// stderr fast-path in `getRootLogger()` (so test output stays sensible), so
|
|
31
|
+
// these tests exercise the rebind via `initLogger()` calls instead. The
|
|
32
|
+
// "no vellum.log" property is covered by `platform.test.ts` (asserts
|
|
33
|
+
// `getLogsDir()` returns the directory) and by the mechanical guarantee that
|
|
34
|
+
// `buildRotatingLogger` derives filenames via `logFilePathForDate`.
|
|
35
|
+
|
|
36
|
+
const SLEEP_MS = 100;
|
|
37
|
+
|
|
38
|
+
const dirA = mkdtempSync(join(tmpdir(), "logger-rebind-A-"));
|
|
39
|
+
const dirB = mkdtempSync(join(tmpdir(), "logger-rebind-B-"));
|
|
40
|
+
|
|
41
|
+
afterAll(() => {
|
|
42
|
+
// Detach the module-level rootLogger from the temp dirs we're about to
|
|
43
|
+
// delete. Without this, a later flush (or the test runner's shutdown)
|
|
44
|
+
// could try to write into a removed directory.
|
|
45
|
+
initLogger({ dir: undefined, retentionDays: 0 });
|
|
46
|
+
rmSync(dirA, { recursive: true, force: true });
|
|
47
|
+
rmSync(dirB, { recursive: true, force: true });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("getLogger() proxy rebind", () => {
|
|
51
|
+
test("a proxy created BEFORE initLogger() still routes to the post-init root", async () => {
|
|
52
|
+
// Create the proxy before initLogger has run. This mirrors the real
|
|
53
|
+
// lifecycle.ts pattern: modules call `getLogger()` at import time, long
|
|
54
|
+
// before `initLogger()` boots in daemon startup.
|
|
55
|
+
const log = getLogger("early-binding");
|
|
56
|
+
|
|
57
|
+
initLogger({ dir: dirA, retentionDays: 0 });
|
|
58
|
+
|
|
59
|
+
log.info("first — should land in dirA");
|
|
60
|
+
|
|
61
|
+
await Bun.sleep(SLEEP_MS);
|
|
62
|
+
|
|
63
|
+
const aFiles = readdirSync(dirA);
|
|
64
|
+
expect(aFiles.some((f) => LOG_FILE_PATTERN.test(f))).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("subsequent log calls follow rootLogger swaps from initLogger()", async () => {
|
|
68
|
+
// rootLogger is currently bound to dirA from the previous test. Reuse
|
|
69
|
+
// an existing proxy and verify it follows the swap.
|
|
70
|
+
const log = getLogger("rebind-target");
|
|
71
|
+
log.info("warm-up against dirA so the child is cached");
|
|
72
|
+
|
|
73
|
+
await Bun.sleep(SLEEP_MS);
|
|
74
|
+
|
|
75
|
+
// Swap the rootLogger to a different directory.
|
|
76
|
+
initLogger({ dir: dirB, retentionDays: 0 });
|
|
77
|
+
|
|
78
|
+
log.info("post-swap — should land in dirB if the proxy rebound");
|
|
79
|
+
|
|
80
|
+
await Bun.sleep(SLEEP_MS);
|
|
81
|
+
|
|
82
|
+
// If the proxy correctly re-evaluates getRootLogger() on each access,
|
|
83
|
+
// the second log call hits the dirB root and dirB gets a daily log
|
|
84
|
+
// file. If the proxy were still caching the original child against the
|
|
85
|
+
// dirA root, dirB would stay empty.
|
|
86
|
+
const bFiles = readdirSync(dirB);
|
|
87
|
+
expect(bFiles.some((f) => LOG_FILE_PATTERN.test(f))).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -142,7 +142,7 @@ describe("MCP AbortSignal threading", () => {
|
|
|
142
142
|
);
|
|
143
143
|
|
|
144
144
|
expect(tool.name).toBe("mcp__test-server__my-tool");
|
|
145
|
-
expect(tool.
|
|
145
|
+
expect(tool.name).toBe("mcp__test-server__my-tool");
|
|
146
146
|
});
|
|
147
147
|
|
|
148
148
|
test("keeps MCP tool names with trailing whitespace distinct", () => {
|
|
@@ -211,7 +211,7 @@ describe("MCP AbortSignal threading", () => {
|
|
|
211
211
|
expect(tool.name.startsWith("mcp__stripe_link-cli__create_link__")).toBe(
|
|
212
212
|
true,
|
|
213
213
|
);
|
|
214
|
-
expect(tool.
|
|
214
|
+
expect(tool.name).toBe(tool.name);
|
|
215
215
|
|
|
216
216
|
await tool.execute(
|
|
217
217
|
{ someArg: "value" },
|
|
@@ -321,6 +321,9 @@ describe("image-studio skill script wrapper", () => {
|
|
|
321
321
|
|
|
322
322
|
expect(result.isError).toBe(true);
|
|
323
323
|
expect(result.content).toContain("Mock Gemini error: API failure");
|
|
324
|
+
expect(result.content).toContain(
|
|
325
|
+
"Do not change service configuration (mode, provider, or model) to try to fix it",
|
|
326
|
+
);
|
|
324
327
|
});
|
|
325
328
|
|
|
326
329
|
test("openai generation error uses OpenAI-specific mapping", async () => {
|
|
@@ -331,6 +334,34 @@ describe("image-studio skill script wrapper", () => {
|
|
|
331
334
|
|
|
332
335
|
expect(result.isError).toBe(true);
|
|
333
336
|
expect(result.content).toContain("Mock OpenAI error: openai failure");
|
|
337
|
+
expect(result.content).toContain(
|
|
338
|
+
"Do not change service configuration (mode, provider, or model) to try to fix it",
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test("missing credentials error includes guidance not to change service config", async () => {
|
|
343
|
+
mockGeminiKey = undefined;
|
|
344
|
+
|
|
345
|
+
const result = await run({ prompt: "a cat" }, fakeContext);
|
|
346
|
+
|
|
347
|
+
expect(result.isError).toBe(true);
|
|
348
|
+
expect(result.content).toContain("No Gemini API key");
|
|
349
|
+
expect(result.content).toContain(
|
|
350
|
+
"Do not change service configuration (mode, provider, or model) to try to fix it",
|
|
351
|
+
);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test("managed mode credential error includes guidance not to change service config", async () => {
|
|
355
|
+
mockImageGenMode = "managed";
|
|
356
|
+
mockManagedBaseUrl = undefined;
|
|
357
|
+
|
|
358
|
+
const result = await run({ prompt: "a cat" }, fakeContext);
|
|
359
|
+
|
|
360
|
+
expect(result.isError).toBe(true);
|
|
361
|
+
expect(result.content).toContain("Managed proxy is not available");
|
|
362
|
+
expect(result.content).toContain(
|
|
363
|
+
"Do not change service configuration (mode, provider, or model) to try to fix it",
|
|
364
|
+
);
|
|
334
365
|
});
|
|
335
366
|
|
|
336
367
|
test("reads source images from file paths on disk", async () => {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Covers:
|
|
5
5
|
* - Returns null when `memoryV2Static` is missing/empty.
|
|
6
6
|
* - Returns null when `mode === "minimal"`.
|
|
7
|
-
* - Wraps content in `<
|
|
7
|
+
* - Wraps content in `<info>...</info>` and uses
|
|
8
8
|
* `after-memory-prefix` placement.
|
|
9
|
-
* - Escapes any `</
|
|
9
|
+
* - Escapes any `</info>` substring inside the authored content so the
|
|
10
10
|
* wrapper cannot be broken out of.
|
|
11
11
|
*
|
|
12
12
|
* Hermetic: drives the injector's `produce()` directly with a synthesized
|
|
@@ -66,7 +66,7 @@ describe("memory-v2-static injector", () => {
|
|
|
66
66
|
expect(await memoryV2StaticInjector.produce(ctx)).toBeNull();
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
test("wraps content in <
|
|
69
|
+
test("wraps content in <info>...</info> with after-memory-prefix placement", async () => {
|
|
70
70
|
const content =
|
|
71
71
|
"## Essentials\n\nAlice prefers VS Code.\n\n## Threads\n\nOpen: ship PR.";
|
|
72
72
|
const ctx = makeContext({
|
|
@@ -77,11 +77,11 @@ describe("memory-v2-static injector", () => {
|
|
|
77
77
|
expect(block).not.toBeNull();
|
|
78
78
|
expect(block!.id).toBe("memory-v2-static");
|
|
79
79
|
expect(block!.placement).toBe("after-memory-prefix");
|
|
80
|
-
expect(block!.text).toBe(`<
|
|
80
|
+
expect(block!.text).toBe(`<info>\n${content}\n</info>`);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
test("escapes inner </
|
|
84
|
-
const content = "## Essentials\n\nText with </
|
|
83
|
+
test("escapes inner </info> closing tags so the wrapper cannot be broken out of", async () => {
|
|
84
|
+
const content = "## Essentials\n\nText with </info> embedded.";
|
|
85
85
|
const ctx = makeContext({
|
|
86
86
|
injectionInputs: { memoryV2Static: content },
|
|
87
87
|
});
|
|
@@ -89,7 +89,7 @@ describe("memory-v2-static injector", () => {
|
|
|
89
89
|
const block = await memoryV2StaticInjector.produce(ctx);
|
|
90
90
|
expect(block).not.toBeNull();
|
|
91
91
|
expect(block!.text).toBe(
|
|
92
|
-
"<
|
|
92
|
+
"<info>\n## Essentials\n\nText with </info> embedded.\n</info>",
|
|
93
93
|
);
|
|
94
94
|
});
|
|
95
95
|
});
|
|
@@ -29,7 +29,7 @@ describe("model intents", () => {
|
|
|
29
29
|
"gpt-5.4-nano",
|
|
30
30
|
);
|
|
31
31
|
expect(resolveModelIntent("gemini", "latency-optimized")).toBe(
|
|
32
|
-
"gemini-3.1-flash-lite
|
|
32
|
+
"gemini-3.1-flash-lite",
|
|
33
33
|
);
|
|
34
34
|
expect(resolveModelIntent("gemini", "quality-optimized")).toBe(
|
|
35
35
|
"gemini-3.1-pro-preview",
|
|
@@ -44,9 +44,7 @@ describe("model intents", () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test("falls back to provider default for unknown providers", () => {
|
|
47
|
-
expect(getProviderDefaultModel("unknown-provider")).toBe(
|
|
48
|
-
"claude-opus-4-7",
|
|
49
|
-
);
|
|
47
|
+
expect(getProviderDefaultModel("unknown-provider")).toBe("claude-opus-4-7");
|
|
50
48
|
expect(resolveModelIntent("unknown-provider", "quality-optimized")).toBe(
|
|
51
49
|
"claude-opus-4-7",
|
|
52
50
|
);
|
|
@@ -44,7 +44,7 @@ describe("onboarding template contracts", () => {
|
|
|
44
44
|
test("instructs saving to IDENTITY.md, SOUL.md, and user persona file via file_edit", () => {
|
|
45
45
|
expect(bootstrap).toContain("IDENTITY.md");
|
|
46
46
|
expect(bootstrap).toContain("SOUL.md");
|
|
47
|
-
expect(bootstrap).toContain("{{
|
|
47
|
+
expect(bootstrap).toContain("{{userSlug}}.md");
|
|
48
48
|
expect(bootstrap).toContain("file_edit");
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -56,6 +56,7 @@ let lastCreateParams: Record<string, unknown> | null = null;
|
|
|
56
56
|
let lastCreateOptions: Record<string, unknown> | null = null;
|
|
57
57
|
let lastConstructorOptions: Record<string, unknown> | null = null;
|
|
58
58
|
let shouldThrow: Error | null = null;
|
|
59
|
+
const DEFAULT_SDK_TIMEOUT_MS = 1_860_000;
|
|
59
60
|
|
|
60
61
|
function userMsg(text: string): Message {
|
|
61
62
|
return { role: "user", content: [{ type: "text", text }] };
|
|
@@ -102,6 +103,7 @@ mock.module("openai", () => ({
|
|
|
102
103
|
|
|
103
104
|
// Import after mocking
|
|
104
105
|
import { FireworksProvider } from "../providers/fireworks/client.js";
|
|
106
|
+
import { MinimaxProvider } from "../providers/minimax/client.js";
|
|
105
107
|
import { OllamaProvider } from "../providers/ollama/client.js";
|
|
106
108
|
import { OpenAIChatCompletionsProvider } from "../providers/openai/chat-completions-provider.js";
|
|
107
109
|
import { OpenAIProvider } from "../providers/openai/client.js";
|
|
@@ -307,6 +309,7 @@ describe("OpenAIProvider", () => {
|
|
|
307
309
|
expect(lastConstructorOptions).toEqual({
|
|
308
310
|
apiKey: "sk-local",
|
|
309
311
|
baseURL: "http://127.0.0.1:11434/v1",
|
|
312
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
310
313
|
});
|
|
311
314
|
});
|
|
312
315
|
|
|
@@ -319,6 +322,7 @@ describe("OpenAIProvider", () => {
|
|
|
319
322
|
expect(lastConstructorOptions).toEqual({
|
|
320
323
|
apiKey: "ollama",
|
|
321
324
|
baseURL: "http://127.0.0.1:11434/v1",
|
|
325
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
322
326
|
});
|
|
323
327
|
} finally {
|
|
324
328
|
if (previousBaseUrl !== undefined) {
|
|
@@ -338,6 +342,7 @@ describe("OpenAIProvider", () => {
|
|
|
338
342
|
expect(lastConstructorOptions).toEqual({
|
|
339
343
|
apiKey: "ollama",
|
|
340
344
|
baseURL: "http://127.0.0.1:11434/v1",
|
|
345
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
341
346
|
});
|
|
342
347
|
} finally {
|
|
343
348
|
if (previousBaseUrl !== undefined) {
|
|
@@ -1280,6 +1285,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1280
1285
|
expect(lastConstructorOptions).toEqual({
|
|
1281
1286
|
apiKey: "ast-key-123",
|
|
1282
1287
|
baseURL: "https://platform.example.com/v1/runtime-proxy/openai",
|
|
1288
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1283
1289
|
});
|
|
1284
1290
|
});
|
|
1285
1291
|
|
|
@@ -1289,6 +1295,19 @@ describe("custom baseURL initialization", () => {
|
|
|
1289
1295
|
expect(lastConstructorOptions).toEqual({
|
|
1290
1296
|
apiKey: "sk-user-key",
|
|
1291
1297
|
baseURL: undefined,
|
|
1298
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1302
|
+
test("OpenAIProvider passes configured stream timeout plus buffer to SDK", () => {
|
|
1303
|
+
new OpenAIProvider("sk-user-key", "gpt-4o", {
|
|
1304
|
+
streamTimeoutMs: 300_000,
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
expect(lastConstructorOptions).toEqual({
|
|
1308
|
+
apiKey: "sk-user-key",
|
|
1309
|
+
baseURL: undefined,
|
|
1310
|
+
timeout: 360_000,
|
|
1292
1311
|
});
|
|
1293
1312
|
});
|
|
1294
1313
|
|
|
@@ -1305,6 +1324,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1305
1324
|
expect(lastConstructorOptions).toEqual({
|
|
1306
1325
|
apiKey: "ast-key-123",
|
|
1307
1326
|
baseURL: "https://platform.example.com/v1/runtime-proxy/fireworks",
|
|
1327
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1308
1328
|
});
|
|
1309
1329
|
});
|
|
1310
1330
|
|
|
@@ -1317,6 +1337,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1317
1337
|
expect(lastConstructorOptions).toEqual({
|
|
1318
1338
|
apiKey: "fw-user-key",
|
|
1319
1339
|
baseURL: "https://api.fireworks.ai/inference/v1",
|
|
1340
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1320
1341
|
});
|
|
1321
1342
|
});
|
|
1322
1343
|
|
|
@@ -1329,6 +1350,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1329
1350
|
expect(lastConstructorOptions).toEqual({
|
|
1330
1351
|
apiKey: "ast-key-123",
|
|
1331
1352
|
baseURL: "https://platform.example.com/v1/runtime-proxy/openrouter",
|
|
1353
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1332
1354
|
});
|
|
1333
1355
|
});
|
|
1334
1356
|
|
|
@@ -1338,6 +1360,30 @@ describe("custom baseURL initialization", () => {
|
|
|
1338
1360
|
expect(lastConstructorOptions).toEqual({
|
|
1339
1361
|
apiKey: "or-user-key",
|
|
1340
1362
|
baseURL: "https://openrouter.ai/api/v1",
|
|
1363
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1364
|
+
});
|
|
1365
|
+
});
|
|
1366
|
+
|
|
1367
|
+
test("MinimaxProvider forwards a custom baseURL", () => {
|
|
1368
|
+
const managed = new MinimaxProvider("ast-key-123", "MiniMax-M2.7", {
|
|
1369
|
+
baseURL: "https://platform.example.com/v1/runtime-proxy/minimax",
|
|
1370
|
+
});
|
|
1371
|
+
|
|
1372
|
+
expect(managed.name).toBe("minimax");
|
|
1373
|
+
expect(lastConstructorOptions).toEqual({
|
|
1374
|
+
apiKey: "ast-key-123",
|
|
1375
|
+
baseURL: "https://platform.example.com/v1/runtime-proxy/minimax",
|
|
1376
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1377
|
+
});
|
|
1378
|
+
});
|
|
1379
|
+
|
|
1380
|
+
test("MinimaxProvider without custom baseURL uses default MiniMax URL", () => {
|
|
1381
|
+
new MinimaxProvider("mm-user-key", "MiniMax-M2.7");
|
|
1382
|
+
|
|
1383
|
+
expect(lastConstructorOptions).toEqual({
|
|
1384
|
+
apiKey: "mm-user-key",
|
|
1385
|
+
baseURL: "https://api.minimax.io/v1",
|
|
1386
|
+
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
1341
1387
|
});
|
|
1342
1388
|
});
|
|
1343
1389
|
});
|