chore(lint): enable stricter error rules

This commit is contained in:
Peter Steinberger
2026-06-01 01:12:00 +01:00
parent 0bfba7e26d
commit 27dde7a4d6
458 changed files with 3159 additions and 936 deletions

View File

@@ -82,7 +82,10 @@
"typescript/no-meaningless-void-operator": "error", "typescript/no-meaningless-void-operator": "error",
"typescript/no-misused-promises": "error", "typescript/no-misused-promises": "error",
"typescript/no-inferrable-types": "error", "typescript/no-inferrable-types": "error",
"typescript/only-throw-error": "error",
"typescript/no-non-null-asserted-nullish-coalescing": "error", "typescript/no-non-null-asserted-nullish-coalescing": "error",
"typescript/prefer-promise-reject-errors": "error",
"typescript/restrict-plus-operands": "error",
"typescript/no-unnecessary-qualifier": "error", "typescript/no-unnecessary-qualifier": "error",
"typescript/no-unnecessary-type-assertion": "error", "typescript/no-unnecessary-type-assertion": "error",
"typescript/no-unnecessary-type-arguments": "error", "typescript/no-unnecessary-type-arguments": "error",
@@ -109,6 +112,8 @@
"typescript/require-array-sort-compare": "error", "typescript/require-array-sort-compare": "error",
"typescript/restrict-template-expressions": "error", "typescript/restrict-template-expressions": "error",
"typescript/triple-slash-reference": "error", "typescript/triple-slash-reference": "error",
"typescript/unbound-method": "error",
"typescript/use-unknown-in-catch-callback-variable": "error",
"unicorn/consistent-date-clone": "error", "unicorn/consistent-date-clone": "error",
"unicorn/consistent-empty-array-spread": "error", "unicorn/consistent-empty-array-spread": "error",
"unicorn/consistent-function-scoping": "off", "unicorn/consistent-function-scoping": "off",
@@ -128,6 +133,7 @@
"unicorn/no-unnecessary-slice-end": "error", "unicorn/no-unnecessary-slice-end": "error",
"unicorn/no-useless-error-capture-stack-trace": "error", "unicorn/no-useless-error-capture-stack-trace": "error",
"unicorn/no-useless-promise-resolve-reject": "error", "unicorn/no-useless-promise-resolve-reject": "error",
"unicorn/no-useless-switch-case": "error",
"unicorn/no-zero-fractions": "error", "unicorn/no-zero-fractions": "error",
"unicorn/prefer-date-now": "error", "unicorn/prefer-date-now": "error",
"unicorn/prefer-dom-node-text-content": "error", "unicorn/prefer-dom-node-text-content": "error",

View File

