Skip to content
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

Feature dsmodels 20250228 #6317

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

wangjianhuaa
Copy link

@wangjianhuaa wangjianhuaa commented Mar 1, 2025

💻 变更类型 | Change Type

  • feat
  • fix

🔀 变更说明 | Description of Change

📝 补充信息 | Additional Information

Summary by CodeRabbit

  • New Features
    • Introduced Huawei service integration, enabling users to configure Huawei API keys and endpoints through the settings.
    • Enhanced the system to properly route and handle requests for Huawei services.
    • Expanded localization support by adding Huawei-specific configuration labels in multiple languages.
    • Updated environment and container configurations to include Huawei parameters alongside existing integrations.

Copy link

vercel bot commented Mar 1, 2025

@wangjianhuaa is attempting to deploy a commit to the NextChat Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Mar 1, 2025

Walkthrough

The changes primarily introduce Huawei API integration into the application across both client and server. New environment variables and configuration options for Huawei have been added to the .env.template, server configuration, and Docker Compose setup. The API routing now includes a Huawei case with a dedicated handler in a new file, while the client API integrates a new HuaweiApi class. Enhancements also include updates to constants, localization files across multiple languages, UI settings, and store logic to validate Huawei API keys.

Changes

Files Change Summary
.env.template, app/config/server.ts, docker-compose.yml Added new Huawei-related environment variables and configuration options.
app/api/[provider]/.../route.ts, app/api/huawei.ts Extended API routing to include a new case for Huawei and implemented a dedicated Huawei API handler with authentication and request processing.
app/client/api.ts, app/client/platforms/huawei.ts Integrated HuaweiApi into the client with methods for chat, speech, and other interactions.
app/constant.ts Defined new Huawei constants, enum entries, and model listings to support Huawei integration.
app/components/settings.ts, app/store/access.ts Added Huawei-specific settings in the UI and updated store logic to include Huawei API key validation and default Huawei URL.
app/locales/{ar,bn,cn,cs,da,de,en,es,fr,id,it,jp,ko,no,pt,ru,sk,tr,tw,vi}.ts Added new Huawei sections with localized strings for API key, secret key, and endpoint configuration.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant R as API Router
    participant H as Huawei Handler
    participant A as Auth & Request
    participant E as Huawei API Endpoint

    C->>R: Send request (/api/huawei)
    R->>H: Route to Huawei handler
    H->>A: Check OPTIONS & authenticate
    A->>E: Forward API request with modified payload
    E-->>A: Return API response
    A-->>H: Return processed response
    H-->>R: Deliver final API response
    R-->>C: Respond to client
Loading

Poem

I hopped through lines of code so bright,
Adding Huawei keys with all my might.
From routes to endpoints, features bloom,
Localization sings, banishing gloom.
In fields of bytes, I leap and play,
Celebrating changes the rabbit way! 🐰✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (14)
app/config/server.ts (1)

91-94: Fix comment formatting for consistency.

There should be a space between "huawei" and "only" in the comment to match the style of other provider comments in the file.

-      //huaweionly
+      // huawei only
       HUAWEI_URL?: string;
       HUAWEI_API_KEY?: string;
app/api/huawei.ts (6)

94-97: Remove commented code

There's commented code for an alternative URL construction approach that should be removed to maintain code cleanliness.

-  // if(!baseUrl){
-  //     baseUrl = HUAWEI_BASE_URL
-  // }
-  // baseUrl = Huawei.ChatPath(modelName) || serverConfig.huaweiUrl || HUAWEI_BASE_URL;

138-162: Remove commented model filtering code

This block of commented code related to model filtering should be removed if not needed or implemented properly if the functionality is required.

-  // #1815 try to refuse some request to some models
-  // if (serverConfig.customModels) {
-  //     try {
-  //         const jsonBody = JSON.parse(bodyText);  // 直接使用已解析的 body
-  //
-  //
-  //         if (
-  //             isModelNotavailableInServer(
-  //                 serverConfig.customModels,
-  //                 jsonBody?.model as string,
-  //                 ServiceProvider.Huawei as string,
-  //             )
-  //         ) {
-  //             return NextResponse.json(
-  //                 {
-  //                     error: true,
-  //                     message: `you are not allowed to use ${jsonBody?.model} model`,
-  //                 },
-  //                 {
-  //                     status: 403,
-  //                 },
-  //             );
-  //         }
-  //     } catch (e) {
-  //         console.error(`[Huawei] filter`, e);
-  //     }
-  // }

