mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: 更新命令文档,增强 Bash 兼容性并添加动态模型选项更新功能
This commit is contained in:
@@ -320,4 +320,4 @@ function parseMarkdownBody(body) {
|
|||||||
## Related Commands
|
## Related Commands
|
||||||
|
|
||||||
- `/issue:plan` - Plan solution for issue
|
- `/issue:plan` - Plan solution for issue
|
||||||
- `/issue:manage` - Interactive issue management
|
|
||||||
|
|||||||
@@ -304,6 +304,12 @@ Next: \`/issue:queue\` → \`/issue:execute\`
|
|||||||
| User cancels selection | Skip issue, continue with others |
|
| User cancels selection | Skip issue, continue with others |
|
||||||
| File conflicts | Agent detects and suggests resolution order |
|
| File conflicts | Agent detects and suggests resolution order |
|
||||||
|
|
||||||
|
## Bash Compatibility
|
||||||
|
|
||||||
|
**Avoid**: `$(cmd)`, `$var`, `for` loops — will be escaped incorrectly
|
||||||
|
|
||||||
|
**Use**: Simple commands + `&&` chains, quote comma params `"pending,registered"`
|
||||||
|
|
||||||
## Quality Checklist
|
## Quality Checklist
|
||||||
|
|
||||||
Before completing, verify:
|
Before completing, verify:
|
||||||
@@ -319,6 +325,5 @@ Before completing, verify:
|
|||||||
## Related Commands
|
## Related Commands
|
||||||
|
|
||||||
- `/issue:queue` - Form execution queue from bound solutions
|
- `/issue:queue` - Form execution queue from bound solutions
|
||||||
- `/issue:execute` - Execute queue with codex
|
|
||||||
- `ccw issue list` - List all issues
|
- `ccw issue list` - List all issues
|
||||||
- `ccw issue status` - View issue and solution details
|
- `ccw issue status` - View issue and solution details
|
||||||
|
|||||||
@@ -385,7 +385,6 @@ Before completing, verify:
|
|||||||
|
|
||||||
## Related Commands
|
## Related Commands
|
||||||
|
|
||||||
- `/issue:plan` - Plan issues and bind solutions
|
|
||||||
- `/issue:execute` - Execute queue with codex
|
- `/issue:execute` - Execute queue with codex
|
||||||
- `ccw issue queue list` - View current queue
|
- `ccw issue queue list` - View current queue
|
||||||
- `ccw issue update --from-queue [queue-id]` - Sync issue statuses from queue
|
- `ccw issue update --from-queue [queue-id]` - Sync issue statuses from queue
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ var ENV_VAR_GROUPS = {
|
|||||||
labelKey: 'codexlens.envGroup.embedding',
|
labelKey: 'codexlens.envGroup.embedding',
|
||||||
icon: 'box',
|
icon: 'box',
|
||||||
vars: {
|
vars: {
|
||||||
'CODEXLENS_EMBEDDING_BACKEND': { label: 'Backend', type: 'select', options: ['fastembed', 'litellm'], default: 'fastembed', settingsPath: 'embedding.backend' },
|
'CODEXLENS_EMBEDDING_BACKEND': { label: 'Backend', type: 'select', options: ['local', 'api'], default: 'local', settingsPath: 'embedding.backend' },
|
||||||
'CODEXLENS_EMBEDDING_MODEL': {
|
'CODEXLENS_EMBEDDING_MODEL': {
|
||||||
label: 'Model',
|
label: 'Model',
|
||||||
type: 'model-select',
|
type: 'model-select',
|
||||||
@@ -694,7 +694,7 @@ var ENV_VAR_GROUPS = {
|
|||||||
icon: 'arrow-up-down',
|
icon: 'arrow-up-down',
|
||||||
vars: {
|
vars: {
|
||||||
'CODEXLENS_RERANKER_ENABLED': { label: 'Enabled', type: 'select', options: ['true', 'false'], default: 'true', settingsPath: 'reranker.enabled' },
|
'CODEXLENS_RERANKER_ENABLED': { label: 'Enabled', type: 'select', options: ['true', 'false'], default: 'true', settingsPath: 'reranker.enabled' },
|
||||||
'CODEXLENS_RERANKER_BACKEND': { label: 'Backend', type: 'select', options: ['fastembed', 'onnx', 'api', 'litellm'], default: 'fastembed', settingsPath: 'reranker.backend' },
|
'CODEXLENS_RERANKER_BACKEND': { label: 'Backend', type: 'select', options: ['local', 'api'], default: 'local', settingsPath: 'reranker.backend' },
|
||||||
'CODEXLENS_RERANKER_MODEL': {
|
'CODEXLENS_RERANKER_MODEL': {
|
||||||
label: 'Model',
|
label: 'Model',
|
||||||
type: 'model-select',
|
type: 'model-select',
|
||||||
@@ -786,9 +786,11 @@ async function loadEnvVariables() {
|
|||||||
var localEmbeddingModels = [];
|
var localEmbeddingModels = [];
|
||||||
if (localModelsResponse && localModelsResponse.ok) {
|
if (localModelsResponse && localModelsResponse.ok) {
|
||||||
var localData = await localModelsResponse.json();
|
var localData = await localModelsResponse.json();
|
||||||
if (localData.success && localData.models) {
|
// CLI returns { success: true, result: { models: [...] } }
|
||||||
// Filter to only downloaded models
|
if (localData.success) {
|
||||||
localEmbeddingModels = localData.models.filter(function(m) { return m.downloaded; });
|
var models = localData.models || (localData.result && localData.result.models) || [];
|
||||||
|
// Filter to only installed models (CLI uses 'installed' not 'downloaded')
|
||||||
|
localEmbeddingModels = models.filter(function(m) { return m.installed; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,12 +798,28 @@ async function loadEnvVariables() {
|
|||||||
var localRerankerModels = [];
|
var localRerankerModels = [];
|
||||||
if (localRerankerModelsResponse && localRerankerModelsResponse.ok) {
|
if (localRerankerModelsResponse && localRerankerModelsResponse.ok) {
|
||||||
var localRerankerData = await localRerankerModelsResponse.json();
|
var localRerankerData = await localRerankerModelsResponse.json();
|
||||||
if (localRerankerData.success && localRerankerData.models) {
|
// CLI returns { success: true, result: { models: [...] } }
|
||||||
// Filter to only downloaded models
|
if (localRerankerData.success) {
|
||||||
localRerankerModels = localRerankerData.models.filter(function(m) { return m.downloaded; });
|
var models = localRerankerData.models || (localRerankerData.result && localRerankerData.result.models) || [];
|
||||||
|
// Filter to only installed models
|
||||||
|
localRerankerModels = models.filter(function(m) { return m.installed; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache model data for dynamic backend switching
|
||||||
|
var embeddingVars = ENV_VAR_GROUPS.embedding.vars;
|
||||||
|
var rerankerVars = ENV_VAR_GROUPS.reranker.vars;
|
||||||
|
cachedEmbeddingModels = {
|
||||||
|
local: localEmbeddingModels,
|
||||||
|
api: configuredEmbeddingModels,
|
||||||
|
apiModels: embeddingVars['CODEXLENS_EMBEDDING_MODEL'] ? embeddingVars['CODEXLENS_EMBEDDING_MODEL'].apiModels || [] : []
|
||||||
|
};
|
||||||
|
cachedRerankerModels = {
|
||||||
|
local: localRerankerModels,
|
||||||
|
api: configuredRerankerModels,
|
||||||
|
apiModels: rerankerVars['CODEXLENS_RERANKER_MODEL'] ? rerankerVars['CODEXLENS_RERANKER_MODEL'].apiModels || [] : []
|
||||||
|
};
|
||||||
|
|
||||||
var env = result.env || {};
|
var env = result.env || {};
|
||||||
var settings = result.settings || {}; // Current settings from settings.json
|
var settings = result.settings || {}; // Current settings from settings.json
|
||||||
var html = '<div class="space-y-4">';
|
var html = '<div class="space-y-4">';
|
||||||
@@ -851,9 +869,14 @@ async function loadEnvVariables() {
|
|||||||
var value = env[key] || settings[key] || config.default || '';
|
var value = env[key] || settings[key] || config.default || '';
|
||||||
|
|
||||||
if (config.type === 'select') {
|
if (config.type === 'select') {
|
||||||
|
// Add onchange handler for backend selects to update model options dynamically
|
||||||
|
var onchangeHandler = '';
|
||||||
|
if (key === 'CODEXLENS_EMBEDDING_BACKEND' || key === 'CODEXLENS_RERANKER_BACKEND') {
|
||||||
|
onchangeHandler = ' onchange="updateModelOptionsOnBackendChange(\'' + key + '\', this.value)"';
|
||||||
|
}
|
||||||
html += '<div class="flex items-center gap-2">' +
|
html += '<div class="flex items-center gap-2">' +
|
||||||
'<label class="text-xs text-muted-foreground w-28 flex-shrink-0">' + escapeHtml(config.label) + '</label>' +
|
'<label class="text-xs text-muted-foreground w-28 flex-shrink-0">' + escapeHtml(config.label) + '</label>' +
|
||||||
'<select class="tool-config-input flex-1 text-xs py-1" data-env-key="' + escapeHtml(key) + '">';
|
'<select class="tool-config-input flex-1 text-xs py-1" data-env-key="' + escapeHtml(key) + '"' + onchangeHandler + '>';
|
||||||
config.options.forEach(function(opt) {
|
config.options.forEach(function(opt) {
|
||||||
html += '<option value="' + escapeHtml(opt) + '"' + (value === opt ? ' selected' : '') + '>' + escapeHtml(opt) + '</option>';
|
html += '<option value="' + escapeHtml(opt) + '"' + (value === opt ? ' selected' : '') + '>' + escapeHtml(opt) + '</option>';
|
||||||
});
|
});
|
||||||
@@ -914,9 +937,13 @@ async function loadEnvVariables() {
|
|||||||
if (actualLocalModels.length > 0) {
|
if (actualLocalModels.length > 0) {
|
||||||
html += '<option value="" disabled>-- ' + (t('codexlens.downloadedModels') || 'Downloaded Models') + ' --</option>';
|
html += '<option value="" disabled>-- ' + (t('codexlens.downloadedModels') || 'Downloaded Models') + ' --</option>';
|
||||||
actualLocalModels.forEach(function(model) {
|
actualLocalModels.forEach(function(model) {
|
||||||
var modelId = model.model_id || model.id || model.name;
|
// Priority: profile (for fastembed) > model_id > id > name
|
||||||
var displayName = model.display_name || model.name || modelId;
|
var modelId = model.profile || model.model_id || model.id || model.name;
|
||||||
html += '<option value="' + escapeHtml(modelId) + '">' + escapeHtml(displayName) + '</option>';
|
var displayName = model.display_name || model.name || model.profile || modelId;
|
||||||
|
// Show both profile and model name for clarity
|
||||||
|
var displayText = model.profile && model.name ?
|
||||||
|
model.profile + ' (' + model.name + ')' : displayName;
|
||||||
|
html += '<option value="' + escapeHtml(modelId) + '">' + escapeHtml(displayText) + '</option>';
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
html += '<option value="" disabled>-- ' + (t('codexlens.noLocalModels') || 'No models downloaded') + ' --</option>';
|
html += '<option value="" disabled>-- ' + (t('codexlens.noLocalModels') || 'No models downloaded') + ' --</option>';
|
||||||
@@ -961,12 +988,14 @@ async function loadEnvVariables() {
|
|||||||
if (window.lucide) lucide.createIcons();
|
if (window.lucide) lucide.createIcons();
|
||||||
|
|
||||||
// Add change handler for backend selects to dynamically update model options
|
// Add change handler for backend selects to dynamically update model options
|
||||||
|
// Note: Does NOT auto-save - user must click Save button
|
||||||
var backendSelects = container.querySelectorAll('select[data-env-key*="BACKEND"]');
|
var backendSelects = container.querySelectorAll('select[data-env-key*="BACKEND"]');
|
||||||
backendSelects.forEach(function(select) {
|
backendSelects.forEach(function(select) {
|
||||||
select.addEventListener('change', function() {
|
select.addEventListener('change', function() {
|
||||||
var backendKey = select.getAttribute('data-env-key');
|
var backendKey = select.getAttribute('data-env-key');
|
||||||
var newBackend = select.value;
|
var newBackend = select.value;
|
||||||
var isApiBackend = newBackend === 'litellm' || newBackend === 'api';
|
// 'api' is the API backend, 'local' is the local backend
|
||||||
|
var isApiBackend = newBackend === 'api';
|
||||||
|
|
||||||
// Determine which model input to update
|
// Determine which model input to update
|
||||||
var isEmbedding = backendKey.indexOf('EMBEDDING') !== -1;
|
var isEmbedding = backendKey.indexOf('EMBEDDING') !== -1;
|
||||||
@@ -983,64 +1012,65 @@ async function loadEnvVariables() {
|
|||||||
var modelConfig = ENV_VAR_GROUPS[groupKey]?.vars[modelKey];
|
var modelConfig = ENV_VAR_GROUPS[groupKey]?.vars[modelKey];
|
||||||
|
|
||||||
if (modelConfig) {
|
if (modelConfig) {
|
||||||
var modelList = isApiBackend
|
// Use the loaded models from closure
|
||||||
? (modelConfig.apiModels || modelConfig.models || [])
|
var apiModelList = modelConfig.apiModels || [];
|
||||||
: (modelConfig.localModels || modelConfig.models || []);
|
var apiConfiguredModels = isEmbedding ? configuredEmbeddingModels : configuredRerankerModels;
|
||||||
var configuredModels = isEmbedding ? configuredEmbeddingModels : configuredRerankerModels;
|
var actualLocalModels = isEmbedding ? localEmbeddingModels : localRerankerModels;
|
||||||
|
|
||||||
// Rebuild datalist
|
// Rebuild datalist
|
||||||
var html = '';
|
var optionsHtml = '';
|
||||||
if (isApiBackend && configuredModels.length > 0) {
|
|
||||||
html += '<option value="" disabled>-- ' + t('codexlens.configuredInApiSettings') + ' --</option>';
|
if (isApiBackend) {
|
||||||
configuredModels.forEach(function(model) {
|
// For API backend: show configured models from API settings first
|
||||||
var providers = model.providers ? model.providers.join(', ') : '';
|
if (apiConfiguredModels.length > 0) {
|
||||||
html += '<option value="' + escapeHtml(model.modelId) + '">' +
|
optionsHtml += '<option value="" disabled>-- ' + (t('codexlens.configuredModels') || 'Configured in API Settings') + ' --</option>';
|
||||||
escapeHtml(model.modelName || model.modelId) +
|
apiConfiguredModels.forEach(function(model) {
|
||||||
(providers ? ' (' + escapeHtml(providers) + ')' : '') +
|
var providers = model.providers ? model.providers.join(', ') : '';
|
||||||
'</option>';
|
optionsHtml += '<option value="' + escapeHtml(model.modelId) + '">' +
|
||||||
});
|
escapeHtml(model.modelName || model.modelId) +
|
||||||
if (modelList.length > 0) {
|
(providers ? ' (' + escapeHtml(providers) + ')' : '') +
|
||||||
html += '<option value="" disabled>-- ' + t('codexlens.commonModels') + ' --</option>';
|
'</option>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Then show common API models as suggestions
|
||||||
|
if (apiModelList.length > 0) {
|
||||||
|
optionsHtml += '<option value="" disabled>-- ' + (t('codexlens.commonModels') || 'Common Models') + ' --</option>';
|
||||||
|
apiModelList.forEach(function(group) {
|
||||||
|
group.items.forEach(function(model) {
|
||||||
|
var exists = apiConfiguredModels.some(function(m) { return m.modelId === model; });
|
||||||
|
if (!exists) {
|
||||||
|
optionsHtml += '<option value="' + escapeHtml(model) + '">' + escapeHtml(group.group) + ': ' + escapeHtml(model) + '</option>';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For local backend: show actually downloaded models
|
||||||
|
if (actualLocalModels.length > 0) {
|
||||||
|
optionsHtml += '<option value="" disabled>-- ' + (t('codexlens.downloadedModels') || 'Downloaded Models') + ' --</option>';
|
||||||
|
actualLocalModels.forEach(function(model) {
|
||||||
|
var modelId = model.profile || model.model_id || model.id || model.name;
|
||||||
|
var displayName = model.display_name || model.name || model.profile || modelId;
|
||||||
|
var displayText = model.profile && model.name ?
|
||||||
|
model.profile + ' (' + model.name + ')' : displayName;
|
||||||
|
optionsHtml += '<option value="' + escapeHtml(modelId) + '">' + escapeHtml(displayText) + '</option>';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
optionsHtml += '<option value="" disabled>-- ' + (t('codexlens.noLocalModels') || 'No models downloaded') + ' --</option>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modelList.forEach(function(group) {
|
datalist.innerHTML = optionsHtml;
|
||||||
group.items.forEach(function(model) {
|
|
||||||
var exists = configuredModels.some(function(m) { return m.modelId === model; });
|
|
||||||
if (!exists) {
|
|
||||||
html += '<option value="' + escapeHtml(model) + '">' + escapeHtml(group.group) + ': ' + escapeHtml(model) + '</option>';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
datalist.innerHTML = html;
|
// Clear current model value when switching backend type
|
||||||
|
modelInput.value = '';
|
||||||
// Clear current model value if it doesn't match new backend type
|
modelInput.placeholder = isApiBackend ?
|
||||||
var currentValue = modelInput.value;
|
(t('codexlens.selectApiModel') || 'Select API model...') :
|
||||||
var isCurrentLocal = modelConfig.localModels?.some(function(g) {
|
(t('codexlens.selectLocalModel') || 'Select local model...');
|
||||||
return g.items.includes(currentValue);
|
|
||||||
});
|
|
||||||
var isCurrentApi = modelConfig.apiModels?.some(function(g) {
|
|
||||||
return g.items.includes(currentValue);
|
|
||||||
});
|
|
||||||
|
|
||||||
// If switching to API and current is local (or vice versa), clear or set default
|
|
||||||
if (isApiBackend && isCurrentLocal) {
|
|
||||||
modelInput.value = '';
|
|
||||||
modelInput.placeholder = t('codexlens.selectApiModel');
|
|
||||||
} else if (!isApiBackend && isCurrentApi) {
|
|
||||||
modelInput.value = modelConfig.localModels?.[0]?.items?.[0] || '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Note: No auto-save here - user must click Save button
|
||||||
// Save and refresh after a short delay
|
|
||||||
saveEnvVariables().then(function() {
|
|
||||||
loadEnvVariables();
|
|
||||||
loadModelList();
|
|
||||||
loadRerankerModelList();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1099,6 +1129,74 @@ function applyLiteLLMProvider(providerId) {
|
|||||||
// Make function globally accessible
|
// Make function globally accessible
|
||||||
window.applyLiteLLMProvider = applyLiteLLMProvider;
|
window.applyLiteLLMProvider = applyLiteLLMProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update model datalist options when backend changes
|
||||||
|
* @param {string} backendKey - The backend key that changed (CODEXLENS_EMBEDDING_BACKEND or CODEXLENS_RERANKER_BACKEND)
|
||||||
|
* @param {string} newBackend - The new backend value ('local' or 'api')
|
||||||
|
*/
|
||||||
|
function updateModelOptionsOnBackendChange(backendKey, newBackend) {
|
||||||
|
var isEmbedding = backendKey === 'CODEXLENS_EMBEDDING_BACKEND';
|
||||||
|
var modelKey = isEmbedding ? 'CODEXLENS_EMBEDDING_MODEL' : 'CODEXLENS_RERANKER_MODEL';
|
||||||
|
var datalistId = 'models-' + modelKey.replace(/_/g, '-').toLowerCase();
|
||||||
|
var datalist = document.getElementById(datalistId);
|
||||||
|
|
||||||
|
if (!datalist) return;
|
||||||
|
|
||||||
|
var isApiBackend = newBackend === 'api' || newBackend === 'litellm';
|
||||||
|
var cachedModels = isEmbedding ? cachedEmbeddingModels : cachedRerankerModels;
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
if (isApiBackend) {
|
||||||
|
// For API backend: show configured models from API settings first
|
||||||
|
var configuredModels = cachedModels.api || [];
|
||||||
|
if (configuredModels.length > 0) {
|
||||||
|
html += '<option value="" disabled>-- ' + (t('codexlens.configuredModels') || 'Configured in API Settings') + ' --</option>';
|
||||||
|
configuredModels.forEach(function(model) {
|
||||||
|
var providers = model.providers ? model.providers.join(', ') : '';
|
||||||
|
html += '<option value="' + escapeHtml(model.modelId) + '">' +
|
||||||
|
escapeHtml(model.modelName || model.modelId) +
|
||||||
|
(providers ? ' (' + escapeHtml(providers) + ')' : '') +
|
||||||
|
'</option>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Then show common API models as suggestions
|
||||||
|
var apiModelList = cachedModels.apiModels || [];
|
||||||
|
if (apiModelList.length > 0) {
|
||||||
|
html += '<option value="" disabled>-- ' + (t('codexlens.commonModels') || 'Common Models') + ' --</option>';
|
||||||
|
apiModelList.forEach(function(group) {
|
||||||
|
group.items.forEach(function(model) {
|
||||||
|
// Skip if already in configured list
|
||||||
|
var exists = configuredModels.some(function(m) { return m.modelId === model; });
|
||||||
|
if (!exists) {
|
||||||
|
html += '<option value="' + escapeHtml(model) + '">' + escapeHtml(group.group) + ': ' + escapeHtml(model) + '</option>';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For local backend: show actually downloaded models
|
||||||
|
var localModels = cachedModels.local || [];
|
||||||
|
if (localModels.length > 0) {
|
||||||
|
html += '<option value="" disabled>-- ' + (t('codexlens.downloadedModels') || 'Downloaded Models') + ' --</option>';
|
||||||
|
localModels.forEach(function(model) {
|
||||||
|
var modelId = model.profile || model.model_id || model.id || model.name;
|
||||||
|
var displayName = model.display_name || model.name || model.profile || modelId;
|
||||||
|
var displayText = model.profile && model.name ?
|
||||||
|
model.profile + ' (' + model.name + ')' : displayName;
|
||||||
|
html += '<option value="' + escapeHtml(modelId) + '">' + escapeHtml(displayText) + '</option>';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
html += '<option value="" disabled>-- ' + (t('codexlens.noLocalModels') || 'No models downloaded') + ' --</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
datalist.innerHTML = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make function globally accessible
|
||||||
|
window.updateModelOptionsOnBackendChange = updateModelOptionsOnBackendChange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save environment variables to ~/.codexlens/.env
|
* Save environment variables to ~/.codexlens/.env
|
||||||
*/
|
*/
|
||||||
@@ -1141,6 +1239,9 @@ async function saveEnvVariables() {
|
|||||||
var detectedGpuInfo = null;
|
var detectedGpuInfo = null;
|
||||||
// Store available GPU devices
|
// Store available GPU devices
|
||||||
var availableGpuDevices = null;
|
var availableGpuDevices = null;
|
||||||
|
// Store model data for dynamic backend switching
|
||||||
|
var cachedEmbeddingModels = { local: [], api: [], apiModels: [] };
|
||||||
|
var cachedRerankerModels = { local: [], api: [], apiModels: [] };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect GPU support
|
* Detect GPU support
|
||||||
|
|||||||
Reference in New Issue
Block a user