Skip to content

Conversation

@yyhhyyyyyy
Copy link
Collaborator

@yyhhyyyyyy yyhhyyyyyy commented Oct 11, 2025

refactor capability-driven model config + i18n

Summary by CodeRabbit

  • New Features

    • Capability-driven configuration for reasoning, thinking budget ranges, and search (with defaults, forced, and strategy options).
    • Unified Thinking Budget and Search sections in chat and settings, with conditional visibility and auto-populated defaults.
    • Reasoning toggle appears only when supported.
  • Refactor

    • Replaced hard-coded, per-model logic with a centralized capability-based approach.
    • Simplified validation to a single generic path.
  • i18n

    • Added description/placeholder and unified validation (required/min/max) for Thinking Budget across locales.
    • Removed model-specific texts; minor label casing updates in some languages.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 11, 2025

Walkthrough

Adds capability-query APIs to ConfigPresenter and IConfigPresenter, delegating to modelCapabilities. Refactors ChatConfig.vue and ModelConfigDialog.vue to query capabilities and render unified UI for reasoning, thinking budget, and search. Standardizes i18n thinkingBudget strings across locales with generic description/placeholder/validation.

Changes

Cohort / File(s) Summary
Presenter capability API
src/main/presenter/configPresenter/index.ts, src/shared/types/presenters/legacy.presenters.d.ts
ConfigPresenter imports modelCapabilities and adds four methods: supportsReasoningCapability, getThinkingBudgetRange, supportsSearchCapability, getSearchDefaults. IConfigPresenter interface extended with these optional methods.
Renderer components: capability-driven UI
src/renderer/src/components/ChatConfig.vue, src/renderer/src/components/settings/ModelConfigDialog.vue
Replaces per-model conditionals with capability-driven state and computed values. Adds fetchCapabilities, unified thinking budget handling and validation, and unified search controls with defaults/visibility driven by capabilities.
i18n: thinkingBudget standardization
src/renderer/src/i18n/*/settings.json (en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW)
Removes model-specific Gemini/Qwen3 blocks. Adds thinkingBudget.description and placeholder. Introduces unified validation messages: required, minValue, maxValue. Minor label casing adjustments in some locales.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant C1 as ChatConfig.vue
  participant C2 as ModelConfigDialog.vue
  participant P as ConfigPresenter
  participant MC as modelCapabilities

  rect rgba(200,220,255,0.2)
    note over U,C1: Open chat or change provider/model
    U->>C1: Open / Change selection
    C1->>P: fetchCapabilities(providerId, modelId)\n(supportsReasoning, getBudgetRange,\n supportsSearch, getSearchDefaults)
    P->>MC: Query capability data
    MC-->>P: capability info
    P-->>C1: capability info
    C1-->>C1: Derive UI flags & defaults
  end

  rect rgba(200,255,200,0.2)
    note over U,C2: Open Model Config dialog
    U->>C2: Open dialog
    C2->>P: fetchCapabilities(providerId, modelId)
    P->>MC: Query capability data
    MC-->>P: capability info
    P-->>C2: capability info
    C2-->>C2: Render reasoning, budget, search sections
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • zerob13

Poem

I twitch my ears at configs bright,
New caps hop in, a tidy sight.
Budgets think, and searches start,
One burrowed brain, one beating heart.
With unified paths, I thump—hooray!
Less maze to map, more time to play.
(\/)<(^^)> 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly captures the primary change by indicating a refactor toward capability-driven model configuration and accompanying i18n updates, accurately reflecting the broad scope of code and localization changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/capability-driven-model-config

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@zerob13 zerob13 merged commit 580d1de into dev Oct 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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/src/components/ChatConfig.vue (1)

435-460: Respect capability-provided defaults for search options.

When the presenter exposes default/forced/strategy values via getSearchDefaults, the UI still renders enableSearch, forcedSearch, and searchStrategy as if the defaults were false/'turbo' whenever the conversation hasn’t overridden them. This misleads users and can unintentionally disable provider-required behaviors. Please derive the displayed values from capabilitySearchDefaults before falling back to hardcoded defaults. Suggested update:

+const resolvedEnableSearch = computed(() => {
+  return props.enableSearch ?? capabilitySearchDefaults.value?.default ?? false
+})
+
+const resolvedForcedSearch = computed(() => {
+  if (!hasForcedSearchOption.value) return props.forcedSearch ?? false
+  return props.forcedSearch ?? capabilitySearchDefaults.value?.forced ?? false
+})
+
+const resolvedSearchStrategy = computed(() => {
+  if (!hasSearchStrategyOption.value) return props.searchStrategy ?? 'turbo'
+  return props.searchStrategy ?? capabilitySearchDefaults.value?.strategy ?? 'turbo'
+})
-            <Switch
-              :model-value="props.enableSearch ?? false"
+            <Switch
+              :model-value="resolvedEnableSearch"
               @update:model-value="(value) => emit('update:enableSearch', value)"
             />
…
-          <div v-if="props.enableSearch && hasForcedSearchOption" class="flex items-center justify-between">
+          <div v-if="resolvedEnableSearch && hasForcedSearchOption" class="flex items-center justify-between">-            <Switch :model-value="props.forcedSearch ?? false" @update:model-value="(value) => emit('update:forcedSearch', value)" />
+            <Switch
+              :model-value="resolvedForcedSearch"
+              @update:model-value="(value) => emit('update:forcedSearch', value)"
+            />-          <div v-if="props.enableSearch && hasSearchStrategyOption" class="space-y-2">
+          <div v-if="resolvedEnableSearch && hasSearchStrategyOption" class="space-y-2">-            <Select :model-value="props.searchStrategy ?? 'turbo'" @update:model-value="(value) => emit('update:searchStrategy', value as 'turbo' | 'max')">
+            <Select
+              :model-value="resolvedSearchStrategy"
+              @update:model-value="(value) =>
+                emit('update:searchStrategy', value as 'turbo' | 'max')"
+              "
+            >

Remember to import/use the new computed values where needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f730d53 and f6ed6a3.

📒 Files selected for processing (14)
  • src/main/presenter/configPresenter/index.ts (2 hunks)
  • src/renderer/src/components/ChatConfig.vue (7 hunks)
  • src/renderer/src/components/settings/ModelConfigDialog.vue (10 hunks)
  • src/renderer/src/i18n/en-US/settings.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (1 hunks)
  • src/renderer/src/i18n/pt-BR/settings.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (1 hunks)
  • src/shared/types/presenters/legacy.presenters.d.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (25)
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/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/components/ChatConfig.vue
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/en-US/settings.json
src/renderer/src/**

📄 CodeRabbit inference engine (AGENTS.md)

Put application code for the Vue app under src/renderer/src (components, stores, views, i18n, lib)

Files:

  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/components/ChatConfig.vue
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/en-US/settings.json
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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.

Use Pinia for frontend state management (do not introduce alternative state libraries)

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for all logs and comments

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
  • src/main/presenter/configPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
  • src/main/presenter/configPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
src/renderer/{src,shell,floating}/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/{src,shell,floating}/**/*.vue: Use Vue 3 Composition API for all components
All user-facing strings must use i18n keys via vue-i18n (no hard-coded UI strings)
Use Tailwind CSS utilities and ensure styles are scoped in Vue components

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/src/components/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Organize UI components by feature within src/renderer/src/

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/src/**/*.{vue,ts}

📄 CodeRabbit inference engine (AGENTS.md)

All user-facing strings in the renderer must use vue-i18n keys defined in src/renderer/src/i18n

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
**/*.{js,jsx,ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting: single quotes, no semicolons, max width 100

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
  • src/main/presenter/configPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
src/renderer/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue components in PascalCase (e.g., ChatInput.vue)

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

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

**/*.{js,jsx,ts,tsx}: Use OxLint for JS/TS code; pre-commit hooks run lint-staged and typecheck
Use camelCase for variables and functions
Use PascalCase for types and classes
Use SCREAMING_SNAKE_CASE for constants

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.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/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

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

Files:

  • src/main/presenter/configPresenter/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-logging.mdc)

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

Files:

  • src/main/presenter/configPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.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/**

📄 CodeRabbit inference engine (AGENTS.md)

Place all Electron main-process code under src/main/

Files:

  • src/main/presenter/configPresenter/index.ts
src/main/presenter/**

📄 CodeRabbit inference engine (AGENTS.md)

src/main/presenter/**: Organize main-process presenters under src/main/presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider)
Follow the Presenter pattern for main-process modules

Files:

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

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

共享类型定义放在 shared 目录

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place shared types, utilities, constants, and IPC contract definitions under src/shared/

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**

📄 CodeRabbit inference engine (AGENTS.md)

Store shared TypeScript types/utilities in src/shared/

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
🧠 Learnings (1)
📚 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/{composables,utils}/**/*.ts : Use VueUse for common composables and utility functions.

Applied to files:

  • src/renderer/src/components/ChatConfig.vue
🧬 Code graph analysis (1)
src/main/presenter/configPresenter/index.ts (1)
src/main/presenter/configPresenter/modelCapabilities.ts (1)
  • modelCapabilities (103-103)
🪛 GitHub Actions: PR Check
src/renderer/src/components/settings/ModelConfigDialog.vue

[error] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues in this file.

src/renderer/src/components/ChatConfig.vue

[error] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues in this file.

🔇 Additional comments (2)
src/renderer/src/components/ChatConfig.vue (1)

1-200: Prettier check failing—please reformat before merge.

CI reports a Prettier violation for this file. Please run the project’s Prettier configuration (e.g. pnpm prettier --write src/renderer/src/components/ChatConfig.vue) and commit the formatted output so the pipeline passes.

src/renderer/src/components/settings/ModelConfigDialog.vue (1)

1-366: Run Prettier so CI passes

The PR check is failing on Prettier for this file. Please run the project’s Prettier command (e.g. pnpm prettier --write src/renderer/src/components/settings/ModelConfigDialog.vue) and commit the result.

Comment on lines 130 to 188
// 能力:统一控制思考预算和搜索配置显示
const capabilitySupportsReasoning = ref<boolean | null>(null)
const capabilityBudgetRange = ref<{ min?: number; max?: number; default?: number } | null>(null)
const capabilitySupportsSearch = ref<boolean | null>(null)
const capabilitySearchDefaults = ref<{ default?: boolean; forced?: boolean; strategy?: 'turbo' | 'max' } | null>(null)
const fetchCapabilities = async () => {
if (!props.providerId || !props.modelId) {
capabilitySupportsReasoning.value = null
capabilityBudgetRange.value = null
capabilitySupportsSearch.value = null
return
}
try {
const [sr, br, ss, sd] = await Promise.all([
configPresenter.supportsReasoningCapability?.(props.providerId, props.modelId),
configPresenter.getThinkingBudgetRange?.(props.providerId, props.modelId),
configPresenter.supportsSearchCapability?.(props.providerId, props.modelId),
configPresenter.getSearchDefaults?.(props.providerId, props.modelId)
])
capabilitySupportsReasoning.value = typeof sr === 'boolean' ? sr : null
capabilityBudgetRange.value = br || {}
capabilitySupportsSearch.value = typeof ss === 'boolean' ? ss : null
capabilitySearchDefaults.value = sd || null
} catch {
capabilitySupportsReasoning.value = null
capabilityBudgetRange.value = null
capabilitySupportsSearch.value = null
capabilitySearchDefaults.value = null
}
}
return (isGemini && isGemini25) || (isDashscope && isQwenThinking && modelReasoning.value)
})
watch(
() => [props.providerId, props.modelId],
async () => {
await fetchCapabilities()
},
{ immediate: true }
)
// 是否显示搜索配置 - 支持 Dashscope 的特定模型
const showDashscopeSearchConfig = computed(() => {
const isDashscope = props.providerId === 'dashscope'
if (!isDashscope || !props.modelId) return false
// Dashscope - ENABLE_SEARCH_MODELS
const enableSearchModels = [
'qwen3-max-preview',
'qwen3-max-2025-09-23',
'qwen3-max',
'qwen-max',
'qwen-plus',
'qwen-plus-latest',
'qwen-plus-2025-07-14',
'qwen-flash',
'qwen-flash-2025-07-28',
'qwen-turbo',
'qwen-turbo-latest',
'qwen-turbo-2025-07-15',
'qwq-plus'
]
return enableSearchModels.some((modelName) =>
props.modelId?.toLowerCase().includes(modelName.toLowerCase())
const showThinkingBudget = computed(() => {
return (
modelReasoning.value &&
capabilitySupportsReasoning.value === true &&
!!capabilityBudgetRange.value &&
(capabilityBudgetRange.value!.min !== undefined ||
capabilityBudgetRange.value!.max !== undefined ||
capabilityBudgetRange.value!.default !== undefined)
)
})
// 是否显示搜索配置 - 支持 Gemini 的特定模型
const showGeminiSearchConfig = computed(() => {
const isSearchableModel = props.providerId === 'gemini'
if (!isSearchableModel || !props.modelId) return false
// ENABLE_SEARCH_MODELS
const enableSearchModels = [
'gemini-2.5-pro',
'gemini-2.5-flash',
'gemini-2.5-flash-lite',
'gemini-2.5-flash-lite-preview-06-17',
'gemini-2.0-flash',
'gemini-2.0-flash-lite',
'gemini-1.5-pro',
'gemini-1.5-flash'
]
return enableSearchModels.some((modelName) =>
props.modelId?.toLowerCase().includes(modelName.toLowerCase())
)
})
// 是否显示搜索配置(统一基于能力)
const showSearchConfig = computed(() => capabilitySupportsSearch.value === true)
const hasForcedSearchOption = computed(() => capabilitySearchDefaults.value?.forced !== undefined)
const hasSearchStrategyOption = computed(
() => capabilitySearchDefaults.value?.strategy !== undefined
)
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 | 🟠 Major

Convert inline comments to English.

The newly added comments (lines 130, 182, 375, 440, 448) are written in Chinese, but our renderer guidelines require English for all comments/logs. Please translate or remove them to stay compliant.

🤖 Prompt for AI Agents
In src/renderer/src/components/ChatConfig.vue around lines 130-188 (and also
update lines 182, 375, 440, 448 mentioned in the review), replace the Chinese
inline comments with concise English equivalents (or remove them) to comply with
renderer guidelines; keep the comment meaning unchanged (e.g., translate
"能力:统一控制思考预算和搜索配置显示" to "Capability: unified control for thinking budget and
search config display", "是否显示搜索配置(统一基于能力)" to "Show search configuration
(controlled by capability)", etc.), ensuring comment style and placement remain
the same.

Comment on lines +616 to +631
const [sr, br, ss, sd] = await Promise.all([
configPresenter.supportsReasoningCapability?.(props.providerId, props.modelId),
configPresenter.getThinkingBudgetRange?.(props.providerId, props.modelId),
configPresenter.supportsSearchCapability?.(props.providerId, props.modelId),
configPresenter.getSearchDefaults?.(props.providerId, props.modelId)
])
capabilitySupportsReasoning.value = typeof sr === 'boolean' ? sr : null
capabilityBudgetRange.value = br || {}
capabilitySupportsSearch.value = typeof ss === 'boolean' ? ss : null
capabilitySearchDefaults.value = sd || null
} catch {
capabilitySupportsReasoning.value = null
capabilityBudgetRange.value = null
capabilitySupportsSearch.value = null
capabilitySearchDefaults.value = null
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reset unsupported capability fields before saving

We hide the reasoning/search controls when the presenter says the model can’t handle them, but we never clear the underlying config values. If a user previously enabled reasoning or search, those stale config.value flags stay true and get persisted even though the capability is now false, leaving us with an invalid, non-editable state. Please zero out the related fields as soon as the capability check fails.

     capabilitySupportsReasoning.value = typeof sr === 'boolean' ? sr : null
+    if (capabilitySupportsReasoning.value === false) {
+      config.value.reasoning = false
+      config.value.thinkingBudget = undefined
+    }
     capabilityBudgetRange.value = br || {}
     capabilitySupportsSearch.value = typeof ss === 'boolean' ? ss : null
+    if (capabilitySupportsSearch.value !== true) {
+      config.value.enableSearch = false
+      config.value.forcedSearch = false
+      config.value.searchStrategy = 'turbo'
+    }
     capabilitySearchDefaults.value = sd || null
📝 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
const [sr, br, ss, sd] = await Promise.all([
configPresenter.supportsReasoningCapability?.(props.providerId, props.modelId),
configPresenter.getThinkingBudgetRange?.(props.providerId, props.modelId),
configPresenter.supportsSearchCapability?.(props.providerId, props.modelId),
configPresenter.getSearchDefaults?.(props.providerId, props.modelId)
])
capabilitySupportsReasoning.value = typeof sr === 'boolean' ? sr : null
capabilityBudgetRange.value = br || {}
capabilitySupportsSearch.value = typeof ss === 'boolean' ? ss : null
capabilitySearchDefaults.value = sd || null
} catch {
capabilitySupportsReasoning.value = null
capabilityBudgetRange.value = null
capabilitySupportsSearch.value = null
capabilitySearchDefaults.value = null
}
const [sr, br, ss, sd] = await Promise.all([
configPresenter.supportsReasoningCapability?.(props.providerId, props.modelId),
configPresenter.getThinkingBudgetRange?.(props.providerId, props.modelId),
configPresenter.supportsSearchCapability?.(props.providerId, props.modelId),
configPresenter.getSearchDefaults?.(props.providerId, props.modelId)
])
capabilitySupportsReasoning.value = typeof sr === 'boolean' ? sr : null
if (capabilitySupportsReasoning.value === false) {
config.value.reasoning = false
config.value.thinkingBudget = undefined
}
capabilityBudgetRange.value = br || {}
capabilitySupportsSearch.value = typeof ss === 'boolean' ? ss : null
if (capabilitySupportsSearch.value !== true) {
config.value.enableSearch = false
config.value.forcedSearch = false
config.value.searchStrategy = 'turbo'
}
capabilitySearchDefaults.value = sd || null
} catch {
capabilitySupportsReasoning.value = null
capabilityBudgetRange.value = null
capabilitySupportsSearch.value = null
capabilitySearchDefaults.value = null
}

Comment on lines +387 to +396
supportsReasoningCapability?(providerId: string, modelId: string): boolean
getThinkingBudgetRange?(
providerId: string,
modelId: string
): { min?: number; max?: number; default?: number }
supportsSearchCapability?(providerId: string, modelId: string): boolean
getSearchDefaults?(
providerId: string,
modelId: string
): { default?: boolean; forced?: boolean; strategy?: 'turbo' | 'max' }
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 | 🟠 Major

Declare capability helpers as async in the contract.

These helpers are consumed with await and implemented asynchronously in the presenter layer, but the declaration still returns plain booleans/objects. Please update the signatures to return Promise<...> so implementations type-check correctly and downstream usage matches reality.

-  supportsReasoningCapability?(providerId: string, modelId: string): boolean
+  supportsReasoningCapability?(
+    providerId: string,
+    modelId: string
+  ): Promise<boolean>
   getThinkingBudgetRange?(
     providerId: string,
     modelId: string
-  ): { min?: number; max?: number; default?: number }
-  supportsSearchCapability?(providerId: string, modelId: string): boolean
+  ): Promise<{ min?: number; max?: number; default?: number }>
+  supportsSearchCapability?(
+    providerId: string,
+    modelId: string
+  ): Promise<boolean>
   getSearchDefaults?(
     providerId: string,
     modelId: string
-  ): { default?: boolean; forced?: boolean; strategy?: 'turbo' | 'max' }
+  ): Promise<{ default?: boolean; forced?: boolean; strategy?: 'turbo' | 'max' }>
📝 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
supportsReasoningCapability?(providerId: string, modelId: string): boolean
getThinkingBudgetRange?(
providerId: string,
modelId: string
): { min?: number; max?: number; default?: number }
supportsSearchCapability?(providerId: string, modelId: string): boolean
getSearchDefaults?(
providerId: string,
modelId: string
): { default?: boolean; forced?: boolean; strategy?: 'turbo' | 'max' }
supportsReasoningCapability?(
providerId: string,
modelId: string
): Promise<boolean>
getThinkingBudgetRange?(
providerId: string,
modelId: string
): Promise<{ min?: number; max?: number; default?: number }>
supportsSearchCapability?(
providerId: string,
modelId: string
): Promise<boolean>
getSearchDefaults?(
providerId: string,
modelId: string
): Promise<{ default?: boolean; forced?: boolean; strategy?: 'turbo' | 'max' }>
🤖 Prompt for AI Agents
In src/shared/types/presenters/legacy.presenters.d.ts around lines 387 to 396,
the capability helper signatures are declared as synchronous (returning boolean
or object) but are implemented and consumed asynchronously; update the four
method signatures—supportsReasoningCapability, getThinkingBudgetRange,
supportsSearchCapability, and getSearchDefaults—to return Promise<boolean> and
Promise<{ min?: number; max?: number; default?: number }> / Promise<{ default?:
boolean; forced?: boolean; strategy?: 'turbo' | 'max' }> respectively so
implementations and callers type-check correctly.

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: 2

🧹 Nitpick comments (6)
src/renderer/src/components/ChatConfig.vue (2)

140-164: Prevent stale capability state on rapid model/provider changes

watch triggers fetchCapabilities concurrently; late responses can overwrite newer state. Add a simple request token to guard:

+let capabilityReqId = 0
 const fetchCapabilities = async () => {
-  if (!props.providerId || !props.modelId) {
+  const reqId = ++capabilityReqId
+  if (!props.providerId || !props.modelId) {
     capabilitySupportsReasoning.value = null
     capabilityBudgetRange.value = null
     capabilitySupportsSearch.value = null
     return
   }
   try {
     const [sr, br, ss, sd] = await Promise.all([
       configPresenter.supportsReasoningCapability?.(props.providerId, props.modelId),
       configPresenter.getThinkingBudgetRange?.(props.providerId, props.modelId),
       configPresenter.supportsSearchCapability?.(props.providerId, props.modelId),
       configPresenter.getSearchDefaults?.(props.providerId, props.modelId)
     ])
+    if (reqId !== capabilityReqId) return
     capabilitySupportsReasoning.value = typeof sr === 'boolean' ? sr : null
     capabilityBudgetRange.value = br || {}
     capabilitySupportsSearch.value = typeof ss === 'boolean' ? ss : null
     capabilitySearchDefaults.value = sd || null
   } catch {
+    if (reqId !== capabilityReqId) return
     capabilitySupportsReasoning.value = null
     capabilityBudgetRange.value = null
     capabilitySupportsSearch.value = null
     capabilitySearchDefaults.value = null
   }
 }

130-139: Non-English comments

Comments are in Chinese. Use English for all logs and comments.

As per coding guidelines

Also applies to: 378-410, 412-487

src/renderer/src/components/settings/ModelConfigDialog.vue (4)

483-509: Deduplicate applying search capability defaults

Defaults for enableSearch/forcedSearch/strategy are set twice. Extract once to avoid drift.

-  await fetchCapabilities()
-
-  if (config.value.thinkingBudget === undefined) {
-    const range = capabilityBudgetRange.value
-    if (range && typeof range.default === 'number') {
-      config.value.thinkingBudget = range.default
-    }
-    if (capabilitySupportsSearch.value === true && capabilitySearchDefaults.value) {
-      if (config.value.isUserDefined !== true) {
-        const def = capabilitySearchDefaults.value
-        if (typeof def.default === 'boolean') config.value.enableSearch = def.default
-        if (typeof def.forced === 'boolean') config.value.forcedSearch = def.forced
-        if (def.strategy === 'turbo' || def.strategy === 'max')
-          config.value.searchStrategy = def.strategy
-      }
-    }
-  }
-
-  if (capabilitySupportsSearch.value === true && capabilitySearchDefaults.value) {
-    if (config.value.isUserDefined !== true) {
-      const def = capabilitySearchDefaults.value
-      if (typeof def.default === 'boolean') config.value.enableSearch = def.default
-      if (typeof def.forced === 'boolean') config.value.forcedSearch = def.forced
-      if (def.strategy === 'turbo' || def.strategy === 'max')
-        config.value.searchStrategy = def.strategy
-    }
-  }
+  await fetchCapabilities()
+
+  // Apply capability-driven defaults when not user-defined
+  const applyCapabilityDefaults = () => {
+    const range = capabilityBudgetRange.value
+    if (config.value.thinkingBudget === undefined && range && typeof range.default === 'number') {
+      config.value.thinkingBudget = range.default
+    }
+    if (config.value.isUserDefined !== true && capabilitySupportsSearch.value === true) {
+      const def = capabilitySearchDefaults.value
+      if (def) {
+        if (typeof def.default === 'boolean') config.value.enableSearch = def.default
+        if (typeof def.forced === 'boolean') config.value.forcedSearch = def.forced
+        if (def.strategy === 'turbo' || def.strategy === 'max') config.value.searchStrategy = def.strategy
+      }
+    }
+  }
+  applyCapabilityDefaults()

Also applies to: 501-509


661-676: Align thinking-budget validation with ChatConfig (required vs optional)

Here the field is required when visible; in ChatConfig it’s optional. Decide one behavior and apply consistently. If optional, remove the “required” branch:

-  if (value === undefined || value === null) {
-    return t('settings.model.modelConfig.thinkingBudget.validation.required')
-  }
+  if (value === undefined || value === null) return ''

736-739: Reasoning toggle should be shown only when supported, or already enabled

Using “!== false” shows toggle even when capability is unknown. Prefer explicit support or preserving existing true:

-const showReasoningToggle = computed(() => {
-  return capabilitySupportsReasoning.value !== false
-})
+const showReasoningToggle = computed(() => {
+  return capabilitySupportsReasoning.value === true || config.value.reasoning === true
+})

372-407: Non-English comments

Comments are in Chinese. Use English for all logs and comments.

As per coding guidelines

Also applies to: 217-257, 258-314

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f730d53 and 1a06ba2.

📒 Files selected for processing (14)
  • src/main/presenter/configPresenter/index.ts (2 hunks)
  • src/renderer/src/components/ChatConfig.vue (8 hunks)
  • src/renderer/src/components/settings/ModelConfigDialog.vue (11 hunks)
  • src/renderer/src/i18n/en-US/settings.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (1 hunks)
  • src/renderer/src/i18n/pt-BR/settings.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (1 hunks)
  • src/shared/types/presenters/legacy.presenters.d.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (25)
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/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/components/ChatConfig.vue
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
src/renderer/src/**

📄 CodeRabbit inference engine (AGENTS.md)

Put application code for the Vue app under src/renderer/src (components, stores, views, i18n, lib)

Files:

  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/components/ChatConfig.vue
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

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

**/*.{js,jsx,ts,tsx}: Use OxLint for JS/TS code; pre-commit hooks run lint-staged and typecheck
Use camelCase for variables and functions
Use PascalCase for types and classes
Use SCREAMING_SNAKE_CASE for constants

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/configPresenter/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-logging.mdc)

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

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/configPresenter/index.ts
src/shared/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