47-74: Consider refactoring endpoint mapping to a constant object

The current implementation uses a series of if statements to map model names to endpoints. Consider refactoring this to a constant object mapping for better maintainability.

-  // 先用原始 modelName 获取 charUrl
+  // First get charUrl using the original modelName
   let baseUrl: string;
   let endpoint = "";
-  if (modelName === "DeepSeek-R1-671B-32K") {
-    endpoint = "952e4f88-ef93-4398-ae8d-af37f63f0d8e";
-  }
-  if (modelName === "DeepSeek-V3-671B-32K") {
-    endpoint = "fd53915b-8935-48fe-be70-449d76c0fc87";
-  }
-  if (modelName === "DeepSeek-R1-671B-8K") {
-    endpoint = "861b6827-e5ef-4fa6-90d2-5fd1b2975882";
-  }
-  if (modelName === "DeepSeek-V3-671B-8K") {
-    endpoint = "707c01c8-517c-46ca-827a-d0b21c71b074";
-  }
-  if (modelName === "DeepSeek-V3-671B-4K") {
-    endpoint = "f354eacc-a2c5-43b4-a785-e5aadca988b3";
-  }
-  if (modelName === "DeepSeek-R1-671B-4K") {
-    endpoint = "c3cfa9e2-40c9-485f-a747-caae405296ef";
-  }
+  const MODEL_ENDPOINTS = {
+    "DeepSeek-R1-671B-32K": "952e4f88-ef93-4398-ae8d-af37f63f0d8e",
+    "DeepSeek-V3-671B-32K": "fd53915b-8935-48fe-be70-449d76c0fc87",
+    "DeepSeek-R1-671B-8K": "861b6827-e5ef-4fa6-90d2-5fd1b2975882",
+    "DeepSeek-V3-671B-8K": "707c01c8-517c-46ca-827a-d0b21c71b074",
+    "DeepSeek-V3-671B-4K": "f354eacc-a2c5-43b4-a785-e5aadca988b3",
+    "DeepSeek-R1-671B-4K": "c3cfa9e2-40c9-485f-a747-caae405296ef"
+  };
+  
+  endpoint = MODEL_ENDPOINTS[modelName] || "";

76-92: Translate Chinese comments to English

For better international collaboration, consider translating Chinese comments to English.

-  // 处理请求体:1. 移除 system role 消息 2. 修改 model 名称格式
+  // Process request body: 1. Remove system role messages 2. Modify model name format

72-72: Translate Chinese comments to English

For better international collaboration, consider translating Chinese comments to English.

-    .replace(/(?<!:)\/+/g, "/"); // 只替换不在 :// 后面的多个斜杠
+    .replace(/(?<!:)\/+/g, "/"); // Only replace multiple slashes not immediately following ://

113-117: Add comment for the timeout duration

The 10-minute timeout is quite long. Consider adding a comment explaining why this duration was chosen.

  const timeoutId = setTimeout(
    () => {
      controller.abort();
    },
-    10 * 60 * 1000,
+    10 * 60 * 1000, // 10 minutes timeout for long-running completions
  );
app/client/platforms/huawei.ts (5)

24-36: Interface looks good, but consider validation.
The interface is well-structured for Huawei requests. However, you may want to sanitize or validate potentially optional fields (e.g., max_tokens) to ensure robustness.


38-62: Use the URL API for safer path concatenation.
Manually manipulating strings for URL construction can lead to subtle errors if path or baseUrl contain leading/trailing slashes or query parameters. Consider a more robust approach using the URL constructor:

- return [baseUrl, path].join("/");
+ const url = new URL(path, baseUrl);
+ return url.toString();

64-66: Typed response parsing recommended.
This function relies on the choices array. Using a typed response instead of any helps prevent errors if the API response format changes.


68-70: Implement or remove unimplemented speech method.
Currently, the method is a placeholder and throws an error. Either remove it if not required or implement the required functionality.


190-200: Usage and model listing are not implemented.
Returning dummy usage data and an empty model list is fine for now. If usage tracking and model enumeration become necessary, expand these methods accordingly.

docker-compose.yml (2)

20-53: Centralize or secure API credentials.
The addition of multiple API keys and URLs improves flexibility, but storing secrets in environment variables can risk exposure if logs or environment files are shared. Consider a more secure manager for secrets, such as HashiCorp Vault or a dedicated secrets manager service, and document each variable’s intended usage.


