From 10fa7c1b8daec9cc74688dd5f9f41d76de40db58 Mon Sep 17 00:00:00 2001 From: joshavant <830519+joshavant@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:24:38 -0500 Subject: [PATCH] UI: trim skills and usage controller scaffolding --- ui/src/ui/controllers/skills.ts | 21 +++---------- ui/src/ui/controllers/usage.ts | 52 +++++++++++++++------------------ 2 files changed, 28 insertions(+), 45 deletions(-) diff --git a/ui/src/ui/controllers/skills.ts b/ui/src/ui/controllers/skills.ts index 1737e34125f..52bfc98247b 100644 --- a/ui/src/ui/controllers/skills.ts +++ b/ui/src/ui/controllers/skills.ts @@ -63,21 +63,11 @@ export type SkillMessage = { export type SkillMessageMap = Record; -type LoadSkillsOptions = { - clearMessages?: boolean; -}; - -function setSkillMessage(state: SkillsState, key: string, message?: SkillMessage) { +function setSkillMessage(state: SkillsState, key: string, message: SkillMessage) { if (!key.trim()) { return; } - const next = { ...state.skillMessages }; - if (message) { - next[key] = message; - } else { - delete next[key]; - } - state.skillMessages = next; + state.skillMessages = { ...state.skillMessages, [key]: message }; } function getErrorMessage(err: unknown) { @@ -120,14 +110,11 @@ export function setClawHubSearchQuery(state: SkillsState, query: string) { state.clawhubSearchLoading = false; } -export async function loadSkills(state: SkillsState, options?: LoadSkillsOptions) { +export async function loadSkills(state: SkillsState, options?: { clearMessages?: boolean }) { if (options?.clearMessages && Object.keys(state.skillMessages).length > 0) { state.skillMessages = {}; } - if (!state.client || !state.connected) { - return; - } - if (state.skillsLoading) { + if (!state.client || !state.connected || state.skillsLoading) { return; } state.skillsLoading = true; diff --git a/ui/src/ui/controllers/usage.ts b/ui/src/ui/controllers/usage.ts index 392b51cf0c0..6ff761c015c 100644 --- a/ui/src/ui/controllers/usage.ts +++ b/ui/src/ui/controllers/usage.ts @@ -29,11 +29,6 @@ export type UsageState = { settings?: { gatewayUrl?: string }; }; -type UsageDateInterpretationParams = { - mode: "utc" | "specific"; - utcOffset?: string; -}; - const LEGACY_USAGE_DATE_PARAMS_STORAGE_KEY = "openclaw.control.usage.date-params.v1"; const LEGACY_USAGE_DATE_PARAMS_DEFAULT_GATEWAY_KEY = "__default__"; const LEGACY_USAGE_DATE_PARAMS_MODE_RE = /unexpected property ['"]mode['"]/i; @@ -137,9 +132,7 @@ const formatUtcOffset = (timezoneOffsetMinutes: number): string => { : `UTC${sign}${hours}:${minutes.toString().padStart(2, "0")}`; }; -const buildDateInterpretationParams = ( - timeZone: "local" | "utc", -): UsageDateInterpretationParams => { +const buildDateInterpretationParams = (timeZone: "local" | "utc") => { if (timeZone === "utc") { return { mode: "utc" }; } @@ -253,38 +246,41 @@ export const __test = { }, }; -export async function loadSessionTimeSeries(state: UsageState, sessionKey: string) { - if (!state.client || !state.connected || state.usageTimeSeriesLoading) { +async function runOptionalUsageDetailRequest( + state: UsageState, + loadingKey: "usageTimeSeriesLoading" | "usageSessionLogsLoading", + run: (client: GatewayBrowserClient) => Promise, +) { + const client = state.client; + if (!client || !state.connected || state[loadingKey]) { return; } - state.usageTimeSeriesLoading = true; - state.usageTimeSeries = null; + state[loadingKey] = true; try { - const res = await state.client.request("sessions.usage.timeseries", { key: sessionKey }); - state.usageTimeSeries = res ? (res as SessionUsageTimeSeries) : null; + await run(client); } catch { - // Silently fail - time series is optional. + // Silently fail - optional detail endpoints } finally { - state.usageTimeSeriesLoading = false; + state[loadingKey] = false; } } +export async function loadSessionTimeSeries(state: UsageState, sessionKey: string) { + await runOptionalUsageDetailRequest(state, "usageTimeSeriesLoading", async (client) => { + state.usageTimeSeries = null; + const res = await client.request("sessions.usage.timeseries", { key: sessionKey }); + state.usageTimeSeries = res ? (res as SessionUsageTimeSeries) : null; + }); +} + export async function loadSessionLogs(state: UsageState, sessionKey: string) { - if (!state.client || !state.connected || state.usageSessionLogsLoading) { - return; - } - state.usageSessionLogsLoading = true; - state.usageSessionLogs = null; - try { - const payload = (await state.client.request("sessions.usage.logs", { + await runOptionalUsageDetailRequest(state, "usageSessionLogsLoading", async (client) => { + state.usageSessionLogs = null; + const payload = (await client.request("sessions.usage.logs", { key: sessionKey, limit: 1000, })) as { logs?: unknown } | null; const logs = payload?.logs; state.usageSessionLogs = Array.isArray(logs) ? (logs as SessionLogEntry[]) : null; - } catch { - // Silently fail - logs are optional. - } finally { - state.usageSessionLogsLoading = false; - } + }); }