feat(webui): add MCP CLI toggle and Gemini [1m] suffix settings

- Add ENABLE_EXPERIMENTAL_MCP_CLI toggle in Claude CLI settings (default: true)

- Add Gemini 1M Context Mode toggle for [1m] suffix (default: true)

- Auto-apply [1m] suffix to existing Gemini model configurations

- Add i18n translations for both features (English and Chinese)
This commit is contained in:
Wha1eChai
2026-01-09 18:34:24 +08:00
parent 169e18402f
commit 07a9586aee
8 changed files with 117 additions and 0 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 KiB

After

Width:  |  Height:  |  Size: 170 KiB

BIN
images/webui-models.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 248 KiB

View File

@@ -8,6 +8,16 @@ window.Components.claudeConfig = () => ({
config: { env: {} },
models: [],
loading: false,
gemini1mSuffix: false,
// Model fields that may contain Gemini model names
geminiModelFields: [
'ANTHROPIC_MODEL',
'CLAUDE_CODE_SUBAGENT_MODEL',
'ANTHROPIC_DEFAULT_OPUS_MODEL',
'ANTHROPIC_DEFAULT_SONNET_MODEL',
'ANTHROPIC_DEFAULT_HAIKU_MODEL'
],
init() {
// Only fetch config if this is the active sub-tab
@@ -28,6 +38,36 @@ window.Components.claudeConfig = () => ({
this.models = Alpine.store('data').models || [];
},
/**
* Detect if any Gemini model has [1m] suffix
*/
detectGemini1mSuffix() {
for (const field of this.geminiModelFields) {
const val = this.config.env[field];
if (val && val.toLowerCase().includes('gemini') && val.includes('[1m]')) {
return true;
}
}
return false;
},
/**
* Toggle [1m] suffix for all Gemini models
*/
toggleGemini1mSuffix(enabled) {
for (const field of this.geminiModelFields) {
const val = this.config.env[field];
if (val && val.toLowerCase().includes('gemini')) {
if (enabled && !val.includes('[1m]')) {
this.config.env[field] = val.trim() + ' [1m]';
} else if (!enabled && val.includes('[1m]')) {
this.config.env[field] = val.replace(/\s*\[1m\]$/i, '').trim();
}
}
}
this.gemini1mSuffix = enabled;
},
async fetchConfig() {
const password = Alpine.store('global').webuiPassword;
try {
@@ -38,6 +78,24 @@ window.Components.claudeConfig = () => ({
const data = await response.json();
this.config = data.config || {};
if (!this.config.env) this.config.env = {};
// Default MCP CLI to true if not set
if (this.config.env.ENABLE_EXPERIMENTAL_MCP_CLI === undefined) {
this.config.env.ENABLE_EXPERIMENTAL_MCP_CLI = 'true';
}
// Detect existing [1m] suffix state, default to true
const hasExistingSuffix = this.detectGemini1mSuffix();
const hasGeminiModels = this.geminiModelFields.some(f =>
this.config.env[f]?.toLowerCase().includes('gemini')
);
// Default to enabled: if no suffix found but Gemini models exist, apply suffix
if (!hasExistingSuffix && hasGeminiModels) {
this.toggleGemini1mSuffix(true);
} else {
this.gemini1mSuffix = hasExistingSuffix || !hasGeminiModels;
}
} catch (e) {
console.error('Failed to fetch Claude config:', e);
}

View File

@@ -243,6 +243,12 @@ document.addEventListener('alpine:init', () => {
oauthTimeout: "⏱️ OAuth authorization timed out. Please try again.",
oauthWindowClosed: "OAuth window was closed. Authorization may be incomplete.",
cancelOAuth: "Cancel",
// MCP CLI & Gemini 1M
mcpCliExperimental: "Experimental MCP CLI",
mcpCliDesc: "Enables experimental MCP integration for reliable tool usage with reduced context consumption.",
gemini1mMode: "Gemini 1M Context Mode",
gemini1mDesc: "Appends [1m] suffix to Gemini models for 1M context window support.",
gemini1mWarning: "⚠ Large context may reduce Gemini-3-Pro performance.",
},
zh: {
dashboard: "仪表盘",
@@ -475,6 +481,12 @@ document.addEventListener('alpine:init', () => {
oauthTimeout: "⏱️ OAuth 授权超时,请重试。",
oauthWindowClosed: "OAuth 窗口已关闭,授权可能未完成。",
cancelOAuth: "取消",
// MCP CLI & Gemini 1M
mcpCliExperimental: "实验性 MCP CLI",
mcpCliDesc: "启用实验性 MCP 集成,减少上下文消耗,提高工具调用可靠性。",
gemini1mMode: "Gemini 1M 上下文模式",
gemini1mDesc: "为 Gemini 模型添加 [1m] 后缀以支持 1M 上下文窗口。",
gemini1mWarning: "⚠ 大上下文可能降低 Gemini-3-Pro 性能。",
}
},

View File

@@ -406,6 +406,53 @@
</div>
</div>
<!-- MCP CLI Experimental Mode -->
<div class="card bg-space-900/30 border border-space-border/50 p-5">
<div class="flex items-center justify-between">
<div class="flex flex-col gap-1">
<span class="text-sm font-medium transition-colors"
:class="config.env.ENABLE_EXPERIMENTAL_MCP_CLI === 'true' ? 'text-neon-green' : 'text-gray-300'"
x-text="$store.global.t('mcpCliExperimental')">Experimental MCP CLI</span>
<span class="text-[11px] text-gray-500" x-text="$store.global.t('mcpCliDesc')">
Enables experimental MCP integration for reliable tool usage with reduced context consumption.
</span>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="sr-only peer"
:checked="config.env.ENABLE_EXPERIMENTAL_MCP_CLI === 'true'"
@change="config.env.ENABLE_EXPERIMENTAL_MCP_CLI = $event.target.checked ? 'true' : 'false'">
<div
class="w-9 h-5 bg-space-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-gray-600 after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-neon-green peer-checked:after:bg-white">
</div>
</label>
</div>
</div>
<!-- Gemini 1M Context Suffix Toggle -->
<div class="card bg-space-900/30 border border-space-border/50 p-5">
<div class="flex items-center justify-between">
<div class="flex flex-col gap-1">
<span class="text-sm font-medium transition-colors"
:class="gemini1mSuffix ? 'text-neon-green' : 'text-gray-300'"
x-text="$store.global.t('gemini1mMode')">Gemini 1M Context Mode</span>
<span class="text-[11px] text-gray-500" x-text="$store.global.t('gemini1mDesc')">
Appends [1m] suffix to Gemini models for 1M context window support.
</span>
<span class="text-[10px] text-yellow-500/80" x-text="$store.global.t('gemini1mWarning')">
⚠ Large context may reduce Gemini-3-Pro performance.
</span>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="sr-only peer"
:checked="gemini1mSuffix"
@change="toggleGemini1mSuffix($event.target.checked)">
<div
class="w-9 h-5 bg-space-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-gray-600 after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-neon-green peer-checked:after:bg-white">
</div>
</label>
</div>
</div>
<div class="flex justify-end pt-2">
<button class="btn btn-sm bg-neon-purple hover:bg-purple-600 border-none text-white px-6 gap-2"
@click="saveClaudeConfig" :disabled="loading">