73-106: Mirror environment variables in the proxy container carefully.
As with the main container, check whether all these API keys are strictly necessary in the proxy. Reducing the scope of variables in sensitive contexts helps minimize the risk of leakage.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f7cde17 and 334fff6.

📒 Files selected for processing (30)
  • .env.template (1 hunks)
  • app/api/[provider]/[...path]/route.ts (2 hunks)
  • app/api/huawei.ts (1 hunks)
  • app/client/api.ts (7 hunks)
  • app/client/platforms/huawei.ts (1 hunks)
  • app/components/settings.tsx (3 hunks)
  • app/config/server.ts (3 hunks)
  • app/constant.ts (8 hunks)
  • app/locales/ar.ts (1 hunks)
  • app/locales/bn.ts (1 hunks)
  • app/locales/cn.ts (1 hunks)
  • app/locales/cs.ts (1 hunks)
  • app/locales/da.ts (1 hunks)
  • app/locales/de.ts (1 hunks)
  • app/locales/en.ts (1 hunks)
  • app/locales/es.ts (1 hunks)
  • app/locales/fr.ts (1 hunks)
  • app/locales/id.ts (1 hunks)
  • app/locales/it.ts (1 hunks)
  • app/locales/jp.ts (1 hunks)
  • app/locales/ko.ts (1 hunks)
  • app/locales/no.ts (1 hunks)
  • app/locales/pt.ts (1 hunks)
  • app/locales/ru.ts (1 hunks)
  • app/locales/sk.ts (1 hunks)
  • app/locales/tr.ts (1 hunks)
  • app/locales/tw.ts (1 hunks)
  • app/locales/vi.ts (1 hunks)
  • app/store/access.ts (5 hunks)
  • docker-compose.yml (2 hunks)
🔇 Additional comments (43)
.env.template (1)

84-87: New environment variables added for Huawei Cloud integration.

These new environment variables allow users to configure the Huawei Cloud DeepSeek API endpoint and authentication key, consistent with how other service providers are configured in the application.

app/api/[provider]/[...path]/route.ts (2)

18-18: Handler import for Huawei API implemented correctly.

The import follows the established pattern used for other API providers in the file.


56-57: Properly integrated routing handler for Huawei API.

The new case correctly integrates the Huawei API handler into the existing routing logic, following the same pattern used for other service providers.

app/components/settings.tsx (3)

78-78: Huawei constant imported correctly.

The import is appropriately added to the existing list of service provider constants.


1461-1500: Huawei configuration component implemented consistently.

The huaweiConfigComponent follows the same structure and patterns as other provider configuration components in the file, with proper input fields for URL and API key tied to the accessStore.

The component correctly applies localization using the Locale object and properly handles onChange events to update the store.


1866-1866: Huawei configuration component correctly included in the settings UI.

The component is properly integrated into the conditional rendering logic alongside other service provider configurations.

app/store/access.ts (5)

20-20: HUAWEI_BASE_URL constant imported correctly.

The import is properly added to the list of base URL constants from the application constants.


59-59: DEFAULT_HUAWEI_URL constant defined correctly.

The constant properly follows the pattern used for other service providers, conditionally using either the base URL or API path based on the build mode.


137-139: Huawei configuration added to DEFAULT_ACCESS_STATE.

The state properties for Huawei URL and API key are correctly added to the default state, maintaining consistent structure with other provider configurations.


228-230: isValidHuawei validation method implemented correctly.

The method properly checks if the required Huawei API key is present, following the same pattern as other validation methods.


250-250: Huawei validation integrated into isAuthorized method.

The Huawei validation is correctly added to the authorization check, ensuring users can authenticate with Huawei credentials.

app/locales/cn.ts (1)

541-556: Huawei integration looks good!

The implementation of the Huawei configuration section follows the same pattern as other API providers in the file. The localization strings are properly formatted in Chinese with appropriate titles, subtitles, and placeholders.

app/config/server.ts (2)

170-170: LGTM!

The implementation of the isHuawei flag follows the same pattern as other API providers.


241-244: LGTM!

The Huawei configuration export is implemented correctly, using the same pattern as other providers and the getApiKey utility for proper key handling.

app/locales/tw.ts (1)

389-404: LGTM!

The Huawei configuration is properly localized in Traditional Chinese, following the same structure as other API providers in the file. All required fields (Title, SubTitle, Placeholder) are included.

app/locales/ru.ts (1)

434-449: LGTM!

The Huawei configuration is correctly localized in Russian, adhering to the same structure as other providers. All required fields (Title, SubTitle, Placeholder) are properly translated.

app/locales/jp.ts (1)

427-442: Huawei localization additions look good!

The added Huawei API configuration localization strings for Japanese follow the consistent pattern used for other API providers. The translations are appropriate and maintain the styling conventions.

app/locales/tr.ts (1)

434-449: Huawei localization strings correctly implemented in Turkish.

The added Huawei API configuration section follows the same structure as other providers and includes all necessary fields (ApiKey, SecretKey, Endpoint) with appropriate translations.

app/locales/no.ts (1)

436-451: Norwegian Huawei localization strings are properly formatted.

The implementation of the Huawei configuration strings in Norwegian is consistent with other API provider sections and includes all the necessary translation keys. The text content appears to be appropriately localized.

app/locales/ar.ts (1)

423-438: Arabic Huawei localization correctly implemented with proper RTL support.

The Huawei API configuration section has been properly added to the Arabic localization file with appropriate translations. The structure matches other API providers and will integrate well with the existing UI.

app/locales/bn.ts (1)

431-446: Huawei localization support successfully implemented.

The addition of Huawei localization strings in Bengali follows the established pattern for other providers and includes all necessary elements (ApiKey, SecretKey, and Endpoint) with appropriate translations.

app/locales/da.ts (1)

501-516: Huawei localization entries properly implemented in Danish.

The Huawei localization section is correctly structured with consistent formatting and appropriate Danish translations for API Key, Secret Key, and Endpoint configurations.

app/locales/id.ts (1)

431-446: Huawei localization strings added with correct Indonesian translations.

The added Huawei section maintains consistent structure with other service providers and includes proper Indonesian translations for the configuration options.

app/locales/en.ts (1)

525-540: English localization for Huawei integration correctly implemented.

The Huawei section follows the established pattern for service providers with appropriate English text for API Key, Secret Key, and Endpoint configuration entries. This serves as a good reference template for other language files.

app/locales/pt.ts (1)

366-381: LGTM! The Huawei localization section for Portuguese looks good.

The implementation includes all necessary localization keys for the Huawei integration with proper translations for API key, secret key, and endpoint configurations. The structure matches the existing pattern used for other providers in the codebase.

app/locales/es.ts (1)

444-459: LGTM! The Huawei localization for Spanish is properly implemented.

The Spanish translations for the Huawei API integration follow the same structure as the other language files, with appropriate translations for the API key, secret key, and endpoint address. All required fields are correctly included.

app/locales/it.ts (1)

444-459: LGTM! The Italian localization for Huawei is consistent with other languages.

The Italian localization properly includes all necessary translations for the Huawei integration, following the established pattern for provider configurations. The translations are appropriate and match the intended functionality.

app/locales/de.ts (1)

442-457: LGTM! The German localization for Huawei integration is correctly implemented.

The German translations for the Huawei configuration section are properly structured and follow the same pattern as the other language files. The formal style used ("Verwenden Sie") is consistent with the rest of the German localization file.

app/locales/fr.ts (1)

443-459: LGTM - Huawei provider localization strings added

The French localization strings for the Huawei provider are properly implemented, consistent with the translation patterns of other providers in the file, with appropriate Title, SubTitle, and Placeholder values.

app/locales/vi.ts (1)

430-445: LGTM - Huawei provider localization for Vietnamese added

The Vietnamese localization for the Huawei provider follows the same structure as other provider translations in the file, with proper Title, SubTitle, and Placeholder values.

app/client/api.ts (6)

27-27: LGTM - HuaweiApi import added

The import statement for the HuaweiApi is correctly added, consistent with how other API providers are imported.


177-179: LGTM - Huawei case in ClientApi constructor

Proper handling of the ModelProvider.Huawei case has been added to initialize a new HuaweiApi instance.


272-272: LGTM - isHuawei variable for provider check

The isHuawei boolean variable is correctly defined to check if the current model provider is Huawei.


298-300: LGTM - apiKey handling for Huawei provider

The conditional logic for setting the apiKey for Huawei provider is correctly implemented.


314-314: LGTM - isHuawei included in return object

The isHuawei flag is correctly included in the return object of the getConfig function.


