Skip to content

Conversation

@daniel-lxs
Copy link
Member

@daniel-lxs daniel-lxs commented Jan 16, 2026

Summary

Migrate the OpenRouter provider from the OpenAI SDK to the Vercel AI SDK for a more standardized and maintainable implementation.

Closes COM-502

Problem

The current OpenRouter provider implementation uses the raw OpenAI SDK directly, which requires complex message transformation and reasoning token handling code that is difficult to maintain.

Solution

Refactor the OpenRouter provider to use the @openrouter/ai-sdk-provider package which integrates with Vercel's AI SDK. This provides:

  • Standardized streaming via streamText and generateText
  • Cleaner message conversion through the AI SDK's CoreMessage format
  • Simplified tool handling
  • Consistent provider options interface

Changes

  • Created src/api/transform/ai-sdk.ts with message/tool conversion utilities
  • Rewrote src/api/providers/openrouter.ts to use AI SDK patterns
  • Added comprehensive tests in src/api/transform/__tests__/ai-sdk.spec.ts
  • Updated src/api/providers/__tests__/openrouter.spec.ts with new test patterns
  • Aligned zod versions across the monorepo to prevent type issues (added pnpm override)

Testing

  • tsc --noEmit passes in both packages/types and src
  • All 5338 tests pass (376 test files)

Important

Refactor OpenRouter provider to use Vercel AI SDK, simplifying implementation and improving maintainability.

  • Behavior:
    • Refactor OpenRouterHandler in openrouter.ts to use Vercel AI SDK, replacing OpenAI SDK.
    • Implements createMessage and completePrompt using streamText and generateText from Vercel AI SDK.
    • Handles API and stream errors, tool call events, and reasoning delta chunks.
  • Utilities:
    • Add ai-sdk.ts for converting messages and tools to AI SDK format and processing stream parts.
  • Testing:
    • Update tests in openrouter.spec.ts to mock Vercel AI SDK functions and verify new behavior.
    • Add tests in ai-sdk.spec.ts for conversion utilities.
  • Dependencies:
    • Add @openrouter/ai-sdk-provider and ai to devDependencies.
    • Align zod version across packages.

This description was created by Ellipsis for 5260473. You can customize this summary. It will automatically update as commits are pushed.

- Replace direct OpenAI SDK usage with @openrouter/ai-sdk-provider
- Add 'ai' package for streamText() and generateText() functions
- Extract reusable AI SDK conversion utilities to src/api/transform/ai-sdk.ts:
  - convertToAiSdkMessages(): Anthropic messages to CoreMessage format
  - convertToolsForAiSdk(): OpenAI tools to AI SDK tool format
  - processAiSdkStreamPart(): AI SDK stream events to ApiStreamChunk
- Update tests to mock AI SDK functions instead of OpenAI client
- Add comprehensive tests for the new ai-sdk.ts utility module

This follows Vercel's AI SDK provider pattern for standardized LLM integration
and enables easier migration of other providers in the future.
@daniel-lxs daniel-lxs requested review from cte, jr and mrubens as code owners January 16, 2026 16:32
@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. Enhancement New feature or request labels Jan 16, 2026
@roomote
Copy link
Contributor

roomote bot commented Jan 16, 2026

Rooviewer Clock   See task on Roo Cloud

Review of commit 5260473. Found 1 issue that needs attention before merging.

  • Missing getReasoningDetails() method in src/api/providers/openrouter.ts - Task.ts relies on this method for preserving reasoning context across multi-turn conversations with models like Gemini 3
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

private client: OpenAI
protected models: ModelRecord = {}
protected endpoints: ModelRecord = {}
private readonly providerName = "OpenRouter"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old implementation had a getReasoningDetails() method and currentReasoningDetails accumulator that Task.ts relies on (see line 959 in Task.ts). This method accumulates reasoning_details from the stream (handling reasoning.text, reasoning.summary, and reasoning.encrypted types) and provides them for persistence in API conversation history. This is required for models like Gemini 3 via OpenRouter that use the reasoning.encrypted format - without it, reasoning context won't be preserved across multi-turn conversations, potentially breaking those model integrations.

Fix it with Roo Code or mention @roomote and request a fix.

@daniel-lxs daniel-lxs marked this pull request as draft January 16, 2026 16:40
- Fixed tool result output format to use typed object { type: 'text', value: string }
  instead of plain string to satisfy AI SDK validation schema
- Added tool name resolution by building a map of tool call IDs to names
- Updated tests to reflect new output format
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

2 participants