@@ -68,7 +68,7 @@ class LegacyRunTurnEventQueue {
return item; return item;
} }
if (this.error) { if (this.error) {
throw this.error; throw toLintErrorObject(this.error, "Non-Error thrown");
} }
if (this.closed) { if (this.closed) {
return null; return null;
@@ -178,3 +178,17 @@ export function lazyStartRuntimeTurn(
}, },
}; };
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -286,7 +286,7 @@ describe("AcpxRuntime fresh reset wrapper", () => {
}) })
.then( .then(
() => ({ status: "resolved" as const }), () => ({ status: "resolved" as const }),
(error) => ({ status: "rejected" as const, error }), (error: unknown) => ({ status: "rejected" as const, error }),
); );
expect(outcome.status).toBe("rejected"); expect(outcome.status).toBe("rejected");
@@ -298,7 +298,12 @@ describe("AcpxRuntime fresh reset wrapper", () => {
code: "ACP_SESSION_INIT_FAILED", code: "ACP_SESSION_INIT_FAILED",
message: expect.stringContaining("deployment missing"), message: expect.stringContaining("deployment missing"),
}); });
expect(outcome.error.message).not.toContain("sk-testsecret1234567890"); const error = outcome.error;
expect(error).toBeInstanceOf(AcpRuntimeError);
if (!(error instanceof AcpRuntimeError)) {
throw new Error("expected AcpRuntimeError");
}
expect(error.message).not.toContain("sk-testsecret1234567890");
}); });
it("adds Codex wrapper stderr tail to generic first-turn failures", async () => { it("adds Codex wrapper stderr tail to generic first-turn failures", async () => {

View File

@@ -218,13 +218,21 @@ describe("active-memory plugin", () => {
}; };
const waitForAbort = async (abortSignal?: AbortSignal): Promise<never> => { const waitForAbort = async (abortSignal?: AbortSignal): Promise<never> => {
if (abortSignal?.aborted) { if (abortSignal?.aborted) {
throw (abortSignal.reason as unknown) ?? new Error("Operation aborted"); throw toLintErrorObject(
(abortSignal.reason as unknown) ?? new Error("Operation aborted"),
"Non-Error thrown",
);
} }
return await new Promise<never>((_resolve, reject) => { return await new Promise<never>((_resolve, reject) => {
abortSignal?.addEventListener( abortSignal?.addEventListener(
"abort", "abort",
() => { () => {
reject((abortSignal.reason as unknown) ?? new Error("Operation aborted")); reject(
toLintErrorObject(
(abortSignal.reason as unknown) ?? new Error("Operation aborted"),
"Non-Error rejection",
),
);
}, },
{ once: true }, { once: true },
); );
@@ -4350,3 +4358,17 @@ describe("active-memory plugin", () => {
expect(config.circuitBreakerCooldownMs).toBe(5000); expect(config.circuitBreakerCooldownMs).toBe(5000);
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -1011,7 +1011,6 @@ function buildPromptStyleLines(style: ActiveMemoryPromptStyle): string[] {
"If relevant memory is mostly a stable user preference or recurring habit, lean toward returning it.", "If relevant memory is mostly a stable user preference or recurring habit, lean toward returning it.",
"If the strongest match is only a one-off historical fact and not a recurring preference or habit, prefer NONE unless the latest user message clearly asks for that fact.", "If the strongest match is only a one-off historical fact and not a recurring preference or habit, prefer NONE unless the latest user message clearly asks for that fact.",
]; ];
case "balanced":
default: default:
return [ return [
"Treat the latest user message as the primary query.", "Treat the latest user message as the primary query.",
@@ -1982,7 +1981,7 @@ async function waitForSubagentPartialTimeoutData(
(await Promise.race([ (await Promise.race([
subagentPromise.then( subagentPromise.then(
() => undefined, () => undefined,
(error) => readPartialTimeoutData(error), (error: unknown) => readPartialTimeoutData(error),
), ),
timeoutPromise, timeoutPromise,
])) ?? {} ])) ?? {}

View File

@@ -571,7 +571,7 @@ export async function startGatewayBonjourAdvertiser(
.then(() => { .then(() => {
logger.info(`bonjour: advertised ${serviceSummary(label, svc)}`); logger.info(`bonjour: advertised ${serviceSummary(label, svc)}`);
}) })
.catch((err) => { .catch((err: unknown) => {
handleAdvertiseFailure(label, svc, err, "failed"); handleAdvertiseFailure(label, svc, err, "failed");
}); });
} catch (err) { } catch (err) {
@@ -747,7 +747,7 @@ export async function startGatewayBonjourAdvertiser(
)})`, )})`,
); );
try { try {
void svc.advertise().catch((err) => { void svc.advertise().catch((err: unknown) => {
logger.warn( logger.warn(
`bonjour: watchdog re-advertise failed (${serviceSummary(label, svc)}): ${formatBonjourError(err)}`, `bonjour: watchdog re-advertise failed (${serviceSummary(label, svc)}): ${formatBonjourError(err)}`,
); );

View File

@@ -416,7 +416,8 @@ describe("cdp.helpers internal", () => {
await expect( await expect(
withCdpSocket(server.url, async (send) => { withCdpSocket(server.url, async (send) => {
await send("Test.ok"); await send("Test.ok");
const rejectRawString = () => Promise.reject("raw-string-from-callback"); const rejectRawString = () =>
Promise.reject(toLintErrorObject("raw-string-from-callback", "Non-Error rejection"));
return rejectRawString(); return rejectRawString();
}), }),
).rejects.toThrow(/raw-string-from-callback/); ).rejects.toThrow(/raw-string-from-callback/);
@@ -572,3 +573,17 @@ describe("openCdpWebSocket option handling", () => {
ws.close(); ws.close();
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -258,7 +258,7 @@ function extractJsonMessage(result: ChromeMcpToolResult): unknown {
} }
} }
if (lastError) { if (lastError) {
throw lastError; throw toLintErrorObject(lastError, "Non-Error thrown");
} }
return null; return null;
} }
@@ -629,7 +629,7 @@ async function closeChromeMcpClientAndProcess(params: {
return; return;
} }
await params.client.close().catch(() => {}); await params.client.close().catch(() => {});
await terminateChromeMcpProcessTree(rootPid, descendantPids).catch((err) => { await terminateChromeMcpProcessTree(rootPid, descendantPids).catch((err: unknown) => {
log.trace( log.trace(
`Unable to fully terminate Chrome MCP subprocess tree for pid ${rootPid}: ${err instanceof Error ? err.message : String(err)}`, `Unable to fully terminate Chrome MCP subprocess tree for pid ${rootPid}: ${err instanceof Error ? err.message : String(err)}`,
); );
@@ -761,7 +761,8 @@ async function waitForChromeMcpReady(
if (signal) { if (signal) {
racers.push( racers.push(
new Promise<never>((_, reject) => { new Promise<never>((_, reject) => {
abortListener = () => reject(signal.reason ?? new Error("aborted")); abortListener = () =>
reject(toLintErrorObject(signal.reason ?? new Error("aborted"), "Non-Error rejection"));
signal.addEventListener("abort", abortListener, { once: true }); signal.addEventListener("abort", abortListener, { once: true });
}), }),
); );
@@ -793,7 +794,8 @@ async function waitForChromeMcpPendingSession(
return await Promise.race([ return await Promise.race([
pending, pending,
new Promise<never>((_, reject) => { new Promise<never>((_, reject) => {
abortListener = () => reject(signal.reason ?? new Error("aborted")); abortListener = () =>
reject(toLintErrorObject(signal.reason ?? new Error("aborted"), "Non-Error rejection"));
signal.addEventListener("abort", abortListener, { once: true }); signal.addEventListener("abort", abortListener, { once: true });
}), }),
]); ]);
@@ -1022,7 +1024,8 @@ async function callTool(
if (signal) { if (signal) {
racers.push( racers.push(
new Promise<never>((_, reject) => { new Promise<never>((_, reject) => {
abortListener = () => reject(signal.reason ?? new Error("aborted")); abortListener = () =>
reject(toLintErrorObject(signal.reason ?? new Error("aborted"), "Non-Error rejection"));
signal.addEventListener("abort", abortListener, { once: true }); signal.addEventListener("abort", abortListener, { once: true });
}), }),
); );
@@ -1540,3 +1543,17 @@ export async function resetChromeMcpSessionsForTest(): Promise<void> {
await stopAllChromeMcpSessions(); await stopAllChromeMcpSessions();
chromeMcpProcessCleanupDepsForTest = null; chromeMcpProcessCleanupDepsForTest = null;
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -315,9 +315,17 @@ export async function fetchBrowserJson<T>(
let abortListener: (() => void) | undefined; let abortListener: (() => void) | undefined;
const abortPromise: Promise<never> = abortCtrl.signal.aborted const abortPromise: Promise<never> = abortCtrl.signal.aborted
? Promise.reject(abortCtrl.signal.reason ?? new Error("aborted")) ? Promise.reject(
toLintErrorObject(abortCtrl.signal.reason ?? new Error("aborted"), "Non-Error rejection"),
)
: new Promise((_, reject) => { : new Promise((_, reject) => {
abortListener = () => reject(abortCtrl.signal.reason ?? new Error("aborted")); abortListener = () =>
reject(
toLintErrorObject(
abortCtrl.signal.reason ?? new Error("aborted"),
"Non-Error rejection",
),
);
abortCtrl.signal.addEventListener("abort", abortListener, { once: true }); abortCtrl.signal.addEventListener("abort", abortListener, { once: true });
}); });
@@ -382,3 +390,17 @@ export const testApi = {
withLoopbackBrowserAuth: withLoopbackBrowserAuthImpl, withLoopbackBrowserAuth: withLoopbackBrowserAuthImpl,
}; };
export { testApi as __test }; export { testApi as __test };
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -1359,12 +1359,12 @@ export async function gotoPageWithNavigationGuard(
try { try {
const response = await opts.page.goto(opts.url, { timeout: opts.timeoutMs }); const response = await opts.page.goto(opts.url, { timeout: opts.timeoutMs });
if (blockedError) { if (blockedError) {
throw blockedError; throw toLintErrorObject(blockedError, "Non-Error thrown");
} }
return response; return response;
} catch (err) { } catch (err) {
if (blockedError) { if (blockedError) {
throw blockedError; throw toLintErrorObject(blockedError, "Non-Error thrown");
} }
throw err; throw err;
} finally { } finally {
@@ -1813,3 +1813,17 @@ export async function focusPageByTargetIdViaPlaywright(opts: {
} }
} }
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -192,7 +192,7 @@ async function assertObservedDelayedNavigations(opts: {
}); });
} }
if (subframeError) { if (subframeError) {
throw subframeError; throw toLintErrorObject(subframeError, "Non-Error thrown");
} }
} }
@@ -276,7 +276,7 @@ function scheduleDelayedInteractionNavigationGuard(opts: {
const settle = (err?: unknown) => { const settle = (err?: unknown) => {
cleanup(); cleanup();
if (err) { if (err) {
reject(err); reject(toLintErrorObject(err, "Non-Error rejection"));
return; return;
} }
resolve(); resolve();
@@ -428,11 +428,11 @@ async function assertInteractionNavigationCompletedSafely<T>(opts: {
} }
if (subframeError) { if (subframeError) {
throw subframeError; throw toLintErrorObject(subframeError, "Non-Error thrown");
} }
if (actionError) { if (actionError) {
throw actionError; throw toLintErrorObject(actionError, "Non-Error thrown");
} }
return result as T; return result as T;
} }
@@ -478,12 +478,14 @@ function createAbortPromiseWithListener(
const abortPromise: Promise<never> = signal.aborted const abortPromise: Promise<never> = signal.aborted
? (() => { ? (() => {
onAbort?.(signal.reason); onAbort?.(signal.reason);
return Promise.reject(signal.reason ?? new Error("aborted")); return Promise.reject(
toLintErrorObject(signal.reason ?? new Error("aborted"), "Non-Error rejection"),
);
})() })()
: new Promise((_, reject) => { : new Promise((_, reject) => {
abortListener = () => { abortListener = () => {
onAbort?.(signal.reason); onAbort?.(signal.reason);
reject(signal.reason ?? new Error("aborted")); reject(toLintErrorObject(signal.reason ?? new Error("aborted"), "Non-Error rejection"));
}; };
signal.addEventListener("abort", abortListener, { once: true }); signal.addEventListener("abort", abortListener, { once: true });
}); });
@@ -1712,3 +1714,17 @@ export async function batchViaPlaywright(opts: {
} }
return { results }; return { results };
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -178,7 +178,7 @@ async function runExistingSessionActionWithNavigationGuard<T>(params: {
} }
if (actionError) { if (actionError) {
throw actionError; throw toLintErrorObject(actionError, "Non-Error thrown");
} }
return result as T; return result as T;
@@ -809,3 +809,17 @@ export function registerBrowserAgentActRoutes(
}), }),
); );
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -701,7 +701,7 @@ export function registerBrowserAgentSnapshotRoutes(
const pw = await getPwAiModule(); const pw = await getPwAiModule();
const snap = plan.wantsRoleSnapshot const snap = plan.wantsRoleSnapshot
? pw ? pw
? await pw.snapshotRoleViaPlaywright(roleSnapshotArgs).catch(async (err) => { ? await pw.snapshotRoleViaPlaywright(roleSnapshotArgs).catch(async (err: unknown) => {
const fallback = await cdpRoleSnapshot(); const fallback = await cdpRoleSnapshot();
if (fallback) { if (fallback) {
return fallback; return fallback;

View File

@@ -20,10 +20,21 @@ describe("browser route dispatcher (abort)", () => {
const signal = req.signal; const signal = req.signal;
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
if (signal?.aborted) { if (signal?.aborted) {
reject(signal.reason ?? new Error("aborted")); reject(
toLintErrorObject(
signal.reason ?? new Error("aborted"),
"Non-Error rejection",
),
);
return; return;
} }
const onAbort = () => reject(signal?.reason ?? new Error("aborted")); const onAbort = () =>
reject(
toLintErrorObject(
signal?.reason ?? new Error("aborted"),
"Non-Error rejection",
),
);
signal?.addEventListener("abort", onAbort, { once: true }); signal?.addEventListener("abort", onAbort, { once: true });
queueMicrotask(() => { queueMicrotask(() => {
signal?.removeEventListener("abort", onAbort); signal?.removeEventListener("abort", onAbort);
@@ -81,3 +92,17 @@ describe("browser route dispatcher (abort)", () => {
expect(body.error).toBe("invalid path parameter encoding: id"); expect(body.error).toBe("invalid path parameter encoding: id");
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -66,7 +66,7 @@ export async function normalizeBrowserScreenshot(
} }
if (processorUnavailableError) { if (processorUnavailableError) {
throw processorUnavailableError; throw toLintErrorObject(processorUnavailableError, "Non-Error thrown");
} }
const best = smallest?.buffer ?? buffer; const best = smallest?.buffer ?? buffer;
@@ -74,3 +74,17 @@ export async function normalizeBrowserScreenshot(
`Browser screenshot could not be reduced below ${(maxBytes / (1024 * 1024)).toFixed(0)}MB (got ${(best.byteLength / (1024 * 1024)).toFixed(2)}MB)`, `Browser screenshot could not be reduced below ${(maxBytes / (1024 * 1024)).toFixed(0)}MB (got ${(best.byteLength / (1024 * 1024)).toFixed(2)}MB)`,
); );
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -377,7 +377,7 @@ export function createProfileTabOps({
method: "PUT", method: "PUT",
}, },
getCdpControlPolicy(), getCdpControlPolicy(),
).catch(async (err) => { ).catch(async (err: unknown) => {
if (String(err).includes("HTTP 405")) { if (String(err).includes("HTTP 405")) {
return await fetchJson<CdpTarget>( return await fetchJson<CdpTarget>(
endpoint, endpoint,

View File

@@ -57,7 +57,10 @@ vi.mock("../sdk-node-runtime.js", () => ({
new Promise<never>((_, reject) => { new Promise<never>((_, reject) => {
abortCtrl.signal.addEventListener( abortCtrl.signal.addEventListener(
"abort", "abort",
() => reject(abortCtrl.signal.reason ?? timeoutError), () =>
reject(
toLintErrorObject(abortCtrl.signal.reason ?? timeoutError, "Non-Error rejection"),
),
{ once: true }, { once: true },
); );
}), }),
@@ -490,3 +493,17 @@ describe("runBrowserProxyCommand", () => {
expect(dispatcherMocks.dispatch).not.toHaveBeenCalled(); expect(dispatcherMocks.dispatch).not.toHaveBeenCalled();
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -45,11 +45,14 @@ function waitForAbort(
cleanup: () => void; cleanup: () => void;
} { } {
if (signal.aborted) { if (signal.aborted) {
return { promise: Promise.reject(signal.reason ?? fallback), cleanup: () => undefined }; return {
promise: Promise.reject(toLintErrorObject(signal.reason ?? fallback, "Non-Error rejection")),
cleanup: () => undefined,
};
} }
let listener: (() => void) | undefined; let listener: (() => void) | undefined;
const promise = new Promise<never>((_, reject) => { const promise = new Promise<never>((_, reject) => {
listener = () => reject(signal.reason ?? fallback); listener = () => reject(toLintErrorObject(signal.reason ?? fallback, "Non-Error rejection"));
signal.addEventListener("abort", listener, { once: true }); signal.addEventListener("abort", listener, { once: true });
}); });
return { return {
@@ -82,3 +85,17 @@ export async function withTimeout<T>(
abort.cleanup(); abort.cleanup();
} }
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -84,7 +84,7 @@ export async function startBrowserControlServerFromConfig(): Promise<BrowserServ
const server = await new Promise<Server>((resolve, reject) => { const server = await new Promise<Server>((resolve, reject) => {
const s = app.listen(port, "127.0.0.1", () => resolve(s)); const s = app.listen(port, "127.0.0.1", () => resolve(s));
s.once("error", reject); s.once("error", reject);
}).catch((err) => { }).catch((err: unknown) => {
logServer.error(`openclaw browser server failed to bind 127.0.0.1:${port}: ${String(err)}`); logServer.error(`openclaw browser server failed to bind 127.0.0.1:${port}: ${String(err)}`);
return null; return null;
}); });

View File

@@ -193,8 +193,6 @@ async function pollBytePlusTask(params: {
throw new Error( throw new Error(
readBytePlusErrorMessage(payload.error) || "BytePlus video generation failed", readBytePlusErrorMessage(payload.error) || "BytePlus video generation failed",
); );
case "queued":
case "running":
default: default:
await waitProviderOperationPollInterval({ deadline, pollIntervalMs: POLL_INTERVAL_MS }); await waitProviderOperationPollInterval({ deadline, pollIntervalMs: POLL_INTERVAL_MS });
break; break;

View File

@@ -222,7 +222,9 @@ async function main() {
} }
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
await main().catch((error) => { await main().catch(
/** @param {unknown} error */ (error) => {
fail(error instanceof Error ? error.message : String(error)); fail(error instanceof Error ? error.message : String(error));
}); },
);
} }

View File

@@ -42,8 +42,10 @@ async function main() {
} }
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) { if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
main().catch((err) => { main().catch(
/** @param {unknown} err */ (err) => {
console.error(String(err)); console.error(String(err));
process.exit(1); process.exit(1);
}); },
);
} }

View File

@@ -487,7 +487,7 @@ export async function startCanvasHost(opts: CanvasHostServerOpts): Promise<Canva
res.statusCode = 404; res.statusCode = 404;
res.setHeader("Content-Type", "text/plain; charset=utf-8"); res.setHeader("Content-Type", "text/plain; charset=utf-8");
res.end("Not Found"); res.end("Not Found");
})().catch((err) => { })().catch((err: unknown) => {
opts.runtime.error(`Canvas host request failed: ${String(err)}`); opts.runtime.error(`Canvas host request failed: ${String(err)}`);
res.statusCode = 500; res.statusCode = 500;
res.setHeader("Content-Type", "text/plain; charset=utf-8"); res.setHeader("Content-Type", "text/plain; charset=utf-8");

View File

@@ -11,7 +11,7 @@ function formatErrorMessage(error: unknown): string {
} }
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) { if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
serveCodexSupervisorMcp().catch((err) => { serveCodexSupervisorMcp().catch((err: unknown) => {
process.stderr.write(`codex-supervisor-serve: ${formatErrorMessage(err)}\n`); process.stderr.write(`codex-supervisor-serve: ${formatErrorMessage(err)}\n`);
process.exit(1); process.exit(1);
}); });

View File

@@ -556,7 +556,7 @@ export class CodexNativeSubagentMonitor {
childState.transcriptPollTimer = setTimeout(() => { childState.transcriptPollTimer = setTimeout(() => {
childState.transcriptPollTimer = undefined; childState.transcriptPollTimer = undefined;
void this.reconcileChildTranscript(childState.childThreadId) void this.reconcileChildTranscript(childState.childThreadId)
.catch((error) => { .catch((error: unknown) => {
embeddedAgentLog.warn("Failed to reconcile Codex native subagent transcript", { embeddedAgentLog.warn("Failed to reconcile Codex native subagent transcript", {
childThreadId: childState.childThreadId, childThreadId: childState.childThreadId,
error: formatErrorMessage(error), error: formatErrorMessage(error),
@@ -595,7 +595,7 @@ export class CodexNativeSubagentMonitor {
} }
this.taskRowReconcileTimer = setInterval( this.taskRowReconcileTimer = setInterval(
() => { () => {
void this.reconcileKnownTaskRows().catch((error) => { void this.reconcileKnownTaskRows().catch((error: unknown) => {
embeddedAgentLog.warn("Failed to reconcile Codex native subagent task rows", { embeddedAgentLog.warn("Failed to reconcile Codex native subagent task rows", {
error: formatErrorMessage(error), error: formatErrorMessage(error),
}); });

View File

@@ -88,10 +88,10 @@ export async function waitForPluginApprovalDecision(params: {
let onAbort: (() => void) | undefined; let onAbort: (() => void) | undefined;
const abortPromise = new Promise<never>((_, reject) => { const abortPromise = new Promise<never>((_, reject) => {
if (params.signal!.aborted) { if (params.signal!.aborted) {
reject(params.signal!.reason); reject(toLintErrorObject(params.signal!.reason, "Non-Error rejection"));
return; return;
} }
onAbort = () => reject(params.signal!.reason); onAbort = () => reject(toLintErrorObject(params.signal!.reason, "Non-Error rejection"));
params.signal!.addEventListener("abort", onAbort, { once: true }); params.signal!.addEventListener("abort", onAbort, { once: true });
}); });
try { try {
@@ -121,3 +121,17 @@ export function mapExecDecisionToOutcome(
function truncateForGateway(value: string, maxLength: number): string { function truncateForGateway(value: string, maxLength: number): string {
return value.length <= maxLength ? value : `${value.slice(0, Math.max(0, maxLength - 3))}...`; return value.length <= maxLength ? value : `${value.slice(0, Math.max(0, maxLength - 3))}...`;
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -1037,7 +1037,7 @@ describe("runCodexAppServerAttempt context-engine lifecycle", () => {
await vi.waitFor( await vi.waitFor(
() => { () => {
if (runError) { if (runError) {
throw runError; throw toLintErrorObject(runError, "Non-Error thrown");
} }
expect(harness.requests.map((request) => request.method)).toContain("turn/start"); expect(harness.requests.map((request) => request.method)).toContain("turn/start");
}, },
@@ -1709,3 +1709,17 @@ describe("runCodexAppServerAttempt context-engine lifecycle", () => {
expect(maintain).not.toHaveBeenCalled(); expect(maintain).not.toHaveBeenCalled();
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -696,7 +696,7 @@ describe("runCodexAppServerAttempt", () => {
}); });
await expect( await expect(
client.request("turn/start", turnParams).catch(async (error) => { client.request("turn/start", turnParams).catch(async (error: unknown) => {
await releaseCodexSandboxExecServerEnvironment(sandbox); await releaseCodexSandboxExecServerEnvironment(sandbox);
throw error; throw error;
}), }),
@@ -763,7 +763,7 @@ describe("runCodexAppServerAttempt", () => {
nativeCodeModeOnlyEnabled: false, nativeCodeModeOnlyEnabled: false,
userMcpServersEnabled: false, userMcpServersEnabled: false,
environmentSelection, environmentSelection,
}).catch(async (error) => { }).catch(async (error: unknown) => {
await releaseCodexSandboxExecServerEnvironment(sandbox); await releaseCodexSandboxExecServerEnvironment(sandbox);
throw error; throw error;
}), }),
@@ -1237,7 +1237,7 @@ describe("runCodexAppServerAttempt", () => {
params.prompt = "already persisted prompt"; params.prompt = "already persisted prompt";
params.suppressNextUserMessagePersistence = true; params.suppressNextUserMessagePersistence = true;
const readTranscript = async () => const readTranscript = async () =>
fs.readFile(sessionFile, "utf8").catch((error) => { fs.readFile(sessionFile, "utf8").catch((error: unknown) => {
if ((error as NodeJS.ErrnoException).code === "ENOENT") { if ((error as NodeJS.ErrnoException).code === "ENOENT") {
return ""; return "";
} }

View File

@@ -94,9 +94,11 @@ export function createCodexUserInputBridge(params: {
resolvePending(emptyUserInputResponse()); resolvePending(emptyUserInputResponse());
return; return;
} }
void deliverUserInputPrompt(params.paramsForRun, requestParams.questions).catch((error) => { void deliverUserInputPrompt(params.paramsForRun, requestParams.questions).catch(
(error: unknown) => {
embeddedAgentLog.warn("failed to deliver codex user input prompt", { error }); embeddedAgentLog.warn("failed to deliver codex user input prompt", { error });
}); },
);
}); });
}, },
handleQueuedMessage(text) { handleQueuedMessage(text) {

View File

@@ -388,7 +388,8 @@ async function withPluginMigrationEligibility(params: {
return evaluated; return evaluated;
} }
const snapshot = await refreshSourceAppInventory(params.requestOptions).catch((error) => { const snapshot = await refreshSourceAppInventory(params.requestOptions).catch(
(error: unknown) => {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
for (const { plugin, apps } of pending) { for (const { plugin, apps } of pending) {
evaluated.push({ evaluated.push({
@@ -403,7 +404,8 @@ async function withPluginMigrationEligibility(params: {
}); });
} }
return undefined; return undefined;
}); },
);
if (!snapshot) { if (!snapshot) {
return evaluated; return evaluated;
} }

View File

@@ -1396,7 +1396,7 @@ describe("runCopilotAttempt", () => {
const sdk = makeFakeSdk(); const sdk = makeFakeSdk();
const pool = makeFakePool(sdk); const pool = makeFakePool(sdk);
pool.release = vi.fn(async () => { pool.release = vi.fn(async () => {
throw "release failed"; throw toLintErrorObject("release failed", "Non-Error thrown");
}); });
await expect(runCopilotAttempt(makeParams(), { pool })).rejects.toThrow("release failed"); await expect(runCopilotAttempt(makeParams(), { pool })).rejects.toThrow("release failed");
@@ -1414,7 +1414,7 @@ describe("runCopilotAttempt", () => {
}); });
const pool = makeFakePool(sdk); const pool = makeFakePool(sdk);
pool.release = vi.fn(async () => { pool.release = vi.fn(async () => {
throw "release failed"; throw toLintErrorObject("release failed", "Non-Error thrown");
}); });
const result = await runCopilotAttempt(makeParams(), { pool }); const result = await runCopilotAttempt(makeParams(), { pool });
@@ -2534,3 +2534,17 @@ describe("runCopilotAttempt", () => {
}); });
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -115,7 +115,7 @@ export function attachEventBridge(
}); });
deltaChain = deltaQueue.then(() => { deltaChain = deltaQueue.then(() => {
if (firstDeltaError !== undefined) { if (firstDeltaError !== undefined) {
throw firstDeltaError; throw toLintErrorObject(firstDeltaError, "Non-Error thrown");
} }
}); });
void deltaChain.catch(() => undefined); void deltaChain.catch(() => undefined);
@@ -354,3 +354,17 @@ function registerListener<K extends SessionEventType>(
session.off?.(eventType, handler as (...args: unknown[]) => void); session.off?.(eventType, handler as (...args: unknown[]) => void);
}); });
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -419,7 +419,7 @@ describe("createCopilotClientPool", () => {
it("normalizes non-Error stop failures during dispose", async () => { it("normalizes non-Error stop failures during dispose", async () => {
const sdk = makeFake({ const sdk = makeFake({
stop: () => { stop: () => {
throw "stop-string"; throw toLintErrorObject("stop-string", "Non-Error thrown");
}, },
}); });
const pool = createCopilotClientPool({ sdkFactory: sdk.fake }); const pool = createCopilotClientPool({ sdkFactory: sdk.fake });
@@ -485,3 +485,17 @@ describe("createCopilotClientPool", () => {
expect(String(sdk.ctorCalls[0]?.baseDirectory)).toBe(normalizedHome); expect(String(sdk.ctorCalls[0]?.baseDirectory)).toBe(normalizedHome);
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -30,7 +30,7 @@ export async function loadCopilotSdk(options: LoadCopilotSdkOptions = {}): Promi
const promise = doLoad(options); const promise = doLoad(options);
if (useCache) { if (useCache) {
cached = promise.catch((err) => { cached = promise.catch((err: unknown) => {
cached = undefined; cached = undefined;
throw err; throw err;
}); });

View File

@@ -204,7 +204,7 @@ describe("createTraceContextProvider", () => {
const onError = vi.fn(); const onError = vi.fn();
const provider = createTraceContextProvider({ const provider = createTraceContextProvider({
getTraceparent: () => { getTraceparent: () => {
throw "string-boom"; throw toLintErrorObject("string-boom", "Non-Error thrown");
}, },
onError, onError,
}); });
@@ -236,3 +236,17 @@ describe("createTraceContextProvider", () => {
expect(getTraceparent).not.toHaveBeenCalled(); expect(getTraceparent).not.toHaveBeenCalled();
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -504,11 +504,11 @@ export function createPairingNotifierService(api: OpenClawPluginApi): OpenClawPl
await notifyPendingPairingRequests({ api, statePath }); await notifyPendingPairingRequests({ api, statePath });
}; };
await tick().catch((err) => { await tick().catch((err: unknown) => {
api.logger.warn(`device-pair: initial notify poll failed: ${formatErrorMessage(err)}`); api.logger.warn(`device-pair: initial notify poll failed: ${formatErrorMessage(err)}`);
}); });
notifyInterval = setInterval(() => { notifyInterval = setInterval(() => {
tick().catch((err) => { tick().catch((err: unknown) => {
api.logger.warn(`device-pair: notify poll failed: ${formatErrorMessage(err)}`); api.logger.warn(`device-pair: notify poll failed: ${formatErrorMessage(err)}`);
}); });
}, NOTIFY_POLL_INTERVAL_MS); }, NOTIFY_POLL_INTERVAL_MS);

View File

@@ -331,7 +331,7 @@ async function resolveBrowserExecutablePath(config: OpenClawConfig): Promise<str
return await executablePathCache.valuePromise; return await executablePathCache.valuePromise;
} }
const valuePromise = resolveBrowserExecutablePathUncached(config).catch((error) => { const valuePromise = resolveBrowserExecutablePathUncached(config).catch((error: unknown) => {
if (executablePathCache?.valuePromise === valuePromise) { if (executablePathCache?.valuePromise === valuePromise) {
executablePathCache = null; executablePathCache = null;
} }
@@ -405,7 +405,7 @@ async function acquireSharedBrowser(params: {
} }
return browser; return browser;
}) })
.catch((error) => { .catch((error: unknown) => {
if (sharedBrowserState?.browserPromise === browserPromise) { if (sharedBrowserState?.browserPromise === browserPromise) {
sharedBrowserState = null; sharedBrowserState = null;
} }

View File

@@ -226,7 +226,7 @@ export class DiffArtifactStore {
this.nextCleanupAt = now + this.cleanupIntervalMs; this.nextCleanupAt = now + this.cleanupIntervalMs;
const cleanupPromise = this.cleanupExpired() const cleanupPromise = this.cleanupExpired()
.catch((error) => { .catch((error: unknown) => {
this.nextCleanupAt = 0; this.nextCleanupAt = 0;
this.logger?.warn(`Failed to clean expired diff artifacts: ${String(error)}`); this.logger?.warn(`Failed to clean expired diff artifacts: ${String(error)}`);
}) })

View File

@@ -163,7 +163,7 @@ describe("createDiscordRestClient proxy support", () => {
}, },
}) })
.catch((err: unknown) => { .catch((err: unknown) => {
reject(err); reject(toLintErrorObject(err, "Non-Error rejection"));
server.close(); server.close();
}); });
}); });
@@ -175,3 +175,17 @@ describe("createDiscordRestClient proxy support", () => {
expect(received.body).toContain('"attachments":[{"id":0,"filename":"image.png"}]'); expect(received.body).toContain('"attachments":[{"id":0,"filename":"image.png"}]');
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -153,7 +153,6 @@ export function mapButtonStyle(style?: DiscordComponentButtonStyle): ButtonStyle
return ButtonStyle.Danger; return ButtonStyle.Danger;
case "link": case "link":
return ButtonStyle.Link; return ButtonStyle.Link;
case "primary":
default: default:
return ButtonStyle.Primary; return ButtonStyle.Primary;
} }

View File

@@ -48,7 +48,7 @@ export async function waitForDiscordGatewayStop(
gateway?.disconnect?.(); gateway?.disconnect?.();
} finally { } finally {
cleanup(); cleanup();
reject(err); reject(toLintErrorObject(err, "Non-Error rejection"));
} }
}; };
const onAbort = () => { const onAbort = () => {
@@ -73,3 +73,17 @@ export async function waitForDiscordGatewayStop(
params.registerForceStop?.(onForceStop); params.registerForceStop?.(onForceStop);
}); });
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -59,7 +59,7 @@ export function queueInitialDiscordAckReaction(params: {
if (!params.shouldSendAckReaction || !params.ackReaction) { if (!params.shouldSendAckReaction || !params.ackReaction) {
return; return;
} }
void params.reactionAdapter.setReaction(params.ackReaction).catch((err) => { void params.reactionAdapter.setReaction(params.ackReaction).catch((err: unknown) => {
logAckFailure({ logAckFailure({
log: logVerbose, log: logVerbose,
channel: "discord", channel: "discord",

View File

@@ -239,7 +239,9 @@ function createGatewayPlugin(params: {
info, info,
usedFallback: false, usedFallback: false,
})) }))
.catch((error) => resolveGatewayInfoWithFallback({ runtime: params.runtime, error })); .catch((error: unknown) =>
resolveGatewayInfoWithFallback({ runtime: params.runtime, error }),
);
this.gatewayInfo = resolved.info; this.gatewayInfo = resolved.info;
this.gatewayInfoUsedFallback = resolved.usedFallback; this.gatewayInfoUsedFallback = resolved.usedFallback;
} }

View File

@@ -47,7 +47,7 @@ export class DiscordMessageListener extends MessageCreateListener {
// Per-session ordering is owned by the message run queue. // Per-session ordering is owned by the message run queue.
void Promise.resolve() void Promise.resolve()
.then(() => this.handler(data, client)) .then(() => this.handler(data, client))
.catch((err) => { .catch((err: unknown) => {
const logger = this.logger ?? discordEventQueueLog; const logger = this.logger ?? discordEventQueueLog;
logger.error(danger(`discord handler failed: ${String(err)}`)); logger.error(danger(`discord handler failed: ${String(err)}`));
}); });
@@ -68,7 +68,7 @@ export class DiscordInteractionListener extends InteractionCreateListener {
// or compaction without blocking later gateway events. // or compaction without blocking later gateway events.
void Promise.resolve() void Promise.resolve()
.then(() => client.handleInteraction(data as Parameters<Client["handleInteraction"]>[0], {})) .then(() => client.handleInteraction(data as Parameters<Client["handleInteraction"]>[0], {}))
.catch((err) => { .catch((err: unknown) => {
const logger = this.logger ?? discordEventQueueLog; const logger = this.logger ?? discordEventQueueLog;
logger.error(danger(`discord interaction handler failed: ${String(err)}`)); logger.error(danger(`discord interaction handler failed: ${String(err)}`));
}); });

View File

@@ -113,7 +113,7 @@ function startAcceptedTypingFeedback(params: {
}; };
activeFeedback.set(dedupeKey, { channelId, feedback: replyTypingFeedback }); activeFeedback.set(dedupeKey, { channelId, feedback: replyTypingFeedback });
ctx.replyTypingFeedback = replyTypingFeedback; ctx.replyTypingFeedback = replyTypingFeedback;
void replyTypingFeedback.onReplyStart().catch((err) => { void replyTypingFeedback.onReplyStart().catch((err: unknown) => {
logVerbose(`discord accepted typing feedback failed: ${String(err)}`); logVerbose(`discord accepted typing feedback failed: ${String(err)}`);
}); });
return replyTypingFeedback; return replyTypingFeedback;

View File

@@ -267,7 +267,7 @@ async function fetchDiscordMedia(params: {
fallbackContentType: params.fallbackContentType, fallbackContentType: params.fallbackContentType,
originalFilename: params.originalFilename, originalFilename: params.originalFilename,
...(signal ? { requestInit: { signal } } : {}), ...(signal ? { requestInit: { signal } } : {}),
}).catch((error) => { }).catch((error: unknown) => {
if (timedOut) { if (timedOut) {
return new Promise<never>(() => {}); return new Promise<never>(() => {});
} }
@@ -365,8 +365,6 @@ function resolveStickerAssetCandidates(sticker: APIStickerItem): DiscordStickerA
fileName: `${baseName}.json`, fileName: `${baseName}.json`,
}, },
]; ];
case StickerFormatType.APNG:
case StickerFormatType.PNG:
default: default:
return [ return [
{ url: `${DISCORD_STICKER_ASSET_BASE_URL}/${sticker.id}.png`, fileName: `${baseName}.png` }, { url: `${DISCORD_STICKER_ASSET_BASE_URL}/${sticker.id}.png`, fileName: `${baseName}.png` },

View File

@@ -727,7 +727,9 @@ describe("runDiscordGatewayLifecycle", () => {
waitForDiscordGatewayStopMock.mockImplementationOnce( waitForDiscordGatewayStopMock.mockImplementationOnce(
(params: WaitForDiscordGatewayStopParams) => (params: WaitForDiscordGatewayStopParams) =>
new Promise<void>((_resolve, reject) => { new Promise<void>((_resolve, reject) => {
params.registerForceStop?.((err) => reject(err)); params.registerForceStop?.((err) =>
reject(toLintErrorObject(err, "Non-Error rejection")),
);
gateway.isConnected = false; gateway.isConnected = false;
emitter.emit("debug", "Gateway websocket opened"); emitter.emit("debug", "Gateway websocket opened");
}), }),
@@ -755,3 +757,17 @@ describe("runDiscordGatewayLifecycle", () => {
} }
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -365,7 +365,7 @@ export async function writeVoiceWavFile(
function scheduleTempCleanup(tempDir: string, delayMs: number = 30 * 60 * 1000): void { function scheduleTempCleanup(tempDir: string, delayMs: number = 30 * 60 * 1000): void {
const timer = setTimeout(() => { const timer = setTimeout(() => {
fs.rm(tempDir, { recursive: true, force: true }).catch((err) => { fs.rm(tempDir, { recursive: true, force: true }).catch((err: unknown) => {
if (shouldLogVerbose()) { if (shouldLogVerbose()) {
logVerbose(`discord voice: temp cleanup failed for ${tempDir}: ${formatErrorMessage(err)}`); logVerbose(`discord voice: temp cleanup failed for ${tempDir}: ${formatErrorMessage(err)}`);
} }

View File

@@ -221,7 +221,9 @@ function isUnknownDiscordVoiceStateError(err: unknown): boolean {
function startAutoJoin(manager: Pick<DiscordVoiceManager, "autoJoin">) { function startAutoJoin(manager: Pick<DiscordVoiceManager, "autoJoin">) {
void manager void manager
.autoJoin() .autoJoin()
.catch((err) => logger.warn(`discord voice: autoJoin failed: ${formatErrorMessage(err)}`)); .catch((err: unknown) =>
logger.warn(`discord voice: autoJoin failed: ${formatErrorMessage(err)}`),
);
} }
function resolveDiscordVoiceAgentRoute(params: { function resolveDiscordVoiceAgentRoute(params: {
@@ -782,7 +784,7 @@ export class DiscordVoiceManager {
} }
const speakingHandler: ((userId: string) => void) | undefined = (userId: string) => { const speakingHandler: ((userId: string) => void) | undefined = (userId: string) => {
void this.handleSpeakingStart(entry, userId).catch((err) => { void this.handleSpeakingStart(entry, userId).catch((err: unknown) => {
logger.warn(`discord voice: capture failed: ${formatErrorMessage(err)}`); logger.warn(`discord voice: capture failed: ${formatErrorMessage(err)}`);
}); });
}; };
@@ -1134,7 +1136,7 @@ export class DiscordVoiceManager {
return; return;
} }
this.followUsersReconcileTimer = setInterval(() => { this.followUsersReconcileTimer = setInterval(() => {
void this.reconcileFollowedUsers("interval").catch((err) => { void this.reconcileFollowedUsers("interval").catch((err: unknown) => {
logger.warn(`discord voice: follow user reconciliation failed: ${formatErrorMessage(err)}`); logger.warn(`discord voice: follow user reconciliation failed: ${formatErrorMessage(err)}`);
}); });
}, FOLLOW_USERS_RECONCILE_INTERVAL_MS); }, FOLLOW_USERS_RECONCILE_INTERVAL_MS);
@@ -1176,7 +1178,7 @@ export class DiscordVoiceManager {
this.params.client.rest, this.params.client.rest,
plan.guildId, plan.guildId,
userId, userId,
).catch((err) => { ).catch((err: unknown) => {
if (!isUnknownDiscordVoiceStateError(err)) { if (!isUnknownDiscordVoiceStateError(err)) {
logger.warn( logger.warn(
`discord voice: follow user reconcile skipped transient voice state error guild=${plan.guildId} user=${userId} reason=${reason}: ${formatErrorMessage(err)}`, `discord voice: follow user reconcile skipped transient voice state error guild=${plan.guildId} user=${userId} reason=${reason}: ${formatErrorMessage(err)}`,
@@ -1415,7 +1417,7 @@ export class DiscordVoiceManager {
this.params.client.rest, this.params.client.rest,
guildId, guildId,
this.botUserId, this.botUserId,
).catch((err) => { ).catch((err: unknown) => {
if (!isUnknownDiscordVoiceStateError(err)) { if (!isUnknownDiscordVoiceStateError(err)) {
logger.warn( logger.warn(
`discord voice: follow reconcile skipped transient bot voice state error guild=${guildId} reason=${reason}: ${formatErrorMessage(err)}`, `discord voice: follow reconcile skipped transient bot voice state error guild=${guildId} reason=${reason}: ${formatErrorMessage(err)}`,
@@ -1473,13 +1475,17 @@ export class DiscordVoiceManager {
private enqueueProcessing(entry: VoiceSessionEntry, task: () => Promise<void>) { private enqueueProcessing(entry: VoiceSessionEntry, task: () => Promise<void>) {
entry.processingQueue = entry.processingQueue entry.processingQueue = entry.processingQueue
.then(task) .then(task)
.catch((err) => logger.warn(`discord voice: processing failed: ${formatErrorMessage(err)}`)); .catch((err: unknown) =>
logger.warn(`discord voice: processing failed: ${formatErrorMessage(err)}`),
);
} }
private enqueuePlayback(entry: VoiceSessionEntry, task: () => Promise<void>) { private enqueuePlayback(entry: VoiceSessionEntry, task: () => Promise<void>) {
entry.playbackQueue = entry.playbackQueue entry.playbackQueue = entry.playbackQueue
.then(task) .then(task)
.catch((err) => logger.warn(`discord voice: playback failed: ${formatErrorMessage(err)}`)); .catch((err: unknown) =>
logger.warn(`discord voice: playback failed: ${formatErrorMessage(err)}`),
);
} }
private clearCaptureFinalizeTimer(entry: VoiceSessionEntry, userId: string, generation?: number) { private clearCaptureFinalizeTimer(entry: VoiceSessionEntry, userId: string, generation?: number) {
@@ -1789,7 +1795,7 @@ export class DiscordVoiceManager {
return; return;
} }
void this.recoverFromDecryptFailures(entry) void this.recoverFromDecryptFailures(entry)
.catch((recoverErr) => .catch((recoverErr: unknown) =>
logger.warn(`discord voice: decrypt recovery failed: ${formatErrorMessage(recoverErr)}`), logger.warn(`discord voice: decrypt recovery failed: ${formatErrorMessage(recoverErr)}`),
) )
.finally(() => { .finally(() => {

View File

@@ -15,7 +15,7 @@ async function loadPdfEngine(): Promise<PdfEngine> {
if (!pdfEnginePromise) { if (!pdfEnginePromise) {
pdfEnginePromise = import("clawpdf") pdfEnginePromise = import("clawpdf")
.then(({ createEngine }) => createEngine()) .then(({ createEngine }) => createEngine())
.catch((err) => { .catch((err: unknown) => {
pdfEnginePromise = null; pdfEnginePromise = null;
throw new Error("Dependency clawpdf is required for PDF extraction", { throw new Error("Dependency clawpdf is required for PDF extraction", {
cause: err, cause: err,

View File

@@ -112,7 +112,6 @@ export function resolveFeishuGroupSession(params: {
}) })
: buildFeishuConversationId({ chatId, scope: "group_sender", senderOpenId }); : buildFeishuConversationId({ chatId, scope: "group_sender", senderOpenId });
break; break;
case "group":
default: default:
peerId = chatId; peerId = chatId;
break; break;

View File

@@ -918,7 +918,7 @@ export async function handleFeishuMessage(params: {
replyToMessageId: replyTargetMessageId, replyToMessageId: replyTargetMessageId,
replyInThread: isGroup ? (groupSession?.replyInThread ?? false) : false, replyInThread: isGroup ? (groupSession?.replyInThread ?? false) : false,
accountId: account.accountId, accountId: account.accountId,
}).catch((err) => { }).catch((err: unknown) => {
log(`feishu[${account.accountId}]: failed to send ACP init error reply: ${String(err)}`); log(`feishu[${account.accountId}]: failed to send ACP init error reply: ${String(err)}`);
}); });
return; return;

View File

@@ -37,7 +37,6 @@ export function buildFeishuConversationId(params: {
return `${chatId}:topic:${topicId}`; return `${chatId}:topic:${topicId}`;
} }
return senderOpenId ? `${chatId}:sender:${senderOpenId}` : chatId; return senderOpenId ? `${chatId}:sender:${senderOpenId}` : chatId;
case "group":
default: default:
return chatId; return chatId;
} }

View File

@@ -272,7 +272,7 @@ function registerEventHandlers(
const error = runtime?.error ?? console.error; const error = runtime?.error ?? console.error;
const runFeishuHandler = async (params: { task: () => Promise<void>; errorMessage: string }) => { const runFeishuHandler = async (params: { task: () => Promise<void>; errorMessage: string }) => {
if (fireAndForget) { if (fireAndForget) {
void params.task().catch((err) => { void params.task().catch((err: unknown) => {
error(`${params.errorMessage}: ${String(err)}`); error(`${params.errorMessage}: ${String(err)}`);
}); });
return; return;
@@ -417,7 +417,7 @@ function registerEventHandlers(
accountId, accountId,
}); });
if (fireAndForget) { if (fireAndForget) {
promise.catch((err) => { promise.catch((err: unknown) => {
error(`feishu[${accountId}]: error handling card action: ${String(err)}`); error(`feishu[${accountId}]: error handling card action: ${String(err)}`);
}); });
} else { } else {

View File

@@ -138,7 +138,7 @@ export function createFeishuBotMenuHandler(params: {
} }
return await handleLegacyMenu(); return await handleLegacyMenu();
}) })
.catch(async (err) => { .catch(async (err: unknown) => {
if (isFeishuRetryableSyntheticEventError(err)) { if (isFeishuRetryableSyntheticEventError(err)) {
await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log); await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log);
} else { } else {
@@ -150,7 +150,7 @@ export function createFeishuBotMenuHandler(params: {
releaseFeishuMessageProcessing(syntheticMessageId, accountId); releaseFeishuMessageProcessing(syntheticMessageId, accountId);
}); });
if (fireAndForget) { if (fireAndForget) {
promise.catch((err) => { promise.catch((err: unknown) => {
error(`feishu[${accountId}]: error handling bot menu event: ${String(err)}`); error(`feishu[${accountId}]: error handling bot menu event: ${String(err)}`);
}); });
return; return;

View File

@@ -35,7 +35,7 @@ export function createFeishuDriveCommentNoticeHandler(params: {
const getBotOpenId = params.getBotOpenId ?? ((id) => botOpenIds.get(id)); const getBotOpenId = params.getBotOpenId ?? ((id) => botOpenIds.get(id));
const runFeishuHandler = async (task: () => Promise<void>) => { const runFeishuHandler = async (task: () => Promise<void>) => {
const promise = task().catch((err) => { const promise = task().catch((err: unknown) => {
error(`feishu[${accountId}]: error handling drive comment notice: ${String(err)}`); error(`feishu[${accountId}]: error handling drive comment notice: ${String(err)}`);
}); });
if (!fireAndForget) { if (!fireAndForget) {

View File

@@ -331,7 +331,7 @@ async function resolveParsedCommentContent(params: {
resolvedObjToken: objToken, resolvedObjToken: objToken,
}; };
}) })
.catch((error) => { .catch((error: unknown) => {
params.logger?.( params.logger?.(
`feishu[${params.accountId}]: wiki link resolution threw token=${link.wikiNodeToken} error=${formatErrorMessage(error)}`, `feishu[${params.accountId}]: wiki link resolution threw token=${link.wikiNodeToken} error=${formatErrorMessage(error)}`,
); );
@@ -485,7 +485,7 @@ async function requestFeishuOpenApi<T>(params: {
{ timeoutMs: params.timeoutMs }, { timeoutMs: params.timeoutMs },
) )
.then((resolved) => (resolved.status === "resolved" ? resolved.value : null)) .then((resolved) => (resolved.status === "resolved" ? resolved.value : null))
.catch((error) => { .catch((error: unknown) => {
params.logger?.(`${params.errorLabel}: ${formatErrorDetails(error)}`); params.logger?.(`${params.errorLabel}: ${formatErrorDetails(error)}`);
return null; return null;
}); });

View File

@@ -329,7 +329,7 @@ export function createFeishuMessageReceiveHandler({
await inboundDebouncer.enqueue(event); await inboundDebouncer.enqueue(event);
}; };
if (fireAndForget) { if (fireAndForget) {
void processMessage().catch((err) => { void processMessage().catch((err: unknown) => {
releaseFeishuMessageProcessing(messageDedupeKey, accountId); releaseFeishuMessageProcessing(messageDedupeKey, accountId);
error(`feishu[${accountId}]: error handling message: ${String(err)}`); error(`feishu[${accountId}]: error handling message: ${String(err)}`);
}); });

View File

@@ -79,7 +79,7 @@ async function waitForSlowBodyTimeoutResponse(
socket.setEncoding("utf8"); socket.setEncoding("utf8");
socket.on("error", () => {}); socket.on("error", () => {});
socket.on("data", (chunk) => { socket.on("data", (chunk) => {
response += chunk; response += chunk.toString();
if (response.includes("Request body timeout")) { if (response.includes("Request body timeout")) {
clearTimeout(failTimer); clearTimeout(failTimer);
socket.destroy(); socket.destroy();
@@ -127,7 +127,7 @@ async function waitForOversizedBodyResponse(url: string): Promise<string> {
socket.setEncoding("utf8"); socket.setEncoding("utf8");
socket.on("data", (chunk) => { socket.on("data", (chunk) => {
response += chunk; response += chunk.toString();
if (response.includes("Payload too large")) { if (response.includes("Payload too large")) {
finish(response); finish(response);
} }

View File

@@ -18,7 +18,6 @@ function resolveFeishuParentConversationCandidates(rawId: string): string[] {
case "group_topic": case "group_topic":
case "group_sender": case "group_sender":
return [parsed.chatId]; return [parsed.chatId];
case "group":
default: default:
return []; return [];
} }

View File

@@ -520,7 +520,7 @@ export class FeishuStreamingSession {
.then(async ({ release }) => { .then(async ({ release }) => {
await release(); await release();
}) })
.catch((e) => this.log?.(`Note update failed: ${String(e)}`)); .catch((e: unknown) => this.log?.(`Note update failed: ${String(e)}`));
} }
async close(finalText?: string, options?: { note?: string }): Promise<boolean> { async close(finalText?: string, options?: { note?: string }): Promise<boolean> {
@@ -584,7 +584,7 @@ export class FeishuStreamingSession {
.then(async ({ release }) => { .then(async ({ release }) => {
await release(); await release();
}) })
.catch((e) => this.log?.(`Close failed: ${String(e)}`)); .catch((e: unknown) => this.log?.(`Close failed: ${String(e)}`));
const finalState = this.state; const finalState = this.state;
this.state = null; this.state = null;
this.pendingText = null; this.pendingText = null;

View File

@@ -144,7 +144,7 @@ export function handleGoogleMeetRealtimeConsultToolCall(params: {
}); });
params.session.submitToolResult(callId, result); params.session.submitToolResult(callId, result);
}) })
.catch((error: Error) => { .catch((error: unknown) => {
params.onTalkEvent?.({ params.onTalkEvent?.({
type: "tool.error", type: "tool.error",
callId, callId,

View File

@@ -277,7 +277,7 @@ export async function startNodeAgentAudioBridge(params: {
), ),
); );
}) })
.catch((error) => { .catch((error: unknown) => {
params.logger.warn(`[google-meet] node agent TTS failed: ${formatErrorMessage(error)}`); params.logger.warn(`[google-meet] node agent TTS failed: ${formatErrorMessage(error)}`);
}); });
}; };
@@ -557,7 +557,7 @@ export async function startNodeRealtimeAudioBridge(params: {
}, },
timeoutMs: 5_000, timeoutMs: 5_000,
}) })
.catch((error) => { .catch((error: unknown) => {
params.logger.warn( params.logger.warn(
`[google-meet] node audio output failed: ${formatErrorMessage(error)}`, `[google-meet] node audio output failed: ${formatErrorMessage(error)}`,
); );
@@ -580,7 +580,7 @@ export async function startNodeRealtimeAudioBridge(params: {
}, },
timeoutMs: 5_000, timeoutMs: 5_000,
}) })
.catch((error) => { .catch((error: unknown) => {
params.logger.warn( params.logger.warn(
`[google-meet] node audio clear failed: ${formatErrorMessage(error)}`, `[google-meet] node audio clear failed: ${formatErrorMessage(error)}`,
); );

View File

@@ -696,7 +696,7 @@ export async function startCommandAgentAudioBridge(params: {
}); });
endTalkTurn(); endTalkTurn();
}) })
.catch((error) => { .catch((error: unknown) => {
params.logger.warn(`[google-meet] agent TTS failed: ${formatErrorMessage(error)}`); params.logger.warn(`[google-meet] agent TTS failed: ${formatErrorMessage(error)}`);
}); });
}; };

View File

@@ -68,7 +68,7 @@ async function createConnectedGatewayClient(
reject(new Error("gateway event loop readiness timeout")); reject(new Error("gateway event loop readiness timeout"));
} }
}) })
.catch((err) => { .catch((err: unknown) => {
clearTimeout(timer); clearTimeout(timer);
reject(err instanceof Error ? err : new Error(String(err))); reject(err instanceof Error ? err : new Error(String(err)));
}); });

View File

@@ -140,7 +140,7 @@ describeLive("google plugin live", () => {
} }
} }
if (lastError) { if (lastError) {
throw lastError; throw toLintErrorObject(lastError, "Non-Error thrown");
} }
expect(result?.provider).toBe("gemini"); expect(result?.provider).toBe("gemini");
@@ -177,3 +177,17 @@ describeLive("google plugin live", () => {
}); });
}, 120_000); }, 120_000);
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -637,7 +637,12 @@ describe("google transport stream", () => {
(_url: string, init?: RequestInit) => (_url: string, init?: RequestInit) =>
new Promise<Response>((_resolve, reject) => { new Promise<Response>((_resolve, reject) => {
init?.signal?.addEventListener("abort", () => { init?.signal?.addEventListener("abort", () => {
reject(init.signal?.reason ?? new Error("aborted")); reject(
toLintErrorObject(
init.signal?.reason ?? new Error("aborted"),
"Non-Error rejection",
),
);
}); });
}), }),
) )
@@ -1984,3 +1989,17 @@ describe("google transport stream", () => {
]); ]);
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -287,7 +287,7 @@ export function createGoogleChatWebhookRequestHandler(params: {
const dispatchTarget = selectedTarget; const dispatchTarget = selectedTarget;
dispatchTarget.statusSink?.({ lastInboundAt: Date.now() }); dispatchTarget.statusSink?.({ lastInboundAt: Date.now() });
params.processEvent(parsedEvent, dispatchTarget).catch((err) => { params.processEvent(parsedEvent, dispatchTarget).catch((err: unknown) => {
dispatchTarget.runtime.error?.( dispatchTarget.runtime.error?.(
`[${dispatchTarget.account.accountId}] Google Chat webhook failed: ${String(err)}`, `[${dispatchTarget.account.accountId}] Google Chat webhook failed: ${String(err)}`,
); );

View File

@@ -132,7 +132,7 @@ describe("monitorIMessageProvider watch.subscribe startup retry", () => {
const monitorErrorPromise = monitorIMessageProvider({ const monitorErrorPromise = monitorIMessageProvider({
config: { channels: { imessage: {} } } as never, config: { channels: { imessage: {} } } as never,
runtime: runtime as never, runtime: runtime as never,
}).catch((error) => error); }).catch((error: unknown) => error);
await vi.runAllTimersAsync(); await vi.runAllTimersAsync();
const monitorError = await monitorErrorPromise; const monitorError = await monitorErrorPromise;

View File

@@ -1036,7 +1036,7 @@ export async function monitorIMessageProvider(opts: MonitorIMessageOpts = {}): P
runtime, runtime,
onNotification: (msg) => { onNotification: (msg) => {
if (msg.method === "message") { if (msg.method === "message") {
void handleMessage(msg.params).catch((err) => { void handleMessage(msg.params).catch((err: unknown) => {
runtime.error?.(`imessage: handler failed: ${String(err)}`); runtime.error?.(`imessage: handler failed: ${String(err)}`);
}); });
} else if (msg.method === "error") { } else if (msg.method === "error") {

View File

@@ -376,7 +376,7 @@ export async function connectIrcClient(options: IrcClientOptions): Promise<IrcCl
text, text,
rawLine, rawLine,
}), }),
).catch((error) => { ).catch((error: unknown) => {
fail(error); fail(error);
}); });
} }

View File

@@ -615,6 +615,20 @@ export async function handleLineWebhookEvents(
} }
} }
if (firstError) { if (firstError) {
throw firstError; throw toLintErrorObject(firstError, "Non-Error thrown");
} }
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -437,7 +437,7 @@ export async function monitorLineProvider(
logVerbose(`line: received ${body.events.length} webhook events`); logVerbose(`line: received ${body.events.length} webhook events`);
void Promise.resolve() void Promise.resolve()
.then(() => match.target.bot.handleWebhook(body)) .then(() => match.target.bot.handleWebhook(body))
.catch((err) => { .catch((err: unknown) => {
match.target.runtime.error?.( match.target.runtime.error?.(
danger(`line webhook dispatch failed: ${String(err)}`), danger(`line webhook dispatch failed: ${String(err)}`),
); );

View File

@@ -224,7 +224,7 @@ async function pushLineMessages(
}); });
if (behavior.errorContext) { if (behavior.errorContext) {
await pushRequest.catch((err) => { await pushRequest.catch((err: unknown) => {
logLineHttpError(err, behavior.errorContext!); logLineHttpError(err, behavior.errorContext!);
throw err; throw err;
}); });
@@ -301,7 +301,6 @@ export async function sendMessageLine(
case "audio": case "audio":
messages.push(createAudioMessage(mediaUrl, opts.durationMs ?? 60000)); messages.push(createAudioMessage(mediaUrl, opts.durationMs ?? 60000));
break; break;
case "image":
default: default:
// Backward compatibility: keep image as default when media kind is unspecified. // Backward compatibility: keep image as default when media kind is unspecified.
{ {

View File

@@ -128,7 +128,7 @@ export function createLineNodeWebhookHandler(params: {
logVerbose(`line: received ${body.events.length} webhook events`); logVerbose(`line: received ${body.events.length} webhook events`);
void Promise.resolve() void Promise.resolve()
.then(() => params.bot.handleWebhook(body)) .then(() => params.bot.handleWebhook(body))
.catch((err) => logLineWebhookDispatchError(params.runtime, err)); .catch((err: unknown) => logLineWebhookDispatchError(params.runtime, err));
} }
} catch (err) { } catch (err) {
await receiveContext?.nack(err); await receiveContext?.nack(err);

View File

@@ -93,7 +93,7 @@ export function createLineWebhookMiddleware(
logVerbose(`line: received ${body.events.length} webhook events`); logVerbose(`line: received ${body.events.length} webhook events`);
void Promise.resolve() void Promise.resolve()
.then(() => onEvents(body)) .then(() => onEvents(body))
.catch((err) => logLineWebhookDispatchError(runtime, err)); .catch((err: unknown) => logLineWebhookDispatchError(runtime, err));
} }
} catch (err) { } catch (err) {
await receiveContext?.nack(err); await receiveContext?.nack(err);

View File

@@ -217,7 +217,7 @@ export function wrapLmstudioInferencePreload(ctx: ProviderWrapStreamFnContext):
() => { () => {
recordPreloadSuccess(preloadKey); recordPreloadSuccess(preloadKey);
}, },
(error) => { (error: unknown) => {
const entry = recordPreloadFailure(preloadKey, Date.now()); const entry = recordPreloadFailure(preloadKey, Date.now());
throw Object.assign(new Error("preload-failed"), { throw Object.assign(new Error("preload-failed"), {
cause: error, cause: error,

View File

@@ -583,7 +583,12 @@ describe("createEmbeddedLobsterRunner", () => {
); );
ctx?.signal?.addEventListener("abort", () => { ctx?.signal?.addEventListener("abort", () => {
clearTimeout(timeout); clearTimeout(timeout);
reject(ctx.signal?.reason ?? new Error("aborted")); reject(
toLintErrorObject(
ctx.signal?.reason ?? new Error("aborted"),
"Non-Error rejection",
),
);
}); });
}), }),
), ),
@@ -605,3 +610,17 @@ describe("createEmbeddedLobsterRunner", () => {
).rejects.toThrow(/timed out|aborted/); ).rejects.toThrow(/timed out|aborted/);
}); });
}); });
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -286,9 +286,9 @@ async function withTimeout<T>(
clearTimeout(timer); clearTimeout(timer);
resolve(value); resolve(value);
}, },
(error) => { (error: unknown) => {
clearTimeout(timer); clearTimeout(timer);
reject(error); reject(toLintErrorObject(error, "Non-Error rejection"));
}, },
); );
}); });
@@ -392,3 +392,17 @@ export function createEmbeddedLobsterRunner(options?: {
}, },
}; };
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -259,7 +259,7 @@ export class FileBackedMatrixSyncStore extends MemoryStore {
} }
this.persistTimer = setTimeout(() => { this.persistTimer = setTimeout(() => {
this.persistTimer = null; this.persistTimer = null;
void this.flush().catch((err) => { void this.flush().catch((err: unknown) => {
LogService.warn("MatrixFileSyncStore", "Failed to persist Matrix sync store:", err); LogService.warn("MatrixFileSyncStore", "Failed to persist Matrix sync store:", err);
}); });
}, PERSIST_DEBOUNCE_MS); }, PERSIST_DEBOUNCE_MS);

View File

@@ -112,7 +112,7 @@ function createHarness(params?: {
const runDetachedTask = vi.fn((_label: string, task: () => Promise<void>) => { const runDetachedTask = vi.fn((_label: string, task: () => Promise<void>) => {
const promise = Promise.resolve() const promise = Promise.resolve()
.then(task) .then(task)
.catch((error) => { .catch((error: unknown) => {
throw error; throw error;
}) })
.finally(() => { .finally(() => {

View File

@@ -230,7 +230,7 @@ export function registerMatrixMonitorEvents(params: {
} }
return Promise.resolve() return Promise.resolve()
.then(task) .then(task)
.catch((error) => { .catch((error: unknown) => {
logVerboseMessage(`matrix: ${label} failed (${String(error)})`); logVerboseMessage(`matrix: ${label} failed (${String(error)})`);
}); });
}; };

View File

@@ -905,12 +905,14 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
if (!isPollEvent) { if (!isPollEvent) {
return null; return null;
} }
pollSnapshotPromise ??= fetchMatrixPollSnapshot(client, roomId, event).catch((err) => { pollSnapshotPromise ??= fetchMatrixPollSnapshot(client, roomId, event).catch(
(err: unknown) => {
logVerboseMessage( logVerboseMessage(
`matrix: failed resolving poll snapshot room=${roomId} id=${event.event_id ?? "unknown"}: ${String(err)}`, `matrix: failed resolving poll snapshot room=${roomId} id=${event.event_id ?? "unknown"}: ${String(err)}`,
); );
return null; return null;
}); },
);
return await pollSnapshotPromise; return await pollSnapshotPromise;
}; };
@@ -1481,7 +1483,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
.then(({ reactMatrixMessage }) => .then(({ reactMatrixMessage }) =>
reactMatrixMessage(roomId, messageId, ackReaction, client), reactMatrixMessage(roomId, messageId, ackReaction, client),
) )
.catch((err) => { .catch((err: unknown) => {
logVerboseMessage(`matrix react failed for room ${roomId}: ${String(err)}`); logVerboseMessage(`matrix react failed for room ${roomId}: ${String(err)}`);
}); });
} }
@@ -1489,7 +1491,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
if (messageId) { if (messageId) {
loadMatrixSendModule() loadMatrixSendModule()
.then(({ sendReadReceiptMatrix }) => sendReadReceiptMatrix(roomId, messageId, client)) .then(({ sendReadReceiptMatrix }) => sendReadReceiptMatrix(roomId, messageId, client))
.catch((err) => { .catch((err: unknown) => {
logVerboseMessage( logVerboseMessage(
`matrix: read receipt failed room=${roomId} id=${messageId}: ${String(err)}`, `matrix: read receipt failed room=${roomId} id=${messageId}: ${String(err)}`,
); );

View File

@@ -281,7 +281,7 @@ export async function createMatrixInboundEventDeduper(params: {
}, },
ttlMs > 0 ? { ttlMs } : undefined, ttlMs > 0 ? { ttlMs } : undefined,
) )
.catch((err) => { .catch((err: unknown) => {
LogService.warn( LogService.warn(
"MatrixInboundDedupe", "MatrixInboundDedupe",
"Failed persisting Matrix inbound dedupe entry:", "Failed persisting Matrix inbound dedupe entry:",

View File

@@ -494,7 +494,7 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
auth, auth,
env: process.env, env: process.env,
abortSignal: opts.abortSignal, abortSignal: opts.abortSignal,
}).catch((err) => { }).catch((err: unknown) => {
logVerboseMessage(`matrix: failed to backfill deviceId after startup (${String(err)})`); logVerboseMessage(`matrix: failed to backfill deviceId after startup (${String(err)})`);
}); });

View File

@@ -136,7 +136,9 @@ export async function handleInboundMatrixReaction(params: {
return; return;
} }
const targetEvent = await params.client.getEvent(params.roomId, reaction.eventId).catch((err) => { const targetEvent = await params.client
.getEvent(params.roomId, reaction.eventId)
.catch((err: unknown) => {
params.logVerboseMessage( params.logVerboseMessage(
`matrix: failed resolving reaction target room=${params.roomId} id=${reaction.eventId}: ${String(err)}`, `matrix: failed resolving reaction target room=${params.roomId} id=${reaction.eventId}: ${String(err)}`,
); );

View File

@@ -56,7 +56,9 @@ export function createMatrixReplyContextResolver(params: {
return cached; return cached;
} }
const event = await params.client.getEvent(input.roomId, input.eventId).catch((err) => { const event = await params.client
.getEvent(input.roomId, input.eventId)
.catch((err: unknown) => {
params.logVerboseMessage( params.logVerboseMessage(
`matrix: failed resolving reply context room=${input.roomId} id=${input.eventId}: ${String(err)}`, `matrix: failed resolving reply context room=${input.roomId} id=${input.eventId}: ${String(err)}`,
); );

View File

@@ -9,7 +9,7 @@ export function createMatrixMonitorTaskRunner(params: {
const runDetachedTask = (label: string, task: () => Promise<void>): Promise<void> => { const runDetachedTask = (label: string, task: () => Promise<void>): Promise<void> => {
const trackedTask: Promise<void> = Promise.resolve() const trackedTask: Promise<void> = Promise.resolve()
.then(task) .then(task)
.catch((error) => { .catch((error: unknown) => {
const message = String(error); const message = String(error);
params.logVerboseMessage(`matrix: ${label} failed (${message})`); params.logVerboseMessage(`matrix: ${label} failed (${message})`);
params.logger.warn("matrix background task failed", { params.logger.warn("matrix background task failed", {

View File

@@ -74,7 +74,7 @@ export function createMatrixThreadContextResolver(params: {
const rootEvent = await params.client const rootEvent = await params.client
.getEvent(input.roomId, input.threadRootId) .getEvent(input.roomId, input.threadRootId)
.catch((err) => { .catch((err: unknown) => {
params.logVerboseMessage( params.logVerboseMessage(
`matrix: failed resolving thread root room=${input.roomId} id=${input.threadRootId}: ${String(err)}`, `matrix: failed resolving thread root room=${input.roomId} id=${input.threadRootId}: ${String(err)}`,
); );

View File

@@ -628,7 +628,7 @@ export function createMatrixVerificationEventRouter(params: {
routeTask, routeTask,
); );
} else { } else {
void routeTask().catch((err) => { void routeTask().catch((err: unknown) => {
params.logVerboseMessage(`matrix: failed routing verification event: ${String(err)}`); params.logVerboseMessage(`matrix: failed routing verification event: ${String(err)}`);
}); });
} }

View File

@@ -11,7 +11,11 @@ export async function clearAllIndexedDbState(params?: { databasePrefix?: string
new Promise<void>((resolve, reject) => { new Promise<void>((resolve, reject) => {
const req = indexedDB.deleteDatabase(name); const req = indexedDB.deleteDatabase(name);
req.addEventListener("success", () => resolve(), { once: true }); req.addEventListener("success", () => resolve(), { once: true });
req.addEventListener("error", () => reject(req.error), { once: true }); req.addEventListener(
"error",
() => reject(toLintErrorObject(req.error, "Non-Error rejection")),
{ once: true },
);
req.addEventListener("blocked", () => resolve(), { once: true }); req.addEventListener("blocked", () => resolve(), { once: true });
}), }),
), ),
@@ -43,9 +47,17 @@ export async function seedDatabase(params: {
db.close(); db.close();
resolve(); resolve();
}); });
tx.addEventListener("error", () => reject(tx.error), { once: true }); tx.addEventListener(
"error",
() => reject(toLintErrorObject(tx.error, "Non-Error rejection")),
{ once: true },
);
}); });
req.addEventListener("error", () => reject(req.error), { once: true }); req.addEventListener(
"error",
() => reject(toLintErrorObject(req.error, "Non-Error rejection")),
{ once: true },
);
}); });
} }
@@ -82,9 +94,35 @@ export async function readDatabaseRecords(params: {
values = valuesReq.result; values = valuesReq.result;
maybeResolve(); maybeResolve();
}); });
keysReq.addEventListener("error", () => reject(keysReq.error), { once: true }); keysReq.addEventListener(
valuesReq.addEventListener("error", () => reject(valuesReq.error), { once: true }); "error",
() => reject(toLintErrorObject(keysReq.error, "Non-Error rejection")),
{ once: true },
);
valuesReq.addEventListener(
"error",
() => reject(toLintErrorObject(valuesReq.error, "Non-Error rejection")),
{ once: true },
);
}); });
req.addEventListener("error", () => reject(req.error), { once: true }); req.addEventListener(
"error",
() => reject(toLintErrorObject(req.error, "Non-Error rejection")),
{ once: true },
);
}); });
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -97,7 +97,11 @@ function parseSnapshotPayload(data: string): IdbDatabaseSnapshot[] | null {
function idbReq<T>(req: IDBRequest<T>): Promise<T> { function idbReq<T>(req: IDBRequest<T>): Promise<T> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
req.addEventListener("success", () => resolve(req.result), { once: true }); req.addEventListener("success", () => resolve(req.result), { once: true });
req.addEventListener("error", () => reject(req.error), { once: true }); req.addEventListener(
"error",
() => reject(toLintErrorObject(req.error, "Non-Error rejection")),
{ once: true },
);
}); });
} }
@@ -117,7 +121,9 @@ async function dumpIndexedDatabases(databasePrefix?: string): Promise<IdbDatabas
const db: IDBDatabase = await new Promise((resolve, reject) => { const db: IDBDatabase = await new Promise((resolve, reject) => {
const r = idb.open(name, version); const r = idb.open(name, version);
r.addEventListener("success", () => resolve(r.result), { once: true }); r.addEventListener("success", () => resolve(r.result), { once: true });
r.addEventListener("error", () => reject(r.error), { once: true }); r.addEventListener("error", () => reject(toLintErrorObject(r.error, "Non-Error rejection")), {
once: true,
});
}); });
const stores: IdbStoreSnapshot[] = []; const stores: IdbStoreSnapshot[] = [];
@@ -203,7 +209,9 @@ async function restoreIndexedDatabases(snapshot: IdbDatabaseSnapshot[]): Promise
}, },
{ once: true }, { once: true },
); );
r.addEventListener("error", () => reject(r.error), { once: true }); r.addEventListener("error", () => reject(toLintErrorObject(r.error, "Non-Error rejection")), {
once: true,
});
}); });
} }
} }
@@ -284,3 +292,17 @@ export async function persistIdbToDisk(params?: {
LogService.warn("IdbPersistence", "Failed to persist IndexedDB snapshot:", err); LogService.warn("IdbPersistence", "Failed to persist IndexedDB snapshot:", err);
} }
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -394,7 +394,7 @@ export class MatrixVerificationManager {
.then(() => { .then(() => {
this.touchVerificationSession(session); this.touchVerificationSession(session);
}) })
.catch((err) => { .catch((err: unknown) => {
session.acceptRequested = false; session.acceptRequested = false;
session.error = formatMatrixErrorMessage(err); session.error = formatMatrixErrorMessage(err);
this.touchVerificationSession(session); this.touchVerificationSession(session);
@@ -516,7 +516,7 @@ export class MatrixVerificationManager {
.then(() => { .then(() => {
this.touchVerificationSession(session); this.touchVerificationSession(session);
}) })
.catch((err) => { .catch((err: unknown) => {
session.error = formatMatrixErrorMessage(err); session.error = formatMatrixErrorMessage(err);
this.touchVerificationSession(session); this.touchVerificationSession(session);
}); });
@@ -545,7 +545,7 @@ export class MatrixVerificationManager {
.then(() => { .then(() => {
this.touchVerificationSession(session); this.touchVerificationSession(session);
}) })
.catch((err) => { .catch((err: unknown) => {
session.error = formatMatrixErrorMessage(err); session.error = formatMatrixErrorMessage(err);
this.touchVerificationSession(session); this.touchVerificationSession(session);
}); });

View File

@@ -35,10 +35,24 @@ export async function awaitMatrixStartupWithAbort<T>(
abortSignal.removeEventListener("abort", onAbort); abortSignal.removeEventListener("abort", onAbort);
resolve(value); resolve(value);
}, },
(error) => { (error: unknown) => {
abortSignal.removeEventListener("abort", onAbort); abortSignal.removeEventListener("abort", onAbort);
reject(error); reject(toLintErrorObject(error, "Non-Error rejection"));
}, },
); );
}); });
} }
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
if (value instanceof Error) {
return value;
}
if (typeof value === "string") {
return new Error(value);
}
const error = new Error(fallbackMessage, { cause: value });
if ((typeof value === "object" && value !== null) || typeof value === "function") {
Object.assign(error, value);
}
return error;
}

View File

@@ -368,7 +368,7 @@ export async function createMatrixThreadBindingManager(params: {
}; };
const persist = async () => await enqueuePersist(); const persist = async () => await enqueuePersist();
const persistSafely = (reason: string, bindings?: MatrixThreadBindingRecord[]) => { const persistSafely = (reason: string, bindings?: MatrixThreadBindingRecord[]) => {
void enqueuePersist(bindings).catch((err) => { void enqueuePersist(bindings).catch((err: unknown) => {
params.logVerboseMessage?.( params.logVerboseMessage?.(
`matrix: failed persisting thread bindings account=${params.accountId} action=${reason}: ${String(err)}`, `matrix: failed persisting thread bindings account=${params.accountId} action=${reason}: ${String(err)}`,
); );
@@ -383,7 +383,7 @@ export async function createMatrixThreadBindingManager(params: {
await persist(); await persist();
} }
await migrationStore.register(legacyImportKey, { importedAt: Date.now() }); await migrationStore.register(legacyImportKey, { importedAt: Date.now() });
await fs.rm(legacyFilePath, { force: true }).catch((err) => { await fs.rm(legacyFilePath, { force: true }).catch((err: unknown) => {
params.logVerboseMessage?.( params.logVerboseMessage?.(
`matrix: failed removing migrated legacy thread bindings account=${params.accountId}: ${String(err)}`, `matrix: failed removing migrated legacy thread bindings account=${params.accountId}: ${String(err)}`,
); );
@@ -693,7 +693,7 @@ export async function createMatrixThreadBindingManager(params: {
await sendFarewellMessages(removed, (record) => await sendFarewellMessages(removed, (record) =>
reasonByBindingKey.get(resolveBindingKey(record)), reasonByBindingKey.get(resolveBindingKey(record)),
); );
})().catch((err) => { })().catch((err: unknown) => {
params.logVerboseMessage?.( params.logVerboseMessage?.(
`matrix: failed auto-unbinding expired bindings account=${params.accountId}: ${String(err)}`, `matrix: failed auto-unbinding expired bindings account=${params.accountId}: ${String(err)}`,
); );

View File

@@ -2165,7 +2165,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
client, client,
commands, commands,
log: (msg) => runtime.log?.(msg), log: (msg) => runtime.log?.(msg),
}).catch((err) => { }).catch((err: unknown) => {
runtime.error?.(`mattermost: slash cleanup failed: ${String(err)}`); runtime.error?.(`mattermost: slash cleanup failed: ${String(err)}`);
}); });
}; };

View File

@@ -500,8 +500,8 @@ export function formatBackfillDiaryDate(isoDay: string, _timezone?: string): str
} }
async function assertSafeDreamsPath(dreamsPath: string): Promise<void> { async function assertSafeDreamsPath(dreamsPath: string): Promise<void> {
const stat = await fs.lstat(dreamsPath).catch((err: NodeJS.ErrnoException) => { const stat = await fs.lstat(dreamsPath).catch((err: unknown) => {
if (err.code === "ENOENT") { if (extractErrorCode(err) === "ENOENT") {
return null; return null;
} }
throw err; throw err;

View File

@@ -1,6 +1,7 @@
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
import fs from "node:fs/promises"; import fs from "node:fs/promises";
import path from "node:path"; import path from "node:path";
import { extractErrorCode } from "openclaw/plugin-sdk/error-runtime";
type DreamingArtifactsAuditIssue = { type DreamingArtifactsAuditIssue = {
severity: "warn" | "error"; severity: "warn" | "error";
@@ -87,8 +88,8 @@ function buildArchiveTimestamp(now: Date): string {
} }
async function ensureArchivablePath(targetPath: string): Promise<"file" | "dir" | null> { async function ensureArchivablePath(targetPath: string): Promise<"file" | "dir" | null> {
const stat = await fs.lstat(targetPath).catch((err: NodeJS.ErrnoException) => { const stat = await fs.lstat(targetPath).catch((err: unknown) => {
if (err.code === "ENOENT") { if (extractErrorCode(err) === "ENOENT") {
return null; return null;
} }
throw err; throw err;

View File

@@ -860,7 +860,7 @@ export function registerShortTermPromotionDreaming(api: OpenClawPluginApi): void
} }
scheduleStartupCronRetry(); scheduleStartupCronRetry();
}) })
.catch((err) => { .catch((err: unknown) => {
if (disposed) { if (disposed) {
return; return;
} }
@@ -877,7 +877,7 @@ export function registerShortTermPromotionDreaming(api: OpenClawPluginApi): void
return; return;
} }
runtimeCronReconcileTimer = setInterval(() => { runtimeCronReconcileTimer = setInterval(() => {
void reconcileManagedDreamingCron({ reason: "runtime" }).catch((err) => { void reconcileManagedDreamingCron({ reason: "runtime" }).catch((err: unknown) => {
api.logger.error(`memory-core: dreaming cron reconcile failed: ${formatErrorMessage(err)}`); api.logger.error(`memory-core: dreaming cron reconcile failed: ${formatErrorMessage(err)}`);
}); });
}, RUNTIME_CRON_RECONCILE_INTERVAL_MS); }, RUNTIME_CRON_RECONCILE_INTERVAL_MS);

View File

@@ -8,7 +8,7 @@ export function startAsyncSearchSync(params: {
if (!params.enabled || (!params.dirty && !params.sessionsDirty)) { if (!params.enabled || (!params.dirty && !params.sessionsDirty)) {
return; return;
} }
void params.sync({ reason: "search" }).catch((err) => { void params.sync({ reason: "search" }).catch((err: unknown) => {
params.onError(err); params.onError(err);
}); });
} }

Some files were not shown because too many files have changed in this diff Show More