chore: enable consistent-return

This commit is contained in:
Peter Steinberger
2026-04-10 20:56:08 +01:00
parent bc27278d6d
commit 0ebeee8b0d
68 changed files with 223 additions and 107 deletions

View File

@@ -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: {

View File

@@ -285,6 +285,7 @@ describe("exec approvals", () => {
invokeParams = params;
return { payload: { success: true, stdout: "ok" } };
}
return undefined;
},
});

View File

@@ -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 {

View File

@@ -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<string, unknown> {

View File

@@ -883,7 +883,7 @@ export async function runWithModelFallback<T>(params: {
}
}
throwFallbackFailureSummary({
return throwFallbackFailureSummary({
attempts,
candidates,
lastError,
@@ -945,7 +945,7 @@ export async function runWithImageModelFallback<T>(params: {
}
}
throwFallbackFailureSummary({
return throwFallbackFailureSummary({
attempts,
candidates,
lastError,

View File

@@ -35,7 +35,7 @@ export function handleAgentStart(ctx: EmbeddedPiSubscribeContext) {
});
}
export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) {
export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext): void | Promise<void> {
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<void>(onBlockReplyFlushResult)) {
return onBlockReplyFlushResult;
}
return undefined;
});
}
@@ -143,6 +144,7 @@ export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) {
if (isPromiseLike<void>(onBlockReplyFlushResult)) {
return onBlockReplyFlushResult;
}
return undefined;
};
let lifecycleTerminalEmitted = false;
@@ -172,4 +174,5 @@ export function handleAgentEnd(ctx: EmbeddedPiSubscribeContext) {
}
emitLifecycleTerminalOnce();
return undefined;
}

View File

@@ -433,7 +433,7 @@ export function handleMessageUpdate(
export function handleMessageEnd(
ctx: EmbeddedPiSubscribeContext,
evt: AgentEvent & { message: AgentMessage },
) {
): void | Promise<void> {
const msg = evt.message;
if (msg?.role !== "assistant" || isTranscriptOnlyOpenClawAssistantMessage(msg)) {
return;
@@ -659,6 +659,7 @@ export function handleMessageEnd(
if (isPromiseLike<void>(onBlockReplyFlushResult)) {
return onBlockReplyFlushResult;
}
return undefined;
})
.finally(() => {
finalizeMessageEnd();
@@ -673,4 +674,5 @@ export function handleMessageEnd(
}
finalizeMessageEnd();
return undefined;
}

View File

@@ -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<void> {
const continueAfterBlockReplyFlush = (): void | Promise<void> => {
const onBlockReplyFlushResult = ctx.params.onBlockReplyFlush?.();
if (isPromiseLike<void>(onBlockReplyFlushResult)) {
return onBlockReplyFlushResult.then(() => {
@@ -532,6 +532,7 @@ export function handleToolExecutionStart(
});
}
continueToolExecutionStart();
return undefined;
};
const continueToolExecutionStart = () => {

View File

@@ -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);

View File

@@ -154,6 +154,7 @@ export async function executeNodeCommandAction(params: {
return jsonResult(raw ?? {});
}
}
throw new Error("Unsupported node command action");
}
export async function invokeNodeCommandPayload(params: {

View File

@@ -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({

View File

@@ -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(

View File

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

View File

@@ -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<void> => {
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<void> => {
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 () => {

View File

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

View File

@@ -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 {

View File

@@ -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[] {

View File

@@ -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: {

View File

@@ -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)) {

View File

@@ -144,7 +144,7 @@ export async function generateImage(
}
}
throwCapabilityGenerationFailure({
return throwCapabilityGenerationFailure({
capabilityLabel: "image generation",
attempts,
lastError,

View File

@@ -108,6 +108,7 @@ export function matchBoundaryFileOpenFailure<T>(
case "io":
return handlers.io ? handlers.io(failure) : handlers.fallback(failure);
}
return handlers.fallback(failure);
}
function openBoundaryFileResolved(params: {

View File

@@ -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<DevicePairingStateFile> {

View File

@@ -34,6 +34,7 @@ export function resolveIndicatorType(
case "skipped":
return undefined;
}
throw new Error("Unsupported heartbeat status");
}
type HeartbeatEventState = {

View File

@@ -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(

View File

@@ -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;

View File

@@ -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");
}
/**

View File

@@ -146,7 +146,7 @@ export async function generateMusic(
}
}
throwCapabilityGenerationFailure({
return throwCapabilityGenerationFailure({
capabilityLabel: "music generation",
attempts,
lastError,

View File

@@ -151,4 +151,5 @@ export function buildProviderReplayFamilyHooks(
}),
};
}
throw new Error("Unsupported provider replay family");
}

View File

@@ -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.

View File

@@ -172,4 +172,5 @@ export function buildProviderToolCompatFamilyHooks(family: ProviderToolCompatFam
inspectToolSchemas: inspectGeminiToolSchemas,
};
}
throw new Error("Unsupported provider tool compatibility family");
}

View File

@@ -57,6 +57,7 @@ function createSearchCredentialFields(
setCredentialValue: () => {},
};
}
throw new Error("Unsupported web search credential type");
}
function createConfiguredCredentialFields(

View File

@@ -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));

View File

@@ -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 }) => {

View File

@@ -250,6 +250,7 @@ function marketplaceEntrySourceToInput(source: MarketplaceEntrySource): string {
case "url":
return source.url;
}
throw new Error("Unsupported marketplace entry source");
}
function parseMarketplaceManifest(

View File

@@ -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?: {

View File

@@ -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,

View File

@@ -156,7 +156,7 @@ export async function generateVideo(
}
}
throwCapabilityGenerationFailure({
return throwCapabilityGenerationFailure({
capabilityLabel: "video generation",
attempts,
lastError,