mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
refactor(ui): simplify agent overview component by removing unused identity fields and enhancing fallback display
This commit is contained in:
@@ -2005,8 +2005,8 @@
|
||||
|
||||
.agents-overview-grid {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 10px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
}
|
||||
|
||||
.agent-kv {
|
||||
@@ -2658,6 +2658,67 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Debug Event Log
|
||||
=========================================== */
|
||||
|
||||
.debug-event-log-scroll {
|
||||
margin-top: 12px;
|
||||
max-height: 480px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.debug-event-entry {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.debug-event-entry:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.debug-event-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 0;
|
||||
cursor: pointer;
|
||||
font-family: var(--mono);
|
||||
font-size: 13px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.debug-event-summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.debug-event-summary::before {
|
||||
content: "▸";
|
||||
flex-shrink: 0;
|
||||
width: 12px;
|
||||
color: var(--muted);
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.debug-event-entry[open] > .debug-event-summary::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.debug-event-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.debug-event-ts {
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.debug-event-payload {
|
||||
margin: 0 0 8px 22px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Overview Event Log
|
||||
=========================================== */
|
||||
@@ -2838,8 +2899,10 @@
|
||||
|
||||
.ov-bottom-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 14px;
|
||||
max-height: 420px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
grid-template-columns: 260px minmax(0, 1fr);
|
||||
gap: 0;
|
||||
height: calc(100vh - 160px);
|
||||
margin: -16px;
|
||||
margin: 0 -16px -16px;
|
||||
border-radius: var(--radius-xl);
|
||||
border: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { html, nothing } from "lit";
|
||||
import type { AgentIdentityResult, AgentsFilesListResult, AgentsListResult } from "../types.ts";
|
||||
import type { AgentsFilesListResult, AgentsListResult } from "../types.ts";
|
||||
import {
|
||||
agentAvatarHue,
|
||||
agentBadgeText,
|
||||
buildModelOptions,
|
||||
normalizeAgentLabel,
|
||||
normalizeModelValue,
|
||||
parseFallbackList,
|
||||
resolveAgentConfig,
|
||||
resolveAgentEmoji,
|
||||
resolveModelFallbacks,
|
||||
resolveModelLabel,
|
||||
resolveModelPrimary,
|
||||
@@ -20,9 +16,6 @@ export function renderAgentOverview(params: {
|
||||
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;
|
||||
@@ -36,9 +29,6 @@ export function renderAgentOverview(params: {
|
||||
agent,
|
||||
configForm,
|
||||
agentFilesList,
|
||||
agentIdentity,
|
||||
agentIdentityLoading,
|
||||
agentIdentityError,
|
||||
configLoading,
|
||||
configSaving,
|
||||
configDirty,
|
||||
@@ -65,26 +55,9 @@ export function renderAgentOverview(params: {
|
||||
const effectivePrimary = modelPrimary ?? defaultPrimary ?? null;
|
||||
const modelFallbacks = resolveModelFallbacks(config.entry?.model);
|
||||
const fallbackChips = modelFallbacks ?? [];
|
||||
const identityName =
|
||||
agentIdentity?.name?.trim() ||
|
||||
agent.identity?.name?.trim() ||
|
||||
agent.name?.trim() ||
|
||||
config.entry?.name ||
|
||||
"-";
|
||||
const resolvedEmoji = resolveAgentEmoji(agent, agentIdentity);
|
||||
const identityEmoji = resolvedEmoji || "-";
|
||||
const skillFilter = Array.isArray(config.entry?.skills) ? config.entry?.skills : null;
|
||||
const skillCount = skillFilter?.length ?? null;
|
||||
const identityStatus = agentIdentityLoading
|
||||
? "Loading…"
|
||||
: agentIdentityError
|
||||
? "Unavailable"
|
||||
: "";
|
||||
const isDefault = Boolean(params.defaultId && agent.id === params.defaultId);
|
||||
const badge = agentBadgeText(agent.id, params.defaultId);
|
||||
const hue = agentAvatarHue(agent.id);
|
||||
const displayName = normalizeAgentLabel(agent);
|
||||
const subtitle = agent.identity?.theme?.trim() || "";
|
||||
const disabled = !configForm || configLoading || configSaving;
|
||||
|
||||
const removeChip = (index: number) => {
|
||||
@@ -104,27 +77,11 @@ export function renderAgentOverview(params: {
|
||||
}
|
||||
};
|
||||
|
||||
const fallbackSummary = fallbackChips.length > 0 ? `${fallbackChips.length} configured` : "none";
|
||||
|
||||
return html`
|
||||
<section class="card">
|
||||
<div class="card-title">Overview</div>
|
||||
<div class="card-sub">Workspace paths and identity metadata.</div>
|
||||
|
||||
<div class="agent-identity-card" style="margin-top: 16px;">
|
||||
<div class="agent-avatar" style="--agent-hue: ${hue}">
|
||||
${resolvedEmoji || displayName.slice(0, 1)}
|
||||
</div>
|
||||
<div class="agent-identity-details">
|
||||
<div class="agent-identity-name">${identityName}</div>
|
||||
<div class="agent-identity-meta">
|
||||
${identityEmoji !== "-" ? html`<span>${identityEmoji}</span>` : nothing}
|
||||
${subtitle ? html`<span>${subtitle}</span>` : nothing}
|
||||
${badge ? html`<span class="agent-pill">${badge}</span>` : nothing}
|
||||
${identityStatus ? html`<span class="muted">${identityStatus}</span>` : nothing}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="agents-overview-grid" style="margin-top: 16px;">
|
||||
<div class="agents-overview-grid">
|
||||
<div class="agent-kv">
|
||||
<div class="label">Workspace</div>
|
||||
<div>
|
||||
@@ -144,23 +101,25 @@ export function renderAgentOverview(params: {
|
||||
<div class="label">Skills Filter</div>
|
||||
<div>${skillFilter ? `${skillCount} selected` : "all skills"}</div>
|
||||
</div>
|
||||
<div class="agent-kv">
|
||||
<div class="label">Fallbacks</div>
|
||||
<div class="mono">${fallbackSummary}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${
|
||||
configDirty
|
||||
? html`
|
||||
<div class="callout warn" style="margin-top: 16px">You have unsaved config changes.</div>
|
||||
<div class="callout warn" style="margin-top: 12px">You have unsaved config changes.</div>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
|
||||
<div class="agent-model-select" style="margin-top: 20px;">
|
||||
<div class="label">Model Selection</div>
|
||||
<div class="row" style="gap: 12px; flex-wrap: wrap;">
|
||||
<label class="field" style="min-width: 260px; flex: 1;">
|
||||
<div class="agent-model-select">
|
||||
<div class="row" style="gap: 12px; flex-wrap: wrap; align-items: flex-end;">
|
||||
<label class="field" style="min-width: 240px; flex: 1;">
|
||||
<span>Primary model${isDefault ? " (default)" : ""}</span>
|
||||
<select
|
||||
.value=${effectivePrimary ?? ""}
|
||||
?disabled=${disabled}
|
||||
@change=${(e: Event) =>
|
||||
onModelChange(agent.id, (e.target as HTMLSelectElement).value || null)}
|
||||
@@ -177,7 +136,7 @@ export function renderAgentOverview(params: {
|
||||
${buildModelOptions(configForm, effectivePrimary ?? undefined)}
|
||||
</select>
|
||||
</label>
|
||||
<div class="field" style="min-width: 260px; flex: 1;">
|
||||
<div class="field" style="min-width: 240px; flex: 1;">
|
||||
<span>Fallbacks</span>
|
||||
<div class="agent-chip-input" @click=${(e: Event) => {
|
||||
const container = e.currentTarget as HTMLElement;
|
||||
@@ -214,18 +173,18 @@ export function renderAgentOverview(params: {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="justify-content: flex-end; gap: 8px;">
|
||||
<button class="btn btn--sm" ?disabled=${configLoading} @click=${onConfigReload}>
|
||||
Reload Config
|
||||
</button>
|
||||
<button
|
||||
class="btn btn--sm primary"
|
||||
?disabled=${configSaving || !configDirty}
|
||||
@click=${onConfigSave}
|
||||
>
|
||||
${configSaving ? "Saving…" : "Save"}
|
||||
</button>
|
||||
<div class="agent-model-actions">
|
||||
<button class="btn btn--sm" ?disabled=${configLoading} @click=${onConfigReload}>
|
||||
Reload Config
|
||||
</button>
|
||||
<button
|
||||
class="btn btn--sm primary"
|
||||
?disabled=${configSaving || !configDirty}
|
||||
@click=${onConfigSave}
|
||||
>
|
||||
${configSaving ? "Saving…" : "Save"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -387,7 +387,10 @@ export function buildModelOptions(
|
||||
<option value="" disabled>No configured models</option>
|
||||
`;
|
||||
}
|
||||
return options.map((option) => html`<option value=${option.value}>${option.label}</option>`);
|
||||
return options.map(
|
||||
(option) =>
|
||||
html`<option value=${option.value} ?selected=${current === option.value}>${option.label}</option>`,
|
||||
);
|
||||
}
|
||||
|
||||
type CompiledPattern =
|
||||
|
||||
@@ -120,26 +120,49 @@ export function renderDebug(props: DebugProps) {
|
||||
</section>
|
||||
|
||||
<section class="card" style="margin-top: 18px;">
|
||||
<div class="card-title">Event Log</div>
|
||||
<div class="card-sub">Latest gateway events.</div>
|
||||
<div class="row" style="justify-content: space-between; align-items: baseline;">
|
||||
<div>
|
||||
<div class="card-title">Event Log</div>
|
||||
<div class="card-sub">Latest gateway events.</div>
|
||||
</div>
|
||||
${
|
||||
props.eventLog.length > 0
|
||||
? html`<button
|
||||
class="btn btn-sm"
|
||||
@click=${(e: Event) => {
|
||||
const section = (e.target as HTMLElement).closest("section")!;
|
||||
const details = section.querySelectorAll<HTMLDetailsElement>(
|
||||
"details.debug-event-entry",
|
||||
);
|
||||
const allOpen = Array.from(details).every((d) => d.open);
|
||||
details.forEach((d) => (d.open = !allOpen));
|
||||
}}
|
||||
>${"Expand All / Collapse All"}</button>`
|
||||
: nothing
|
||||
}
|
||||
</div>
|
||||
${
|
||||
props.eventLog.length === 0
|
||||
? html`
|
||||
<div class="muted" style="margin-top: 12px">No events yet.</div>
|
||||
`
|
||||
: html`
|
||||
<div class="list" style="margin-top: 12px;">
|
||||
<div class="debug-event-log-scroll">
|
||||
${props.eventLog.map(
|
||||
(evt) => html`
|
||||
<div class="list-item">
|
||||
<div class="list-main">
|
||||
<div class="list-title">${evt.event}</div>
|
||||
<div class="list-sub">${new Date(evt.ts).toLocaleTimeString()}</div>
|
||||
</div>
|
||||
<div class="list-meta">
|
||||
<pre class="code-block">${formatEventPayload(evt.payload)}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<details class="debug-event-entry">
|
||||
<summary class="debug-event-summary">
|
||||
<span class="debug-event-name">${evt.event}</span>
|
||||
<span class="debug-event-ts muted">${new Date(evt.ts).toLocaleTimeString()}</span>
|
||||
</summary>
|
||||
${
|
||||
evt.payload
|
||||
? html`<pre class="code-block debug-event-payload">${formatEventPayload(evt.payload)}</pre>`
|
||||
: html`
|
||||
<div class="muted" style="padding: 8px 0 4px">No payload.</div>
|
||||
`
|
||||
}
|
||||
</details>
|
||||
`,
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user