import { html, nothing } from "lit" ;
import { t } from "../../i18n/index.ts" ;
import type {
AgentIdentityResult,
AgentsFilesListResult,
AgentsListResult,
ModelCatalogEntry,
} from "../types.ts" ;
import {
buildModelOptions,
normalizeModelValue,
parseFallbackList,
resolveAgentConfig,
resolveModelFallbacks,
resolveModelLabel,
resolveModelPrimary,
} from "./agents-utils.ts" ;
import type { AgentsPanel } from "./agents.types.ts" ;
export function renderAgentOverview(params: {
agent: AgentsListResult["agents" ][number];
basePath: string;
defaultId: string | null ;
configForm: Record<string, unknown> | null ;
agentFilesList: AgentsFilesListResult | null ;
agentIdentity: AgentIdentityResult | null ;
agentIdentityLoading: boolean ;
agentIdentityError: string | null ;
configLoading: boolean ;
configSaving: boolean ;
configDirty: boolean ;
modelCatalog: ModelCatalogEntry[];
onConfigReload: () => void ;
onConfigSave: () => void ;
onModelChange: (agentId: string, modelId: string | null ) => void ;
onModelFallbacksChange: (agentId: string, fallbacks: string[]) => void ;
onSelectPanel: (panel: AgentsPanel) => void ;
}) {
const {
agent,
configForm,
agentFilesList,
configLoading,
configSaving,
configDirty,
onConfigReload,
onConfigSave,
onModelChange,
onModelFallbacksChange,
onSelectPanel,
} = params;
const config = resolveAgentConfig(configForm, agent.id);
const agentModel = agent.model;
const workspaceFromFiles =
agentFilesList && agentFilesList.agentId === agent.id ? agentFilesList.workspace : null ;
const workspace =
workspaceFromFiles ||
config.entry?.workspace ||
config.defaults?.workspace ||
agent.workspace ||
"default" ;
const model = config.entry?.model
? resolveModelLabel(config.entry?.model)
: config.defaults?.model
? resolveModelLabel(config.defaults?.model)
: resolveModelLabel(agentModel);
const defaultModel = resolveModelLabel(config.defaults?.model ?? agentModel);
const entryPrimary = resolveModelPrimary(config.entry?.model);
const defaultPrimary =
resolveModelPrimary(config.defaults?.model) ||
(defaultModel !== "-" ? normalizeModelValue(defaultModel) : null ) ||
(configForm ? null : resolveModelPrimary(agentModel));
const effectivePrimary = entryPrimary ?? defaultPrimary ?? null ;
const modelFallbacks =
resolveModelFallbacks(config.entry?.model) ??
resolveModelFallbacks(config.defaults?.model) ??
(configForm ? null : resolveModelFallbacks(agentModel));
const fallbackChips = modelFallbacks ?? [];
const skillFilter = Array.isArray(config.entry?.skills) ? config.entry?.skills : null ;
const skillCount = skillFilter?.length ?? null ;
const isDefault = Boolean (params.defaultId && agent.id === params.defaultId);
const disabled = !configForm || configLoading || configSaving;
const removeChip = (index: number) => {
const next = fallbackChips.filter((_, i) => i !== index);
onModelFallbacksChange(agent.id, next);
};
const handleChipKeydown = (e: KeyboardEvent) => {
const input = e.target as HTMLInputElement;
if (e.key === "Enter" || e.key === "," ) {
e.preventDefault();
const parsed = parseFallbackList(input.value);
if (parsed.length > 0 ) {
onModelFallbacksChange(agent.id, [...fallbackChips, ...parsed]);
input.value = "" ;
}
}
};
return html`
<section class ="card" >
<div class ="card-title" >Overview</div>
<div class ="card-sub" >Workspace paths and identity metadata.</div>
<div class ="agents-overview-grid" style="margin-top: 16px;" >
<div class ="agent-kv" >
<div class ="label" >Workspace</div>
<div>
<button
type="button"
class ="workspace-link mono"
@click=${() => onSelectPanel("files" )}
title="Open Files tab"
>
${workspace}
</button>
</div>
</div>
<div class ="agent-kv" >
<div class ="label" >Primary Model</div>
<div class ="mono" >${model}</div>
</div>
<div class ="agent-kv" >
<div class ="label" >Skills Filter</div>
<div>${skillFilter ? `${skillCount} selected` : "all skills" }</div>
</div>
</div>
${configDirty
? html`
<div class ="callout warn" style="margin-top: 16px" >
You have unsaved config changes.
</div>
`
: nothing}
<div class ="agent-model-select" style="margin-top: 20px;" >
<div class ="label" >Model Selection</div>
<div class ="agent-model-fields" >
<label class ="field" >
<span>Primary model${isDefault ? " (default)" : "" }</span>
<select
.value=${isDefault ? (effectivePrimary ?? "" ) : (entryPrimary ?? "" )}
?disabled=${disabled}
@change=${(e: Event) =>
onModelChange(agent.id, (e.target as HTMLSelectElement).value || null )}
>
${isDefault
? html` <option value="" >Not set</option> `
: html`
<option value="" >
${defaultPrimary ? `Inherit default (${defaultPrimary})` : "Inherit default" }
</option>
`}
${buildModelOptions(configForm, effectivePrimary ?? undefined, params.modelCatalog)}
</select>
</label>
<div class ="field" >
<span>Fallbacks</span>
<div
class ="agent-chip-input"
@click=${(e: Event) => {
const container = e.currentTarget as HTMLElement;
const input = container.querySelector("input" );
if (input) {
input.focus();
}
}}
>
${fallbackChips.map(
(chip, i) => html`
<span class ="chip" >
${chip}
<button
type="button"
class ="chip-remove"
?disabled=${disabled}
@click=${() => removeChip(i)}
>
×
</button>
</span>
`,
)}
<input
?disabled=${disabled}
placeholder=${fallbackChips.length === 0 ? "provider/model" : "" }
@keydown=${handleChipKeydown}
@blur=${(e: Event) => {
const input = e.target as HTMLInputElement;
const parsed = parseFallbackList(input.value);
if (parsed.length > 0 ) {
onModelFallbacksChange(agent.id, [...fallbackChips, ...parsed]);
input.value = "" ;
}
}}
/>
</div>
</div>
</div>
<div class ="agent-model-actions" >
<button
type="button"
class ="btn btn--sm"
?disabled=${configLoading}
@click=${onConfigReload}
>
${t("common.reloadConfig" )}
</button>
<button
type="button"
class ="btn btn--sm primary"
?disabled=${configSaving || !configDirty}
@click=${onConfigSave}
>
${configSaving ? "Saving…" : "Save" }
</button>
</div>
</div>
</section>
`;
}
Messung V0.5 in Prozent C=99 H=98 G=98
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland