Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 156 additions & 1 deletion src/main/presenter/configPresenter/providerModelSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,162 @@ export const providerModelSettings: Record<string, { models: ProviderModelSettin

// Moonshot提供商特定模型配置
moonshot: {
models: []
models: [
{
id: 'kimi-k2-0905-preview',
name: 'Kimi K2 0905 Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 262144,
match: ['kimi-k2-0905-preview'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'kimi-k2-0711-preview',
name: 'Kimi K2 0711 Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-k2-0711-preview'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'kimi-k2-turbo-preview',
name: 'Kimi K2 Turbo Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 262144,
match: ['kimi-k2-turbo-preview'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest',
name: 'Kimi Latest',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-8k',
name: 'Kimi Latest 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['kimi-latest-8k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-32k',
name: 'Kimi Latest 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['kimi-latest-32k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-128k',
name: 'Kimi Latest 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest-128k'],
vision: true,
functionCall: true,
reasoning: false
},
Comment on lines +567 to +609
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

⚠️ Potential issue

Fix substring matching collisions: 'kimi-latest' shadows its -8k/-32k/-128k variants

getProviderSpecificModelConfig uses includes() for matching. Because 'kimi-latest' appears before 'kimi-latest-8k/-32k/-128k', selecting e.g. 'kimi-latest-32k' will match the earlier 'kimi-latest' block and return wrong limits/features.

Minimal fix (reorder: put specific variants before the generic one):

@@
-      {
-        id: 'kimi-latest',
-        name: 'Kimi Latest',
-        temperature: 0.7,
-        maxTokens: 65536,
-        contextLength: 131072,
-        match: ['kimi-latest'],
-        vision: true,
-        functionCall: true,
-        reasoning: false
-      },
       {
         id: 'kimi-latest-8k',
         name: 'Kimi Latest 8K',
@@
       {
         id: 'kimi-latest-32k',
         name: 'Kimi Latest 32K',
@@
       {
         id: 'kimi-latest-128k',
         name: 'Kimi Latest 128K',
@@
+      {
+        id: 'kimi-latest',
+        name: 'Kimi Latest',
+        temperature: 0.7,
+        maxTokens: 65536,
+        contextLength: 131072,
+        match: ['kimi-latest'],
+        vision: true,
+        functionCall: true,
+        reasoning: false
+      },

Alternatively (preferred), harden the matcher to prefer exact/longest matches (see separate comment).

📝 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
id: 'kimi-latest',
name: 'Kimi Latest',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-8k',
name: 'Kimi Latest 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['kimi-latest-8k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-32k',
name: 'Kimi Latest 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['kimi-latest-32k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-128k',
name: 'Kimi Latest 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest-128k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-8k',
name: 'Kimi Latest 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['kimi-latest-8k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-32k',
name: 'Kimi Latest 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['kimi-latest-32k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-128k',
name: 'Kimi Latest 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest-128k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest',
name: 'Kimi Latest',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest'],
vision: true,
functionCall: true,
reasoning: false
},
🤖 Prompt for AI Agents
In src/main/presenter/configPresenter/providerModelSettings.ts around lines
567-609, the model entry for 'kimi-latest' appears before its '-8k/-32k/-128k'
variants so the current includes()-based matching will match the generic
'kimi-latest' first and return incorrect config for specific variants; fix by
either moving the specific variant entries ('kimi-latest-128k',
'kimi-latest-32k', 'kimi-latest-8k') before the generic 'kimi-latest' entry, or,
preferably, change the matching logic in getProviderSpecificModelConfig to
prefer exact or longest matches (e.g., check exact equality first, then fallback
to includes, or sort candidate match strings by length descending and choose the
longest includes match) so specific models are selected over the generic one.

{
id: 'moonshot-v1-8k',
name: 'Moonshot V1 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k',
name: 'Moonshot V1 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k',
name: 'Moonshot V1 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-8k-vision-preview',
name: 'Moonshot V1 8K Vision Preview',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k-vision-preview',
name: 'Moonshot V1 32K Vision Preview',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k-vision-preview',
name: 'Moonshot V1 128K Vision Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
Comment on lines +611 to +675
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

⚠️ Potential issue

Fix collisions between 'moonshot-v1-k' and 'moonshot-v1-k-vision-preview'

Because of includes(), the non-vision entries ('moonshot-v1-8k/32k/128k') precede the '...-vision-preview' ones, so choosing a vision model will match the earlier non-vision block and incorrectly set vision=false.

Minimal fix (reorder: place vision-preview blocks before the non-vision ones):

@@
-      {
-        id: 'moonshot-v1-8k',
-        name: 'Moonshot V1 8K',
-        temperature: 0.7,
-        maxTokens: 4096,
-        contextLength: 8192,
-        match: ['moonshot-v1-8k'],
-        vision: false,
-        functionCall: true,
-        reasoning: false
-      },
-      {
-        id: 'moonshot-v1-32k',
-        name: 'Moonshot V1 32K',
-        temperature: 0.7,
-        maxTokens: 16384,
-        contextLength: 32768,
-        match: ['moonshot-v1-32k'],
-        vision: false,
-        functionCall: true,
-        reasoning: false
-      },
-      {
-        id: 'moonshot-v1-128k',
-        name: 'Moonshot V1 128K',
-        temperature: 0.7,
-        maxTokens: 65536,
-        contextLength: 131072,
-        match: ['moonshot-v1-128k'],
-        vision: false,
-        functionCall: true,
-        reasoning: false
-      },
       {
         id: 'moonshot-v1-8k-vision-preview',
         name: 'Moonshot V1 8K Vision Preview',
@@
       {
         id: 'moonshot-v1-32k-vision-preview',
         name: 'Moonshot V1 32K Vision Preview',
@@
       {
         id: 'moonshot-v1-128k-vision-preview',
         name: 'Moonshot V1 128K Vision Preview',
@@
+      {
+        id: 'moonshot-v1-8k',
+        name: 'Moonshot V1 8K',
+        temperature: 0.7,
+        maxTokens: 4096,
+        contextLength: 8192,
+        match: ['moonshot-v1-8k'],
+        vision: false,
+        functionCall: true,
+        reasoning: false
+      },
+      {
+        id: 'moonshot-v1-32k',
+        name: 'Moonshot V1 32K',
+        temperature: 0.7,
+        maxTokens: 16384,
+        contextLength: 32768,
+        match: ['moonshot-v1-32k'],
+        vision: false,
+        functionCall: true,
+        reasoning: false
+      },
+      {
+        id: 'moonshot-v1-128k',
+        name: 'Moonshot V1 128K',
+        temperature: 0.7,
+        maxTokens: 65536,
+        contextLength: 131072,
+        match: ['moonshot-v1-128k'],
+        vision: false,
+        functionCall: true,
+        reasoning: false
+      },
📝 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
id: 'moonshot-v1-8k',
name: 'Moonshot V1 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k',
name: 'Moonshot V1 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k',
name: 'Moonshot V1 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-8k-vision-preview',
name: 'Moonshot V1 8K Vision Preview',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k-vision-preview',
name: 'Moonshot V1 32K Vision Preview',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k-vision-preview',
name: 'Moonshot V1 128K Vision Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-8k-vision-preview',
name: 'Moonshot V1 8K Vision Preview',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k-vision-preview',
name: 'Moonshot V1 32K Vision Preview',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k-vision-preview',
name: 'Moonshot V1 128K Vision Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-8k',
name: 'Moonshot V1 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k',
name: 'Moonshot V1 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k',
name: 'Moonshot V1 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k'],
vision: false,
functionCall: true,
reasoning: false
},
🤖 Prompt for AI Agents
In src/main/presenter/configPresenter/providerModelSettings.ts around lines 611
to 675 the current ordering places the non-vision Moonshot entries
('moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k') before their
'-vision-preview' counterparts, causing includes() to match the non-vision entry
first and incorrectly set vision=false for vision models; fix by reordering
these blocks so each '-vision-preview' entry appears before its corresponding
non-vision entry (i.e., move the three vision-preview objects above the three
non-vision objects) ensuring the includes() check hits the vision variants
first.

{
id: 'kimi-thinking-preview',
name: 'Kimi Thinking Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-thinking-preview'],
vision: true,
functionCall: false,
reasoning: true
}
]
Comment on lines +532 to +687
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

Prefer exact/most-specific matching over substring order-dependence

Relying on includes() + array order is fragile and caused the above bugs. Improve matcher to:

  1. prefer exact matches; 2) else pick the candidate with the longest match string. Backward compatible with shorter aliases like 'deepseek-r1-0528'.

Apply outside this hunk in getProviderSpecificModelConfig():

@@ export function getProviderSpecificModelConfig(
-  // 遍历该提供商的模型数组,查找匹配的模型配置
-  for (const config of providerSetting.models) {
-    // 检查是否有任何匹配条件符合
-    if (config.match.some((matchStr) => lowerModelId.includes(matchStr.toLowerCase()))) {
-      return {
-        maxTokens: config.maxTokens,
-        contextLength: config.contextLength,
-        temperature: config.temperature, // 保持可选,某些模型不支持
-        vision: config.vision || false,
-        functionCall: config.functionCall || false,
-        reasoning: config.reasoning || false,
-        type: config.type || ModelType.Chat,
-        reasoningEffort: config.reasoningEffort,
-        verbosity: config.verbosity,
-        maxCompletionTokens: config.maxCompletionTokens,
-        thinkingBudget: config.thinkingBudget,
-        enableSearch: config.enableSearch ?? false,
-        forcedSearch: config.forcedSearch ?? false,
-        searchStrategy: config.searchStrategy || 'turbo'
-      }
-    }
-  }
+  // Build match candidates, prefer exact, else longest match
+  const candidates = providerSetting.models.flatMap((cfg) =>
+    (cfg.match || []).map((m) => ({
+      cfg,
+      mLower: m.toLowerCase(),
+      mLen: m.length
+    }))
+  ).filter(({ mLower }) => lowerModelId.includes(mLower))
+
+  // Prefer exact match first
+  const exact = candidates.find(({ mLower }) => lowerModelId === mLower)
+  const best = exact ??
+    candidates.sort((a, b) => b.mLen - a.mLen)[0]
+
+  if (best) {
+    const config = best.cfg
+    return {
+      maxTokens: config.maxTokens,
+      contextLength: config.contextLength,
+      temperature: config.temperature,
+      vision: config.vision || false,
+      functionCall: config.functionCall || false,
+      reasoning: config.reasoning || false,
+      type: config.type || ModelType.Chat,
+      reasoningEffort: config.reasoningEffort,
+      verbosity: config.verbosity,
+      maxCompletionTokens: config.maxCompletionTokens,
+      thinkingBudget: config.thinkingBudget,
+      enableSearch: config.enableSearch ?? false,
+      forcedSearch: config.forcedSearch ?? false,
+      searchStrategy: config.searchStrategy || 'turbo'
+    }
+  }
📝 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
models: [
{
id: 'kimi-k2-0905-preview',
name: 'Kimi K2 0905 Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 262144,
match: ['kimi-k2-0905-preview'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'kimi-k2-0711-preview',
name: 'Kimi K2 0711 Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-k2-0711-preview'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'kimi-k2-turbo-preview',
name: 'Kimi K2 Turbo Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 262144,
match: ['kimi-k2-turbo-preview'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest',
name: 'Kimi Latest',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-8k',
name: 'Kimi Latest 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['kimi-latest-8k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-32k',
name: 'Kimi Latest 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['kimi-latest-32k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-latest-128k',
name: 'Kimi Latest 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-latest-128k'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-8k',
name: 'Moonshot V1 8K',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k',
name: 'Moonshot V1 32K',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k',
name: 'Moonshot V1 128K',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k'],
vision: false,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-8k-vision-preview',
name: 'Moonshot V1 8K Vision Preview',
temperature: 0.7,
maxTokens: 4096,
contextLength: 8192,
match: ['moonshot-v1-8k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-32k-vision-preview',
name: 'Moonshot V1 32K Vision Preview',
temperature: 0.7,
maxTokens: 16384,
contextLength: 32768,
match: ['moonshot-v1-32k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'moonshot-v1-128k-vision-preview',
name: 'Moonshot V1 128K Vision Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['moonshot-v1-128k-vision-preview'],
vision: true,
functionCall: true,
reasoning: false
},
{
id: 'kimi-thinking-preview',
name: 'Kimi Thinking Preview',
temperature: 0.7,
maxTokens: 65536,
contextLength: 131072,
match: ['kimi-thinking-preview'],
vision: true,
functionCall: false,
reasoning: true
}
]
export function getProviderSpecificModelConfig(
providerSetting: ProviderSetting,
modelId: string
) {
const lowerModelId = modelId.toLowerCase()
// Build match candidates, prefer exact, else longest match
const candidates = providerSetting.models
.flatMap((cfg) =>
(cfg.match || []).map((m) => ({
cfg,
mLower: m.toLowerCase(),
mLen: m.length
}))
)
.filter(({ mLower }) => lowerModelId.includes(mLower))
// Prefer exact match first
const exact = candidates.find(({ mLower }) => lowerModelId === mLower)
const best = exact ?? candidates.sort((a, b) => b.mLen - a.mLen)[0]
if (best) {
const config = best.cfg
return {
maxTokens: config.maxTokens,
contextLength: config.contextLength,
temperature: config.temperature,
vision: config.vision || false,
functionCall: config.functionCall || false,
reasoning: config.reasoning || false,
type: config.type || ModelType.Chat,
reasoningEffort: config.reasoningEffort,
verbosity: config.verbosity,
maxCompletionTokens: config.maxCompletionTokens,
thinkingBudget: config.thinkingBudget,
enableSearch: config.enableSearch ?? false,
forcedSearch: config.forcedSearch ?? false,
searchStrategy: config.searchStrategy || 'turbo'
}
}
// (fallback logic unchanged…)
}
🤖 Prompt for AI Agents
In src/main/presenter/configPresenter/providerModelSettings.ts around lines 532
to 687, the model-matching logic currently relies on includes() plus array order
which is fragile; change getProviderSpecificModelConfig() so it first searches
for an exact match (modelId === candidate) and returns that if found; if no
exact match, filter candidates that are substrings of the modelId and pick the
one with the longest match string (max length) to prefer most-specific aliases;
keep behavior backward-compatible for short aliases by falling back to the
previous selection when lengths tie or no candidates match.

},

// Ollama提供商特定模型配置
Expand Down