@vellumai/assistant 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +11 -12
- package/docker-entrypoint.sh +13 -2
- package/docker-init-apt-root.sh +79 -6
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +945 -36
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +271 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +272 -0
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/compaction-events.test.ts +1 -1
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/compactor-tail-resolution.test.ts +107 -1
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +112 -57
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
- package/src/__tests__/conversation-agent-loop.test.ts +77 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +161 -0
- package/src/__tests__/conversation-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +290 -85
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +6 -0
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/external-plugin-loader.test.ts +91 -19
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/host-app-control-proxy.test.ts +241 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +7 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +9 -2
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +3 -0
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +2 -0
- package/src/__tests__/llm-resolver.test.ts +340 -3
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/managed-profile-guard.test.ts +10 -0
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/openai-provider.test.ts +323 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +3 -3
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
- package/src/__tests__/platform-proxy-context.test.ts +6 -1
- package/src/__tests__/platform.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +3 -3
- package/src/__tests__/plugin-types.test.ts +2 -2
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/provider-catalog-visibility.test.ts +16 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +27 -25
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +57 -101
- package/src/__tests__/terminal-tools.test.ts +11 -1
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-executor.test.ts +90 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +88 -5
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +208 -22
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/browser/operations.ts +15 -0
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +14 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +469 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/memory-v2.ts +308 -0
- package/src/cli/commands/notifications.ts +89 -37
- package/src/cli/commands/plugins.ts +67 -0
- package/src/cli/commands/schedules.ts +297 -5
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/install-from-github.ts +8 -9
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/program.ts +14 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +117 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +124 -0
- package/src/config/feature-flag-registry.json +111 -23
- package/src/config/llm-resolver.ts +66 -1
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -3
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/channels.ts +9 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +14 -0
- package/src/config/schemas/llm.ts +4 -3
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +51 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/context/compactor.ts +80 -13
- package/src/context/token-estimator.ts +72 -31
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -22
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +231 -23
- package/src/daemon/conversation-agent-loop.ts +252 -56
- package/src/daemon/conversation-lifecycle.ts +142 -116
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +144 -75
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +7 -0
- package/src/daemon/conversation.ts +42 -12
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +449 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +80 -0
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-app-control-proxy.ts +69 -18
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/host-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +67 -65
- package/src/daemon/memory-v2-startup.ts +49 -13
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +8 -0
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/messages.ts +68 -1
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/pkb-reminder-builder.test.ts +10 -53
- package/src/daemon/pkb-reminder-builder.ts +4 -19
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +72 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/skill-memory-refresh.ts +5 -1
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +44 -1
- package/src/heartbeat/heartbeat-service.ts +35 -191
- package/src/home/__tests__/feed-types.test.ts +40 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +20 -3
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +94 -0
- package/src/home/suggested-prompts.ts +177 -9
- package/src/ipc/cli-client.ts +147 -45
- package/src/memory/__tests__/conversation-queries.test.ts +220 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +407 -10
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/conversation-queries.ts +87 -1
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +22 -0
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +84 -3
- package/src/memory/graph/conversation-graph-memory.ts +18 -6
- package/src/memory/graph/tools.ts +6 -37
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs-worker.ts +21 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +7 -2
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +4 -22
- package/src/memory/memory-retrospective-job.ts +438 -21
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +26 -8
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/index.ts +20 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +2 -0
- package/src/memory/schema/infrastructure.ts +2 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +221 -17
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/router.test.ts +489 -1
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +69 -29
- package/src/memory/v2/page-index.ts +246 -19
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +18 -3
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +5 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +521 -36
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +111 -44
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +10 -1
- package/src/notifications/home-feed-side-effect.ts +136 -27
- package/src/notifications/signal.ts +0 -4
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +13 -4
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +4 -1
- package/src/plugins/defaults/injectors.ts +118 -26
- package/src/plugins/external-plugin-loader.ts +82 -10
- package/src/plugins/types.ts +16 -7
- package/src/prompts/__tests__/system-prompt.test.ts +44 -45
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +4 -8
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -76
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +51 -10
- package/src/providers/__tests__/inference.test.ts +2 -0
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +63 -13
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +24 -21
- package/src/providers/inference/auth.ts +15 -3
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/connections.ts +85 -5
- package/src/providers/inference/resolve-auth.ts +50 -5
- package/src/providers/model-catalog.ts +244 -242
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +215 -25
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +46 -4
- package/src/providers/platform-proxy/constants.ts +3 -4
- package/src/providers/provider-catalog-visibility.ts +3 -1
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +30 -1
- package/src/providers/types.ts +25 -0
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +212 -57
- package/src/runtime/auth/route-policy.ts +20 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +7 -51
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +121 -5
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/channel-availability-routes.ts +5 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +146 -1
- package/src/runtime/routes/conversation-query-routes.ts +130 -12
- package/src/runtime/routes/conversation-routes.ts +288 -76
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +8 -1
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +14 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +192 -3
- package/src/runtime/routes/integrations/a2a.ts +294 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-v2-routes.ts +217 -0
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/slack-channel-routes.ts +187 -0
- package/src/runtime/routes/subagents-routes.ts +41 -0
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/subagent/manager.ts +2 -0
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
- package/src/tools/browser/browser-execution.ts +93 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
- package/src/tools/browser/cdp-client/factory.ts +87 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
- package/src/tools/browser/cdp-client/types.ts +36 -0
- package/src/tools/browser/pinned-tabs.ts +90 -0
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +128 -2
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +213 -64
- package/src/tools/network/web-search.ts +191 -66
- package/src/tools/registry.ts +2 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +41 -2
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/types/onboarding-context.ts +4 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/platform.ts +0 -5
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -21,6 +21,13 @@ interface FakeChunk {
|
|
|
21
21
|
choices: Array<{
|
|
22
22
|
delta: {
|
|
23
23
|
content?: string | null;
|
|
24
|
+
reasoning_content?: string | null;
|
|
25
|
+
reasoning?: string | null;
|
|
26
|
+
reasoning_details?: Array<{
|
|
27
|
+
type?: string;
|
|
28
|
+
summary?: string | null;
|
|
29
|
+
text?: string | null;
|
|
30
|
+
}> | null;
|
|
24
31
|
tool_calls?: Array<{
|
|
25
32
|
index: number;
|
|
26
33
|
id?: string;
|
|
@@ -209,6 +216,44 @@ function cachedUsageChunk(
|
|
|
209
216
|
};
|
|
210
217
|
}
|
|
211
218
|
|
|
219
|
+
function reasoningChunk(
|
|
220
|
+
reasoning: string,
|
|
221
|
+
finish: string | null = null,
|
|
222
|
+
): FakeChunk {
|
|
223
|
+
return {
|
|
224
|
+
choices: [
|
|
225
|
+
{ delta: { reasoning_content: reasoning }, finish_reason: finish },
|
|
226
|
+
],
|
|
227
|
+
usage: null,
|
|
228
|
+
model: "gpt-5.2",
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// OpenRouter spec uses `delta.reasoning` rather than `delta.reasoning_content`.
|
|
233
|
+
function openRouterReasoningChunk(
|
|
234
|
+
reasoning: string,
|
|
235
|
+
finish: string | null = null,
|
|
236
|
+
): FakeChunk {
|
|
237
|
+
return {
|
|
238
|
+
choices: [{ delta: { reasoning }, finish_reason: finish }],
|
|
239
|
+
usage: null,
|
|
240
|
+
model: "gpt-5.2",
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// OpenRouter's documented reasoning-summary shape: a `reasoning_details` array
|
|
245
|
+
// with entries tagged `reasoning.summary` / `reasoning.text` / `reasoning.encrypted`.
|
|
246
|
+
function reasoningDetailsChunk(
|
|
247
|
+
details: Array<{ type?: string; summary?: string; text?: string }>,
|
|
248
|
+
finish: string | null = null,
|
|
249
|
+
): FakeChunk {
|
|
250
|
+
return {
|
|
251
|
+
choices: [{ delta: { reasoning_details: details }, finish_reason: finish }],
|
|
252
|
+
usage: null,
|
|
253
|
+
model: "gpt-5.2",
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
212
257
|
// ---------------------------------------------------------------------------
|
|
213
258
|
// Class extraction sanity checks
|
|
214
259
|
// ---------------------------------------------------------------------------
|
|
@@ -339,6 +384,153 @@ describe("OpenAIProvider", () => {
|
|
|
339
384
|
expect(events[1]).toEqual({ type: "text_delta", text: ", world!" });
|
|
340
385
|
});
|
|
341
386
|
|
|
387
|
+
// -----------------------------------------------------------------------
|
|
388
|
+
// Reasoning content (MiniMax / DeepSeek extension)
|
|
389
|
+
// -----------------------------------------------------------------------
|
|
390
|
+
test("parses reasoning_content into thinking block", async () => {
|
|
391
|
+
fakeChunks = [
|
|
392
|
+
reasoningChunk("Let me think..."),
|
|
393
|
+
textChunk("The answer is 42."),
|
|
394
|
+
usageChunk(10, 20),
|
|
395
|
+
];
|
|
396
|
+
|
|
397
|
+
const result = await provider.sendMessage([userMsg("Hi")]);
|
|
398
|
+
|
|
399
|
+
expect(result.content).toHaveLength(2);
|
|
400
|
+
expect(result.content[0]).toEqual({
|
|
401
|
+
type: "thinking",
|
|
402
|
+
thinking: "Let me think...",
|
|
403
|
+
signature: "",
|
|
404
|
+
});
|
|
405
|
+
expect(result.content[1]).toEqual({
|
|
406
|
+
type: "text",
|
|
407
|
+
text: "The answer is 42.",
|
|
408
|
+
});
|
|
409
|
+
expect(result.usage).toEqual({ inputTokens: 10, outputTokens: 20 });
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test("fires thinking_delta events during streaming", async () => {
|
|
413
|
+
fakeChunks = [
|
|
414
|
+
reasoningChunk("Let me think..."),
|
|
415
|
+
textChunk("The answer is 42."),
|
|
416
|
+
usageChunk(10, 20),
|
|
417
|
+
];
|
|
418
|
+
|
|
419
|
+
const events: ProviderEvent[] = [];
|
|
420
|
+
await provider.sendMessage([userMsg("Hi")], undefined, undefined, {
|
|
421
|
+
onEvent: (e) => events.push(e),
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
expect(events).toHaveLength(2);
|
|
425
|
+
expect(events[0]).toEqual({
|
|
426
|
+
type: "thinking_delta",
|
|
427
|
+
thinking: "Let me think...",
|
|
428
|
+
});
|
|
429
|
+
expect(events[1]).toEqual({
|
|
430
|
+
type: "text_delta",
|
|
431
|
+
text: "The answer is 42.",
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
test("reasoning + tool calls orders correctly (thinking → tool_use)", async () => {
|
|
436
|
+
fakeChunks = [
|
|
437
|
+
reasoningChunk("Planning..."),
|
|
438
|
+
...toolCallChunks([
|
|
439
|
+
{ id: "call_1", name: "file_read", args: '{"path":"/a"}' },
|
|
440
|
+
]),
|
|
441
|
+
usageChunk(10, 30),
|
|
442
|
+
];
|
|
443
|
+
|
|
444
|
+
const result = await provider.sendMessage([userMsg("Read /a")]);
|
|
445
|
+
|
|
446
|
+
expect(result.content).toHaveLength(2);
|
|
447
|
+
expect(result.content[0].type).toBe("thinking");
|
|
448
|
+
expect(result.content[1].type).toBe("tool_use");
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test("no thinking block when reasoning_content is absent", async () => {
|
|
452
|
+
fakeChunks = [textChunk("Just text"), usageChunk(10, 5)];
|
|
453
|
+
|
|
454
|
+
const result = await provider.sendMessage([userMsg("Hi")]);
|
|
455
|
+
|
|
456
|
+
expect(result.content).toHaveLength(1);
|
|
457
|
+
expect(result.content[0].type).toBe("text");
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
test("parses OpenRouter's `delta.reasoning` field into thinking block", async () => {
|
|
461
|
+
fakeChunks = [
|
|
462
|
+
openRouterReasoningChunk("Hmm, let me think..."),
|
|
463
|
+
textChunk("Final answer."),
|
|
464
|
+
usageChunk(10, 8),
|
|
465
|
+
];
|
|
466
|
+
|
|
467
|
+
const events: ProviderEvent[] = [];
|
|
468
|
+
const result = await provider.sendMessage(
|
|
469
|
+
[userMsg("Hi")],
|
|
470
|
+
undefined,
|
|
471
|
+
undefined,
|
|
472
|
+
{
|
|
473
|
+
onEvent: (e) => events.push(e),
|
|
474
|
+
},
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
expect(result.content).toHaveLength(2);
|
|
478
|
+
expect(result.content[0]).toEqual({
|
|
479
|
+
type: "thinking",
|
|
480
|
+
thinking: "Hmm, let me think...",
|
|
481
|
+
signature: "",
|
|
482
|
+
});
|
|
483
|
+
expect(result.content[1]).toEqual({ type: "text", text: "Final answer." });
|
|
484
|
+
expect(events).toContainEqual({
|
|
485
|
+
type: "thinking_delta",
|
|
486
|
+
thinking: "Hmm, let me think...",
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test("parses OpenRouter `delta.reasoning_details` summary/text entries and skips encrypted", async () => {
|
|
491
|
+
fakeChunks = [
|
|
492
|
+
reasoningDetailsChunk([
|
|
493
|
+
{ type: "reasoning.summary", summary: "Plan step one. " },
|
|
494
|
+
{ type: "reasoning.encrypted", text: "ENCRYPTED_BLOB" },
|
|
495
|
+
{ type: "reasoning.text", text: "Detailed thought." },
|
|
496
|
+
]),
|
|
497
|
+
textChunk("Done."),
|
|
498
|
+
usageChunk(10, 8),
|
|
499
|
+
];
|
|
500
|
+
|
|
501
|
+
const events: ProviderEvent[] = [];
|
|
502
|
+
const result = await provider.sendMessage(
|
|
503
|
+
[userMsg("Hi")],
|
|
504
|
+
undefined,
|
|
505
|
+
undefined,
|
|
506
|
+
{
|
|
507
|
+
onEvent: (e) => events.push(e),
|
|
508
|
+
},
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
expect(result.content).toHaveLength(2);
|
|
512
|
+
expect(result.content[0]).toEqual({
|
|
513
|
+
type: "thinking",
|
|
514
|
+
thinking: "Plan step one. Detailed thought.",
|
|
515
|
+
signature: "",
|
|
516
|
+
});
|
|
517
|
+
expect(result.content[1]).toEqual({ type: "text", text: "Done." });
|
|
518
|
+
expect(events).toContainEqual({
|
|
519
|
+
type: "thinking_delta",
|
|
520
|
+
thinking: "Plan step one. ",
|
|
521
|
+
});
|
|
522
|
+
expect(events).toContainEqual({
|
|
523
|
+
type: "thinking_delta",
|
|
524
|
+
thinking: "Detailed thought.",
|
|
525
|
+
});
|
|
526
|
+
// Encrypted blob must never surface as visible thinking.
|
|
527
|
+
for (const e of events) {
|
|
528
|
+
if (e.type === "thinking_delta") {
|
|
529
|
+
expect(e.thinking).not.toContain("ENCRYPTED_BLOB");
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
|
|
342
534
|
// -----------------------------------------------------------------------
|
|
343
535
|
// System prompt
|
|
344
536
|
// -----------------------------------------------------------------------
|
|
@@ -1306,14 +1498,17 @@ describe("OpenRouterProvider reasoning", () => {
|
|
|
1306
1498
|
shouldThrow = null;
|
|
1307
1499
|
});
|
|
1308
1500
|
|
|
1309
|
-
test("sends reasoning.enabled=true when thinking config is present", async () => {
|
|
1501
|
+
test("sends reasoning.enabled=true with default detailed summary when thinking config is present", async () => {
|
|
1310
1502
|
const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
|
|
1311
1503
|
await provider.sendMessage([userMsg("hi")], undefined, undefined, {
|
|
1312
1504
|
config: { thinking: { type: "adaptive" } },
|
|
1313
1505
|
});
|
|
1314
1506
|
|
|
1315
1507
|
expect(lastCreateParams).toBeTruthy();
|
|
1316
|
-
expect(lastCreateParams!.reasoning).toEqual({
|
|
1508
|
+
expect(lastCreateParams!.reasoning).toEqual({
|
|
1509
|
+
enabled: true,
|
|
1510
|
+
summary: "detailed",
|
|
1511
|
+
});
|
|
1317
1512
|
});
|
|
1318
1513
|
|
|
1319
1514
|
test("sends reasoning.enabled=false when thinking is explicitly disabled", async () => {
|
|
@@ -1376,7 +1571,10 @@ describe("OpenRouterProvider reasoning", () => {
|
|
|
1376
1571
|
await retry.sendMessage([userMsg("hi")], undefined, undefined, {
|
|
1377
1572
|
config: { thinking: { type: "adaptive" } },
|
|
1378
1573
|
});
|
|
1379
|
-
expect(lastCreateParams!.reasoning).toEqual({
|
|
1574
|
+
expect(lastCreateParams!.reasoning).toEqual({
|
|
1575
|
+
enabled: true,
|
|
1576
|
+
summary: "detailed",
|
|
1577
|
+
});
|
|
1380
1578
|
});
|
|
1381
1579
|
|
|
1382
1580
|
test("RetryProvider + OpenRouterProvider disables thinking end-to-end", async () => {
|
|
@@ -1389,6 +1587,23 @@ describe("OpenRouterProvider reasoning", () => {
|
|
|
1389
1587
|
});
|
|
1390
1588
|
expect(lastCreateParams!.reasoning).toEqual({ enabled: false });
|
|
1391
1589
|
});
|
|
1590
|
+
|
|
1591
|
+
test("nests effort under reasoning and omits top-level reasoning_effort", async () => {
|
|
1592
|
+
const provider = new OpenRouterProvider("or-key", "moonshotai/kimi-k2.6");
|
|
1593
|
+
await provider.sendMessage([userMsg("hi")], undefined, undefined, {
|
|
1594
|
+
config: { thinking: { enabled: true }, effort: "max" },
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
expect(lastCreateParams).toBeTruthy();
|
|
1598
|
+
expect(lastCreateParams!.reasoning).toEqual({
|
|
1599
|
+
enabled: true,
|
|
1600
|
+
effort: "xhigh",
|
|
1601
|
+
summary: "detailed",
|
|
1602
|
+
});
|
|
1603
|
+
// Critical: must NOT also send the OpenAI-native flat field — OpenRouter
|
|
1604
|
+
// rejects requests that carry both forms for reasoning models.
|
|
1605
|
+
expect(lastCreateParams).not.toHaveProperty("reasoning_effort");
|
|
1606
|
+
});
|
|
1392
1607
|
});
|
|
1393
1608
|
|
|
1394
1609
|
describe("OpenRouterProvider Anthropic-compatible errors", () => {
|
|
@@ -1529,4 +1744,109 @@ describe("OpenAIProvider reasoning_effort", () => {
|
|
|
1529
1744
|
});
|
|
1530
1745
|
expect(lastCreateParams!.reasoning_effort).toBe("medium");
|
|
1531
1746
|
});
|
|
1747
|
+
|
|
1748
|
+
test('maxReasoningEffort: "max" passes "max" through unclamped', async () => {
|
|
1749
|
+
const uncapped = new OpenAIProvider("test-key", "gpt-5", {
|
|
1750
|
+
maxReasoningEffort: "max",
|
|
1751
|
+
});
|
|
1752
|
+
await uncapped.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1753
|
+
config: { effort: "max" },
|
|
1754
|
+
});
|
|
1755
|
+
expect(lastCreateParams!.reasoning_effort).toBe("max");
|
|
1756
|
+
await uncapped.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1757
|
+
config: { effort: "xhigh" },
|
|
1758
|
+
});
|
|
1759
|
+
expect(lastCreateParams!.reasoning_effort).toBe("xhigh");
|
|
1760
|
+
});
|
|
1761
|
+
});
|
|
1762
|
+
|
|
1763
|
+
describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
1764
|
+
beforeEach(() => {
|
|
1765
|
+
fakeChunks = [];
|
|
1766
|
+
lastCreateParams = null;
|
|
1767
|
+
});
|
|
1768
|
+
|
|
1769
|
+
test('DeepSeek V4 Pro accepts "max" unclamped', async () => {
|
|
1770
|
+
const fw = new FireworksProvider(
|
|
1771
|
+
"fw-key",
|
|
1772
|
+
"accounts/fireworks/models/deepseek-v4-pro",
|
|
1773
|
+
);
|
|
1774
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1775
|
+
config: { effort: "max" },
|
|
1776
|
+
});
|
|
1777
|
+
expect(lastCreateParams!.reasoning_effort).toBe("max");
|
|
1778
|
+
});
|
|
1779
|
+
|
|
1780
|
+
test('DeepSeek V4 Pro accepts "xhigh" unclamped', async () => {
|
|
1781
|
+
const fw = new FireworksProvider(
|
|
1782
|
+
"fw-key",
|
|
1783
|
+
"accounts/fireworks/models/deepseek-v4-pro",
|
|
1784
|
+
);
|
|
1785
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1786
|
+
config: { effort: "xhigh" },
|
|
1787
|
+
});
|
|
1788
|
+
expect(lastCreateParams!.reasoning_effort).toBe("xhigh");
|
|
1789
|
+
});
|
|
1790
|
+
|
|
1791
|
+
test('Kimi K2.6 clamps "xhigh"/"max" down to "high"', async () => {
|
|
1792
|
+
const fw = new FireworksProvider(
|
|
1793
|
+
"fw-key",
|
|
1794
|
+
"accounts/fireworks/models/kimi-k2p6",
|
|
1795
|
+
);
|
|
1796
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1797
|
+
config: { effort: "xhigh" },
|
|
1798
|
+
});
|
|
1799
|
+
expect(lastCreateParams!.reasoning_effort).toBe("high");
|
|
1800
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1801
|
+
config: { effort: "max" },
|
|
1802
|
+
});
|
|
1803
|
+
expect(lastCreateParams!.reasoning_effort).toBe("high");
|
|
1804
|
+
});
|
|
1805
|
+
|
|
1806
|
+
test('unknown Fireworks model falls back to "high" ceiling', async () => {
|
|
1807
|
+
const fw = new FireworksProvider(
|
|
1808
|
+
"fw-key",
|
|
1809
|
+
"accounts/fireworks/models/some-future-model",
|
|
1810
|
+
);
|
|
1811
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1812
|
+
config: { effort: "max" },
|
|
1813
|
+
});
|
|
1814
|
+
expect(lastCreateParams!.reasoning_effort).toBe("high");
|
|
1815
|
+
});
|
|
1816
|
+
|
|
1817
|
+
test("effort below ceiling is forwarded verbatim", async () => {
|
|
1818
|
+
const fw = new FireworksProvider(
|
|
1819
|
+
"fw-key",
|
|
1820
|
+
"accounts/fireworks/models/deepseek-v4-pro",
|
|
1821
|
+
);
|
|
1822
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1823
|
+
config: { effort: "medium" },
|
|
1824
|
+
});
|
|
1825
|
+
expect(lastCreateParams!.reasoning_effort).toBe("medium");
|
|
1826
|
+
});
|
|
1827
|
+
|
|
1828
|
+
test('effort: "none" passes through regardless of ceiling', async () => {
|
|
1829
|
+
const fw = new FireworksProvider(
|
|
1830
|
+
"fw-key",
|
|
1831
|
+
"accounts/fireworks/models/kimi-k2p6",
|
|
1832
|
+
);
|
|
1833
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1834
|
+
config: { effort: "none" },
|
|
1835
|
+
});
|
|
1836
|
+
expect(lastCreateParams!.reasoning_effort).toBe("none");
|
|
1837
|
+
});
|
|
1838
|
+
|
|
1839
|
+
test("model override picks ceiling from runtime model, not constructor model", async () => {
|
|
1840
|
+
const fw = new FireworksProvider(
|
|
1841
|
+
"fw-key",
|
|
1842
|
+
"accounts/fireworks/models/kimi-k2p6",
|
|
1843
|
+
);
|
|
1844
|
+
await fw.sendMessage([userMsg("hi")], undefined, "system", {
|
|
1845
|
+
config: {
|
|
1846
|
+
effort: "max",
|
|
1847
|
+
model: "accounts/fireworks/models/deepseek-v4-pro",
|
|
1848
|
+
},
|
|
1849
|
+
});
|
|
1850
|
+
expect(lastCreateParams!.reasoning_effort).toBe("max");
|
|
1851
|
+
});
|
|
1532
1852
|
});
|
|
@@ -92,9 +92,9 @@ describe("OpenAI Responses API cutover guard", () => {
|
|
|
92
92
|
|
|
93
93
|
// The factory must NOT instantiate OpenAIChatCompletionsProvider or
|
|
94
94
|
// OpenAIProvider (the backward-compatible alias) inside the `openai:`
|
|
95
|
-
// factory entry. Other entries (e.g. `
|
|
96
|
-
//
|
|
97
|
-
//
|
|
95
|
+
// factory entry. Other entries (e.g. `openai-compatible:`) may legitimately
|
|
96
|
+
// use OpenAIChatCompletionsProvider since that's the OpenAI Chat Completions
|
|
97
|
+
// transport for third-party endpoints.
|
|
98
98
|
const openaiEntryRegion =
|
|
99
99
|
/(?:^|\s)openai\s*:\s*\([^)]*\)\s*=>\s*[\s\S]{0,400}?(?=\}\s*,\s*[a-z-]+\s*:|\}\s*;)/m.exec(
|
|
100
100
|
source,
|
|
@@ -714,16 +714,16 @@ describe("OpenAIResponsesProvider", () => {
|
|
|
714
714
|
});
|
|
715
715
|
|
|
716
716
|
// -----------------------------------------------------------------------
|
|
717
|
-
// store
|
|
717
|
+
// store — omitted so prompt caching can persist across turns
|
|
718
718
|
// -----------------------------------------------------------------------
|
|
719
|
-
test("
|
|
719
|
+
test("does not set store in params (defaults to true server-side)", async () => {
|
|
720
720
|
fakeStreamEvents = [textDeltaEvent("OK"), completedEvent(10, 2)];
|
|
721
721
|
|
|
722
722
|
await provider.sendMessage([
|
|
723
723
|
{ role: "user", content: [{ type: "text", text: "Hi" }] },
|
|
724
724
|
]);
|
|
725
725
|
|
|
726
|
-
expect(lastStreamParams!.store).
|
|
726
|
+
expect(lastStreamParams!.store).toBeUndefined();
|
|
727
727
|
});
|
|
728
728
|
|
|
729
729
|
// -----------------------------------------------------------------------
|
|
@@ -1122,7 +1122,7 @@ describe("OpenAIResponsesProvider", () => {
|
|
|
1122
1122
|
const rawReq = result.rawRequest as Record<string, unknown>;
|
|
1123
1123
|
expect(rawReq.model).toBe("gpt-5.2");
|
|
1124
1124
|
expect(rawReq.instructions).toBe("System prompt");
|
|
1125
|
-
expect(rawReq.store).
|
|
1125
|
+
expect(rawReq.store).toBeUndefined();
|
|
1126
1126
|
|
|
1127
1127
|
// rawResponse should contain the final response object, including `output`
|
|
1128
1128
|
// which downstream normalization relies on for Responses API detection.
|
|
@@ -116,7 +116,7 @@ describe("OpenRouter provider.only plumbing", () => {
|
|
|
116
116
|
expect(extras.provider).toBe(undefined);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
test("
|
|
119
|
+
test("enables thinking with default detailed summary alongside provider.only", () => {
|
|
120
120
|
const provider = new ProbeOpenRouterProvider(
|
|
121
121
|
"fake-key",
|
|
122
122
|
"x-ai/grok-4.20-beta",
|
|
@@ -128,12 +128,12 @@ describe("OpenRouter provider.only plumbing", () => {
|
|
|
128
128
|
},
|
|
129
129
|
});
|
|
130
130
|
expect(extras).toEqual({
|
|
131
|
-
reasoning: { enabled: true },
|
|
131
|
+
reasoning: { enabled: true, summary: "detailed" },
|
|
132
132
|
provider: { only: ["xAI"] },
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
test("disabled thinking keeps reasoning disabled
|
|
136
|
+
test("disabled thinking keeps reasoning disabled and omits summary", () => {
|
|
137
137
|
const provider = new ProbeOpenRouterProvider(
|
|
138
138
|
"fake-key",
|
|
139
139
|
"x-ai/grok-4.20-beta",
|
|
@@ -149,5 +149,53 @@ describe("OpenRouter provider.only plumbing", () => {
|
|
|
149
149
|
provider: { only: ["xAI"] },
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
test("nests effort under reasoning and maps `max` to xhigh", () => {
|
|
154
|
+
const provider = new ProbeOpenRouterProvider(
|
|
155
|
+
"fake-key",
|
|
156
|
+
"moonshotai/kimi-k2.6",
|
|
157
|
+
);
|
|
158
|
+
const extras = provider.probeExtras({
|
|
159
|
+
config: {
|
|
160
|
+
thinking: { enabled: true },
|
|
161
|
+
effort: "max",
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
expect(extras).toEqual({
|
|
165
|
+
reasoning: { enabled: true, effort: "xhigh", summary: "detailed" },
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("honors a per-call summary override", () => {
|
|
170
|
+
const provider = new ProbeOpenRouterProvider(
|
|
171
|
+
"fake-key",
|
|
172
|
+
"moonshotai/kimi-k2.6",
|
|
173
|
+
);
|
|
174
|
+
const extras = provider.probeExtras({
|
|
175
|
+
config: {
|
|
176
|
+
thinking: { enabled: true },
|
|
177
|
+
openrouter: { reasoning: { summary: "concise" } },
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
expect(extras).toEqual({
|
|
181
|
+
reasoning: { enabled: true, summary: "concise" },
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("ignores an invalid summary override and falls back to detailed", () => {
|
|
186
|
+
const provider = new ProbeOpenRouterProvider(
|
|
187
|
+
"fake-key",
|
|
188
|
+
"moonshotai/kimi-k2.6",
|
|
189
|
+
);
|
|
190
|
+
const extras = provider.probeExtras({
|
|
191
|
+
config: {
|
|
192
|
+
thinking: { enabled: true },
|
|
193
|
+
openrouter: { reasoning: { summary: "verbose" } },
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
expect(extras).toEqual({
|
|
197
|
+
reasoning: { enabled: true, summary: "detailed" },
|
|
198
|
+
});
|
|
199
|
+
});
|
|
152
200
|
});
|
|
153
201
|
});
|
|
@@ -5,7 +5,11 @@ import { OpenRouterProvider } from "../providers/openrouter/client.js";
|
|
|
5
5
|
import type { Message } from "../providers/types.js";
|
|
6
6
|
|
|
7
7
|
/** Build a minimal valid PNG header encoding the given dimensions. */
|
|
8
|
-
function makePngBase64(
|
|
8
|
+
function makePngBase64(
|
|
9
|
+
width: number,
|
|
10
|
+
height: number,
|
|
11
|
+
paddingBytes = 0,
|
|
12
|
+
): string {
|
|
9
13
|
const header = Buffer.alloc(24);
|
|
10
14
|
header[0] = 0x89;
|
|
11
15
|
header[1] = 0x50;
|
|
@@ -41,13 +45,13 @@ describe("OpenRouterProvider token estimation routing", () => {
|
|
|
41
45
|
expect(provider.tokenEstimationProvider).toBe("openrouter");
|
|
42
46
|
});
|
|
43
47
|
|
|
44
|
-
test("estimatePromptTokens applies
|
|
48
|
+
test("estimatePromptTokens applies dimension-based image scaling when routed via OpenRouter to Anthropic", () => {
|
|
45
49
|
const provider = new OpenRouterProvider(
|
|
46
50
|
"fake-key",
|
|
47
51
|
"anthropic/claude-opus-4-6",
|
|
48
52
|
);
|
|
49
53
|
// 1920x1080 screenshot with ~200 KB of pixel data → base64/4 would be ~65k
|
|
50
|
-
// tokens; dimension-based
|
|
54
|
+
// tokens; dimension-based rules land around 1.6k tokens.
|
|
51
55
|
const messages: Message[] = [
|
|
52
56
|
{
|
|
53
57
|
role: "user",
|
|
@@ -68,33 +72,38 @@ describe("OpenRouterProvider token estimation routing", () => {
|
|
|
68
72
|
providerName: provider.tokenEstimationProvider,
|
|
69
73
|
});
|
|
70
74
|
|
|
71
|
-
// Dimension-based estimate should be well under 5k; base64/4 would exceed 50k.
|
|
72
75
|
expect(estimated).toBeLessThan(5_000);
|
|
73
76
|
});
|
|
74
77
|
|
|
75
|
-
test("estimatePromptTokens
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
test("estimatePromptTokens applies dimension-based image scaling for non-Anthropic OpenRouter models", () => {
|
|
79
|
+
// A naive base64/4 estimate on a 1920x1080 screenshot (~200 KB) lands near
|
|
80
|
+
// 65k tokens and trips spurious compaction long before the real context
|
|
81
|
+
// window fills. Vision models on OpenRouter — both anthropic/* and
|
|
82
|
+
// non-Anthropic (Kimi K2.6, Grok, etc.) — must use the dimension-based
|
|
83
|
+
// formula.
|
|
84
|
+
for (const model of ["moonshotai/kimi-k2.6", "x-ai/grok-4.20-beta"]) {
|
|
85
|
+
const provider = new OpenRouterProvider("fake-key", model);
|
|
86
|
+
const messages: Message[] = [
|
|
87
|
+
{
|
|
88
|
+
role: "user",
|
|
89
|
+
content: [
|
|
90
|
+
{
|
|
91
|
+
type: "image",
|
|
92
|
+
source: {
|
|
93
|
+
type: "base64",
|
|
94
|
+
media_type: "image/png",
|
|
95
|
+
data: makePngBase64(1920, 1080, 200_000),
|
|
96
|
+
},
|
|
87
97
|
},
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
];
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
];
|
|
92
101
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
const estimated = estimatePromptTokens(messages, "system", {
|
|
103
|
+
providerName: provider.tokenEstimationProvider,
|
|
104
|
+
});
|
|
96
105
|
|
|
97
|
-
|
|
98
|
-
|
|
106
|
+
expect(estimated).toBeLessThan(5_000);
|
|
107
|
+
}
|
|
99
108
|
});
|
|
100
109
|
});
|