diff --git a/.oxlintrc.json b/.oxlintrc.json index 752bd621d0d..51ef3fbac41 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -65,6 +65,10 @@ "typescript/no-unnecessary-type-parameters": "error", "typescript/no-unsafe-type-assertion": "off", "typescript/no-useless-default-assignment": "error", + "typescript/switch-exhaustiveness-check": [ + "error", + { "considerDefaultExhaustiveForUnions": true } + ], "typescript/prefer-return-this-type": "error", "typescript/prefer-find": "error", "typescript/prefer-function-type": "error", diff --git a/extensions/diagnostics-otel/src/service.ts b/extensions/diagnostics-otel/src/service.ts index 55b55621225..ca625cd1181 100644 --- a/extensions/diagnostics-otel/src/service.ts +++ b/extensions/diagnostics-otel/src/service.ts @@ -648,6 +648,11 @@ export function createDiagnosticsOtelService(): OpenClawPluginService { case "diagnostic.heartbeat": recordHeartbeat(evt); return; + case "tool.loop": + case "diagnostic.memory.sample": + case "diagnostic.memory.pressure": + case "payload.large": + return; } } catch (err) { ctx.logger.error( diff --git a/extensions/memory-wiki/src/query.ts b/extensions/memory-wiki/src/query.ts index 42cc8cecf48..a86f77acf64 100644 --- a/extensions/memory-wiki/src/query.ts +++ b/extensions/memory-wiki/src/query.ts @@ -267,6 +267,8 @@ function scoreClaimMatch(params: { case "unknown": score -= 4; break; + case undefined: + break; } score += isClaimContestedStatus(params.status) ? -6 : 4; return score; diff --git a/extensions/voice-call/src/manager/events.ts b/extensions/voice-call/src/manager/events.ts index f15fbf0ee8f..230641704fd 100644 --- a/extensions/voice-call/src/manager/events.ts +++ b/extensions/voice-call/src/manager/events.ts @@ -229,6 +229,10 @@ export function processEvent(ctx: EventContext, event: NormalizedEvent): void { transitionState(call, "listening"); break; + case "call.silence": + case "call.dtmf": + break; + case "call.ended": finalizeCall({ ctx, diff --git a/extensions/voice-call/src/media-stream.ts b/extensions/voice-call/src/media-stream.ts index 87320077e1a..39128a9814e 100644 --- a/extensions/voice-call/src/media-stream.ts +++ b/extensions/voice-call/src/media-stream.ts @@ -233,6 +233,10 @@ export class MediaStreamHandler { session = null; } break; + + case "clear": + case "mark": + break; } } catch (error) { console.error("[MediaStream] Error processing message:", error); diff --git a/src/plugin-sdk/provider-stream-shared.ts b/src/plugin-sdk/provider-stream-shared.ts index 18858e726a7..9ebf3733574 100644 --- a/src/plugin-sdk/provider-stream-shared.ts +++ b/src/plugin-sdk/provider-stream-shared.ts @@ -192,6 +192,8 @@ export function resolveGoogleGemini3ThinkingLevel(params: { case "max": case "xhigh": return "HIGH"; + case undefined: + break; } if (typeof params.thinkingBudget === "number") { return params.thinkingBudget <= 2048 ? "LOW" : "HIGH"; @@ -214,6 +216,8 @@ export function resolveGoogleGemini3ThinkingLevel(params: { case "max": case "xhigh": return "HIGH"; + case undefined: + break; } if (typeof params.thinkingBudget !== "number") { return undefined; diff --git a/test/scripts/oxlint-config.test.ts b/test/scripts/oxlint-config.test.ts index e382665f45e..d70d72f8e42 100644 --- a/test/scripts/oxlint-config.test.ts +++ b/test/scripts/oxlint-config.test.ts @@ -132,6 +132,15 @@ describe("oxlint config", () => { ]); }); + it("enables exhaustive switch linting", () => { + const config = readJson(".oxlintrc.json") as OxlintConfig; + + expect(config.rules?.["typescript/switch-exhaustiveness-check"]).toEqual([ + "error", + { considerDefaultExhaustiveForUnions: true }, + ]); + }); + it("enables clean zero-baseline lint rules", () => { const config = readJson(".oxlintrc.json") as OxlintConfig; diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index e1b89cf5c14..7a00ebd53c1 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -1158,6 +1158,10 @@ export function renderApp(state: AppViewState) { void loadToolsCatalog(state, agentId); void refreshVisibleToolsEffectiveForCurrentSession(state); return; + case "overview": + case "channels": + case "cron": + return; } }; const refreshAgentsPanelSupplementalData = (panel: AppViewState["agentsPanel"]) => { diff --git a/ui/src/ui/app-settings.ts b/ui/src/ui/app-settings.ts index e64aeda9149..3bb4a7b7f3e 100644 --- a/ui/src/ui/app-settings.ts +++ b/ui/src/ui/app-settings.ts @@ -323,6 +323,10 @@ async function refreshAgentsTab(host: SettingsHost, app: SettingsAppHost) { case "cron": void loadCron(host); return; + case "overview": + case "tools": + case undefined: + return; } }