-
Notifications
You must be signed in to change notification settings - Fork 61.2k
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
feat: Add new provider OpenRouter #6324
base: main
Are you sure you want to change the base?
Conversation
@wyfyjc is attempting to deploy a commit to the NextChat Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThis pull request integrates support for the OpenRouter service. It adds new environment configuration entries and updates the server configuration to load these variables. The API routing is extended with a new case for OpenRouter along with a dedicated handler file. Client-side API classes and a new platform module are introduced to support OpenRouter calls. Additionally, UI components, locale strings, and state management in the access store are updated to incorporate settings and validations for OpenRouter. Changes
Sequence Diagram(s)sequenceDiagram
participant C as Client
participant R as API Router
participant H as OpenRouter Handler
participant A as Auth Module
participant X as External OpenRouter Service
C->>R: Send request to /api/openrouter
R->>H: Route to OpenRouter handler
H->>A: Call authentication for OpenRouter
A-->>H: Return auth status (success/failure)
alt Auth success
H->>X: Forward request to OpenRouter service
X-->>H: Return response
H-->>R: Return processed response
R-->>C: Send final response
else Auth failure
H-->>C: Return 401 Unauthorized
end
Poem
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 1
🔭 Outside diff range comments (2)
app/api/[provider]/[...path]/route.ts (1)
26-56
: 💡 Verification agent🧩 Analysis chain
Verify ApiPath.OpenRouter is defined in the constant file
The PR adds a handler for
ApiPath.OpenRouter
, but we should verify this constant is properly defined in the app/constant.ts file.
🏁 Script executed:
#!/bin/bash # Check if OpenRouter is defined in the constant.ts file grep -A 5 "ApiPath" app/constant.tsLength of output: 178
Missing
ApiPath.OpenRouter
definition inapp/constant.ts
.
It appears that while a handler forApiPath.OpenRouter
has been added in the routing file, there is no corresponding enum entry inapp/constant.ts
. Please update theApiPath
enum to include a proper definition forOpenRouter
(e.g.,OpenRouter = "/api/openrouter"
) to ensure consistency.app/client/api.ts (1)
254-313
: 💡 Verification agent🧩 Analysis chain
Consider adding OpenRouter to the API key selection logic.
The
getConfig
function doesn't include a case for OpenRouter when selecting the appropriate API key. This could potentially cause issues when the OpenRouter provider is selected.
🏁 Script executed:
#!/bin/bash # Check if OpenRouter is handled in the access store rg -A 5 "openrouterApiKey" --glob "*.ts" -iLength of output: 1140
Action Required: Integrate OpenRouter into API Key Selection
The current implementation of
getConfig
inapp/client/api.ts
(lines 254–313) does not handle the OpenRouter provider. Our repository confirms that anopenrouterApiKey
is defined in the access store and is used inapp/api/auth.ts
, but it isn’t referenced in this selection chain. Please update the API key selection logic to include a case for whenmodelConfig.providerName
is OpenRouter. For example, you might add:
- A new condition like:
const isOpenRouter = modelConfig.providerName === ServiceProvider.OpenRouter;- And update the
apiKey
selection chain to use:: isOpenRouter ? accessStore.openrouterApiKeyThis change will ensure consistency across the codebase and proper handling of the OpenRouter provider.
🧹 Nitpick comments (9)
app/config/server.ts (1)
91-257
: Documentation would enhance the OpenRouter implementation.Consider adding a brief comment explaining what OpenRouter is and why it's being integrated, especially since the PR mentions only implementing one specific model ("anthropic/claude-3.7-sonnet").
// openrouter only +// OpenRouter is a unified API that provides access to various AI models, +// including those from Anthropic, OpenAI, and others. +// Currently only anthropic/claude-3.7-sonnet model is integrated. OPENROUTER_URL?: string; OPENROUTER_API_KEY?: string;app/components/settings.tsx (1)
1462-1503
: Consider extracting repeated config blocks into a generic factory.
The newly introducedopenRouterConfigComponent
closely resembles configuration blocks for other providers. Refactoring all provider config components into a single, data-driven factory-style component could reduce code duplication and centralize maintenance.- // Example snippet: unify repeated config blocks - const openRouterConfigComponent = accessStore.provider === ServiceProvider.OpenRouter && ( - <> - <ListItem ... > - <input ... /> - </ListItem> - <ListItem ... > - <PasswordInput ... /> - </ListItem> - </> - ); + // Proposed pseudocode: + function renderProviderConfig(provider: ServiceProvider) { + const configs = [ + { label: "Endpoint", stateKey: "xxxUrl", placeholder: "Example.com/..." }, + { label: "ApiKey", stateKey: "xxxApiKey", placeholder: "sk-..." }, + // ... + ]; + return configs.map(({ label, stateKey, placeholder }) => ( + <ListItem title={label} ...> + <PasswordInput or input + ... + value={accessStore[stateKey]} + placeholder={placeholder} + onChange={(e) => accessStore.update((st) => (st[stateKey] = e.currentTarget.value))} + /> + </ListItem> + )); + }app/api/openrouter.ts (2)
14-15
: Limited ALLOWED_PATH ensures request security.
By restricting requests only toOpenRouter.ChatPath
, this prevents unauthorized route access. If additional routes are introduced later, ensure that they are similarly whitelisted.
59-146
: Suggest thorough testing and monitoring for long-running requests.
- A 10-minute timeout may be suitable for certain tasks, but if responses grow or concurrent requests are frequent, the server may consume resources excessively.
- Model filtering logic in lines 98–127 gracefully handles unapproved models with a 403. Continue maintaining a thorough test suite to verify correct handling of malformed request bodies.
- Final headers remove
www-authenticate
and disable buffering, ensuring a correct streaming response.app/client/platforms/openrouter.ts (4)
65-70
: Unify error handling inextractMessage(...)
.
Returningres
outright whenchoices?.at(0)?.message?.content
is missing can yield inconsistent return types. Consider returning a string or throwing an error to maintain consistent consumption patterns downstream.
72-74
: Implementspeech(...)
method or remove placeholder.
This placeholder currently throws an error. If speech functionality is not immediately required, either remove the method or comment it with a clear roadmap.
105-109
: Avoid hardcoding4000
tokens for vision models.
Currently,max_tokens
is forced to at least 4000 for vision models. This arbitrary limit may not be suitable for all usage scenarios and can unexpectedly inflate usage costs.
249-265
: Provide a fallback or additional models inmodels()
.
Currently, only one model—“anthropic/claude-3.7-sonnet”—is returned. If longer-term expansion is planned, allow for dynamic retrieval from an API or configuration to avoid future manual updates.app/constant.ts (1)
274-277
: Document or allow overrides forOpenRouter.ChatPath
.
HavingChatPath
hardcoded to"v1/chat/completions"
is valid for now, but future changes to the OpenRouter API or custom routing might require this core logic to be configurable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
.env.template
(1 hunks)app/api/[provider]/[...path]/route.ts
(2 hunks)app/api/auth.ts
(1 hunks)app/api/openrouter.ts
(1 hunks)app/client/api.ts
(3 hunks)app/client/platforms/openrouter.ts
(1 hunks)app/components/emoji.tsx
(1 hunks)app/components/settings.tsx
(3 hunks)app/config/server.ts
(3 hunks)app/constant.ts
(7 hunks)app/locales/cn.ts
(1 hunks)app/locales/en.ts
(1 hunks)app/store/access.ts
(5 hunks)
🔇 Additional comments (26)
.env.template (1)
85-89
: Good addition of OpenRouter configuration variablesThe OpenRouter API key and URL configuration entries are appropriately added with clear comments indicating they're optional. This matches the convention used for other service configurations in the file.
app/api/auth.ts (1)
107-109
: Authorization handler properly added for OpenRouterThe OpenRouter case is correctly integrated into the existing switch statement, following the established pattern of other providers.
app/components/emoji.tsx (2)
67-70
: Icon mapping properly updated for Anthropic modelsAdding support for model names starting with "anthropic" for the Claude icon is appropriate, as OpenRouter may reference Anthropic models with this prefix.
74-77
: Improved readability for Mistral model conditionThe reformatting of the condition for Mistral models improves readability while maintaining the same functionality.
app/api/[provider]/[...path]/route.ts (2)
17-17
: Correct import of OpenRouter handlerThe import follows the established pattern for other API handlers.
54-55
: OpenRouter API path case correctly addedThe OpenRouter case is properly integrated into the existing switch statement, allowing the application to handle OpenRouter API requests.
app/client/api.ts (3)
27-27
: Appropriate import for the new OpenRouter API integration.The import follows the same pattern as other platform imports, maintaining consistency in the code organization.
177-179
: Proper handler implementation for OpenRouter in the ClientApi constructor.This implementation follows the established pattern for other providers, creating a new instance of the OpenRouterApi class when ModelProvider.OpenRouter is selected.
389-390
: Complete the OpenRouter implementation in the getClientApi function.The implementation correctly maps the ServiceProvider.OpenRouter to ModelProvider.OpenRouter, which is consistent with the pattern used for other providers.
app/locales/en.ts (1)
546-556
: Good localization implementation for OpenRouter.The localization strings for OpenRouter follow the same structure and pattern as other providers, including both API key and endpoint configuration options. This maintains consistency in the user interface.
app/locales/cn.ts (1)
537-547
: Chinese localization implemented properly for OpenRouter.The Chinese localization strings for OpenRouter match the structure and content of the English version, providing a consistent experience for Chinese users. The translations appear accurate and maintain the same informational content.
app/config/server.ts (3)
91-94
: Proper environment variable declarations for OpenRouter.The environment variables for OpenRouter (OPENROUTER_URL and OPENROUTER_API_KEY) are declared with correct types and follow the established pattern for other providers.
170-170
: Server-side flag implementation for OpenRouter detection.The
isOpenRouter
flag is implemented consistently with other provider flags, checking for the presence of the API key environment variable.
254-257
: Configuration values exported for OpenRouter.The server configuration correctly exports the OpenRouter-related values, including the flag, URL, and API key, following the same pattern as other providers.
app/components/settings.tsx (1)
78-78
: No concerns regarding the OpenRouter import.
This import appropriately matches the newly introduced provider and is consistent with the existing import style.app/store/access.ts (5)
20-20
: Importing OPENROUTER_BASE_URL is aligned with other providers.
The new import follows the existing pattern for default URLs and ensures maintainability.
63-64
: Default OpenRouter URL initialization is consistent.
DefiningDEFAULT_OPENROUTER_URL
mirrors the approach for other providers, supporting both app and API path usage.
138-141
: Adding openrouterUrl and openrouterApiKey maintains store consistency.
The new fields match the pattern for storing provider-specific credentials and endpoints, ensuring uniform usage with other providers.
229-232
: The introduced isValidOpenRouter() method is consistent with existing validations.
It follows the same pattern of ensuring that necessary keys are set. The approach is straightforward and easy to maintain.
252-252
: Including isValidOpenRouter() in isAuthorized() properly integrates OpenRouter.
This addition ensures that OpenRouter credentials are recognized as a valid authorization source.app/api/openrouter.ts (2)
1-13
: Imports and initial definitions are well-structured.
They align with the project’s architecture, referencing updated constants and utilities for OpenRouter.
16-55
: The handle function correctly restricts methods and enforces authentication.
- Returns 200 for OPTIONS requests, conforming to standard preflight handling.
- Blocks forbidden paths with a 403.
- Enforces authorization via the
auth
function, returning 401 on failure.
This pattern prevents unauthorized usage and ensures robust security.app/client/platforms/openrouter.ts (1)
32-63
: Handle potential custom protocol edge cases inpath(...)
.
The logic adequately checks whetherbaseUrl
starts with "http" or `ApiPath.OpenRouter", but if a user specifies a protocol other than HTTP(S), it might be prepended with "https://". Consider whether to allow or prohibit alternative protocols, and clarify this handling in documentation.app/constant.ts (3)
39-39
: New OpenRouter constants and enum entries look good.
DefiningOPENROUTER_BASE_URL
,ApiPath.OpenRouter
, and enumeratingOpenRouter
inServiceProvider
andModelProvider
is consistent and well-structured.Also applies to: 77-77, 136-136, 163-163
663-666
: Limiting built-in OpenRouter models.
Using a single built-in model simplifies maintenance. If more models are needed in the future, consider bundling them behind a configuration or discovery mechanism.
823-833
: Seamless addition ofopenrouterModels
toDEFAULT_MODELS
.
This extension properly setsproviderName: "OpenRouter"
and aligns with the existing pattern for enumerating default models.
// @ts-ignore | ||
runTools[index]["function"]["arguments"] += args; | ||
} | ||
} | ||
|
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.
🛠️ Refactor suggestion
Revisit the ts-ignore
and string concatenation approach.
Doing runTools[index]["function"]["arguments"] += args;
with ts-ignore
can introduce hidden bugs. Consider properly typing these arguments or using a safer merge strategy to reduce reliance on ts-ignore
.
💻 变更类型 | Change Type
🔀 变更说明 | Description of Change
Add new provider OpenRouter
📝 补充信息 | Additional Information
Due to the excessive number of models provided by OpenRouter, only one model, anthropic/claude-3.7-sonnet, is built into constant.ts.
Summary by CodeRabbit
New Features
Documentation