共享类型定义放在 shared 目录

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for all logs and comments

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
  • src/main/presenter/configPresenter/index.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
  • src/main/presenter/configPresenter/index.ts
src/shared/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place shared types, utilities, constants, and IPC contract definitions under src/shared/

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**

📄 CodeRabbit inference engine (AGENTS.md)

Store shared TypeScript types/utilities in src/shared/

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
**/*.{js,jsx,ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting: single quotes, no semicolons, max width 100

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
  • src/main/presenter/configPresenter/index.ts
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.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.

Use Pinia for frontend state management (do not introduce alternative state libraries)

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/{src,shell,floating}/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/{src,shell,floating}/**/*.vue: Use Vue 3 Composition API for all components
All user-facing strings must use i18n keys via vue-i18n (no hard-coded UI strings)
Use Tailwind CSS utilities and ensure styles are scoped in Vue components

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/src/components/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Organize UI components by feature within src/renderer/src/

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/src/**/*.{vue,ts}

📄 CodeRabbit inference engine (AGENTS.md)

All user-facing strings in the renderer must use vue-i18n keys defined in src/renderer/src/i18n

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue components in PascalCase (e.g., ChatInput.vue)

Files:

  • src/renderer/src/components/settings/ModelConfigDialog.vue
  • src/renderer/src/components/ChatConfig.vue
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/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

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

Files:

  • src/main/presenter/configPresenter/index.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/**

📄 CodeRabbit inference engine (AGENTS.md)

Place all Electron main-process code under src/main/

Files:

  • src/main/presenter/configPresenter/index.ts
src/main/presenter/**

📄 CodeRabbit inference engine (AGENTS.md)

src/main/presenter/**: Organize main-process presenters under src/main/presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider)
Follow the Presenter pattern for main-process modules

Files:

  • src/main/presenter/configPresenter/index.ts
🧠 Learnings (2)
📚 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/{composables,utils}/**/*.ts : Use VueUse for common composables and utility functions.

Applied to files:

  • src/renderer/src/components/ChatConfig.vue
📚 Learning: 2025-09-06T03:07:23.817Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-06T03:07:23.817Z
Learning: Applies to src/main/presenter/configPresenter/providers.ts : Add provider configuration entries in src/main/presenter/configPresenter/providers.ts

Applied to files:

  • src/main/presenter/configPresenter/index.ts
🧬 Code graph analysis (1)
src/main/presenter/configPresenter/index.ts (1)
src/main/presenter/configPresenter/modelCapabilities.ts (1)
  • modelCapabilities (103-103)
⏰ 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 (12)
src/renderer/src/i18n/fa-IR/settings.json (1)

160-167: Unify terminology and include missing {min} placeholder in fa-IR/settings.json

  • In thinkingBudget.description, replace “توکن” with “نشانه‌های” for consistency.
  • In thinkingBudget.validation.minValue, change to “مقدار نمی‌تواند کمتر از {min} باشد”.

Verify that all other locales define identical thinkingBudget keys and include both {min} and {max} placeholders.

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

172-179: Unified thinkingBudget keys look good

Consolidation to description/placeholder/validation is consistent and clear. Placeholders align with range text.

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

160-167: LGTM on unified thinkingBudget

Consistent keys and correct {min}/{max} placeholders.

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

160-167: Thinking budget i18n updated correctly

Unified keys and validation messages are consistent with other locales.

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

160-167: Good consolidation

Unified thinkingBudget fields and validation read well; placeholders OK.

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

159-167: LGTM, plus minor label polish

Unified structure is correct; label case change is fine. Placeholders align with range.

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

160-167: Looks good

Unified thinkingBudget keys and validation are consistent across locales.

src/renderer/src/i18n/pt-BR/settings.json (1)

160-167: Consolidation approved

Description/placeholder/validation for thinkingBudget are correct; placeholders match range.

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

160-167: No stale thinkingBudget.gemini/qwen3 keys found; unified thinkingBudget keys confirmed in all locales

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

36-36: Capability-query methods added and wired correctly

Delegations to modelCapabilities with precise return types; matches IConfigPresenter optional surface.

