feat(ui): 支持自定义 API 并发数 (1-32 workers)

- 添加 codexlens.concurrency 和 concurrencyHint 翻译 (中英文)
- 将 worker 下拉菜单改为数字输入框,支持 1-32 范围
- 添加 validateConcurrencyInput 输入验证函数
- 默认值 4 workers,显示推荐提示

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
catlog22
2025-12-25 13:11:51 +08:00
parent 501d9a05d4
commit 1dc55f8811
2 changed files with 29 additions and 10 deletions

View File

@@ -266,6 +266,9 @@ const i18n = {
'codexlens.noApiModels': 'No API embedding models configured',
'codexlens.embeddingModel': 'Embedding Model',
'codexlens.modelHint': 'Select embedding model for vector search (models with ✓ are installed)',
'codexlens.concurrency': 'API Concurrency',
'codexlens.concurrencyHint': 'Number of parallel API calls (1-32). Higher values speed up indexing but may hit rate limits.',
'codexlens.concurrencyCustom': 'Custom',
'codexlens.fullIndex': 'Full',
'codexlens.vectorIndex': 'Vector',
'codexlens.ftsIndex': 'FTS',
@@ -1925,6 +1928,9 @@ const i18n = {
'codexlens.noApiModels': '未配置 API 嵌入模型',
'codexlens.embeddingModel': '嵌入模型',
'codexlens.modelHint': '选择向量搜索的嵌入模型(带 ✓ 的已安装)',
'codexlens.concurrency': 'API 并发数',
'codexlens.concurrencyHint': '并行 API 调用数量1-32。较高的值可加速索引但可能触发速率限制。',
'codexlens.concurrencyCustom': '自定义',
'codexlens.fullIndex': '全部',
'codexlens.vectorIndex': '向量',
'codexlens.ftsIndex': 'FTS',

View File

@@ -1999,14 +1999,15 @@ function buildCodexLensManagerPage(config) {
'</div>' +
// Concurrency selector (only for LiteLLM backend)
'<div id="concurrencySelector" class="hidden">' +
'<label class="block text-sm font-medium mb-1.5">' + (t('codexlens.concurrency') || 'API Concurrency') + '</label>' +
'<select id="pageConcurrencySelect" class="w-full px-3 py-2 border border-border rounded-lg bg-background text-sm">' +
'<option value="1">1 (Sequential)</option>' +
'<option value="2">2 workers</option>' +
'<option value="4" selected>4 workers (Recommended)</option>' +
'<option value="8">8 workers</option>' +
'</select>' +
'<p class="text-xs text-muted-foreground mt-1">' + (t('codexlens.concurrencyHint') || 'Number of parallel API calls for embedding generation') + '</p>' +
'<label class="block text-sm font-medium mb-1.5">' + t('codexlens.concurrency') + '</label>' +
'<div class="flex items-center gap-2">' +
'<input type="number" id="pageConcurrencyInput" min="1" max="32" value="4" ' +
'class="w-24 px-3 py-2 border border-border rounded-lg bg-background text-sm" ' +
'onchange="validateConcurrencyInput(this)" />' +
'<span class="text-sm text-muted-foreground">workers</span>' +
'<span class="text-xs text-primary ml-2">(4 = recommended)</span>' +
'</div>' +
'<p class="text-xs text-muted-foreground mt-1">' + t('codexlens.concurrencyHint') + '</p>' +
'</div>' +
// Index buttons - two modes: full (FTS + Vector) or FTS only
'<div class="grid grid-cols-2 gap-3">' +
@@ -2204,6 +2205,18 @@ function buildModelSelectOptionsForPage() {
return options;
}
/**
* Validate concurrency input value (1-32)
*/
function validateConcurrencyInput(input) {
var value = parseInt(input.value, 10);
if (isNaN(value) || value < 1) {
input.value = 1;
} else if (value > 32) {
input.value = 32;
}
}
/**
* Handle embedding backend change
*/
@@ -2290,10 +2303,10 @@ window.onEmbeddingBackendChange = onEmbeddingBackendChange;
function initCodexLensIndexFromPage(indexType) {
var backendSelect = document.getElementById('pageBackendSelect');
var modelSelect = document.getElementById('pageModelSelect');
var concurrencySelect = document.getElementById('pageConcurrencySelect');
var concurrencyInput = document.getElementById('pageConcurrencyInput');
var selectedBackend = backendSelect ? backendSelect.value : 'fastembed';
var selectedModel = modelSelect ? modelSelect.value : 'code';
var selectedConcurrency = concurrencySelect ? parseInt(concurrencySelect.value, 10) : 1;
var selectedConcurrency = concurrencyInput ? Math.min(32, Math.max(1, parseInt(concurrencyInput.value, 10) || 4)) : 4;
// For FTS-only index, model is not needed
if (indexType === 'normal') {