394-395: LGTM - Huawei case in getClientApi function

The getClientApi function has been properly updated to handle the ServiceProvider.Huawei case.

app/locales/ko.ts (1)

424-439: LGTM - Huawei provider localization for Korean added

The Korean localization strings for the Huawei provider have been properly implemented, with appropriate translations for Title, SubTitle, and Placeholder fields.

app/locales/cs.ts (1)

430-445: Localization additions for Huawei API look good

The localization for the Huawei API settings maintains consistent structure with other provider sections, including appropriate translations for API Key, Secret Key, and Endpoint fields.

app/locales/sk.ts (1)

366-381: Slovak localization for Huawei is correctly implemented

The Slovak translations for the Huawei API integration maintain consistency with other provider sections and follow the same pattern as in other language files.

app/api/huawei.ts (1)

83-84: Note on model name transformation

The code filters out system role messages and transforms the model name to only retain "DeepSeek-R1" or "DeepSeek-V3". Ensure this behavior is documented as it may not be obvious to future maintainers.

    messages: body.messages
      .map((msg: any) => ({
        role: msg.role,
        content: msg.content,
      }))
      .filter((msg: any) => msg.role !== "system"),
-    model: modelName.replace(/^(DeepSeek-(?:R1|V3)).*$/, "$1"), // 只保留 DeepSeek-R1 或 DeepSeek-V3
+    model: modelName.replace(/^(DeepSeek-(?:R1|V3)).*$/, "$1"), // Only keep DeepSeek-R1 or DeepSeek-V3 prefix
app/constant.ts (2)

668-682: Good model documentation with URLs

The addition of model endpoints in comments provides helpful reference for developers working with these endpoints in the future.


579-583:

❓ Verification inconclusive

ByteDance models array includes DeepSeek models

DeepSeek models appear to be added to the bytedanceModels array. Is this intentional? DeepSeek and ByteDance seem to be separate entities, and these models are also being implemented via Huawei. Consider whether these should be in a separate array.


🏁 Script executed:

#!/bin/bash
# Check if DeepSeek models appear in both ByteDance and Huawei implementations

echo "Checking DeepSeek model implementations..."
rg -A 5 -B 5 "deepseek" app/constant.ts

Length of output: 3124


DeepSeek Models in ByteDance Configuration – Clarification Needed

It appears that in app/constant.ts the following DeepSeek model entries are included in what seems to be the ByteDance models list:

  • "deepseek-r1-250120"
  • "deepseek-v3-241226"
  • "deepseek-r1-distill-qwen-7b-250120"
  • "deepseek-r1-distill-qwen-32b-250120"

Since there is also a dedicated deepseekModels array (and DeepSeek models are being mapped under Huawei as well), please verify whether including these in the ByteDance configuration is intentional. If not, consider moving them to a more appropriate grouping to clearly separate DeepSeek from ByteDance.

app/client/platforms/huawei.ts (1)

1-2: No concerns: file initialization is correct.
Everything looks good. Using "use client" is appropriate for Next.js client components.

