@vellumai/assistant 0.8.3 → 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/docker-entrypoint.sh +0 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +1492 -100
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +302 -33
- package/src/__tests__/approval-cascade.test.ts +1 -1
- 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 +4 -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-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +2 -1
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -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__/config-watcher.test.ts +1 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
- package/src/__tests__/conversation-agent-loop.test.ts +188 -129
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- 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 +324 -0
- package/src/__tests__/conversation-lifecycle.test.ts +53 -12
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- 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-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -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 +7 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- 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__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- 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 +161 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/log-export-routes.test.ts +99 -2
- 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__/message-queue-steer.test.ts +114 -0
- 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 +151 -0
- package/src/__tests__/openai-responses-provider.test.ts +118 -16
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -5
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- 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__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- 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__/server-history-render.test.ts +83 -4
- 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__/steer-tool-repair.test.ts +249 -0
- 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 +161 -124
- package/src/__tests__/terminal-tools.test.ts +12 -2
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- 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 +89 -53
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- 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__/twilio-routes.test.ts +1 -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__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +94 -10
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- 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/attachments.ts +1 -0
- package/src/agent/loop.ts +65 -20
- 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/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- 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 +10 -12
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference-providers.ts +147 -1
- 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 +483 -0
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/program.ts +2 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.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/SKILL.md +8 -0
- 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-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +24 -12
- package/src/config/call-site-defaults.ts +20 -0
- package/src/config/feature-flag-registry.json +115 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
- package/src/config/schemas/call-site-catalog.ts +35 -0
- package/src/config/schemas/llm.ts +14 -0
- package/src/config/schemas/memory-v2.ts +294 -1
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +60 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
- package/src/daemon/conversation-agent-loop.ts +307 -88
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +149 -118
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +145 -84
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +70 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +54 -32
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +2 -0
- package/src/daemon/handlers/conversations.ts +90 -3
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +5 -5
- package/src/daemon/host-file-proxy.ts +5 -5
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +11 -11
- package/src/daemon/lifecycle.ts +40 -23
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +14 -9
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +66 -7
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- 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/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +85 -0
- package/src/home/suggested-prompts.ts +168 -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__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +191 -100
- 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 +26 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- 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 +68 -15
- 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-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +11 -3
- package/src/memory/memory-retrospective-job.ts +413 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +41 -14
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- 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 +34 -0
- package/src/memory/migrations/registry.ts +58 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +22 -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-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +158 -112
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +660 -4
- package/src/memory/v2/consolidation-job.ts +14 -0
- 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-events.ts +101 -0
- package/src/memory/v2/injection.ts +42 -25
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +369 -62
- 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/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +38 -50
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +8 -5
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +6 -3
- 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 +100 -20
- 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__/system-prompt.test.ts +46 -2
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +69 -19
- package/src/prompts/system-prompt.ts +118 -216
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +10 -2
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +281 -9
- 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 +159 -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/fireworks/client.ts +20 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +18 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +91 -1
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +63 -23
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +86 -23
- package/src/providers/openrouter/client.ts +5 -1
- 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/types.ts +25 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +152 -56
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +43 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -6
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +50 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/approval-routes.ts +4 -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/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +147 -2
- 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 +196 -31
- package/src/runtime/routes/conversation-routes.ts +472 -425
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- 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/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +17 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +20 -4
- 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/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +427 -0
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/sanity-routes.ts +159 -0
- 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 +188 -0
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/services/conversation-serializer.ts +30 -4
- 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/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- 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 +150 -0
- package/src/tools/browser/browser-execution.ts +106 -0
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
- package/src/tools/browser/cdp-client/factory.ts +171 -4
- package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
- package/src/tools/browser/cdp-client/types.ts +101 -0
- package/src/tools/browser/pinned-tabs.ts +146 -0
- 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-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +187 -2
- 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/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +216 -73
- package/src/tools/network/web-search.ts +216 -98
- 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/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +31 -98
- package/src/tools/ui-surface/definitions.ts +9 -23
- package/src/types/onboarding-context.ts +4 -0
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -7
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +4 -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/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/prompts/cache-boundary.ts +0 -8
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
2
|
|
|
3
|
-
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../../prompts/system-prompt.js";
|
|
4
3
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
5
4
|
import { ProviderError } from "../../util/errors.js";
|
|
6
5
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -537,6 +536,55 @@ function formatOrphanedWebSearchResultAsText(block: {
|
|
|
537
536
|
*
|
|
538
537
|
* Builds a fresh result array without mutating the input.
|
|
539
538
|
*/
|
|
539
|
+
/**
|
|
540
|
+
* Find the start index of the active tool-use continuation span at the tail
|
|
541
|
+
* of the formatted message array. Messages from this index onward may contain
|
|
542
|
+
* thinking blocks that must be preserved for Anthropic's tool-use protocol.
|
|
543
|
+
*
|
|
544
|
+
* The active span is the trailing sequence of alternating
|
|
545
|
+
* assistant(tool_use) → user(tool_result) messages. Everything before it is
|
|
546
|
+
* a completed historical turn whose thinking blocks can be safely stripped.
|
|
547
|
+
*
|
|
548
|
+
* Returns `messages.length` when there is no active tool-use continuation
|
|
549
|
+
* (i.e. all messages are historical — strip thinking from everything).
|
|
550
|
+
*/
|
|
551
|
+
function findActiveToolUseContinuationStart(
|
|
552
|
+
messages: Anthropic.MessageParam[],
|
|
553
|
+
): number {
|
|
554
|
+
// Walk backwards from the end. The tail pattern we're looking for is:
|
|
555
|
+
// ... assistant(tool_use) user(tool_result) [assistant(tool_use) user(tool_result)]* ...
|
|
556
|
+
// The last message is typically a user message (the new prompt), so if it
|
|
557
|
+
// doesn't contain tool_result blocks, there's no active continuation.
|
|
558
|
+
let i = messages.length - 1;
|
|
559
|
+
|
|
560
|
+
while (i >= 0) {
|
|
561
|
+
const msg = messages[i];
|
|
562
|
+
if (msg.role === "user") {
|
|
563
|
+
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
564
|
+
const hasToolResult = content.some(
|
|
565
|
+
(b) => typeof b !== "string" && isToolResultBlock(b),
|
|
566
|
+
);
|
|
567
|
+
if (!hasToolResult) break;
|
|
568
|
+
// This user message has tool_result — the preceding assistant message
|
|
569
|
+
// should have the matching tool_use and its thinking blocks preserved.
|
|
570
|
+
i--;
|
|
571
|
+
} else if (msg.role === "assistant") {
|
|
572
|
+
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
573
|
+
const hasToolUse = content.some(
|
|
574
|
+
(b) => typeof b !== "string" && isToolUseBlock(b),
|
|
575
|
+
);
|
|
576
|
+
if (!hasToolUse) break;
|
|
577
|
+
// This assistant message has tool_use — it's part of the active span.
|
|
578
|
+
// Check if the preceding user message continues the chain.
|
|
579
|
+
i--;
|
|
580
|
+
} else {
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
return i + 1;
|
|
586
|
+
}
|
|
587
|
+
|
|
540
588
|
function ensureToolPairing(
|
|
541
589
|
messages: Anthropic.MessageParam[],
|
|
542
590
|
): Anthropic.MessageParam[] {
|
|
@@ -770,6 +818,15 @@ export class AnthropicProvider implements Provider {
|
|
|
770
818
|
((config as Record<string, unknown> | undefined)?.cacheTtl as
|
|
771
819
|
| "5m"
|
|
772
820
|
| "1h") ?? "1h";
|
|
821
|
+
// Opt-out for callers (e.g. the memory router) that send a single
|
|
822
|
+
// user message per call with content that changes every time. The
|
|
823
|
+
// turn-start cache breakpoint below is only useful when the same
|
|
824
|
+
// prefix is re-sent on a subsequent call (typical for the main agent
|
|
825
|
+
// loop's tool-use iterations); one-shot callers pay cache_creation
|
|
826
|
+
// cost without a future hit.
|
|
827
|
+
const disableTurnStartCache =
|
|
828
|
+
(config as Record<string, unknown> | undefined)?.disableTurnStartCache ===
|
|
829
|
+
true;
|
|
773
830
|
let sentMessages: Anthropic.MessageParam[] | undefined;
|
|
774
831
|
const startedAt = Date.now();
|
|
775
832
|
// Hoisted so the catch block can distinguish our inner stream timeout
|
|
@@ -925,10 +982,29 @@ export class AnthropicProvider implements Provider {
|
|
|
925
982
|
}
|
|
926
983
|
}
|
|
927
984
|
|
|
928
|
-
//
|
|
929
|
-
//
|
|
930
|
-
//
|
|
931
|
-
//
|
|
985
|
+
// Strip thinking/redacted_thinking blocks from completed historical
|
|
986
|
+
// assistant turns. Anthropic only requires these blocks for active
|
|
987
|
+
// tool-use continuation (the tail span where assistant tool_use is
|
|
988
|
+
// followed by user tool_result). Replaying stale thinking blocks from
|
|
989
|
+
// earlier turns causes 400 errors when the signature is no longer
|
|
990
|
+
// valid (e.g. after a provider/model/profile switch).
|
|
991
|
+
const activeToolUseStart = findActiveToolUseContinuationStart(formatted);
|
|
992
|
+
for (let i = 0; i < activeToolUseStart; i++) {
|
|
993
|
+
const msg = formatted[i];
|
|
994
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.content)) continue;
|
|
995
|
+
const stripped = (msg.content as Anthropic.ContentBlockParam[]).filter(
|
|
996
|
+
(b) =>
|
|
997
|
+
typeof b === "string" ||
|
|
998
|
+
(b.type !== "thinking" && b.type !== "redacted_thinking"),
|
|
999
|
+
);
|
|
1000
|
+
if (stripped.length === 0) {
|
|
1001
|
+
stripped.push({
|
|
1002
|
+
type: "text" as const,
|
|
1003
|
+
text: PLACEHOLDER_BLOCKS_OMITTED,
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
formatted[i] = { ...msg, content: stripped };
|
|
1007
|
+
}
|
|
932
1008
|
|
|
933
1009
|
sentMessages = ensureToolPairing(
|
|
934
1010
|
repairOrphanedServerToolBlocks(formatted),
|
|
@@ -938,6 +1014,7 @@ export class AnthropicProvider implements Provider {
|
|
|
938
1014
|
speed,
|
|
939
1015
|
output_config,
|
|
940
1016
|
cacheTtl: _cacheTtl,
|
|
1017
|
+
disableTurnStartCache: _disableTurnStartCache,
|
|
941
1018
|
max_tokens: callerMaxTokens,
|
|
942
1019
|
usageAttributionHeaders,
|
|
943
1020
|
...restConfig
|
|
@@ -994,38 +1071,17 @@ export class AnthropicProvider implements Provider {
|
|
|
994
1071
|
};
|
|
995
1072
|
|
|
996
1073
|
if (systemPrompt) {
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
boundaryIdx + SYSTEM_PROMPT_CACHE_BOUNDARY.length,
|
|
1009
|
-
);
|
|
1010
|
-
const systemBlocks = [staticBlock, dynamicBlock]
|
|
1011
|
-
.filter((text) => text.length > 0)
|
|
1012
|
-
.map((text) => ({
|
|
1013
|
-
type: "text" as const,
|
|
1014
|
-
text,
|
|
1015
|
-
cache_control: cacheControl,
|
|
1016
|
-
}));
|
|
1017
|
-
if (systemBlocks.length > 0) {
|
|
1018
|
-
params.system = systemBlocks;
|
|
1019
|
-
}
|
|
1020
|
-
} else {
|
|
1021
|
-
params.system = [
|
|
1022
|
-
{
|
|
1023
|
-
type: "text" as const,
|
|
1024
|
-
text: systemPrompt,
|
|
1025
|
-
cache_control: cacheControl,
|
|
1026
|
-
},
|
|
1027
|
-
];
|
|
1028
|
-
}
|
|
1074
|
+
// The whole system prompt is rendered as a single cached
|
|
1075
|
+
// block. A 1-hour cache TTL is used (when supported by the
|
|
1076
|
+
// model) so the breakpoint survives turn gaps that exceed the
|
|
1077
|
+
// default 5-minute window.
|
|
1078
|
+
params.system = [
|
|
1079
|
+
{
|
|
1080
|
+
type: "text" as const,
|
|
1081
|
+
text: systemPrompt,
|
|
1082
|
+
cache_control: cacheControl,
|
|
1083
|
+
},
|
|
1084
|
+
];
|
|
1029
1085
|
}
|
|
1030
1086
|
|
|
1031
1087
|
if (tools && tools.length > 0) {
|
|
@@ -1089,7 +1145,9 @@ export class AnthropicProvider implements Provider {
|
|
|
1089
1145
|
}
|
|
1090
1146
|
};
|
|
1091
1147
|
const turnStartIdx = findUserTextMsgIdx(msgs.length - 1);
|
|
1092
|
-
if (turnStartIdx >= 0)
|
|
1148
|
+
if (turnStartIdx >= 0 && !disableTurnStartCache) {
|
|
1149
|
+
applyCacheControlToLastBlock(turnStartIdx);
|
|
1150
|
+
}
|
|
1093
1151
|
|
|
1094
1152
|
// Previous-turn anchor: when this request is the first of a new turn
|
|
1095
1153
|
// (turn-start is the very last message — no tool-use loop yet), also
|
|
@@ -1101,9 +1159,8 @@ export class AnthropicProvider implements Provider {
|
|
|
1101
1159
|
// cache_creation tokens per new turn). Skipped during tool-use loops
|
|
1102
1160
|
// where the current turn-start already covers the same prefix and a
|
|
1103
1161
|
// second anchor would blow the 4-breakpoint budget.
|
|
1104
|
-
let prevTurnAnchorIdx = -1;
|
|
1105
1162
|
if (turnStartIdx === msgs.length - 1 && turnStartIdx > 0) {
|
|
1106
|
-
prevTurnAnchorIdx = findUserTextMsgIdx(turnStartIdx - 1);
|
|
1163
|
+
const prevTurnAnchorIdx = findUserTextMsgIdx(turnStartIdx - 1);
|
|
1107
1164
|
if (prevTurnAnchorIdx >= 0)
|
|
1108
1165
|
applyCacheControlToLastBlock(prevTurnAnchorIdx);
|
|
1109
1166
|
}
|
|
@@ -1114,7 +1171,6 @@ export class AnthropicProvider implements Provider {
|
|
|
1114
1171
|
// cheaply without conflicting with the 1h breakpoints above.
|
|
1115
1172
|
// Skip thinking/redacted_thinking blocks — Anthropic doesn't allow
|
|
1116
1173
|
// cache_control on those types.
|
|
1117
|
-
let tailBreakpointApplied = false;
|
|
1118
1174
|
if (turnStartIdx >= 0 && turnStartIdx < sentMessages.length - 1) {
|
|
1119
1175
|
const lastMsg = sentMessages[sentMessages.length - 1];
|
|
1120
1176
|
if (Array.isArray(lastMsg.content) && lastMsg.content.length > 0) {
|
|
@@ -1136,34 +1192,15 @@ export class AnthropicProvider implements Provider {
|
|
|
1136
1192
|
if (tailBlock && typeof tailBlock !== "string") {
|
|
1137
1193
|
(tailBlock as unknown as Record<string, unknown>).cache_control =
|
|
1138
1194
|
tailCacheControl;
|
|
1139
|
-
tailBreakpointApplied = true;
|
|
1140
1195
|
}
|
|
1141
1196
|
}
|
|
1142
1197
|
}
|
|
1143
1198
|
|
|
1144
|
-
//
|
|
1145
|
-
//
|
|
1146
|
-
//
|
|
1147
|
-
//
|
|
1148
|
-
//
|
|
1149
|
-
// block (workspace context) rarely changes mid-session and
|
|
1150
|
-
// benefits more from caching. Tail and prev-turn-anchor are
|
|
1151
|
-
// mutually exclusive (prev-turn-anchor only fires when turn-start
|
|
1152
|
-
// is the last message, which is the exact condition that suppresses
|
|
1153
|
-
// the tail), so we never exceed 5.
|
|
1154
|
-
const hasToolCacheBreakpoint =
|
|
1155
|
-
params.tools?.some(
|
|
1156
|
-
(t) => "cache_control" in t && t.cache_control != null,
|
|
1157
|
-
) ?? false;
|
|
1158
|
-
if (
|
|
1159
|
-
(tailBreakpointApplied || prevTurnAnchorIdx >= 0) &&
|
|
1160
|
-
Array.isArray(params.system) &&
|
|
1161
|
-
params.system.length === 2 &&
|
|
1162
|
-
hasToolCacheBreakpoint
|
|
1163
|
-
) {
|
|
1164
|
-
delete (params.system[0] as unknown as Record<string, unknown>)
|
|
1165
|
-
.cache_control;
|
|
1166
|
-
}
|
|
1199
|
+
// Cache-breakpoint accounting: system(1) + tools(1) + turn-start(1) +
|
|
1200
|
+
// (tail OR prev-turn-anchor)(1) = 4 — exactly Anthropic's per-request
|
|
1201
|
+
// cap. Tail and prev-turn-anchor are mutually exclusive (the latter
|
|
1202
|
+
// only fires when turn-start is the last message, which suppresses
|
|
1203
|
+
// the tail), so the total can't drift past 4.
|
|
1167
1204
|
|
|
1168
1205
|
// Strip orphaned UTF-16 surrogates so the Anthropic JSON parser never
|
|
1169
1206
|
// sees invalid strings produced by upstream surrogate-splitting `.slice()` calls.
|
|
@@ -1274,6 +1311,19 @@ export class AnthropicProvider implements Provider {
|
|
|
1274
1311
|
let lastInputJsonEmitMs = 0;
|
|
1275
1312
|
let pendingInputJsonFlush: ReturnType<typeof setTimeout> | undefined;
|
|
1276
1313
|
|
|
1314
|
+
// Anthropic streams `server_tool_use` block input via `input_json_delta`
|
|
1315
|
+
// events (the block's own `input` field is `{}` at content_block_start).
|
|
1316
|
+
// We accumulate the JSON separately from regular `tool_use` blocks so
|
|
1317
|
+
// the daemon can read the resolved query when the paired
|
|
1318
|
+
// `web_search_tool_result` arrives — without this, downstream activity
|
|
1319
|
+
// metadata sees an empty query.
|
|
1320
|
+
let currentServerToolUseId: string | undefined;
|
|
1321
|
+
let accumulatedServerToolInputJson = "";
|
|
1322
|
+
const resolvedServerToolInputs = new Map<
|
|
1323
|
+
string,
|
|
1324
|
+
Record<string, unknown>
|
|
1325
|
+
>();
|
|
1326
|
+
|
|
1277
1327
|
stream.on("streamEvent", (event) => {
|
|
1278
1328
|
// Reset the text sentinel buffer at each content-block boundary.
|
|
1279
1329
|
// A new block starts fresh; at the end of a block, flush any
|
|
@@ -1300,6 +1350,8 @@ export class AnthropicProvider implements Provider {
|
|
|
1300
1350
|
event.type === "content_block_start" &&
|
|
1301
1351
|
event.content_block.type === "server_tool_use"
|
|
1302
1352
|
) {
|
|
1353
|
+
currentServerToolUseId = event.content_block.id;
|
|
1354
|
+
accumulatedServerToolInputJson = "";
|
|
1303
1355
|
onEvent?.({
|
|
1304
1356
|
type: "server_tool_start",
|
|
1305
1357
|
name: event.content_block.name,
|
|
@@ -1315,11 +1367,21 @@ export class AnthropicProvider implements Provider {
|
|
|
1315
1367
|
) {
|
|
1316
1368
|
const block = event.content_block as {
|
|
1317
1369
|
tool_use_id: string;
|
|
1318
|
-
content?:
|
|
1370
|
+
content?:
|
|
1371
|
+
| { type: "web_search_tool_result_error"; error_code?: string }
|
|
1372
|
+
| unknown[];
|
|
1319
1373
|
};
|
|
1320
1374
|
const isError =
|
|
1321
1375
|
!Array.isArray(block.content) &&
|
|
1322
1376
|
block.content?.type === "web_search_tool_result_error";
|
|
1377
|
+
const errorCode =
|
|
1378
|
+
isError && !Array.isArray(block.content)
|
|
1379
|
+
? block.content?.error_code
|
|
1380
|
+
: undefined;
|
|
1381
|
+
const resolvedInput = resolvedServerToolInputs.get(
|
|
1382
|
+
block.tool_use_id,
|
|
1383
|
+
);
|
|
1384
|
+
resolvedServerToolInputs.delete(block.tool_use_id);
|
|
1323
1385
|
onEvent?.({
|
|
1324
1386
|
type: "server_tool_complete",
|
|
1325
1387
|
toolUseId: block.tool_use_id,
|
|
@@ -1327,6 +1389,8 @@ export class AnthropicProvider implements Provider {
|
|
|
1327
1389
|
...(Array.isArray(block.content)
|
|
1328
1390
|
? { content: block.content }
|
|
1329
1391
|
: {}),
|
|
1392
|
+
...(resolvedInput ? { resolvedInput } : {}),
|
|
1393
|
+
...(errorCode ? { errorCode } : {}),
|
|
1330
1394
|
});
|
|
1331
1395
|
}
|
|
1332
1396
|
if (event.type === "content_block_stop") {
|
|
@@ -1345,6 +1409,25 @@ export class AnthropicProvider implements Provider {
|
|
|
1345
1409
|
currentStreamingToolName = undefined;
|
|
1346
1410
|
currentStreamingToolUseId = undefined;
|
|
1347
1411
|
accumulatedInputJson = "";
|
|
1412
|
+
// Finalize the resolved input for a `server_tool_use` block (e.g.
|
|
1413
|
+
// the actual web-search query) so the paired `web_search_tool_result`
|
|
1414
|
+
// emits `server_tool_complete` with `resolvedInput` populated.
|
|
1415
|
+
if (currentServerToolUseId && accumulatedServerToolInputJson) {
|
|
1416
|
+
try {
|
|
1417
|
+
const parsed = JSON.parse(accumulatedServerToolInputJson);
|
|
1418
|
+
if (parsed && typeof parsed === "object") {
|
|
1419
|
+
resolvedServerToolInputs.set(
|
|
1420
|
+
currentServerToolUseId,
|
|
1421
|
+
parsed as Record<string, unknown>,
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
} catch {
|
|
1425
|
+
// Malformed partial JSON — drop silently; downstream falls
|
|
1426
|
+
// back to whatever was captured at server_tool_start.
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
currentServerToolUseId = undefined;
|
|
1430
|
+
accumulatedServerToolInputJson = "";
|
|
1348
1431
|
// Flush residual text buffer unless it's exactly a sentinel.
|
|
1349
1432
|
if (textBuffer.length > 0 && !isCompleteSentinel(textBuffer)) {
|
|
1350
1433
|
onEvent?.({ type: "text_delta", text: textBuffer });
|
|
@@ -1354,6 +1437,13 @@ export class AnthropicProvider implements Provider {
|
|
|
1354
1437
|
});
|
|
1355
1438
|
|
|
1356
1439
|
stream.on("inputJson", (partialJson) => {
|
|
1440
|
+
if (currentServerToolUseId) {
|
|
1441
|
+
// Server-tool input (e.g. `web_search` query) — accumulate without
|
|
1442
|
+
// emitting `input_json_delta`; the daemon only consumes the
|
|
1443
|
+
// finalized value from `server_tool_complete.resolvedInput`.
|
|
1444
|
+
accumulatedServerToolInputJson += partialJson;
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1357
1447
|
if (!currentStreamingToolName) return;
|
|
1358
1448
|
accumulatedInputJson += partialJson;
|
|
1359
1449
|
const now = Date.now();
|
|
@@ -1544,6 +1634,9 @@ export class AnthropicProvider implements Provider {
|
|
|
1544
1634
|
case "text":
|
|
1545
1635
|
return { type: "text", text: block.text };
|
|
1546
1636
|
case "thinking":
|
|
1637
|
+
if (!block.signature) {
|
|
1638
|
+
return null;
|
|
1639
|
+
}
|
|
1547
1640
|
return {
|
|
1548
1641
|
type: "thinking",
|
|
1549
1642
|
thinking: block.thinking,
|
|
@@ -24,6 +24,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
24
24
|
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
25
25
|
import { getConfig } from "../config/loader.js";
|
|
26
26
|
import { getDb } from "../memory/db-connection.js";
|
|
27
|
+
import { isConnectionCompatibleWithModel } from "./connection-model-compat.js";
|
|
27
28
|
import {
|
|
28
29
|
ConnectionResolutionError,
|
|
29
30
|
tryResolveProviderForConnectionName,
|
|
@@ -73,10 +74,15 @@ export class CallSiteRoutingProvider implements Provider {
|
|
|
73
74
|
* `expectedProvider` is the provider name the resolved profile
|
|
74
75
|
* declared. The hook verifies the connection's provider matches
|
|
75
76
|
* and throws on mismatch.
|
|
77
|
+
*
|
|
78
|
+
* `model` is the resolved call-site model, threaded through so the
|
|
79
|
+
* connection lookup can gate `oauth_subscription` (Codex) connections
|
|
80
|
+
* by model compatibility.
|
|
76
81
|
*/
|
|
77
82
|
private readonly resolveByConnection: (
|
|
78
83
|
connectionName: string,
|
|
79
84
|
expectedProvider: string,
|
|
85
|
+
model: string | undefined,
|
|
80
86
|
) => Promise<Provider | null>,
|
|
81
87
|
) {
|
|
82
88
|
this.tokenEstimationProvider = defaultProvider.tokenEstimationProvider;
|
|
@@ -155,7 +161,11 @@ export class CallSiteRoutingProvider implements Provider {
|
|
|
155
161
|
const candidates = listConnections(getDb(), {
|
|
156
162
|
provider: resolved.provider,
|
|
157
163
|
});
|
|
158
|
-
const active = candidates.find(
|
|
164
|
+
const active = candidates.find(
|
|
165
|
+
(c) =>
|
|
166
|
+
c.status === "active" &&
|
|
167
|
+
isConnectionCompatibleWithModel(c, resolved.model),
|
|
168
|
+
);
|
|
159
169
|
if (active) {
|
|
160
170
|
connectionName = active.name;
|
|
161
171
|
}
|
|
@@ -168,6 +178,7 @@ export class CallSiteRoutingProvider implements Provider {
|
|
|
168
178
|
const connectionProvider = await this.resolveByConnection(
|
|
169
179
|
connectionName,
|
|
170
180
|
resolved.provider,
|
|
181
|
+
resolved.model,
|
|
171
182
|
);
|
|
172
183
|
if (connectionProvider) return connectionProvider;
|
|
173
184
|
return this.defaultProvider;
|
|
@@ -200,11 +211,12 @@ export function wrapWithCallSiteRouting(
|
|
|
200
211
|
): Provider {
|
|
201
212
|
return new CallSiteRoutingProvider(
|
|
202
213
|
base,
|
|
203
|
-
(connectionName, expectedProvider) =>
|
|
214
|
+
(connectionName, expectedProvider, model) =>
|
|
204
215
|
tryResolveProviderForConnectionName(
|
|
205
216
|
connectionName,
|
|
206
217
|
config,
|
|
207
218
|
expectedProvider,
|
|
219
|
+
model,
|
|
208
220
|
),
|
|
209
221
|
);
|
|
210
222
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model-compatibility gate for auto-resolved provider connections.
|
|
3
|
+
*
|
|
4
|
+
* When a profile uses "Any active <provider> connection" (no
|
|
5
|
+
* `provider_connection` pinned), the daemon auto-picks an active connection
|
|
6
|
+
* for the provider. `oauth_subscription` connections (ChatGPT Codex) hard-
|
|
7
|
+
* route every request to the Codex endpoint, which rejects non-Codex models
|
|
8
|
+
* with HTTP 400. This helper lets the auto-resolution sites skip such a
|
|
9
|
+
* connection when the requested model is not Codex-compatible.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { ProviderConnection } from "./inference/auth.js";
|
|
13
|
+
import { isCodexSubscriptionModel } from "./openai/codex-models.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Whether `connection` can serve a request for `model` during
|
|
17
|
+
* auto-resolution.
|
|
18
|
+
*
|
|
19
|
+
* `oauth_subscription` connections route through the ChatGPT Codex endpoint,
|
|
20
|
+
* so they are only compatible with Codex models. Every other auth type
|
|
21
|
+
* imposes no model restriction and is always compatible.
|
|
22
|
+
*
|
|
23
|
+
* `model` may be undefined when the call site has no resolved model; in that
|
|
24
|
+
* case no model gating is applied (returns true) so resolution behaviour is
|
|
25
|
+
* unchanged.
|
|
26
|
+
*
|
|
27
|
+
* This gate applies to auto-resolution only — an explicitly pinned
|
|
28
|
+
* `provider_connection` bypasses connection selection entirely and is used
|
|
29
|
+
* regardless of model.
|
|
30
|
+
*/
|
|
31
|
+
export function isConnectionCompatibleWithModel(
|
|
32
|
+
connection: Pick<ProviderConnection, "auth">,
|
|
33
|
+
model: string | undefined,
|
|
34
|
+
): boolean {
|
|
35
|
+
if (connection.auth.type !== "oauth_subscription") return true;
|
|
36
|
+
if (!model) return true;
|
|
37
|
+
return isCodexSubscriptionModel(model);
|
|
38
|
+
}
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
31
31
|
import { getDb } from "../memory/db-connection.js";
|
|
32
32
|
import { getLogger } from "../util/logger.js";
|
|
33
|
+
import { isConnectionCompatibleWithModel } from "./connection-model-compat.js";
|
|
33
34
|
import { getConnection, listConnections } from "./inference/connections.js";
|
|
34
35
|
import type { ProvidersConfig } from "./registry.js";
|
|
35
36
|
import { resolveProviderFromConnection } from "./registry.js";
|
|
@@ -79,11 +80,16 @@ export class ConnectionResolutionError extends Error {
|
|
|
79
80
|
* `expectedProvider` is the provider name the resolving profile declared.
|
|
80
81
|
* Pass `undefined` to skip the mismatch check (callers that don't yet
|
|
81
82
|
* know the expected provider).
|
|
83
|
+
*
|
|
84
|
+
* `model` is the resolved call-site model. It gates the `provider_mismatch`
|
|
85
|
+
* auto-recovery below so a non-Codex model is never rerouted onto an
|
|
86
|
+
* `oauth_subscription` (ChatGPT Codex) connection.
|
|
82
87
|
*/
|
|
83
88
|
export async function tryResolveProviderForConnectionName(
|
|
84
89
|
connectionName: string,
|
|
85
90
|
config: ProvidersConfig,
|
|
86
91
|
expectedProvider?: string,
|
|
92
|
+
model?: string,
|
|
87
93
|
): Promise<Provider | null> {
|
|
88
94
|
let connection;
|
|
89
95
|
try {
|
|
@@ -113,7 +119,10 @@ export async function tryResolveProviderForConnectionName(
|
|
|
113
119
|
try {
|
|
114
120
|
const db = getDb();
|
|
115
121
|
const candidates = listConnections(db, { provider: expectedProvider });
|
|
116
|
-
const active = candidates.find(
|
|
122
|
+
const active = candidates.find(
|
|
123
|
+
(c) =>
|
|
124
|
+
c.status === "active" && isConnectionCompatibleWithModel(c, model),
|
|
125
|
+
);
|
|
117
126
|
if (active) {
|
|
118
127
|
log.info(
|
|
119
128
|
{
|
|
@@ -192,7 +201,11 @@ export async function resolveDefaultProvider(
|
|
|
192
201
|
const candidates = listConnections(getDb(), {
|
|
193
202
|
provider: resolved.provider,
|
|
194
203
|
});
|
|
195
|
-
const active = candidates.find(
|
|
204
|
+
const active = candidates.find(
|
|
205
|
+
(c) =>
|
|
206
|
+
c.status === "active" &&
|
|
207
|
+
isConnectionCompatibleWithModel(c, resolved.model),
|
|
208
|
+
);
|
|
196
209
|
if (active) {
|
|
197
210
|
log.info(
|
|
198
211
|
{ provider: resolved.provider, resolvedConnection: active.name },
|
|
@@ -216,5 +229,6 @@ export async function resolveDefaultProvider(
|
|
|
216
229
|
connectionName,
|
|
217
230
|
config,
|
|
218
231
|
resolved.provider,
|
|
232
|
+
resolved.model,
|
|
219
233
|
);
|
|
220
234
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PROVIDER_CATALOG } from "../model-catalog.js";
|
|
1
2
|
import { OpenAIChatCompletionsProvider } from "../openai/chat-completions-provider.js";
|
|
2
3
|
|
|
3
4
|
export interface FireworksProviderOptions {
|
|
@@ -8,6 +9,15 @@ export interface FireworksProviderOptions {
|
|
|
8
9
|
|
|
9
10
|
const DEFAULT_FIREWORKS_BASE_URL = "https://api.fireworks.ai/inference/v1";
|
|
10
11
|
|
|
12
|
+
const FIREWORKS_MODEL_EFFORT_CEILINGS: ReadonlyMap<
|
|
13
|
+
string,
|
|
14
|
+
"high" | "xhigh" | "max"
|
|
15
|
+
> = new Map(
|
|
16
|
+
PROVIDER_CATALOG.find((p) => p.id === "fireworks")?.models.flatMap((m) =>
|
|
17
|
+
m.maxEffort ? ([[m.id, m.maxEffort]] as const) : [],
|
|
18
|
+
) ?? [],
|
|
19
|
+
);
|
|
20
|
+
|
|
11
21
|
export class FireworksProvider extends OpenAIChatCompletionsProvider {
|
|
12
22
|
constructor(
|
|
13
23
|
apiKey: string,
|
|
@@ -19,9 +29,17 @@ export class FireworksProvider extends OpenAIChatCompletionsProvider {
|
|
|
19
29
|
providerName: "fireworks",
|
|
20
30
|
providerLabel: "Fireworks",
|
|
21
31
|
streamTimeoutMs: options.streamTimeoutMs,
|
|
22
|
-
//
|
|
23
|
-
// low|medium|high
|
|
32
|
+
// Fallback for models not declared in the catalog. Most Fireworks
|
|
33
|
+
// chat-completions models only document `low|medium|high`; per-model
|
|
34
|
+
// overrides (e.g. DeepSeek V4 → "max") come from
|
|
35
|
+
// {@link resolveMaxReasoningEffort}.
|
|
24
36
|
maxReasoningEffort: "high",
|
|
25
37
|
});
|
|
26
38
|
}
|
|
39
|
+
|
|
40
|
+
protected override resolveMaxReasoningEffort(
|
|
41
|
+
model: string,
|
|
42
|
+
): "high" | "xhigh" | "max" {
|
|
43
|
+
return FIREWORKS_MODEL_EFFORT_CEILINGS.get(model) ?? "high";
|
|
44
|
+
}
|
|
27
45
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type * as genai from "@google/genai";
|
|
2
|
-
import { ApiError, GoogleGenAI } from "@google/genai";
|
|
2
|
+
import { ApiError, GoogleGenAI, ThinkingLevel } from "@google/genai";
|
|
3
3
|
|
|
4
|
-
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../../prompts/cache-boundary.js";
|
|
5
4
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
6
5
|
import { ProviderError } from "../../util/errors.js";
|
|
7
6
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -34,6 +33,47 @@ function isGemini3Model(model: string): boolean {
|
|
|
34
33
|
return model.startsWith("gemini-3") || model.startsWith("models/gemini-3");
|
|
35
34
|
}
|
|
36
35
|
|
|
36
|
+
const THINKING_LEVEL_BY_NAME: Record<string, ThinkingLevel> = {
|
|
37
|
+
minimal: ThinkingLevel.MINIMAL,
|
|
38
|
+
low: ThinkingLevel.LOW,
|
|
39
|
+
medium: ThinkingLevel.MEDIUM,
|
|
40
|
+
high: ThinkingLevel.HIGH,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Translate the resolved wire-shape `thinking` config into Gemini's
|
|
45
|
+
* `thinkingConfig`. Returns `undefined` when no thinking config was supplied,
|
|
46
|
+
* which lets Google's per-model default apply (e.g. `gemini-3.5-flash`
|
|
47
|
+
* defaults to dynamic medium-level thinking).
|
|
48
|
+
*
|
|
49
|
+
* `enabled: false` maps to `thinkingLevel: MINIMAL` because Gemini 3.x cannot
|
|
50
|
+
* fully disable thinking — `"minimal"` is the floor. `includeThoughts` is
|
|
51
|
+
* gated on `streamThinking` so callers that opted out of streaming thoughts
|
|
52
|
+
* don't pay for thought tokens in the response.
|
|
53
|
+
*/
|
|
54
|
+
function buildThinkingConfig(
|
|
55
|
+
thinking: Record<string, unknown> | undefined,
|
|
56
|
+
): genai.ThinkingConfig | undefined {
|
|
57
|
+
if (!thinking) return undefined;
|
|
58
|
+
if (thinking.type === "disabled") {
|
|
59
|
+
return {
|
|
60
|
+
thinkingLevel: ThinkingLevel.MINIMAL,
|
|
61
|
+
includeThoughts: false,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (thinking.type !== "adaptive") return undefined;
|
|
65
|
+
|
|
66
|
+
const result: genai.ThinkingConfig = {};
|
|
67
|
+
if (typeof thinking.level === "string") {
|
|
68
|
+
const mapped = THINKING_LEVEL_BY_NAME[thinking.level];
|
|
69
|
+
if (mapped) result.thinkingLevel = mapped;
|
|
70
|
+
}
|
|
71
|
+
if (typeof thinking.streamThinking === "boolean") {
|
|
72
|
+
result.includeThoughts = thinking.streamThinking;
|
|
73
|
+
}
|
|
74
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
37
77
|
function stripGeminiHttpOptions(
|
|
38
78
|
config: genai.GenerateContentConfig,
|
|
39
79
|
): genai.GenerateContentConfig {
|
|
@@ -175,6 +215,9 @@ export class GeminiProvider implements Provider {
|
|
|
175
215
|
const usageAttributionHeaders = configObj?.usageAttributionHeaders as
|
|
176
216
|
| Record<string, string>
|
|
177
217
|
| undefined;
|
|
218
|
+
const thinkingConfig = buildThinkingConfig(
|
|
219
|
+
configObj?.thinking as Record<string, unknown> | undefined,
|
|
220
|
+
);
|
|
178
221
|
const activeModel = modelOverride ?? this.model;
|
|
179
222
|
|
|
180
223
|
try {
|
|
@@ -183,14 +226,14 @@ export class GeminiProvider implements Provider {
|
|
|
183
226
|
const geminiConfig: genai.GenerateContentConfig = {};
|
|
184
227
|
|
|
185
228
|
if (systemPrompt) {
|
|
186
|
-
geminiConfig.systemInstruction = systemPrompt
|
|
187
|
-
SYSTEM_PROMPT_CACHE_BOUNDARY,
|
|
188
|
-
"\n",
|
|
189
|
-
);
|
|
229
|
+
geminiConfig.systemInstruction = systemPrompt;
|
|
190
230
|
}
|
|
191
231
|
if (maxTokens) {
|
|
192
232
|
geminiConfig.maxOutputTokens = maxTokens;
|
|
193
233
|
}
|
|
234
|
+
if (thinkingConfig) {
|
|
235
|
+
geminiConfig.thinkingConfig = thinkingConfig;
|
|
236
|
+
}
|
|
194
237
|
if (tools && tools.length > 0) {
|
|
195
238
|
geminiConfig.tools = [
|
|
196
239
|
{
|