Skip to content

Conversation

@zerob13
Copy link
Collaborator

@zerob13 zerob13 commented Aug 11, 2025

增加 modelscope 为新的provider
支持了 modelscope 的 mcp 同步能力
完成 #615

Summary by CodeRabbit

  • New Features

    • ModelScope provider integration with API key verification and MCP server sync (bulk import, lookup, and sync result summary).
    • Floating chat window support with toggle/show/hide controls and floating-button right-click context menu.
  • UI

    • Settings UI for ModelScope MCP sync (pagination, filters, import results, errors) and new provider icon.
    • New scrollable popover component used in several menus.
  • Localization

    • Expanded translations for ModelScope and richer verification/error messages across many locales.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 11, 2025

Walkthrough

Adds ModelScope provider and MCP synchronization (provider entry, provider class, conversion, sync/import), UI and i18n for ModelScope MCP sync, batch MCP import/lookups on ConfigPresenter/McpConfHelper, floating-button right-click plus floating chat window/tab integration, and a new ScrollablePopover component.

Changes

Cohort / File(s) Summary
ConfigPresenter & MCP helper
src/main/presenter/configPresenter/index.ts, src/main/presenter/configPresenter/mcpConfHelper.ts
Expose batchImportMcpServers(...) and findMcpServerByPackage(...) on ConfigPresenter; add ExtendedMCPServerConfig, batchImportMcpServers(...), findServerByPackage(...), and private generateUniqueServerName(...) in McpConfHelper (duplicate block observed).
Provider registry & provider implementation
src/main/presenter/configPresenter/providers.ts, src/main/presenter/llmProviderPresenter/index.ts, src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts, src/renderer/src/components/icons/ModelIcon.vue
Add ModelScope entry to DEFAULT_PROVIDERS; register ModelscopeProvider in provider factory; add syncModelScopeMcpServers(...) to LLMProviderPresenter; implement ModelscopeProvider (OpenAI-compatible wrappers, key checks, syncMcpServers, convertMcpServerToConfig); add ModelScope icon mapping.
Renderer: ModelScope sync UI & i18n
src/renderer/src/components/settings/ModelProviderSettingsDetail.vue, src/renderer/src/components/settings/ModelScopeMcpSync.vue, src/renderer/src/i18n/.../settings.json
Render ModelScope MCP sync panel in provider settings; add ModelScopeMcpSync.vue with sync controls, results, errors, and loading states; add extensive ModelScope and verification i18n keys across multiple locales (en-US, fa-IR, fr-FR, ja-JP, ko-KR, ru-RU, zh-CN, zh-HK, zh-TW).
Shared presenter typings
src/shared/presenter.d.ts
Add ModelScopeMcpSyncOptions, ModelScopeMcpSyncResult; extend ILlmProviderPresenter with syncModelScopeMcpServers(...); add isApplicationQuitting() and floating window/tab registration typings.
Floating button / floating chat flow
src/preload/floating-preload.ts, src/renderer/floating/FloatingButton.vue, src/renderer/floating/env.d.ts, src/main/events.ts, src/main/presenter/floatingButtonPresenter/index.ts, src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
Add RIGHT_CLICKED event and onRightClick() IPC; FloatingButton handles contextmenu and invokes onRightClick; presenter handles RIGHT_CLICKED to show context menu (open main window, exit app); expose FloatingButtonWindow.getWindow().
Floating chat window & window/tab presenters
src/main/presenter/windowPresenter/FloatingChatWindow.ts, src/main/presenter/windowPresenter/index.ts, src/main/presenter/tabPresenter.ts
Add FloatingChatWindow class (create/show/hide/toggle/destroy/isShowing/getWindow); wire it into WindowPresenter with lifecycle/public APIs and message routing; add registerFloatingWindow(...) / unregisterFloatingWindow(...) in TabPresenter to represent floating window as a virtual tab.
Popover / UI wrapper components
src/renderer/src/components/ScrollablePopover.vue, src/renderer/src/components/NewThread.vue, src/renderer/src/components/TitleView.vue, src/renderer/src/components/ui/popover/PopoverContent.vue
Add ScrollablePopover.vue; replace Popover usage in NewThread and TitleView with ScrollablePopover (trigger slot + optional scrollable content); minor typing/formatting change in PopoverContent props.
Misc: UI, responsive, and small changes
src/renderer/src/components/mcp-config/components/McpToolPanel.vue, src/renderer/src/components/icons/..., i18n additions across locales
Responsive changes to McpToolPanel; icon asset import and mapping for modelscope; multiple i18n additions per locale (verification messages, operation lifecycle strings, ModelScope subtree).

Sequence Diagram(s)

sequenceDiagram
  participant UI as ModelScopeMcpSync.vue
  participant LPP as LLMProviderPresenter
  participant MSP as ModelscopeProvider
  participant MSAPI as ModelScope API
  participant CP as ConfigPresenter
  participant H as McpConfHelper

  UI->>LPP: syncModelScopeMcpServers(providerId, options)
  LPP->>MSP: syncMcpServers(options)
  MSP->>MSAPI: GET /mcp_servers (Authorization)
  MSAPI-->>MSP: mcp_server_list
  MSP-->>LPP: server list
  loop per server
    LPP->>MSP: convertMcpServerToConfig(server)
    LPP->>CP: batchImportMcpServers([configs], options) or addMcpServer checks
    CP->>H: delegate batchImportMcpServers(...)
    H-->>CP: { imported, skipped, errors }
  end
  LPP-->>UI: aggregated { imported, skipped, errors }
Loading
sequenceDiagram
  participant EXT as External caller
  participant CP as ConfigPresenter
  participant H as McpConfHelper

  EXT->>CP: batchImportMcpServers(servers, options)
  CP->>H: batchImportMcpServers(servers, options)
  H->>H: generateUniqueServerName / dedupe / add/update servers
  H-->>CP: { imported, skipped, errors }
  CP-->>EXT: result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • deepinfect

Poem

I nibble keys and hop through queues,
I fetch new scopes and sync the news.
Servers lined up, carrots in rows,
Imported some, the skipped ones froze.
A happy rabbit, code well-sown — hop on, let features grow! 🥕🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/add-modelscope-provider

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
  • 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 explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests 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: 9

🔭 Outside diff range comments (1)
src/shared/presenter.d.ts (1)

982-982: Fix the type annotation typo.

-  env: Record<string, unknow>
+  env: Record<string, unknown>
🧹 Nitpick comments (3)
src/renderer/src/components/settings/ModelScopeMcpSync.vue (1)

13-55: Use English for code comments per repo guideline.

New comments are Chinese; please convert to concise English.

Example:

  • "同步选项" -> "Sync options"
  • "额外选项" -> "Additional options"
  • "同步按钮和状态" -> "Sync action and status"
  • "错误信息显示" -> "Error messages"
  • "同步结果详情" -> "Sync result details"
src/main/presenter/llmProviderPresenter/index.ts (1)

1615-1742: Consider improving type safety instead of using any casts.

The implementation is functionally correct, but uses as any casts on lines 1649 and 1675 to access ModelscopeProvider-specific methods. Consider:

  1. Adding a type guard or interface to properly type the provider
  2. Or extending the BaseLLMProvider interface with optional MCP sync methods
-        const modelscopeProvider = provider as any
-        const mcpResponse = await modelscopeProvider.syncMcpServers(syncOptions)
+        // Type guard for ModelscopeProvider
+        if (!('syncMcpServers' in provider)) {
+          throw new Error('Provider does not support MCP synchronization')
+        }
+        const modelscopeProvider = provider as ModelscopeProvider
+        const mcpResponse = await modelscopeProvider.syncMcpServers(syncOptions)
src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1)

209-307: Simplify emoji selection array to reduce code bloat.

The emoji array contains 98 elements taking up nearly 100 lines. Consider a more concise approach.

-    // Generate random emoji for icon
-    const emojis = [
-      '🔧',
-      '⚡',
-      // ... 94 more lines
-      '🔖'
-    ]
+    // Generate random emoji for icon
+    const emojis = '🔧⚡🚀🔨⚙️🛠️🔥💡⭐🎯🎨🔮💎🎪🎭📱💻🖥️⌨️🖱️📡🔊📢📣📯🔔🔕📻📺📷📹🎥📽️🔍🔎💰💳💸💵🎲🃏🎮🕹️🎳🖌️🖍️📝✏️📏📐📌📍🗂️📂📁📰📄📃📜📋📊📈📉📦📫📪📬📭📮🗳️✉️📧📨📩📤📥🗄️🗃️📑🗞️🔖'.match(/./gu) || []
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d7a5953 and 1024a14.

📒 Files selected for processing (17)
  • src/main/presenter/configPresenter/index.ts (1 hunks)
  • src/main/presenter/configPresenter/mcpConfHelper.ts (2 hunks)
  • src/main/presenter/configPresenter/providers.ts (1 hunks)
  • src/main/presenter/llmProviderPresenter/index.ts (4 hunks)
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1 hunks)
  • src/renderer/src/components/icons/ModelIcon.vue (1 hunks)
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue (2 hunks)
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue (1 hunks)
  • src/renderer/src/i18n/en-US/settings.json (3 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (2 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (2 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (2 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (2 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (2 hunks)
  • src/shared/presenter.d.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (22)
src/renderer/src/**/*

📄 CodeRabbit Inference Engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/main/presenter/configPresenter/index.ts
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.

Files:

  • src/renderer/src/components/icons/ModelIcon.vue
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Strict type checking enabled for TypeScript

**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/main/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Main to Renderer: Use EventBus to broadcast events via mainWindow.webContents.send()

Use Electron's built-in APIs for file system and native dialogs

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/main/presenter/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

One presenter per functional domain

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/main/presenter/configPresenter/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Centralize configuration in configPresenter/

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/development-setup.mdc)

**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/{main,renderer}/**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

src/{main,renderer}/**/*.ts: Use context isolation for improved security
Implement proper inter-process communication (IPC) patterns
Optimize application startup time with lazy loading
Implement proper error handling and logging for debugging

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/main/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

主进程代码放在 src/main

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/main/presenter/configPresenter/providers.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Add provider configuration in configPresenter/providers.ts when adding a new LLM provider

Files:

  • src/main/presenter/configPresenter/providers.ts
src/main/presenter/llmProviderPresenter/index.ts

📄 CodeRabbit Inference Engine (.cursor/rules/llm-agent-loop.mdc)

src/main/presenter/llmProviderPresenter/index.ts: src/main/presenter/llmProviderPresenter/index.ts should manage the overall Agent loop, conversation history, tool execution via McpPresenter, and frontend communication via eventBus.
The main Agent loop in llmProviderPresenter/index.ts should handle multi-round LLM calls and tool usage, maintaining conversation state and controlling the loop with needContinueConversation and toolCallCount.
The main Agent loop should send standardized STREAM_EVENTS (RESPONSE, END, ERROR) to the frontend via eventBus.
The main Agent loop should buffer text content, handle tool call events, format tool results for the next LLM call, and manage conversation continuation logic.

Files:

  • src/main/presenter/llmProviderPresenter/index.ts
src/shared/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared types in src/shared/

Files:

  • src/shared/presenter.d.ts
src/shared/*.d.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

The shared/*.d.ts files are used to define the types of objects exposed by the main process to the renderer process

Files:

  • src/shared/presenter.d.ts
src/shared/**/*.{ts,tsx,d.ts}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

共享类型定义放在 shared 目录

Files:

  • src/shared/presenter.d.ts
src/main/presenter/llmProviderPresenter/providers/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/main/presenter/llmProviderPresenter/providers/*.ts: Create provider file in src/main/presenter/llmProviderPresenter/providers/ when adding a new LLM provider
Implement coreStream method following standardized event interface in LLM provider files

src/main/presenter/llmProviderPresenter/providers/*.ts: Each file in src/main/presenter/llmProviderPresenter/providers/*.ts should handle interaction with a specific LLM API, including request/response formatting, tool definition conversion, native/non-native tool call management, and standardizing output streams to a common event format.
Provider implementations must use a coreStream method that yields standardized stream events to decouple the main loop from provider-specific details.
The coreStream method in each Provider must perform a single streaming API request per conversation round and must not contain multi-round tool call loop logic.
Provider files should implement helper methods such as formatMessages, convertToProviderTools, parseFunctionCalls, and prepareFunctionCallPrompt as needed for provider-specific logic.
All provider implementations must parse provider-specific data chunks and yield standardized events for text, reasoning, tool calls, usage, errors, stop reasons, and image data.
When a provider does not support native function calling, it must prepare messages using prompt wrapping (e.g., prepareFunctionCallPrompt) before making the API call.
When a provider supports native function calling, MCP tools must be converted to the provider's format (e.g., using convertToProviderTools) and included in the API request.
Provider implementations should aggregate and yield usage events as part of the standardized stream.
Provider implementations should yield image data events in the standardized format when applicable.
Provider implementations should yield reasoning events in the standardized format when applicable.
Provider implementations should yield tool call events (`tool_call_star...

Files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/providers.ts : Add provider configuration in configPresenter/providers.ts when adding a new LLM provider
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Iconify/Vue for icon implementation.

Applied to files:

  • src/renderer/src/components/icons/ModelIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Import Icon component from Iconify/Vue.

Applied to files:

  • src/renderer/src/components/icons/ModelIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use the Icon component with lucide icons.

Applied to files:

  • src/renderer/src/components/icons/ModelIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Follow naming pattern: {collection}:{icon-name} for icons.

Applied to files:

  • src/renderer/src/components/icons/ModelIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : For cases where lucide icons don't meet requirements, use other Iconify collections as fallback.

Applied to files:

  • src/renderer/src/components/icons/ModelIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Prefer "lucide:" icon family as the primary choice.

Applied to files:

  • src/renderer/src/components/icons/ModelIcon.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/mcpPresenter/inMemoryServers/*.ts : Implement new MCP tool in src/main/presenter/mcpPresenter/inMemoryServers/ when adding a new MCP tool

Applied to files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/mcpPresenter/index.ts : Register new MCP tool in mcpPresenter/index.ts

Applied to files:

  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Vue 3 with TypeScript, leveraging defineComponent and PropType.

Applied to files:

  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/providers.ts : Add provider configuration in configPresenter/providers.ts when adding a new LLM provider

Applied to files:

  • src/main/presenter/configPresenter/providers.ts
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : `src/main/presenter/llmProviderPresenter/index.ts` should manage the overall Agent loop, conversation history, tool execution via `McpPresenter`, and frontend communication via `eventBus`.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : When a provider supports native function calling, MCP tools must be converted to the provider's format (e.g., using `convertToProviderTools`) and included in the API request.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Create provider file in src/main/presenter/llmProviderPresenter/providers/ when adding a new LLM provider

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each file in `src/main/presenter/llmProviderPresenter/providers/*.ts` should handle interaction with a specific LLM API, including request/response formatting, tool definition conversion, native/non-native tool call management, and standardizing output streams to a common event format.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Implement coreStream method following standardized event interface in LLM provider files

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Provider implementations should yield events asynchronously using the async generator pattern.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Provider files should implement helper methods such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt` as needed for provider-specific logic.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : The main Agent loop should buffer text content, handle tool call events, format tool results for the next LLM call, and manage conversation continuation logic.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : All provider implementations must parse provider-specific data chunks and yield standardized events for text, reasoning, tool calls, usage, errors, stop reasons, and image data.

Applied to files:

  • src/main/presenter/llmProviderPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
🧬 Code Graph Analysis (3)
src/main/presenter/llmProviderPresenter/index.ts (2)
src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1)
  • ModelscopeProvider (41-340)
src/shared/presenter.d.ts (2)
  • ModelScopeMcpSyncOptions (529-535)
  • ModelScopeMcpSyncResult (538-542)
src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (2)
src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts (1)
  • OpenAICompatibleProvider (68-1356)
src/shared/presenter.d.ts (4)
  • LLM_PROVIDER (491-511)
  • ChatMessage (1225-1237)
  • LLMResponse (824-841)
  • KeyStatus (1314-1320)
src/main/presenter/configPresenter/mcpConfHelper.ts (2)
src/shared/presenter.d.ts (1)
  • MCPServerConfig (979-991)
src/main/eventbus.ts (1)
  • eventBus (151-151)
🔇 Additional comments (24)
src/renderer/src/components/icons/ModelIcon.vue (1)

60-60: LGTM!

The ModelScope icon integration follows the existing pattern correctly.

Also applies to: 63-63

src/shared/presenter.d.ts (2)

528-543: LGTM!

The new ModelScope MCP sync interfaces are well-structured and follow TypeScript conventions.


613-617: Method signature looks good.

The new syncModelScopeMcpServers method follows the interface's async pattern correctly.

src/renderer/src/i18n/en-US/settings.json (3)

269-272: LGTM!

The new verification error messages provide clear feedback for different failure scenarios.


357-408: Comprehensive i18n coverage for ModelScope.

The ModelScope translations are well-organized and cover all aspects of the MCP sync feature including UI labels, status messages, and error handling.


433-438: LGTM!

The general provider operation messages provide consistent feedback across all provider operations.

src/renderer/src/i18n/ru-RU/settings.json (3)

269-271: LGTM!

The Russian translations for verification errors are consistent with other languages.


431-431: Check the Russian translation for ModelScope name.

The translation "Моделикоп" appears to be incorrect. Consider using either "ModelScope" (keeping the English brand name) or a proper transliteration like "МоделСкоуп".


384-430: Russian translations are comprehensive.

The ModelScope MCP sync translations cover all necessary UI elements and messages.

Also applies to: 432-439

src/main/presenter/configPresenter/mcpConfHelper.ts (4)

29-44: Well-structured interface for extended MCP configuration.

The ExtendedMCPServerConfig interface properly extends the base configuration with ModelScope-specific fields.


644-744: Robust batch import implementation with good error handling.

The batchImportMcpServers method provides:

  • Proper validation and duplicate detection
  • Flexible import options (skip/overwrite)
  • Comprehensive error handling and logging
  • Event emission for UI updates

The implementation follows best practices for async operations and error management.


752-776: Smart unique name generation.

The generateUniqueServerName method properly handles package name sanitization and conflict resolution with numeric suffixes.


783-794: Useful utility method for package lookup.

The findServerByPackage method provides an efficient way to check for existing servers by package name.

src/renderer/src/i18n/zh-CN/settings.json (3)

250-256: Bold, concise provider toasts look good.

Keys are consistent with existing patterns; no issues.


260-312: ModelScope block is comprehensive and aligns with UI usage.

All keys required by ModelScopeMcpSync are present and consistently named.


333-337: Verify dialog additions are appropriate.

The new error states complete the status surface; good to ship.

src/renderer/src/i18n/ko-KR/settings.json (1)

268-272: Verify dialog messages added correctly.

Wording is acceptable and keys mirror other locales.

src/renderer/src/i18n/fa-IR/settings.json (1)

269-273: OAuth verify error keys added correctly.

No issues with key naming.

src/renderer/src/i18n/ja-JP/settings.json (1)

269-273: Verify dialog error keys are fine.

Wording and keys consistent with other locales.

src/renderer/src/i18n/fr-FR/settings.json (1)

269-273: Verify dialog error keys added correctly.

Good parity with other locales.

src/main/presenter/configPresenter/providers.ts (1)

567-580: New provider entry looks correct and aligns with prior learning to register providers here.

id matches UI checks ('modelscope'), and defaultBaseUrl/baseUrl are consistent.

src/main/presenter/configPresenter/index.ts (1)

1170-1196: LGTM! Clean delegation pattern for MCP server management.

The new methods properly delegate to mcpConfHelper and maintain consistency with the existing ConfigPresenter API design.

src/main/presenter/llmProviderPresenter/index.ts (1)

173-175: Provider registration looks good.

The ModelscopeProvider is correctly registered in the factory method following the existing pattern.

src/renderer/src/i18n/zh-HK/settings.json (1)

268-439: Well-structured i18n additions for ModelScope provider.

The translations are comprehensive, properly nested, and follow the existing naming conventions. All user-facing strings for the ModelScope MCP sync feature are appropriately localized.

@zerob13
Copy link
Collaborator Author

zerob13 commented Aug 11, 2025

#615

@zerob13 zerob13 changed the title feat: add mcp sync and modelscope provider feat: add mcp sync and modelscope provider #615 Aug 11, 2025
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: 9

🔭 Outside diff range comments (1)
src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts (1)

57-64: Security: webSecurity disabled and sandbox off (unconditional)

webSecurity: false and sandbox: false are set unconditionally. This weakens renderer isolation. Gate these by environment and prefer sandbox: true with contextIsolation: true. Only relax in dev if strictly necessary.

Apply this diff:

-        webPreferences: {
-          nodeIntegration: false,
-          contextIsolation: true,
-          preload: path.join(__dirname, '../preload/floating.mjs'),
-          webSecurity: false, // 开发模式下允许跨域
-          devTools: isDev, // 开发模式下启用开发者工具
-          sandbox: false // 禁用沙盒模式,确保预加载脚本能正常工作
-        }
+        webPreferences: {
+          nodeIntegration: false,
+          contextIsolation: true,
+          preload: path.join(__dirname, '../preload/floating.mjs'),
+          webSecurity: !isDev, // Allow cross-origin only in development
+          devTools: isDev,
+          sandbox: true // Keep sandbox on; preload works with contextIsolation + sandbox
+        }

If you have known blockers with sandbox: true, document them and narrowly scope any exceptions.

♻️ Duplicate comments (1)
src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1)

157-164: Timeout addition for MCP fetch is addressed — thanks

A fetch timeout via AbortSignal.timeout(30000) prevents hangs on bad networks. This resolves the prior feedback.

🧹 Nitpick comments (18)
src/renderer/src/components/NewThread.vue (1)

74-86: Add accessibility labels to the icon-only settings button

Provide an i18n-backed aria-label and proper popup semantics.

Apply this diff:

-                <Button
+                <Button
                   class="w-7 h-full rounded-none border-none shadow-none transition-all duration-300"
                   :class="{
                     'w-0 opacity-0 p-0 overflow-hidden': !showSettingsButton && !isHovering,
                     'w-7 opacity-100': showSettingsButton || isHovering
                   }"
                   size="icon"
                   variant="outline"
+                  :aria-label="t('common.settings')"
+                  aria-haspopup="dialog"
+                  :aria-expanded="settingsPopoverOpen"
                 >
src/renderer/src/components/TitleView.vue (1)

46-51: Add accessibility labels to the icon-only settings button

Add an i18n-backed aria-label and popup semantics.

Apply this diff:

-      <ScrollablePopover align="end" content-class="w-80" :enable-scrollable="true">
+      <ScrollablePopover align="end" content-class="w-80" :enable-scrollable="true">
         <template #trigger>
-          <Button class="w-7 h-7 rounded-md" size="icon" variant="outline">
+          <Button
+            class="w-7 h-7 rounded-md"
+            size="icon"
+            variant="outline"
+            :aria-label="t('common.settings')"
+            aria-haspopup="dialog"
+          >
             <Icon icon="lucide:settings-2" class="w-4 h-4" />
           </Button>
         </template>
src/renderer/src/components/ScrollablePopover.vue (1)

1-34: Forward content-specific attrs and explicitly bridge v-model for robustness

Current $attrs are forwarded only to Popover, which prevents passing PopoverContent-specific props (e.g., side, sideOffset, avoidCollisions) from callers. Also, relying implicitly on $attrs for v-model:open works but lacks type-safety.

Consider this contained refactor:

  • Disable automatic fallthrough to avoid ambiguity.
  • Split attributes between Popover (open / onUpdate:open) and PopoverContent (everything else).
  • Explicitly bridge update:open to preserve v-model behavior.

Apply this diff:

 <template>
-  <Popover v-bind="$attrs">
+  <Popover v-bind="popoverAttrs">
     <PopoverTrigger as-child>
       <slot name="trigger" />
     </PopoverTrigger>
-    <PopoverContent
-      :align="align"
-      :class="cn('p-0', contentClass, enableScrollable && 'max-h-96 overflow-hidden')"
-    >
+    <PopoverContent
+      v-bind="contentAttrs"
+      :align="align"
+      :class="cn('p-0', contentClass, enableScrollable && 'max-h-96 overflow-hidden')"
+    >
       <div v-if="enableScrollable" class="max-h-96 overflow-y-auto">
         <slot />
       </div>
       <slot v-else />
     </PopoverContent>
   </Popover>
 </template>

 <script setup lang="ts">
-import type { HTMLAttributes } from 'vue'
+import type { HTMLAttributes } from 'vue'
+import { useAttrs, computed } from 'vue'
 import { cn } from '@/lib/utils'
 import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
 
+defineOptions({ inheritAttrs: false })
+
 interface ScrollablePopoverProps {
   align?: 'start' | 'center' | 'end'
   enableScrollable?: boolean
   contentClass?: HTMLAttributes['class']
 }
 
-withDefaults(defineProps<ScrollablePopoverProps>(), {
+const props = withDefaults(defineProps<ScrollablePopoverProps>(), {
   align: 'center',
   enableScrollable: false,
   contentClass: ''
 })
+
+// Split $attrs between Popover (model handling) and PopoverContent (positioning/behavior)
+const rawAttrs = useAttrs() as Record<string, any>
+const popoverAttrs = computed(() => {
+  const out: Record<string, any> = {}
+  if (rawAttrs.open !== undefined) out.open = rawAttrs.open
+  if (rawAttrs['onUpdate:open']) out['onUpdate:open'] = rawAttrs['onUpdate:open']
+  return out
+})
+const contentAttrs = computed(() => {
+  const rest: Record<string, any> = {}
+  for (const key in rawAttrs) {
+    if (key !== 'open' && key !== 'onUpdate:open') rest[key] = rawAttrs[key]
+  }
+  return rest
+})
 </script>
src/renderer/src/i18n/en-US/settings.json (2)

357-409: Polish phrasing for clarity and consistency

A few labels read awkwardly in English. Suggested refinements:

-        "operationalServers": "Operating a server",
+        "operationalServers": "Operational Servers",
-        "onlyHosted": "Hosting services only",
+        "onlyHosted": "Hosted services only",
-        "pageNumber": "page number",
+        "pageNumber": "Page Number",
-        "pageNumberPlaceholder": "Please enter the page number",
+        "pageNumberPlaceholder": "Enter page number",
-        "syncComplete": "Synchronous completion",
+        "syncComplete": "Sync complete",
-      "baseUrl": "API Address",
+      "baseUrl": "API Base URL",
-      "verifySuccess": "Verification is successful"
+      "verifySuccess": "Verification successful"

433-439: Tighten toast wording

Shorter, conventional phrasing reads better in toasts.

-    "configurationSaved": "Configuration saved",
-    "configurationUpdated": "Configuration updated",
-    "dataRefreshed": "Data has been refreshed",
-    "operationFailed": "Operation failed",
-    "operationSuccess": "Operation is successful",
-    "settingsApplied": "Settings applied"
+    "configurationSaved": "Configuration saved",
+    "configurationUpdated": "Configuration updated",
+    "dataRefreshed": "Data refreshed",
+    "operationFailed": "Operation failed",
+    "operationSuccess": "Operation successful",
+    "settingsApplied": "Settings applied"
src/renderer/src/i18n/zh-TW/settings.json (2)

269-273: 用詞本地化一致性(繁體中文)

將「連接/網絡/地址/API Key」統一為繁體慣用詞「連線/網路/位址/API 金鑰」。

-        "successDesc": "API 金鑰和設定驗證成功,可以正常使用",
-        "connectionError": "連接錯誤,請檢查網絡連接和 API 地址",
-        "serverError": "服務器錯誤,請稍後重試",
-        "unauthorized": "認證失敗,API Key 無效或已過期"
+        "successDesc": "API 金鑰和設定驗證成功,可以正常使用",
+        "connectionError": "連線錯誤,請檢查網路連線與 API 位址",
+        "serverError": "伺服器錯誤,請稍後重試",
+        "unauthorized": "認證失敗,API 金鑰無效或已過期"

434-440: Provider 通用訊息用語(繁中)

建議改為台灣常用詞與自然表述。

-    "configurationSaved": "配置已保存",
-    "configurationUpdated": "配置已更新",
-    "dataRefreshed": "數據已刷新",
-    "operationFailed": "操作失敗",
-    "operationSuccess": "操作成功",
-    "settingsApplied": "設置已應用"
+    "configurationSaved": "設定已儲存",
+    "configurationUpdated": "設定已更新",
+    "dataRefreshed": "資料已重新整理",
+    "operationFailed": "操作失敗",
+    "operationSuccess": "操作成功",
+    "settingsApplied": "設定已套用"
src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (3)

185-189: Prefer structured logging over console.log

Use the app’s logger (if available) with level and context instead of console.log, per logging guidelines.

-      console.log(
-        `Successfully fetched ${data.data.mcp_server_list.length} operational MCP servers from ModelScope`
-      )
+      console.info('[INFO][ModelScope][syncMcpServers]', {
+        count: data.data.mcp_server_list.length
+      })

200-340: Locale selection and URL/casing tweaks in server conversion

  • Prefer English locale for non-Chinese environments; then fall back to zh/name/id.
  • providerUrl likely doesn’t need an “@” before id.
  • Consider deterministic icon selection to avoid config churn across runs.
-    const displayName = mcpServer.chinese_name || mcpServer.id
+    const displayName =
+      mcpServer.locales?.en?.name ||
+      mcpServer.chinese_name ||
+      mcpServer.name ||
+      mcpServer.id
@@
-      description:
-        mcpServer.locales?.zh?.description ||
-        mcpServer.description ||
-        `ModelScope MCP Server: ${displayName}`,
+      description:
+        mcpServer.locales?.en?.description ||
+        mcpServer.locales?.zh?.description ||
+        mcpServer.description ||
+        `ModelScope MCP Server: ${displayName}`,
@@
-      descriptions:
-        mcpServer.locales?.zh?.description ||
-        mcpServer.description ||
-        `ModelScope MCP Server: ${displayName}`,
+      descriptions:
+        mcpServer.locales?.en?.description ||
+        mcpServer.locales?.zh?.description ||
+        mcpServer.description ||
+        `ModelScope MCP Server: ${displayName}`,
@@
-      providerUrl: `https://www.modelscope.cn/mcp/servers/@${mcpServer.id}`,
+      providerUrl: `https://www.modelscope.cn/mcp/servers/${encodeURIComponent(mcpServer.id)}`,

To keep icons stable per server, derive an index from a simple hash of id:

function pickEmojiById(id: string, list: string[]) {
  let h = 0
  for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) >>> 0
  return list[h % list.length]
}
// const randomEmoji = pickEmojiById(mcpServer.id, emojis)

122-137: Return typed error codes to align with i18n verify messages

Enhance check() failures with a machine-readable code (e.g., unauthorized/serverError/connectionError) so the renderer can map to provider.dialog.verify.* keys.

-      return { isOk: false, errorMsg: errorMessage }
+      const err = (error ?? {}) as any
+      const code =
+        err.status === 401 || err.status === 403
+          ? 'unauthorized'
+          : err.name === 'AbortError'
+          ? 'connectionError'
+          : 'serverError'
+      return { isOk: false, errorMsg: `${code}:${errorMessage}` }

I can wire a small helper to parse and surface { code, message } consistently across providers.

src/main/presenter/configPresenter/mcpConfHelper.ts (1)

714-717: Improve type safety for server configuration

The type casting from ExtendedMCPServerConfig to MCPServerConfig could be unsafe. Consider creating a proper conversion function or ensuring compatibility between the interfaces.

-        // Add or update the server
-        const success = await this.addMcpServer(serverName, mcpConfig as unknown as MCPServerConfig)
-        if (success || overwriteExisting) {
-          if (existingServer && overwriteExisting) {
-            await this.updateMcpServer(serverName, mcpConfig as unknown as Partial<MCPServerConfig>)
+        // Add or update the server
+        const mcpServerConfig: MCPServerConfig = {
+          command: mcpConfig.package ? 'npx' : mcpConfig.name,
+          args: mcpConfig.package ? ['-y', mcpConfig.package] : mcpConfig.args,
+          env: mcpConfig.env,
+          descriptions: mcpConfig.description,
+          icons: '📦',
+          autoApprove: [],
+          disable: !mcpConfig.enabled,
+          type: mcpConfig.type
+        }
+        const success = await this.addMcpServer(serverName, mcpServerConfig)
+        if (success || overwriteExisting) {
+          if (existingServer && overwriteExisting) {
+            await this.updateMcpServer(serverName, mcpServerConfig)
src/renderer/floating/env.d.ts (1)

14-16: API surface OK; improve typing for config callback

onRightClick addition looks good. For onConfigUpdate, avoid any; expose a shared type for the floating button config (e.g., FloatingButtonPublicConfig in src/shared).

Example:

// src/shared/floating-button.ts
export type FloatingButtonPublicConfig = {
  opacity?: number
  // ...other fields you intend to expose to renderer
}

Then:

- onConfigUpdate: (callback: (config: any) => void) => void
+ onConfigUpdate: (callback: (config: FloatingButtonPublicConfig) => void) => void
src/renderer/floating/FloatingButton.vue (1)

10-10: Right-click UX OK; de-duplicate animation logic

The right-click path works and prevents the default menu. The scale animation is duplicated in handleClick and handleRightClick—extract it to a small helper to keep the code DRY.

<script setup lang="ts">
 import { ref, onMounted, onUnmounted } from 'vue'
 const isPulsing = ref(true)
 const floatingButton = ref<HTMLElement>()
 
-const handleClick = () => {
-  // 点击反馈动画
+const animatePress = () => {
   if (floatingButton.value) {
     floatingButton.value.style.transform = 'scale(0.9)'
     setTimeout(() => {
       if (floatingButton.value) {
         floatingButton.value.style.transform = ''
       }
     }, 150)
   }
+}
+
+const handleClick = () => {
+  animatePress()
   if (window.floatingButtonAPI) {
     try {
       window.floatingButtonAPI.onClick()
     } catch (error) {
       console.error('=== FloatingButton: Error calling onClick API ===:', error)
     }
   } else {
     console.error('=== FloatingButton: floatingButtonAPI not available ===')
   }
 }
 
 const handleRightClick = (event: MouseEvent) => {
   event.preventDefault()
-  if (floatingButton.value) {
-    floatingButton.value.style.transform = 'scale(0.9)'
-    setTimeout(() => {
-      if (floatingButton.value) {
-        floatingButton.value.style.transform = ''
-      }
-    }, 150)
-  }
+  animatePress()
   if (window.floatingButtonAPI) {
     try {
       window.floatingButtonAPI.onRightClick()
     } catch (error) {
       console.error('=== FloatingButton: Error calling onRightClick API ===:', error)
     }
   } else {
     console.error('=== FloatingButton: floatingButtonAPI not available ===')
   }
 }
</script>

Also applies to: 52-73

src/main/presenter/floatingButtonPresenter/index.ts (4)

113-137: Click handler: bounds-aware toggle is solid; consider passing pointer position

The bounds capture and toggleFloatingChatWindow invocation look correct. Optional enhancement: include cursor coordinates for more precise anchoring if needed.

If you later want to anchor to the pointer:

  • Send screenX/screenY from the renderer via IPC on click/right-click.
  • Fall back to window bounds if absent.

158-167: Background pre-create: add structured logging

Replace console.error/log with the shared logger for consistency and structured logs with levels per guidelines.

-      presenter.windowPresenter.createFloatingChatWindow().catch((error) => {
-        console.error('Failed to pre-create floating chat window:', error)
-      })
-      console.log('Started pre-creating floating chat window in background')
+      presenter.windowPresenter.createFloatingChatWindow().catch((error) => {
+        logger.error('Failed to pre-create floating chat window', { error })
+      })
+      logger.info('Started pre-creating floating chat window in background')

(Import logger from the shared logger module used elsewhere.)


206-226: Open/focus main window: OK

Robust handling of minimized/absent main window. Consider using structured logger instead of console.log for consistency.


228-235: Quit flow: OK

exitApplication uses app.quit() with error handling. Consider prompting or saving state if any pending operations exist (optional).

src/main/presenter/windowPresenter/index.ts (1)

1106-1121: Consider improving error handling in createFloatingChatWindow

The method properly handles errors and prevents duplicate creation, but consider whether throwing the error is the best approach. You might want to handle it gracefully at the caller level or return a boolean/result object instead.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1024a14 and efa1c4f.

📒 Files selected for processing (21)
  • src/main/events.ts (1 hunks)
  • src/main/presenter/configPresenter/mcpConfHelper.ts (2 hunks)
  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts (1 hunks)
  • src/main/presenter/floatingButtonPresenter/index.ts (4 hunks)
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1 hunks)
  • src/main/presenter/tabPresenter.ts (1 hunks)
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts (1 hunks)
  • src/main/presenter/windowPresenter/index.ts (6 hunks)
  • src/preload/floating-preload.ts (2 hunks)
  • src/renderer/floating/FloatingButton.vue (2 hunks)
  • src/renderer/floating/env.d.ts (1 hunks)
  • src/renderer/src/components/NewThread.vue (3 hunks)
  • src/renderer/src/components/ScrollablePopover.vue (1 hunks)
  • src/renderer/src/components/TitleView.vue (2 hunks)
  • src/renderer/src/components/icons/ModelIcon.vue (1 hunks)
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue (2 hunks)
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue (1 hunks)
  • src/renderer/src/components/ui/popover/PopoverContent.vue (1 hunks)
  • src/renderer/src/i18n/en-US/settings.json (3 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (2 hunks)
  • src/shared/presenter.d.ts (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/renderer/src/components/ui/popover/PopoverContent.vue
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/renderer/src/components/settings/ModelProviderSettingsDetail.vue
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
  • src/renderer/src/components/icons/ModelIcon.vue
  • src/shared/presenter.d.ts
🧰 Additional context used
📓 Path-based instructions (18)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/renderer/floating/env.d.ts
  • src/main/presenter/tabPresenter.ts
  • src/renderer/src/components/TitleView.vue
  • src/renderer/floating/FloatingButton.vue
  • src/main/events.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/preload/floating-preload.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Strict type checking enabled for TypeScript

**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/renderer/floating/env.d.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/events.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/preload/floating-preload.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/main/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Main to Renderer: Use EventBus to broadcast events via mainWindow.webContents.send()

Use Electron's built-in APIs for file system and native dialogs

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/events.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/main/presenter/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

One presenter per functional domain

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/development-setup.mdc)

**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/renderer/floating/env.d.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/events.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/preload/floating-preload.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/{main,renderer}/**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

src/{main,renderer}/**/*.ts: Use context isolation for improved security
Implement proper inter-process communication (IPC) patterns
Optimize application startup time with lazy loading
Implement proper error handling and logging for debugging

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/renderer/floating/env.d.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/events.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/main/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

主进程代码放在 src/main

Files:

  • src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/events.ts
  • src/main/presenter/windowPresenter/FloatingChatWindow.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/floating/env.d.ts
  • src/renderer/src/components/TitleView.vue
  • src/renderer/floating/FloatingButton.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.

Files:

  • src/renderer/floating/env.d.ts
  • src/renderer/src/components/TitleView.vue
  • src/renderer/floating/FloatingButton.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/floating/env.d.ts
  • src/renderer/src/components/TitleView.vue
  • src/renderer/floating/FloatingButton.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.

Files:

  • src/renderer/floating/env.d.ts
  • src/renderer/src/components/TitleView.vue
  • src/renderer/floating/FloatingButton.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/TitleView.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/components/TitleView.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/renderer/src/**/*

📄 CodeRabbit Inference Engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/components/TitleView.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/en-US/settings.json
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/TitleView.vue
  • src/renderer/src/components/NewThread.vue
  • src/renderer/src/components/ScrollablePopover.vue
src/preload/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Context isolation enabled with preload scripts for security

Files:

  • src/preload/floating-preload.ts
src/main/presenter/configPresenter/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Centralize configuration in configPresenter/

Files:

  • src/main/presenter/configPresenter/mcpConfHelper.ts
src/main/presenter/llmProviderPresenter/providers/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/main/presenter/llmProviderPresenter/providers/*.ts: Create provider file in src/main/presenter/llmProviderPresenter/providers/ when adding a new LLM provider
Implement coreStream method following standardized event interface in LLM provider files

src/main/presenter/llmProviderPresenter/providers/*.ts: Each file in src/main/presenter/llmProviderPresenter/providers/*.ts should handle interaction with a specific LLM API, including request/response formatting, tool definition conversion, native/non-native tool call management, and standardizing output streams to a common event format.
Provider implementations must use a coreStream method that yields standardized stream events to decouple the main loop from provider-specific details.
The coreStream method in each Provider must perform a single streaming API request per conversation round and must not contain multi-round tool call loop logic.
Provider files should implement helper methods such as formatMessages, convertToProviderTools, parseFunctionCalls, and prepareFunctionCallPrompt as needed for provider-specific logic.
All provider implementations must parse provider-specific data chunks and yield standardized events for text, reasoning, tool calls, usage, errors, stop reasons, and image data.
When a provider does not support native function calling, it must prepare messages using prompt wrapping (e.g., prepareFunctionCallPrompt) before making the API call.
When a provider supports native function calling, MCP tools must be converted to the provider's format (e.g., using convertToProviderTools) and included in the API request.
Provider implementations should aggregate and yield usage events as part of the standardized stream.
Provider implementations should yield image data events in the standardized format when applicable.
Provider implementations should yield reasoning events in the standardized format when applicable.
Provider implementations should yield tool call events (`tool_call_star...

Files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
🧠 Learnings (13)
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Import Icon component from Iconify/Vue.

Applied to files:

  • src/renderer/src/components/TitleView.vue
  • src/renderer/src/components/NewThread.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/**/*.ts : Centralize configuration in configPresenter/

Applied to files:

  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
📚 Learning: 2025-07-21T01:45:54.229Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:45:54.229Z
Learning: Applies to src/renderer/src/composables/usePresenter.ts : The IPC in the renderer process is implemented in usePresenter.ts, allowing direct calls to the presenter-related interfaces exposed by the main process

Applied to files:

  • src/main/presenter/floatingButtonPresenter/index.ts
📚 Learning: 2025-07-21T01:45:54.229Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:45:54.229Z
Learning: Applies to src/main/presenter/index.ts : The IPC messages from the main process to notify the view mainly rely on the EventBus index.ts to listen for events that need to be notified and then send them to the renderer through the mainWindow

Applied to files:

  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/mcpPresenter/inMemoryServers/*.ts : Implement new MCP tool in src/main/presenter/mcpPresenter/inMemoryServers/ when adding a new MCP tool

Applied to files:

  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/mcpPresenter/index.ts : Register new MCP tool in mcpPresenter/index.ts

Applied to files:

  • src/main/presenter/configPresenter/mcpConfHelper.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : When a provider supports native function calling, MCP tools must be converted to the provider's format (e.g., using `convertToProviderTools`) and included in the API request.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Provider files should implement helper methods such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt` as needed for provider-specific logic.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/providers.ts : Add provider configuration in configPresenter/providers.ts when adding a new LLM provider

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each file in `src/main/presenter/llmProviderPresenter/providers/*.ts` should handle interaction with a specific LLM API, including request/response formatting, tool definition conversion, native/non-native tool call management, and standardizing output streams to a common event format.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : `src/main/presenter/llmProviderPresenter/index.ts` should manage the overall Agent loop, conversation history, tool execution via `McpPresenter`, and frontend communication via `eventBus`.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Create provider file in src/main/presenter/llmProviderPresenter/providers/ when adding a new LLM provider

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : All provider implementations must parse provider-specific data chunks and yield standardized events for text, reasoning, tool calls, usage, errors, stop reasons, and image data.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
🧬 Code Graph Analysis (2)
src/preload/floating-preload.ts (1)
src/main/events.ts (1)
  • FLOATING_BUTTON_EVENTS (178-184)
src/main/presenter/floatingButtonPresenter/index.ts (2)
src/main/events.ts (1)
  • FLOATING_BUTTON_EVENTS (178-184)
src/renderer/src/events.ts (1)
  • FLOATING_BUTTON_EVENTS (129-134)
🔇 Additional comments (32)
src/renderer/src/components/NewThread.vue (3)

67-73: ScrollablePopover integration looks correct

align, content-class, and enable-scrollable are set properly. v-model:open and @update:open will pass through via $attrs to the inner Popover. No functional issues spotted.


87-97: ChatConfig placement inside ScrollablePopover is good

Binding limits and model/provider IDs are wired correctly; the scrollable content prevents overflow. Looks good.


111-111: Import is correct

Local import path to ScrollablePopover.vue is accurate and consistent with other usages.

src/renderer/src/components/TitleView.vue (2)

52-67: ScrollablePopover usage is correct

Content moved directly under the wrapper with align/end and consistent width/scroll behavior. Bindings to ChatConfig remain intact.


78-78: Import is correct

ScrollablePopover import path is valid and consistent.

src/renderer/src/i18n/en-US/settings.json (1)

269-273: Good addition: granular verify error states

New verify error keys (connectionError/serverError/unauthorized) look consistent and will help map backend failures to user-friendly messages.

src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1)

102-115: Verify timeout handling on openai.models.list in OpenAICompatibleProvider

The { timeout: 10000 } option passed to
this.openai.models.list({ timeout: 10000 })
may be ignored by the OpenAI SDK in use. Please confirm that the client honors a timeout parameter in its models.list() call. If it does not, switch to using an AbortController:

  • File: src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts
  • Method: fetchOpenAIModels(options?: { timeout: number })
  • Client instantiation in createOpenAIClient() only sets fetchOptions.dispatcher, not an abort signal.

Suggested replacement:

-    const response = await this.openai.models.list({ timeout: 10000 })
+    const controller = new AbortController()
+    const timer = setTimeout(() => controller.abort(), 10_000)
+    try {
+      // many OpenAI SDKs accept request options as the second arg
+      const response = await (this.openai as any).models.list(
+        {}, 
+        { signal: controller.signal }
+      )
+      return {
+        limit_remaining: 'Available',
+        remainNum: response.data?.length || 0
+      }
+    } finally {
+      clearTimeout(timer)
+    }
src/main/presenter/configPresenter/mcpConfHelper.ts (5)

29-44: LGTM: Well-structured interface extension

The ExtendedMCPServerConfig interface appropriately extends the base MCP server functionality with ModelScope-specific metadata. The optional fields for package, version, source, etc., provide good flexibility for external integrations.


644-744: Strong implementation with proper error handling

The batchImportMcpServers method demonstrates excellent error handling patterns and follows TypeScript best practices. Key strengths:

  • Comprehensive error handling with try-catch blocks
  • Proper type safety with explicit type assertions
  • Clear logging for debugging and monitoring
  • Proper event emission for UI updates

The method correctly handles various import scenarios (skip existing, overwrite, enable by default) and provides detailed feedback through the return object.


746-776: Robust unique name generation logic

The generateUniqueServerName helper method properly sanitizes package names and ensures uniqueness through incremental suffixes. The regex-based cleanup and collision detection logic is sound.


778-794: Efficient package lookup implementation

The findServerByPackage method efficiently searches through existing servers to find matches by package name. The type casting to ExtendedMCPServerConfig is necessary and safe given the context.


738-741: Ignore direct webContents.send suggestion

Using eventBus.sendToRenderer() is the intended pattern for main-to-renderer IPC in this codebase. The EventBus abstraction wraps calls to mainWindow.webContents.send(), ensuring consistency, decoupling, and testability across all presenters.

No changes required here.

Likely an incorrect or invalid review comment.

src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts (1)

173-175: Accessor looks fine; keep scope internal

getWindow() is acceptable for internal coordination (anchoring, bounds). Ensure it’s only used in main-process code paths and never exposed to renderer.

Please confirm no renderer-side imports or exposures of BrowserWindow are introduced.

src/main/presenter/tabPresenter.ts (1)

946-980: Virtual tab registration is safe—apply stronger typing and lifecycle cleanup

We can tighten the types around tabs and confirm that virtual-tab entries are removed when the floating window is torn down.

  • Introduce a VirtualView type for the minimal view interface.
  • Change tabs to Map<number, WebContentsView | VirtualView>.
  • Confirmed: FloatingChatWindow.destroy() calls its private unregisterVirtualTab(), which invokes tabPresenter.unregisterFloatingWindow(id) before BrowserWindow.destroy(). No stale entries remain when windows are programmatically destroyed.
-  private tabs: Map<number, WebContentsView> = new Map()
+  type VirtualView = {
+    webContents: Electron.WebContents
+    setVisible: (visible: boolean) => void
+    setBounds: (bounds: { x: number; y: number; width: number; height: number }) => void
+    getBounds: () => { x: number; y: number; width: number; height: number }
+  }
+  private tabs: Map<number, WebContentsView | VirtualView> = new Map()

   registerFloatingWindow(webContentsId: number, webContents: Electron.WebContents): void {
     // …
-      const virtualView = {
+      const virtualView: VirtualView = {
         webContents,
         setVisible: () => {},
         setBounds: () => {},
         getBounds: () => ({ x: 0, y: 0, width: 400, height: 600 })
-      } as any
+      }
       this.webContentsToTabId.set(webContentsId, webContentsId)
       this.tabs.set(webContentsId, virtualView)
src/main/presenter/floatingButtonPresenter/index.ts (4)

51-52: Good: cleanup of IPC listeners on destroy

Removing CLICKED and RIGHT_CLICKED listeners avoids duplicate handlers after re-init.


111-112: Good: defensive listener cleanup before re-registering

Pre-emptively removing listeners prevents handler accumulation across re-initializations.


139-145: Right-click handler: OK

Handler delegates to showContextMenu with error handling. Looks good.


155-156: Pre-creation timing

Pre-creating the floating chat window can improve UX. Ensure createFloatingChatWindow is idempotent to avoid duplicate windows if enable/initialize is called multiple times.

Would you like a simple guard in presenter.windowPresenter to no-op if already created?

src/main/presenter/windowPresenter/index.ts (8)

16-16: Import path consistency verified

The import correctly references the FloatingChatWindow class from the same directory.


42-42: Property initialization looks good

The floatingChatWindow property is properly typed and initialized to null.


62-62: Good cleanup on app quit

Properly destroys the floating chat window when the application is quitting to prevent memory leaks.


177-198: Preview file enhancement handles floating window correctly

The fallback logic for using the floating chat window when no focused window exists is well-implemented with proper null checks.


504-513: Message broadcasting to floating window implemented correctly

The enhancement properly includes the floating chat window in message broadcasts with appropriate null checks and error handling.


1123-1137: showFloatingChatWindow implementation looks good

The method correctly ensures the window is created before showing it and passes the position parameter through.


1146-1160: toggleFloatingChatWindow implementation is correct

The method properly ensures window creation before toggling and passes the position parameter.


1162-1168: Proper cleanup in destroyFloatingChatWindow

The method correctly destroys the window and nullifies the reference to prevent memory leaks.

src/main/presenter/windowPresenter/FloatingChatWindow.ts (6)

1-10: Imports are well-organized

All necessary dependencies are imported correctly.


11-43: Configuration structure is well-defined

The interfaces and default configuration provide good structure with reasonable defaults for the floating window.


116-148: Show method handles loading states correctly

The method properly manages the window visibility considering loading states and position updates.


238-332: Sophisticated positioning algorithm handles edge cases well

The position calculation correctly considers screen boundaries, prioritizes positions based on screen center distance, and ensures the window stays within the work area.


357-397: Window event handling is comprehensive and correct

The event handlers properly manage window lifecycle, prevent unwanted destruction, and maintain visibility state.


203-218: Virtual tab registration is properly implemented

The method correctly registers the floating window as a virtual tab with appropriate error handling.

@zerob13 zerob13 merged commit 3feafbc into dev Aug 11, 2025
1 of 2 checks passed
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: 6

🔭 Outside diff range comments (1)
src/renderer/src/components/mcp-config/components/McpToolPanel.vue (1)

173-192: Handle empty-tool state in the top selector (add i18n message)

When serverTools is empty, the dropdown renders with no options. Show an explicit empty state using i18n.

-        <div v-if="showTopSelector" class="flex-shrink-0 px-4 py-4">
-          <Select v-model="selectedToolName">
+        <div v-if="showTopSelector" class="flex-shrink-0 px-4 py-4">
+          <template v-if="serverTools.length > 0">
+            <Select v-model="selectedToolName">
               <SelectTrigger class="w-full">
                 <SelectValue :placeholder="t('mcp.tools.selectToolToDebug')" />
               </SelectTrigger>
               <SelectContent>
                 <SelectItem
                   v-for="tool in serverTools"
                   :key="tool.function.name"
                   :value="tool.function.name"
                 >
                   <div class="flex items-center space-x-2">
                     <Icon icon="lucide:function-square" class="h-3 w-3 text-primary" />
                     <span>{{ tool.function.name }}</span>
                   </div>
                 </SelectItem>
               </SelectContent>
-          </Select>
+            </Select>
+          </template>
+          <p v-else class="text-sm text-muted-foreground">
+            {{ t('mcp.tools.noToolsAvailable') }}
+          </p>
         </div>

Follow-up: add the translation key mcp.tools.noToolsAvailable.

♻️ Duplicate comments (4)
src/renderer/src/i18n/zh-TW/settings.json (1)

381-404: ModelScope 區塊繁中用詞統一(伺服器/網路/位址/匯入/營運 等)

多處為簡體或陸用詞,建議改為台灣慣用語。以下為重點修正片段(其餘同理套用):

-        "invalidServerData": "無效的服務器數據",
+        "invalidServerData": "無效的伺服器資料",
-        "authenticationFailed": "認證失敗,請檢查 API Key",
+        "authenticationFailed": "認證失敗,請檢查 API 金鑰",
-        "convertingServers": "正在轉換服務器配置...",
+        "convertingServers": "正在轉換伺服器設定...",
-        "description": "從 ModelScope 同步 MCP 服務器到本地配置,可以快速添加常用的 MCP 工具。\n所有服務默認禁用,導入後可手動啟用。",
+        "description": "從 ModelScope 同步 MCP 伺服器到本機設定,可快速新增常用 MCP 工具。\n所有服務預設停用,匯入後可手動啟用。",
-        "errors": "錯誤 {count} 個",
+        "errors": "共 {count} 個錯誤",
-        "fetchingServers": "正在獲取 MCP 服務器列表...",
+        "fetchingServers": "正在取得 MCP 伺服器清單...",
-        "imported": "已導入 {count} 個服務",
+        "imported": "已匯入 {count} 個服務",
-        "importingServers": "正在導入服務器配置...",
+        "importingServers": "正在匯入伺服器設定...",
-        "noOperationalUrls": "未找到可用的運營地址",
+        "noOperationalUrls": "未找到可用的營運位址",
-        "serverAlreadyExists": "服務器已存在,跳過導入",
+        "serverAlreadyExists": "伺服器已存在,已略過匯入",
-        "pageSize": "每頁數量",
+        "pageSize": "每頁筆數",
-      "apiKey": "API 密鑰",
+      "apiKey": "API 金鑰",
-      "apiKeyHelper": "在 ModelScope 控制台獲取您的 API Key",
+      "apiKeyHelper": "請在 ModelScope 主控台取得您的 API 金鑰",
-      "apiKeyPlaceholder": "請輸入 ModelScope API Key",
+      "apiKeyPlaceholder": "請輸入 ModelScope API 金鑰",
-      "baseUrl": "API 地址",
+      "baseUrl": "API 位址",
-      "baseUrlHelper": "ModelScope API 服務地址",
+      "baseUrlHelper": "ModelScope API 服務位址",
-      "connected": "已連接",
+      "connected": "已連線",
-      "connecting": "連接中...",
+      "connecting": "連線中...",
-      "invalidKey": "無效的 API Key",
+      "invalidKey": "無效的 API 金鑰",
-      "keyRequired": "請輸入 API Key",
+      "keyRequired": "請輸入 API 金鑰",
-        "operationalServers": "運營服務器",
+        "operationalServers": "營運伺服器",
-        "rateLimitConfig": "速率限製配置",
+        "rateLimitConfig": "速率限制設定",
-        "specialConfig": "特殊配置",
+        "specialConfig": "特殊設定",
-        "title": "提供商設置詳情"
+        "title": "服務提供者設定詳情"

另建議將下列 Toast 統一為繁中用語:

-    "configurationSaved": "配置已保存",
-    "configurationUpdated": "配置已更新",
-    "dataRefreshed": "數據已刷新",
-    "settingsApplied": "設置已應用"
+    "configurationSaved": "設定已儲存",
+    "configurationUpdated": "設定已更新",
+    "dataRefreshed": "資料已重新整理",
+    "settingsApplied": "設定已套用"

Also applies to: 405-432

src/renderer/src/i18n/fa-IR/settings.json (1)

381-435: Fix brand typos and broken placeholders (will break interpolation)

Multiple “Modelcope/ModelCope” typos and non-standard placeholders (e.g., {تعداد}, {COUNT}) will break UI interpolation. Apply:

-      "apiKeyHelper": "کلید API خود را در کنسول ModelCope دریافت کنید",
+      "apiKeyHelper": "کلید API خود را در کنسول ModelScope دریافت کنید",
-      "apiKeyPlaceholder": "لطفاً کلید API Modelcope را وارد کنید",
+      "apiKeyPlaceholder": "لطفاً کلید API ModelScope را وارد کنید",
-      "baseUrlHelper": "آدرس خدمات API Modelcope",
+      "baseUrlHelper": "آدرس خدمات API ModelScope",
-      "description": "Modelcope یک بستر اشتراک گذاری مدل به عنوان یک سرویس است که توسط آکادمی Alibaba Damo راه اندازی شده است",
+      "description": "ModelScope یک بستر اشتراک‌گذاری مدل به‌عنوان سرویس است که توسط Alibaba Damo Academy راه‌اندازی شده است",
-        "syncFromModelScope": "همگام سازی از Modelcope",
+        "syncFromModelScope": "همگام‌سازی از ModelScope",
-        "errors": "خطا {تعداد}",
+        "errors": "خطا {count}",
-        "imported": "{تعداد خدمات وارد شده است",
+        "imported": "{count} سرویس وارد شد",
-        "skipped": "خدمات SKIP {COUNT",
+        "skipped": "{count} سرویس رد شد",
-        "noApiKey": "لطفاً ابتدا کلید API Modelcope را پیکربندی کنید",
+        "noApiKey": "لطفاً ابتدا کلید API ModelScope را پیکربندی کنید",
-      "name": "مدلهای مدل",
+      "name": "ModelScope"

Also refine a few awkward phrases:

-        "convertingServers": "تبدیل پیکربندی سرور ...",
+        "convertingServers": "در حال تبدیل پیکربندی سرور...",
-        "importingServers": "وارد کردن پیکربندی سرور ...",
+        "importingServers": "در حال وارد کردن پیکربندی سرور...",
-        "syncComplete": "اتمام همزمان",
+        "syncComplete": "همگام‌سازی کامل شد"
src/renderer/src/i18n/ja-JP/settings.json (1)

408-429: Normalize brand and improve counters/labels

  • Fix brand casing, improve skipped string and label terms.
-        "description": "MODESCOPEからローカル構成までMCPサーバーを同期すると、一般的に使用されるMCPツールをすばやく追加できます。すべてのサービスはデフォルトで無効になり、インポート後に手動で有効にすることができます。",
+        "description": "ModelScope からローカル構成へ MCP サーバーを同期すると、よく使われる MCP ツールをすばやく追加できます。すべてのサービスはデフォルトで無効で、インポート後に手動で有効化できます。",
-        "errors": "エラー{count}",
+        "errors": "{count} 件のエラー",
-        "imported": "{count}サービスがインポートされています",
+        "imported": "{count} 件のサービスをインポートしました",
-        "skipped": "Skip {count}サービス",
+        "skipped": "{count} 件のサービスをスキップ",
-        "operationalServers": "サーバーの操作",
+        "operationalServers": "運用サーバー"
src/renderer/src/i18n/fr-FR/settings.json (1)

381-435: Correct brand, “connecting”, and broken placeholder; improve phrasing

Apply the following to avoid interpolation issues and awkward French:

-      "apiKeyHelper": "Obtenez votre clé API dans la console Modelcope",
+      "apiKeyHelper": "Obtenez votre clé API dans la console ModelScope",
-      "apiKeyPlaceholder": "Veuillez saisir la clé de l'API Modelscope",
+      "apiKeyPlaceholder": "Veuillez saisir la clé API ModelScope",
-      "baseUrlHelper": "Adresse du service API Modelcope",
+      "baseUrlHelper": "Adresse du service API ModelScope",
-      "connecting": "De liaison...",
+      "connecting": "Connexion...",
-      "description": "Modelcope est une plate-forme de partage modèle en tant que service lancée par Alibaba Damo Academy",
+      "description": "ModelScope est une plateforme de partage de modèles en tant que service lancée par Alibaba Damo Academy",
-        "operationalDescription": "Synchroniser les serveurs MCP qui peuvent être utilisés directement sur la plate-forme Modelcope",
+        "operationalDescription": "Synchroniser les serveurs MCP directement utilisables sur la plateforme ModelScope",
-        "operationalServers": "Exploitation d'un serveur",
+        "operationalServers": "Serveurs opérationnels",
-        "syncFromModelScope": "Synchronisation de Modelscope",
+        "syncFromModelScope": "Synchroniser depuis ModelScope",
-        "errors": "Erreur {count}",
+        "errors": "{count} erreur(s)",
-        "imported": "{comte} Les services ont été importés",
+        "imported": "{count} service(s) importé(s)",
-        "skipped": "Skip {count} Services",
+        "skipped": "{count} service(s) ignoré(s)",
-        "syncComplete": "Achèvement synchrone",
+        "syncComplete": "Synchronisation terminée",
-      "name": "Modelcope",
+      "name": "ModelScope"
🧹 Nitpick comments (5)
src/renderer/src/components/mcp-config/components/McpToolPanel.vue (2)

56-63: Use English for code comments (policy requirement)

Replace Chinese comments with English per repo guidelines. Logic looks good.

-// 屏幕断点:lg 及以上
+// Breakpoint: lg and above
 const isLgScreen = useMediaQuery('(min-width: 1024px)')

-// 顶部下拉是否显示:小屏时显示;或大屏但左侧列表不可用(无工具)时显示
+// Show top selector on small screens, or on large screens when no tools are available (left list unusable)
 const showTopSelector = computed(() => {
   return !isLgScreen.value || serverTools.value.length === 0
 })

197-225: A11y: mark selected item in the side list

Expose selection state for screen readers.

-                <Button
+                <Button
                   v-for="tool in serverTools"
                   :key="tool.function.name"
                   variant="ghost"
                   class="w-full justify-start h-auto p-3 text-left"
                   :class="{
                     'bg-accent text-accent-foreground': selectedToolName === tool.function.name
                   }"
+                  :aria-pressed="selectedToolName === tool.function.name"
                   @click="selectTool(tool)"
                 >
src/renderer/src/i18n/en-US/settings.json (1)

433-438: Tighten toast grammar

-    "operationSuccess": "Operation is successful",
+    "operationSuccess": "Operation successful"
src/renderer/src/i18n/fa-IR/settings.json (1)

436-438: Polish operation success message

-    "operationSuccess": "عمليات موفقيت آميز است",
+    "operationSuccess": "عمليات با موفقیت انجام شد"
src/renderer/src/i18n/ja-JP/settings.json (1)

434-435: Unify success wording

-      "verifySuccess": "検証は成功しました"
+      "verifySuccess": "検証に成功しました"
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5d349d5 and 9b6fa54.

📒 Files selected for processing (13)
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1 hunks)
  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue (5 hunks)
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue (1 hunks)
  • src/renderer/src/i18n/en-US/settings.json (3 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (2 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (2 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (2 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (2 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (2 hunks)
  • src/shared/presenter.d.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/renderer/src/components/settings/ModelScopeMcpSync.vue
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/shared/presenter.d.ts
  • src/renderer/src/i18n/ko-KR/settings.json
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/src/**/*

📄 CodeRabbit Inference Engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.

Files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
🧠 Learnings (3)
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/renderer/src/**/*.vue : Implement responsive design with Tailwind CSS for new UI components

Applied to files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Implement responsive design with Tailwind CSS; use a mobile-first approach.

Applied to files:

  • src/renderer/src/components/mcp-config/components/McpToolPanel.vue
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/*.json : Maintain consistent structure across all translation files

Applied to files:

  • src/renderer/src/i18n/zh-TW/settings.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-check (x64)
🔇 Additional comments (4)
src/renderer/src/components/mcp-config/components/McpToolPanel.vue (1)

22-22: Dependency verified: @vueuse/core is already declared
Found in package.json under devDependencies ("@vueuse/core": "^12.7.0"), so the import in McpToolPanel.vue will resolve. No further changes needed.

src/renderer/src/i18n/zh-CN/settings.json (3)

250-256: Provider status toasts look consistent and reusable

Keys and phrasing are clear; no placeholder or punctuation issues detected.


260-311: ModelScope block reads well; placeholders consistent

  • Wording is natural (e.g., “运营服务器”, “未找到可用的运营地址”).
  • All counters use {count}; inputs have clear placeholders.

No action needed.


332-336: Verify error variants are complete and precise

The added verify states cover unauthorized/server/connection. Text is unambiguous.

Comment on lines +388 to 390
line-clamp: 2;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Non-standard CSS: avoid line-clamp and remove unused helper

line-clamp is not widely supported; -webkit-line-clamp is enough. Also, .line-clamp-2 isn’t used in the template—either remove it or apply it where needed.

 .line-clamp-2 {
   display: -webkit-box;
-  line-clamp: 2;
   -webkit-line-clamp: 2;
   -webkit-box-orient: vertical;
   overflow: hidden;
 }

If you intend to clamp the description, apply the class (assuming the plugin or this helper is desired) outside this hunk:

<p class="text-sm text-secondary-foreground line-clamp-2">
  {{ selectedTool.function.description || selectedTool.function.name }}
</p>

Optionally confirm Tailwind’s line-clamp plugin is configured:


🏁 Script executed:

#!/bin/bash
# Check for Tailwind line-clamp plugin usage
rg -n "@tailwindcss/line-clamp|lineClamp" tailwind.config.* package.json -S || true

Length of output: 85


Remove non-standard line-clamp and resolve unused helper

The line-clamp property isn’t part of any spec and has spotty support. Your .line-clamp-2 class isn’t used anywhere—and you don’t have Tailwind’s line-clamp plugin installed—so either apply it or remove it entirely.

• File: src/renderer/src/components/mcp-config/components/McpToolPanel.vue
• In the <style> block around lines 388–390, remove the non-standard property
• In the <template>, either add class="line-clamp-2" to the <p> rendering the description or delete the helper class
• Confirm there’s no @tailwindcss/line-clamp entry in tailwind.config.js (none was found)

Suggested diff:

 .line-clamp-2 {
   display: -webkit-box;
-  line-clamp: 2;
   -webkit-line-clamp: 2;
   -webkit-box-orient: vertical;
   overflow: hidden;
 }

Usage example if you choose to keep the helper:

<p class="text-sm text-secondary-foreground line-clamp-2">
  {{ selectedTool.function.description || selectedTool.function.name }}
</p>
🤖 Prompt for AI Agents
In src/renderer/src/components/mcp-config/components/McpToolPanel.vue around
lines 388–390, remove the non-standard CSS lines (line-clamp,
-webkit-line-clamp, -webkit-box-orient) from the <style> block; then either
delete the unused .line-clamp-2 helper class entirely from the file, or keep it
and add class="line-clamp-2" to the <p> that renders the description (the <p>
with selectedTool.function.description || selectedTool.function.name) so the
helper is actually used; do not add Tailwind plugin changes here since none is
present.

Comment on lines +357 to +408
"modelscope": {
"mcpSync": {
"title": "Sync MCP Services",
"description": "Sync MCP servers from ModelScope to local configuration, allowing quick addition of common MCP tools.",
"sync": "Start Sync",
"syncing": "Syncing...",
"pageSize": "Page Size",
"imported": "Imported {count} services",
"skipped": "Skipped {count} services",
"errors": "{count} errors",
"errorDetails": "Error Details",
"noApiKey": "Please configure ModelScope API Key first",
"noServersFound": "No available MCP services found",
"authenticationFailed": "Authentication failed, please check API Key",
"convertingServers": "Converting server configuration...",
"fetchingServers": "Getting the list of MCP servers...",
"importingServers": "Importing server configuration...",
"noOperationalUrls": "No available operating address found",
"pageNumber": "page number",
"pageNumberPlaceholder": "Please enter the page number",
"serverAlreadyExists": "The server already exists, skip import",
"syncComplete": "Synchronous completion",
"invalidServerData": "Invalid server data"
},
"apiKey": "API Key",
"apiKeyHelper": "Get your API Key in the ModelScope console",
"apiKeyPlaceholder": "Please enter ModelScope API Key",
"baseUrl": "API Address",
"baseUrlHelper": "ModelScope API service address",
"connected": "Connected",
"connecting": "Connecting...",
"description": "ModelScope is a model-as-a-service sharing platform launched by Alibaba Damo Academy",
"details": {
"apiConfig": "API Configuration",
"mcpSync": "MCP Synchronization",
"modelManagement": "Model Management",
"operationalDescription": "Synchronize MCP servers that can be used directly on the ModelScope platform",
"operationalServers": "Operating a server",
"rateLimitConfig": "Rate limit configuration",
"safetySettings": "Security settings",
"specialConfig": "Special configuration",
"syncFromModelScope": "Sync from ModelScope",
"title": "Provider settings details"
},
"invalidKey": "Invalid API Key",
"keyRequired": "Please enter API Key",
"name": "ModelScope",
"networkError": "Network connection error",
"notConnected": "Not connected",
"verifyFailed": "Verification failed",
"verifySuccess": "Verification is successful"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Polish ModelScope copy and fix awkward phrasings

Several strings are unnatural or inconsistent. Recommend:

-        "description": "Sync MCP servers from ModelScope to local configuration, allowing quick addition of common MCP tools.",
+        "description": "Sync MCP servers from ModelScope to your local configuration to quickly add common MCP tools. All services are imported disabled; enable them manually after import.",
-        "pageNumber": "page number",
+        "pageNumber": "Page Number",
-        "noOperationalUrls": "No available operating address found",
+        "noOperationalUrls": "No operational URLs found",
-        "serverAlreadyExists": "The server already exists, skip import",
+        "serverAlreadyExists": "Server already exists, skipping import",
-        "syncComplete": "Synchronous completion",
+        "syncComplete": "Sync complete",
-      "baseUrl": "API Address",
+      "baseUrl": "API Base URL",
-      "details": {
+      "details": {
-        "operationalServers": "Operating a server",
+        "operationalServers": "Operational Servers",
-        "safetySettings": "Security settings",
+        "safetySettings": "Safety settings",
-      "verifySuccess": "Verification is successful"
+      "verifySuccess": "Verification successful"
📝 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
"modelscope": {
"mcpSync": {
"title": "Sync MCP Services",
"description": "Sync MCP servers from ModelScope to local configuration, allowing quick addition of common MCP tools.",
"sync": "Start Sync",
"syncing": "Syncing...",
"pageSize": "Page Size",
"imported": "Imported {count} services",
"skipped": "Skipped {count} services",
"errors": "{count} errors",
"errorDetails": "Error Details",
"noApiKey": "Please configure ModelScope API Key first",
"noServersFound": "No available MCP services found",
"authenticationFailed": "Authentication failed, please check API Key",
"convertingServers": "Converting server configuration...",
"fetchingServers": "Getting the list of MCP servers...",
"importingServers": "Importing server configuration...",
"noOperationalUrls": "No available operating address found",
"pageNumber": "page number",
"pageNumberPlaceholder": "Please enter the page number",
"serverAlreadyExists": "The server already exists, skip import",
"syncComplete": "Synchronous completion",
"invalidServerData": "Invalid server data"
},
"apiKey": "API Key",
"apiKeyHelper": "Get your API Key in the ModelScope console",
"apiKeyPlaceholder": "Please enter ModelScope API Key",
"baseUrl": "API Address",
"baseUrlHelper": "ModelScope API service address",
"connected": "Connected",
"connecting": "Connecting...",
"description": "ModelScope is a model-as-a-service sharing platform launched by Alibaba Damo Academy",
"details": {
"apiConfig": "API Configuration",
"mcpSync": "MCP Synchronization",
"modelManagement": "Model Management",
"operationalDescription": "Synchronize MCP servers that can be used directly on the ModelScope platform",
"operationalServers": "Operating a server",
"rateLimitConfig": "Rate limit configuration",
"safetySettings": "Security settings",
"specialConfig": "Special configuration",
"syncFromModelScope": "Sync from ModelScope",
"title": "Provider settings details"
},
"invalidKey": "Invalid API Key",
"keyRequired": "Please enter API Key",
"name": "ModelScope",
"networkError": "Network connection error",
"notConnected": "Not connected",
"verifyFailed": "Verification failed",
"verifySuccess": "Verification is successful"
},
"modelscope": {
"mcpSync": {
"title": "Sync MCP Services",
"description": "Sync MCP servers from ModelScope to your local configuration to quickly add common MCP tools. All services are imported disabled; enable them manually after import.",
"sync": "Start Sync",
"syncing": "Syncing...",
"pageSize": "Page Size",
"imported": "Imported {count} services",
"skipped": "Skipped {count} services",
"errors": "{count} errors",
"errorDetails": "Error Details",
"noApiKey": "Please configure ModelScope API Key first",
"noServersFound": "No available MCP services found",
"authenticationFailed": "Authentication failed, please check API Key",
"convertingServers": "Converting server configuration...",
"fetchingServers": "Getting the list of MCP servers...",
"importingServers": "Importing server configuration...",
"noOperationalUrls": "No operational URLs found",
"pageNumber": "Page Number",
"pageNumberPlaceholder": "Please enter the page number",
"serverAlreadyExists": "Server already exists, skipping import",
"syncComplete": "Sync complete",
"invalidServerData": "Invalid server data"
},
"apiKey": "API Key",
"apiKeyHelper": "Get your API Key in the ModelScope console",
"apiKeyPlaceholder": "Please enter ModelScope API Key",
"baseUrl": "API Base URL",
"baseUrlHelper": "ModelScope API service address",
"connected": "Connected",
"connecting": "Connecting...",
"description": "ModelScope is a model-as-a-service sharing platform launched by Alibaba Damo Academy",
"details": {
"apiConfig": "API Configuration",
"mcpSync": "MCP Synchronization",
"modelManagement": "Model Management",
"operationalDescription": "Synchronize MCP servers that can be used directly on the ModelScope platform",
"operationalServers": "Operational Servers",
"rateLimitConfig": "Rate limit configuration",
"safetySettings": "Safety settings",
"specialConfig": "Special configuration",
"syncFromModelScope": "Sync from ModelScope",
"title": "Provider settings details"
},
"invalidKey": "Invalid API Key",
"keyRequired": "Please enter API Key",
"name": "ModelScope",
"networkError": "Network connection error",
"notConnected": "Not connected",
"verifyFailed": "Verification failed",
"verifySuccess": "Verification successful"
},
🤖 Prompt for AI Agents
In src/renderer/src/i18n/en-US/settings.json around lines 357 to 408, several
ModelScope strings are awkward or inconsistent; update wording for clarity and
consistency: change "Sync MCP Services" → "Synchronize MCP Servers", "Start
Sync" → "Start Sync", or better "Start Synchronization", "Please configure
ModelScope API Key first" → "Please configure your ModelScope API key first",
"Get your API Key in the ModelScope console" → "Get your API key from the
ModelScope console", "Please enter ModelScope API Key" → "Enter ModelScope API
key", "API Address" → "API URL", "Getting the list of MCP servers..." →
"Fetching MCP servers...", "Importing server configuration..." → "Importing
servers...", "No available operating address found" → "No available operational
addresses found", "page number" → "Page Number" and placeholder "Please enter
the page number" → "Enter page number", "The server already exists, skip import"
→ "Server already exists; skipped", "Synchronous completion" → "Sync complete",
"Provider settings details" → "Provider settings", and "Verification is
successful" → "Verification successful" (also normalize capitalization of "API
Key"/"API key" across entries). Apply these small copy edits to the listed keys
for clearer, consistent UI text.

Comment on lines +381 to +435
"configurationSaved": "پیکربندی ذخیره شده",
"configurationUpdated": "پیکربندی به روز شد",
"dataRefreshed": "داده ها تازه شده است",
"modelscope": {
"apiKey": "کلید API",
"apiKeyHelper": "کلید API خود را در کنسول ModelCope دریافت کنید",
"apiKeyPlaceholder": "لطفاً کلید API Modelcope را وارد کنید",
"baseUrl": "آدرس API",
"baseUrlHelper": "آدرس خدمات API Modelcope",
"connected": "متصل",
"connecting": "اتصال ...",
"description": "Modelcope یک بستر اشتراک گذاری مدل به عنوان یک سرویس است که توسط آکادمی Alibaba Damo راه اندازی شده است",
"details": {
"apiConfig": "پیکربندی API",
"mcpSync": "همگام سازی MCP",
"modelManagement": "مدیریت مدل",
"operationalDescription": "سرورهای MCP را همگام سازی کنید که می توانند مستقیماً در سیستم عامل ModelCope استفاده شوند",
"operationalServers": "کار کردن یک سرور",
"rateLimitConfig": "پیکربندی حد نرخ",
"safetySettings": "تنظیمات امنیتی",
"specialConfig": "پیکربندی خاص",
"syncFromModelScope": "همگام سازی از Modelcope",
"title": "جزئیات تنظیمات ارائه دهنده"
},
"invalidKey": "کلید API نامعتبر",
"keyRequired": "لطفا کلید API را وارد کنید",
"mcpSync": {
"authenticationFailed": "احراز هویت انجام نشد ، لطفاً کلید API را بررسی کنید",
"convertingServers": "تبدیل پیکربندی سرور ...",
"description": "همگام سازی یک سرور MCP از ModelScope به تنظیمات محلی به شما امکان می دهد تا به سرعت ابزارهای MCP متداول را اضافه کنید. کلیه خدمات به طور پیش فرض غیرفعال می شوند و پس از وارد کردن می توانند به صورت دستی فعال شوند.",
"errorDetails": "جزئیات خطا",
"errors": "خطا {تعداد}",
"fetchingServers": "دریافت لیست سرورهای MCP ...",
"imported": "{تعداد خدمات وارد شده است",
"importingServers": "وارد کردن پیکربندی سرور ...",
"invalidServerData": "داده های سرور نامعتبر",
"noApiKey": "لطفاً ابتدا کلید API Modelcope را پیکربندی کنید",
"noOperationalUrls": "هیچ آدرس عملیاتی موجود یافت نمی شود",
"noServersFound": "هیچ سرویس MCP در دسترس یافت نشد",
"pageNumber": "شماره صفحه",
"pageNumberPlaceholder": "لطفا شماره صفحه را وارد کنید",
"pageSize": "مقدار در هر صفحه",
"serverAlreadyExists": "سرور در حال حاضر وجود دارد ، واردات را پرش کنید",
"skipped": "خدمات SKIP {COUNT",
"sync": "همگام سازی را شروع کنید",
"syncComplete": "اتمام همزمان",
"syncing": "هماهنگ سازی ...",
"title": "همگام سازی خدمات MCP"
},
"name": "مدلهای مدل",
"networkError": "خطای اتصال شبکه",
"notConnected": "متصل نیست",
"verifyFailed": "تأیید انجام نشد",
"verifySuccess": "تأیید موفقیت آمیز است"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Quick scan for remaining typos across locales

Run to find brand typos and non-{count} counters in i18n:


🏁 Script executed:

#!/bin/bash
# Find brand typos across locales
rg -n "Modelcope|ModelCope|MODESCOPE" src/renderer/src/i18n

# Find suspicious counters not using {count} within modelscope blocks
rg -n --context 2 '"modelscope".*\n' -r '' src/renderer/src/i18n/en-US/settings.json >/dev/null 2>&1
# Generic heuristic: look for placeholders with non-latin or all-caps words around count keys
rg -n '"errors"|\"imported\"|\"skipped\"' -A 2 src/renderer/src/i18n | rg -n '\{(?!count\})[^}]+\}'

Length of output: 2895


🏁 Script executed:

#!/bin/bash
# Extract the 'modelscope' block from the English locale for reference
rg -n '"modelscope"' -n -A 40 -B 5 src/renderer/src/i18n/en-US/settings.json

Length of output: 2577


Fix inconsistent “ModelScope” naming and {count} placeholders across locales

A quick grep shows several locales using “Modelcope”, “ModelCope” or even “MODESCOPE” instead of the English “ModelScope”, plus malformed count placeholders in Farsi. Please correct the following:

• ru-RU/settings.json (≈line 392):

  • Change "ModelCope-это …""ModelScope-это …"
    • ja-JP/settings.json (≈line 410):
  • Change "MODESCOPEから…""ModelScopeから…"
    • fa-IR/settings.json (multiple lines):
  • Lines 386, 387, 389, 397, 402, 417: use “ModelScope” instead of “Modelcope”/“ModelCope”
  • In mcpSync:
    "errors": "خطا {تعداد}" → use {count} (e.g. "خطا {count}")
    "imported": "{تعداد services وارد شده است" → include {count} and close braces (e.g. "وارد شد {count} سرویس")
    "skipped": "خدمات SKIP {COUNT" → use lowercase {count}, close brace (e.g. "رد شد {count} سرویس")
    • fr-FR/settings.json (≈lines 386–430):
  • Replace “Modelcope” with “ModelScope” to match English source

After fixing these, rerun your grep to ensure no stray typos or placeholder mismatches remain.

Comment on lines +381 to +435
"configurationSaved": "Configuration enregistrée",
"configurationUpdated": "Configuration mise à jour",
"dataRefreshed": "Les données ont été rafraîchies",
"modelscope": {
"apiKey": "Clé API",
"apiKeyHelper": "Obtenez votre clé API dans la console Modelcope",
"apiKeyPlaceholder": "Veuillez saisir la clé de l'API Modelscope",
"baseUrl": "Adresse API",
"baseUrlHelper": "Adresse du service API Modelcope",
"connected": "Connecté",
"connecting": "De liaison...",
"description": "Modelcope est une plate-forme de partage modèle en tant que service lancée par Alibaba Damo Academy",
"details": {
"apiConfig": "Configuration de l'API",
"mcpSync": "Synchronisation MCP",
"modelManagement": "Gestion des modèles",
"operationalDescription": "Synchroniser les serveurs MCP qui peuvent être utilisés directement sur la plate-forme Modelcope",
"operationalServers": "Exploitation d'un serveur",
"rateLimitConfig": "Configuration de la limite de taux",
"safetySettings": "Paramètres de sécurité",
"specialConfig": "Configuration spéciale",
"syncFromModelScope": "Synchronisation de Modelscope",
"title": "Détails des paramètres du fournisseur"
},
"invalidKey": "Clé API non valide",
"keyRequired": "Veuillez saisir la clé de l'API",
"mcpSync": {
"authenticationFailed": "Échec de l'authentification, veuillez vérifier la clé de l'API",
"convertingServers": "Conversion de la configuration du serveur ...",
"description": "La synchronisation d'un serveur MCP de Modelcope aux configurations locales vous permet d'ajouter rapidement des outils MCP couramment utilisés. Tous les services sont désactivés par défaut et peuvent être activés manuellement après l'importation.",
"errorDetails": "Détails d'erreur",
"errors": "Erreur {count}",
"fetchingServers": "Obtenir la liste des serveurs MCP ...",
"imported": "{comte} Les services ont été importés",
"importingServers": "Configuration d'importation de serveur ...",
"invalidServerData": "Données de serveur non valides",
"noApiKey": "Veuillez d'abord configurer la clé de l'API Modelcope",
"noOperationalUrls": "Aucune adresse de fonctionnement disponible trouvée",
"noServersFound": "Aucun service MCP disponible trouvé",
"pageNumber": "numéro de page",
"pageNumberPlaceholder": "Veuillez saisir le numéro de page",
"pageSize": "Quantité par page",
"serverAlreadyExists": "Le serveur existe déjà, sautez l'importation",
"skipped": "Skip {count} Services",
"sync": "Commencer à se synchroniser",
"syncComplete": "Achèvement synchrone",
"syncing": "Synchronisation...",
"title": "Synchroniser les services MCP"
},
"name": "Modelcope",
"networkError": "Erreur de connexion réseau",
"notConnected": "Non connecté",
"verifyFailed": "Échec de la vérification",
"verifySuccess": "La vérification est réussie"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Optional consistency pass across locales

To ensure we didn’t miss any other “Modelcope/MODESCOPE” or non-{count} counters:


🏁 Script executed:

#!/bin/bash
# Scan i18n locales for brand typos and suspicious counters
rg -n "Modelcope|ModelCope|MODESCOPE" src/renderer/src/i18n

# Check common counter keys for non-{count} placeholders
rg -n '"errors"|"imported"|"skipped"' -A 2 src/renderer/src/i18n | rg -n '\{(?!count\})[^}]+\}'

Length of output: 2695


Fix inconsistent “Modelcope” usage across locales

The scan uncovered mismatched brand spellings in several locale files. Please update these to the canonical “Modelcope”:

  • src/renderer/src/i18n/ru-RU/settings.json:392
    • “ModelCope-это платформа…” → “Modelcope-это платформа…”
  • src/renderer/src/i18n/ja-JP/settings.json:410
    • “MODESCOPEからローカル構成までMCPサーバーを同期すると…” → “Modelcopeからローカル構成までMCPサーバーを同期すると…”
  • src/renderer/src/i18n/fa-IR/settings.json:
    • Line 386: “کلید API خود را در کنسول ModelCope دریافت کنید” → “…کنسول Modelcope…”
    • Line 397: “سرورهای MCP را همگام سازی کنید … سیستم عامل ModelCope استفاده شوند” → “…سیستم عامل Modelcope…”
    • Lines 387, 389, 402, 417: fix “Modelcope” consistency

For the counter placeholders check, ripgrep’s default engine doesn’t support look‐arounds. To catch any {…} that isn’t {count}, you can rerun with PCRE2:

rg -n '"errors"|"imported"|"skipped"' -A2 src/renderer/src/i18n \
  | rg --pcre2 -n '\{(?!count\})[^}]+\}'

Ensure no other non–{count} placeholders remain.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/fr-FR/settings.json around lines 381 to 435, ensure the
brand name is consistently "Modelcope" and fix incorrect placeholder tokens:
change "imported": "{comte} Les services ont été importés" to use the canonical
placeholder "{count}" and update "skipped": "Skip {count} Services" to a proper
French string keeping "{count}" (e.g. "Ignoré {count} services"); then apply the
same canonical "Modelcope" spelling fixes in the other locale files called out
by the reviewer (ru-RU, ja-JP, fa-IR) and run the provided ripgrep PCRE2 command
to find any other placeholders that are not "{count}" and correct them to use
"{count}" consistently.

Comment on lines +380 to +435
"oauthVerifyFailed": "OAuth 連接驗證失敗",
"configurationSaved": "配置已保存",
"configurationUpdated": "配置已更新",
"dataRefreshed": "數據已刷新",
"modelscope": {
"apiKey": "API 密鑰",
"apiKeyHelper": "在 ModelScope 控制台獲取您的 API Key",
"apiKeyPlaceholder": "請輸入 ModelScope API Key",
"baseUrl": "API 地址",
"baseUrlHelper": "ModelScope API 服務地址",
"connected": "已連接",
"connecting": "連接中...",
"description": "ModelScope 是阿里巴巴達摩院推出的模型即服務共享平台",
"details": {
"apiConfig": "API 配置",
"mcpSync": "MCP 同步",
"modelManagement": "模型管理",
"operationalDescription": "同步 ModelScope 平台上可直接使用的 MCP 服務器",
"operationalServers": "運營服務器",
"rateLimitConfig": "速率限製配置",
"safetySettings": "安全設置",
"specialConfig": "特殊配置",
"syncFromModelScope": "從 ModelScope 同步",
"title": "提供商設置詳情"
},
"invalidKey": "無效的 API Key",
"keyRequired": "請輸入 API Key",
"mcpSync": {
"authenticationFailed": "認證失敗,請檢查 API Key",
"convertingServers": "正在轉換服務器配置...",
"description": "從 ModelScope 同步 MCP 服務器到本地配置,可以快速添加常用的 MCP 工具。\n所有服務默認禁用,導入後可手動啟用。",
"errorDetails": "錯誤詳情",
"errors": "錯誤 {count} 個",
"fetchingServers": "正在獲取 MCP 服務器列表...",
"imported": "已導入 {count} 個服務",
"importingServers": "正在導入服務器配置...",
"invalidServerData": "無效的服務器數據",
"noApiKey": "請先配置 ModelScope API Key",
"noOperationalUrls": "未找到可用的運營地址",
"noServersFound": "未找到可用的 MCP 服務",
"pageNumber": "頁碼",
"pageNumberPlaceholder": "請輸入頁碼",
"pageSize": "每頁數量",
"serverAlreadyExists": "服務器已存在,跳過導入",
"skipped": "跳過 {count} 個服務",
"sync": "開始同步",
"syncComplete": "同步完成",
"syncing": "同步中...",
"title": "同步 MCP 服務"
},
"name": "ModelScope",
"networkError": "網絡連接錯誤",
"notConnected": "未連接",
"verifyFailed": "驗證失敗",
"verifySuccess": "驗證成功"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

ModelScope:粵/繁用語與錯別字修正(伺服器/限制/營運/連線/匯入)

  • 統一「服務器」→「伺服器」,「速率限製」→「速率限制」。
  • 「連接」→「連線」,「導入」→「匯入」,「運營」→「營運」。

範例修正(節選):

-      "connecting": "連接中...",
+      "connecting": "連線中...",
-        "convertingServers": "正在轉換服務器配置...",
+        "convertingServers": "正在轉換伺服器設定...",
-        "fetchingServers": "正在獲取 MCP 服務器列表...",
+        "fetchingServers": "正在取得 MCP 伺服器清單...",
-        "importingServers": "正在導入服務器配置...",
+        "importingServers": "正在匯入伺服器設定...",
-        "invalidServerData": "無效的服務器數據",
+        "invalidServerData": "無效的伺服器資料",
-        "noOperationalUrls": "未找到可用的運營地址",
+        "noOperationalUrls": "未找到可用的營運地址",
-        "serverAlreadyExists": "服務器已存在,跳過導入",
+        "serverAlreadyExists": "伺服器已存在,已略過匯入",
-        "pageSize": "每頁數量",
+        "pageSize": "每頁數量",
-        "operationalServers": "運營服務器",
+        "operationalServers": "營運伺服器",
-        "rateLimitConfig": "速率限製配置",
+        "rateLimitConfig": "速率限制配置"

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-HK/settings.json around lines 380 to 435, update
Cantonese/traditional Chinese terminology and typos: replace all occurrences of
"服務器" with "伺服器", "速率限製" with "速率限制", "連接" with "連線" (where used as network
connection), "導入" with "匯入", and "運營" with "營運"; adjust the affected strings
(e.g., "connecting", "connected", "connected/connecting helpers", MCP sync
messages like
importingServers/fetchingServers/imported/skipped/noOperationalUrls/operationalServers)
to use the corrected words and ensure punctuation/spacing remains valid JSON.

Comment on lines +269 to 273
"successDesc": "API 金鑰和設定驗證成功,可以正常使用",
"connectionError": "連接錯誤,請檢查網絡連接和 API 地址",
"serverError": "服務器錯誤,請稍後重試",
"unauthorized": "認證失敗,API Key 無效或已過期"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

用語統一(繁中在地化:連線/網路/位址/金鑰)

建議改為台灣慣用語,避免簡中用詞混入。

-        "successDesc": "API 金鑰和設定驗證成功,可以正常使用",
-        "connectionError": "連接錯誤,請檢查網絡連接和 API 地址",
-        "serverError": "服務器錯誤,請稍後重試",
-        "unauthorized": "認證失敗,API Key 無效或已過期"
+        "successDesc": "API 金鑰與設定驗證成功,可正常使用",
+        "connectionError": "連線錯誤,請檢查網路連線與 API 位址",
+        "serverError": "伺服器錯誤,請稍後重試",
+        "unauthorized": "認證失敗,API 金鑰無效或已過期"
📝 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
"successDesc": "API 金鑰和設定驗證成功,可以正常使用",
"connectionError": "連接錯誤,請檢查網絡連接和 API 地址",
"serverError": "服務器錯誤,請稍後重試",
"unauthorized": "認證失敗,API Key 無效或已過期"
},
"successDesc": "API 金鑰與設定驗證成功,可正常使用",
"connectionError": "連線錯誤,請檢查網路連線與 API 位址",
"serverError": "伺服器錯誤,請稍後重試",
"unauthorized": "認證失敗,API 金鑰無效或已過期"
},
🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-TW/settings.json around lines 269 to 273, the
current translations use Mainland Chinese terms; update the strings to
Taiwan-localized wording: replace "連接錯誤" with "連線錯誤" and mention "網路連線和 API 位址",
replace "服務器錯誤" with "伺服器錯誤" (or "伺服器發生錯誤"), and change "API Key" / "金鑰"
phrasing to use "API 金鑰" consistently (e.g., "認證失敗,API 金鑰無效或已過期"); also ensure
"API 金鑰和設定驗證成功,可以正常使用" follows the same wording conventions for "金鑰" and "連線" so
all four messages use Taiwan terms consistently.

zerob13 added a commit that referenced this pull request Aug 13, 2025
* fix: add AlertDialogDescription to resolve accessibility warning (#706)

* fix: resolve focus flicker when creating new windows with Ctrl+Shift+N (#707)

* feat: enhance window management by implementing main window ID handling (#709)

* docs: update zhipu developer doc website link (#715)

Co-authored-by: gongchao <chao.gong@aminer.cn>

* refactor: better translate (#716)

* chore: en-us i18n

* chore(i18n): polish ja-JP translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fr-FR translations; keep chat.input.placeholder unchanged

* chore(i18n): refine fr-FR MCP & Settings copy; idiomatic, concise, brand-consistent

* chore(i18n): polish ru-RU translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fa-IR translations across UI; keep chat.input.placeholder unchanged

* chore: fix format

* chore: fix i18n

* chore: lock rolldown-vite version

* feat: add GPT-5 series model support (#717)

* ci(vite): Bundle the main file into a single file to speed up loading. (#718)

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps (#721)

* chore: bump deps

* fix: rolldown-vite 7.1.0 and duckdb bundle issue

* chore: back to vite

* chore: update electron

* chore: update versions

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps

---------

Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* feat: add mcp sync and modelscope provider #615 (#723)

* wip: add modelscope provider

* feat: add mcp sync to modelscope

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* chore: i18n and format

* feat: better style

* fix: mcp tool display

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>

* fix: move_files newPath parse issue (#725)

* fix: move_files newPath 参数计算规则

* fix: move_files 移动前需要判断dest是目录还是文件

* feat: add Claude Opus 4.1 to anthropic default model list (#726)

* feat: Add mcprouter's MCP marketplace api support (#727)

* wip: add mcp market

* feat: mcp market install

* wip: mcp install status sync

* feat: mcp server config mask

* chore: remove working doc

* chore: add translate

* feat: add ESC key to close floating chat window (#728)

* feat: add floating button position persistence with boundary validation (#729)

* feat: add floating button position persistence with boundary validation

* feat: refactor floating button to use electron-window-state

* chore: bump to 0.3.0

* feat: add reasoning_effort parameter support for gpt-oss models (#731)

* feat: add reasoning_effort parameter support for gpt-oss models

- add reasoning effort UI support across all components

* fix: preserve user reasoning effort settings and improve display logic

* fix: artifacts code not streaming (#732)

* fix: artifact react load failed

* chore: remove log

* fix: artifacts code not stream

* fix: format

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
Co-authored-by: hllshiro <40970081+hllshiro@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: gongchao <chao.gong@aminer.cn>
Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
Co-authored-by: wanna <wanna.w@binarywalk.com>
zerob13 added a commit that referenced this pull request Aug 13, 2025
* fix: add AlertDialogDescription to resolve accessibility warning (#706)

* fix: resolve focus flicker when creating new windows with Ctrl+Shift+N (#707)

* feat: enhance window management by implementing main window ID handling (#709)

* docs: update zhipu developer doc website link (#715)

Co-authored-by: gongchao <chao.gong@aminer.cn>

* refactor: better translate (#716)

* chore: en-us i18n

* chore(i18n): polish ja-JP translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fr-FR translations; keep chat.input.placeholder unchanged

* chore(i18n): refine fr-FR MCP & Settings copy; idiomatic, concise, brand-consistent

* chore(i18n): polish ru-RU translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fa-IR translations across UI; keep chat.input.placeholder unchanged

* chore: fix format

* chore: fix i18n

* chore: lock rolldown-vite version

* feat: add GPT-5 series model support (#717)

* ci(vite): Bundle the main file into a single file to speed up loading. (#718)

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps (#721)

* chore: bump deps

* fix: rolldown-vite 7.1.0 and duckdb bundle issue

* chore: back to vite

* chore: update electron

* chore: update versions

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps

---------

Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* feat: add mcp sync and modelscope provider #615 (#723)

* wip: add modelscope provider

* feat: add mcp sync to modelscope

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* chore: i18n and format

* feat: better style

* fix: mcp tool display

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>

* fix: move_files newPath parse issue (#725)

* fix: move_files newPath 参数计算规则

* fix: move_files 移动前需要判断dest是目录还是文件

* feat: add Claude Opus 4.1 to anthropic default model list (#726)

* feat: Add mcprouter's MCP marketplace api support (#727)

* wip: add mcp market

* feat: mcp market install

* wip: mcp install status sync

* feat: mcp server config mask

* chore: remove working doc

* chore: add translate

* feat: add ESC key to close floating chat window (#728)

* feat: add floating button position persistence with boundary validation (#729)

* feat: add floating button position persistence with boundary validation

* feat: refactor floating button to use electron-window-state

* chore: bump to 0.3.0

* feat: add reasoning_effort parameter support for gpt-oss models (#731)

* feat: add reasoning_effort parameter support for gpt-oss models

- add reasoning effort UI support across all components

* fix: preserve user reasoning effort settings and improve display logic

* fix: artifacts code not streaming (#732)

* fix: artifact react load failed

* chore: remove log

* fix: artifacts code not stream

* fix: format

* feat: disable automatic model enabling for better UX (#734)

* feat: sync provider sorting from settings to model selection (#736)

* feat: sync provider sorting from settings to model selection

* feat: refactor ModelSelect to use computed providers for better reactivity

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
Co-authored-by: hllshiro <40970081+hllshiro@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: gongchao <chao.gong@aminer.cn>
Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
Co-authored-by: wanna <wanna.w@binarywalk.com>
@zerob13 zerob13 deleted the feature/add-modelscope-provider branch September 21, 2025 15:15
@coderabbitai coderabbitai bot mentioned this pull request Dec 1, 2025
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.

3 participants