Skip to content

feat(adapter-gemini): 支持手动模型列表#910

Closed
Sor85 wants to merge 1 commit into
ChatLunaLab:v1-devfrom
Sor85:feat/gemini-additional-models
Closed

feat(adapter-gemini): 支持手动模型列表#910
Sor85 wants to merge 1 commit into
ChatLunaLab:v1-devfrom
Sor85:feat/gemini-additional-models

Conversation

@Sor85

@Sor85 Sor85 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 为 Gemini adapter 增加 pullModelsadditionalModels 配置。
  • 手动 Gemini 模型复用现有 expandModelVariants() 展开后缀,远端模型按展开后的名称去重追加。
  • 手动非 Gemini 模型在模型列表和请求配置中保留原始名称。

Test Plan

  • yarn fast-build adapter-gemini
  • yarn exec cross-env TS_NODE_PROJECT=packages/adapter-gemini/tests/tsconfig.json mocha -r tsconfig-paths/register -r esbuild-register -r yml-register --exit "packages/adapter-gemini/tests/**/*.spec.ts"
  • yarn eslint packages/adapter-gemini/src --cache --ext=ts
  • yarn eslint packages/adapter-gemini/tests/client.spec.ts --no-ignore --cache --ext=ts
  • git diff --check

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

总体概述

Gemini 适配器新增对额外模型的配置管理与处理流程:通过 pullModels 开关控制是否拉取远程模型列表,并支持在配置中指定 additionalModels 进行本地模型补充;客户端在刷新模型时按名称进行去重合并,模型配置准备阶段针对非 Gemini 模型提供早期返回以简化处理。

变更项

额外模型配置与集成

层级 / 文件 摘要
配置定义与 Schema 更新
packages/adapter-gemini/src/index.ts
导入 ModelCapabilities 类型;扩展 Config 接口,新增 pullModels: booleanadditionalModels 数组字段(包含模型名称、类型、能力和上下文大小);更新 Schema 定义以支持这些字段的类型约束、默认值和表格呈现。
客户端模型刷新与去重
packages/adapter-gemini/src/client.ts
refreshModels() 方法根据 pullModels 条件性调用 requester 获取远程模型;遍历 additionalModels 并为每个条目构建 ModelInfo,根据模型类型差异化生成能力列表;通过临时集合对展开的变体进行收集,按模型 name 去重后合并到最终列表中。
模型配置准备的早期返回
packages/adapter-gemini/src/utils.ts
prepareModelConfig() 新增从 additionalModels 查找匹配项的分支;当模型名称不包含 gemini 时直接返回配置对象,设置默认的思考参数和图片生成配置,跳过后续的模型名称后缀解析。
单元测试覆盖
packages/adapter-gemini/tests/client.spec.ts
新增测试文件验证 refreshModels()prepareModelConfig() 的行为;包含三个主要用例:(1)禁用远程拉取且配置 Gemini 模型的变体展开;(2)处理非 Gemini 模型的名称保持与能力配置;(3)验证配置准备中的模型名称保持与参数透传。

相关 PR

建议审查人员

  • dingyi222666

🐰 兔兔轻声唱起歌儿

额外模型来敲门,无需远程再奔跑,
本地配置自行管,按名去重合并巧,
Gemini 家族心不烦,小伙伴也有席位坐。


🎯 3 (中等复杂度) | ⏱️ ~25 分钟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR标题准确反映主要变更:为Gemini adapter增加手动模型列表配置功能。
Description check ✅ Passed PR描述与变更集密切相关,详细说明了配置项、处理逻辑和测试计划。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the ability to manually configure additional models and toggle automatic model fetching (pullModels) in the Gemini adapter. It updates the client to parse and expand these additional models, adds schema configuration and localization for the new settings, and includes corresponding unit tests. The review feedback highlights potential runtime TypeError exceptions if additionalModels is undefined (e.g., when a user updates the plugin but has not yet saved the new configuration). Specifically, it is recommended to add nullish coalescing or optional chaining when iterating or searching through additionalModels in client.ts and utils.ts.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

// --- 将原始模型转换并展开为变体列表 ---
const models: ModelInfo[] = []

for (const model of this._config.additionalModels) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

在 Koishi 插件中,当用户更新插件但尚未在控制台重新保存配置时,新引入的配置项 additionalModels 可能会是 undefined。直接对其进行 for...of 遍历会导致运行时报错 TypeError: ... is not iterable

建议添加空值保护,例如使用空数组作为回退值。

Suggested change
for (const model of this._config.additionalModels) {
for (const model of this._config.additionalModels ?? []) {

Comment on lines +550 to +553
const extra = pluginConfig.additionalModels.find(
(item) =>
item.model === model && !item.model.toLowerCase().includes('gemini')
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

同理,在 prepareModelConfig 中,pluginConfig.additionalModels 在配置未更新时可能为 undefined。直接调用 .find() 会导致运行时抛出 TypeError: Cannot read properties of undefined (reading 'find') 异常。

建议使用可选链(optional chaining)进行安全调用。

Suggested change
const extra = pluginConfig.additionalModels.find(
(item) =>
item.model === model && !item.model.toLowerCase().includes('gemini')
)
const extra = pluginConfig.additionalModels?.find(
(item) =>
item.model === model && !item.model.toLowerCase().includes('gemini')
)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/adapter-gemini/src/client.ts`:
- Around line 147-171: The additionalModels branch currently pushes baseInfo
into models without name-based deduplication, causing duplicate model names when
manual config includes repeats or base+variant pairs; update the logic handling
this._config.additionalModels so it uses the same expansion + dedupe path as the
remote results—invoke expandModelVariants(models, baseInfo,
this._config.imageModelSearch) as before and, if it returns false, only push
baseInfo when no existing entry in models has the same name (compare
ModelInfo.name), or reuse the same dedupe routine used later in refreshModels();
ensure references: additionalModels, baseInfo, expandModelVariants, models, and
refreshModels().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3691df3b-dee7-4813-bf97-9b171e463b40

📥 Commits

Reviewing files that changed from the base of the PR and between 690493b and b01e1b6.

⛔ Files ignored due to path filters (3)
  • packages/adapter-gemini/src/locales/en-US.schema.yml is excluded by !**/*.yml
  • packages/adapter-gemini/src/locales/zh-CN.schema.yml is excluded by !**/*.yml
  • packages/adapter-gemini/tests/tsconfig.json is excluded by !**/*.json
📒 Files selected for processing (4)
  • packages/adapter-gemini/src/client.ts
  • packages/adapter-gemini/src/index.ts
  • packages/adapter-gemini/src/utils.ts
  • packages/adapter-gemini/tests/client.spec.ts

Comment on lines +147 to +171
for (const model of this._config.additionalModels) {
const modelNameLower = model.model.toLowerCase()
const isEmbedding = model.modelType === 'Embeddings 嵌入模型'

const baseInfo: ModelInfo = {
name: model.model,
maxTokens: model.contextSize,
type: isEmbedding ? ModelType.embeddings : ModelType.llm,
capabilities: isEmbedding
? []
: modelNameLower.includes('gemini')
? createGeminiCapabilities(modelNameLower, false)
: model.modelCapabilities
}

if (
!expandModelVariants(
models,
baseInfo,
this._config.imageModelSearch
)
) {
models.push(baseInfo)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

补充模型分支缺少按名称去重,可能返回重复模型

Line 147-171 当前把 additionalModels 展开后直接写入 models,但只在 Line 205 对远端展开结果做了去重。
当手动配置里出现重复项,或同时配置基础模型与其变体(如 gemini-2.5-pro + gemini-2.5-pro-thinking)时,refreshModels() 会返回重复 name,与最终列表去重预期不一致。

建议修复(在 additionalModels 分支也走同样的去重路径)
-        for (const model of this._config.additionalModels) {
+        for (const model of this._config.additionalModels) {
             const modelNameLower = model.model.toLowerCase()
             const isEmbedding = model.modelType === 'Embeddings 嵌入模型'
 
             const baseInfo: ModelInfo = {
                 name: model.model,
                 maxTokens: model.contextSize,
                 type: isEmbedding ? ModelType.embeddings : ModelType.llm,
                 capabilities: isEmbedding
                     ? []
                     : modelNameLower.includes('gemini')
                       ? createGeminiCapabilities(modelNameLower, false)
                       : model.modelCapabilities
             }
 
-            if (
-                !expandModelVariants(
-                    models,
-                    baseInfo,
-                    this._config.imageModelSearch
-                )
-            ) {
-                models.push(baseInfo)
-            }
+            const items: ModelInfo[] = []
+            if (
+                !expandModelVariants(
+                    items,
+                    baseInfo,
+                    this._config.imageModelSearch
+                )
+            ) {
+                items.push(baseInfo)
+            }
+
+            for (const item of items) {
+                if (models.findIndex((info) => info.name === item.name) < 0) {
+                    models.push(item)
+                }
+            }
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/adapter-gemini/src/client.ts` around lines 147 - 171, The
additionalModels branch currently pushes baseInfo into models without name-based
deduplication, causing duplicate model names when manual config includes repeats
or base+variant pairs; update the logic handling this._config.additionalModels
so it uses the same expansion + dedupe path as the remote results—invoke
expandModelVariants(models, baseInfo, this._config.imageModelSearch) as before
and, if it returns false, only push baseInfo when no existing entry in models
has the same name (compare ModelInfo.name), or reuse the same dedupe routine
used later in refreshModels(); ensure references: additionalModels, baseInfo,
expandModelVariants, models, and refreshModels().

@Sor85 Sor85 closed this Jun 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant