UI: trim skills and usage controller scaffolding

This commit is contained in:
joshavant
2026-04-09 20:24:38 -05:00
committed by Josh Avant
parent db039d994d
commit 10fa7c1b8d
2 changed files with 28 additions and 45 deletions

View File

@@ -63,21 +63,11 @@ export type SkillMessage = {
export type SkillMessageMap = Record<string, SkillMessage>;
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;

View File

@@ -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<void>,
) {
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;
}
});
}