Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,28 +102,42 @@ export function AgentLabSection(): ReactElement {
setEditing(true);
}

function mergeTemplateModels(currentModels: ModelForm[], vendor: string): ModelForm[] {
const entry = catalog.data?.find((item) => item.vendor === vendor);
if (!entry?.models.length) return currentModels;
const seen = new Set(currentModels.map((m) => m.id));
const extra = entry.models
.filter((m) => !seen.has(m.id))
.map((m) => ({ id: m.id, label: m.label ?? '', capabilities: m.capabilities as Capability[] }));
return extra.length > 0 ? [...currentModels, ...extra] : currentModels;
}

function applyVendor(vendor: string): void {
const entry = catalog.data?.find((item) => item.vendor === vendor);
setForm((current) => ({
...current,
vendor,
baseUrl: current.baseUrl.trim() || entry?.baseUrl || current.baseUrl,
name: current.name.trim() || entry?.label?.replace(/(.*?)/g, '') || current.name,
models: mergeTemplateModels(current.models, vendor),
}));
}

function importTemplateModels(): void {
const entry = catalog.data?.find((item) => item.vendor === form.vendor);
if (!entry?.models.length) return;
setForm((current) => {
const seen = new Set(current.models.map((m) => m.id));
const extra = entry.models
.filter((m) => !seen.has(m.id))
.map((m) => ({ id: m.id, label: m.label ?? '', capabilities: m.capabilities as Capability[] }));
return { ...current, models: [...current.models, ...extra] };
});
setForm((current) => ({
...current,
models: mergeTemplateModels(current.models, form.vendor),
}));
}

/** 模板中有多少个模型尚未添加(用于按钮 badge)。 */
const newModelCount = useMemo(() => {
const entry = catalog.data?.find((item) => item.vendor === form.vendor);
if (!entry?.models.length) return 0;
const seen = new Set(form.models.map((m) => m.id));
return entry.models.filter((m) => !seen.has(m.id)).length;
}, [catalog.data, form.vendor, form.models]);

function addModel(): void {
setForm((c) => ({ ...c, models: [...c.models, { id: '', label: '', capabilities: ['chat'] }] }));
}
Expand Down Expand Up @@ -320,7 +334,7 @@ export function AgentLabSection(): ReactElement {
<div className="weq-set-card-title">可用模型</div>
<div className="weq-set-card-action" style={{ display: 'flex', gap: 6 }}>
<button type="button" className="weq-set-btn weq-set-btn-soft weq-set-btn-sm" onClick={importTemplateModels} disabled={!vendorEntry?.models.length}>
<Sparkles size={12} /> 导入模板推荐
<Sparkles size={12} /> 导入模板推荐{newModelCount > 0 ? ` (${newModelCount})` : ''}
</button>
<button type="button" className="weq-set-btn weq-set-btn-soft weq-set-btn-sm" onClick={addModel}>
<Plus size={12} /> 手动添加
Expand Down
6 changes: 5 additions & 1 deletion apps/desktop/src/renderer/src/views/AgentLabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,11 @@ export function AgentLabView(): ReactElement {
<strong>{activePersona?.name ?? '克隆体'}</strong>
<span>
{activePersona
? `${activePersona.models?.chat?.model ?? '旧版克隆,请重建'} · 样本 ${activePersona.corpusMessageCount} 条`
? (() => {
const p = (providers.data ?? []).find((pr) => pr.id === activePersona.models?.chat?.providerId);
const modelText = activePersona.models?.chat?.model ?? '旧版克隆,请重建';
return `${p ? `${p.name} · ` : ''}${modelText} · 样本 ${activePersona.corpusMessageCount} 条`;
})()
: '加载中…'}
</span>
</div>
Expand Down
15 changes: 14 additions & 1 deletion packages/service/src/bootstrap/agentlab_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,21 @@ import type { UserConfigService } from './user_config';
export class AgentLabConfigService {
constructor(private readonly userConfig: UserConfigService) {}

/**
* 用厂商模板自动补全缺失的模型(仅追加,不覆盖已有)。
* 解决了用户早前保存的 provider 不包含 catalog 后续新增模型的问题。
*/
private enrichProvider(p: AgentLabProviderConfig): AgentLabProviderConfig {
const entry = AGENTLAB_PROVIDER_CATALOG.find((c) => c.vendor === p.vendor);
if (!entry?.models?.length) return p;
const existingIds = new Set(p.models.map((m) => m.id));
const extra = entry.models.filter((m) => !existingIds.has(m.id));
if (extra.length === 0) return p;
return { ...p, models: [...p.models, ...extra] };
}

listProviders(): AgentLabProviderConfig[] {
return this.userConfig.getSettings().agentLab.providers;
return this.userConfig.getSettings().agentLab.providers.map((p) => this.enrichProvider(p));
}

getProvider(providerId: string): AgentLabProviderConfig | null {
Expand Down
Loading