@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2
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/bun.lock +0 -20
- package/docs/workspace-tools.md +33 -42
- package/eslint-rules/cli-no-daemon-internals.js +0 -6
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
- package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
- package/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
- package/openapi.yaml +0 -155
- package/package.json +1 -4
- package/scripts/test.sh +15 -36
- package/src/__tests__/actor-token-service.test.ts +14 -36
- package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
- package/src/__tests__/annotate-risk-options.test.ts +0 -2
- package/src/__tests__/approval-cascade.test.ts +0 -2
- package/src/__tests__/assistant-attachments.test.ts +0 -42
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -2
- package/src/__tests__/build-persisted-content.test.ts +0 -2
- package/src/__tests__/call-controller.test.ts +0 -19
- package/src/__tests__/channel-guardian.test.ts +58 -94
- package/src/__tests__/channel-reply-delivery.test.ts +0 -2
- package/src/__tests__/compaction-events.test.ts +0 -2
- package/src/__tests__/compaction.benchmark.test.ts +0 -2
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
- package/src/__tests__/config-loader-backfill.test.ts +10 -123
- package/src/__tests__/config-schema.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
- package/src/__tests__/contacts-relay-reads.test.ts +15 -13
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +0 -134
- package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
- package/src/__tests__/conversation-history-web-search.test.ts +0 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -2
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
- package/src/__tests__/conversation-process-callsite.test.ts +0 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
- package/src/__tests__/conversation-queue.test.ts +0 -91
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
- package/src/__tests__/conversation-slash-queue.test.ts +0 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
- package/src/__tests__/conversation-speed-override.test.ts +0 -2
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
- package/src/__tests__/conversation-title-service.test.ts +0 -2
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-migration-rollback.test.ts +171 -205
- package/src/__tests__/db-test-helpers.ts +4 -5
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
- package/src/__tests__/disk-pressure-guard.test.ts +0 -41
- package/src/__tests__/dm-persistence.test.ts +0 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
- package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
- package/src/__tests__/exploration-drift-hook.test.ts +2 -3
- package/src/__tests__/filing-service.test.ts +0 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
- package/src/__tests__/guardian-dispatch.test.ts +1 -95
- package/src/__tests__/guardian-outbound-http.test.ts +0 -13
- package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
- package/src/__tests__/heartbeat-service.test.ts +0 -2
- package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
- package/src/__tests__/host-app-control-routes.test.ts +30 -24
- package/src/__tests__/host-bash-routes.test.ts +41 -31
- package/src/__tests__/host-browser-routes.test.ts +32 -26
- package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
- package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
- package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
- package/src/__tests__/http-user-message-parity.test.ts +8 -290
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/invite-redemption-service.test.ts +0 -198
- package/src/__tests__/llm-context-normalization.test.ts +0 -105
- package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
- package/src/__tests__/llm-usage-store.test.ts +0 -25
- package/src/__tests__/mcp-health-check.test.ts +1 -2
- package/src/__tests__/media-stream-server-integration.test.ts +0 -127
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
- package/src/__tests__/messaging-send-tool.test.ts +0 -2
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +5 -146
- package/src/__tests__/native-web-search.test.ts +0 -2
- package/src/__tests__/non-member-access-request.test.ts +17 -189
- package/src/__tests__/notification-broadcaster.test.ts +0 -4
- package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
- package/src/__tests__/notification-deep-link.test.ts +0 -6
- package/src/__tests__/notification-guardian-path.test.ts +0 -19
- package/src/__tests__/openai-provider.test.ts +12 -22
- package/src/__tests__/openai-responses-provider.test.ts +2 -12
- package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
- package/src/__tests__/plugin-bootstrap.test.ts +73 -3
- package/src/__tests__/plugin-route-contribution.test.ts +17 -4
- package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
- package/src/__tests__/plugin-types.test.ts +2 -0
- package/src/__tests__/process-message-background-slack.test.ts +0 -2
- package/src/__tests__/process-message-display-content.test.ts +0 -2
- package/src/__tests__/provider-error-scenarios.test.ts +4 -5
- package/src/__tests__/provider-usage-tracking.test.ts +0 -39
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
- package/src/__tests__/registry.test.ts +1 -4
- package/src/__tests__/relay-server.test.ts +25 -694
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -14
- package/src/__tests__/send-endpoint-busy.test.ts +8 -30
- package/src/__tests__/skills.test.ts +0 -44
- package/src/__tests__/slack-inbound-verification.test.ts +2 -47
- package/src/__tests__/stt-hints.test.ts +13 -44
- package/src/__tests__/subagent-detail.test.ts +0 -27
- package/src/__tests__/subagent-disposal.test.ts +0 -65
- package/src/__tests__/subagent-notify-parent.test.ts +0 -2
- package/src/__tests__/subagent-role-registry.test.ts +2 -7
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
- package/src/__tests__/subagent-tools.test.ts +0 -2
- package/src/__tests__/suggestion-routes.test.ts +0 -2
- package/src/__tests__/title-generate-hook.test.ts +0 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
- package/src/__tests__/tool-executor.test.ts +11 -16
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
- package/src/__tests__/tool-start-timestamp.test.ts +0 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
- package/src/__tests__/twilio-routes.test.ts +0 -96
- package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +0 -33
- package/src/__tests__/web-search-backend-failure.test.ts +0 -2
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
- package/src/__tests__/workspace-tool-loader.test.ts +2 -195
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +0 -56
- package/src/api/index.ts +1 -19
- package/src/api/responses/llm-request-log-entry.ts +0 -29
- package/src/api/responses/subagent-detail.ts +0 -17
- package/src/api/surfaces.ts +3 -39
- package/src/approvals/guardian-request-resolvers.ts +11 -1
- package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +8 -10
- package/src/calls/inbound-trust-reader.ts +1 -17
- package/src/calls/media-stream-server.ts +0 -21
- package/src/calls/relay-server.ts +50 -167
- package/src/calls/relay-setup-router.ts +7 -37
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +12 -9
- package/src/calls/twilio-routes.ts +4 -14
- package/src/channels/types.ts +20 -10
- package/src/cli/commands/__tests__/cache.test.ts +1 -8
- package/src/cli/commands/cache.ts +181 -194
- package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
- package/src/cli/commands/db/status.ts +1 -37
- package/src/cli/commands/mcp.ts +218 -252
- package/src/cli/commands/memory/index.ts +0 -2
- package/src/cli/commands/plugins.ts +3 -75
- package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
- package/src/cli/lib/list-installed-plugins.ts +1 -179
- package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
- package/src/config/bundled-skills/subagent/SKILL.md +1 -1
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/feature-flag-registry.json +13 -5
- package/src/config/loader.ts +5 -38
- package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
- package/src/config/schemas/memory-lifecycle.ts +0 -12
- package/src/config/schemas/memory-v3.ts +0 -7
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/timeouts.ts +0 -8
- package/src/config/seed-inference-profiles.ts +11 -21
- package/src/config/skills.ts +5 -27
- package/src/config/sync-gated-profiles.ts +13 -12
- package/src/contacts/contacts-write.ts +0 -3
- package/src/daemon/assistant-attachments.ts +4 -27
- package/src/daemon/conversation-agent-loop.ts +0 -28
- package/src/daemon/conversation-process.ts +16 -35
- package/src/daemon/conversation-surfaces.ts +38 -111
- package/src/daemon/conversation-tool-setup.ts +16 -50
- package/src/daemon/conversation.ts +1 -13
- package/src/daemon/disk-pressure-guard.ts +2 -12
- package/src/daemon/event-loop-watchdog.ts +1 -28
- package/src/daemon/external-plugins-bootstrap.ts +34 -4
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
- package/src/daemon/handlers/config-a2a.ts +14 -6
- package/src/daemon/handlers/config-channels.ts +22 -78
- package/src/daemon/handlers/conversations.ts +0 -77
- package/src/daemon/lifecycle.ts +0 -4
- package/src/daemon/mcp-reload-service.ts +0 -10
- package/src/daemon/memory-v2-startup.test.ts +0 -72
- package/src/daemon/memory-v2-startup.ts +19 -87
- package/src/daemon/message-types/conversations.ts +0 -2
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +4 -0
- package/src/daemon/shutdown-handlers.ts +0 -20
- package/src/daemon/tool-setup-types.ts +0 -9
- package/src/daemon/workspace-tools-watcher.ts +328 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/client.ts +1 -15
- package/src/mcp/mcp-auth-orchestrator.ts +1 -6
- package/src/mcp/mcp-oauth-provider.ts +8 -19
- package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
- package/src/memory/conversation-crud.ts +0 -38
- package/src/memory/db-connection.ts +3 -22
- package/src/memory/db-init.ts +502 -36
- package/src/memory/db-singleton.ts +4 -6
- package/src/memory/jobs-worker.ts +0 -58
- package/src/memory/llm-request-log-store.ts +1 -26
- package/src/memory/llm-usage-store.ts +20 -48
- package/src/memory/memory-retrospective-job.ts +8 -9
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/registry.ts +573 -0
- package/src/memory/migrations/run-migrations.ts +6 -90
- package/src/memory/migrations/validate-migration-state.ts +66 -101
- package/src/memory/schema/conversations.ts +0 -9
- package/src/memory/schema/infrastructure.ts +0 -20
- package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
- package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
- package/src/memory/v2/cli-command-store.ts +38 -75
- package/src/memory/v2/prompts/consolidation.ts +82 -13
- package/src/memory/v2/prompts/router.ts +93 -21
- package/src/memory/v2/skill-store.ts +31 -68
- package/src/notifications/__tests__/broadcaster.test.ts +8 -16
- package/src/notifications/__tests__/decision-engine.test.ts +9 -78
- package/src/notifications/broadcaster.ts +1 -8
- package/src/notifications/decision-engine.ts +7 -15
- package/src/notifications/destination-resolver.ts +24 -68
- package/src/notifications/emit-signal.ts +14 -39
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +4 -7
- package/src/plugin-api/index.ts +6 -6
- package/src/plugin-api/types.ts +5 -3
- package/src/plugin-api/vision-support.test.ts +4 -28
- package/src/plugin-api/vision-support.ts +31 -66
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
- package/src/plugins/defaults/advisor/consult.ts +6 -110
- package/src/plugins/defaults/advisor/steering.ts +2 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
- package/src/plugins/mtime-cache.ts +291 -76
- package/src/plugins/pipeline.ts +13 -111
- package/src/plugins/types.ts +2 -0
- package/src/providers/anthropic/client.ts +0 -5
- package/src/providers/call-site-routing.ts +0 -4
- package/src/providers/model-catalog.ts +0 -16
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/chat-completions-provider.ts +83 -37
- package/src/providers/openai/responses-provider.ts +46 -50
- package/src/providers/openrouter/client.ts +0 -5
- package/src/providers/provider-send-message.ts +0 -4
- package/src/providers/ratelimit.ts +0 -4
- package/src/providers/retry.ts +0 -4
- package/src/providers/types.ts +0 -9
- package/src/providers/usage-tracking.ts +0 -4
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
- package/src/runtime/access-request-helper.ts +39 -19
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +2 -9
- package/src/runtime/auth/require-bound-guardian.ts +11 -21
- package/src/runtime/channel-verification-service.ts +31 -56
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +7 -66
- package/src/runtime/invite-redemption-service.ts +187 -198
- package/src/runtime/local-actor-identity.ts +11 -76
- package/src/runtime/pending-interactions.ts +1 -11
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +32 -8
- package/src/runtime/routes/conversation-cli-routes.ts +5 -4
- package/src/runtime/routes/conversation-list-routes.ts +7 -4
- package/src/runtime/routes/conversation-query-routes.ts +0 -72
- package/src/runtime/routes/conversation-routes.ts +85 -84
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -3
- package/src/runtime/routes/guardian-action-routes.ts +5 -4
- package/src/runtime/routes/host-app-control-routes.ts +4 -5
- package/src/runtime/routes/host-bash-routes.ts +4 -5
- package/src/runtime/routes/host-browser-routes.ts +11 -9
- package/src/runtime/routes/host-cu-routes.ts +4 -5
- package/src/runtime/routes/host-file-routes.ts +4 -5
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +2 -3
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
- package/src/runtime/routes/index.ts +0 -2
- package/src/runtime/routes/llm-context-normalization.ts +0 -83
- package/src/runtime/routes/mcp-auth-routes.ts +19 -171
- package/src/runtime/routes/migration-rollback-routes.ts +3 -4
- package/src/runtime/routes/migration-routes.ts +1 -4
- package/src/runtime/routes/subagents-routes.ts +0 -5
- package/src/runtime/routes/surface-action-routes.ts +56 -42
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
- package/src/runtime/services/conversation-serializer.ts +9 -7
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +9 -85
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +0 -16
- package/src/subagent/manager.ts +0 -9
- package/src/subagent/types.ts +3 -3
- package/src/telemetry/types.ts +1 -34
- package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
- package/src/telemetry/usage-telemetry-reporter.ts +3 -87
- package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
- package/src/tools/ask-question/ask-question-tool.ts +0 -13
- package/src/tools/executor.ts +4 -4
- package/src/tools/registry.ts +0 -18
- package/src/tools/shared/filesystem/path-policy.ts +5 -12
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +2 -9
- package/src/tools/tool-manifest.ts +0 -3
- package/src/tools/types.ts +2 -17
- package/src/tools/workspace-tools/loader.ts +244 -348
- package/src/util/errors.ts +1 -26
- package/src/util/platform.ts +0 -5
- package/src/workflows/library.test.ts +0 -140
- package/src/workflows/library.ts +28 -82
- package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
- package/src/workspace/migrations/registry.ts +0 -2
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
- package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
- package/src/__tests__/code-search-tool.test.ts +0 -585
- package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
- package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
- package/src/__tests__/plugin-pipeline.test.ts +0 -96
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
- package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
- package/src/agent/loop-exclusive-tool.test.ts +0 -150
- package/src/api/constants/sse-replay.ts +0 -41
- package/src/api/events/conversation-notice.ts +0 -26
- package/src/approvals/guardian-channel-delivery.ts +0 -30
- package/src/approvals/guardian-expiry-notifier.ts +0 -148
- package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
- package/src/cli/commands/memory/worker.ts +0 -175
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
- package/src/config/prune-seeded-callsite-defaults.ts +0 -110
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
- package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
- package/src/contacts/guardian-delivery-reader.ts +0 -223
- package/src/contacts/member-write-relay.ts +0 -189
- package/src/daemon/conversation-notices.ts +0 -60
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
- package/src/hooks/hook-loader.ts +0 -341
- package/src/mcp/mcp-header-store.ts +0 -134
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
- package/src/memory/__tests__/prompt-override.test.ts +0 -192
- package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
- package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
- package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
- package/src/memory/prompt-override.ts +0 -129
- package/src/memory/steps.ts +0 -573
- package/src/memory/watchdog-events-store.ts +0 -87
- package/src/memory/worker-control.ts +0 -118
- package/src/memory/worker-process.ts +0 -72
- package/src/notifications/__tests__/connected-channels.test.ts +0 -114
- package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
- package/src/onboarding/checkin-event.test.ts +0 -222
- package/src/onboarding/checkin-event.ts +0 -321
- package/src/onboarding/schedule-checkin.ts +0 -190
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
- package/src/plugins/defaults/advisor/context-pack.ts +0 -288
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
- package/src/plugins/surface-import.ts +0 -121
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
- package/src/providers/openai/api-error-normalization.ts +0 -270
- package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
- package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
- package/src/runtime/anchored-guardian.test.ts +0 -156
- package/src/runtime/anchored-guardian.ts +0 -135
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
- package/src/runtime/local-principal-trust.ts +0 -52
- package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
- package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
- package/src/tools/filesystem/search.ts +0 -543
- package/src/util/telemetry-db-path.ts +0 -24
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
|
@@ -786,11 +786,6 @@ export class AnthropicProvider implements Provider {
|
|
|
786
786
|
this.useNativeWebSearch = options.useNativeWebSearch ?? false;
|
|
787
787
|
}
|
|
788
788
|
|
|
789
|
-
/** See {@link Provider.supportsNativeWebSearch}. */
|
|
790
|
-
get supportsNativeWebSearch(): boolean {
|
|
791
|
-
return this.useNativeWebSearch;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
789
|
async sendMessage(
|
|
795
790
|
messages: Message[],
|
|
796
791
|
options?: SendMessageOptions,
|
|
@@ -43,9 +43,6 @@ import type {
|
|
|
43
43
|
|
|
44
44
|
export class CallSiteRoutingProvider implements Provider {
|
|
45
45
|
public readonly tokenEstimationProvider?: string;
|
|
46
|
-
// Forward native web-search capability so it survives the wrapper chain
|
|
47
|
-
// (callers like the advisor consult gate on it). Fixed at construction.
|
|
48
|
-
public readonly supportsNativeWebSearch?: boolean;
|
|
49
46
|
|
|
50
47
|
// Per-call async context that tracks which provider is currently executing.
|
|
51
48
|
// Using AsyncLocalStorage instead of a plain instance field means concurrent
|
|
@@ -97,7 +94,6 @@ export class CallSiteRoutingProvider implements Provider {
|
|
|
97
94
|
) => Promise<Provider | null>,
|
|
98
95
|
) {
|
|
99
96
|
this.tokenEstimationProvider = defaultProvider.tokenEstimationProvider;
|
|
100
|
-
this.supportsNativeWebSearch = defaultProvider.supportsNativeWebSearch;
|
|
101
97
|
if (defaultProvider.countInputTokens) {
|
|
102
98
|
this.countInputTokens =
|
|
103
99
|
defaultProvider.countInputTokens.bind(defaultProvider);
|
|
@@ -760,22 +760,6 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
|
|
|
760
760
|
maxEffort: "max",
|
|
761
761
|
pricing: { inputPer1mTokens: 1.74, outputPer1mTokens: 3.48 },
|
|
762
762
|
},
|
|
763
|
-
{
|
|
764
|
-
id: "accounts/fireworks/models/deepseek-v4-flash",
|
|
765
|
-
displayName: "DeepSeek V4 Flash",
|
|
766
|
-
contextWindowTokens: 1040000,
|
|
767
|
-
maxOutputTokens: 131072,
|
|
768
|
-
supportsThinking: true,
|
|
769
|
-
supportsCaching: true,
|
|
770
|
-
supportsVision: false,
|
|
771
|
-
supportsToolUse: true,
|
|
772
|
-
maxEffort: "max",
|
|
773
|
-
pricing: {
|
|
774
|
-
inputPer1mTokens: 0.14,
|
|
775
|
-
outputPer1mTokens: 0.28,
|
|
776
|
-
cacheReadPer1mTokens: 0.03,
|
|
777
|
-
},
|
|
778
|
-
},
|
|
779
763
|
],
|
|
780
764
|
defaultModel: "accounts/fireworks/models/kimi-k2p5",
|
|
781
765
|
apiKeyUrl: "https://fireworks.ai/account/api-keys",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import OpenAI from "openai";
|
|
4
|
+
|
|
5
|
+
import { extractApiErrorDetail } from "../chat-completions-provider.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Construct a real `OpenAI.APIError` so production code paths that use
|
|
9
|
+
* `instanceof OpenAI.APIError` and SDK-defined getters keep matching.
|
|
10
|
+
*/
|
|
11
|
+
function buildApiError(
|
|
12
|
+
status: number,
|
|
13
|
+
body: unknown,
|
|
14
|
+
headers?: Headers,
|
|
15
|
+
): InstanceType<typeof OpenAI.APIError> {
|
|
16
|
+
return new OpenAI.APIError(
|
|
17
|
+
status,
|
|
18
|
+
body as Record<string, unknown>,
|
|
19
|
+
undefined,
|
|
20
|
+
headers ?? new Headers(),
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe("extractApiErrorDetail", () => {
|
|
25
|
+
test("serializes a structured body so logs show the upstream error", () => {
|
|
26
|
+
// This is the canonical OpenRouter shape that motivated the helper:
|
|
27
|
+
// the SDK's `error.message` collapses to "400 Provider returned error"
|
|
28
|
+
// and the real detail lives nested under `error.metadata.raw`.
|
|
29
|
+
const err = buildApiError(400, {
|
|
30
|
+
error: {
|
|
31
|
+
code: 400,
|
|
32
|
+
message: "Provider returned error",
|
|
33
|
+
metadata: {
|
|
34
|
+
raw: "messages.4: tool_use_id must reference a prior tool_use block",
|
|
35
|
+
provider_name: "Anthropic",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
const { detail, requestId } = extractApiErrorDetail(err);
|
|
40
|
+
expect(detail).toContain("Provider returned error");
|
|
41
|
+
expect(detail).toContain("tool_use_id must reference a prior tool_use");
|
|
42
|
+
expect(detail).toContain("Anthropic");
|
|
43
|
+
expect(requestId).toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("surfaces the upstream request id when present in headers", () => {
|
|
47
|
+
const headers = new Headers({ "x-request-id": "req_abc123" });
|
|
48
|
+
const err = buildApiError(
|
|
49
|
+
400,
|
|
50
|
+
{ error: { message: "Provider returned error" } },
|
|
51
|
+
headers,
|
|
52
|
+
);
|
|
53
|
+
const { requestId } = extractApiErrorDetail(err);
|
|
54
|
+
expect(requestId).toBe("req_abc123");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("falls back to x-openrouter-request-id when x-request-id is absent", () => {
|
|
58
|
+
const headers = new Headers({
|
|
59
|
+
"x-openrouter-request-id": "gen-or-xyz",
|
|
60
|
+
});
|
|
61
|
+
const err = buildApiError(
|
|
62
|
+
400,
|
|
63
|
+
{ error: { message: "Provider returned error" } },
|
|
64
|
+
headers,
|
|
65
|
+
);
|
|
66
|
+
const { requestId } = extractApiErrorDetail(err);
|
|
67
|
+
expect(requestId).toBe("gen-or-xyz");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("returns empty detail when the body is missing", () => {
|
|
71
|
+
// The SDK constructs an APIError even when the upstream response had
|
|
72
|
+
// no JSON body (e.g. network-layer 5xx). The helper must degrade
|
|
73
|
+
// gracefully rather than emit `undefined` or `null` strings.
|
|
74
|
+
const err = buildApiError(500, undefined);
|
|
75
|
+
const { detail, requestId } = extractApiErrorDetail(err);
|
|
76
|
+
expect(detail).toBe("");
|
|
77
|
+
expect(requestId).toBeUndefined();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("returns empty detail when the body serializes to an empty object", () => {
|
|
81
|
+
// `{}` carries zero signal and just adds noise to log lines.
|
|
82
|
+
const err = buildApiError(429, {});
|
|
83
|
+
const { detail } = extractApiErrorDetail(err);
|
|
84
|
+
expect(detail).toBe("");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("truncates very long bodies with an ellipsis", () => {
|
|
88
|
+
const huge = "X".repeat(5000);
|
|
89
|
+
const err = buildApiError(400, { error: { message: huge } });
|
|
90
|
+
const { detail } = extractApiErrorDetail(err);
|
|
91
|
+
// Cap is 2000 chars; the helper appends a single-char ellipsis when truncating.
|
|
92
|
+
expect(detail.length).toBeLessThanOrEqual(2001);
|
|
93
|
+
expect(detail.endsWith("…")).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("preserves string bodies verbatim (no double-encoding)", () => {
|
|
97
|
+
// Some providers return a non-JSON body (HTML error page, plain text).
|
|
98
|
+
// The SDK stores it on `error.error` as a string in that case.
|
|
99
|
+
const err = buildApiError(502, "upstream timeout");
|
|
100
|
+
const { detail } = extractApiErrorDetail(err);
|
|
101
|
+
expect(detail).toBe("upstream timeout");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("returns empty detail when JSON.stringify throws (cyclic body)", () => {
|
|
105
|
+
// Pathological body — should not propagate the TypeError to callers.
|
|
106
|
+
// OpenAI's `APIError` constructor itself JSON.stringifies the body to
|
|
107
|
+
// build its own `.message`, so we can't get to this branch via the SDK
|
|
108
|
+
// constructor; build a structural stand-in instead.
|
|
109
|
+
const cyclic: Record<string, unknown> = {};
|
|
110
|
+
cyclic.self = cyclic;
|
|
111
|
+
const stub = {
|
|
112
|
+
status: 400,
|
|
113
|
+
message: "synthetic",
|
|
114
|
+
headers: new Headers(),
|
|
115
|
+
error: cyclic,
|
|
116
|
+
} as unknown as InstanceType<typeof OpenAI.APIError>;
|
|
117
|
+
const { detail } = extractApiErrorDetail(stub);
|
|
118
|
+
expect(detail).toBe("");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -22,11 +22,6 @@ import {
|
|
|
22
22
|
isUnparseableToolArgs,
|
|
23
23
|
wrapUnparseableToolArgs,
|
|
24
24
|
} from "../unparseable-tool-args.js";
|
|
25
|
-
import {
|
|
26
|
-
captureRawErrorBodyFetch,
|
|
27
|
-
formatNormalizedOpenAIAPIError,
|
|
28
|
-
normalizeOpenAIAPIError,
|
|
29
|
-
} from "./api-error-normalization.js";
|
|
30
25
|
import {
|
|
31
26
|
coerceObjectParamsToJsonString,
|
|
32
27
|
decodeCoercedObjectArgs,
|
|
@@ -48,7 +43,6 @@ import {
|
|
|
48
43
|
*/
|
|
49
44
|
export function detectOpenAICompatibleContextOverflow(
|
|
50
45
|
error: InstanceType<typeof OpenAI.APIError>,
|
|
51
|
-
extraMessage?: string,
|
|
52
46
|
): { actualTokens?: number; maxTokens?: number } | null {
|
|
53
47
|
// OpenAI-compatible providers use 400 (most) or 413 (rarer payload-too-large).
|
|
54
48
|
const status = error.status;
|
|
@@ -59,9 +53,7 @@ export function detectOpenAICompatibleContextOverflow(
|
|
|
59
53
|
/context_length_exceeded|context_window_exceeded|input_too_long|prompt_too_long/i.test(
|
|
60
54
|
code,
|
|
61
55
|
);
|
|
62
|
-
|
|
63
|
-
// generic ("400 Provider returned error") while the real signal is in the body.
|
|
64
|
-
const message = `${error.message ?? ""} ${extraMessage ?? ""}`;
|
|
56
|
+
const message = error.message ?? "";
|
|
65
57
|
const messageMatches =
|
|
66
58
|
/context.?length.?exceeded|context.?window.?exceeded|prompt.?is.?too.?long|prompt_too_long|input.?too.?long|too.?many.?(?:input.?)?tokens|maximum.?context/i.test(
|
|
67
59
|
message,
|
|
@@ -71,6 +63,53 @@ export function detectOpenAICompatibleContextOverflow(
|
|
|
71
63
|
return extractOverflowTokensFromMessage(message);
|
|
72
64
|
}
|
|
73
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Build the human-readable error string surfaced from an
|
|
68
|
+
* `OpenAI.APIError`. The SDK's `error.message` is typically a one-line
|
|
69
|
+
* summary like `"400 Provider returned error"` — useless when the
|
|
70
|
+
* upstream is OpenRouter (which wraps the real downstream error on
|
|
71
|
+
* `error.error.metadata.raw`) or any provider that returns nested
|
|
72
|
+
* structured details.
|
|
73
|
+
*
|
|
74
|
+
* Returns `{ detail, requestId }` where `detail` includes the JSON body
|
|
75
|
+
* (truncated) and `requestId` is the upstream correlation header when
|
|
76
|
+
* present. Callers fold these into the thrown `ProviderError` so log
|
|
77
|
+
* lines actually identify the failure without re-running the request.
|
|
78
|
+
*
|
|
79
|
+
* Exported for tests.
|
|
80
|
+
*/
|
|
81
|
+
export function extractApiErrorDetail(
|
|
82
|
+
error: InstanceType<typeof OpenAI.APIError>,
|
|
83
|
+
): { detail: string; requestId: string | undefined } {
|
|
84
|
+
const body = (error as { error?: unknown }).error;
|
|
85
|
+
let detail = "";
|
|
86
|
+
if (body !== undefined && body !== null) {
|
|
87
|
+
try {
|
|
88
|
+
const serialized = typeof body === "string" ? body : JSON.stringify(body);
|
|
89
|
+
if (serialized && serialized !== "{}") {
|
|
90
|
+
detail =
|
|
91
|
+
serialized.length > MAX_API_ERROR_DETAIL_CHARS
|
|
92
|
+
? `${serialized.slice(0, MAX_API_ERROR_DETAIL_CHARS)}…`
|
|
93
|
+
: serialized;
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
// Body had a cycle or threw on toJSON — fall through with empty detail.
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const requestId = readHeader(error.headers, [
|
|
100
|
+
"x-request-id",
|
|
101
|
+
"x-openrouter-request-id",
|
|
102
|
+
"openai-request-id",
|
|
103
|
+
"x-amzn-requestid",
|
|
104
|
+
]);
|
|
105
|
+
return { detail, requestId };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Cap on the inline-rendered body to keep log lines readable while still
|
|
109
|
+
* surfacing the meaningful upstream payload. Tuned to comfortably hold
|
|
110
|
+
* OpenRouter's `error.metadata.raw` strings, which are typically <1KB. */
|
|
111
|
+
const MAX_API_ERROR_DETAIL_CHARS = 2000;
|
|
112
|
+
|
|
74
113
|
const VISION_NOT_SUPPORTED_PATTERNS = [
|
|
75
114
|
/no endpoints found that support image input/i,
|
|
76
115
|
/does not support image/i,
|
|
@@ -82,9 +121,8 @@ const VISION_NOT_SUPPORTED_PATTERNS = [
|
|
|
82
121
|
|
|
83
122
|
export function detectVisionNotSupported(
|
|
84
123
|
error: InstanceType<typeof OpenAI.APIError>,
|
|
85
|
-
extraMessage?: string,
|
|
86
124
|
): boolean {
|
|
87
|
-
const haystack = `${error.message} ${
|
|
125
|
+
const haystack = `${error.message} ${JSON.stringify((error as { error?: unknown }).error ?? "")}`;
|
|
88
126
|
return VISION_NOT_SUPPORTED_PATTERNS.some((re) => re.test(haystack));
|
|
89
127
|
}
|
|
90
128
|
|
|
@@ -108,6 +146,34 @@ export function detectVisionNotSupported(
|
|
|
108
146
|
*/
|
|
109
147
|
export const EMPTY_ASSISTANT_TURN_PLACEHOLDER = PLACEHOLDER_EMPTY_TURN.slice(1);
|
|
110
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Read the first matching header from an SDK error's headers object,
|
|
151
|
+
* tolerating both Map-like (`Headers.get()`) and plain-object shapes.
|
|
152
|
+
* Mirrors the shape-tolerance already in `extractRetryAfterMs`.
|
|
153
|
+
*/
|
|
154
|
+
function readHeader(
|
|
155
|
+
headers: unknown,
|
|
156
|
+
names: readonly string[],
|
|
157
|
+
): string | undefined {
|
|
158
|
+
if (!headers) return undefined;
|
|
159
|
+
const getter =
|
|
160
|
+
typeof (headers as { get?: unknown }).get === "function"
|
|
161
|
+
? (headers as { get(name: string): string | null }).get.bind(headers)
|
|
162
|
+
: undefined;
|
|
163
|
+
for (const name of names) {
|
|
164
|
+
let value: string | null | undefined;
|
|
165
|
+
if (getter) {
|
|
166
|
+
value = getter(name);
|
|
167
|
+
} else if (typeof headers === "object") {
|
|
168
|
+
const record = headers as Record<string, unknown>;
|
|
169
|
+
const raw = record[name] ?? record[name.toLowerCase()];
|
|
170
|
+
value = typeof raw === "string" ? raw : undefined;
|
|
171
|
+
}
|
|
172
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
173
|
+
}
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
111
177
|
export interface OpenAIChatCompletionsProviderOptions {
|
|
112
178
|
baseURL?: string;
|
|
113
179
|
providerName?: string;
|
|
@@ -276,8 +342,6 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
276
342
|
apiKey,
|
|
277
343
|
baseURL: options.baseURL,
|
|
278
344
|
timeout: sdkTimeoutMs,
|
|
279
|
-
// Capture the raw non-2xx body before the SDK parses (and drops) it.
|
|
280
|
-
fetch: captureRawErrorBodyFetch,
|
|
281
345
|
});
|
|
282
346
|
this.model = model;
|
|
283
347
|
this.extraCreateParams = options.extraCreateParams ?? {};
|
|
@@ -699,16 +763,11 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
699
763
|
? signal.reason
|
|
700
764
|
: undefined;
|
|
701
765
|
if (error instanceof OpenAI.APIError) {
|
|
702
|
-
const
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
);
|
|
708
|
-
const overflow = detectOpenAICompatibleContextOverflow(
|
|
709
|
-
error,
|
|
710
|
-
normalized.message,
|
|
711
|
-
);
|
|
766
|
+
const { detail, requestId } = extractApiErrorDetail(error);
|
|
767
|
+
const detailSuffix = detail ? ` ${detail}` : "";
|
|
768
|
+
const requestIdSuffix = requestId ? ` [request_id=${requestId}]` : "";
|
|
769
|
+
const formattedMessage = `${this.providerLabel} API error (${error.status}): ${error.message}${detailSuffix}${requestIdSuffix}`;
|
|
770
|
+
const overflow = detectOpenAICompatibleContextOverflow(error);
|
|
712
771
|
if (overflow) {
|
|
713
772
|
throw new ContextOverflowError(formattedMessage, this.name, {
|
|
714
773
|
actualTokens: overflow.actualTokens,
|
|
@@ -717,7 +776,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
717
776
|
cause: error,
|
|
718
777
|
});
|
|
719
778
|
}
|
|
720
|
-
if (detectVisionNotSupported(error
|
|
779
|
+
if (detectVisionNotSupported(error)) {
|
|
721
780
|
const model = modelOverride ?? this.model;
|
|
722
781
|
throw new ProviderError(
|
|
723
782
|
`This model (${model}) doesn't support image input. Remove the image or switch to a vision-capable model.`,
|
|
@@ -730,23 +789,10 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
730
789
|
const errorOptions: {
|
|
731
790
|
retryAfterMs?: number;
|
|
732
791
|
abortReason?: unknown;
|
|
733
|
-
apiErrorCode?: string;
|
|
734
|
-
apiErrorType?: string;
|
|
735
|
-
apiErrorParam?: string;
|
|
736
|
-
requestId?: string;
|
|
737
|
-
rawBody?: string;
|
|
738
792
|
} = {};
|
|
739
793
|
if (retryAfterMs !== undefined)
|
|
740
794
|
errorOptions.retryAfterMs = retryAfterMs;
|
|
741
795
|
if (abortReason) errorOptions.abortReason = abortReason;
|
|
742
|
-
if (normalized.apiErrorCode)
|
|
743
|
-
errorOptions.apiErrorCode = normalized.apiErrorCode;
|
|
744
|
-
if (normalized.apiErrorType)
|
|
745
|
-
errorOptions.apiErrorType = normalized.apiErrorType;
|
|
746
|
-
if (normalized.apiErrorParam)
|
|
747
|
-
errorOptions.apiErrorParam = normalized.apiErrorParam;
|
|
748
|
-
if (normalized.requestId) errorOptions.requestId = normalized.requestId;
|
|
749
|
-
if (normalized.rawBody) errorOptions.rawBody = normalized.rawBody;
|
|
750
796
|
throw new ProviderError(
|
|
751
797
|
formattedMessage,
|
|
752
798
|
this.name,
|
|
@@ -16,11 +16,6 @@ import type {
|
|
|
16
16
|
} from "../types.js";
|
|
17
17
|
import { ContextOverflowError } from "../types.js";
|
|
18
18
|
import { wrapUnparseableToolArgs } from "../unparseable-tool-args.js";
|
|
19
|
-
import {
|
|
20
|
-
captureRawErrorBodyFetch,
|
|
21
|
-
formatNormalizedOpenAIAPIError,
|
|
22
|
-
normalizeOpenAIAPIError,
|
|
23
|
-
} from "./api-error-normalization.js";
|
|
24
19
|
import { detectOpenAICompatibleContextOverflow } from "./chat-completions-provider.js";
|
|
25
20
|
|
|
26
21
|
const log = getLogger("openai-responses");
|
|
@@ -153,6 +148,7 @@ export class OpenAIResponsesProvider implements Provider {
|
|
|
153
148
|
private streamTimeoutMs: number;
|
|
154
149
|
private useNativeWebSearch: boolean;
|
|
155
150
|
private codexSubscription: boolean;
|
|
151
|
+
private lastCodexErrorBody: string | undefined;
|
|
156
152
|
|
|
157
153
|
constructor(
|
|
158
154
|
apiKey: string,
|
|
@@ -172,18 +168,32 @@ export class OpenAIResponsesProvider implements Provider {
|
|
|
172
168
|
? "https://chatgpt.com/backend-api/codex"
|
|
173
169
|
: options.baseURL,
|
|
174
170
|
timeout: sdkTimeoutMs,
|
|
175
|
-
|
|
176
|
-
|
|
171
|
+
...(this.codexSubscription
|
|
172
|
+
? {
|
|
173
|
+
fetch: async (url: RequestInfo | URL, init?: RequestInit) => {
|
|
174
|
+
const res = await globalThis.fetch(url, init);
|
|
175
|
+
if (!res.ok) {
|
|
176
|
+
const body = await res.text();
|
|
177
|
+
this.lastCodexErrorBody = body;
|
|
178
|
+
log.warn(
|
|
179
|
+
{ status: res.status, body, url: String(url) },
|
|
180
|
+
"Codex endpoint raw error response",
|
|
181
|
+
);
|
|
182
|
+
return new Response(body, {
|
|
183
|
+
status: res.status,
|
|
184
|
+
statusText: res.statusText,
|
|
185
|
+
headers: res.headers,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return res;
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
: {}),
|
|
177
192
|
});
|
|
178
193
|
this.model = model;
|
|
179
194
|
this.useNativeWebSearch = options.useNativeWebSearch ?? false;
|
|
180
195
|
}
|
|
181
196
|
|
|
182
|
-
/** See {@link Provider.supportsNativeWebSearch}. */
|
|
183
|
-
get supportsNativeWebSearch(): boolean {
|
|
184
|
-
return this.useNativeWebSearch;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
197
|
async sendMessage(
|
|
188
198
|
messages: Message[],
|
|
189
199
|
options?: SendMessageOptions,
|
|
@@ -500,57 +510,43 @@ export class OpenAIResponsesProvider implements Provider {
|
|
|
500
510
|
? signal.reason
|
|
501
511
|
: undefined;
|
|
502
512
|
if (error instanceof OpenAI.APIError) {
|
|
503
|
-
const
|
|
504
|
-
if (
|
|
505
|
-
|
|
513
|
+
const overflow = detectOpenAICompatibleContextOverflow(error);
|
|
514
|
+
if (overflow) {
|
|
515
|
+
throw new ContextOverflowError(
|
|
516
|
+
`${this.providerLabel} API error (${error.status}): ${error.message}`,
|
|
517
|
+
this.name,
|
|
506
518
|
{
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
519
|
+
actualTokens: overflow.actualTokens,
|
|
520
|
+
maxTokens: overflow.maxTokens,
|
|
521
|
+
statusCode: error.status,
|
|
522
|
+
cause: error,
|
|
510
523
|
},
|
|
511
|
-
"Codex endpoint raw error response",
|
|
512
524
|
);
|
|
513
525
|
}
|
|
514
|
-
const formattedMessage = formatNormalizedOpenAIAPIError(
|
|
515
|
-
this.providerLabel,
|
|
516
|
-
error.status,
|
|
517
|
-
normalized,
|
|
518
|
-
);
|
|
519
|
-
const overflow = detectOpenAICompatibleContextOverflow(
|
|
520
|
-
error,
|
|
521
|
-
normalized.message,
|
|
522
|
-
);
|
|
523
|
-
if (overflow) {
|
|
524
|
-
throw new ContextOverflowError(formattedMessage, this.name, {
|
|
525
|
-
actualTokens: overflow.actualTokens,
|
|
526
|
-
maxTokens: overflow.maxTokens,
|
|
527
|
-
statusCode: error.status,
|
|
528
|
-
cause: error,
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
526
|
const retryAfterMs = extractRetryAfterMs(error.headers);
|
|
532
527
|
const errorOptions: {
|
|
533
528
|
retryAfterMs?: number;
|
|
534
529
|
abortReason?: unknown;
|
|
535
|
-
apiErrorCode?: string;
|
|
536
|
-
apiErrorType?: string;
|
|
537
|
-
apiErrorParam?: string;
|
|
538
|
-
requestId?: string;
|
|
539
|
-
rawBody?: string;
|
|
540
530
|
} = {};
|
|
541
531
|
if (retryAfterMs !== undefined)
|
|
542
532
|
errorOptions.retryAfterMs = retryAfterMs;
|
|
543
533
|
if (abortReason) errorOptions.abortReason = abortReason;
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
534
|
+
let errorDetail = error.message;
|
|
535
|
+
if (this.lastCodexErrorBody) {
|
|
536
|
+
try {
|
|
537
|
+
const parsed = JSON.parse(this.lastCodexErrorBody);
|
|
538
|
+
if (parsed.detail) errorDetail = parsed.detail;
|
|
539
|
+
} catch {
|
|
540
|
+
errorDetail = this.lastCodexErrorBody.slice(0, 200);
|
|
541
|
+
}
|
|
542
|
+
this.lastCodexErrorBody = undefined;
|
|
543
|
+
}
|
|
544
|
+
const extras = [error.code, error.type, error.param]
|
|
545
|
+
.filter(Boolean)
|
|
546
|
+
.join(", ");
|
|
547
|
+
const extraSuffix = extras ? ` [${extras}]` : "";
|
|
552
548
|
throw new ProviderError(
|
|
553
|
-
|
|
549
|
+
`${this.providerLabel} API error (${error.status}): ${errorDetail}${extraSuffix}`,
|
|
554
550
|
this.name,
|
|
555
551
|
error.status,
|
|
556
552
|
Object.keys(errorOptions).length > 0 ? errorOptions : undefined,
|
|
@@ -140,11 +140,6 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
|
|
|
140
140
|
return isAnthropicModel(this.defaultModel) ? "anthropic" : this.name;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
/** See {@link Provider.supportsNativeWebSearch}. Set per model at construction. */
|
|
144
|
-
get supportsNativeWebSearch(): boolean {
|
|
145
|
-
return this.useNativeWebSearch;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
143
|
override async sendMessage(
|
|
149
144
|
messages: Message[],
|
|
150
145
|
options?: SendMessageOptions,
|
|
@@ -43,9 +43,6 @@ let lazyInitPromise: Promise<void> | null = null;
|
|
|
43
43
|
export class CallSiteConfiguredProvider implements Provider {
|
|
44
44
|
public readonly name: string;
|
|
45
45
|
public readonly tokenEstimationProvider?: string;
|
|
46
|
-
// Forward native web-search capability so it survives the wrapper chain
|
|
47
|
-
// (callers like the advisor consult gate on it). Fixed at construction.
|
|
48
|
-
public readonly supportsNativeWebSearch?: boolean;
|
|
49
46
|
|
|
50
47
|
constructor(
|
|
51
48
|
private readonly inner: Provider,
|
|
@@ -55,7 +52,6 @@ export class CallSiteConfiguredProvider implements Provider {
|
|
|
55
52
|
) {
|
|
56
53
|
this.name = inner.name;
|
|
57
54
|
this.tokenEstimationProvider = inner.tokenEstimationProvider;
|
|
58
|
-
this.supportsNativeWebSearch = inner.supportsNativeWebSearch;
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
sendMessage(
|
|
@@ -23,10 +23,6 @@ export class RateLimitProvider implements Provider {
|
|
|
23
23
|
return this.inner.tokenEstimationProvider;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
get supportsNativeWebSearch(): boolean | undefined {
|
|
27
|
-
return this.inner.supportsNativeWebSearch;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
private requestTimestamps: number[];
|
|
31
27
|
|
|
32
28
|
// Forward the optional token-counting endpoint so the capability survives
|
package/src/providers/retry.ts
CHANGED
|
@@ -618,10 +618,6 @@ export class RetryProvider implements Provider {
|
|
|
618
618
|
return this.inner.tokenEstimationProvider;
|
|
619
619
|
}
|
|
620
620
|
|
|
621
|
-
get supportsNativeWebSearch(): boolean | undefined {
|
|
622
|
-
return this.inner.supportsNativeWebSearch;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
621
|
// Forward the optional token-counting endpoint so the capability survives
|
|
626
622
|
// the wrapper chain (callers gate on its presence). Bound straight to the
|
|
627
623
|
// inner provider — count_tokens is a cheap separate endpoint and its caller
|
package/src/providers/types.ts
CHANGED
|
@@ -265,15 +265,6 @@ export interface Provider {
|
|
|
265
265
|
* Falls back to `name` when unset.
|
|
266
266
|
*/
|
|
267
267
|
tokenEstimationProvider?: string;
|
|
268
|
-
/**
|
|
269
|
-
* True when this provider instance was constructed to run web search
|
|
270
|
-
* server-side (provider-native). The native search only activates when a
|
|
271
|
-
* `web_search`-named tool is passed in the request, so callers that want to
|
|
272
|
-
* enable web search on a one-shot completion (e.g. the advisor consult) check
|
|
273
|
-
* this first — passing the tool to a non-native instance would surface an
|
|
274
|
-
* unexecutable client tool call. Absent/false on providers without it.
|
|
275
|
-
*/
|
|
276
|
-
supportsNativeWebSearch?: boolean;
|
|
277
268
|
sendMessage(
|
|
278
269
|
messages: Message[],
|
|
279
270
|
options?: SendMessageOptions,
|
|
@@ -18,9 +18,6 @@ const log = getLogger("provider-usage-tracking");
|
|
|
18
18
|
export class UsageTrackingProvider implements Provider {
|
|
19
19
|
public readonly name: string;
|
|
20
20
|
public readonly tokenEstimationProvider?: string;
|
|
21
|
-
// Forward native web-search capability so it survives the wrapper chain
|
|
22
|
-
// (callers like the advisor consult gate on it). Fixed at construction.
|
|
23
|
-
public readonly supportsNativeWebSearch?: boolean;
|
|
24
21
|
// Forward the optional token-counting endpoint so the capability survives
|
|
25
22
|
// the wrapper chain. Bound straight to the inner provider — count_tokens is
|
|
26
23
|
// not billed, so there's no usage to track.
|
|
@@ -29,7 +26,6 @@ export class UsageTrackingProvider implements Provider {
|
|
|
29
26
|
constructor(private readonly inner: Provider) {
|
|
30
27
|
this.name = inner.name;
|
|
31
28
|
this.tokenEstimationProvider = inner.tokenEstimationProvider;
|
|
32
|
-
this.supportsNativeWebSearch = inner.supportsNativeWebSearch;
|
|
33
29
|
if (inner.countInputTokens) {
|
|
34
30
|
this.countInputTokens = inner.countInputTokens.bind(inner);
|
|
35
31
|
}
|