@vellumai/assistant 0.6.4 → 0.6.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/.prettierignore +5 -0
- package/ARCHITECTURE.md +32 -36
- package/Dockerfile +12 -0
- package/README.md +3 -4
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +1 -20
- package/docs/architecture/security.md +16 -16
- package/docs/error-handling.md +111 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/knip.json +9 -2
- package/node_modules/@vellumai/ces-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/openapi.yaml +123 -11
- package/package.json +6 -3
- package/scripts/generate-openapi.ts +50 -11
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +112 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +171 -2
- package/src/__tests__/approval-cascade.test.ts +31 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +51 -182
- package/src/__tests__/btw-routes.test.ts +47 -1
- package/src/__tests__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +27 -4
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +428 -501
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +11 -28
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +427 -114
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +530 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
- package/src/__tests__/conversation-agent-loop.test.ts +412 -82
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
- package/src/__tests__/conversation-process-callsite.test.ts +306 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
- package/src/__tests__/conversation-queue.test.ts +41 -26
- package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
- package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +34 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
- package/src/__tests__/conversation-speed-override.test.ts +30 -11
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +3 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
- package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +135 -19
- package/src/__tests__/credentials-cli.test.ts +1 -9
- package/src/__tests__/cross-provider-web-search.test.ts +84 -0
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/gemini-provider.test.ts +0 -3
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/intent-routing.test.ts +1 -40
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +121 -0
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +684 -0
- package/src/__tests__/model-intents.test.ts +9 -83
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/oauth-store.test.ts +10 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/openai-provider.test.ts +7 -0
- package/src/__tests__/openai-responses-provider.test.ts +396 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/pricing.test.ts +50 -3
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +0 -1
- package/src/__tests__/reaction-persistence.test.ts +560 -0
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +29 -1
- package/src/__tests__/server-history-render.test.ts +31 -0
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skills.test.ts +19 -33
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +160 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor.test.ts +60 -94
- package/src/__tests__/trust-store.test.ts +442 -109
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +1 -13
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +209 -17
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/telephony-stt-routing.ts +1 -1
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/email-list.test.ts +6 -0
- package/src/cli/commands/__tests__/email-send.test.ts +93 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +14 -1
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +300 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +23 -4
- package/src/cli.ts +0 -37
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -175
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +194 -10
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +30 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/filing.ts +2 -7
- package/src/config/schemas/heartbeat.ts +0 -5
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +318 -0
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +9 -4
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/schemas/tts.ts +53 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skills.ts +2 -2
- package/src/context/__tests__/compact-prompt.test.ts +45 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/prompts/compact.md +12 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/window-manager.ts +229 -25
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +19 -8
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +65 -2
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +0 -1
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
- package/src/daemon/conversation-agent-loop.ts +462 -80
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-lifecycle.ts +30 -6
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-process.ts +10 -4
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +760 -29
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +10 -5
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +118 -30
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +54 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +2 -2
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +76 -14
- package/src/daemon/message-types/conversations.ts +14 -0
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +117 -9
- package/src/daemon/tool-side-effects.ts +0 -9
- package/src/daemon/watch-handler.ts +4 -4
- package/src/daemon/web-search-history.ts +126 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/heartbeat-service.ts +76 -28
- package/src/home/__tests__/feed-scheduler.test.ts +39 -11
- package/src/home/__tests__/rollup-producer.test.ts +44 -0
- package/src/home/assistant-feed-authoring.ts +4 -0
- package/src/home/emit-feed-event.ts +4 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +56 -2
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rollup-producer.ts +34 -5
- package/src/home/suggested-prompts.ts +101 -0
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/socket-path.test.ts +73 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +2 -1
- package/src/ipc/cli-server.ts +26 -8
- package/src/ipc/gateway-client.ts +4 -4
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +61 -0
- package/src/ipc/routes/browser.ts +96 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/index.ts +17 -1
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +100 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/conversation-analyze-job.ts +14 -13
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +103 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-title-service.ts +7 -4
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +89 -29
- package/src/memory/graph/extraction.test.ts +272 -2
- package/src/memory/graph/extraction.ts +173 -51
- package/src/memory/graph/graph-search.test.ts +92 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +230 -48
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/indexer.ts +5 -5
- package/src/memory/job-handlers/conversation-starters.ts +23 -20
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +44 -3
- package/src/memory/jobs-worker.ts +4 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/pkb/pkb-index.test.ts +368 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +438 -0
- package/src/memory/pkb/pkb-search.ts +137 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.ts +122 -1
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +22 -0
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/adapter.ts +14 -2
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
- package/src/messaging/providers/slack/render-transcript.ts +443 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/oauth/oauth-store.ts +1 -0
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/seed-providers.ts +4 -2
- package/src/permissions/approval-policy.test.ts +948 -0
- package/src/permissions/approval-policy.ts +257 -0
- package/src/permissions/bash-risk-classifier.test.ts +1208 -0
- package/src/permissions/bash-risk-classifier.ts +707 -0
- package/src/permissions/checker.ts +217 -708
- package/src/permissions/command-registry.test.ts +535 -0
- package/src/permissions/command-registry.ts +825 -0
- package/src/permissions/defaults.ts +26 -78
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/risk-types.ts +205 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +161 -62
- package/src/permissions/types.ts +23 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +1 -16
- package/src/platform/client.ts +19 -1
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/SOUL.md +2 -2
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +183 -14
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/gemini/client.ts +65 -2
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +501 -33
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +57 -1
- package/src/providers/openai/responses-provider.ts +86 -9
- package/src/providers/openrouter/client.ts +76 -9
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +19 -8
- package/src/providers/retry.ts +174 -39
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +7 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
- package/src/providers/speech-to-text/xai-realtime.ts +796 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +93 -3
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/agent-wake.ts +63 -22
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/btw-sidechain.ts +13 -3
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +52 -1
- package/src/runtime/http-types.ts +23 -1
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/vbundle-importer.ts +154 -9
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
- package/src/runtime/routes/approval-routes.ts +12 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +133 -27
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +120 -2
- package/src/runtime/routes/inbound-message-handler.ts +912 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/integrations/slack/channel.ts +25 -3
- package/src/runtime/routes/llm-context-normalization.ts +23 -1
- package/src/runtime/routes/migration-routes.ts +720 -124
- package/src/runtime/routes/settings-routes.ts +4 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +3 -2
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
- package/src/runtime/services/analyze-conversation.ts +12 -16
- package/src/runtime/skill-route-registry.ts +28 -6
- package/src/schedule/scheduler.ts +8 -0
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +98 -35
- package/src/security/secure-keys.ts +7 -8
- package/src/security/token-manager.ts +27 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/skills/catalog-cache.ts +26 -7
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
- package/src/stt/daemon-batch-transcriber.ts +33 -0
- package/src/stt/stt-stream-session.ts +8 -1
- package/src/stt/types.ts +5 -1
- package/src/subagent/manager.ts +41 -13
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
- package/src/tools/browser/browser-execution.ts +65 -38
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +4 -0
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +36 -15
- package/src/tools/policy-context.ts +25 -8
- package/src/tools/registry.ts +55 -3
- package/src/tools/side-effects.ts +0 -11
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +1 -0
- package/src/tools/tool-manifest.ts +6 -21
- package/src/tools/types.ts +12 -3
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +240 -13
- package/src/tts/provider-catalog.ts +18 -0
- package/src/tts/providers/index.ts +2 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/types.ts +46 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +2 -2
- package/src/util/pricing.ts +15 -5
- package/src/watcher/engine.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
- package/src/__tests__/gmail-archive-gate.test.ts +0 -246
- package/src/__tests__/gmail-preferences.test.ts +0 -117
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
- package/src/__tests__/update-bulletin-format.test.ts +0 -181
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -478
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/doctor.ts +0 -341
- package/src/config/bundled-skills/browser/SKILL.md +0 -88
- package/src/config/bundled-skills/browser/TOOLS.json +0 -516
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/gmail/SKILL.md +0 -221
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/slack/SKILL.md +0 -108
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/prompts/templates/UPDATES.md +0 -50
- package/src/prompts/update-bulletin-format.ts +0 -85
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -139
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -15,12 +15,50 @@ import type {
|
|
|
15
15
|
SendMessageOptions,
|
|
16
16
|
ToolDefinition,
|
|
17
17
|
} from "../types.js";
|
|
18
|
+
import {
|
|
19
|
+
ContextOverflowError,
|
|
20
|
+
extractOverflowTokensFromMessage,
|
|
21
|
+
} from "../types.js";
|
|
18
22
|
|
|
19
23
|
const log = getLogger("anthropic-client");
|
|
20
24
|
|
|
21
25
|
/** Validation-specific timeout (10s) so a stalled network doesn't block key submission. */
|
|
22
26
|
const VALIDATION_TIMEOUT_MS = 10_000;
|
|
23
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Detect Anthropic's `prompt_too_long` context-overflow signal.
|
|
30
|
+
*
|
|
31
|
+
* Anthropic returns HTTP 400 with a body shaped as
|
|
32
|
+
* `{ type: "error", error: { type: "invalid_request_error", message: "..." } }`
|
|
33
|
+
* where the inner `message` carries the "prompt is too long: N tokens > M
|
|
34
|
+
* maximum" text. The SDK stores the body at `APIError.error` and formats a
|
|
35
|
+
* top-level `message` by JSON-stringifying the body when no top-level
|
|
36
|
+
* `.message` key exists — so we probe both the nested body and the
|
|
37
|
+
* formatted string.
|
|
38
|
+
*/
|
|
39
|
+
export function detectAnthropicContextOverflow(
|
|
40
|
+
error: InstanceType<typeof Anthropic.APIError>,
|
|
41
|
+
): { actualTokens?: number; maxTokens?: number } | null {
|
|
42
|
+
// 413 is theoretically adjacent but Anthropic does not emit it today.
|
|
43
|
+
if (error.status !== 400) return null;
|
|
44
|
+
const body = error.error as
|
|
45
|
+
| {
|
|
46
|
+
type?: string;
|
|
47
|
+
message?: string;
|
|
48
|
+
error?: { type?: string; message?: string };
|
|
49
|
+
}
|
|
50
|
+
| undefined;
|
|
51
|
+
const innerMessage =
|
|
52
|
+
(typeof body === "object" && body != null
|
|
53
|
+
? (body.error?.message ?? body.message)
|
|
54
|
+
: undefined) ?? "";
|
|
55
|
+
const topLevelMessage = error.message ?? "";
|
|
56
|
+
const combined = `${innerMessage} ${topLevelMessage}`;
|
|
57
|
+
if (!/prompt.?is.?too.?long|prompt_too_long/i.test(combined)) return null;
|
|
58
|
+
// Prefer the clean inner message over the JSON-stringified top-level string.
|
|
59
|
+
return extractOverflowTokensFromMessage(innerMessage || topLevelMessage);
|
|
60
|
+
}
|
|
61
|
+
|
|
24
62
|
/** Rate-limit the orphaned-surrogate warning so a single bad stream can't flood logs. */
|
|
25
63
|
const ORPHAN_WARNING_THROTTLE_MS = 60_000;
|
|
26
64
|
let lastOrphanWarningMs = 0;
|
|
@@ -132,6 +170,26 @@ export const PLACEHOLDER_EMPTY_TURN =
|
|
|
132
170
|
export const PLACEHOLDER_BLOCKS_OMITTED =
|
|
133
171
|
"\x00__PLACEHOLDER__[internal blocks omitted]";
|
|
134
172
|
|
|
173
|
+
// Compared against the payload with any leading `\x00` stripped, so the check
|
|
174
|
+
// matches both the prefixed sentinel we emit and any bare variant that lost
|
|
175
|
+
// the null byte in transit (e.g. the model echoing the text back without
|
|
176
|
+
// reproducing the control character).
|
|
177
|
+
const PLACEHOLDER_SENTINEL_BARE: ReadonlySet<string> = new Set([
|
|
178
|
+
PLACEHOLDER_EMPTY_TURN.slice(1),
|
|
179
|
+
PLACEHOLDER_BLOCKS_OMITTED.slice(1),
|
|
180
|
+
]);
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* True when the text is one of the provider's internal alternation-preserving
|
|
184
|
+
* sentinels, with or without the null-byte prefix. These must never be
|
|
185
|
+
* persisted or rendered to users — they exist only in outbound Anthropic API
|
|
186
|
+
* request bodies.
|
|
187
|
+
*/
|
|
188
|
+
export function isPlaceholderSentinelText(text: string): boolean {
|
|
189
|
+
const normalized = text.startsWith("\x00") ? text.slice(1) : text;
|
|
190
|
+
return PLACEHOLDER_SENTINEL_BARE.has(normalized);
|
|
191
|
+
}
|
|
192
|
+
|
|
135
193
|
/**
|
|
136
194
|
* Synthetic placeholder injected as user-message content when Anthropic API
|
|
137
195
|
* alternation requires a user turn but no real user content exists. Uses the
|
|
@@ -607,16 +665,27 @@ export class AnthropicProvider implements Provider {
|
|
|
607
665
|
authToken?: string;
|
|
608
666
|
} = {},
|
|
609
667
|
) {
|
|
668
|
+
this.streamTimeoutMs = options.streamTimeoutMs ?? 1_800_000;
|
|
669
|
+
// Pass the same deadline to the SDK so its per-request timeout can't
|
|
670
|
+
// fire before `createStreamTimeout` does. The SDK's default is 10 min,
|
|
671
|
+
// which truncates any request we intend to run longer than that. We add
|
|
672
|
+
// a 60s buffer so `createStreamTimeout` always wins — its abort reason
|
|
673
|
+
// produces a clearer error message than the SDK's generic timeout.
|
|
674
|
+
const sdkTimeoutMs = this.streamTimeoutMs + 60_000;
|
|
610
675
|
this.client = options.authToken
|
|
611
676
|
? new Anthropic({
|
|
612
677
|
apiKey: null,
|
|
613
678
|
authToken: options.authToken,
|
|
614
679
|
baseURL: options.baseURL,
|
|
680
|
+
timeout: sdkTimeoutMs,
|
|
615
681
|
})
|
|
616
|
-
: new Anthropic({
|
|
682
|
+
: new Anthropic({
|
|
683
|
+
apiKey,
|
|
684
|
+
baseURL: options.baseURL,
|
|
685
|
+
timeout: sdkTimeoutMs,
|
|
686
|
+
});
|
|
617
687
|
this.model = model;
|
|
618
688
|
this.useNativeWebSearch = options.useNativeWebSearch ?? false;
|
|
619
|
-
this.streamTimeoutMs = options.streamTimeoutMs ?? 1_800_000;
|
|
620
689
|
}
|
|
621
690
|
|
|
622
691
|
async sendMessage(
|
|
@@ -631,6 +700,11 @@ export class AnthropicProvider implements Provider {
|
|
|
631
700
|
| "5m"
|
|
632
701
|
| "1h") ?? "1h";
|
|
633
702
|
let sentMessages: Anthropic.MessageParam[] | undefined;
|
|
703
|
+
const startedAt = Date.now();
|
|
704
|
+
// Hoisted so the catch block can distinguish our inner stream timeout
|
|
705
|
+
// (30 min default) from an external transport abort (bun fetch deadline,
|
|
706
|
+
// edge LB, NAT idle) — only the latter should be retried.
|
|
707
|
+
let innerTimeoutSignal: AbortSignal | undefined;
|
|
634
708
|
try {
|
|
635
709
|
const formatted = messages
|
|
636
710
|
.map((m) => {
|
|
@@ -720,10 +794,7 @@ export class AnthropicProvider implements Provider {
|
|
|
720
794
|
)
|
|
721
795
|
return false;
|
|
722
796
|
const text = (c[0] as { text?: string }).text;
|
|
723
|
-
return (
|
|
724
|
-
text === PLACEHOLDER_EMPTY_TURN ||
|
|
725
|
-
text === PLACEHOLDER_BLOCKS_OMITTED
|
|
726
|
-
);
|
|
797
|
+
return typeof text === "string" && isPlaceholderSentinelText(text);
|
|
727
798
|
};
|
|
728
799
|
if (isPlaceholder(iContent)) {
|
|
729
800
|
formatted.splice(i, 1);
|
|
@@ -747,7 +818,11 @@ export class AnthropicProvider implements Provider {
|
|
|
747
818
|
max_tokens: callerMaxTokens,
|
|
748
819
|
...restConfig
|
|
749
820
|
} = (config ?? {}) as Record<string, unknown> & {
|
|
750
|
-
|
|
821
|
+
// "xhigh" is an intermediate tier between "high" and "max" supported
|
|
822
|
+
// by newer Anthropic models (e.g. Opus 4.7). The SDK's OutputConfig
|
|
823
|
+
// type doesn't yet include it, so we widen to the internal effort
|
|
824
|
+
// union and cast when building mergedOutputConfig.
|
|
825
|
+
effort?: "low" | "medium" | "high" | "xhigh" | "max";
|
|
751
826
|
speed?: "standard" | "fast";
|
|
752
827
|
output_config?: Record<string, unknown>;
|
|
753
828
|
};
|
|
@@ -761,7 +836,9 @@ export class AnthropicProvider implements Provider {
|
|
|
761
836
|
const supportsEffort = !isHaiku;
|
|
762
837
|
const mergedOutputConfig = {
|
|
763
838
|
...(output_config ?? {}),
|
|
764
|
-
...(effort && supportsEffort
|
|
839
|
+
...(effort && supportsEffort
|
|
840
|
+
? { effort: effort as Anthropic.OutputConfig["effort"] }
|
|
841
|
+
: {}),
|
|
765
842
|
};
|
|
766
843
|
// Build cache_control objects: Haiku doesn't support the extended
|
|
767
844
|
// cache TTL beta, so omit the ttl field for Haiku models.
|
|
@@ -948,6 +1025,7 @@ export class AnthropicProvider implements Provider {
|
|
|
948
1025
|
|
|
949
1026
|
const { signal: timeoutSignal, cleanup: cleanupTimeout } =
|
|
950
1027
|
createStreamTimeout(this.streamTimeoutMs, signal);
|
|
1028
|
+
innerTimeoutSignal = timeoutSignal;
|
|
951
1029
|
|
|
952
1030
|
/** Minimal stream interface shared by MessageStream and BetaMessageStream. */
|
|
953
1031
|
interface UnifiedStream {
|
|
@@ -999,8 +1077,30 @@ export class AnthropicProvider implements Provider {
|
|
|
999
1077
|
signal: timeoutSignal,
|
|
1000
1078
|
}) as unknown as UnifiedStream);
|
|
1001
1079
|
|
|
1080
|
+
// Buffer streaming text until it's clear the accumulated text isn't
|
|
1081
|
+
// going to form a placeholder sentinel. Sentinels are injected into
|
|
1082
|
+
// outbound requests for role alternation and are sometimes echoed by
|
|
1083
|
+
// the model; holding back partial prefixes prevents them from
|
|
1084
|
+
// flashing on the live UI before cleanAssistantContent strips them
|
|
1085
|
+
// at persist time. Buffer is bounded by the longest sentinel (~45
|
|
1086
|
+
// chars) and resets on every content_block_start.
|
|
1087
|
+
const SENTINEL_TEXTS: readonly string[] = [
|
|
1088
|
+
PLACEHOLDER_EMPTY_TURN,
|
|
1089
|
+
PLACEHOLDER_EMPTY_TURN.slice(1),
|
|
1090
|
+
PLACEHOLDER_BLOCKS_OMITTED,
|
|
1091
|
+
PLACEHOLDER_BLOCKS_OMITTED.slice(1),
|
|
1092
|
+
];
|
|
1093
|
+
const couldBeSentinelPrefix = (s: string): boolean =>
|
|
1094
|
+
SENTINEL_TEXTS.some((sentinel) => sentinel.startsWith(s));
|
|
1095
|
+
const isCompleteSentinel = (s: string): boolean =>
|
|
1096
|
+
SENTINEL_TEXTS.includes(s);
|
|
1097
|
+
let textBuffer = "";
|
|
1098
|
+
|
|
1002
1099
|
stream.on("text", (text) => {
|
|
1003
|
-
|
|
1100
|
+
textBuffer += text;
|
|
1101
|
+
if (couldBeSentinelPrefix(textBuffer)) return;
|
|
1102
|
+
onEvent?.({ type: "text_delta", text: textBuffer });
|
|
1103
|
+
textBuffer = "";
|
|
1004
1104
|
});
|
|
1005
1105
|
|
|
1006
1106
|
stream.on("thinking", (thinking) => {
|
|
@@ -1015,6 +1115,13 @@ export class AnthropicProvider implements Provider {
|
|
|
1015
1115
|
let pendingInputJsonFlush: ReturnType<typeof setTimeout> | undefined;
|
|
1016
1116
|
|
|
1017
1117
|
stream.on("streamEvent", (event) => {
|
|
1118
|
+
// Reset the text sentinel buffer at each content-block boundary.
|
|
1119
|
+
// A new block starts fresh; at the end of a block, flush any
|
|
1120
|
+
// buffered text that is NOT a complete sentinel, and drop it if
|
|
1121
|
+
// it is one.
|
|
1122
|
+
if (event.type === "content_block_start") {
|
|
1123
|
+
textBuffer = "";
|
|
1124
|
+
}
|
|
1018
1125
|
if (
|
|
1019
1126
|
event.type === "content_block_start" &&
|
|
1020
1127
|
event.content_block.type === "tool_use"
|
|
@@ -1078,6 +1185,11 @@ export class AnthropicProvider implements Provider {
|
|
|
1078
1185
|
currentStreamingToolName = undefined;
|
|
1079
1186
|
currentStreamingToolUseId = undefined;
|
|
1080
1187
|
accumulatedInputJson = "";
|
|
1188
|
+
// Flush residual text buffer unless it's exactly a sentinel.
|
|
1189
|
+
if (textBuffer.length > 0 && !isCompleteSentinel(textBuffer)) {
|
|
1190
|
+
onEvent?.({ type: "text_delta", text: textBuffer });
|
|
1191
|
+
}
|
|
1192
|
+
textBuffer = "";
|
|
1081
1193
|
}
|
|
1082
1194
|
});
|
|
1083
1195
|
|
|
@@ -1143,10 +1255,18 @@ export class AnthropicProvider implements Provider {
|
|
|
1143
1255
|
} catch (error) {
|
|
1144
1256
|
// Propagate a tagged AbortReason (set by the daemon at controller.abort())
|
|
1145
1257
|
// so wrapped errors can be classified as user cancellation downstream.
|
|
1258
|
+
const callerAborted = signal?.aborted === true;
|
|
1146
1259
|
const abortReason =
|
|
1147
|
-
|
|
1148
|
-
? signal
|
|
1260
|
+
callerAborted && isAbortReason(signal!.reason)
|
|
1261
|
+
? signal!.reason
|
|
1149
1262
|
: undefined;
|
|
1263
|
+
const elapsedMs = Date.now() - startedAt;
|
|
1264
|
+
// Inner-timeout means OUR 30-min stream deadline fired, not the caller
|
|
1265
|
+
// and not an external transport cutoff. We rewrite the message so the
|
|
1266
|
+
// retry layer can distinguish it from a transport abort (which should
|
|
1267
|
+
// retry) — a timed-out stream would almost certainly time out again.
|
|
1268
|
+
const innerTimeoutFired =
|
|
1269
|
+
innerTimeoutSignal?.aborted === true && !callerAborted;
|
|
1150
1270
|
if (error instanceof Anthropic.APIError) {
|
|
1151
1271
|
// Log detailed message structure for tool_use/tool_result ordering errors
|
|
1152
1272
|
if (
|
|
@@ -1162,30 +1282,79 @@ export class AnthropicProvider implements Provider {
|
|
|
1162
1282
|
"Anthropic 400: tool_use/tool_result pairing error — dumping message structure",
|
|
1163
1283
|
);
|
|
1164
1284
|
}
|
|
1285
|
+
const isAbortMessage =
|
|
1286
|
+
error.status === undefined &&
|
|
1287
|
+
/request was aborted/i.test(error.message);
|
|
1165
1288
|
if (abortReason) {
|
|
1166
1289
|
log.info(
|
|
1167
|
-
{ abortReason, message: error.message },
|
|
1290
|
+
{ abortReason, elapsedMs, message: error.message },
|
|
1168
1291
|
"Anthropic request aborted by daemon",
|
|
1169
1292
|
);
|
|
1293
|
+
} else if (isAbortMessage) {
|
|
1294
|
+
log.error(
|
|
1295
|
+
{
|
|
1296
|
+
elapsedMs,
|
|
1297
|
+
cause: error.cause,
|
|
1298
|
+
callerSignalAborted: callerAborted,
|
|
1299
|
+
innerTimeoutFired,
|
|
1300
|
+
message: error.message,
|
|
1301
|
+
},
|
|
1302
|
+
innerTimeoutFired
|
|
1303
|
+
? "Anthropic stream timed out (inner streamTimeoutMs fired)"
|
|
1304
|
+
: "Anthropic stream aborted by transport — no daemon or inner-timeout abort; likely bun fetch deadline, edge LB, or network idle cutoff",
|
|
1305
|
+
);
|
|
1170
1306
|
} else {
|
|
1171
1307
|
log.error(
|
|
1172
1308
|
{
|
|
1173
1309
|
status: error.status,
|
|
1310
|
+
elapsedMs,
|
|
1174
1311
|
message: error.message,
|
|
1175
1312
|
headers: Object.fromEntries(error.headers?.entries() ?? []),
|
|
1176
1313
|
},
|
|
1177
1314
|
`Anthropic API error (${error.status})`,
|
|
1178
1315
|
);
|
|
1179
1316
|
}
|
|
1317
|
+
const overflow = detectAnthropicContextOverflow(error);
|
|
1318
|
+
if (overflow) {
|
|
1319
|
+
throw new ContextOverflowError(
|
|
1320
|
+
`Anthropic API error (${error.status}): ${error.message}`,
|
|
1321
|
+
"anthropic",
|
|
1322
|
+
{
|
|
1323
|
+
actualTokens: overflow.actualTokens,
|
|
1324
|
+
maxTokens: overflow.maxTokens,
|
|
1325
|
+
statusCode: error.status,
|
|
1326
|
+
cause: error,
|
|
1327
|
+
},
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1180
1330
|
const retryAfterMs = extractRetryAfterMs(error.headers);
|
|
1181
1331
|
const errorOptions: {
|
|
1182
1332
|
retryAfterMs?: number;
|
|
1183
1333
|
abortReason?: unknown;
|
|
1334
|
+
cause?: unknown;
|
|
1184
1335
|
} = {};
|
|
1185
|
-
if (retryAfterMs !== undefined)
|
|
1336
|
+
if (retryAfterMs !== undefined)
|
|
1337
|
+
errorOptions.retryAfterMs = retryAfterMs;
|
|
1186
1338
|
if (abortReason) errorOptions.abortReason = abortReason;
|
|
1339
|
+
// Only preserve the original error as `cause` for transport aborts
|
|
1340
|
+
// without a daemon-tagged reason — it's the diagnostic signal the
|
|
1341
|
+
// retry layer and log reader rely on. Don't leak it through the
|
|
1342
|
+
// caller-aborted path, which already carries `abortReason`.
|
|
1343
|
+
if (!abortReason && isAbortMessage) errorOptions.cause = error;
|
|
1344
|
+
// Rewrite the message only for inner-timeout, so the retry layer
|
|
1345
|
+
// won't retry a request that already hit its 30-min deadline.
|
|
1346
|
+
const rewrittenMessage =
|
|
1347
|
+
isAbortMessage && innerTimeoutFired
|
|
1348
|
+
? `Anthropic stream timed out after ${Math.round(elapsedMs / 1000)}s (inner streamTimeoutMs)`
|
|
1349
|
+
: error.message;
|
|
1350
|
+
// Only include the `(status)` parenthetical when the SDK surfaced a
|
|
1351
|
+
// real HTTP status. Abort paths and mid-stream protocol errors have
|
|
1352
|
+
// `error.status === undefined`, and string-interpolating that produces
|
|
1353
|
+
// a confusing "Anthropic API error (undefined): …" message.
|
|
1354
|
+
const statusPart =
|
|
1355
|
+
error.status !== undefined ? ` (${error.status})` : "";
|
|
1187
1356
|
throw new ProviderError(
|
|
1188
|
-
`Anthropic API error
|
|
1357
|
+
`Anthropic API error${statusPart}: ${rewrittenMessage}`,
|
|
1189
1358
|
"anthropic",
|
|
1190
1359
|
error.status,
|
|
1191
1360
|
Object.keys(errorOptions).length > 0 ? errorOptions : undefined,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider wrapper that routes each `sendMessage` call to a different
|
|
3
|
+
* underlying provider transport when the per-call `options.config.callSite`
|
|
4
|
+
* resolves to a provider name that differs from the default.
|
|
5
|
+
*
|
|
6
|
+
* Without this wrapper the conversation-level provider transport is fixed at
|
|
7
|
+
* construction time, so a per-call-site `llm.callSites.<id>.provider`
|
|
8
|
+
* override only affects the request *metadata* the downstream client sees —
|
|
9
|
+
* the actual HTTP transport still belongs to `llm.default.provider`. That
|
|
10
|
+
* means routing decisions like "send `memoryRetrieval` calls to OpenAI even
|
|
11
|
+
* though the main agent runs on Anthropic" silently fail.
|
|
12
|
+
*
|
|
13
|
+
* `CallSiteRoutingProvider` consults `resolveCallSiteConfig` per call. When
|
|
14
|
+
* the resolved provider name differs from the default's name and the
|
|
15
|
+
* registry can produce a Provider for it, the call is delegated to that
|
|
16
|
+
* provider; otherwise it falls back to the default. Other Provider interface
|
|
17
|
+
* surface area (`name`, `tokenEstimationProvider`) is delegated to the
|
|
18
|
+
* default so wrappers further out (e.g. `RateLimitProvider`) still see a
|
|
19
|
+
* stable identity.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
23
|
+
import { getConfig } from "../config/loader.js";
|
|
24
|
+
import type {
|
|
25
|
+
Message,
|
|
26
|
+
Provider,
|
|
27
|
+
ProviderResponse,
|
|
28
|
+
SendMessageOptions,
|
|
29
|
+
ToolDefinition,
|
|
30
|
+
} from "./types.js";
|
|
31
|
+
|
|
32
|
+
export class CallSiteRoutingProvider implements Provider {
|
|
33
|
+
public readonly name: string;
|
|
34
|
+
public readonly tokenEstimationProvider?: string;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
private readonly defaultProvider: Provider,
|
|
38
|
+
private readonly getProviderByName: (name: string) => Provider | undefined,
|
|
39
|
+
) {
|
|
40
|
+
this.name = defaultProvider.name;
|
|
41
|
+
this.tokenEstimationProvider = defaultProvider.tokenEstimationProvider;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async sendMessage(
|
|
45
|
+
messages: Message[],
|
|
46
|
+
tools?: ToolDefinition[],
|
|
47
|
+
systemPrompt?: string,
|
|
48
|
+
options?: SendMessageOptions,
|
|
49
|
+
): Promise<ProviderResponse> {
|
|
50
|
+
const target = this.selectProvider(options);
|
|
51
|
+
return target.sendMessage(messages, tools, systemPrompt, options);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Pick the provider to route this call through. The default provider wins
|
|
56
|
+
* unless the per-call `callSite` resolves to a different provider name and
|
|
57
|
+
* the registry can produce a Provider for it.
|
|
58
|
+
*/
|
|
59
|
+
private selectProvider(options?: SendMessageOptions): Provider {
|
|
60
|
+
const callSite = options?.config?.callSite;
|
|
61
|
+
if (!callSite) return this.defaultProvider;
|
|
62
|
+
|
|
63
|
+
const resolved = resolveCallSiteConfig(callSite, getConfig().llm);
|
|
64
|
+
if (resolved.provider === this.defaultProvider.name) {
|
|
65
|
+
return this.defaultProvider;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const alternative = this.getProviderByName(resolved.provider);
|
|
69
|
+
return alternative ?? this.defaultProvider;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -14,6 +14,58 @@ import type {
|
|
|
14
14
|
SendMessageOptions,
|
|
15
15
|
ToolDefinition,
|
|
16
16
|
} from "../types.js";
|
|
17
|
+
import {
|
|
18
|
+
ContextOverflowError,
|
|
19
|
+
extractOverflowTokensFromMessage,
|
|
20
|
+
} from "../types.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Token/context-specific phrases that reliably indicate context-overflow
|
|
24
|
+
* regardless of status code. These never appear in quota/rate-limit error
|
|
25
|
+
* messages, so matching one of these is safe on any accepted status.
|
|
26
|
+
*/
|
|
27
|
+
const GEMINI_CONTEXT_OVERFLOW_TOKEN_PATTERNS =
|
|
28
|
+
/token.?count.*exceeds|exceeds.*maximum.*tokens|prompt.?is.?too.?long|too.?many.?(?:input.?)?tokens|input.?too.?long|context.?length.?exceeded/i;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Detect Gemini's context-overflow signals on an `ApiError`. Gemini surfaces
|
|
32
|
+
* this condition via its "RESOURCE_EXHAUSTED" category. The Gemini SDK's
|
|
33
|
+
* `ApiError` only exposes `status` and `message`, so we match on both.
|
|
34
|
+
*
|
|
35
|
+
* On 400 (INVALID_ARGUMENT, the Generative Language API path), the
|
|
36
|
+
* `resource.?exhausted` phrase alone is sufficient — only context-overflow
|
|
37
|
+
* is surfaced with that status.
|
|
38
|
+
*
|
|
39
|
+
* On 429 (RESOURCE_EXHAUSTED, the Vertex path), the same status is used for
|
|
40
|
+
* BOTH rate-limit quota exhaustion AND context-overflow. To discriminate,
|
|
41
|
+
* we require a token/context-specific phrase; the bare `resource.?exhausted`
|
|
42
|
+
* signal is too broad and would misclassify quota errors as overflow and
|
|
43
|
+
* bypass the retry path in `providers/retry.ts`.
|
|
44
|
+
*/
|
|
45
|
+
export function detectGeminiContextOverflow(
|
|
46
|
+
error: ApiError,
|
|
47
|
+
): { actualTokens?: number; maxTokens?: number } | null {
|
|
48
|
+
const status = error.status;
|
|
49
|
+
// 400 = INVALID_ARGUMENT (prompt too long), 413 occasional,
|
|
50
|
+
// 429 with RESOURCE_EXHAUSTED is the Vertex path.
|
|
51
|
+
if (status !== 400 && status !== 413 && status !== 429) return null;
|
|
52
|
+
const message = error.message ?? "";
|
|
53
|
+
|
|
54
|
+
// 429 has two meanings (quota vs context-overflow) — require a
|
|
55
|
+
// token/context-specific phrase to classify as overflow.
|
|
56
|
+
if (status === 429) {
|
|
57
|
+
if (!GEMINI_CONTEXT_OVERFLOW_TOKEN_PATTERNS.test(message)) return null;
|
|
58
|
+
return extractOverflowTokensFromMessage(message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 400/413: either a token/context-specific phrase or the broader
|
|
62
|
+
// `resource.?exhausted` signal is a reliable overflow indicator.
|
|
63
|
+
const matches =
|
|
64
|
+
/resource.?exhausted/i.test(message) ||
|
|
65
|
+
GEMINI_CONTEXT_OVERFLOW_TOKEN_PATTERNS.test(message);
|
|
66
|
+
if (!matches) return null;
|
|
67
|
+
return extractOverflowTokensFromMessage(message);
|
|
68
|
+
}
|
|
17
69
|
|
|
18
70
|
const log = getLogger("gemini-client");
|
|
19
71
|
|
|
@@ -238,6 +290,19 @@ export class GeminiProvider implements Provider {
|
|
|
238
290
|
? signal.reason
|
|
239
291
|
: undefined;
|
|
240
292
|
if (error instanceof ApiError) {
|
|
293
|
+
const overflow = detectGeminiContextOverflow(error);
|
|
294
|
+
if (overflow) {
|
|
295
|
+
throw new ContextOverflowError(
|
|
296
|
+
`Gemini API error (${error.status}): ${error.message}`,
|
|
297
|
+
"gemini",
|
|
298
|
+
{
|
|
299
|
+
actualTokens: overflow.actualTokens,
|
|
300
|
+
maxTokens: overflow.maxTokens,
|
|
301
|
+
statusCode: error.status,
|
|
302
|
+
cause: error,
|
|
303
|
+
},
|
|
304
|
+
);
|
|
305
|
+
}
|
|
241
306
|
throw new ProviderError(
|
|
242
307
|
`Gemini API error (${error.status}): ${error.message}`,
|
|
243
308
|
"gemini",
|
|
@@ -330,7 +395,6 @@ export class GeminiProvider implements Provider {
|
|
|
330
395
|
case "tool_use":
|
|
331
396
|
parts.push({
|
|
332
397
|
functionCall: {
|
|
333
|
-
id: block.id,
|
|
334
398
|
name: block.name,
|
|
335
399
|
args: block.input,
|
|
336
400
|
},
|
|
@@ -363,7 +427,6 @@ export class GeminiProvider implements Provider {
|
|
|
363
427
|
}
|
|
364
428
|
parts.push({
|
|
365
429
|
functionResponse: {
|
|
366
|
-
id: block.tool_use_id,
|
|
367
430
|
name: toolCallNames.get(block.tool_use_id) ?? block.tool_use_id,
|
|
368
431
|
response: { output: outputText },
|
|
369
432
|
},
|
|
@@ -28,7 +28,8 @@ export interface ManagedProviderMeta {
|
|
|
28
28
|
export const MANAGED_PROVIDER_META: Record<string, ManagedProviderMeta> = {
|
|
29
29
|
openai: {
|
|
30
30
|
name: "openai",
|
|
31
|
-
managed:
|
|
31
|
+
managed: true,
|
|
32
|
+
proxyPath: "/v1/runtime-proxy/openai",
|
|
32
33
|
},
|
|
33
34
|
anthropic: {
|
|
34
35
|
name: "anthropic",
|