mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
feat: 添加高可用性模型池支持,优化路径解析功能
This commit is contained in:
@@ -1122,6 +1122,55 @@ select.cli-input {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===========================
|
||||||
|
Model Pools (High Availability)
|
||||||
|
=========================== */
|
||||||
|
|
||||||
|
.model-pools-list {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-type-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-type-header {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
background: hsl(var(--muted) / 0.3);
|
||||||
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-item {
|
||||||
|
padding: 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
|
transition: background-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-item:hover {
|
||||||
|
background: hsl(var(--muted) / 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-item.selected {
|
||||||
|
background: hsl(var(--primary) / 0.1);
|
||||||
|
border-left: 3px solid hsl(var(--primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-item .pool-name {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-item .pool-target {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
}
|
||||||
|
|
||||||
/* Responsive adjustments for tabs */
|
/* Responsive adjustments for tabs */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.sidebar-tab {
|
.sidebar-tab {
|
||||||
|
|||||||
@@ -2396,7 +2396,7 @@ function deleteModel(providerId, modelId, modelType) {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return loadApiSettings();
|
return loadApiSettings(true); // Force refresh to get updated data
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
if (selectedProviderId === providerId) {
|
if (selectedProviderId === providerId) {
|
||||||
@@ -4091,23 +4091,21 @@ function renderModelPoolsList() {
|
|||||||
type === 'llm' ? t('apiSettings.llmPools') :
|
type === 'llm' ? t('apiSettings.llmPools') :
|
||||||
t('apiSettings.rerankerPools');
|
t('apiSettings.rerankerPools');
|
||||||
|
|
||||||
html += '<div class="pool-type-group" style="margin-bottom: 1.5rem;">' +
|
html += '<div class="pool-type-group">' +
|
||||||
'<div class="pool-type-header" style="padding: 0.5rem; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; color: var(--text-secondary); border-bottom: 1px solid var(--border);">' +
|
'<div class="pool-type-header">' + typeLabel + '</div>';
|
||||||
typeLabel +
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
pools.forEach(function(pool) {
|
pools.forEach(function(pool) {
|
||||||
var isSelected = selectedPoolId === pool.id;
|
var isSelected = selectedPoolId === pool.id;
|
||||||
var statusClass = pool.enabled ? 'status-enabled' : 'status-disabled';
|
var statusClass = pool.enabled ? 'status-enabled' : 'status-disabled';
|
||||||
var statusText = pool.enabled ? t('common.enabled') : t('common.disabled');
|
var statusText = pool.enabled ? t('common.enabled') : t('common.disabled');
|
||||||
|
|
||||||
html += '<div class="pool-item' + (isSelected ? ' selected' : '') + '" onclick="selectModelPool(\'' + pool.id + '\')" style="padding: 0.75rem; cursor: pointer; border-bottom: 1px solid var(--border);">' +
|
html += '<div class="pool-item' + (isSelected ? ' selected' : '') + '" onclick="selectModelPool(\'' + pool.id + '\')">' +
|
||||||
'<div style="display: flex; justify-content: space-between; align-items: center;">' +
|
'<div style="display: flex; justify-content: space-between; align-items: center;">' +
|
||||||
'<div style="flex: 1; min-width: 0;">' +
|
'<div style="flex: 1; min-width: 0;">' +
|
||||||
'<div style="font-weight: 500; margin-bottom: 0.25rem;">' + escapeHtml(pool.name || pool.targetModel) + '</div>' +
|
'<div class="pool-name">' + escapeHtml(pool.name || pool.targetModel) + '</div>' +
|
||||||
'<div style="font-size: 0.75rem; color: var(--text-secondary);">' + escapeHtml(pool.targetModel) + '</div>' +
|
'<div class="pool-target">' + escapeHtml(pool.targetModel) + '</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<span class="status-badge ' + statusClass + '" style="font-size: 0.7rem; padding: 0.25rem 0.5rem; border-radius: 4px;">' + statusText + '</span>' +
|
'<span class="status-badge ' + statusClass + '">' + statusText + '</span>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export interface ValidatePathOptions {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a path, handling ~ for home directory
|
* Resolve a path, handling ~ for home directory
|
||||||
|
* Also handles Windows drive-relative paths (e.g., "D:path" -> "D:\path")
|
||||||
* @param inputPath - Path to resolve
|
* @param inputPath - Path to resolve
|
||||||
* @returns Absolute path
|
* @returns Absolute path
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +35,17 @@ export function resolvePath(inputPath: string): string {
|
|||||||
return join(homedir(), inputPath.slice(1));
|
return join(homedir(), inputPath.slice(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Windows drive-relative paths (e.g., "D:path" without backslash)
|
||||||
|
// Pattern: single letter followed by colon, then immediately a non-slash character
|
||||||
|
// This converts "D:path" to "D:\path" to make it absolute
|
||||||
|
if (process.platform === 'win32' || /^[a-zA-Z]:/.test(inputPath)) {
|
||||||
|
const driveRelativeMatch = inputPath.match(/^([a-zA-Z]:)([^/\\].*)$/);
|
||||||
|
if (driveRelativeMatch) {
|
||||||
|
// Insert backslash after drive letter
|
||||||
|
inputPath = driveRelativeMatch[1] + '\\' + driveRelativeMatch[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(inputPath);
|
return resolve(inputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user