From 8ff48f0a74e7fb46e1019e41ab004f619b50157e Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Fri, 13 Mar 2026 19:10:35 -0500 Subject: [PATCH] fix: resolve branch typecheck regressions --- extensions/diffs/src/tool.test.ts | 2 +- extensions/matrix/src/test-mocks.ts | 22 ++++++++++++++++- extensions/sglang/index.ts | 21 ++++++++++++---- .../synology-chat/src/channel.test-mocks.ts | 9 ++++--- extensions/telegram/src/channel.ts | 24 +++++++++---------- extensions/tlon/src/channel.ts | 19 +++++++++++---- extensions/vllm/index.ts | 21 ++++++++++++---- extensions/voice-call/index.ts | 4 +++- src/auto-reply/reply/test-helpers.ts | 7 +++++- .../routes/agent.existing-session.test.ts | 4 +++- .../message-handler.module-test-helpers.ts | 5 ++-- 11 files changed, 103 insertions(+), 35 deletions(-) diff --git a/extensions/diffs/src/tool.test.ts b/extensions/diffs/src/tool.test.ts index 1e939c60390..210586ad381 100644 --- a/extensions/diffs/src/tool.test.ts +++ b/extensions/diffs/src/tool.test.ts @@ -432,7 +432,7 @@ function createToolWithScreenshotter( function expectArtifactOnlyFileResult( screenshotter: DiffScreenshotter, - result: { details?: Record } | null | undefined, + result: { details?: unknown } | null | undefined, ) { expect(screenshotter.screenshotHtml).toHaveBeenCalledTimes(1); expect((result?.details as Record).mode).toBe("file"); diff --git a/extensions/matrix/src/test-mocks.ts b/extensions/matrix/src/test-mocks.ts index 8a104b94650..687b94459ea 100644 --- a/extensions/matrix/src/test-mocks.ts +++ b/extensions/matrix/src/test-mocks.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { vi } from "vitest"; type MatrixBotSdkMockParams = { @@ -7,7 +8,26 @@ type MatrixBotSdkMockParams = { includeVerboseLogService?: boolean; }; -export function createMatrixBotSdkMock(params: MatrixBotSdkMockParams = {}) { +type MatrixBotSdkMock = { + ConsoleLogger: new () => { + trace: Mock<() => void>; + debug: Mock<() => void>; + info: Mock<() => void>; + warn: Mock<() => void>; + error: Mock<() => void>; + }; + MatrixClient: unknown; + LogService: { + setLogger: Mock<() => void>; + warn?: Mock<() => void>; + info?: Mock<() => void>; + debug?: Mock<() => void>; + }; + SimpleFsStorageProvider: unknown; + RustSdkCryptoStorageProvider: unknown; +}; + +export function createMatrixBotSdkMock(params: MatrixBotSdkMockParams = {}): MatrixBotSdkMock { return { ConsoleLogger: class { trace = vi.fn(); diff --git a/extensions/sglang/index.ts b/extensions/sglang/index.ts index 13e301de28b..4c9102caebc 100644 --- a/extensions/sglang/index.ts +++ b/extensions/sglang/index.ts @@ -2,9 +2,11 @@ import { buildSglangProvider, configureOpenAICompatibleSelfHostedProviderNonInteractive, emptyPluginConfigSchema, - promptAndConfigureOpenAICompatibleSelfHostedProviderAuth, + promptAndConfigureOpenAICompatibleSelfHostedProvider, type OpenClawPluginApi, + type ProviderAuthContext, type ProviderAuthMethodNonInteractiveContext, + type ProviderAuthResult, type ProviderDiscoveryContext, } from "openclaw/plugin-sdk/core"; @@ -28,8 +30,8 @@ const sglangPlugin = { label: "SGLang", hint: "Fast self-hosted OpenAI-compatible server", kind: "custom", - run: (ctx) => - promptAndConfigureOpenAICompatibleSelfHostedProviderAuth({ + run: async (ctx: ProviderAuthContext): Promise => { + const result = await promptAndConfigureOpenAICompatibleSelfHostedProvider({ cfg: ctx.config, prompter: ctx.prompter, providerId: PROVIDER_ID, @@ -37,7 +39,18 @@ const sglangPlugin = { defaultBaseUrl: DEFAULT_BASE_URL, defaultApiKeyEnvVar: "SGLANG_API_KEY", modelPlaceholder: "Qwen/Qwen3-8B", - }), + }); + return { + profiles: [ + { + profileId: result.profileId, + credential: result.credential, + }, + ], + configPatch: result.config, + defaultModel: result.modelRef, + }; + }, runNonInteractive: async (ctx: ProviderAuthMethodNonInteractiveContext) => configureOpenAICompatibleSelfHostedProviderNonInteractive({ ctx, diff --git a/extensions/synology-chat/src/channel.test-mocks.ts b/extensions/synology-chat/src/channel.test-mocks.ts index b27c7ad434c..10ccca5f9d0 100644 --- a/extensions/synology-chat/src/channel.test-mocks.ts +++ b/extensions/synology-chat/src/channel.test-mocks.ts @@ -1,4 +1,5 @@ import type { IncomingMessage, ServerResponse } from "node:http"; +import type { Mock } from "vitest"; import { vi } from "vitest"; export type RegisteredRoute = { @@ -7,11 +8,13 @@ export type RegisteredRoute = { handler: (req: IncomingMessage, res: ServerResponse) => Promise; }; -export const registerPluginHttpRouteMock = vi.fn<(params: RegisteredRoute) => () => void>(() => - vi.fn(), +export const registerPluginHttpRouteMock: Mock<(params: RegisteredRoute) => () => void> = vi.fn( + () => vi.fn(), ); -export const dispatchReplyWithBufferedBlockDispatcher = vi.fn().mockResolvedValue({ counts: {} }); +export const dispatchReplyWithBufferedBlockDispatcher: Mock< + () => Promise<{ counts: Record }> +> = vi.fn().mockResolvedValue({ counts: {} }); async function readRequestBodyWithLimitForTest(req: IncomingMessage): Promise { return await new Promise((resolve, reject) => { diff --git a/extensions/telegram/src/channel.ts b/extensions/telegram/src/channel.ts index b5ae12fa06d..20d012c9dda 100644 --- a/extensions/telegram/src/channel.ts +++ b/extensions/telegram/src/channel.ts @@ -85,12 +85,12 @@ type TelegramSendOptions = NonNullable[2]>; function buildTelegramSendOptions(params: { cfg: OpenClawConfig; - mediaUrl?: string; - mediaLocalRoots?: readonly string[]; - accountId?: string; - replyToId?: string; - threadId?: string; - silent?: boolean; + mediaUrl?: string | null; + mediaLocalRoots?: readonly string[] | null; + accountId?: string | null; + replyToId?: string | null; + threadId?: string | number | null; + silent?: boolean | null; }): TelegramSendOptions { return { verbose: false, @@ -108,13 +108,13 @@ async function sendTelegramOutbound(params: { cfg: OpenClawConfig; to: string; text: string; - mediaUrl?: string; - mediaLocalRoots?: readonly string[]; - accountId?: string; + mediaUrl?: string | null; + mediaLocalRoots?: readonly string[] | null; + accountId?: string | null; deps?: { sendTelegram?: TelegramSendFn }; - replyToId?: string; - threadId?: string; - silent?: boolean; + replyToId?: string | null; + threadId?: string | number | null; + silent?: boolean | null; }) { const send = params.deps?.sendTelegram ?? getTelegramRuntime().channel.telegram.sendMessageTelegram; diff --git a/extensions/tlon/src/channel.ts b/extensions/tlon/src/channel.ts index b84679e1f39..eb37c8d7f74 100644 --- a/extensions/tlon/src/channel.ts +++ b/extensions/tlon/src/channel.ts @@ -154,8 +154,17 @@ function applyTlonSetupConfig(params: { } type ResolvedTlonAccount = ReturnType; +type ConfiguredTlonAccount = ResolvedTlonAccount & { + ship: string; + url: string; + code: string; +}; -function resolveOutboundContext(params: { cfg: OpenClawConfig; accountId?: string; to: string }) { +function resolveOutboundContext(params: { + cfg: OpenClawConfig; + accountId?: string | null; + to: string; +}) { const account = resolveTlonAccount(params.cfg, params.accountId ?? undefined); if (!account.configured || !account.ship || !account.url || !account.code) { throw new Error("Tlon account not configured"); @@ -166,15 +175,15 @@ function resolveOutboundContext(params: { cfg: OpenClawConfig; accountId?: strin throw new Error(`Invalid Tlon target. Use ${formatTargetHint()}`); } - return { account, parsed }; + return { account: account as ConfiguredTlonAccount, parsed }; } -function resolveReplyId(replyToId?: string, threadId?: string) { +function resolveReplyId(replyToId?: string | null, threadId?: string | number | null) { return (replyToId ?? threadId) ? String(replyToId ?? threadId) : undefined; } async function withHttpPokeAccountApi( - account: ResolvedTlonAccount & { ship: string; url: string; code: string }, + account: ConfiguredTlonAccount, run: (api: Awaited>) => Promise, ) { const api = await createHttpPokeApi({ @@ -241,7 +250,7 @@ const tlonOutbound: ChannelOutboundAdapter = { shipUrl: account.url, shipName: account.ship.replace(/^~/, ""), verbose: false, - getCode: async () => account.code!, + getCode: async () => account.code, }); const uploadedUrl = mediaUrl ? await uploadImageFromUrl(mediaUrl) : undefined; diff --git a/extensions/vllm/index.ts b/extensions/vllm/index.ts index 3a30f8b9f76..fd0a5e18914 100644 --- a/extensions/vllm/index.ts +++ b/extensions/vllm/index.ts @@ -2,9 +2,11 @@ import { buildVllmProvider, configureOpenAICompatibleSelfHostedProviderNonInteractive, emptyPluginConfigSchema, - promptAndConfigureOpenAICompatibleSelfHostedProviderAuth, + promptAndConfigureOpenAICompatibleSelfHostedProvider, type OpenClawPluginApi, + type ProviderAuthContext, type ProviderAuthMethodNonInteractiveContext, + type ProviderAuthResult, type ProviderDiscoveryContext, } from "openclaw/plugin-sdk/core"; @@ -28,8 +30,8 @@ const vllmPlugin = { label: "vLLM", hint: "Local/self-hosted OpenAI-compatible server", kind: "custom", - run: (ctx) => - promptAndConfigureOpenAICompatibleSelfHostedProviderAuth({ + run: async (ctx: ProviderAuthContext): Promise => { + const result = await promptAndConfigureOpenAICompatibleSelfHostedProvider({ cfg: ctx.config, prompter: ctx.prompter, providerId: PROVIDER_ID, @@ -37,7 +39,18 @@ const vllmPlugin = { defaultBaseUrl: DEFAULT_BASE_URL, defaultApiKeyEnvVar: "VLLM_API_KEY", modelPlaceholder: "meta-llama/Meta-Llama-3-8B-Instruct", - }), + }); + return { + profiles: [ + { + profileId: result.profileId, + credential: result.credential, + }, + ], + configPatch: result.config, + defaultModel: result.modelRef, + }; + }, runNonInteractive: async (ctx: ProviderAuthMethodNonInteractiveContext) => configureOpenAICompatibleSelfHostedProviderNonInteractive({ ctx, diff --git a/extensions/voice-call/index.ts b/extensions/voice-call/index.ts index e61b5142ef1..7393fb03c9b 100644 --- a/extensions/voice-call/index.ts +++ b/extensions/voice-call/index.ts @@ -230,7 +230,9 @@ const voiceCallPlugin = { const respondToCallMessageAction = async (params: { requestParams: GatewayRequestHandlerOptions["params"]; respond: GatewayRequestHandlerOptions["respond"]; - action: (request: Awaited>) => Promise<{ + action: ( + request: Exclude>, { error: string }>, + ) => Promise<{ success: boolean; error?: string; transcript?: string; diff --git a/src/auto-reply/reply/test-helpers.ts b/src/auto-reply/reply/test-helpers.ts index d92bf481f42..fe1913e723d 100644 --- a/src/auto-reply/reply/test-helpers.ts +++ b/src/auto-reply/reply/test-helpers.ts @@ -27,6 +27,8 @@ export function createMockFollowupRun( enqueuedAt: Date.now(), originatingTo: "channel:C1", run: { + agentId: "agent", + agentDir: "/tmp/agent", sessionId: "session", sessionKey: "main", messageProvider: "whatsapp", @@ -34,7 +36,10 @@ export function createMockFollowupRun( sessionFile: "/tmp/session.jsonl", workspaceDir: "/tmp", config: {}, - skillsSnapshot: {}, + skillsSnapshot: { + prompt: "", + skills: [], + }, provider: "anthropic", model: "claude", thinkLevel: "low", diff --git a/src/browser/routes/agent.existing-session.test.ts b/src/browser/routes/agent.existing-session.test.ts index 070a0ed41d7..89b234cdc5c 100644 --- a/src/browser/routes/agent.existing-session.test.ts +++ b/src/browser/routes/agent.existing-session.test.ts @@ -26,7 +26,9 @@ const routeState = vi.hoisted(() => ({ })); const chromeMcpMocks = vi.hoisted(() => ({ - evaluateChromeMcpScript: vi.fn(async () => true), + evaluateChromeMcpScript: vi.fn( + async (_params: { profileName: string; targetId: string; fn: string }) => true, + ), navigateChromeMcpPage: vi.fn(async ({ url }: { url: string }) => ({ url })), takeChromeMcpScreenshot: vi.fn(async () => Buffer.from("png")), takeChromeMcpSnapshot: vi.fn(async () => ({ diff --git a/src/discord/monitor/message-handler.module-test-helpers.ts b/src/discord/monitor/message-handler.module-test-helpers.ts index 046813e397f..fce7580e912 100644 --- a/src/discord/monitor/message-handler.module-test-helpers.ts +++ b/src/discord/monitor/message-handler.module-test-helpers.ts @@ -1,7 +1,8 @@ import { vi } from "vitest"; +import type { MockFn } from "../../test-utils/vitest-mock-fn.js"; -export const preflightDiscordMessageMock = vi.fn(); -export const processDiscordMessageMock = vi.fn(); +export const preflightDiscordMessageMock: MockFn = vi.fn(); +export const processDiscordMessageMock: MockFn = vi.fn(); vi.mock("./message-handler.preflight.js", () => ({ preflightDiscordMessage: preflightDiscordMessageMock,