-
Notifications
You must be signed in to change notification settings - Fork 123
v6 work-in-progress #319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
v6 work-in-progress #319
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…nfig F0.1: Switch to Bun - Run bun install to create bun.lock - Keep pnpm-lock.yaml for backward compatibility - Update scripts to use bun instead of pnpm F0.2: Update package.json for v6 - Update version to 6.0.0-alpha.0 - Move @ai-sdk/provider (^3.0.0) and @ai-sdk/provider-utils (^4.0.0) to dependencies - Update ai to ^6.0.0 in devDependencies - Update peerDependencies: zod ^3.25 || ^4.1 - Remove ai from peerDependencies (devDep only) F0.3: Update tsconfig.json - Change target from es2017 to ES2022 - Clean up include patterns for src/ and e2e/ - Remove Next.js specific configuration
- S1.11: Add OpenRouterEmbeddingModel stub (EmbeddingModelV3) - S1.12: Add OpenRouterImageModel stub (ImageModelV3, Tier 3) - S1.13: Add OpenRouterProvider interface and createOpenRouter factory - S1.14: Add internal/index.ts re-exports for advanced users - S1.15: Add src/index.ts with public exports and default instance Config updates: - Add baseUrl alias (deprecated) for compatibility - Add extraBody to provider settings - Make plugin and model options allow arbitrary properties
- Add @effect-native/fetch-hooks dev dependency - Add missing vi import to reasoning-multiturn e2e test - Add non-null assertion to baseURL to fix type error
Implement streaming support for the V3 language model:
- Create OpenRouter client with settings (apiKey, baseURL)
- Call client.chat.send({ stream: true })
- Transform SDK's EventStream to AI SDK V3 stream parts
- Emit proper lifecycle: stream-start, text-start/delta/end, reasoning-start/delta/end, response-metadata, finish
- Wire up existing utils: convertToOpenRouterMessages, mapOpenRouterFinishReason, buildUsage, buildProviderMetadata
- Handle headers with combineHeaders + normalizeHeaders
- Support call options: maxOutputTokens, temperature, topP, frequencyPenalty, presencePenalty, seed, stopSequences
- Add e2e/setup.ts that configures @effect-native/fetch-hooks - E2E_RECORD=1 enables recording mode (real API calls saved to fixtures) - Default replay mode uses cached fixtures (no network calls) - Sensitive headers (Authorization, x-api-key) are redacted - Create e2e/__fixtures__/ directory for cached responses - Update vitest.e2e.config.ts to use setup file
Implements LanguageModelV3 doGenerate method in OpenRouterChatLanguageModel: - Calls OpenRouter SDK with stream: false for non-streaming requests - Parses response to build content array (reasoning, text, tool-calls) - Uses existing utils: buildUsage, buildProviderMetadata, mapOpenRouterFinishReason - Returns full LanguageModelV3GenerateResult with content, usage, response metadata Adds e2e fixtures for reasoning-effort tests.
Change message content types to match OpenRouter SDK expectations: - text content: 'text' instead of 'input_text'/'output_text' - image content: 'image_url' with nested imageUrl object - file content: 'file' with fileUrl property This fixes SDKValidationError when sending messages to OpenRouter.
The OpenRouter SDK's Chat API only accepts specific content types:
- text: { type: 'text', text: string }
- image_url: { type: 'image_url', imageUrl: { url, detail? } }
- audio/video types
The previous code used { type: 'file', fileUrl } for non-image files,
which caused SDKValidationError during request serialization.
Changed convertFilePart() to always use image_url format since
OpenRouter's Chat API uses this type for all URL-based content.
The file-parser plugin handles non-image files (PDFs, etc.) when enabled.
- Fix streaming logic to emit finish only after receiving usage chunk (OpenRouter sends finish_reason and usage in separate chunks) - Update buildProviderMetadata to use camelCase fields from SDK - Add state tracking for finish reason, provider, text/reasoning end - Update tests to use camelCase (matching SDK transformed output) Note: The @openrouter/sdk strips 'provider' and 'cost' fields from API responses due to strict Zod parsing. Token usage data is working.
The @openrouter/sdk strips the cost field due to Zod schema limitations.
…rted OpenRouter's Chat Completions API only supports image URLs via image_url type. PDF URLs fail with 'unsupported format' errors from upstream providers. Changes: - Remove application/pdf from supportedUrls in language model - Update pdf-url E2E test to test image URLs instead (renamed to image urls) - Update pdf-blob tests to use Gemini (supports PDF data URIs) - Adjust FileParserPlugin token threshold to be realistic (5000 vs 150) PDF base64 data URIs work with Gemini through the Chat API. For other models, use the OpenRouter Responses API for PDF support.
- Replace SDK streaming with native fetch to handle large annotation chunks - The OpenRouter SDK has parsing issues with large JSON chunks containing web search annotations - Native fetch properly parses the raw SSE stream and extracts url_citation annotations - Convert raw snake_case API fields to camelCase for provider metadata - Also pass through plugins, transforms, and other model options to streaming requests - Update test to handle variable API behavior (sources may not always be returned)
- Pass cache_control from providerOptions.openrouter to message content - Add cacheWriteTokens to promptTokensDetails in provider metadata - Add imageTokens to completionTokensDetails in provider metadata - Fix cache-control E2E test to use correct model and provider routing - Add unit test for cache_control message conversion The test was failing because: 1. OpenRouter was routing to Google instead of Anthropic 2. cache_control wasn't being passed through from providerOptions 3. cacheWriteTokens wasn't being extracted from API response
- Updated from ^0.0.2 to ^0.1.0 (released npm version) - Fixed typecheck error in web-search test (narrow source type)
- Change from client.chat.send() to client.beta.responses.send() - Update request format to OpenResponsesRequest (input instead of messages) - Update response parsing for OpenResponsesNonStreamingResponse format - Update convertToOpenRouterMessages to produce Responses API format: - type: 'input_text' instead of 'text' for user messages - type: 'input_image' instead of 'image_url' for images - type: 'input_file' for non-image files - callId (camelCase) instead of call_id for function calls - Simple string content for assistant messages
- Create separate convert-to-chat-completions-messages.ts for streaming - doStream continues to use Chat Completions API (/chat/completions) - doGenerate uses Responses API (via previous commit) - Update E2E fixtures for new request formats
The Responses API requires a status field ('completed' | 'incomplete') for
function_call_output items. Successful tool results get 'completed', while
error outputs (error-text, error-json, execution-denied) get 'incomplete'.
- Add convertToolsToResponsesFormat to convert AI SDK function tools
to OpenRouter Responses API format
- Add convertToolChoiceToResponsesFormat to map tool choice options:
- 'auto', 'none', 'required' map directly
- { type: 'tool', toolName } maps to { type: 'function', name }
- Include tools and toolChoice in request params when provided
- Emit 'unsupported' warnings for non-function tool types
- Response parsing for function_call output items was already implemented
The streaming e2e tests were failing due to: 1. Stale/corrupted fixture files that had malformed JSON chunks 2. @openrouter/sdk@0.3.11 now requires zod v4 for its 'zod/v4' exports Changes: - Upgraded zod from ^3.25 to 4.3.5 for SDK compatibility - Regenerated all e2e fixtures with fresh API responses - Streaming provider metadata now works correctly Note: cache-control test still fails due to model not triggering cache tokens (expected behavior, not a code issue).
Test constructor properties: - specificationVersion is 'v3' - provider is 'openrouter' - modelId is set correctly - maxEmbeddingsPerCall is 2048 - supportsParallelCalls is true - implements EmbeddingModelV3 interface
Tests provider creation, callable interface, and all model factory methods: - specificationVersion 'v3' verification - provider(modelId) returns LanguageModelV3 - languageModel(), chat(), embeddingModel(), imageModel() methods - Deprecated aliases (textEmbeddingModel, embedding) - Provider configuration options (baseURL, headers, fetch, extraBody)
The OpenRouter API doesn't always return cache token data (depends on provider/model support and cache availability). Updated test to: - Verify promptTokensDetails structure exists without requiring values - Add separate live-only test for verifying actual cache hits - Log cache details for debugging visibility
Map AI SDK responseFormat option to OpenRouter Responses API text.format:
- { type: 'text' } -> { type: 'text' }
- { type: 'json' } -> { type: 'json_object' }
- { type: 'json', schema, name } -> { type: 'json_schema', name, schema }
This enables structured output / JSON schema constraints for models that
support it via the AI SDK generateObject() and streamObject() APIs.
Document that OpenRouter model variants (:online, :nitro, :floor, :free) work automatically since the model ID is passed through unchanged.
docs: add npm alpha channel badge docs: add alpha install instructions docs: add Coming Soon section with planned features
* ci: add PR snapshot workflow using pkg-pr-new * ci: add contents:read permission and concurrency group
wlib
reviewed
Jan 10, 2026
| readonly provider = 'openrouter'; | ||
| readonly modelId: string; | ||
|
|
||
| private readonly settings: OpenRouterModelSettings; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get Property 'settings' of exported anonymous class type may not be private or protected. ts(4094) from this btw
|
ETA? I need this quick! |
|
@brrock |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.