@@ -332,6 +340,7 @@ export function getHeaders(ignoreHeaders: boolean = false) {
isXAI,
isChatGLM,
isSiliconFlow,
isHuawei: boolean,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix type annotation syntax

There's a syntax issue with the variable declaration. The "boolean" after the variable name needs to be corrected.

Apply this fix:

-    isHuawei: boolean,
+    isHuawei,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isHuawei: boolean,
isHuawei,

provider: {
id: "huawei",
providerName: "Huawei",
providerType: "Huawei",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix inconsistent provider type capitalization

The providerType for Huawei is capitalized while other providers use lowercase. This inconsistency could lead to bugs if code elsewhere expects lowercase provider types.

-      providerType: "Huawei",
+      providerType: "huawei",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
providerType: "Huawei",
providerType: "huawei",

Comment on lines +114 to +176
if (shouldStream) {
const [tools, funcs] = usePluginStore
.getState()
.getAsTools(
useChatStore.getState().currentSession().mask?.plugin || [],
);

return streamWithThink(
chatPath,
requestPayload,
getHeaders(),
tools as any[],
funcs,
controller,
// parseSSE
(text: string, runTools: ChatMessageTool[]) => {
const json = JSON.parse(text);
const choices = json.choices as Array<{
delta: {
content: string;
tool_calls: ChatMessageTool[];
};
}>;
const tool_calls = choices[0]?.delta?.tool_calls;
if (tool_calls?.length > 0) {
const index = tool_calls[0]?.index;
const id = tool_calls[0]?.id;
const args = tool_calls[0]?.function?.arguments;
if (id) {
runTools.push({
id,
type: tool_calls[0]?.type,
function: {
name: tool_calls[0]?.function?.name as string,
arguments: args,
},
});
} else {
// @ts-ignore
runTools[index]["function"]["arguments"] += args;
}
}
return {
isThinking: false,
content: choices[0]?.delta?.content || "",
};
},
// processToolMessage
(
payload: RequestPayloadForHuawei,
toolCallMessage: any,
toolCallResult: any[],
) => {
payload?.messages?.splice(
payload?.messages?.length,
0,
toolCallMessage,
...toolCallResult,
);
},
options,
);
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Clear the timeout in streaming scenarios.
When shouldStream is true, the setTimeout is not cleared, causing a potential abort even after streaming completes. Safely handle the timeout in a try/finally block to avoid terminating ongoing sessions.

- if (shouldStream) {
-   return streamWithThink( ... ); // no clearTimeout
- } else {
+ let result;
+ if (shouldStream) {
+   try {
+     result = await streamWithThink(...);
+   } finally {
+     clearTimeout(requestTimeoutId);
+   }
+ } else {
    const res = await fetch(chatPath, chatPayload);
    clearTimeout(requestTimeoutId);
    ...
  }
  return result;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (shouldStream) {
const [tools, funcs] = usePluginStore
.getState()
.getAsTools(
useChatStore.getState().currentSession().mask?.plugin || [],
);
return streamWithThink(
chatPath,
requestPayload,
getHeaders(),
tools as any[],
funcs,
controller,
// parseSSE
(text: string, runTools: ChatMessageTool[]) => {
const json = JSON.parse(text);
const choices = json.choices as Array<{
delta: {
content: string;
tool_calls: ChatMessageTool[];
};
}>;
const tool_calls = choices[0]?.delta?.tool_calls;
if (tool_calls?.length > 0) {
const index = tool_calls[0]?.index;
const id = tool_calls[0]?.id;
const args = tool_calls[0]?.function?.arguments;
if (id) {
runTools.push({
id,
type: tool_calls[0]?.type,
function: {
name: tool_calls[0]?.function?.name as string,
arguments: args,
},
});
} else {
// @ts-ignore
runTools[index]["function"]["arguments"] += args;
}
}
return {
isThinking: false,
content: choices[0]?.delta?.content || "",
};
},
// processToolMessage
(
payload: RequestPayloadForHuawei,
toolCallMessage: any,
toolCallResult: any[],
) => {
payload?.messages?.splice(
payload?.messages?.length,
0,
toolCallMessage,
...toolCallResult,
);
},
options,
);
} else {
let result;
if (shouldStream) {
const [tools, funcs] = usePluginStore
.getState()
.getAsTools(
useChatStore.getState().currentSession().mask?.plugin || [],
);
try {
result = await streamWithThink(
chatPath,
requestPayload,
getHeaders(),
tools as any[],
funcs,
controller,
// parseSSE
(text: string, runTools: ChatMessageTool[]) => {
const json = JSON.parse(text);
const choices = json.choices as Array<{
delta: {
content: string;
tool_calls: ChatMessageTool[];
};
}>;
const tool_calls = choices[0]?.delta?.tool_calls;
if (tool_calls?.length > 0) {
const index = tool_calls[0]?.index;
const id = tool_calls[0]?.id;
const args = tool_calls[0]?.function?.arguments;
if (id) {
runTools.push({
id,
type: tool_calls[0]?.type,
function: {
name: tool_calls[0]?.function?.name as string,
arguments: args,
},
});
} else {
// @ts-ignore
runTools[index]["function"]["arguments"] += args;
}
}
return {
isThinking: false,
content: choices[0]?.delta?.content || "",
};
},
// processToolMessage
(
payload: RequestPayloadForHuawei,
toolCallMessage: any,
toolCallResult: any[],
) => {
payload?.messages?.splice(
payload?.messages?.length,
0,
toolCallMessage,
...toolCallResult,
);
},
options,
);
} finally {
clearTimeout(requestTimeoutId);
}
} else {
const res = await fetch(chatPath, chatPayload);
clearTimeout(requestTimeoutId);
result = res;
}
return result;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant