diff --git a/.oxlintrc.json b/.oxlintrc.json index fc873fc0df..9ac7e25f21 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -31,7 +31,6 @@ "skills/", "src/canvas-host/a2ui/a2ui.bundle.js", "Swabble/", - "vendor/", - "ui/" + "vendor/" ] } diff --git a/ui/src/ui/app-channels.ts b/ui/src/ui/app-channels.ts index 3f139ea5a8..53b599a21c 100644 --- a/ui/src/ui/app-channels.ts +++ b/ui/src/ui/app-channels.ts @@ -36,15 +36,15 @@ export async function handleChannelConfigReload(host: OpenClawApp) { } function parseValidationErrors(details: unknown): Record { - if (!Array.isArray(details)) return {}; + if (!Array.isArray(details)) {return {};} const errors: Record = {}; for (const entry of details) { - if (typeof entry !== "string") continue; + if (typeof entry !== "string") {continue;} const [rawField, ...rest] = entry.split(":"); - if (!rawField || rest.length === 0) continue; + if (!rawField || rest.length === 0) {continue;} const field = rawField.trim(); const message = rest.join(":").trim(); - if (field && message) errors[field] = message; + if (field && message) {errors[field] = message;} } return errors; } @@ -78,7 +78,7 @@ export function handleNostrProfileFieldChange( value: string, ) { const state = host.nostrProfileFormState; - if (!state) return; + if (!state) {return;} host.nostrProfileFormState = { ...state, values: { @@ -94,7 +94,7 @@ export function handleNostrProfileFieldChange( export function handleNostrProfileToggleAdvanced(host: OpenClawApp) { const state = host.nostrProfileFormState; - if (!state) return; + if (!state) {return;} host.nostrProfileFormState = { ...state, showAdvanced: !state.showAdvanced, @@ -103,7 +103,7 @@ export function handleNostrProfileToggleAdvanced(host: OpenClawApp) { export async function handleNostrProfileSave(host: OpenClawApp) { const state = host.nostrProfileFormState; - if (!state || state.saving) return; + if (!state || state.saving) {return;} const accountId = resolveNostrAccountId(host); host.nostrProfileFormState = { @@ -172,7 +172,7 @@ export async function handleNostrProfileSave(host: OpenClawApp) { export async function handleNostrProfileImport(host: OpenClawApp) { const state = host.nostrProfileFormState; - if (!state || state.importing) return; + if (!state || state.importing) {return;} const accountId = resolveNostrAccountId(host); host.nostrProfileFormState = { diff --git a/ui/src/ui/app-chat.ts b/ui/src/ui/app-chat.ts index 030b714679..bd2d1348e9 100644 --- a/ui/src/ui/app-chat.ts +++ b/ui/src/ui/app-chat.ts @@ -32,9 +32,9 @@ export function isChatBusy(host: ChatHost) { export function isChatStopCommand(text: string) { const trimmed = text.trim(); - if (!trimmed) return false; + if (!trimmed) {return false;} const normalized = trimmed.toLowerCase(); - if (normalized === "/stop") return true; + if (normalized === "/stop") {return true;} return ( normalized === "stop" || normalized === "esc" || @@ -46,14 +46,14 @@ export function isChatStopCommand(text: string) { function isChatResetCommand(text: string) { const trimmed = text.trim(); - if (!trimmed) return false; + if (!trimmed) {return false;} const normalized = trimmed.toLowerCase(); - if (normalized === "/new" || normalized === "/reset") return true; + if (normalized === "/new" || normalized === "/reset") {return true;} return normalized.startsWith("/new ") || normalized.startsWith("/reset "); } export async function handleAbortChat(host: ChatHost) { - if (!host.connected) return; + if (!host.connected) {return;} host.chatMessage = ""; await abortChatRun(host as unknown as OpenClawApp); } @@ -66,7 +66,7 @@ function enqueueChatMessage( ) { const trimmed = text.trim(); const hasAttachments = Boolean(attachments && attachments.length > 0); - if (!trimmed && !hasAttachments) return; + if (!trimmed && !hasAttachments) {return;} host.chatQueue = [ ...host.chatQueue, { @@ -123,9 +123,9 @@ async function sendChatMessageNow( } async function flushChatQueue(host: ChatHost) { - if (!host.connected || isChatBusy(host)) return; + if (!host.connected || isChatBusy(host)) {return;} const [next, ...rest] = host.chatQueue; - if (!next) return; + if (!next) {return;} host.chatQueue = rest; const ok = await sendChatMessageNow(host, next.text, { attachments: next.attachments, @@ -145,7 +145,7 @@ export async function handleSendChat( messageOverride?: string, opts?: { restoreDraft?: boolean }, ) { - if (!host.connected) return; + if (!host.connected) {return;} const previousDraft = host.chatMessage; const message = (messageOverride ?? host.chatMessage).trim(); const attachments = host.chatAttachments ?? []; @@ -153,7 +153,7 @@ export async function handleSendChat( const hasAttachments = attachmentsToSend.length > 0; // Allow sending with just attachments (no message text required) - if (!message && !hasAttachments) return; + if (!message && !hasAttachments) {return;} if (isChatStopCommand(message)) { await handleAbortChat(host); @@ -201,7 +201,7 @@ type SessionDefaultsSnapshot = { function resolveAgentIdForSession(host: ChatHost): string | null { const parsed = parseAgentSessionKey(host.sessionKey); - if (parsed?.agentId) return parsed.agentId; + if (parsed?.agentId) {return parsed.agentId;} const snapshot = host.hello?.snapshot as | { sessionDefaults?: SessionDefaultsSnapshot } | undefined; diff --git a/ui/src/ui/app-gateway.ts b/ui/src/ui/app-gateway.ts index fab7124753..7ef63f9883 100644 --- a/ui/src/ui/app-gateway.ts +++ b/ui/src/ui/app-gateway.ts @@ -64,8 +64,8 @@ function normalizeSessionKeyForDefaults( ): string { const raw = (value ?? "").trim(); const mainSessionKey = defaults.mainSessionKey?.trim(); - if (!mainSessionKey) return raw; - if (!raw) return mainSessionKey; + if (!mainSessionKey) {return raw;} + if (!raw) {return mainSessionKey;} const mainKey = defaults.mainKey?.trim() || "main"; const defaultAgentId = defaults.defaultAgentId?.trim(); const isAlias = @@ -77,7 +77,7 @@ function normalizeSessionKeyForDefaults( } function applySessionDefaults(host: GatewayHost, defaults?: SessionDefaultsSnapshot) { - if (!defaults?.mainSessionKey) return; + if (!defaults?.mainSessionKey) {return;} const resolvedSessionKey = normalizeSessionKeyForDefaults(host.sessionKey, defaults); const resolvedSettingsSessionKey = normalizeSessionKeyForDefaults( host.settings.sessionKey, @@ -168,7 +168,7 @@ function handleGatewayEventUnsafe(host: GatewayHost, evt: GatewayEventFrame) { } if (evt.event === "agent") { - if (host.onboarding) return; + if (host.onboarding) {return;} handleAgentEvent( host as unknown as Parameters[0], evt.payload as AgentEventPayload | undefined, @@ -198,7 +198,7 @@ function handleGatewayEventUnsafe(host: GatewayHost, evt: GatewayEventFrame) { } } } - if (state === "final") void loadChatHistory(host as unknown as OpenClawApp); + if (state === "final") {void loadChatHistory(host as unknown as OpenClawApp);} return; } diff --git a/ui/src/ui/app-lifecycle.ts b/ui/src/ui/app-lifecycle.ts index de02533990..d66eec7a6a 100644 --- a/ui/src/ui/app-lifecycle.ts +++ b/ui/src/ui/app-lifecycle.ts @@ -77,7 +77,8 @@ export function handleUpdated(host: LifecycleHost, changed: Map[0], forcedByTab || forcedByLoad || !host.chatHasAutoScrolled, diff --git a/ui/src/ui/app-polling.ts b/ui/src/ui/app-polling.ts index c0aa7c9d1d..7aad75a2aa 100644 --- a/ui/src/ui/app-polling.ts +++ b/ui/src/ui/app-polling.ts @@ -11,7 +11,7 @@ type PollingHost = { }; export function startNodesPolling(host: PollingHost) { - if (host.nodesPollInterval != null) return; + if (host.nodesPollInterval != null) {return;} host.nodesPollInterval = window.setInterval( () => void loadNodes(host as unknown as OpenClawApp, { quiet: true }), 5000, @@ -19,35 +19,35 @@ export function startNodesPolling(host: PollingHost) { } export function stopNodesPolling(host: PollingHost) { - if (host.nodesPollInterval == null) return; + if (host.nodesPollInterval == null) {return;} clearInterval(host.nodesPollInterval); host.nodesPollInterval = null; } export function startLogsPolling(host: PollingHost) { - if (host.logsPollInterval != null) return; + if (host.logsPollInterval != null) {return;} host.logsPollInterval = window.setInterval(() => { - if (host.tab !== "logs") return; + if (host.tab !== "logs") {return;} void loadLogs(host as unknown as OpenClawApp, { quiet: true }); }, 2000); } export function stopLogsPolling(host: PollingHost) { - if (host.logsPollInterval == null) return; + if (host.logsPollInterval == null) {return;} clearInterval(host.logsPollInterval); host.logsPollInterval = null; } export function startDebugPolling(host: PollingHost) { - if (host.debugPollInterval != null) return; + if (host.debugPollInterval != null) {return;} host.debugPollInterval = window.setInterval(() => { - if (host.tab !== "debug") return; + if (host.tab !== "debug") {return;} void loadDebug(host as unknown as OpenClawApp); }, 3000); } export function stopDebugPolling(host: PollingHost) { - if (host.debugPollInterval == null) return; + if (host.debugPollInterval == null) {return;} clearInterval(host.debugPollInterval); host.debugPollInterval = null; } diff --git a/ui/src/ui/app-render.helpers.ts b/ui/src/ui/app-render.helpers.ts index f2ff179616..5a8ade23b3 100644 --- a/ui/src/ui/app-render.helpers.ts +++ b/ui/src/ui/app-render.helpers.ts @@ -134,7 +134,7 @@ export function renderChatControls(state: AppViewState) { class="btn btn--sm btn--icon ${showThinking ? "active" : ""}" ?disabled=${disableThinkingToggle} @click=${() => { - if (disableThinkingToggle) return; + if (disableThinkingToggle) {return;} state.applySettings({ ...state.settings, chatShowThinking: !state.settings.chatShowThinking, @@ -153,7 +153,7 @@ export function renderChatControls(state: AppViewState) { class="btn btn--sm btn--icon ${focusActive ? "active" : ""}" ?disabled=${disableFocusToggle} @click=${() => { - if (disableFocusToggle) return; + if (disableFocusToggle) {return;} state.applySettings({ ...state.settings, chatFocusMode: !state.settings.chatFocusMode, @@ -183,18 +183,18 @@ function resolveMainSessionKey( ): string | null { const snapshot = hello?.snapshot as { sessionDefaults?: SessionDefaultsSnapshot } | undefined; const mainSessionKey = snapshot?.sessionDefaults?.mainSessionKey?.trim(); - if (mainSessionKey) return mainSessionKey; + if (mainSessionKey) {return mainSessionKey;} const mainKey = snapshot?.sessionDefaults?.mainKey?.trim(); - if (mainKey) return mainKey; - if (sessions?.sessions?.some((row) => row.key === "main")) return "main"; + if (mainKey) {return mainKey;} + if (sessions?.sessions?.some((row) => row.key === "main")) {return "main";} return null; } function resolveSessionDisplayName(key: string, row?: SessionsListResult["sessions"][number]) { const label = row?.label?.trim(); - if (label) return `${label} (${key})`; + if (label) {return `${label} (${key})`;} const displayName = row?.displayName?.trim(); - if (displayName) return displayName; + if (displayName) {return displayName;} return key; } diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index 31abb5881c..7d7cf7331a 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -98,8 +98,8 @@ function resolveAssistantAvatarUrl(state: AppViewState): string | undefined { const agent = list.find((entry) => entry.id === agentId); const identity = agent?.identity; const candidate = identity?.avatarUrl ?? identity?.avatar; - if (!candidate) return undefined; - if (AVATAR_DATA_RE.test(candidate) || AVATAR_HTTP_RE.test(candidate)) return candidate; + if (!candidate) {return undefined;} + if (AVATAR_DATA_RE.test(candidate) || AVATAR_HTTP_RE.test(candidate)) {return candidate;} return identity?.avatarUrl; } @@ -486,7 +486,7 @@ export function renderApp(state: AppViewState) { return Promise.all([loadChatHistory(state), refreshChatAvatar(state)]); }, onToggleFocusMode: () => { - if (state.onboarding) return; + if (state.onboarding) {return;} state.applySettings({ ...state.settings, chatFocusMode: !state.settings.chatFocusMode, diff --git a/ui/src/ui/app-scroll.ts b/ui/src/ui/app-scroll.ts index 36977047d4..85814e9c1b 100644 --- a/ui/src/ui/app-scroll.ts +++ b/ui/src/ui/app-scroll.ts @@ -12,7 +12,7 @@ type ScrollHost = { }; export function scheduleChatScroll(host: ScrollHost, force = false) { - if (host.chatScrollFrame) cancelAnimationFrame(host.chatScrollFrame); + if (host.chatScrollFrame) {cancelAnimationFrame(host.chatScrollFrame);} if (host.chatScrollTimeout != null) { clearTimeout(host.chatScrollTimeout); host.chatScrollTimeout = null; @@ -25,7 +25,7 @@ export function scheduleChatScroll(host: ScrollHost, force = false) { overflowY === "auto" || overflowY === "scroll" || container.scrollHeight - container.clientHeight > 1; - if (canScroll) return container; + if (canScroll) {return container;} } return (document.scrollingElement ?? document.documentElement) as HTMLElement | null; }; @@ -34,22 +34,22 @@ export function scheduleChatScroll(host: ScrollHost, force = false) { host.chatScrollFrame = requestAnimationFrame(() => { host.chatScrollFrame = null; const target = pickScrollTarget(); - if (!target) return; + if (!target) {return;} const distanceFromBottom = target.scrollHeight - target.scrollTop - target.clientHeight; const shouldStick = force || host.chatUserNearBottom || distanceFromBottom < 200; - if (!shouldStick) return; - if (force) host.chatHasAutoScrolled = true; + if (!shouldStick) {return;} + if (force) {host.chatHasAutoScrolled = true;} target.scrollTop = target.scrollHeight; host.chatUserNearBottom = true; const retryDelay = force ? 150 : 120; host.chatScrollTimeout = window.setTimeout(() => { host.chatScrollTimeout = null; const latest = pickScrollTarget(); - if (!latest) return; + if (!latest) {return;} const latestDistanceFromBottom = latest.scrollHeight - latest.scrollTop - latest.clientHeight; const shouldStickRetry = force || host.chatUserNearBottom || latestDistanceFromBottom < 200; - if (!shouldStickRetry) return; + if (!shouldStickRetry) {return;} latest.scrollTop = latest.scrollHeight; host.chatUserNearBottom = true; }, retryDelay); @@ -58,16 +58,16 @@ export function scheduleChatScroll(host: ScrollHost, force = false) { } export function scheduleLogsScroll(host: ScrollHost, force = false) { - if (host.logsScrollFrame) cancelAnimationFrame(host.logsScrollFrame); + if (host.logsScrollFrame) {cancelAnimationFrame(host.logsScrollFrame);} void host.updateComplete.then(() => { host.logsScrollFrame = requestAnimationFrame(() => { host.logsScrollFrame = null; const container = host.querySelector(".log-stream") as HTMLElement | null; - if (!container) return; + if (!container) {return;} const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight; const shouldStick = force || distanceFromBottom < 80; - if (!shouldStick) return; + if (!shouldStick) {return;} container.scrollTop = container.scrollHeight; }); }); @@ -75,14 +75,14 @@ export function scheduleLogsScroll(host: ScrollHost, force = false) { export function handleChatScroll(host: ScrollHost, event: Event) { const container = event.currentTarget as HTMLElement | null; - if (!container) return; + if (!container) {return;} const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight; host.chatUserNearBottom = distanceFromBottom < 200; } export function handleLogsScroll(host: ScrollHost, event: Event) { const container = event.currentTarget as HTMLElement | null; - if (!container) return; + if (!container) {return;} const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight; host.logsAtBottom = distanceFromBottom < 80; } @@ -93,7 +93,7 @@ export function resetChatScroll(host: ScrollHost) { } export function exportLogs(lines: string[], label: string) { - if (lines.length === 0) return; + if (lines.length === 0) {return;} const blob = new Blob([`${lines.join("\n")}\n`], { type: "text/plain" }); const url = URL.createObjectURL(blob); const anchor = document.createElement("a"); @@ -105,9 +105,9 @@ export function exportLogs(lines: string[], label: string) { } export function observeTopbar(host: ScrollHost) { - if (typeof ResizeObserver === "undefined") return; + if (typeof ResizeObserver === "undefined") {return;} const topbar = host.querySelector(".topbar"); - if (!topbar) return; + if (!topbar) {return;} const update = () => { const { height } = topbar.getBoundingClientRect(); host.style.setProperty("--topbar-height", `${height}px`); diff --git a/ui/src/ui/app-settings.ts b/ui/src/ui/app-settings.ts index e821c6bfec..7f0d01071f 100644 --- a/ui/src/ui/app-settings.ts +++ b/ui/src/ui/app-settings.ts @@ -64,13 +64,13 @@ export function applySettings(host: SettingsHost, next: UiSettings) { export function setLastActiveSessionKey(host: SettingsHost, next: string) { const trimmed = next.trim(); - if (!trimmed) return; - if (host.settings.lastActiveSessionKey === trimmed) return; + if (!trimmed) {return;} + if (host.settings.lastActiveSessionKey === trimmed) {return;} applySettings(host, { ...host.settings, lastActiveSessionKey: trimmed }); } export function applySettingsFromUrl(host: SettingsHost) { - if (!window.location.search) return; + if (!window.location.search) {return;} const params = new URLSearchParams(window.location.search); const tokenRaw = params.get("token"); const passwordRaw = params.get("password"); @@ -117,20 +117,20 @@ export function applySettingsFromUrl(host: SettingsHost) { shouldCleanUrl = true; } - if (!shouldCleanUrl) return; + if (!shouldCleanUrl) {return;} const url = new URL(window.location.href); url.search = params.toString(); window.history.replaceState({}, "", url.toString()); } export function setTab(host: SettingsHost, next: Tab) { - if (host.tab !== next) host.tab = next; - if (next === "chat") host.chatHasAutoScrolled = false; - if (next === "logs") startLogsPolling(host as unknown as Parameters[0]); - else stopLogsPolling(host as unknown as Parameters[0]); + if (host.tab !== next) {host.tab = next;} + if (next === "chat") {host.chatHasAutoScrolled = false;} + if (next === "logs") {startLogsPolling(host as unknown as Parameters[0]);} + else {stopLogsPolling(host as unknown as Parameters[0]);} if (next === "debug") - startDebugPolling(host as unknown as Parameters[0]); - else stopDebugPolling(host as unknown as Parameters[0]); + {startDebugPolling(host as unknown as Parameters[0]);} + else {stopDebugPolling(host as unknown as Parameters[0]);} void refreshActiveTab(host); syncUrlWithTab(host, next, false); } @@ -150,12 +150,12 @@ export function setTheme(host: SettingsHost, next: ThemeMode, context?: ThemeTra } export async function refreshActiveTab(host: SettingsHost) { - if (host.tab === "overview") await loadOverview(host); - if (host.tab === "channels") await loadChannelsTab(host); - if (host.tab === "instances") await loadPresence(host as unknown as OpenClawApp); - if (host.tab === "sessions") await loadSessions(host as unknown as OpenClawApp); - if (host.tab === "cron") await loadCron(host); - if (host.tab === "skills") await loadSkills(host as unknown as OpenClawApp); + if (host.tab === "overview") {await loadOverview(host);} + if (host.tab === "channels") {await loadChannelsTab(host);} + if (host.tab === "instances") {await loadPresence(host as unknown as OpenClawApp);} + if (host.tab === "sessions") {await loadSessions(host as unknown as OpenClawApp);} + if (host.tab === "cron") {await loadCron(host);} + if (host.tab === "skills") {await loadSkills(host as unknown as OpenClawApp);} if (host.tab === "nodes") { await loadNodes(host as unknown as OpenClawApp); await loadDevices(host as unknown as OpenClawApp); @@ -185,7 +185,7 @@ export async function refreshActiveTab(host: SettingsHost) { } export function inferBasePath() { - if (typeof window === "undefined") return ""; + if (typeof window === "undefined") {return "";} const configured = window.__OPENCLAW_CONTROL_UI_BASE_PATH__; if (typeof configured === "string" && configured.trim()) { return normalizeBasePath(configured); @@ -200,17 +200,17 @@ export function syncThemeWithSettings(host: SettingsHost) { export function applyResolvedTheme(host: SettingsHost, resolved: ResolvedTheme) { host.themeResolved = resolved; - if (typeof document === "undefined") return; + if (typeof document === "undefined") {return;} const root = document.documentElement; root.dataset.theme = resolved; root.style.colorScheme = resolved; } export function attachThemeListener(host: SettingsHost) { - if (typeof window === "undefined" || typeof window.matchMedia !== "function") return; + if (typeof window === "undefined" || typeof window.matchMedia !== "function") {return;} host.themeMedia = window.matchMedia("(prefers-color-scheme: dark)"); host.themeMediaHandler = (event) => { - if (host.theme !== "system") return; + if (host.theme !== "system") {return;} applyResolvedTheme(host, event.matches ? "dark" : "light"); }; if (typeof host.themeMedia.addEventListener === "function") { @@ -224,7 +224,7 @@ export function attachThemeListener(host: SettingsHost) { } export function detachThemeListener(host: SettingsHost) { - if (!host.themeMedia || !host.themeMediaHandler) return; + if (!host.themeMedia || !host.themeMediaHandler) {return;} if (typeof host.themeMedia.removeEventListener === "function") { host.themeMedia.removeEventListener("change", host.themeMediaHandler); return; @@ -238,16 +238,16 @@ export function detachThemeListener(host: SettingsHost) { } export function syncTabWithLocation(host: SettingsHost, replace: boolean) { - if (typeof window === "undefined") return; + if (typeof window === "undefined") {return;} const resolved = tabFromPath(window.location.pathname, host.basePath) ?? "chat"; setTabFromRoute(host, resolved); syncUrlWithTab(host, resolved, replace); } export function onPopState(host: SettingsHost) { - if (typeof window === "undefined") return; + if (typeof window === "undefined") {return;} const resolved = tabFromPath(window.location.pathname, host.basePath); - if (!resolved) return; + if (!resolved) {return;} const url = new URL(window.location.href); const session = url.searchParams.get("session")?.trim(); @@ -264,18 +264,18 @@ export function onPopState(host: SettingsHost) { } export function setTabFromRoute(host: SettingsHost, next: Tab) { - if (host.tab !== next) host.tab = next; - if (next === "chat") host.chatHasAutoScrolled = false; - if (next === "logs") startLogsPolling(host as unknown as Parameters[0]); - else stopLogsPolling(host as unknown as Parameters[0]); + if (host.tab !== next) {host.tab = next;} + if (next === "chat") {host.chatHasAutoScrolled = false;} + if (next === "logs") {startLogsPolling(host as unknown as Parameters[0]);} + else {stopLogsPolling(host as unknown as Parameters[0]);} if (next === "debug") - startDebugPolling(host as unknown as Parameters[0]); - else stopDebugPolling(host as unknown as Parameters[0]); - if (host.connected) void refreshActiveTab(host); + {startDebugPolling(host as unknown as Parameters[0]);} + else {stopDebugPolling(host as unknown as Parameters[0]);} + if (host.connected) {void refreshActiveTab(host);} } export function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) { - if (typeof window === "undefined") return; + if (typeof window === "undefined") {return;} const targetPath = normalizePath(pathForTab(tab, host.basePath)); const currentPath = normalizePath(window.location.pathname); const url = new URL(window.location.href); @@ -298,11 +298,11 @@ export function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) { } export function syncUrlWithSessionKey(host: SettingsHost, sessionKey: string, replace: boolean) { - if (typeof window === "undefined") return; + if (typeof window === "undefined") {return;} const url = new URL(window.location.href); url.searchParams.set("session", sessionKey); - if (replace) window.history.replaceState({}, "", url.toString()); - else window.history.pushState({}, "", url.toString()); + if (replace) {window.history.replaceState({}, "", url.toString());} + else {window.history.pushState({}, "", url.toString());} } export async function loadOverview(host: SettingsHost) { diff --git a/ui/src/ui/app-tool-stream.ts b/ui/src/ui/app-tool-stream.ts index f438149981..7f47a30dbc 100644 --- a/ui/src/ui/app-tool-stream.ts +++ b/ui/src/ui/app-tool-stream.ts @@ -35,25 +35,25 @@ type ToolStreamHost = { }; function extractToolOutputText(value: unknown): string | null { - if (!value || typeof value !== "object") return null; + if (!value || typeof value !== "object") {return null;} const record = value as Record; - if (typeof record.text === "string") return record.text; + if (typeof record.text === "string") {return record.text;} const content = record.content; - if (!Array.isArray(content)) return null; + if (!Array.isArray(content)) {return null;} const parts = content .map((item) => { - if (!item || typeof item !== "object") return null; + if (!item || typeof item !== "object") {return null;} const entry = item as Record; - if (entry.type === "text" && typeof entry.text === "string") return entry.text; + if (entry.type === "text" && typeof entry.text === "string") {return entry.text;} return null; }) .filter((part): part is string => Boolean(part)); - if (parts.length === 0) return null; + if (parts.length === 0) {return null;} return parts.join("\n"); } function formatToolOutput(value: unknown): string | null { - if (value === null || value === undefined) return null; + if (value === null || value === undefined) {return null;} if (typeof value === "number" || typeof value === "boolean") { return String(value); } @@ -71,7 +71,7 @@ function formatToolOutput(value: unknown): string | null { } } const truncated = truncateText(text, TOOL_OUTPUT_CHAR_LIMIT); - if (!truncated.truncated) return truncated.text; + if (!truncated.truncated) {return truncated.text;} return `${truncated.text}\n\n… truncated (${truncated.total} chars, showing first ${truncated.text.length}).`; } @@ -99,10 +99,10 @@ function buildToolStreamMessage(entry: ToolStreamEntry): Record } function trimToolStream(host: ToolStreamHost) { - if (host.toolStreamOrder.length <= TOOL_STREAM_LIMIT) return; + if (host.toolStreamOrder.length <= TOOL_STREAM_LIMIT) {return;} const overflow = host.toolStreamOrder.length - TOOL_STREAM_LIMIT; const removed = host.toolStreamOrder.splice(0, overflow); - for (const id of removed) host.toolStreamById.delete(id); + for (const id of removed) {host.toolStreamById.delete(id);} } function syncToolStreamMessages(host: ToolStreamHost) { @@ -124,7 +124,7 @@ export function scheduleToolStreamSync(host: ToolStreamHost, force = false) { flushToolStreamSync(host); return; } - if (host.toolStreamSyncTimer != null) return; + if (host.toolStreamSyncTimer != null) {return;} host.toolStreamSyncTimer = window.setTimeout( () => flushToolStreamSync(host), TOOL_STREAM_THROTTLE_MS, @@ -182,7 +182,7 @@ export function handleCompactionEvent(host: CompactionHost, payload: AgentEventP } export function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPayload) { - if (!payload) return; + if (!payload) {return;} // Handle compaction events if (payload.stream === "compaction") { @@ -190,17 +190,17 @@ export function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPaylo return; } - if (payload.stream !== "tool") return; + if (payload.stream !== "tool") {return;} const sessionKey = typeof payload.sessionKey === "string" ? payload.sessionKey : undefined; - if (sessionKey && sessionKey !== host.sessionKey) return; + if (sessionKey && sessionKey !== host.sessionKey) {return;} // Fallback: only accept session-less events for the active run. - if (!sessionKey && host.chatRunId && payload.runId !== host.chatRunId) return; - if (host.chatRunId && payload.runId !== host.chatRunId) return; - if (!host.chatRunId) return; + if (!sessionKey && host.chatRunId && payload.runId !== host.chatRunId) {return;} + if (host.chatRunId && payload.runId !== host.chatRunId) {return;} + if (!host.chatRunId) {return;} const data = payload.data ?? {}; const toolCallId = typeof data.toolCallId === "string" ? data.toolCallId : ""; - if (!toolCallId) return; + if (!toolCallId) {return;} const name = typeof data.name === "string" ? data.name : "tool"; const phase = typeof data.phase === "string" ? data.phase : ""; const args = phase === "start" ? data.args : undefined; @@ -229,8 +229,8 @@ export function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPaylo host.toolStreamOrder.push(toolCallId); } else { entry.name = name; - if (args !== undefined) entry.args = args; - if (output !== undefined) entry.output = output; + if (args !== undefined) {entry.args = args;} + if (output !== undefined) {entry.output = output;} entry.updatedAt = now; } diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index 54ba72498f..3052dab03e 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -84,10 +84,10 @@ declare global { const injectedAssistantIdentity = resolveInjectedAssistantIdentity(); function resolveOnboardingMode(): boolean { - if (!window.location.search) return false; + if (!window.location.search) {return false;} const params = new URLSearchParams(window.location.search); const raw = params.get("onboarding"); - if (!raw) return false; + if (!raw) {return false;} const normalized = raw.trim().toLowerCase(); return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on"; } @@ -406,7 +406,7 @@ export class OpenClawApp extends LitElement { async handleExecApprovalDecision(decision: "allow-once" | "allow-always" | "deny") { const active = this.execApprovalQueue[0]; - if (!active || !this.client || this.execApprovalBusy) return; + if (!active || !this.client || this.execApprovalBusy) {return;} this.execApprovalBusy = true; this.execApprovalError = null; try { @@ -424,7 +424,7 @@ export class OpenClawApp extends LitElement { handleGatewayUrlConfirm() { const nextGatewayUrl = this.pendingGatewayUrl; - if (!nextGatewayUrl) return; + if (!nextGatewayUrl) {return;} this.pendingGatewayUrl = null; applySettingsInternal(this as unknown as Parameters[0], { ...this.settings, @@ -455,7 +455,7 @@ export class OpenClawApp extends LitElement { window.clearTimeout(this.sidebarCloseTimer); } this.sidebarCloseTimer = window.setTimeout(() => { - if (this.sidebarOpen) return; + if (this.sidebarOpen) {return;} this.sidebarContent = null; this.sidebarError = null; this.sidebarCloseTimer = null; diff --git a/ui/src/ui/assistant-identity.ts b/ui/src/ui/assistant-identity.ts index 6159cc36e2..68c65db1be 100644 --- a/ui/src/ui/assistant-identity.ts +++ b/ui/src/ui/assistant-identity.ts @@ -18,10 +18,10 @@ declare global { } function coerceIdentityValue(value: string | undefined, maxLength: number): string | undefined { - if (typeof value !== "string") return undefined; + if (typeof value !== "string") {return undefined;} const trimmed = value.trim(); - if (!trimmed) return undefined; - if (trimmed.length <= maxLength) return trimmed; + if (!trimmed) {return undefined;} + if (trimmed.length <= maxLength) {return trimmed;} return trimmed.slice(0, maxLength); } diff --git a/ui/src/ui/chat/copy-as-markdown.ts b/ui/src/ui/chat/copy-as-markdown.ts index 3d11eb32e7..49fc1763b1 100644 --- a/ui/src/ui/chat/copy-as-markdown.ts +++ b/ui/src/ui/chat/copy-as-markdown.ts @@ -13,7 +13,7 @@ type CopyButtonOptions = { }; async function copyTextToClipboard(text: string): Promise { - if (!text) return false; + if (!text) {return false;} try { await navigator.clipboard.writeText(text); @@ -40,14 +40,14 @@ function createCopyButton(options: CopyButtonOptions): TemplateResult { const btn = e.currentTarget as HTMLButtonElement | null; const iconContainer = btn?.querySelector(".chat-copy-btn__icon") as HTMLElement | null; - if (!btn || btn.dataset.copying === "1") return; + if (!btn || btn.dataset.copying === "1") {return;} btn.dataset.copying = "1"; btn.setAttribute("aria-busy", "true"); btn.disabled = true; const copied = await copyTextToClipboard(options.text()); - if (!btn.isConnected) return; + if (!btn.isConnected) {return;} delete btn.dataset.copying; btn.removeAttribute("aria-busy"); @@ -58,7 +58,7 @@ function createCopyButton(options: CopyButtonOptions): TemplateResult { setButtonLabel(btn, ERROR_LABEL); window.setTimeout(() => { - if (!btn.isConnected) return; + if (!btn.isConnected) {return;} delete btn.dataset.error; setButtonLabel(btn, idleLabel); }, ERROR_FOR_MS); @@ -69,7 +69,7 @@ function createCopyButton(options: CopyButtonOptions): TemplateResult { setButtonLabel(btn, COPIED_LABEL); window.setTimeout(() => { - if (!btn.isConnected) return; + if (!btn.isConnected) {return;} delete btn.dataset.copied; setButtonLabel(btn, idleLabel); }, COPIED_FOR_MS); diff --git a/ui/src/ui/chat/grouped-render.ts b/ui/src/ui/chat/grouped-render.ts index 97ad421f69..e7cb006f69 100644 --- a/ui/src/ui/chat/grouped-render.ts +++ b/ui/src/ui/chat/grouped-render.ts @@ -24,14 +24,14 @@ function extractImages(message: unknown): ImageBlock[] { if (Array.isArray(content)) { for (const block of content) { - if (typeof block !== "object" || block === null) continue; + if (typeof block !== "object" || block === null) {continue;} const b = block as Record; if (b.type === "image") { // Handle source object format (from sendChatMessage) const source = b.source as Record | undefined; if (source?.type === "base64" && typeof source.data === "string") { - const data = source.data as string; + const data = source.data; const mediaType = (source.media_type as string) || "image/png"; // If data is already a data URL, use it directly const url = data.startsWith("data:") ? data : `data:${mediaType};base64,${data}`; @@ -188,12 +188,12 @@ function renderAvatar(role: string, assistant?: Pick @@ -251,7 +251,7 @@ function renderGroupedMessage( return html`${toolCards.map((card) => renderToolCardSidebar(card, onOpenSidebar))}`; } - if (!markdown && !hasToolCards && !hasImages) return nothing; + if (!markdown && !hasToolCards && !hasImages) {return nothing;} return html`
diff --git a/ui/src/ui/chat/message-extract.ts b/ui/src/ui/chat/message-extract.ts index 6a63a073fd..418692a6b7 100644 --- a/ui/src/ui/chat/message-extract.ts +++ b/ui/src/ui/chat/message-extract.ts @@ -20,16 +20,16 @@ const textCache = new WeakMap(); const thinkingCache = new WeakMap(); function looksLikeEnvelopeHeader(header: string): boolean { - if (/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z\b/.test(header)) return true; - if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}\b/.test(header)) return true; + if (/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z\b/.test(header)) {return true;} + if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}\b/.test(header)) {return true;} return ENVELOPE_CHANNELS.some((label) => header.startsWith(`${label} `)); } export function stripEnvelope(text: string): string { const match = text.match(ENVELOPE_PREFIX); - if (!match) return text; + if (!match) {return text;} const header = match[1] ?? ""; - if (!looksLikeEnvelopeHeader(header)) return text; + if (!looksLikeEnvelopeHeader(header)) {return text;} return text.slice(match[0].length); } @@ -45,7 +45,7 @@ export function extractText(message: unknown): string | null { const parts = content .map((p) => { const item = p as Record; - if (item.type === "text" && typeof item.text === "string") return item.text; + if (item.type === "text" && typeof item.text === "string") {return item.text;} return null; }) .filter((v): v is string => typeof v === "string"); @@ -63,9 +63,9 @@ export function extractText(message: unknown): string | null { } export function extractTextCached(message: unknown): string | null { - if (!message || typeof message !== "object") return extractText(message); - const obj = message as object; - if (textCache.has(obj)) return textCache.get(obj) ?? null; + if (!message || typeof message !== "object") {return extractText(message);} + const obj = message; + if (textCache.has(obj)) {return textCache.get(obj) ?? null;} const value = extractText(message); textCache.set(obj, value); return value; @@ -80,15 +80,15 @@ export function extractThinking(message: unknown): string | null { const item = p as Record; if (item.type === "thinking" && typeof item.thinking === "string") { const cleaned = item.thinking.trim(); - if (cleaned) parts.push(cleaned); + if (cleaned) {parts.push(cleaned);} } } } - if (parts.length > 0) return parts.join("\n"); + if (parts.length > 0) {return parts.join("\n");} // Back-compat: older logs may still have tags inside text blocks. const rawText = extractRawText(message); - if (!rawText) return null; + if (!rawText) {return null;} const matches = [ ...rawText.matchAll(/<\s*think(?:ing)?\s*>([\s\S]*?)<\s*\/\s*think(?:ing)?\s*>/gi), ]; @@ -97,9 +97,9 @@ export function extractThinking(message: unknown): string | null { } export function extractThinkingCached(message: unknown): string | null { - if (!message || typeof message !== "object") return extractThinking(message); - const obj = message as object; - if (thinkingCache.has(obj)) return thinkingCache.get(obj) ?? null; + if (!message || typeof message !== "object") {return extractThinking(message);} + const obj = message; + if (thinkingCache.has(obj)) {return thinkingCache.get(obj) ?? null;} const value = extractThinking(message); thinkingCache.set(obj, value); return value; @@ -108,24 +108,24 @@ export function extractThinkingCached(message: unknown): string | null { export function extractRawText(message: unknown): string | null { const m = message as Record; const content = m.content; - if (typeof content === "string") return content; + if (typeof content === "string") {return content;} if (Array.isArray(content)) { const parts = content .map((p) => { const item = p as Record; - if (item.type === "text" && typeof item.text === "string") return item.text; + if (item.type === "text" && typeof item.text === "string") {return item.text;} return null; }) .filter((v): v is string => typeof v === "string"); - if (parts.length > 0) return parts.join("\n"); + if (parts.length > 0) {return parts.join("\n");} } - if (typeof m.text === "string") return m.text; + if (typeof m.text === "string") {return m.text;} return null; } export function formatReasoningMarkdown(text: string): string { const trimmed = text.trim(); - if (!trimmed) return ""; + if (!trimmed) {return "";} const lines = trimmed .split(/\r?\n/) .map((line) => line.trim()) diff --git a/ui/src/ui/chat/message-normalizer.ts b/ui/src/ui/chat/message-normalizer.ts index 388939b9f9..d585a484ec 100644 --- a/ui/src/ui/chat/message-normalizer.ts +++ b/ui/src/ui/chat/message-normalizer.ts @@ -26,8 +26,8 @@ export function normalizeMessage(message: unknown): NormalizedMessage { }); const hasToolName = - typeof (m as Record).toolName === "string" || - typeof (m as Record).tool_name === "string"; + typeof (m).toolName === "string" || + typeof (m).tool_name === "string"; if (hasToolId || hasToolContent || hasToolName) { role = "toolResult"; @@ -61,9 +61,9 @@ export function normalizeMessage(message: unknown): NormalizedMessage { export function normalizeRoleForGrouping(role: string): string { const lower = role.toLowerCase(); // Preserve original casing when it's already a core role. - if (role === "user" || role === "User") return role; - if (role === "assistant") return "assistant"; - if (role === "system") return "system"; + if (role === "user" || role === "User") {return role;} + if (role === "assistant") {return "assistant";} + if (role === "system") {return "system";} // Keep tool-related roles distinct so the UI can style/toggle them. if ( lower === "toolresult" || diff --git a/ui/src/ui/chat/tool-cards.ts b/ui/src/ui/chat/tool-cards.ts index 19e8cf82eb..dbe2231323 100644 --- a/ui/src/ui/chat/tool-cards.ts +++ b/ui/src/ui/chat/tool-cards.ts @@ -28,7 +28,7 @@ export function extractToolCards(message: unknown): ToolCard[] { for (const item of content) { const kind = String(item.type ?? "").toLowerCase(); - if (kind !== "toolresult" && kind !== "tool_result") continue; + if (kind !== "toolresult" && kind !== "tool_result") {continue;} const text = extractToolText(item); const name = typeof item.name === "string" ? item.name : "tool"; cards.push({ kind: "result", name, text }); @@ -79,7 +79,7 @@ export function renderToolCardSidebar(card: ToolCard, onOpenSidebar?: (content: @keydown=${ canClick ? (e: KeyboardEvent) => { - if (e.key !== "Enter" && e.key !== " ") return; + if (e.key !== "Enter" && e.key !== " ") {return;} e.preventDefault(); handleClick?.(); } @@ -117,15 +117,15 @@ export function renderToolCardSidebar(card: ToolCard, onOpenSidebar?: (content: } function normalizeContent(content: unknown): Array> { - if (!Array.isArray(content)) return []; + if (!Array.isArray(content)) {return [];} return content.filter(Boolean) as Array>; } function coerceArgs(value: unknown): unknown { - if (typeof value !== "string") return value; + if (typeof value !== "string") {return value;} const trimmed = value.trim(); - if (!trimmed) return value; - if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return value; + if (!trimmed) {return value;} + if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {return value;} try { return JSON.parse(trimmed); } catch { @@ -134,7 +134,7 @@ function coerceArgs(value: unknown): unknown { } function extractToolText(item: Record): string | undefined { - if (typeof item.text === "string") return item.text; - if (typeof item.content === "string") return item.content; + if (typeof item.text === "string") {return item.text;} + if (typeof item.content === "string") {return item.content;} return undefined; } diff --git a/ui/src/ui/components/resizable-divider.ts b/ui/src/ui/components/resizable-divider.ts index 98aba4bc6d..d44cf79b7f 100644 --- a/ui/src/ui/components/resizable-divider.ts +++ b/ui/src/ui/components/resizable-divider.ts @@ -74,10 +74,10 @@ export class ResizableDivider extends LitElement { }; private handleMouseMove = (e: MouseEvent) => { - if (!this.isDragging) return; + if (!this.isDragging) {return;} const container = this.parentElement; - if (!container) return; + if (!container) {return;} const containerWidth = container.getBoundingClientRect().width; const deltaX = e.clientX - this.startX; diff --git a/ui/src/ui/config-form.browser.test.ts b/ui/src/ui/config-form.browser.test.ts index 5f64ee7f20..168a5dc644 100644 --- a/ui/src/ui/config-form.browser.test.ts +++ b/ui/src/ui/config-form.browser.test.ts @@ -51,9 +51,9 @@ describe("config form renderer", () => { container, ); - const tokenInput = container.querySelector("input[type='password']") as HTMLInputElement | null; + const tokenInput = container.querySelector("input[type='password']"); expect(tokenInput).not.toBeNull(); - if (!tokenInput) return; + if (!tokenInput) {return;} tokenInput.value = "abc123"; tokenInput.dispatchEvent(new Event("input", { bubbles: true })); expect(onPatch).toHaveBeenCalledWith(["gateway", "auth", "token"], "abc123"); @@ -65,9 +65,9 @@ describe("config form renderer", () => { tokenButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(onPatch).toHaveBeenCalledWith(["mode"], "token"); - const checkbox = container.querySelector("input[type='checkbox']") as HTMLInputElement | null; + const checkbox = container.querySelector("input[type='checkbox']"); expect(checkbox).not.toBeNull(); - if (!checkbox) return; + if (!checkbox) {return;} checkbox.checked = true; checkbox.dispatchEvent(new Event("change", { bubbles: true })); expect(onPatch).toHaveBeenCalledWith(["enabled"], true); @@ -88,14 +88,14 @@ describe("config form renderer", () => { container, ); - const addButton = container.querySelector(".cfg-array__add") as HTMLButtonElement | null; + const addButton = container.querySelector(".cfg-array__add"); expect(addButton).not.toBeUndefined(); addButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(onPatch).toHaveBeenCalledWith(["allowFrom"], ["+1", ""]); const removeButton = container.querySelector( ".cfg-array__item-remove", - ) as HTMLButtonElement | null; + ); expect(removeButton).not.toBeUndefined(); removeButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(onPatch).toHaveBeenCalledWith(["allowFrom"], []); @@ -152,7 +152,7 @@ describe("config form renderer", () => { const removeButton = container.querySelector( ".cfg-map__item-remove", - ) as HTMLButtonElement | null; + ); expect(removeButton).not.toBeUndefined(); removeButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(onPatch).toHaveBeenCalledWith(["slack"], {}); diff --git a/ui/src/ui/controllers/agents.ts b/ui/src/ui/controllers/agents.ts index deb79ef6b5..93287c5d26 100644 --- a/ui/src/ui/controllers/agents.ts +++ b/ui/src/ui/controllers/agents.ts @@ -10,13 +10,13 @@ export type AgentsState = { }; export async function loadAgents(state: AgentsState) { - if (!state.client || !state.connected) return; - if (state.agentsLoading) return; + if (!state.client || !state.connected) {return;} + if (state.agentsLoading) {return;} state.agentsLoading = true; state.agentsError = null; try { - const res = (await state.client.request("agents.list", {})) as AgentsListResult | undefined; - if (res) state.agentsList = res; + const res = (await state.client.request("agents.list", {})); + if (res) {state.agentsList = res;} } catch (err) { state.agentsError = String(err); } finally { diff --git a/ui/src/ui/controllers/assistant-identity.ts b/ui/src/ui/controllers/assistant-identity.ts index 98eb090874..a6f12c97de 100644 --- a/ui/src/ui/controllers/assistant-identity.ts +++ b/ui/src/ui/controllers/assistant-identity.ts @@ -14,14 +14,12 @@ export async function loadAssistantIdentity( state: AssistantIdentityState, opts?: { sessionKey?: string }, ) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} const sessionKey = opts?.sessionKey?.trim() || state.sessionKey.trim(); const params = sessionKey ? { sessionKey } : {}; try { - const res = (await state.client.request("agent.identity.get", params)) as - | Partial - | undefined; - if (!res) return; + const res = (await state.client.request("agent.identity.get", params)); + if (!res) {return;} const normalized = normalizeAssistantIdentity(res); state.assistantName = normalized.name; state.assistantAvatar = normalized.avatar; diff --git a/ui/src/ui/controllers/channels.ts b/ui/src/ui/controllers/channels.ts index 7e9e6ee1d9..765e289151 100644 --- a/ui/src/ui/controllers/channels.ts +++ b/ui/src/ui/controllers/channels.ts @@ -4,15 +4,15 @@ import type { ChannelsState } from "./channels.types"; export type { ChannelsState }; export async function loadChannels(state: ChannelsState, probe: boolean) { - if (!state.client || !state.connected) return; - if (state.channelsLoading) return; + if (!state.client || !state.connected) {return;} + if (state.channelsLoading) {return;} state.channelsLoading = true; state.channelsError = null; try { const res = (await state.client.request("channels.status", { probe, timeoutMs: 8000, - })) as ChannelsStatusSnapshot; + })); state.channelsSnapshot = res; state.channelsLastSuccess = Date.now(); } catch (err) { @@ -23,13 +23,13 @@ export async function loadChannels(state: ChannelsState, probe: boolean) { } export async function startWhatsAppLogin(state: ChannelsState, force: boolean) { - if (!state.client || !state.connected || state.whatsappBusy) return; + if (!state.client || !state.connected || state.whatsappBusy) {return;} state.whatsappBusy = true; try { const res = (await state.client.request("web.login.start", { force, timeoutMs: 30000, - })) as { message?: string; qrDataUrl?: string }; + })); state.whatsappLoginMessage = res.message ?? null; state.whatsappLoginQrDataUrl = res.qrDataUrl ?? null; state.whatsappLoginConnected = null; @@ -43,15 +43,15 @@ export async function startWhatsAppLogin(state: ChannelsState, force: boolean) { } export async function waitWhatsAppLogin(state: ChannelsState) { - if (!state.client || !state.connected || state.whatsappBusy) return; + if (!state.client || !state.connected || state.whatsappBusy) {return;} state.whatsappBusy = true; try { const res = (await state.client.request("web.login.wait", { timeoutMs: 120000, - })) as { connected?: boolean; message?: string }; + })); state.whatsappLoginMessage = res.message ?? null; state.whatsappLoginConnected = res.connected ?? null; - if (res.connected) state.whatsappLoginQrDataUrl = null; + if (res.connected) {state.whatsappLoginQrDataUrl = null;} } catch (err) { state.whatsappLoginMessage = String(err); state.whatsappLoginConnected = null; @@ -61,7 +61,7 @@ export async function waitWhatsAppLogin(state: ChannelsState) { } export async function logoutWhatsApp(state: ChannelsState) { - if (!state.client || !state.connected || state.whatsappBusy) return; + if (!state.client || !state.connected || state.whatsappBusy) {return;} state.whatsappBusy = true; try { await state.client.request("channels.logout", { channel: "whatsapp" }); diff --git a/ui/src/ui/controllers/chat.ts b/ui/src/ui/controllers/chat.ts index 582105114e..63d908ac0b 100644 --- a/ui/src/ui/controllers/chat.ts +++ b/ui/src/ui/controllers/chat.ts @@ -28,14 +28,14 @@ export type ChatEventPayload = { }; export async function loadChatHistory(state: ChatState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.chatLoading = true; state.lastError = null; try { const res = (await state.client.request("chat.history", { sessionKey: state.sessionKey, limit: 200, - })) as { messages?: unknown[]; thinkingLevel?: string | null }; + })); state.chatMessages = Array.isArray(res.messages) ? res.messages : []; state.chatThinkingLevel = res.thinkingLevel ?? null; } catch (err) { @@ -47,7 +47,7 @@ export async function loadChatHistory(state: ChatState) { function dataUrlToBase64(dataUrl: string): { content: string; mimeType: string } | null { const match = /^data:([^;]+);base64,(.+)$/.exec(dataUrl); - if (!match) return null; + if (!match) {return null;} return { mimeType: match[1], content: match[2] }; } @@ -56,10 +56,10 @@ export async function sendChatMessage( message: string, attachments?: ChatAttachment[], ): Promise { - if (!state.client || !state.connected) return null; + if (!state.client || !state.connected) {return null;} const msg = message.trim(); const hasAttachments = attachments && attachments.length > 0; - if (!msg && !hasAttachments) return null; + if (!msg && !hasAttachments) {return null;} const now = Date.now(); @@ -99,7 +99,7 @@ export async function sendChatMessage( ? attachments .map((att) => { const parsed = dataUrlToBase64(att.dataUrl); - if (!parsed) return null; + if (!parsed) {return null;} return { type: "image", mimeType: parsed.mimeType, @@ -139,7 +139,7 @@ export async function sendChatMessage( } export async function abortChatRun(state: ChatState): Promise { - if (!state.client || !state.connected) return false; + if (!state.client || !state.connected) {return false;} const runId = state.chatRunId; try { await state.client.request( @@ -154,13 +154,13 @@ export async function abortChatRun(state: ChatState): Promise { } export function handleChatEvent(state: ChatState, payload?: ChatEventPayload) { - if (!payload) return null; - if (payload.sessionKey !== state.sessionKey) return null; + if (!payload) {return null;} + if (payload.sessionKey !== state.sessionKey) {return null;} // Final from another run (e.g. sub-agent announce): refresh history to show new message. // See https://github.com/openclaw/openclaw/issues/1909 if (payload.runId && state.chatRunId && payload.runId !== state.chatRunId) { - if (payload.state === "final") return "final"; + if (payload.state === "final") {return "final";} return null; } diff --git a/ui/src/ui/controllers/config.ts b/ui/src/ui/controllers/config.ts index 84b9ae5158..cb4d6b5223 100644 --- a/ui/src/ui/controllers/config.ts +++ b/ui/src/ui/controllers/config.ts @@ -35,11 +35,11 @@ export type ConfigState = { }; export async function loadConfig(state: ConfigState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.configLoading = true; state.lastError = null; try { - const res = (await state.client.request("config.get", {})) as ConfigSnapshot; + const res = (await state.client.request("config.get", {})); applyConfigSnapshot(state, res); } catch (err) { state.lastError = String(err); @@ -49,11 +49,11 @@ export async function loadConfig(state: ConfigState) { } export async function loadConfigSchema(state: ConfigState) { - if (!state.client || !state.connected) return; - if (state.configSchemaLoading) return; + if (!state.client || !state.connected) {return;} + if (state.configSchemaLoading) {return;} state.configSchemaLoading = true; try { - const res = (await state.client.request("config.schema", {})) as ConfigSchemaResponse; + const res = (await state.client.request("config.schema", {})); applyConfigSchema(state, res); } catch (err) { state.lastError = String(err); @@ -74,7 +74,7 @@ export function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot typeof snapshot.raw === "string" ? snapshot.raw : snapshot.config && typeof snapshot.config === "object" - ? serializeConfigForm(snapshot.config as Record) + ? serializeConfigForm(snapshot.config) : state.configRaw; if (!state.configFormDirty || state.configFormMode === "raw") { state.configRaw = rawFromSnapshot; @@ -94,7 +94,7 @@ export function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot } export async function saveConfig(state: ConfigState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.configSaving = true; state.lastError = null; try { @@ -118,7 +118,7 @@ export async function saveConfig(state: ConfigState) { } export async function applyConfig(state: ConfigState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.configApplying = true; state.lastError = null; try { @@ -146,7 +146,7 @@ export async function applyConfig(state: ConfigState) { } export async function runUpdate(state: ConfigState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.updateRunning = true; state.lastError = null; try { diff --git a/ui/src/ui/controllers/config/form-utils.ts b/ui/src/ui/controllers/config/form-utils.ts index 1edd97b9c6..6a7d95bf2f 100644 --- a/ui/src/ui/controllers/config/form-utils.ts +++ b/ui/src/ui/controllers/config/form-utils.ts @@ -14,19 +14,19 @@ export function setPathValue( path: Array, value: unknown, ) { - if (path.length === 0) return; + if (path.length === 0) {return;} let current: Record | unknown[] = obj; for (let i = 0; i < path.length - 1; i += 1) { const key = path[i]; const nextKey = path[i + 1]; if (typeof key === "number") { - if (!Array.isArray(current)) return; + if (!Array.isArray(current)) {return;} if (current[key] == null) { current[key] = typeof nextKey === "number" ? [] : ({} as Record); } current = current[key] as Record | unknown[]; } else { - if (typeof current !== "object" || current == null) return; + if (typeof current !== "object" || current == null) {return;} const record = current as Record; if (record[key] == null) { record[key] = typeof nextKey === "number" ? [] : ({} as Record); @@ -36,7 +36,7 @@ export function setPathValue( } const lastKey = path[path.length - 1]; if (typeof lastKey === "number") { - if (Array.isArray(current)) current[lastKey] = value; + if (Array.isArray(current)) {current[lastKey] = value;} return; } if (typeof current === "object" && current != null) { @@ -48,22 +48,22 @@ export function removePathValue( obj: Record | unknown[], path: Array, ) { - if (path.length === 0) return; + if (path.length === 0) {return;} let current: Record | unknown[] = obj; for (let i = 0; i < path.length - 1; i += 1) { const key = path[i]; if (typeof key === "number") { - if (!Array.isArray(current)) return; + if (!Array.isArray(current)) {return;} current = current[key] as Record | unknown[]; } else { - if (typeof current !== "object" || current == null) return; + if (typeof current !== "object" || current == null) {return;} current = (current as Record)[key] as Record | unknown[]; } - if (current == null) return; + if (current == null) {return;} } const lastKey = path[path.length - 1]; if (typeof lastKey === "number") { - if (Array.isArray(current)) current.splice(lastKey, 1); + if (Array.isArray(current)) {current.splice(lastKey, 1);} return; } if (typeof current === "object" && current != null) { diff --git a/ui/src/ui/controllers/cron.ts b/ui/src/ui/controllers/cron.ts index ac128cab8a..d73f638c42 100644 --- a/ui/src/ui/controllers/cron.ts +++ b/ui/src/ui/controllers/cron.ts @@ -17,9 +17,9 @@ export type CronState = { }; export async function loadCronStatus(state: CronState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} try { - const res = (await state.client.request("cron.status", {})) as CronStatus; + const res = (await state.client.request("cron.status", {})); state.cronStatus = res; } catch (err) { state.cronError = String(err); @@ -27,14 +27,14 @@ export async function loadCronStatus(state: CronState) { } export async function loadCronJobs(state: CronState) { - if (!state.client || !state.connected) return; - if (state.cronLoading) return; + if (!state.client || !state.connected) {return;} + if (state.cronLoading) {return;} state.cronLoading = true; state.cronError = null; try { const res = (await state.client.request("cron.list", { includeDisabled: true, - })) as { jobs?: CronJob[] }; + })); state.cronJobs = Array.isArray(res.jobs) ? res.jobs : []; } catch (err) { state.cronError = String(err); @@ -46,29 +46,29 @@ export async function loadCronJobs(state: CronState) { export function buildCronSchedule(form: CronFormState) { if (form.scheduleKind === "at") { const ms = Date.parse(form.scheduleAt); - if (!Number.isFinite(ms)) throw new Error("Invalid run time."); + if (!Number.isFinite(ms)) {throw new Error("Invalid run time.");} return { kind: "at" as const, atMs: ms }; } if (form.scheduleKind === "every") { const amount = toNumber(form.everyAmount, 0); - if (amount <= 0) throw new Error("Invalid interval amount."); + if (amount <= 0) {throw new Error("Invalid interval amount.");} const unit = form.everyUnit; const mult = unit === "minutes" ? 60_000 : unit === "hours" ? 3_600_000 : 86_400_000; return { kind: "every" as const, everyMs: amount * mult }; } const expr = form.cronExpr.trim(); - if (!expr) throw new Error("Cron expression required."); + if (!expr) {throw new Error("Cron expression required.");} return { kind: "cron" as const, expr, tz: form.cronTz.trim() || undefined }; } export function buildCronPayload(form: CronFormState) { if (form.payloadKind === "systemEvent") { const text = form.payloadText.trim(); - if (!text) throw new Error("System event text required."); + if (!text) {throw new Error("System event text required.");} return { kind: "systemEvent" as const, text }; } const message = form.payloadText.trim(); - if (!message) throw new Error("Agent message required."); + if (!message) {throw new Error("Agent message required.");} const payload: { kind: "agentTurn"; message: string; @@ -77,16 +77,16 @@ export function buildCronPayload(form: CronFormState) { to?: string; timeoutSeconds?: number; } = { kind: "agentTurn", message }; - if (form.deliver) payload.deliver = true; - if (form.channel) payload.channel = form.channel; - if (form.to.trim()) payload.to = form.to.trim(); + if (form.deliver) {payload.deliver = true;} + if (form.channel) {payload.channel = form.channel;} + if (form.to.trim()) {payload.to = form.to.trim();} const timeoutSeconds = toNumber(form.timeoutSeconds, 0); - if (timeoutSeconds > 0) payload.timeoutSeconds = timeoutSeconds; + if (timeoutSeconds > 0) {payload.timeoutSeconds = timeoutSeconds;} return payload; } export async function addCronJob(state: CronState) { - if (!state.client || !state.connected || state.cronBusy) return; + if (!state.client || !state.connected || state.cronBusy) {return;} state.cronBusy = true; state.cronError = null; try { @@ -107,7 +107,7 @@ export async function addCronJob(state: CronState) { ? { postToMainPrefix: state.cronForm.postToMainPrefix.trim() } : undefined, }; - if (!job.name) throw new Error("Name required."); + if (!job.name) {throw new Error("Name required.");} await state.client.request("cron.add", job); state.cronForm = { ...state.cronForm, @@ -125,7 +125,7 @@ export async function addCronJob(state: CronState) { } export async function toggleCronJob(state: CronState, job: CronJob, enabled: boolean) { - if (!state.client || !state.connected || state.cronBusy) return; + if (!state.client || !state.connected || state.cronBusy) {return;} state.cronBusy = true; state.cronError = null; try { @@ -140,7 +140,7 @@ export async function toggleCronJob(state: CronState, job: CronJob, enabled: boo } export async function runCronJob(state: CronState, job: CronJob) { - if (!state.client || !state.connected || state.cronBusy) return; + if (!state.client || !state.connected || state.cronBusy) {return;} state.cronBusy = true; state.cronError = null; try { @@ -154,7 +154,7 @@ export async function runCronJob(state: CronState, job: CronJob) { } export async function removeCronJob(state: CronState, job: CronJob) { - if (!state.client || !state.connected || state.cronBusy) return; + if (!state.client || !state.connected || state.cronBusy) {return;} state.cronBusy = true; state.cronError = null; try { @@ -173,12 +173,12 @@ export async function removeCronJob(state: CronState, job: CronJob) { } export async function loadCronRuns(state: CronState, jobId: string) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} try { const res = (await state.client.request("cron.runs", { id: jobId, limit: 50, - })) as { entries?: CronRunLogEntry[] }; + })); state.cronRunsJobId = jobId; state.cronRuns = Array.isArray(res.entries) ? res.entries : []; } catch (err) { diff --git a/ui/src/ui/controllers/debug.ts b/ui/src/ui/controllers/debug.ts index 2f189af88f..f2da44ca37 100644 --- a/ui/src/ui/controllers/debug.ts +++ b/ui/src/ui/controllers/debug.ts @@ -16,8 +16,8 @@ export type DebugState = { }; export async function loadDebug(state: DebugState) { - if (!state.client || !state.connected) return; - if (state.debugLoading) return; + if (!state.client || !state.connected) {return;} + if (state.debugLoading) {return;} state.debugLoading = true; try { const [status, health, models, heartbeat] = await Promise.all([ @@ -30,7 +30,7 @@ export async function loadDebug(state: DebugState) { state.debugHealth = health as HealthSnapshot; const modelPayload = models as { models?: unknown[] } | undefined; state.debugModels = Array.isArray(modelPayload?.models) ? modelPayload?.models : []; - state.debugHeartbeat = heartbeat as unknown; + state.debugHeartbeat = heartbeat; } catch (err) { state.debugCallError = String(err); } finally { @@ -39,7 +39,7 @@ export async function loadDebug(state: DebugState) { } export async function callDebugMethod(state: DebugState) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.debugCallError = null; state.debugCallResult = null; try { diff --git a/ui/src/ui/controllers/devices.ts b/ui/src/ui/controllers/devices.ts index e63547ba72..91f14e6f97 100644 --- a/ui/src/ui/controllers/devices.ts +++ b/ui/src/ui/controllers/devices.ts @@ -46,25 +46,25 @@ export type DevicesState = { }; export async function loadDevices(state: DevicesState, opts?: { quiet?: boolean }) { - if (!state.client || !state.connected) return; - if (state.devicesLoading) return; + if (!state.client || !state.connected) {return;} + if (state.devicesLoading) {return;} state.devicesLoading = true; - if (!opts?.quiet) state.devicesError = null; + if (!opts?.quiet) {state.devicesError = null;} try { - const res = (await state.client.request("device.pair.list", {})) as DevicePairingList | null; + const res = (await state.client.request("device.pair.list", {})); state.devicesList = { - pending: Array.isArray(res?.pending) ? res!.pending : [], - paired: Array.isArray(res?.paired) ? res!.paired : [], + pending: Array.isArray(res?.pending) ? res.pending : [], + paired: Array.isArray(res?.paired) ? res.paired : [], }; } catch (err) { - if (!opts?.quiet) state.devicesError = String(err); + if (!opts?.quiet) {state.devicesError = String(err);} } finally { state.devicesLoading = false; } } export async function approveDevicePairing(state: DevicesState, requestId: string) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} try { await state.client.request("device.pair.approve", { requestId }); await loadDevices(state); @@ -74,9 +74,9 @@ export async function approveDevicePairing(state: DevicesState, requestId: strin } export async function rejectDevicePairing(state: DevicesState, requestId: string) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} const confirmed = window.confirm("Reject this device pairing request?"); - if (!confirmed) return; + if (!confirmed) {return;} try { await state.client.request("device.pair.reject", { requestId }); await loadDevices(state); @@ -89,11 +89,9 @@ export async function rotateDeviceToken( state: DevicesState, params: { deviceId: string; role: string; scopes?: string[] }, ) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} try { - const res = (await state.client.request("device.token.rotate", params)) as - | { token?: string; role?: string; deviceId?: string; scopes?: string[] } - | undefined; + const res = (await state.client.request("device.token.rotate", params)); if (res?.token) { const identity = await loadOrCreateDeviceIdentity(); const role = res.role ?? params.role; @@ -117,9 +115,9 @@ export async function revokeDeviceToken( state: DevicesState, params: { deviceId: string; role: string }, ) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} const confirmed = window.confirm(`Revoke token for ${params.deviceId} (${params.role})?`); - if (!confirmed) return; + if (!confirmed) {return;} try { await state.client.request("device.token.revoke", params); const identity = await loadOrCreateDeviceIdentity(); diff --git a/ui/src/ui/controllers/exec-approval.ts b/ui/src/ui/controllers/exec-approval.ts index 968b14efcf..e32c1a6ca0 100644 --- a/ui/src/ui/controllers/exec-approval.ts +++ b/ui/src/ui/controllers/exec-approval.ts @@ -28,15 +28,15 @@ function isRecord(value: unknown): value is Record { } export function parseExecApprovalRequested(payload: unknown): ExecApprovalRequest | null { - if (!isRecord(payload)) return null; + if (!isRecord(payload)) {return null;} const id = typeof payload.id === "string" ? payload.id.trim() : ""; const request = payload.request; - if (!id || !isRecord(request)) return null; + if (!id || !isRecord(request)) {return null;} const command = typeof request.command === "string" ? request.command.trim() : ""; - if (!command) return null; + if (!command) {return null;} const createdAtMs = typeof payload.createdAtMs === "number" ? payload.createdAtMs : 0; const expiresAtMs = typeof payload.expiresAtMs === "number" ? payload.expiresAtMs : 0; - if (!createdAtMs || !expiresAtMs) return null; + if (!createdAtMs || !expiresAtMs) {return null;} return { id, request: { @@ -55,9 +55,9 @@ export function parseExecApprovalRequested(payload: unknown): ExecApprovalReques } export function parseExecApprovalResolved(payload: unknown): ExecApprovalResolved | null { - if (!isRecord(payload)) return null; + if (!isRecord(payload)) {return null;} const id = typeof payload.id === "string" ? payload.id.trim() : ""; - if (!id) return null; + if (!id) {return null;} return { id, decision: typeof payload.decision === "string" ? payload.decision : null, diff --git a/ui/src/ui/controllers/exec-approvals.ts b/ui/src/ui/controllers/exec-approvals.ts index 87804642fd..7d5e21ddff 100644 --- a/ui/src/ui/controllers/exec-approvals.ts +++ b/ui/src/ui/controllers/exec-approvals.ts @@ -56,7 +56,7 @@ function resolveExecApprovalsRpc(target?: ExecApprovalsTarget | null): { return { method: "exec.approvals.get", params: {} }; } const nodeId = target.nodeId.trim(); - if (!nodeId) return null; + if (!nodeId) {return null;} return { method: "exec.approvals.node.get", params: { nodeId } }; } @@ -68,7 +68,7 @@ function resolveExecApprovalsSaveRpc( return { method: "exec.approvals.set", params }; } const nodeId = target.nodeId.trim(); - if (!nodeId) return null; + if (!nodeId) {return null;} return { method: "exec.approvals.node.set", params: { ...params, nodeId } }; } @@ -76,8 +76,8 @@ export async function loadExecApprovals( state: ExecApprovalsState, target?: ExecApprovalsTarget | null, ) { - if (!state.client || !state.connected) return; - if (state.execApprovalsLoading) return; + if (!state.client || !state.connected) {return;} + if (state.execApprovalsLoading) {return;} state.execApprovalsLoading = true; state.lastError = null; try { @@ -86,7 +86,7 @@ export async function loadExecApprovals( state.lastError = "Select a node before loading exec approvals."; return; } - const res = (await state.client.request(rpc.method, rpc.params)) as ExecApprovalsSnapshot; + const res = (await state.client.request(rpc.method, rpc.params)); applyExecApprovalsSnapshot(state, res); } catch (err) { state.lastError = String(err); @@ -109,7 +109,7 @@ export async function saveExecApprovals( state: ExecApprovalsState, target?: ExecApprovalsTarget | null, ) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.execApprovalsSaving = true; state.lastError = null; try { diff --git a/ui/src/ui/controllers/logs.ts b/ui/src/ui/controllers/logs.ts index 662b5d7cb2..7eee2082a5 100644 --- a/ui/src/ui/controllers/logs.ts +++ b/ui/src/ui/controllers/logs.ts @@ -19,12 +19,12 @@ const LOG_BUFFER_LIMIT = 2000; const LEVELS = new Set(["trace", "debug", "info", "warn", "error", "fatal"]); function parseMaybeJsonString(value: unknown) { - if (typeof value !== "string") return null; + if (typeof value !== "string") {return null;} const trimmed = value.trim(); - if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return null; + if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) {return null;} try { const parsed = JSON.parse(trimmed) as unknown; - if (!parsed || typeof parsed !== "object") return null; + if (!parsed || typeof parsed !== "object") {return null;} return parsed as Record; } catch { return null; @@ -32,13 +32,13 @@ function parseMaybeJsonString(value: unknown) { } function normalizeLevel(value: unknown): LogLevel | null { - if (typeof value !== "string") return null; + if (typeof value !== "string") {return null;} const lowered = value.toLowerCase() as LogLevel; return LEVELS.has(lowered) ? lowered : null; } export function parseLogLine(line: string): LogEntry { - if (!line.trim()) return { raw: line, message: line }; + if (!line.trim()) {return { raw: line, message: line };} try { const obj = JSON.parse(line) as Record; const meta = @@ -51,24 +51,24 @@ export function parseLogLine(line: string): LogEntry { const contextCandidate = typeof obj["0"] === "string" - ? (obj["0"] as string) + ? (obj["0"]) : typeof meta?.name === "string" - ? (meta?.name as string) + ? (meta?.name) : null; const contextObj = parseMaybeJsonString(contextCandidate); let subsystem: string | null = null; if (contextObj) { - if (typeof contextObj.subsystem === "string") subsystem = contextObj.subsystem; - else if (typeof contextObj.module === "string") subsystem = contextObj.module; + if (typeof contextObj.subsystem === "string") {subsystem = contextObj.subsystem;} + else if (typeof contextObj.module === "string") {subsystem = contextObj.module;} } if (!subsystem && contextCandidate && contextCandidate.length < 120) { subsystem = contextCandidate; } let message: string | null = null; - if (typeof obj["1"] === "string") message = obj["1"] as string; - else if (!contextObj && typeof obj["0"] === "string") message = obj["0"] as string; - else if (typeof obj.message === "string") message = obj.message as string; + if (typeof obj["1"] === "string") {message = obj["1"];} + else if (!contextObj && typeof obj["0"] === "string") {message = obj["0"];} + else if (typeof obj.message === "string") {message = obj.message;} return { raw: line, @@ -84,9 +84,9 @@ export function parseLogLine(line: string): LogEntry { } export async function loadLogs(state: LogsState, opts?: { reset?: boolean; quiet?: boolean }) { - if (!state.client || !state.connected) return; - if (state.logsLoading && !opts?.quiet) return; - if (!opts?.quiet) state.logsLoading = true; + if (!state.client || !state.connected) {return;} + if (state.logsLoading && !opts?.quiet) {return;} + if (!opts?.quiet) {state.logsLoading = true;} state.logsError = null; try { const res = await state.client.request("logs.tail", { @@ -103,20 +103,20 @@ export async function loadLogs(state: LogsState, opts?: { reset?: boolean; quiet reset?: boolean; }; const lines = Array.isArray(payload.lines) - ? (payload.lines.filter((line) => typeof line === "string") as string[]) + ? (payload.lines.filter((line) => typeof line === "string")) : []; const entries = lines.map(parseLogLine); const shouldReset = Boolean(opts?.reset || payload.reset || state.logsCursor == null); state.logsEntries = shouldReset ? entries : [...state.logsEntries, ...entries].slice(-LOG_BUFFER_LIMIT); - if (typeof payload.cursor === "number") state.logsCursor = payload.cursor; - if (typeof payload.file === "string") state.logsFile = payload.file; + if (typeof payload.cursor === "number") {state.logsCursor = payload.cursor;} + if (typeof payload.file === "string") {state.logsFile = payload.file;} state.logsTruncated = Boolean(payload.truncated); state.logsLastFetchAt = Date.now(); } catch (err) { state.logsError = String(err); } finally { - if (!opts?.quiet) state.logsLoading = false; + if (!opts?.quiet) {state.logsLoading = false;} } } diff --git a/ui/src/ui/controllers/nodes.ts b/ui/src/ui/controllers/nodes.ts index b9255aaea7..9044575388 100644 --- a/ui/src/ui/controllers/nodes.ts +++ b/ui/src/ui/controllers/nodes.ts @@ -9,17 +9,15 @@ export type NodesState = { }; export async function loadNodes(state: NodesState, opts?: { quiet?: boolean }) { - if (!state.client || !state.connected) return; - if (state.nodesLoading) return; + if (!state.client || !state.connected) {return;} + if (state.nodesLoading) {return;} state.nodesLoading = true; - if (!opts?.quiet) state.lastError = null; + if (!opts?.quiet) {state.lastError = null;} try { - const res = (await state.client.request("node.list", {})) as { - nodes?: Array>; - }; + const res = (await state.client.request("node.list", {})); state.nodes = Array.isArray(res.nodes) ? res.nodes : []; } catch (err) { - if (!opts?.quiet) state.lastError = String(err); + if (!opts?.quiet) {state.lastError = String(err);} } finally { state.nodesLoading = false; } diff --git a/ui/src/ui/controllers/presence.ts b/ui/src/ui/controllers/presence.ts index 3dbec90618..8e50afd612 100644 --- a/ui/src/ui/controllers/presence.ts +++ b/ui/src/ui/controllers/presence.ts @@ -11,13 +11,13 @@ export type PresenceState = { }; export async function loadPresence(state: PresenceState) { - if (!state.client || !state.connected) return; - if (state.presenceLoading) return; + if (!state.client || !state.connected) {return;} + if (state.presenceLoading) {return;} state.presenceLoading = true; state.presenceError = null; state.presenceStatus = null; try { - const res = (await state.client.request("system-presence", {})) as PresenceEntry[] | undefined; + const res = (await state.client.request("system-presence", {})); if (Array.isArray(res)) { state.presenceEntries = res; state.presenceStatus = res.length === 0 ? "No instances yet." : null; diff --git a/ui/src/ui/controllers/sessions.ts b/ui/src/ui/controllers/sessions.ts index 82e8a8db17..bb9a0d8b03 100644 --- a/ui/src/ui/controllers/sessions.ts +++ b/ui/src/ui/controllers/sessions.ts @@ -23,8 +23,8 @@ export async function loadSessions( includeUnknown?: boolean; }, ) { - if (!state.client || !state.connected) return; - if (state.sessionsLoading) return; + if (!state.client || !state.connected) {return;} + if (state.sessionsLoading) {return;} state.sessionsLoading = true; state.sessionsError = null; try { @@ -36,12 +36,10 @@ export async function loadSessions( includeGlobal, includeUnknown, }; - if (activeMinutes > 0) params.activeMinutes = activeMinutes; - if (limit > 0) params.limit = limit; - const res = (await state.client.request("sessions.list", params)) as - | SessionsListResult - | undefined; - if (res) state.sessionsResult = res; + if (activeMinutes > 0) {params.activeMinutes = activeMinutes;} + if (limit > 0) {params.limit = limit;} + const res = (await state.client.request("sessions.list", params)); + if (res) {state.sessionsResult = res;} } catch (err) { state.sessionsError = String(err); } finally { @@ -59,12 +57,12 @@ export async function patchSession( reasoningLevel?: string | null; }, ) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} const params: Record = { key }; - if ("label" in patch) params.label = patch.label; - if ("thinkingLevel" in patch) params.thinkingLevel = patch.thinkingLevel; - if ("verboseLevel" in patch) params.verboseLevel = patch.verboseLevel; - if ("reasoningLevel" in patch) params.reasoningLevel = patch.reasoningLevel; + if ("label" in patch) {params.label = patch.label;} + if ("thinkingLevel" in patch) {params.thinkingLevel = patch.thinkingLevel;} + if ("verboseLevel" in patch) {params.verboseLevel = patch.verboseLevel;} + if ("reasoningLevel" in patch) {params.reasoningLevel = patch.reasoningLevel;} try { await state.client.request("sessions.patch", params); await loadSessions(state); @@ -74,12 +72,12 @@ export async function patchSession( } export async function deleteSession(state: SessionsState, key: string) { - if (!state.client || !state.connected) return; - if (state.sessionsLoading) return; + if (!state.client || !state.connected) {return;} + if (state.sessionsLoading) {return;} const confirmed = window.confirm( `Delete session "${key}"?\n\nDeletes the session entry and archives its transcript.`, ); - if (!confirmed) return; + if (!confirmed) {return;} state.sessionsLoading = true; state.sessionsError = null; try { diff --git a/ui/src/ui/controllers/skills.ts b/ui/src/ui/controllers/skills.ts index 5708b12ef2..de844ab40d 100644 --- a/ui/src/ui/controllers/skills.ts +++ b/ui/src/ui/controllers/skills.ts @@ -24,15 +24,15 @@ type LoadSkillsOptions = { }; function setSkillMessage(state: SkillsState, key: string, message?: SkillMessage) { - if (!key.trim()) return; + if (!key.trim()) {return;} const next = { ...state.skillMessages }; - if (message) next[key] = message; - else delete next[key]; + if (message) {next[key] = message;} + else {delete next[key];} state.skillMessages = next; } function getErrorMessage(err: unknown) { - if (err instanceof Error) return err.message; + if (err instanceof Error) {return err.message;} return String(err); } @@ -40,13 +40,13 @@ export async function loadSkills(state: SkillsState, options?: LoadSkillsOptions if (options?.clearMessages && Object.keys(state.skillMessages).length > 0) { state.skillMessages = {}; } - if (!state.client || !state.connected) return; - if (state.skillsLoading) return; + if (!state.client || !state.connected) {return;} + if (state.skillsLoading) {return;} state.skillsLoading = true; state.skillsError = null; try { - const res = (await state.client.request("skills.status", {})) as SkillStatusReport | undefined; - if (res) state.skillsReport = res; + const res = (await state.client.request("skills.status", {})); + if (res) {state.skillsReport = res;} } catch (err) { state.skillsError = getErrorMessage(err); } finally { @@ -59,7 +59,7 @@ export function updateSkillEdit(state: SkillsState, skillKey: string, value: str } export async function updateSkillEnabled(state: SkillsState, skillKey: string, enabled: boolean) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.skillsBusyKey = skillKey; state.skillsError = null; try { @@ -82,7 +82,7 @@ export async function updateSkillEnabled(state: SkillsState, skillKey: string, e } export async function saveSkillApiKey(state: SkillsState, skillKey: string) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.skillsBusyKey = skillKey; state.skillsError = null; try { @@ -111,7 +111,7 @@ export async function installSkill( name: string, installId: string, ) { - if (!state.client || !state.connected) return; + if (!state.client || !state.connected) {return;} state.skillsBusyKey = skillKey; state.skillsError = null; try { @@ -119,7 +119,7 @@ export async function installSkill( name, installId, timeoutMs: 120000, - })) as { ok?: boolean; message?: string }; + })); await loadSkills(state); setSkillMessage(state, skillKey, { kind: "success", diff --git a/ui/src/ui/device-auth.ts b/ui/src/ui/device-auth.ts index e06d506115..af96ef5723 100644 --- a/ui/src/ui/device-auth.ts +++ b/ui/src/ui/device-auth.ts @@ -18,23 +18,23 @@ function normalizeRole(role: string): string { } function normalizeScopes(scopes: string[] | undefined): string[] { - if (!Array.isArray(scopes)) return []; + if (!Array.isArray(scopes)) {return [];} const out = new Set(); for (const scope of scopes) { const trimmed = scope.trim(); - if (trimmed) out.add(trimmed); + if (trimmed) {out.add(trimmed);} } - return [...out].sort(); + return [...out].toSorted(); } function readStore(): DeviceAuthStore | null { try { const raw = window.localStorage.getItem(STORAGE_KEY); - if (!raw) return null; + if (!raw) {return null;} const parsed = JSON.parse(raw) as DeviceAuthStore; - if (!parsed || parsed.version !== 1) return null; - if (!parsed.deviceId || typeof parsed.deviceId !== "string") return null; - if (!parsed.tokens || typeof parsed.tokens !== "object") return null; + if (!parsed || parsed.version !== 1) {return null;} + if (!parsed.deviceId || typeof parsed.deviceId !== "string") {return null;} + if (!parsed.tokens || typeof parsed.tokens !== "object") {return null;} return parsed; } catch { return null; @@ -54,10 +54,10 @@ export function loadDeviceAuthToken(params: { role: string; }): DeviceAuthEntry | null { const store = readStore(); - if (!store || store.deviceId !== params.deviceId) return null; + if (!store || store.deviceId !== params.deviceId) {return null;} const role = normalizeRole(params.role); const entry = store.tokens[role]; - if (!entry || typeof entry.token !== "string") return null; + if (!entry || typeof entry.token !== "string") {return null;} return entry; } @@ -90,9 +90,9 @@ export function storeDeviceAuthToken(params: { export function clearDeviceAuthToken(params: { deviceId: string; role: string }) { const store = readStore(); - if (!store || store.deviceId !== params.deviceId) return; + if (!store || store.deviceId !== params.deviceId) {return;} const role = normalizeRole(params.role); - if (!store.tokens[role]) return; + if (!store.tokens[role]) {return;} const next = { ...store, tokens: { ...store.tokens } }; delete next.tokens[role]; writeStore(next); diff --git a/ui/src/ui/device-identity.ts b/ui/src/ui/device-identity.ts index 2070fbdc1b..fd03dafcad 100644 --- a/ui/src/ui/device-identity.ts +++ b/ui/src/ui/device-identity.ts @@ -18,7 +18,7 @@ const STORAGE_KEY = "openclaw-device-identity-v1"; function base64UrlEncode(bytes: Uint8Array): string { let binary = ""; - for (const byte of bytes) binary += String.fromCharCode(byte); + for (const byte of bytes) {binary += String.fromCharCode(byte);} return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, ""); } @@ -27,7 +27,7 @@ function base64UrlDecode(input: string): Uint8Array { const padded = normalized + "=".repeat((4 - (normalized.length % 4)) % 4); const binary = atob(padded); const out = new Uint8Array(binary.length); - for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i); + for (let i = 0; i < binary.length; i += 1) {out[i] = binary.charCodeAt(i);} return out; } diff --git a/ui/src/ui/format.ts b/ui/src/ui/format.ts index cdefd2f564..29327a1a4e 100644 --- a/ui/src/ui/format.ts +++ b/ui/src/ui/format.ts @@ -1,44 +1,44 @@ import { stripReasoningTagsFromText } from "../../../src/shared/text/reasoning-tags.js"; export function formatMs(ms?: number | null): string { - if (!ms && ms !== 0) return "n/a"; + if (!ms && ms !== 0) {return "n/a";} return new Date(ms).toLocaleString(); } export function formatAgo(ms?: number | null): string { - if (!ms && ms !== 0) return "n/a"; + if (!ms && ms !== 0) {return "n/a";} const diff = Date.now() - ms; - if (diff < 0) return "just now"; + if (diff < 0) {return "just now";} const sec = Math.round(diff / 1000); - if (sec < 60) return `${sec}s ago`; + if (sec < 60) {return `${sec}s ago`;} const min = Math.round(sec / 60); - if (min < 60) return `${min}m ago`; + if (min < 60) {return `${min}m ago`;} const hr = Math.round(min / 60); - if (hr < 48) return `${hr}h ago`; + if (hr < 48) {return `${hr}h ago`;} const day = Math.round(hr / 24); return `${day}d ago`; } export function formatDurationMs(ms?: number | null): string { - if (!ms && ms !== 0) return "n/a"; - if (ms < 1000) return `${ms}ms`; + if (!ms && ms !== 0) {return "n/a";} + if (ms < 1000) {return `${ms}ms`;} const sec = Math.round(ms / 1000); - if (sec < 60) return `${sec}s`; + if (sec < 60) {return `${sec}s`;} const min = Math.round(sec / 60); - if (min < 60) return `${min}m`; + if (min < 60) {return `${min}m`;} const hr = Math.round(min / 60); - if (hr < 48) return `${hr}h`; + if (hr < 48) {return `${hr}h`;} const day = Math.round(hr / 24); return `${day}d`; } export function formatList(values?: Array): string { - if (!values || values.length === 0) return "none"; + if (!values || values.length === 0) {return "none";} return values.filter((v): v is string => Boolean(v && v.trim())).join(", "); } export function clampText(value: string, max = 120): string { - if (value.length <= max) return value; + if (value.length <= max) {return value;} return `${value.slice(0, Math.max(0, max - 1))}…`; } diff --git a/ui/src/ui/gateway.ts b/ui/src/ui/gateway.ts index 3336e09b50..4343fc75fa 100644 --- a/ui/src/ui/gateway.ts +++ b/ui/src/ui/gateway.ts @@ -91,7 +91,7 @@ export class GatewayBrowserClient { } private connect() { - if (this.closed) return; + if (this.closed) {return;} this.ws = new WebSocket(this.opts.url); this.ws.onopen = () => this.queueConnect(); this.ws.onmessage = (ev) => this.handleMessage(String(ev.data ?? "")); @@ -108,19 +108,19 @@ export class GatewayBrowserClient { } private scheduleReconnect() { - if (this.closed) return; + if (this.closed) {return;} const delay = this.backoffMs; this.backoffMs = Math.min(this.backoffMs * 1.7, 15_000); window.setTimeout(() => this.connect(), delay); } private flushPending(err: Error) { - for (const [, p] of this.pending) p.reject(err); + for (const [, p] of this.pending) {p.reject(err);} this.pending.clear(); } private async sendConnect() { - if (this.connectSent) return; + if (this.connectSent) {return;} this.connectSent = true; if (this.connectTimer !== null) { window.clearTimeout(this.connectTimer); @@ -265,10 +265,10 @@ export class GatewayBrowserClient { if (frame.type === "res") { const res = parsed as GatewayResponseFrame; const pending = this.pending.get(res.id); - if (!pending) return; + if (!pending) {return;} this.pending.delete(res.id); - if (res.ok) pending.resolve(res.payload); - else pending.reject(new Error(res.error?.message ?? "request failed")); + if (res.ok) {pending.resolve(res.payload);} + else {pending.reject(new Error(res.error?.message ?? "request failed"));} return; } } @@ -289,7 +289,7 @@ export class GatewayBrowserClient { private queueConnect() { this.connectNonce = null; this.connectSent = false; - if (this.connectTimer !== null) window.clearTimeout(this.connectTimer); + if (this.connectTimer !== null) {window.clearTimeout(this.connectTimer);} this.connectTimer = window.setTimeout(() => { void this.sendConnect(); }, 750); diff --git a/ui/src/ui/icons.ts b/ui/src/ui/icons.ts index b6e9c6b856..fafc96504b 100644 --- a/ui/src/ui/icons.ts +++ b/ui/src/ui/icons.ts @@ -243,6 +243,6 @@ export function renderEmojiIcon( } export function setEmojiIcon(target: HTMLElement | null, icon: string): void { - if (!target) return; + if (!target) {return;} target.textContent = icon; } diff --git a/ui/src/ui/markdown.ts b/ui/src/ui/markdown.ts index 42aeff4b49..7a246d4792 100644 --- a/ui/src/ui/markdown.ts +++ b/ui/src/ui/markdown.ts @@ -47,7 +47,7 @@ const markdownCache = new Map(); function getCachedMarkdown(key: string): string | null { const cached = markdownCache.get(key); - if (cached === undefined) return null; + if (cached === undefined) {return null;} markdownCache.delete(key); markdownCache.set(key, cached); return cached; @@ -55,19 +55,19 @@ function getCachedMarkdown(key: string): string | null { function setCachedMarkdown(key: string, value: string) { markdownCache.set(key, value); - if (markdownCache.size <= MARKDOWN_CACHE_LIMIT) return; + if (markdownCache.size <= MARKDOWN_CACHE_LIMIT) {return;} const oldest = markdownCache.keys().next().value; - if (oldest) markdownCache.delete(oldest); + if (oldest) {markdownCache.delete(oldest);} } function installHooks() { - if (hooksInstalled) return; + if (hooksInstalled) {return;} hooksInstalled = true; DOMPurify.addHook("afterSanitizeAttributes", (node) => { - if (!(node instanceof HTMLAnchorElement)) return; + if (!(node instanceof HTMLAnchorElement)) {return;} const href = node.getAttribute("href"); - if (!href) return; + if (!href) {return;} node.setAttribute("rel", "noreferrer noopener"); node.setAttribute("target", "_blank"); }); @@ -75,11 +75,11 @@ function installHooks() { export function toSanitizedMarkdownHtml(markdown: string): string { const input = markdown.trim(); - if (!input) return ""; + if (!input) {return "";} installHooks(); if (input.length <= MARKDOWN_CACHE_MAX_CHARS) { const cached = getCachedMarkdown(input); - if (cached !== null) return cached; + if (cached !== null) {return cached;} } const truncated = truncateText(input, MARKDOWN_CHAR_LIMIT); const suffix = truncated.truncated diff --git a/ui/src/ui/navigation.browser.test.ts b/ui/src/ui/navigation.browser.test.ts index 2e4246840a..3120fb8898 100644 --- a/ui/src/ui/navigation.browser.test.ts +++ b/ui/src/ui/navigation.browser.test.ts @@ -89,13 +89,13 @@ describe("control UI routing", () => { expect(window.matchMedia("(max-width: 768px)").matches).toBe(true); - const split = app.querySelector(".chat-split-container") as HTMLElement | null; + const split = app.querySelector(".chat-split-container"); expect(split).not.toBeNull(); if (split) { expect(getComputedStyle(split).position).not.toBe("fixed"); } - const chatMain = app.querySelector(".chat-main") as HTMLElement | null; + const chatMain = app.querySelector(".chat-main"); expect(chatMain).not.toBeNull(); if (chatMain) { expect(getComputedStyle(chatMain).display).not.toBe("none"); @@ -115,9 +115,9 @@ describe("control UI routing", () => { const app = mountApp("/chat"); await app.updateComplete; - const initialContainer = app.querySelector(".chat-thread") as HTMLElement | null; + const initialContainer = app.querySelector(".chat-thread"); expect(initialContainer).not.toBeNull(); - if (!initialContainer) return; + if (!initialContainer) {return;} initialContainer.style.maxHeight = "180px"; initialContainer.style.overflow = "auto"; @@ -132,13 +132,13 @@ describe("control UI routing", () => { await nextFrame(); } - const container = app.querySelector(".chat-thread") as HTMLElement | null; + const container = app.querySelector(".chat-thread"); expect(container).not.toBeNull(); - if (!container) return; + if (!container) {return;} const maxScroll = container.scrollHeight - container.clientHeight; expect(maxScroll).toBeGreaterThan(0); for (let i = 0; i < 10; i++) { - if (container.scrollTop === maxScroll) break; + if (container.scrollTop === maxScroll) {break;} await nextFrame(); } expect(container.scrollTop).toBe(maxScroll); diff --git a/ui/src/ui/navigation.ts b/ui/src/ui/navigation.ts index 8557a21f44..8c5cddd94d 100644 --- a/ui/src/ui/navigation.ts +++ b/ui/src/ui/navigation.ts @@ -40,18 +40,18 @@ const TAB_PATHS: Record = { const PATH_TO_TAB = new Map(Object.entries(TAB_PATHS).map(([tab, path]) => [path, tab as Tab])); export function normalizeBasePath(basePath: string): string { - if (!basePath) return ""; + if (!basePath) {return "";} let base = basePath.trim(); - if (!base.startsWith("/")) base = `/${base}`; - if (base === "/") return ""; - if (base.endsWith("/")) base = base.slice(0, -1); + if (!base.startsWith("/")) {base = `/${base}`;} + if (base === "/") {return "";} + if (base.endsWith("/")) {base = base.slice(0, -1);} return base; } export function normalizePath(path: string): string { - if (!path) return "/"; + if (!path) {return "/";} let normalized = path.trim(); - if (!normalized.startsWith("/")) normalized = `/${normalized}`; + if (!normalized.startsWith("/")) {normalized = `/${normalized}`;} if (normalized.length > 1 && normalized.endsWith("/")) { normalized = normalized.slice(0, -1); } @@ -75,8 +75,8 @@ export function tabFromPath(pathname: string, basePath = ""): Tab | null { } } let normalized = normalizePath(path).toLowerCase(); - if (normalized.endsWith("/index.html")) normalized = "/"; - if (normalized === "/") return "chat"; + if (normalized.endsWith("/index.html")) {normalized = "/";} + if (normalized === "/") {return "chat";} return PATH_TO_TAB.get(normalized) ?? null; } @@ -85,9 +85,9 @@ export function inferBasePathFromPathname(pathname: string): string { if (normalized.endsWith("/index.html")) { normalized = normalizePath(normalized.slice(0, -"/index.html".length)); } - if (normalized === "/") return ""; + if (normalized === "/") {return "";} const segments = normalized.split("/").filter(Boolean); - if (segments.length === 0) return ""; + if (segments.length === 0) {return "";} for (let i = 0; i < segments.length; i++) { const candidate = `/${segments.slice(i).join("/")}`.toLowerCase(); if (PATH_TO_TAB.has(candidate)) { diff --git a/ui/src/ui/presenter.ts b/ui/src/ui/presenter.ts index 0fd1533217..f55f14b4d8 100644 --- a/ui/src/ui/presenter.ts +++ b/ui/src/ui/presenter.ts @@ -15,19 +15,19 @@ export function formatPresenceAge(entry: PresenceEntry): string { } export function formatNextRun(ms?: number | null) { - if (!ms) return "n/a"; + if (!ms) {return "n/a";} return `${formatMs(ms)} (${formatAgo(ms)})`; } export function formatSessionTokens(row: GatewaySessionRow) { - if (row.totalTokens == null) return "n/a"; + if (row.totalTokens == null) {return "n/a";} const total = row.totalTokens ?? 0; const ctx = row.contextTokens ?? 0; return ctx ? `${total} / ${ctx}` : String(total); } export function formatEventPayload(payload: unknown): string { - if (payload == null) return ""; + if (payload == null) {return "";} try { return JSON.stringify(payload, null, 2); } catch { @@ -45,13 +45,13 @@ export function formatCronState(job: CronJob) { export function formatCronSchedule(job: CronJob) { const s = job.schedule; - if (s.kind === "at") return `At ${formatMs(s.atMs)}`; - if (s.kind === "every") return `Every ${formatDurationMs(s.everyMs)}`; + if (s.kind === "at") {return `At ${formatMs(s.atMs)}`;} + if (s.kind === "every") {return `Every ${formatDurationMs(s.everyMs)}`;} return `Cron ${s.expr}${s.tz ? ` (${s.tz})` : ""}`; } export function formatCronPayload(job: CronJob) { const p = job.payload; - if (p.kind === "systemEvent") return `System: ${p.text}`; + if (p.kind === "systemEvent") {return `System: ${p.text}`;} return `Agent: ${p.message}`; } diff --git a/ui/src/ui/storage.ts b/ui/src/ui/storage.ts index 3e1214f112..221e0c58dd 100644 --- a/ui/src/ui/storage.ts +++ b/ui/src/ui/storage.ts @@ -36,7 +36,7 @@ export function loadSettings(): UiSettings { try { const raw = localStorage.getItem(KEY); - if (!raw) return defaults; + if (!raw) {return defaults;} const parsed = JSON.parse(raw) as Partial; return { gatewayUrl: diff --git a/ui/src/ui/theme-transition.ts b/ui/src/ui/theme-transition.ts index 10c3942c9c..5d30208ac7 100644 --- a/ui/src/ui/theme-transition.ts +++ b/ui/src/ui/theme-transition.ts @@ -18,9 +18,9 @@ type DocumentWithViewTransition = Document & { }; const clamp01 = (value: number) => { - if (Number.isNaN(value)) return 0.5; - if (value <= 0) return 0; - if (value >= 1) return 1; + if (Number.isNaN(value)) {return 0.5;} + if (value <= 0) {return 0;} + if (value >= 1) {return 1;} return value; }; @@ -43,7 +43,7 @@ export const startThemeTransition = ({ context, currentTheme, }: ThemeTransitionOptions) => { - if (currentTheme === nextTheme) return; + if (currentTheme === nextTheme) {return;} const documentReference = globalThis.document ?? null; if (!documentReference) { diff --git a/ui/src/ui/theme.ts b/ui/src/ui/theme.ts index 4d2db4f278..bb0cfe728f 100644 --- a/ui/src/ui/theme.ts +++ b/ui/src/ui/theme.ts @@ -9,6 +9,6 @@ export function getSystemTheme(): ResolvedTheme { } export function resolveTheme(mode: ThemeMode): ResolvedTheme { - if (mode === "system") return getSystemTheme(); + if (mode === "system") {return getSystemTheme();} return mode; } diff --git a/ui/src/ui/tool-display.ts b/ui/src/ui/tool-display.ts index 4acbe0b473..64168a2ee6 100644 --- a/ui/src/ui/tool-display.ts +++ b/ui/src/ui/tool-display.ts @@ -39,7 +39,7 @@ function normalizeToolName(name?: string): string { function defaultTitle(name: string): string { const cleaned = name.replace(/_/g, " ").trim(); - if (!cleaned) return "Tool"; + if (!cleaned) {return "Tool";} return cleaned .split(/\s+/) .map((part) => @@ -52,17 +52,17 @@ function defaultTitle(name: string): string { function normalizeVerb(value?: string): string | undefined { const trimmed = value?.trim(); - if (!trimmed) return undefined; + if (!trimmed) {return undefined;} return trimmed.replace(/_/g, " "); } function coerceDisplayValue(value: unknown): string | undefined { - if (value === null || value === undefined) return undefined; + if (value === null || value === undefined) {return undefined;} if (typeof value === "string") { const trimmed = value.trim(); - if (!trimmed) return undefined; + if (!trimmed) {return undefined;} const firstLine = trimmed.split(/\r?\n/)[0]?.trim() ?? ""; - if (!firstLine) return undefined; + if (!firstLine) {return undefined;} return firstLine.length > 160 ? `${firstLine.slice(0, 157)}…` : firstLine; } if (typeof value === "number" || typeof value === "boolean") { @@ -72,7 +72,7 @@ function coerceDisplayValue(value: unknown): string | undefined { const values = value .map((item) => coerceDisplayValue(item)) .filter((item): item is string => Boolean(item)); - if (values.length === 0) return undefined; + if (values.length === 0) {return undefined;} const preview = values.slice(0, 3).join(", "); return values.length > 3 ? `${preview}…` : preview; } @@ -80,11 +80,11 @@ function coerceDisplayValue(value: unknown): string | undefined { } function lookupValueByPath(args: unknown, path: string): unknown { - if (!args || typeof args !== "object") return undefined; + if (!args || typeof args !== "object") {return undefined;} let current: unknown = args; for (const segment of path.split(".")) { - if (!segment) return undefined; - if (!current || typeof current !== "object") return undefined; + if (!segment) {return undefined;} + if (!current || typeof current !== "object") {return undefined;} const record = current as Record; current = record[segment]; } @@ -95,16 +95,16 @@ function resolveDetailFromKeys(args: unknown, keys: string[]): string | undefine for (const key of keys) { const value = lookupValueByPath(args, key); const display = coerceDisplayValue(value); - if (display) return display; + if (display) {return display;} } return undefined; } function resolveReadDetail(args: unknown): string | undefined { - if (!args || typeof args !== "object") return undefined; + if (!args || typeof args !== "object") {return undefined;} const record = args as Record; const path = typeof record.path === "string" ? record.path : undefined; - if (!path) return undefined; + if (!path) {return undefined;} const offset = typeof record.offset === "number" ? record.offset : undefined; const limit = typeof record.limit === "number" ? record.limit : undefined; if (offset !== undefined && limit !== undefined) { @@ -114,7 +114,7 @@ function resolveReadDetail(args: unknown): string | undefined { } function resolveWriteDetail(args: unknown): string | undefined { - if (!args || typeof args !== "object") return undefined; + if (!args || typeof args !== "object") {return undefined;} const record = args as Record; const path = typeof record.path === "string" ? record.path : undefined; return path; @@ -124,7 +124,7 @@ function resolveActionSpec( spec: ToolDisplaySpec | undefined, action: string | undefined, ): ToolDisplayActionSpec | undefined { - if (!spec || !action) return undefined; + if (!spec || !action) {return undefined;} return spec.actions?.[action] ?? undefined; } @@ -148,7 +148,7 @@ export function resolveToolDisplay(params: { const verb = normalizeVerb(actionSpec?.label ?? action); let detail: string | undefined; - if (key === "read") detail = resolveReadDetail(params.args); + if (key === "read") {detail = resolveReadDetail(params.args);} if (!detail && (key === "write" || key === "edit" || key === "attach")) { detail = resolveWriteDetail(params.args); } @@ -178,9 +178,9 @@ export function resolveToolDisplay(params: { export function formatToolDetail(display: ToolDisplay): string | undefined { const parts: string[] = []; - if (display.verb) parts.push(display.verb); - if (display.detail) parts.push(display.detail); - if (parts.length === 0) return undefined; + if (display.verb) {parts.push(display.verb);} + if (display.detail) {parts.push(display.detail);} + if (parts.length === 0) {return undefined;} return parts.join(" · "); } @@ -190,6 +190,6 @@ export function formatToolSummary(display: ToolDisplay): string { } function shortenHomeInString(input: string): string { - if (!input) return input; + if (!input) {return input;} return input.replace(/\/Users\/[^/]+/g, "~").replace(/\/home\/[^/]+/g, "~"); } diff --git a/ui/src/ui/uuid.test.ts b/ui/src/ui/uuid.test.ts index 946a1866d3..afe19ad214 100644 --- a/ui/src/ui/uuid.test.ts +++ b/ui/src/ui/uuid.test.ts @@ -16,7 +16,7 @@ describe("generateUUID", () => { it("falls back to crypto.getRandomValues", () => { const id = generateUUID({ getRandomValues: (bytes) => { - for (let i = 0; i < bytes.length; i++) bytes[i] = i; + for (let i = 0; i < bytes.length; i++) {bytes[i] = i;} return bytes; }, }); diff --git a/ui/src/ui/uuid.ts b/ui/src/ui/uuid.ts index 7c927cda1f..fd5f5fdf5d 100644 --- a/ui/src/ui/uuid.ts +++ b/ui/src/ui/uuid.ts @@ -11,7 +11,7 @@ function uuidFromBytes(bytes: Uint8Array): string { let hex = ""; for (let i = 0; i < bytes.length; i++) { - hex += bytes[i]!.toString(16).padStart(2, "0"); + hex += bytes[i].toString(16).padStart(2, "0"); } return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice( @@ -23,7 +23,7 @@ function uuidFromBytes(bytes: Uint8Array): string { function weakRandomBytes(): Uint8Array { const bytes = new Uint8Array(16); const now = Date.now(); - for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256); + for (let i = 0; i < bytes.length; i++) {bytes[i] = Math.floor(Math.random() * 256);} bytes[0] ^= now & 0xff; bytes[1] ^= (now >>> 8) & 0xff; bytes[2] ^= (now >>> 16) & 0xff; @@ -32,13 +32,13 @@ function weakRandomBytes(): Uint8Array { } function warnWeakCryptoOnce() { - if (warnedWeakCrypto) return; + if (warnedWeakCrypto) {return;} warnedWeakCrypto = true; console.warn("[uuid] crypto API missing; falling back to weak randomness"); } export function generateUUID(cryptoLike: CryptoLike | null = globalThis.crypto): string { - if (cryptoLike && typeof cryptoLike.randomUUID === "function") return cryptoLike.randomUUID(); + if (cryptoLike && typeof cryptoLike.randomUUID === "function") {return cryptoLike.randomUUID();} if (cryptoLike && typeof cryptoLike.getRandomValues === "function") { const bytes = new Uint8Array(16); diff --git a/ui/src/ui/views/channels.config.ts b/ui/src/ui/views/channels.config.ts index 5c2eb62099..c1566242bb 100644 --- a/ui/src/ui/views/channels.config.ts +++ b/ui/src/ui/views/channels.config.ts @@ -18,7 +18,7 @@ function resolveSchemaNode( ): JsonSchema | null { let current = schema; for (const key of path) { - if (!current) return null; + if (!current) {return null;} const type = schemaType(current); if (type === "object") { const properties = current.properties ?? {}; @@ -28,13 +28,13 @@ function resolveSchemaNode( } const additional = current.additionalProperties; if (typeof key === "string" && additional && typeof additional === "object") { - current = additional as JsonSchema; + current = additional; continue; } return null; } if (type === "array") { - if (typeof key !== "number") return null; + if (typeof key !== "number") {return null;} const items = Array.isArray(current.items) ? current.items[0] : current.items; current = items ?? null; continue; diff --git a/ui/src/ui/views/channels.nostr-profile-form.ts b/ui/src/ui/views/channels.nostr-profile-form.ts index a18d1c981e..b9dfc332dd 100644 --- a/ui/src/ui/views/channels.nostr-profile-form.ts +++ b/ui/src/ui/views/channels.nostr-profile-form.ts @@ -140,7 +140,7 @@ export function renderNostrProfileForm(params: { const renderPicturePreview = () => { const picture = state.values.picture; - if (!picture) return nothing; + if (!picture) {return nothing;} return html`
diff --git a/ui/src/ui/views/channels.nostr.ts b/ui/src/ui/views/channels.nostr.ts index 0792f80462..4ad7d82cf2 100644 --- a/ui/src/ui/views/channels.nostr.ts +++ b/ui/src/ui/views/channels.nostr.ts @@ -13,8 +13,8 @@ import { * Truncate a pubkey for display (shows first and last 8 chars) */ function truncatePubkey(pubkey: string | null | undefined): string { - if (!pubkey) return "n/a"; - if (pubkey.length <= 20) return pubkey; + if (!pubkey) {return "n/a";} + if (pubkey.length <= 20) {return pubkey;} return `${pubkey.slice(0, 8)}...${pubkey.slice(-8)}`; } diff --git a/ui/src/ui/views/channels.shared.ts b/ui/src/ui/views/channels.shared.ts index 7da38a7139..7f79e18d5d 100644 --- a/ui/src/ui/views/channels.shared.ts +++ b/ui/src/ui/views/channels.shared.ts @@ -3,11 +3,11 @@ import type { ChannelAccountSnapshot } from "../types"; import type { ChannelKey, ChannelsProps } from "./channels.types"; export function formatDuration(ms?: number | null) { - if (!ms && ms !== 0) return "n/a"; + if (!ms && ms !== 0) {return "n/a";} const sec = Math.round(ms / 1000); - if (sec < 60) return `${sec}s`; + if (sec < 60) {return `${sec}s`;} const min = Math.round(sec / 60); - if (min < 60) return `${min}m`; + if (min < 60) {return `${min}m`;} const hr = Math.round(min / 60); return `${hr}h`; } @@ -15,7 +15,7 @@ export function formatDuration(ms?: number | null) { export function channelEnabled(key: ChannelKey, props: ChannelsProps) { const snapshot = props.snapshot; const channels = snapshot?.channels as Record | null; - if (!snapshot || !channels) return false; + if (!snapshot || !channels) {return false;} const channelStatus = channels[key] as Record | undefined; const configured = typeof channelStatus?.configured === "boolean" && channelStatus.configured; const running = typeof channelStatus?.running === "boolean" && channelStatus.running; @@ -39,6 +39,6 @@ export function renderChannelAccountCount( channelAccounts?: Record | null, ) { const count = getChannelAccountCount(key, channelAccounts); - if (count < 2) return nothing; + if (count < 2) {return nothing;} return html``; } diff --git a/ui/src/ui/views/channels.ts b/ui/src/ui/views/channels.ts index 444b22e59a..c00c914174 100644 --- a/ui/src/ui/views/channels.ts +++ b/ui/src/ui/views/channels.ts @@ -43,8 +43,8 @@ export function renderChannels(props: ChannelsProps) { enabled: channelEnabled(key, props), order: index, })) - .sort((a, b) => { - if (a.enabled !== b.enabled) return a.enabled ? -1 : 1; + .toSorted((a, b) => { + if (a.enabled !== b.enabled) {return a.enabled ? -1 : 1;} return a.order - b.order; }); @@ -89,7 +89,7 @@ ${props.snapshot ? JSON.stringify(props.snapshot, null, 2) : "No snapshot yet."} function resolveChannelOrder(snapshot: ChannelsStatusSnapshot | null): ChannelKey[] { if (snapshot?.channelMeta?.length) { - return snapshot.channelMeta.map((entry) => entry.id) as ChannelKey[]; + return snapshot.channelMeta.map((entry) => entry.id); } if (snapshot?.channelOrder?.length) { return snapshot.channelOrder; @@ -236,7 +236,7 @@ function renderGenericChannelCard( function resolveChannelMetaMap( snapshot: ChannelsStatusSnapshot | null, ): Record { - if (!snapshot?.channelMeta?.length) return {}; + if (!snapshot?.channelMeta?.length) {return {};} return Object.fromEntries(snapshot.channelMeta.map((entry) => [entry.id, entry])); } @@ -248,22 +248,22 @@ function resolveChannelLabel(snapshot: ChannelsStatusSnapshot | null, key: strin const RECENT_ACTIVITY_THRESHOLD_MS = 10 * 60 * 1000; // 10 minutes function hasRecentActivity(account: ChannelAccountSnapshot): boolean { - if (!account.lastInboundAt) return false; + if (!account.lastInboundAt) {return false;} return Date.now() - account.lastInboundAt < RECENT_ACTIVITY_THRESHOLD_MS; } function deriveRunningStatus(account: ChannelAccountSnapshot): "Yes" | "No" | "Active" { - if (account.running) return "Yes"; + if (account.running) {return "Yes";} // If we have recent inbound activity, the channel is effectively running - if (hasRecentActivity(account)) return "Active"; + if (hasRecentActivity(account)) {return "Active";} return "No"; } function deriveConnectedStatus(account: ChannelAccountSnapshot): "Yes" | "No" | "Active" | "n/a" { - if (account.connected === true) return "Yes"; - if (account.connected === false) return "No"; + if (account.connected === true) {return "Yes";} + if (account.connected === false) {return "No";} // If connected is null/undefined but we have recent activity, show as active - if (hasRecentActivity(account)) return "Active"; + if (hasRecentActivity(account)) {return "Active";} return "n/a"; } diff --git a/ui/src/ui/views/chat.ts b/ui/src/ui/views/chat.ts index 070fb76a8c..780e2fb114 100644 --- a/ui/src/ui/views/chat.ts +++ b/ui/src/ui/views/chat.ts @@ -75,7 +75,7 @@ function adjustTextareaHeight(el: HTMLTextAreaElement) { } function renderCompactionIndicator(status: CompactionIndicatorStatus | null | undefined) { - if (!status) return nothing; + if (!status) {return nothing;} // Show "compacting..." while active if (status.active) { @@ -107,7 +107,7 @@ function generateAttachmentId(): string { function handlePaste(e: ClipboardEvent, props: ChatProps) { const items = e.clipboardData?.items; - if (!items || !props.onAttachmentsChange) return; + if (!items || !props.onAttachmentsChange) {return;} const imageItems: DataTransferItem[] = []; for (let i = 0; i < items.length; i++) { @@ -117,13 +117,13 @@ function handlePaste(e: ClipboardEvent, props: ChatProps) { } } - if (imageItems.length === 0) return; + if (imageItems.length === 0) {return;} e.preventDefault(); for (const item of imageItems) { const file = item.getAsFile(); - if (!file) continue; + if (!file) {continue;} const reader = new FileReader(); reader.onload = () => { @@ -142,7 +142,7 @@ function handlePaste(e: ClipboardEvent, props: ChatProps) { function renderAttachmentPreview(props: ChatProps) { const attachments = props.attachments ?? []; - if (attachments.length === 0) return nothing; + if (attachments.length === 0) {return nothing;} return html`
@@ -286,7 +286,7 @@ export function renderChat(props: ChatProps) { error: props.sidebarError ?? null, onClose: props.onCloseSidebar!, onViewRawText: () => { - if (!props.sidebarContent || !props.onOpenSidebar) return; + if (!props.sidebarContent || !props.onOpenSidebar) {return;} props.onOpenSidebar(`\`\`\`\n${props.sidebarContent}\n\`\`\``); }, })} @@ -338,12 +338,12 @@ export function renderChat(props: ChatProps) { .value=${props.draft} ?disabled=${!props.connected} @keydown=${(e: KeyboardEvent) => { - if (e.key !== "Enter") return; - if (e.isComposing || e.keyCode === 229) return; - if (e.shiftKey) return; // Allow Shift+Enter for line breaks - if (!props.connected) return; + if (e.key !== "Enter") {return;} + if (e.isComposing || e.keyCode === 229) {return;} + if (e.shiftKey) {return;} // Allow Shift+Enter for line breaks + if (!props.connected) {return;} e.preventDefault(); - if (canCompose) props.onSend(); + if (canCompose) {props.onSend();} }} @input=${(e: Event) => { const target = e.target as HTMLTextAreaElement; @@ -397,7 +397,7 @@ function groupMessages(items: ChatItem[]): Array { const timestamp = normalized.timestamp || Date.now(); if (!currentGroup || currentGroup.role !== role) { - if (currentGroup) result.push(currentGroup); + if (currentGroup) {result.push(currentGroup);} currentGroup = { kind: "group", key: `group:${role}:${item.key}`, @@ -411,7 +411,7 @@ function groupMessages(items: ChatItem[]): Array { } } - if (currentGroup) result.push(currentGroup); + if (currentGroup) {result.push(currentGroup);} return result; } @@ -475,13 +475,13 @@ function buildChatItems(props: ChatProps): Array { function messageKey(message: unknown, index: number): string { const m = message as Record; const toolCallId = typeof m.toolCallId === "string" ? m.toolCallId : ""; - if (toolCallId) return `tool:${toolCallId}`; + if (toolCallId) {return `tool:${toolCallId}`;} const id = typeof m.id === "string" ? m.id : ""; - if (id) return `msg:${id}`; + if (id) {return `msg:${id}`;} const messageId = typeof m.messageId === "string" ? m.messageId : ""; - if (messageId) return `msg:${messageId}`; + if (messageId) {return `msg:${messageId}`;} const timestamp = typeof m.timestamp === "number" ? m.timestamp : null; const role = typeof m.role === "string" ? m.role : "unknown"; - if (timestamp != null) return `msg:${role}:${timestamp}:${index}`; + if (timestamp != null) {return `msg:${role}:${timestamp}:${index}`;} return `msg:${role}:${index}`; } diff --git a/ui/src/ui/views/config-form.analyze.ts b/ui/src/ui/views/config-form.analyze.ts index a6451806c1..4c4e4ec320 100644 --- a/ui/src/ui/views/config-form.analyze.ts +++ b/ui/src/ui/views/config-form.analyze.ts @@ -41,7 +41,7 @@ function normalizeSchemaNode( if (schema.anyOf || schema.oneOf || schema.allOf) { const union = normalizeUnion(schema, path); - if (union) return union; + if (union) {return union;} return { schema, unsupportedPaths: [pathLabel] }; } @@ -54,8 +54,8 @@ function normalizeSchemaNode( if (normalized.enum) { const { enumValues, nullable: enumNullable } = normalizeEnum(normalized.enum); normalized.enum = enumValues; - if (enumNullable) normalized.nullable = true; - if (enumValues.length === 0) unsupported.add(pathLabel); + if (enumNullable) {normalized.nullable = true;} + if (enumValues.length === 0) {unsupported.add(pathLabel);} } if (type === "object") { @@ -63,8 +63,8 @@ function normalizeSchemaNode( const normalizedProps: Record = {}; for (const [key, value] of Object.entries(properties)) { const res = normalizeSchemaNode(value, [...path, key]); - if (res.schema) normalizedProps[key] = res.schema; - for (const entry of res.unsupportedPaths) unsupported.add(entry); + if (res.schema) {normalizedProps[key] = res.schema;} + for (const entry of res.unsupportedPaths) {unsupported.add(entry);} } normalized.properties = normalizedProps; @@ -73,10 +73,10 @@ function normalizeSchemaNode( } else if (schema.additionalProperties === false) { normalized.additionalProperties = false; } else if (schema.additionalProperties && typeof schema.additionalProperties === "object") { - if (!isAnySchema(schema.additionalProperties as JsonSchema)) { - const res = normalizeSchemaNode(schema.additionalProperties as JsonSchema, [...path, "*"]); - normalized.additionalProperties = res.schema ?? (schema.additionalProperties as JsonSchema); - if (res.unsupportedPaths.length > 0) unsupported.add(pathLabel); + if (!isAnySchema(schema.additionalProperties)) { + const res = normalizeSchemaNode(schema.additionalProperties, [...path, "*"]); + normalized.additionalProperties = res.schema ?? (schema.additionalProperties); + if (res.unsupportedPaths.length > 0) {unsupported.add(pathLabel);} } } } else if (type === "array") { @@ -86,7 +86,7 @@ function normalizeSchemaNode( } else { const res = normalizeSchemaNode(itemsSchema, [...path, "*"]); normalized.items = res.schema ?? itemsSchema; - if (res.unsupportedPaths.length > 0) unsupported.add(pathLabel); + if (res.unsupportedPaths.length > 0) {unsupported.add(pathLabel);} } } else if ( type !== "string" && @@ -108,20 +108,20 @@ function normalizeUnion( schema: JsonSchema, path: Array, ): ConfigSchemaAnalysis | null { - if (schema.allOf) return null; + if (schema.allOf) {return null;} const union = schema.anyOf ?? schema.oneOf; - if (!union) return null; + if (!union) {return null;} const literals: unknown[] = []; const remaining: JsonSchema[] = []; let nullable = false; for (const entry of union) { - if (!entry || typeof entry !== "object") return null; + if (!entry || typeof entry !== "object") {return null;} if (Array.isArray(entry.enum)) { const { enumValues, nullable: enumNullable } = normalizeEnum(entry.enum); literals.push(...enumValues); - if (enumNullable) nullable = true; + if (enumNullable) {nullable = true;} continue; } if ("const" in entry) { @@ -167,11 +167,11 @@ function normalizeUnion( return res; } - const primitiveTypes = ["string", "number", "integer", "boolean"]; + const primitiveTypes = new Set(["string", "number", "integer", "boolean"]); if ( remaining.length > 0 && literals.length === 0 && - remaining.every((entry) => entry.type && primitiveTypes.includes(String(entry.type))) + remaining.every((entry) => entry.type && primitiveTypes.has(String(entry.type))) ) { return { schema: { diff --git a/ui/src/ui/views/config-form.node.ts b/ui/src/ui/views/config-form.node.ts index 768db4508c..282a304585 100644 --- a/ui/src/ui/views/config-form.node.ts +++ b/ui/src/ui/views/config-form.node.ts @@ -18,7 +18,7 @@ function isAnySchema(schema: JsonSchema): boolean { } function jsonValue(value: unknown): string { - if (value === undefined) return ""; + if (value === undefined) {return "";} try { return JSON.stringify(value, null, 2) ?? ""; } catch { @@ -131,8 +131,8 @@ export function renderNode(params: { // Check if it's a set of literal values (enum-like) const extractLiteral = (v: JsonSchema): unknown | undefined => { - if (v.const !== undefined) return v.const; - if (v.enum && v.enum.length === 1) return v.enum[0]; + if (v.const !== undefined) {return v.const;} + if (v.enum && v.enum.length === 1) {return v.enum[0];} return undefined; }; const literals = nonNull.map(extractLiteral); @@ -326,7 +326,7 @@ function renderTextInput(params: { onPatch(path, raw); }} @change=${(e: Event) => { - if (inputType === "number") return; + if (inputType === "number") {return;} const raw = (e.target as HTMLInputElement).value; onPatch(path, raw.trim()); }} @@ -469,10 +469,10 @@ function renderObject(params: { const entries = Object.entries(props); // Sort by hint order - const sorted = entries.sort((a, b) => { + const sorted = entries.toSorted((a, b) => { const orderA = hintForPath([...path, a[0]], hints)?.order ?? 0; const orderB = hintForPath([...path, b[0]], hints)?.order ?? 0; - if (orderA !== orderB) return orderA - orderB; + if (orderA !== orderB) {return orderA - orderB;} return a[0].localeCompare(b[0]); }); @@ -498,7 +498,7 @@ function renderObject(params: { ${ allowExtra ? renderMapField({ - schema: additional as JsonSchema, + schema: additional, value: obj, path, hints, @@ -536,7 +536,7 @@ function renderObject(params: { ${ allowExtra ? renderMapField({ - schema: additional as JsonSchema, + schema: additional, value: obj, path, hints, @@ -671,7 +671,7 @@ function renderMapField(params: { class="cfg-map__add" ?disabled=${disabled} @click=${() => { - const next = { ...(value ?? {}) }; + const next = { ...value }; let index = 1; let key = `custom-${index}`; while (key in next) { @@ -708,9 +708,9 @@ function renderMapField(params: { ?disabled=${disabled} @change=${(e: Event) => { const nextKey = (e.target as HTMLInputElement).value.trim(); - if (!nextKey || nextKey === key) return; - const next = { ...(value ?? {}) }; - if (nextKey in next) return; + if (!nextKey || nextKey === key) {return;} + const next = { ...value }; + if (nextKey in next) {return;} next[nextKey] = next[key]; delete next[key]; onPatch(path, next); @@ -760,7 +760,7 @@ function renderMapField(params: { title="Remove entry" ?disabled=${disabled} @click=${() => { - const next = { ...(value ?? {}) }; + const next = { ...value }; delete next[key]; onPatch(path, next); }} diff --git a/ui/src/ui/views/config-form.render.ts b/ui/src/ui/views/config-form.render.ts index ec6eb5dd47..55ce94cd77 100644 --- a/ui/src/ui/views/config-form.render.ts +++ b/ui/src/ui/views/config-form.render.ts @@ -279,49 +279,49 @@ function getSectionIcon(key: string) { } function matchesSearch(key: string, schema: JsonSchema, query: string): boolean { - if (!query) return true; + if (!query) {return true;} const q = query.toLowerCase(); const meta = SECTION_META[key]; // Check key name - if (key.toLowerCase().includes(q)) return true; + if (key.toLowerCase().includes(q)) {return true;} // Check label and description if (meta) { - if (meta.label.toLowerCase().includes(q)) return true; - if (meta.description.toLowerCase().includes(q)) return true; + if (meta.label.toLowerCase().includes(q)) {return true;} + if (meta.description.toLowerCase().includes(q)) {return true;} } return schemaMatches(schema, q); } function schemaMatches(schema: JsonSchema, query: string): boolean { - if (schema.title?.toLowerCase().includes(query)) return true; - if (schema.description?.toLowerCase().includes(query)) return true; - if (schema.enum?.some((value) => String(value).toLowerCase().includes(query))) return true; + if (schema.title?.toLowerCase().includes(query)) {return true;} + if (schema.description?.toLowerCase().includes(query)) {return true;} + if (schema.enum?.some((value) => String(value).toLowerCase().includes(query))) {return true;} if (schema.properties) { for (const [propKey, propSchema] of Object.entries(schema.properties)) { - if (propKey.toLowerCase().includes(query)) return true; - if (schemaMatches(propSchema, query)) return true; + if (propKey.toLowerCase().includes(query)) {return true;} + if (schemaMatches(propSchema, query)) {return true;} } } if (schema.items) { const items = Array.isArray(schema.items) ? schema.items : [schema.items]; for (const item of items) { - if (item && schemaMatches(item, query)) return true; + if (item && schemaMatches(item, query)) {return true;} } } if (schema.additionalProperties && typeof schema.additionalProperties === "object") { - if (schemaMatches(schema.additionalProperties, query)) return true; + if (schemaMatches(schema.additionalProperties, query)) {return true;} } const unions = schema.anyOf ?? schema.oneOf ?? schema.allOf; if (unions) { for (const entry of unions) { - if (entry && schemaMatches(entry, query)) return true; + if (entry && schemaMatches(entry, query)) {return true;} } } @@ -347,16 +347,16 @@ export function renderConfigForm(props: ConfigFormProps) { const activeSection = props.activeSection; const activeSubsection = props.activeSubsection ?? null; - const entries = Object.entries(properties).sort((a, b) => { + const entries = Object.entries(properties).toSorted((a, b) => { const orderA = hintForPath([a[0]], props.uiHints)?.order ?? 50; const orderB = hintForPath([b[0]], props.uiHints)?.order ?? 50; - if (orderA !== orderB) return orderA - orderB; + if (orderA !== orderB) {return orderA - orderB;} return a[0].localeCompare(b[0]); }); const filteredEntries = entries.filter(([key, node]) => { - if (activeSection && key !== activeSection) return false; - if (searchQuery && !matchesSearch(key, node, searchQuery)) return false; + if (activeSection && key !== activeSection) {return false;} + if (searchQuery && !matchesSearch(key, node, searchQuery)) {return false;} return true; }); @@ -398,7 +398,7 @@ export function renderConfigForm(props: ConfigFormProps) { const hint = hintForPath([sectionKey, subsectionKey], props.uiHints); const label = hint?.label ?? node.title ?? humanize(subsectionKey); const description = hint?.help ?? node.description ?? ""; - const sectionValue = (value as Record)[sectionKey]; + const sectionValue = (value)[sectionKey]; const scopedValue = sectionValue && typeof sectionValue === "object" ? (sectionValue as Record)[subsectionKey] @@ -454,7 +454,7 @@ export function renderConfigForm(props: ConfigFormProps) {
${renderNode({ schema: node, - value: (value as Record)[key], + value: (value)[key], path: [key], hints: props.uiHints, unsupported, diff --git a/ui/src/ui/views/config-form.shared.ts b/ui/src/ui/views/config-form.shared.ts index a6a8e24160..ca184ae93e 100644 --- a/ui/src/ui/views/config-form.shared.ts +++ b/ui/src/ui/views/config-form.shared.ts @@ -17,7 +17,7 @@ export type JsonSchema = { }; export function schemaType(schema: JsonSchema): string | undefined { - if (!schema) return undefined; + if (!schema) {return undefined;} if (Array.isArray(schema.type)) { const filtered = schema.type.filter((t) => t !== "null"); return filtered[0] ?? schema.type[0]; @@ -26,8 +26,8 @@ export function schemaType(schema: JsonSchema): string | undefined { } export function defaultValue(schema?: JsonSchema): unknown { - if (!schema) return ""; - if (schema.default !== undefined) return schema.default; + if (!schema) {return "";} + if (schema.default !== undefined) {return schema.default;} const type = schemaType(schema); switch (type) { case "object": @@ -53,12 +53,12 @@ export function pathKey(path: Array): string { export function hintForPath(path: Array, hints: ConfigUiHints) { const key = pathKey(path); const direct = hints[key]; - if (direct) return direct; + if (direct) {return direct;} const segments = key.split("."); for (const [hintKey, hint] of Object.entries(hints)) { - if (!hintKey.includes("*")) continue; + if (!hintKey.includes("*")) {continue;} const hintSegments = hintKey.split("."); - if (hintSegments.length !== segments.length) continue; + if (hintSegments.length !== segments.length) {continue;} let match = true; for (let i = 0; i < segments.length; i += 1) { if (hintSegments[i] !== "*" && hintSegments[i] !== segments[i]) { @@ -66,7 +66,7 @@ export function hintForPath(path: Array, hints: ConfigUiHints) break; } } - if (match) return hint; + if (match) {return hint;} } return undefined; } diff --git a/ui/src/ui/views/config.browser.test.ts b/ui/src/ui/views/config.browser.test.ts index f101661e62..1c05104dcc 100644 --- a/ui/src/ui/views/config.browser.test.ts +++ b/ui/src/ui/views/config.browser.test.ts @@ -60,7 +60,7 @@ describe("config view", () => { const saveButton = Array.from(container.querySelectorAll("button")).find( (btn) => btn.textContent?.trim() === "Save", - ) as HTMLButtonElement | undefined; + ); expect(saveButton).not.toBeUndefined(); expect(saveButton?.disabled).toBe(false); }); @@ -80,7 +80,7 @@ describe("config view", () => { const saveButton = Array.from(container.querySelectorAll("button")).find( (btn) => btn.textContent?.trim() === "Save", - ) as HTMLButtonElement | undefined; + ); expect(saveButton).not.toBeUndefined(); expect(saveButton?.disabled).toBe(true); }); @@ -99,10 +99,10 @@ describe("config view", () => { const saveButton = Array.from(container.querySelectorAll("button")).find( (btn) => btn.textContent?.trim() === "Save", - ) as HTMLButtonElement | undefined; + ); const applyButton = Array.from(container.querySelectorAll("button")).find( (btn) => btn.textContent?.trim() === "Apply", - ) as HTMLButtonElement | undefined; + ); expect(saveButton).not.toBeUndefined(); expect(applyButton).not.toBeUndefined(); expect(saveButton?.disabled).toBe(true); @@ -123,10 +123,10 @@ describe("config view", () => { const saveButton = Array.from(container.querySelectorAll("button")).find( (btn) => btn.textContent?.trim() === "Save", - ) as HTMLButtonElement | undefined; + ); const applyButton = Array.from(container.querySelectorAll("button")).find( (btn) => btn.textContent?.trim() === "Apply", - ) as HTMLButtonElement | undefined; + ); expect(saveButton).not.toBeUndefined(); expect(applyButton).not.toBeUndefined(); expect(saveButton?.disabled).toBe(false); @@ -146,7 +146,7 @@ describe("config view", () => { const btn = Array.from(container.querySelectorAll("button")).find( (b) => b.textContent?.trim() === "Raw", - ) as HTMLButtonElement | undefined; + ); expect(btn).toBeTruthy(); btn?.click(); expect(onFormModeChange).toHaveBeenCalledWith("raw"); @@ -172,7 +172,7 @@ describe("config view", () => { const btn = Array.from(container.querySelectorAll("button")).find( (b) => b.textContent?.trim() === "Gateway", - ) as HTMLButtonElement | undefined; + ); expect(btn).toBeTruthy(); btn?.click(); expect(onSectionChange).toHaveBeenCalledWith("gateway"); @@ -189,9 +189,9 @@ describe("config view", () => { container, ); - const input = container.querySelector(".config-search__input") as HTMLInputElement | null; + const input = container.querySelector(".config-search__input"); expect(input).not.toBeNull(); - if (!input) return; + if (!input) {return;} input.value = "gateway"; input.dispatchEvent(new Event("input", { bubbles: true })); expect(onSearchChange).toHaveBeenCalledWith("gateway"); diff --git a/ui/src/ui/views/config.ts b/ui/src/ui/views/config.ts index d415cf70af..dd9e2c243e 100644 --- a/ui/src/ui/views/config.ts +++ b/ui/src/ui/views/config.ts @@ -299,7 +299,7 @@ function resolveSectionMeta( description?: string; } { const meta = SECTION_META[key]; - if (meta) return meta; + if (meta) {return meta;} return { label: schema?.title ?? humanize(key), description: schema?.description ?? "", @@ -312,7 +312,7 @@ function resolveSubsections(params: { uiHints: ConfigUiHints; }): SubsectionEntry[] { const { key, schema, uiHints } = params; - if (!schema || schemaType(schema) !== "object" || !schema.properties) return []; + if (!schema || schemaType(schema) !== "object" || !schema.properties) {return [];} const entries = Object.entries(schema.properties).map(([subKey, node]) => { const hint = hintForPath([key, subKey], uiHints); const label = hint?.label ?? node.title ?? humanize(subKey); @@ -328,11 +328,11 @@ function computeDiff( original: Record | null, current: Record | null, ): Array<{ path: string; from: unknown; to: unknown }> { - if (!original || !current) return []; + if (!original || !current) {return [];} const changes: Array<{ path: string; from: unknown; to: unknown }> = []; function compare(orig: unknown, curr: unknown, path: string) { - if (orig === curr) return; + if (orig === curr) {return;} if (typeof orig !== typeof curr) { changes.push({ path, from: orig, to: curr }); return; @@ -369,7 +369,7 @@ function truncateValue(value: unknown, maxLen = 40): string { } catch { str = String(value); } - if (str.length <= maxLen) return str; + if (str.length <= maxLen) {return str;} return str.slice(0, maxLen - 3) + "..."; } @@ -392,7 +392,7 @@ export function renderConfig(props: ConfigProps) { const activeSectionSchema = props.activeSection && analysis.schema && schemaType(analysis.schema) === "object" - ? (analysis.schema.properties?.[props.activeSection] as JsonSchema | undefined) + ? (analysis.schema.properties?.[props.activeSection]) : undefined; const activeSectionMeta = props.activeSection ? resolveSectionMeta(props.activeSection, activeSectionSchema) diff --git a/ui/src/ui/views/cron.test.ts b/ui/src/ui/views/cron.test.ts index 31a93b23be..21d70f11d1 100644 --- a/ui/src/ui/views/cron.test.ts +++ b/ui/src/ui/views/cron.test.ts @@ -63,7 +63,7 @@ describe("cron view", () => { container, ); - const row = container.querySelector(".list-item-clickable") as HTMLElement | null; + const row = container.querySelector(".list-item-clickable"); expect(row).not.toBeNull(); row?.dispatchEvent(new MouseEvent("click", { bubbles: true })); diff --git a/ui/src/ui/views/cron.ts b/ui/src/ui/views/cron.ts index ede5fd0455..db80f0d251 100644 --- a/ui/src/ui/views/cron.ts +++ b/ui/src/ui/views/cron.ts @@ -38,16 +38,16 @@ function buildChannelOptions(props: CronProps): string[] { } const seen = new Set(); return options.filter((value) => { - if (seen.has(value)) return false; + if (seen.has(value)) {return false;} seen.add(value); return true; }); } function resolveChannelLabel(props: CronProps, channel: string): string { - if (channel === "last") return "last"; + if (channel === "last") {return "last";} const meta = props.channelMeta?.find((entry) => entry.id === channel); - if (meta?.label) return meta.label; + if (meta?.label) {return meta.label;} return props.channelLabels?.[channel] ?? channel; } @@ -213,7 +213,7 @@ export function renderCron(props: CronProps) { @change=${(e: Event) => props.onFormChange({ channel: (e.target as HTMLSelectElement) - .value as CronFormState["channel"], + .value, })} > ${channelOptions.map( diff --git a/ui/src/ui/views/exec-approval.ts b/ui/src/ui/views/exec-approval.ts index 33efc947ff..9fa745c66a 100644 --- a/ui/src/ui/views/exec-approval.ts +++ b/ui/src/ui/views/exec-approval.ts @@ -4,21 +4,21 @@ import type { AppViewState } from "../app-view-state"; function formatRemaining(ms: number): string { const remaining = Math.max(0, ms); const totalSeconds = Math.floor(remaining / 1000); - if (totalSeconds < 60) return `${totalSeconds}s`; + if (totalSeconds < 60) {return `${totalSeconds}s`;} const minutes = Math.floor(totalSeconds / 60); - if (minutes < 60) return `${minutes}m`; + if (minutes < 60) {return `${minutes}m`;} const hours = Math.floor(minutes / 60); return `${hours}h`; } function renderMetaRow(label: string, value?: string | null) { - if (!value) return nothing; + if (!value) {return nothing;} return html`
${label}${value}
`; } export function renderExecApprovalPrompt(state: AppViewState) { const active = state.execApprovalQueue[0]; - if (!active) return nothing; + if (!active) {return nothing;} const request = active.request; const remainingMs = active.expiresAtMs - Date.now(); const remaining = remainingMs > 0 ? `expires in ${formatRemaining(remainingMs)}` : "expired"; diff --git a/ui/src/ui/views/gateway-url-confirmation.ts b/ui/src/ui/views/gateway-url-confirmation.ts index 39c6f9d051..4ad44e88bf 100644 --- a/ui/src/ui/views/gateway-url-confirmation.ts +++ b/ui/src/ui/views/gateway-url-confirmation.ts @@ -3,7 +3,7 @@ import type { AppViewState } from "../app-view-state"; export function renderGatewayUrlConfirmation(state: AppViewState) { const { pendingGatewayUrl } = state; - if (!pendingGatewayUrl) return nothing; + if (!pendingGatewayUrl) {return nothing;} return html`