Confirm these methods are exposed through the preload/bridge so usePresenter('configPresenter') sees them. If exposure is reflective, no action needed; otherwise add them to the exposed API.

Also applies to: 212-233

src/shared/types/presenters/legacy.presenters.d.ts (1)

387-396: Interface surface extended for capabilities

Optional methods and their types align with presenter and renderer usage.

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

159-167: ThinkingBudget i18n keys defined across all locales
All required subkeys (label, description, placeholder, range, validation.required, minValue, maxValue) are present and align with the renderer’s UI usage.

Comment on lines +174 to 183
const showThinkingBudget = computed(() => {
return (
modelReasoning.value &&
capabilitySupportsReasoning.value === true &&
!!capabilityBudgetRange.value &&
(capabilityBudgetRange.value!.min !== undefined ||
capabilityBudgetRange.value!.max !== undefined ||
capabilityBudgetRange.value!.default !== undefined)
)
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Unify thinking-budget visibility criteria with ModelConfigDialog

Here you show when any of min/max/default exists. In ModelConfigDialog, visibility depends only on max being defined, which can hide this section for valid ranges. Align both to the “any-of min/max/default” rule to avoid inconsistent UI.

🤖 Prompt for AI Agents
In src/renderer/src/components/ChatConfig.vue around lines 174 to 183, the
computed showThinkingBudget uses "any-of min/max/default" to decide visibility;
update the corresponding visibility logic in ModelConfigDialog to match this
rule so the UI is consistent: change its condition to check
capabilityBudgetRange exists and that at least one of min, max, or default is
not undefined (instead of only checking max), and keep any existing
capabilitySupportsReasoning/modelReasoning checks so the combined predicate
mirrors ChatConfig.vue.

Comment on lines +601 to 606
const showThinkingBudget = computed(() => {
const hasReasoning = config.value.reasoning
const modelConfig = getThinkingBudgetConfig(props.modelId)
const isSupported = modelConfig !== null
return isGemini && hasReasoning && isSupported
})
// 是否显示Qwen3思考预算配置
const showQwen3ThinkingBudget = computed(() => {
const isDashscope = props.providerId === 'dashscope'
const hasReasoning = config.value.reasoning
const modelId = props.modelId.toLowerCase()
// DashScope - ENABLE_THINKING_MODELS
const supportedThinkingModels = [
// Open source versions
'qwen3-next-80b-a3b-thinking',
'qwen3-235b-a22b',
'qwen3-32b',
'qwen3-30b-a3b',
'qwen3-14b',
'qwen3-8b',
'qwen3-4b',
'qwen3-1.7b',
'qwen3-0.6b',
// Commercial versions
'qwen3-vl-plus',
'qwen-plus',
'qwen-plus-latest',
'qwen-plus-2025-04-28',
'qwen-flash',
'qwen-flash-2025-07-28',
'qwen-turbo',
'qwen-turbo-latest',
'qwen-turbo-2025-04-28'
]
const isSupported = supportedThinkingModels.some((supportedModel) =>
modelId.includes(supportedModel)
)
const modelConfig = getThinkingBudgetConfig(props.modelId)
const hasValidConfig = modelConfig !== null
return isDashscope && hasReasoning && isSupported && hasValidConfig
})
// 是否显示DashScope搜索配置
const showDashScopeSearch = computed(() => {
const isDashscope = props.providerId === 'dashscope'
const modelId = props.modelId.toLowerCase()
// DashScope - ENABLE_SEARCH_MODELS
const supportedSearchModels = [
'qwen3-max-2025-09-23',
'qwen3-max-preview',
'qwen3-max',
'qwen-max',
'qwen-plus',
'qwen-flash',
'qwen-turbo',
'qwq-plus'
]
const isSupported = supportedSearchModels.some((supportedModel) =>
modelId.includes(supportedModel)
)
return isDashscope && isSupported
})
// 是否显示Grok搜索配置
const showGrokSearch = computed(() => {
const isGrok = props.providerId === 'grok'
const modelId = props.modelId.toLowerCase()
// According to requirements, all Grok models support internet search
const supportedSearchModels = [
'grok-4',
'grok-3-mini',
'grok-3-mini-fast',
'grok-3-fast',
'grok-3',
'grok-2',
'grok-2-vision',
'grok-2-image'
]
const isSupported =
supportedSearchModels.some((supportedModel) => modelId.includes(supportedModel)) ||
modelId.includes('grok')
return isGrok && isSupported
})
// 是否显示Gemini搜索配置
const showGeminiSearch = computed(() => {
const isGemini = props.providerId === 'gemini'
const modelId = props.modelId.toLowerCase()
const supportedSearchModels = [
'gemini-2.5-pro',
'gemini-2.5-flash',
'gemini-2.5-flash-lite',
'gemini-2.5-flash-lite-preview-06-17',
'gemini-2.0-flash',
'gemini-2.0-flash-lite',
'gemini-1.5-pro',
'gemini-1.5-flash'
]
const isSupported =
supportedSearchModels.some((supportedModel) => modelId.includes(supportedModel)) ||
modelId.includes('gemini')
return isGemini && isSupported
const supported = capabilitySupportsReasoning.value === true
const hasRange = !!thinkingBudgetRange.value && thinkingBudgetRange.value.max !== undefined
return hasReasoning && supported && hasRange
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix thinking-budget visibility to match ChatConfig

Current logic requires max to be defined. Use any-of min/max/default to avoid hiding valid fields.

-const showThinkingBudget = computed(() => {
-  const hasReasoning = config.value.reasoning
-  const supported = capabilitySupportsReasoning.value === true
-  const hasRange = !!thinkingBudgetRange.value && thinkingBudgetRange.value.max !== undefined
-  return hasReasoning && supported && hasRange
-})
+const showThinkingBudget = computed(() => {
+  const hasReasoning = config.value.reasoning
+  const supported = capabilitySupportsReasoning.value === true
+  const r = thinkingBudgetRange.value
+  const hasAny = !!r && (r.min !== undefined || r.max !== undefined || r.default !== undefined)
+  return hasReasoning && supported && hasAny
+})
📝 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
const showThinkingBudget = computed(() => {
const hasReasoning = config.value.reasoning
const modelConfig = getThinkingBudgetConfig(props.modelId)
const isSupported = modelConfig !== null
return isGemini && hasReasoning && isSupported
})
// 是否显示Qwen3思考预算配置
const showQwen3ThinkingBudget = computed(() => {
const isDashscope = props.providerId === 'dashscope'
const hasReasoning = config.value.reasoning
const modelId = props.modelId.toLowerCase()
// DashScope - ENABLE_THINKING_MODELS
const supportedThinkingModels = [
// Open source versions
'qwen3-next-80b-a3b-thinking',
'qwen3-235b-a22b',
'qwen3-32b',
'qwen3-30b-a3b',
'qwen3-14b',
'qwen3-8b',
'qwen3-4b',
'qwen3-1.7b',
'qwen3-0.6b',
// Commercial versions
'qwen3-vl-plus',
'qwen-plus',
'qwen-plus-latest',
'qwen-plus-2025-04-28',
'qwen-flash',
'qwen-flash-2025-07-28',
'qwen-turbo',
'qwen-turbo-latest',
'qwen-turbo-2025-04-28'
]
const isSupported = supportedThinkingModels.some((supportedModel) =>
modelId.includes(supportedModel)
)
const modelConfig = getThinkingBudgetConfig(props.modelId)
const hasValidConfig = modelConfig !== null
return isDashscope && hasReasoning && isSupported && hasValidConfig
})
// 是否显示DashScope搜索配置
const showDashScopeSearch = computed(() => {
const isDashscope = props.providerId === 'dashscope'
const modelId = props.modelId.toLowerCase()
// DashScope - ENABLE_SEARCH_MODELS
const supportedSearchModels = [
'qwen3-max-2025-09-23',
'qwen3-max-preview',
'qwen3-max',
'qwen-max',
'qwen-plus',
'qwen-flash',
'qwen-turbo',
'qwq-plus'
]
const isSupported = supportedSearchModels.some((supportedModel) =>
modelId.includes(supportedModel)
)
return isDashscope && isSupported
})
// 是否显示Grok搜索配置
const showGrokSearch = computed(() => {
const isGrok = props.providerId === 'grok'
const modelId = props.modelId.toLowerCase()
// According to requirements, all Grok models support internet search
const supportedSearchModels = [
'grok-4',
'grok-3-mini',
'grok-3-mini-fast',
'grok-3-fast',
'grok-3',
'grok-2',
'grok-2-vision',
'grok-2-image'
]
const isSupported =
supportedSearchModels.some((supportedModel) => modelId.includes(supportedModel)) ||
modelId.includes('grok')
return isGrok && isSupported
})
// 是否显示Gemini搜索配置
const showGeminiSearch = computed(() => {
const isGemini = props.providerId === 'gemini'
const modelId = props.modelId.toLowerCase()
const supportedSearchModels = [
'gemini-2.5-pro',
'gemini-2.5-flash',
'gemini-2.5-flash-lite',
'gemini-2.5-flash-lite-preview-06-17',
'gemini-2.0-flash',
'gemini-2.0-flash-lite',
'gemini-1.5-pro',
'gemini-1.5-flash'
]
const isSupported =
supportedSearchModels.some((supportedModel) => modelId.includes(supportedModel)) ||
modelId.includes('gemini')
return isGemini && isSupported
const supported = capabilitySupportsReasoning.value === true
const hasRange = !!thinkingBudgetRange.value && thinkingBudgetRange.value.max !== undefined
return hasReasoning && supported && hasRange
})
const showThinkingBudget = computed(() => {
const hasReasoning = config.value.reasoning
const supported = capabilitySupportsReasoning.value === true
const r = thinkingBudgetRange.value
const hasAny = !!r && (r.min !== undefined || r.max !== undefined || r.default !== undefined)
return hasReasoning && supported && hasAny
})
🤖 Prompt for AI Agents
In src/renderer/src/components/settings/ModelConfigDialog.vue around lines 601
to 606, the computed showThinkingBudget currently requires
thinkingBudgetRange.value.max to be defined which hides valid fields; change the
range check to accept any of min, max, or default being present (e.g., compute
hasRange as !!thinkingBudgetRange.value && (thinkingBudgetRange.value.min !==
undefined || thinkingBudgetRange.value.max !== undefined ||
thinkingBudgetRange.value.default !== undefined)), then return hasReasoning &&
supported && hasRange so the visibility matches ChatConfig.

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