From 0ebeee8b0de41611a59500d257ae78b513cbd2d4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 10 Apr 2026 20:56:08 +0100 Subject: [PATCH] chore: enable consistent-return --- .oxlintrc.json | 2 +- CHANGELOG.md | 1 + extensions/active-memory/index.ts | 12 ++--- .../src/browser/routes/agent.act.normalize.ts | 1 + .../browser/src/browser/routes/agent.act.ts | 1 + .../src/cli/browser-cli.test-support.ts | 2 +- .../discord/src/actions/runtime.moderation.ts | 1 + extensions/discord/src/subagent-hooks.ts | 34 +++++++++--- extensions/feishu/src/subagent-hooks.ts | 32 +++++++++--- .../matrix/src/matrix/monitor/handler.ts | 52 +++++++++---------- extensions/memory-lancedb/index.ts | 9 ++-- extensions/memory-wiki/src/compile.ts | 2 + .../nextcloud-talk/src/setup-surface.ts | 2 +- extensions/qa-lab/src/bus-queries.ts | 1 + extensions/qqbot/src/outbound-deliver.ts | 1 + extensions/signal/src/setup-surface.ts | 5 +- extensions/slack/src/setup-core.ts | 2 +- extensions/thread-ownership/index.ts | 14 ++--- .../tlon/src/monitor/approval-runtime.ts | 1 + extensions/tlon/src/monitor/approval.ts | 2 + extensions/webhooks/src/http.ts | 1 + extensions/zalo/src/monitor.ts | 14 ++--- scripts/gh-read.ts | 1 + scripts/lib/ts-topology/analyze.ts | 1 + scripts/lib/ts-topology/scope.ts | 1 + scripts/process-warning-filter.mjs | 3 +- src/agents/bash-tools.exec-runtime.ts | 1 + .../bash-tools.exec.approval-id.test.ts | 1 + src/agents/cli-auth-epoch.ts | 1 + src/agents/google-transport-stream.ts | 1 + src/agents/model-fallback.ts | 4 +- ...i-embedded-subscribe.handlers.lifecycle.ts | 5 +- ...pi-embedded-subscribe.handlers.messages.ts | 4 +- .../pi-embedded-subscribe.handlers.tools.ts | 5 +- src/agents/tool-display-exec-shell.ts | 1 + src/agents/tools/nodes-tool-commands.ts | 1 + src/agents/tools/nodes-tool-media.ts | 1 + .../tools/web-search-provider-common.ts | 1 + .../reply/agent-runner-execution.ts | 12 +++-- src/auto-reply/reply/dispatch-from-config.ts | 25 +++++---- src/cli/daemon-cli/lifecycle.ts | 6 ++- src/commands/backup-shared.ts | 1 + src/commands/doctor-security.ts | 2 + src/config/plugin-auto-enable.shared.ts | 1 + ...runs-one-shot-main-job-disables-it.test.ts | 2 + src/image-generation/runtime.ts | 2 +- src/infra/boundary-file-read.ts | 1 + src/infra/device-pairing.ts | 1 + src/infra/heartbeat-events.ts | 1 + src/infra/shell-wrapper-resolution.ts | 1 + src/infra/warning-filter.ts | 3 +- src/logging/timestamps.ts | 1 + src/music-generation/runtime.ts | 2 +- src/plugin-sdk/provider-model-shared.ts | 1 + src/plugin-sdk/provider-stream.ts | 1 + src/plugin-sdk/provider-tools.ts | 1 + .../provider-web-search-contract-fields.ts | 1 + src/plugins/contracts/registry.ts | 1 + src/plugins/discovery.test.ts | 3 ++ src/plugins/marketplace.ts | 1 + .../runtime/runtime-registry-loader.ts | 2 + src/secrets/resolve.ts | 2 +- src/video-generation/runtime.ts | 2 +- ui/src/ui/app-render.ts | 12 +++-- ui/src/ui/app-settings.ts | 12 +++-- ui/src/ui/controllers/agents.ts | 4 +- ui/src/ui/markdown.ts | 1 + ui/src/ui/views/skills.ts | 1 + 68 files changed, 223 insertions(+), 107 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 4754b9ff177..06d7dad237a 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -17,7 +17,7 @@ "oxc/no-accumulating-spread": "off", "oxc/no-async-endpoint-handlers": "off", "oxc/no-map-spread": "off", - "typescript/consistent-return": "off", + "typescript/consistent-return": "error", "typescript/no-explicit-any": "error", "typescript/no-extraneous-class": "off", "typescript/no-unnecessary-type-conversion": "off", diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c20b8ba953..43a9346d126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -134,6 +134,7 @@ Docs: https://docs.openclaw.ai - Hooks/security: mark agent hook system events as untrusted and sanitize hook display names before cron metadata reuse. (#64372) Thanks @eleqtrizit. - Media/security: honor sender-scoped `toolsBySender` policy for outbound host-media reads so denied senders cannot trigger host file disclosure via attachment hydration. (#64459) Thanks @eleqtrizit. - Browser/security: reject strict-policy hostname navigation unless the hostname is an explicit allowlist exception or IP literal, and route CDP HTTP discovery through the pinned SSRF fetch path. (#64367) Thanks @eleqtrizit. + ## 2026.4.9 ### Changes diff --git a/extensions/active-memory/index.ts b/extensions/active-memory/index.ts index f9a3b029215..6dc64794db1 100644 --- a/extensions/active-memory/index.ts +++ b/extensions/active-memory/index.ts @@ -1496,7 +1496,7 @@ export default definePluginEntry({ agentId: effectiveAgentId, sessionKey: resolvedSessionKey, }); - return; + return undefined; } if (!isEnabledForAgent(config, effectiveAgentId)) { await persistPluginStatusLines({ @@ -1504,7 +1504,7 @@ export default definePluginEntry({ agentId: effectiveAgentId, sessionKey: resolvedSessionKey, }); - return; + return undefined; } if (!isEligibleInteractiveSession(ctx)) { await persistPluginStatusLines({ @@ -1512,7 +1512,7 @@ export default definePluginEntry({ agentId: effectiveAgentId, sessionKey: resolvedSessionKey, }); - return; + return undefined; } if ( !isAllowedChatType(config, { @@ -1526,7 +1526,7 @@ export default definePluginEntry({ agentId: effectiveAgentId, sessionKey: resolvedSessionKey, }); - return; + return undefined; } const query = buildQuery({ latestUserMessage: event.prompt, @@ -1544,11 +1544,11 @@ export default definePluginEntry({ currentModelId: ctx.modelId, }); if (!result.summary) { - return; + return undefined; } const metadata = buildMetadata(result.summary); if (!metadata) { - return; + return undefined; } return { prependSystemContext: ACTIVE_MEMORY_PLUGIN_GUIDANCE, diff --git a/extensions/browser/src/browser/routes/agent.act.normalize.ts b/extensions/browser/src/browser/routes/agent.act.normalize.ts index 76a05605fdc..50a16e85b25 100644 --- a/extensions/browser/src/browser/routes/agent.act.normalize.ts +++ b/extensions/browser/src/browser/routes/agent.act.normalize.ts @@ -318,4 +318,5 @@ export function normalizeActRequest( }; } } + throw new Error("Unsupported browser act kind"); } diff --git a/extensions/browser/src/browser/routes/agent.act.ts b/extensions/browser/src/browser/routes/agent.act.ts index f02b7b42a0f..9ebe491ff12 100644 --- a/extensions/browser/src/browser/routes/agent.act.ts +++ b/extensions/browser/src/browser/routes/agent.act.ts @@ -307,6 +307,7 @@ function getExistingSessionUnsupportedMessage(action: BrowserActRequest): string case "close": return null; } + throw new Error("Unsupported browser act kind"); } export function registerBrowserAgentActRoutes( diff --git a/extensions/browser/src/cli/browser-cli.test-support.ts b/extensions/browser/src/cli/browser-cli.test-support.ts index 04f2f33aad5..ac5a53f4c84 100644 --- a/extensions/browser/src/cli/browser-cli.test-support.ts +++ b/extensions/browser/src/cli/browser-cli.test-support.ts @@ -21,7 +21,7 @@ export function createBrowserProgram(params?: { withGatewayUrl?: boolean }): { if (params?.withGatewayUrl) { browser.option("--url ", "Gateway WebSocket URL"); } - const parentOpts = (cmd: Command) => cmd.parent?.opts?.() as BrowserParentOpts; + const parentOpts = (cmd: Command): BrowserParentOpts => cmd.parent?.opts?.() as BrowserParentOpts; return { program, browser, parentOpts }; } diff --git a/extensions/discord/src/actions/runtime.moderation.ts b/extensions/discord/src/actions/runtime.moderation.ts index fed41d40dad..0d3a51c2c55 100644 --- a/extensions/discord/src/actions/runtime.moderation.ts +++ b/extensions/discord/src/actions/runtime.moderation.ts @@ -128,4 +128,5 @@ export async function handleDiscordModerationAction( return jsonResult({ ok: true }); } } + throw new Error("Unsupported Discord moderation action"); } diff --git a/extensions/discord/src/subagent-hooks.ts b/extensions/discord/src/subagent-hooks.ts index 43523747292..2e6e7a54fbc 100644 --- a/extensions/discord/src/subagent-hooks.ts +++ b/extensions/discord/src/subagent-hooks.ts @@ -52,6 +52,22 @@ type DiscordSubagentDeliveryTargetEvent = { }; }; +type DiscordSubagentSpawningResult = + | { status: "ok"; threadBindingReady?: boolean } + | { status: "error"; error: string } + | undefined; + +type DiscordSubagentDeliveryTargetResult = + | { + origin: { + channel: "discord"; + accountId?: string; + to: string; + threadId?: string | number; + }; + } + | undefined; + function normalizeThreadBindingTargetKind(raw?: string): ThreadBindingTargetKind | undefined { const normalized = normalizeOptionalLowercaseString(raw); if (normalized === "subagent" || normalized === "acp") { @@ -84,13 +100,13 @@ function resolveThreadBindingFlags(api: OpenClawPluginApi, accountId?: string) { export async function handleDiscordSubagentSpawning( api: OpenClawPluginApi, event: DiscordSubagentSpawningEvent, -) { +): Promise { if (!event.threadRequested) { - return; + return undefined; } const channel = normalizeOptionalLowercaseString(event.requester?.channel); if (channel !== "discord") { - return; + return undefined; } const threadBindingFlags = resolveThreadBindingFlags(api, event.requester?.accountId); if (!threadBindingFlags.enabled) { @@ -145,13 +161,15 @@ export function handleDiscordSubagentEnded(event: DiscordSubagentEndedEvent) { }); } -export function handleDiscordSubagentDeliveryTarget(event: DiscordSubagentDeliveryTargetEvent) { +export function handleDiscordSubagentDeliveryTarget( + event: DiscordSubagentDeliveryTargetEvent, +): DiscordSubagentDeliveryTargetResult { if (!event.expectsCompletionMessage) { - return; + return undefined; } const requesterChannel = normalizeOptionalLowercaseString(event.requesterOrigin?.channel); if (requesterChannel !== "discord") { - return; + return undefined; } const requesterAccountId = event.requesterOrigin?.accountId?.trim(); const requesterThreadId = @@ -164,7 +182,7 @@ export function handleDiscordSubagentDeliveryTarget(event: DiscordSubagentDelive targetKind: "subagent", }); if (bindings.length === 0) { - return; + return undefined; } let binding: (typeof bindings)[number] | undefined; @@ -183,7 +201,7 @@ export function handleDiscordSubagentDeliveryTarget(event: DiscordSubagentDelive binding = bindings[0]; } if (!binding) { - return; + return undefined; } return { origin: { diff --git a/extensions/feishu/src/subagent-hooks.ts b/extensions/feishu/src/subagent-hooks.ts index d50a7c00a3b..251c38fb2dc 100644 --- a/extensions/feishu/src/subagent-hooks.ts +++ b/extensions/feishu/src/subagent-hooks.ts @@ -270,16 +270,32 @@ type FeishuSubagentEndedEvent = { targetSessionKey: string; }; +type FeishuSubagentSpawningResult = + | { status: "ok"; threadBindingReady?: boolean } + | { status: "error"; error: string } + | undefined; + +type FeishuSubagentDeliveryTargetResult = + | { + origin: { + channel: "feishu"; + accountId?: string; + to?: string; + threadId?: string | number; + }; + } + | undefined; + export async function handleFeishuSubagentSpawning( event: FeishuSubagentSpawningEvent, ctx: FeishuSubagentContext, -) { +): Promise { if (!event.threadRequested) { - return; + return undefined; } const requesterChannel = normalizeOptionalLowercaseString(event.requester?.channel); if (requesterChannel !== "feishu") { - return; + return undefined; } const manager = getFeishuThreadBindingManager(event.requester?.accountId); @@ -341,13 +357,15 @@ export async function handleFeishuSubagentSpawning( } } -export function handleFeishuSubagentDeliveryTarget(event: FeishuSubagentDeliveryTargetEvent) { +export function handleFeishuSubagentDeliveryTarget( + event: FeishuSubagentDeliveryTargetEvent, +): FeishuSubagentDeliveryTargetResult { if (!event.expectsCompletionMessage) { - return; + return undefined; } const requesterChannel = normalizeOptionalLowercaseString(event.requesterOrigin?.channel); if (requesterChannel !== "feishu") { - return; + return undefined; } const binding = resolveMatchingChildBinding({ @@ -360,7 +378,7 @@ export function handleFeishuSubagentDeliveryTarget(event: FeishuSubagentDelivery }, }); if (!binding) { - return; + return undefined; } return { diff --git a/extensions/matrix/src/matrix/monitor/handler.ts b/extensions/matrix/src/matrix/monitor/handler.ts index 73711345710..009977f1736 100644 --- a/extensions/matrix/src/matrix/monitor/handler.ts +++ b/extensions/matrix/src/matrix/monitor/handler.ts @@ -456,18 +456,18 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam const readIngressPrefix = async () => { const selfUserId = await client.getUserId(); if (senderId === selfUserId) { - return; + return undefined; } if (dropPreStartupMessages) { if (typeof eventTs === "number" && eventTs < startupMs - startupGraceMs) { - return; + return undefined; } if ( typeof eventTs !== "number" && typeof eventAge === "number" && eventAge > startupGraceMs ) { - return; + return undefined; } } @@ -481,7 +481,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam }) ) { logVerboseMessage(`matrix: skip verification/system room message room=${roomId}`); - return; + return undefined; } const locationPayload: MatrixLocationPayload | null = resolveMatrixLocation({ @@ -491,13 +491,13 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam const relates = content["m.relates_to"]; if (relates && "rel_type" in relates && relates.rel_type === RelationType.Replace) { - return; + return undefined; } if (eventId && inboundDeduper) { claimedInboundEvent = inboundDeduper.claimEvent({ roomId, eventId }); if (!claimedInboundEvent) { logVerboseMessage(`matrix: skip duplicate inbound event room=${roomId} id=${eventId}`); - return; + return undefined; } } @@ -520,7 +520,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam const { locationPayload, selfUserId } = params; if (isRoom && groupPolicy === "disabled") { await commitInboundEventIfClaimed(); - return; + return undefined; } const roomInfoForConfig = @@ -553,24 +553,24 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam `matrix: drop configured bot sender=${senderId} (allowBots=false${isDirectMessage ? "" : `, ${roomMatchMeta}`})`, ); await commitInboundEventIfClaimed(); - return; + return undefined; } if (isRoom && roomConfig && !roomConfigInfo?.allowed) { logVerboseMessage(`matrix: room disabled room=${roomId} (${roomMatchMeta})`); await commitInboundEventIfClaimed(); - return; + return undefined; } if (isRoom && groupPolicy === "allowlist") { if (!roomConfigInfo?.allowlistConfigured) { logVerboseMessage(`matrix: drop room message (no allowlist, ${roomMatchMeta})`); await commitInboundEventIfClaimed(); - return; + return undefined; } if (!roomConfig) { logVerboseMessage(`matrix: drop room message (not in allowlist, ${roomMatchMeta})`); await commitInboundEventIfClaimed(); - return; + return undefined; } } @@ -602,7 +602,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam if (isDirectMessage) { if (!dmEnabled || dmPolicy === "disabled") { await commitInboundEventIfClaimed(); - return; + return undefined; } if (dmPolicy !== "open") { const allowMatchMeta = formatAllowlistMatchMeta(directAllowMatch); @@ -643,7 +643,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam logVerboseMessage( `matrix pairing reply failed for ${senderId}: ${String(err)}`, ); - return; + return undefined; } } else { logVerboseMessage( @@ -658,7 +658,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam ); await commitInboundEventIfClaimed(); } - return; + return undefined; } } } @@ -670,7 +670,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam )})`, ); await commitInboundEventIfClaimed(); - return; + return undefined; } if ( isRoom && @@ -686,7 +686,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam )})`, ); await commitInboundEventIfClaimed(); - return; + return undefined; } if (isRoom) { logVerboseMessage(`matrix: allow room ${roomId} (${roomMatchMeta})`); @@ -708,7 +708,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam logVerboseMessage, }); await commitInboundEventIfClaimed(); - return; + return undefined; } let pollSnapshotPromise: Promise | null = null; @@ -748,7 +748,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam : ""; if (!mentionPrecheckText && !mediaUrl && !isPollEvent) { await commitInboundEventIfClaimed(); - return; + return undefined; } const _messageId = event.event_id ?? ""; @@ -797,7 +797,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam `matrix: drop configured bot sender=${senderId} (allowBots=mentions, missing mention, ${roomMatchMeta})`, ); await commitInboundEventIfClaimed(); - return; + return undefined; } const allowTextCommands = core.channel.commands.shouldHandleTextCommands({ cfg, @@ -823,7 +823,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam target: senderId, }); await commitInboundEventIfClaimed(); - return; + return undefined; } const shouldRequireMention = isRoom ? roomConfig?.autoReply === true @@ -856,13 +856,13 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam } logger.info("skipping room message", { roomId, reason: "no-mention" }); await commitInboundEventIfClaimed(); - return; + return undefined; } if (isPollEvent) { const pollSnapshot = await getPollSnapshot(); if (!pollSnapshot) { - return; + return undefined; } content = { msgtype: "m.text", @@ -935,7 +935,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam }); if (!bodyText) { await commitInboundEventIfClaimed(); - return; + return undefined; } const senderName = await getSenderName(); if (_configuredBinding) { @@ -950,7 +950,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam reason: "configured ACP binding unavailable", target: _configuredBinding.spec.conversationId, }); - return; + return undefined; } } if (_runtimeBindingId) { @@ -997,7 +997,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam ? await runRoomIngress(roomId, async () => { const prefix = await readIngressPrefix(); if (!prefix) { - return; + return undefined; } if (prefix.isDirectMessage) { return { deferredPrefix: prefix } as const; @@ -1013,7 +1013,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam : await (async () => { const prefix = await readIngressPrefix(); if (!prefix) { - return; + return undefined; } return await continueIngress(prefix); })(); diff --git a/extensions/memory-lancedb/index.ts b/extensions/memory-lancedb/index.ts index 96cefc42611..e73835cddbb 100644 --- a/extensions/memory-lancedb/index.ts +++ b/extensions/memory-lancedb/index.ts @@ -40,6 +40,8 @@ type MemorySearchResult = { score: number; }; +type LegacyBeforeAgentStartContext = { prependContext: string } | undefined; + // ============================================================================ // LanceDB Provider // ============================================================================ @@ -536,9 +538,9 @@ export default definePluginEntry({ // Auto-recall: inject relevant memories before agent starts if (cfg.autoRecall) { - api.on("before_agent_start", async (event) => { + api.on("before_agent_start", async (event): Promise => { if (!event.prompt || event.prompt.length < 5) { - return; + return undefined; } try { @@ -546,7 +548,7 @@ export default definePluginEntry({ const results = await db.search(vector, 3, 0.3); if (results.length === 0) { - return; + return undefined; } api.logger.info?.(`memory-lancedb: injecting ${results.length} memories into context`); @@ -559,6 +561,7 @@ export default definePluginEntry({ } catch (err) { api.logger.warn(`memory-lancedb: recall failed: ${String(err)}`); } + return undefined; }); } diff --git a/extensions/memory-wiki/src/compile.ts b/extensions/memory-wiki/src/compile.ts index 684ba87d25e..cae5d5bba46 100644 --- a/extensions/memory-wiki/src/compile.ts +++ b/extensions/memory-wiki/src/compile.ts @@ -289,6 +289,7 @@ function formatFreshnessLabel(freshness: WikiFreshness): string { case "unknown": return freshness.reason; } + throw new Error("Unsupported wiki freshness level"); } function formatClaimIdentity(claim: WikiClaimHealth): string { @@ -761,6 +762,7 @@ function rankFreshnessLevel(level: WikiFreshnessLevel): number { case "unknown": return 0; } + throw new Error("Unsupported wiki freshness level"); } function sortClaims(page: WikiPageSummary): WikiClaim[] { diff --git a/extensions/nextcloud-talk/src/setup-surface.ts b/extensions/nextcloud-talk/src/setup-surface.ts index b70623e8677..8d4e7ca16f0 100644 --- a/extensions/nextcloud-talk/src/setup-surface.ts +++ b/extensions/nextcloud-talk/src/setup-surface.ts @@ -64,7 +64,7 @@ export const nextcloudTalkSetupWizard: ChannelSetupWizard = { initialValue: hasApiCredentials, }); if (!configureApiCredentials) { - return; + return undefined; } return { credentialValues: { diff --git a/extensions/qa-lab/src/bus-queries.ts b/extensions/qa-lab/src/bus-queries.ts index 38670ade771..b0f95639fb8 100644 --- a/extensions/qa-lab/src/bus-queries.ts +++ b/extensions/qa-lab/src/bus-queries.ts @@ -73,6 +73,7 @@ export function cloneEvent(event: QaBusEvent): QaBusEvent { case "thread-created": return { ...event, thread: { ...event.thread } }; } + throw new Error("Unsupported QA bus event kind"); } export function buildQaBusSnapshot(params: { diff --git a/extensions/qqbot/src/outbound-deliver.ts b/extensions/qqbot/src/outbound-deliver.ts index 1266ea23def..e6a829dc006 100644 --- a/extensions/qqbot/src/outbound-deliver.ts +++ b/extensions/qqbot/src/outbound-deliver.ts @@ -501,6 +501,7 @@ async function sendQQBotTextChunk(params: { if (event.channelId) { return await sendChannelMessage(token, event.channelId, text, event.messageId); } + return undefined; } async function sendTextChunks( diff --git a/extensions/signal/src/setup-surface.ts b/extensions/signal/src/setup-surface.ts index e7485009026..a918f3b178d 100644 --- a/extensions/signal/src/setup-surface.ts +++ b/extensions/signal/src/setup-surface.ts @@ -42,7 +42,7 @@ export const signalSetupWizard: ChannelSetupWizard = { }), prepare: async ({ cfg, accountId, credentialValues, runtime, prompter, options }) => { if (!options?.allowSignalInstall) { - return; + return undefined; } const currentCliPath = (typeof credentialValues.cliPath === "string" ? credentialValues.cliPath : undefined) ?? @@ -56,7 +56,7 @@ export const signalSetupWizard: ChannelSetupWizard = { initialValue: !cliDetected, }); if (!wantsInstall) { - return; + return undefined; } try { const result = await installSignalCli(runtime); @@ -74,6 +74,7 @@ export const signalSetupWizard: ChannelSetupWizard = { } catch (error) { await prompter.note(`signal-cli install failed: ${String(error)}`, "Signal"); } + return undefined; }, credentials: [], textInputs: [ diff --git a/extensions/slack/src/setup-core.ts b/extensions/slack/src/setup-core.ts index aa711dc3fc6..beedcd9cf27 100644 --- a/extensions/slack/src/setup-core.ts +++ b/extensions/slack/src/setup-core.ts @@ -257,7 +257,7 @@ export function createSlackSetupWizardBase(handlers: { }), finalize: async ({ cfg, accountId, options, prompter }) => { if (hasSlackInteractiveRepliesConfig(cfg, accountId)) { - return; + return undefined; } if (options?.quickstartDefaults) { return { diff --git a/extensions/thread-ownership/index.ts b/extensions/thread-ownership/index.ts index ebd8df2a20c..28fd39ecab1 100644 --- a/extensions/thread-ownership/index.ts +++ b/extensions/thread-ownership/index.ts @@ -13,6 +13,7 @@ type ThreadOwnershipConfig = { }; type AgentEntry = NonNullable["list"]>[number]; +type ThreadOwnershipMessageSendingResult = { cancel: true } | undefined; // In-memory set of {channel}:{thread} keys where this agent was @-mentioned. // Entries expire after 5 minutes. @@ -86,23 +87,23 @@ export default definePluginEntry({ } }); - api.on("message_sending", async (event, ctx) => { + api.on("message_sending", async (event, ctx): Promise => { if (ctx.channelId !== "slack") { - return; + return undefined; } const threadTs = (event.metadata?.threadTs as string) ?? ""; const channelId = (event.metadata?.channelId as string) ?? event.to; if (!threadTs) { - return; + return undefined; } if (abTestChannels.size > 0 && !abTestChannels.has(channelId)) { - return; + return undefined; } cleanExpiredMentions(); if (mentionedThreads.has(`${channelId}:${threadTs}`)) { - return; + return undefined; } try { @@ -122,7 +123,7 @@ export default definePluginEntry({ try { if (resp.ok) { - return; + return undefined; } if (resp.status === 409) { const body = (await resp.json()) as { owner?: string }; @@ -140,6 +141,7 @@ export default definePluginEntry({ `thread-ownership: ownership check failed (${String(err)}), allowing send`, ); } + return undefined; }); }, }); diff --git a/extensions/tlon/src/monitor/approval-runtime.ts b/extensions/tlon/src/monitor/approval-runtime.ts index 9482a01c299..a0ec82a2f7d 100644 --- a/extensions/tlon/src/monitor/approval-runtime.ts +++ b/extensions/tlon/src/monitor/approval-runtime.ts @@ -352,6 +352,7 @@ export function createTlonApprovalRuntime(params: { return true; } } + throw new Error("Unsupported Tlon admin command"); }; return { diff --git a/extensions/tlon/src/monitor/approval.ts b/extensions/tlon/src/monitor/approval.ts index 2e8376530e3..700284cc375 100644 --- a/extensions/tlon/src/monitor/approval.ts +++ b/extensions/tlon/src/monitor/approval.ts @@ -92,6 +92,7 @@ export function formatApprovalRequest(approval: PendingApproval): string { `(ID: ${approval.id})` ); } + throw new Error("Unsupported approval type"); } export type ApprovalResponse = { @@ -211,6 +212,7 @@ export function formatApprovalConfirmation( } return `${actionText} group invite from ${approval.requestingShip} to ${approval.groupFlag}.`; } + throw new Error("Unsupported approval type"); } // ============================================================================ diff --git a/extensions/webhooks/src/http.ts b/extensions/webhooks/src/http.ts index 1d8d4ef9bba..dd0550505ae 100644 --- a/extensions/webhooks/src/http.ts +++ b/extensions/webhooks/src/http.ts @@ -658,6 +658,7 @@ async function executeWebhookAction(params: { }; } } + throw new Error("Unsupported webhook action"); } export function createTaskFlowWebhookRequestHandler(params: { diff --git a/extensions/zalo/src/monitor.ts b/extensions/zalo/src/monitor.ts index 84d3f769018..c08f0f34f7a 100644 --- a/extensions/zalo/src/monitor.ts +++ b/extensions/zalo/src/monitor.ts @@ -173,9 +173,9 @@ function startPollingLoop(params: ZaloPollingLoopParams) { runtime.log?.(`[${account.accountId}] Zalo polling loop started timeout=${String(pollTimeout)}s`); - const poll = async () => { + const poll = async (): Promise => { if (isStopped() || abortSignal.aborted) { - return; + return undefined; } try { @@ -209,7 +209,7 @@ async function processUpdate(params: ZaloUpdateProcessingParams): Promise const { event_name, message } = update; const sharedContext = { token, account, config, runtime, core, statusSink, fetcher }; if (!message) { - return; + return undefined; } switch (event_name) { @@ -245,7 +245,7 @@ async function handleTextMessage( const { message } = params; const { text } = message; if (!text?.trim()) { - return; + return undefined; } await processMessageWithPipeline({ @@ -350,7 +350,7 @@ async function authorizeZaloMessage( } else if (groupAccess.reason === "sender_not_allowlisted") { logVerbose(core, runtime, `zalo: drop group sender ${senderId} (groupPolicy=allowlist)`); } - return; + return undefined; } } @@ -376,7 +376,7 @@ async function authorizeZaloMessage( }); if (directDmOutcome === "disabled") { logVerbose(core, runtime, `Blocked zalo DM from ${senderId} (dmPolicy=disabled)`); - return; + return undefined; } if (directDmOutcome === "unauthorized") { if (dmPolicy === "pairing") { @@ -409,7 +409,7 @@ async function authorizeZaloMessage( `Blocked unauthorized zalo sender ${senderId} (dmPolicy=${dmPolicy})`, ); } - return; + return undefined; } return { diff --git a/scripts/gh-read.ts b/scripts/gh-read.ts index 70749348dd7..89c47192a4f 100644 --- a/scripts/gh-read.ts +++ b/scripts/gh-read.ts @@ -193,6 +193,7 @@ async function resolveInstallation( fail( `missing repo context; pass -R owner/repo, set GH_REPO, or set ${INSTALLATION_ID_ENV} for a direct installation lookup`, ); + throw new Error("unreachable"); } async function createInstallationToken( diff --git a/scripts/lib/ts-topology/analyze.ts b/scripts/lib/ts-topology/analyze.ts index 83d4814f567..0c07628f380 100644 --- a/scripts/lib/ts-topology/analyze.ts +++ b/scripts/lib/ts-topology/analyze.ts @@ -413,4 +413,5 @@ export function filterRecordsForReport( case "public-surface-usage": return records; } + throw new Error("Unsupported topology report"); } diff --git a/scripts/lib/ts-topology/scope.ts b/scripts/lib/ts-topology/scope.ts index dee2ef82320..ca53c6e7680 100644 --- a/scripts/lib/ts-topology/scope.ts +++ b/scripts/lib/ts-topology/scope.ts @@ -72,6 +72,7 @@ function extractOwner(relPath: string): string | null { case "test": return null; } + throw new Error("Unsupported topology scope"); } function extractExtensionId(relPath: string): string | null { diff --git a/scripts/process-warning-filter.mjs b/scripts/process-warning-filter.mjs index f79b3b6b62c..60eb543e13a 100644 --- a/scripts/process-warning-filter.mjs +++ b/scripts/process-warning-filter.mjs @@ -25,7 +25,8 @@ export function installProcessWarningFilter() { return; } - return Reflect.apply(originalEmitWarning, process, args); + Reflect.apply(originalEmitWarning, process, args); + return; }; globalThis[warningFilterKey] = { installed: true }; diff --git a/src/agents/bash-tools.exec-runtime.ts b/src/agents/bash-tools.exec-runtime.ts index a636eee886c..674a0709e6c 100644 --- a/src/agents/bash-tools.exec-runtime.ts +++ b/src/agents/bash-tools.exec-runtime.ts @@ -465,6 +465,7 @@ export function formatExecFailureReason(params: { case "aborted": return "Command aborted before exit code was captured"; } + throw new Error("Unsupported exec failure kind"); } export function buildExecExitOutcome(params: { diff --git a/src/agents/bash-tools.exec.approval-id.test.ts b/src/agents/bash-tools.exec.approval-id.test.ts index aa215ff9c1a..d27ce0b26c4 100644 --- a/src/agents/bash-tools.exec.approval-id.test.ts +++ b/src/agents/bash-tools.exec.approval-id.test.ts @@ -285,6 +285,7 @@ describe("exec approvals", () => { invokeParams = params; return { payload: { success: true, stdout: "ok" } }; } + return undefined; }, }); diff --git a/src/agents/cli-auth-epoch.ts b/src/agents/cli-auth-epoch.ts index 23170739ea4..3b7721c207b 100644 --- a/src/agents/cli-auth-epoch.ts +++ b/src/agents/cli-auth-epoch.ts @@ -101,6 +101,7 @@ function encodeAuthProfileCredential(credential: AuthProfileCredential): string credential.managedBy ?? null, ]); } + throw new Error("Unsupported auth profile credential type"); } function getLocalCliCredentialFingerprint(provider: string): string | undefined { diff --git a/src/agents/google-transport-stream.ts b/src/agents/google-transport-stream.ts index 56d5e257137..d133942697b 100644 --- a/src/agents/google-transport-stream.ts +++ b/src/agents/google-transport-stream.ts @@ -209,6 +209,7 @@ function resolveThinkingLevel(level: ThinkingLevel, modelId: string): GoogleThin case "xhigh": return "HIGH"; } + throw new Error("Unsupported thinking level"); } function getDisabledThinkingConfig(modelId: string): Record { diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index 2e1c7b3f4ab..34a0efade34 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -883,7 +883,7 @@ export async function runWithModelFallback(params: { } } - throwFallbackFailureSummary({ + return throwFallbackFailureSummary({ attempts, candidates, lastError, @@ -945,7 +945,7 @@ export async function runWithImageModelFallback(params: { } } - throwFallbackFailureSummary({ + return throwFallbackFailureSummary({ attempts, candidates, lastError, diff --git a/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts b/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts index 8a672e6fd72..17c134d4133 100644 --- a/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts +++ b/src/agents/pi-embedded-subscribe.handlers.lifecycle.ts @@ -35,7 +35,7 @@ export function handleAgentStart(ctx: EmbeddedPiSubscribeContext) { }); } -export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) { +export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext): void | Promise { const lastAssistant = ctx.state.lastAssistant; const isError = isAssistantMessage(lastAssistant) && lastAssistant.stopReason === "error"; let lifecycleErrorText: string | undefined; @@ -136,6 +136,7 @@ export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) { if (isPromiseLike(onBlockReplyFlushResult)) { return onBlockReplyFlushResult; } + return undefined; }); } @@ -143,6 +144,7 @@ export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) { if (isPromiseLike(onBlockReplyFlushResult)) { return onBlockReplyFlushResult; } + return undefined; }; let lifecycleTerminalEmitted = false; @@ -172,4 +174,5 @@ export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) { } emitLifecycleTerminalOnce(); + return undefined; } diff --git a/src/agents/pi-embedded-subscribe.handlers.messages.ts b/src/agents/pi-embedded-subscribe.handlers.messages.ts index d5fa9c26401..2ae52b7b59b 100644 --- a/src/agents/pi-embedded-subscribe.handlers.messages.ts +++ b/src/agents/pi-embedded-subscribe.handlers.messages.ts @@ -433,7 +433,7 @@ export function handleMessageUpdate( export function handleMessageEnd( ctx: EmbeddedPiSubscribeContext, evt: AgentEvent & { message: AgentMessage }, -) { +): void | Promise { const msg = evt.message; if (msg?.role !== "assistant" || isTranscriptOnlyOpenClawAssistantMessage(msg)) { return; @@ -659,6 +659,7 @@ export function handleMessageEnd( if (isPromiseLike(onBlockReplyFlushResult)) { return onBlockReplyFlushResult; } + return undefined; }) .finally(() => { finalizeMessageEnd(); @@ -673,4 +674,5 @@ export function handleMessageEnd( } finalizeMessageEnd(); + return undefined; } diff --git a/src/agents/pi-embedded-subscribe.handlers.tools.ts b/src/agents/pi-embedded-subscribe.handlers.tools.ts index c1c80178df4..a28fe55e056 100644 --- a/src/agents/pi-embedded-subscribe.handlers.tools.ts +++ b/src/agents/pi-embedded-subscribe.handlers.tools.ts @@ -523,8 +523,8 @@ async function emitToolResultOutput(params: { export function handleToolExecutionStart( ctx: ToolHandlerContext, evt: AgentEvent & { toolName: string; toolCallId: string; args: unknown }, -) { - const continueAfterBlockReplyFlush = () => { +): void | Promise { + const continueAfterBlockReplyFlush = (): void | Promise => { const onBlockReplyFlushResult = ctx.params.onBlockReplyFlush?.(); if (isPromiseLike(onBlockReplyFlushResult)) { return onBlockReplyFlushResult.then(() => { @@ -532,6 +532,7 @@ export function handleToolExecutionStart( }); } continueToolExecutionStart(); + return undefined; }; const continueToolExecutionStart = () => { diff --git a/src/agents/tool-display-exec-shell.ts b/src/agents/tool-display-exec-shell.ts index 742107e4abc..7b40a73d2f3 100644 --- a/src/agents/tool-display-exec-shell.ts +++ b/src/agents/tool-display-exec-shell.ts @@ -338,6 +338,7 @@ export function stripShellPreamble(command: string): PreambleResult { first = { index: idx, length: 1 }; return false; } + return undefined; }); const head = (first ? rest.slice(0, first.index) : rest).trim(); const isChdir = (first ? !first.isOr : i > 0) && isChdirCommand(head); diff --git a/src/agents/tools/nodes-tool-commands.ts b/src/agents/tools/nodes-tool-commands.ts index fc604713849..d63f2720435 100644 --- a/src/agents/tools/nodes-tool-commands.ts +++ b/src/agents/tools/nodes-tool-commands.ts @@ -154,6 +154,7 @@ export async function executeNodeCommandAction(params: { return jsonResult(raw ?? {}); } } + throw new Error("Unsupported node command action"); } export async function invokeNodeCommandPayload(params: { diff --git a/src/agents/tools/nodes-tool-media.ts b/src/agents/tools/nodes-tool-media.ts index 5203f1d4df1..0e091082ef2 100644 --- a/src/agents/tools/nodes-tool-media.ts +++ b/src/agents/tools/nodes-tool-media.ts @@ -52,6 +52,7 @@ export async function executeNodeMediaAction( case "screen_record": return await executeScreenRecord(input); } + throw new Error("Unsupported node media action"); } async function executeCameraSnap({ diff --git a/src/agents/tools/web-search-provider-common.ts b/src/agents/tools/web-search-provider-common.ts index 0b0265d4323..8bc23ea9933 100644 --- a/src/agents/tools/web-search-provider-common.ts +++ b/src/agents/tools/web-search-provider-common.ts @@ -315,6 +315,7 @@ function describeUnsupportedSearchFilter(name: UnsupportedWebSearchFilterName): case "date_before": return "date_after/date_before filtering"; } + throw new Error("Unsupported web search filter"); } export function buildUnsupportedSearchFilterResponse( diff --git a/src/auto-reply/reply/agent-runner-execution.ts b/src/auto-reply/reply/agent-runner-execution.ts index 6436698d67e..1a743e91004 100644 --- a/src/auto-reply/reply/agent-runner-execution.ts +++ b/src/auto-reply/reply/agent-runner-execution.ts @@ -172,6 +172,7 @@ function setFallbackSelectionStateField( } return false; } + throw new Error("Unsupported fallback selection state key"); } function snapshotFallbackSelectionState(entry: SessionEntry): FallbackSelectionState { @@ -628,19 +629,22 @@ export async function runAgentTurnWithFallback(params: { let bootstrapPromptWarningSignaturesSeen = resolveBootstrapWarningSignaturesSeen( params.getActiveSessionEntry()?.systemPromptReport, ); - const persistFallbackCandidateSelection = async (provider: string, model: string) => { + const persistFallbackCandidateSelection = async ( + provider: string, + model: string, + ): Promise<(() => Promise) | undefined> => { if ( !params.sessionKey || !params.activeSessionStore || (provider === params.followupRun.run.provider && model === params.followupRun.run.model) ) { - return; + return undefined; } const activeSessionEntry = params.getActiveSessionEntry() ?? params.activeSessionStore[params.sessionKey]; if (!activeSessionEntry) { - return; + return undefined; } const previousState = snapshotFallbackSelectionState(activeSessionEntry); @@ -652,7 +656,7 @@ export async function runAgentTurnWithFallback(params: { }); const nextState = applied.nextState; if (!applied.updated || !nextState) { - return; + return undefined; } params.activeSessionStore[params.sessionKey] = activeSessionEntry; diff --git a/src/auto-reply/reply/dispatch-from-config.ts b/src/auto-reply/reply/dispatch-from-config.ts index 047f4dac4f2..b2a105421dd 100644 --- a/src/auto-reply/reply/dispatch-from-config.ts +++ b/src/auto-reply/reply/dispatch-from-config.ts @@ -727,7 +727,7 @@ export async function dispatchReplyFromConfig(params: { } return parts.join("\n\n").trim() || "Planning next steps."; }; - const maybeSendWorkingStatus = (label: string) => { + const maybeSendWorkingStatus = async (label: string): Promise => { const normalizedLabel = normalizeWorkingLabel(label); if ( !shouldEmitVerboseProgress() || @@ -744,11 +744,15 @@ export async function dispatchReplyFromConfig(params: { text: `Working: ${normalizedLabel}`, }; if (shouldRouteToOriginating) { - return sendPayloadAsync(payload, undefined, false); + await sendPayloadAsync(payload, undefined, false); + return; } dispatcher.sendToolResult(payload); }; - const sendPlanUpdate = (payload: { explanation?: string; steps?: string[] }) => { + const sendPlanUpdate = async (payload: { + explanation?: string; + steps?: string[]; + }): Promise => { if (!shouldEmitVerboseProgress()) { return; } @@ -756,7 +760,8 @@ export async function dispatchReplyFromConfig(params: { text: formatPlanUpdateText(payload), }; if (shouldRouteToOriginating) { - return sendPayloadAsync(replyPayload, undefined, false); + await sendPayloadAsync(replyPayload, undefined, false); + return; } dispatcher.sendToolResult(replyPayload); }; @@ -866,13 +871,13 @@ export async function dispatchReplyFromConfig(params: { }; return run(); }, - onPlanUpdate: ({ phase, explanation, steps }) => { + onPlanUpdate: async ({ phase, explanation, steps }) => { if (phase !== "update") { return; } - return sendPlanUpdate({ explanation, steps }); + await sendPlanUpdate({ explanation, steps }); }, - onApprovalEvent: ({ phase, status, command, message }) => { + onApprovalEvent: async ({ phase, status, command, message }) => { if (phase !== "requested") { return; } @@ -880,9 +885,9 @@ export async function dispatchReplyFromConfig(params: { if (!label) { return; } - return maybeSendWorkingStatus(label); + await maybeSendWorkingStatus(label); }, - onPatchSummary: ({ phase, summary, title }) => { + onPatchSummary: async ({ phase, summary, title }) => { if (phase !== "end") { return; } @@ -890,7 +895,7 @@ export async function dispatchReplyFromConfig(params: { if (!label) { return; } - return maybeSendWorkingStatus(label); + await maybeSendWorkingStatus(label); }, onBlockReply: (payload: ReplyPayload, context?: BlockReplyContext) => { const run = async () => { diff --git a/src/cli/daemon-cli/lifecycle.ts b/src/cli/daemon-cli/lifecycle.ts index 1921fde4d25..abcfed8e660 100644 --- a/src/cli/daemon-cli/lifecycle.ts +++ b/src/cli/daemon-cli/lifecycle.ts @@ -205,7 +205,7 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi delayMs: POST_RESTART_HEALTH_DELAY_MS, }); if (health.healthy) { - return; + return undefined; } const diagnostics = renderGatewayPortHealthDiagnostics(health); @@ -224,6 +224,7 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi formatCliCommand("openclaw gateway status --deep"), formatCliCommand("openclaw doctor"), ]); + throw new Error("unreachable after gateway restart health failure"); } let health = await waitForGatewayHealthyRestart({ @@ -257,7 +258,7 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi } if (health.healthy) { - return; + return undefined; } const diagnostics = renderRestartDiagnostics(health); @@ -290,6 +291,7 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi formatCliCommand("openclaw gateway status --deep"), formatCliCommand("openclaw doctor"), ]); + throw new Error("unreachable after gateway restart failure"); }, }); } diff --git a/src/commands/backup-shared.ts b/src/commands/backup-shared.ts index 479fd8c0e12..242c669920d 100644 --- a/src/commands/backup-shared.ts +++ b/src/commands/backup-shared.ts @@ -55,6 +55,7 @@ function backupAssetPriority(kind: BackupAssetKind): number { case "workspace": return 3; } + throw new Error("Unsupported backup asset kind"); } export function buildBackupArchiveRoot(nowMs = Date.now()): string { diff --git a/src/commands/doctor-security.ts b/src/commands/doctor-security.ts index 6ae0c538d10..18a0cd98e8a 100644 --- a/src/commands/doctor-security.ts +++ b/src/commands/doctor-security.ts @@ -60,6 +60,7 @@ function execSecurityRank(value: ExecSecurity): number { case "full": return 2; } + throw new Error("Unsupported exec security value"); } function execAskRank(value: ExecAsk): number { @@ -71,6 +72,7 @@ function execAskRank(value: ExecAsk): number { case "always": return 2; } + throw new Error("Unsupported exec ask value"); } function collectExecPolicyConflictWarnings(cfg: OpenClawConfig): string[] { diff --git a/src/config/plugin-auto-enable.shared.ts b/src/config/plugin-auto-enable.shared.ts index afa6abbac06..8e71d5590d2 100644 --- a/src/config/plugin-auto-enable.shared.ts +++ b/src/config/plugin-auto-enable.shared.ts @@ -339,6 +339,7 @@ export function resolvePluginAutoEnableCandidateReason( case "setup-auto-enable": return candidate.reason; } + throw new Error("Unsupported plugin auto-enable candidate"); } export function resolveConfiguredPluginAutoEnableCandidates(params: { diff --git a/src/cron/service.runs-one-shot-main-job-disables-it.test.ts b/src/cron/service.runs-one-shot-main-job-disables-it.test.ts index 36922981156..1fb48999099 100644 --- a/src/cron/service.runs-one-shot-main-job-disables-it.test.ts +++ b/src/cron/service.runs-one-shot-main-job-disables-it.test.ts @@ -78,6 +78,7 @@ vi.mock("node:fs", async () => { return await actual.promises.mkdir(p, { recursive: true }); } ensureDir(p); + return undefined; }, readFile: async (p: string) => { if (!isFixtureInMock(p)) { @@ -164,6 +165,7 @@ vi.mock("node:fs/promises", async () => { return await actual.mkdir(p, { recursive: true }); } ensureDir(p); + return undefined; }, writeFile: async (p: string, data: string, _enc?: unknown) => { if (!isFixturePath(p)) { diff --git a/src/image-generation/runtime.ts b/src/image-generation/runtime.ts index 9838a921910..ea5d47d0568 100644 --- a/src/image-generation/runtime.ts +++ b/src/image-generation/runtime.ts @@ -144,7 +144,7 @@ export async function generateImage( } } - throwCapabilityGenerationFailure({ + return throwCapabilityGenerationFailure({ capabilityLabel: "image generation", attempts, lastError, diff --git a/src/infra/boundary-file-read.ts b/src/infra/boundary-file-read.ts index 2338ade6cfa..31a3a10bed4 100644 --- a/src/infra/boundary-file-read.ts +++ b/src/infra/boundary-file-read.ts @@ -108,6 +108,7 @@ export function matchBoundaryFileOpenFailure( case "io": return handlers.io ? handlers.io(failure) : handlers.fallback(failure); } + return handlers.fallback(failure); } function openBoundaryFileResolved(params: { diff --git a/src/infra/device-pairing.ts b/src/infra/device-pairing.ts index c59ac1a7f1c..f273cfc2479 100644 --- a/src/infra/device-pairing.ts +++ b/src/infra/device-pairing.ts @@ -137,6 +137,7 @@ export function formatDevicePairingForbiddenMessage(result: DevicePairingForbidd case "bootstrap-scope-not-allowed": return `bootstrap profile does not allow scope: ${result.scope ?? "unknown"}`; } + throw new Error("Unsupported device pairing forbidden reason"); } async function loadState(baseDir?: string): Promise { diff --git a/src/infra/heartbeat-events.ts b/src/infra/heartbeat-events.ts index 242bb873635..d8e240c2a3c 100644 --- a/src/infra/heartbeat-events.ts +++ b/src/infra/heartbeat-events.ts @@ -34,6 +34,7 @@ export function resolveIndicatorType( case "skipped": return undefined; } + throw new Error("Unsupported heartbeat status"); } type HeartbeatEventState = { diff --git a/src/infra/shell-wrapper-resolution.ts b/src/infra/shell-wrapper-resolution.ts index 5da57c9476e..4ff6342015c 100644 --- a/src/infra/shell-wrapper-resolution.ts +++ b/src/infra/shell-wrapper-resolution.ts @@ -195,6 +195,7 @@ function extractShellWrapperPayload(argv: string[], spec: ShellWrapperSpec): str case "powershell": return extractPowerShellInlineCommand(argv); } + throw new Error("Unsupported shell wrapper kind"); } function hasEnvManipulationBeforeShellWrapperInternal( diff --git a/src/infra/warning-filter.ts b/src/infra/warning-filter.ts index 1b391bcaaad..efd9a39449b 100644 --- a/src/infra/warning-filter.ts +++ b/src/infra/warning-filter.ts @@ -91,7 +91,8 @@ export function installProcessWarningFilter(): void { process.emit("warning", emitted); return; } - return Reflect.apply(originalEmitWarning, process, args); + Reflect.apply(originalEmitWarning, process, args); + return; }) as typeof process.emitWarning; process.emitWarning = wrappedEmitWarning; diff --git a/src/logging/timestamps.ts b/src/logging/timestamps.ts index 29e0536873b..7a3abec2aa3 100644 --- a/src/logging/timestamps.ts +++ b/src/logging/timestamps.ts @@ -64,6 +64,7 @@ export function formatTimestamp(date: Date, options?: FormatTimestampOptions): s case "long": return `${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}.${parts.fractionalSecond}${parts.offset}`; } + throw new Error("Unsupported timestamp style"); } /** diff --git a/src/music-generation/runtime.ts b/src/music-generation/runtime.ts index 1b564d1b0e8..b53a4f0763a 100644 --- a/src/music-generation/runtime.ts +++ b/src/music-generation/runtime.ts @@ -146,7 +146,7 @@ export async function generateMusic( } } - throwCapabilityGenerationFailure({ + return throwCapabilityGenerationFailure({ capabilityLabel: "music generation", attempts, lastError, diff --git a/src/plugin-sdk/provider-model-shared.ts b/src/plugin-sdk/provider-model-shared.ts index e8588f4a64f..4364ed79175 100644 --- a/src/plugin-sdk/provider-model-shared.ts +++ b/src/plugin-sdk/provider-model-shared.ts @@ -151,4 +151,5 @@ export function buildProviderReplayFamilyHooks( }), }; } + throw new Error("Unsupported provider replay family"); } diff --git a/src/plugin-sdk/provider-stream.ts b/src/plugin-sdk/provider-stream.ts index c05f01fce44..d057843e138 100644 --- a/src/plugin-sdk/provider-stream.ts +++ b/src/plugin-sdk/provider-stream.ts @@ -139,6 +139,7 @@ export function buildProviderStreamFamilyHooks( createToolStreamWrapper(ctx.streamFn, ctx.extraParams?.tool_stream !== false), }; } + throw new Error("Unsupported provider stream family"); } // Public stream-wrapper helpers for provider plugins. diff --git a/src/plugin-sdk/provider-tools.ts b/src/plugin-sdk/provider-tools.ts index 0605ff4beea..ae828a059d3 100644 --- a/src/plugin-sdk/provider-tools.ts +++ b/src/plugin-sdk/provider-tools.ts @@ -172,4 +172,5 @@ export function buildProviderToolCompatFamilyHooks(family: ProviderToolCompatFam inspectToolSchemas: inspectGeminiToolSchemas, }; } + throw new Error("Unsupported provider tool compatibility family"); } diff --git a/src/plugin-sdk/provider-web-search-contract-fields.ts b/src/plugin-sdk/provider-web-search-contract-fields.ts index 5e75baac892..ab019dad857 100644 --- a/src/plugin-sdk/provider-web-search-contract-fields.ts +++ b/src/plugin-sdk/provider-web-search-contract-fields.ts @@ -57,6 +57,7 @@ function createSearchCredentialFields( setCredentialValue: () => {}, }; } + throw new Error("Unsupported web search credential type"); } function createConfiguredCredentialFields( diff --git a/src/plugins/contracts/registry.ts b/src/plugins/contracts/registry.ts index b287fc6a0b5..24b706879fc 100644 --- a/src/plugins/contracts/registry.ts +++ b/src/plugins/contracts/registry.ts @@ -192,6 +192,7 @@ function resolveBundledManifestPluginIdsForContract(contract: ManifestContractKe case "tools": return entry.toolNames.length > 0; } + throw new Error("Unsupported manifest contract key"); }) .map((entry) => entry.pluginId), ).toSorted((left, right) => left.localeCompare(right)); diff --git a/src/plugins/discovery.test.ts b/src/plugins/discovery.test.ts index 7902ab9c3df..a9a474aa524 100644 --- a/src/plugins/discovery.test.ts +++ b/src/plugins/discovery.test.ts @@ -665,6 +665,7 @@ describe("discoverOpenClawPlugins", () => { packageName: "@openclaw/missing-entry-pack", extensions: ["./missing.ts"], }); + return true; }, }, { @@ -688,6 +689,7 @@ describe("discoverOpenClawPlugins", () => { packageName: "@openclaw/pack", extensions: ["./linked/escape.ts"], }); + return true; }, }, { @@ -718,6 +720,7 @@ describe("discoverOpenClawPlugins", () => { packageName: "@openclaw/pack", extensions: ["./escape.ts"], }); + return true; }, }, ] as const)("$name", async ({ setup, expectedDiagnostic, expectedId }) => { diff --git a/src/plugins/marketplace.ts b/src/plugins/marketplace.ts index 3ce34b20000..ac094d5538c 100644 --- a/src/plugins/marketplace.ts +++ b/src/plugins/marketplace.ts @@ -250,6 +250,7 @@ function marketplaceEntrySourceToInput(source: MarketplaceEntrySource): string { case "url": return source.url; } + throw new Error("Unsupported marketplace entry source"); } function parseMarketplaceManifest( diff --git a/src/plugins/runtime/runtime-registry-loader.ts b/src/plugins/runtime/runtime-registry-loader.ts index 47e1abbbbac..11691057044 100644 --- a/src/plugins/runtime/runtime-registry-loader.ts +++ b/src/plugins/runtime/runtime-registry-loader.ts @@ -22,6 +22,7 @@ function scopeRank(scope: typeof pluginRegistryLoaded): number { case "all": return 3; } + throw new Error("Unsupported plugin registry scope"); } function activeRegistrySatisfiesScope( @@ -50,6 +51,7 @@ function activeRegistrySatisfiesScope( case "all": return false; } + throw new Error("Unsupported plugin registry scope"); } export function ensurePluginRegistryLoaded(options?: { diff --git a/src/secrets/resolve.ts b/src/secrets/resolve.ts index c6b27962f4b..808a18d0cb9 100644 --- a/src/secrets/resolve.ts +++ b/src/secrets/resolve.ts @@ -817,7 +817,7 @@ async function resolveProviderRefs(params: { message: `Unsupported secret provider source "${String((params.providerConfig as { source?: unknown }).source)}".`, }); } catch (err) { - throwUnknownProviderResolutionError({ + return throwUnknownProviderResolutionError({ source: params.source, provider: params.providerName, err, diff --git a/src/video-generation/runtime.ts b/src/video-generation/runtime.ts index 19b032e94aa..5ce4605e21b 100644 --- a/src/video-generation/runtime.ts +++ b/src/video-generation/runtime.ts @@ -156,7 +156,7 @@ export async function generateVideo( } } - throwCapabilityGenerationFailure({ + return throwCapabilityGenerationFailure({ capabilityLabel: "video generation", attempts, lastError, diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index 7b995ead66a..3b4f81a1f9d 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -729,17 +729,21 @@ export function renderApp(state: AppViewState) { } switch (state.agentsPanel) { case "files": - return void loadAgentFiles(state, agentId); + void loadAgentFiles(state, agentId); + return; case "skills": - return void loadAgentSkills(state, agentId); + void loadAgentSkills(state, agentId); + return; case "tools": void loadToolsCatalog(state, agentId); - return void refreshVisibleToolsEffectiveForCurrentSession(state); + void refreshVisibleToolsEffectiveForCurrentSession(state); + return; } }; const refreshAgentsPanelSupplementalData = (panel: AppViewState["agentsPanel"]) => { if (panel === "channels") { - return void loadChannels(state, false); + void loadChannels(state, false); + return; } if (panel === "cron") { void state.loadCron(); diff --git a/ui/src/ui/app-settings.ts b/ui/src/ui/app-settings.ts index d652a4ae7b4..d8eaa3e15b8 100644 --- a/ui/src/ui/app-settings.ts +++ b/ui/src/ui/app-settings.ts @@ -272,13 +272,17 @@ async function refreshAgentsTab(host: SettingsHost, app: SettingsAppHost) { void loadAgentIdentity(app, agentId); switch (host.agentsPanel) { case "files": - return void loadAgentFiles(app, agentId); + void loadAgentFiles(app, agentId); + return; case "skills": - return void loadAgentSkills(app, agentId); + void loadAgentSkills(app, agentId); + return; case "channels": - return void loadChannels(app, false); + void loadChannels(app, false); + return; case "cron": - return void loadCron(host); + void loadCron(host); + return; } } diff --git a/ui/src/ui/controllers/agents.ts b/ui/src/ui/controllers/agents.ts index a79e3e9e3b3..5cbada859c7 100644 --- a/ui/src/ui/controllers/agents.ts +++ b/ui/src/ui/controllers/agents.ts @@ -196,11 +196,11 @@ export function refreshVisibleToolsEffectiveForCurrentSession( ): Promise | undefined { const resolvedSessionKey = state.sessionKey?.trim(); if (!resolvedSessionKey || state.agentsPanel !== "tools" || !state.agentsSelectedId) { - return; + return undefined; } const sessionAgentId = resolveAgentIdFromSessionKey(resolvedSessionKey); if (!sessionAgentId || state.agentsSelectedId !== sessionAgentId) { - return; + return undefined; } return loadToolsEffective(state, { agentId: sessionAgentId, diff --git a/ui/src/ui/markdown.ts b/ui/src/ui/markdown.ts index 660e51454c7..dc03b61f225 100644 --- a/ui/src/ui/markdown.ts +++ b/ui/src/ui/markdown.ts @@ -160,6 +160,7 @@ const cjkAutoLinkExtension = { ], }; } + return undefined; }, }; diff --git a/ui/src/ui/views/skills.ts b/ui/src/ui/views/skills.ts index 5e2eb10e560..24c7fadd939 100644 --- a/ui/src/ui/views/skills.ts +++ b/ui/src/ui/views/skills.ts @@ -82,6 +82,7 @@ function skillMatchesStatus(skill: SkillStatusEntry, status: SkillsStatusFilter) case "disabled": return skill.disabled; } + throw new Error("Unsupported skills status filter"); } function skillStatusClass(skill: SkillStatusEntry): string {