diff --git a/src/media-understanding/runner.auto-audio.test.ts b/src/media-understanding/runner.auto-audio.test.ts index b01291c8831..e1c4b25c43a 100644 --- a/src/media-understanding/runner.auto-audio.test.ts +++ b/src/media-understanding/runner.auto-audio.test.ts @@ -1,41 +1,7 @@ -import fs from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; import { describe, expect, it } from "vitest"; -import type { MsgContext } from "../auto-reply/templating.js"; import type { OpenClawConfig } from "../config/config.js"; -import { - buildProviderRegistry, - createMediaAttachmentCache, - normalizeMediaAttachments, - runCapability, -} from "./runner.js"; - -async function withAudioFixture( - run: (params: { - ctx: MsgContext; - media: ReturnType; - cache: ReturnType; - }) => Promise, -) { - const originalPath = process.env.PATH; - process.env.PATH = ""; - const tmpPath = path.join(os.tmpdir(), `openclaw-auto-audio-${Date.now()}.wav`); - await fs.writeFile(tmpPath, Buffer.from("RIFF")); - const ctx: MsgContext = { MediaPath: tmpPath, MediaType: "audio/wav" }; - const media = normalizeMediaAttachments(ctx); - const cache = createMediaAttachmentCache(media, { - localPathRoots: [path.dirname(tmpPath)], - }); - - try { - await run({ ctx, media, cache }); - } finally { - process.env.PATH = originalPath; - await cache.cleanup(); - await fs.unlink(tmpPath).catch(() => {}); - } -} +import { buildProviderRegistry, runCapability } from "./runner.js"; +import { withAudioFixture } from "./runner.test-utils.js"; function createOpenAiAudioProvider( transcribeAudio: (req: { model?: string }) => Promise<{ text: string; model: string }>, @@ -65,7 +31,7 @@ function createOpenAiAudioCfg(extra?: Partial): OpenClawConfig { describe("runCapability auto audio entries", () => { it("uses provider keys to auto-enable audio transcription", async () => { - await withAudioFixture(async ({ ctx, media, cache }) => { + await withAudioFixture("openclaw-auto-audio", async ({ ctx, media, cache }) => { let seenModel: string | undefined; const providerRegistry = createOpenAiAudioProvider(async (req) => { seenModel = req.model; @@ -88,7 +54,7 @@ describe("runCapability auto audio entries", () => { }); it("skips auto audio when disabled", async () => { - await withAudioFixture(async ({ ctx, media, cache }) => { + await withAudioFixture("openclaw-auto-audio", async ({ ctx, media, cache }) => { const providerRegistry = createOpenAiAudioProvider(async () => ({ text: "ok", model: "whisper-1", @@ -117,7 +83,7 @@ describe("runCapability auto audio entries", () => { }); it("prefers explicitly configured audio model entries", async () => { - await withAudioFixture(async ({ ctx, media, cache }) => { + await withAudioFixture("openclaw-auto-audio", async ({ ctx, media, cache }) => { let seenModel: string | undefined; const providerRegistry = createOpenAiAudioProvider(async (req) => { seenModel = req.model; diff --git a/src/media-understanding/runner.deepgram.test.ts b/src/media-understanding/runner.deepgram.test.ts index e4c42d0e64a..38df19b7432 100644 --- a/src/media-understanding/runner.deepgram.test.ts +++ b/src/media-understanding/runner.deepgram.test.ts @@ -1,45 +1,11 @@ -import fs from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; import { describe, expect, it } from "vitest"; -import type { MsgContext } from "../auto-reply/templating.js"; import type { OpenClawConfig } from "../config/config.js"; -import { - buildProviderRegistry, - createMediaAttachmentCache, - normalizeMediaAttachments, - runCapability, -} from "./runner.js"; - -async function withAudioFixture( - run: (params: { - ctx: MsgContext; - media: ReturnType; - cache: ReturnType; - }) => Promise, -) { - const originalPath = process.env.PATH; - process.env.PATH = ""; - const tmpPath = path.join(os.tmpdir(), `openclaw-deepgram-${Date.now()}.wav`); - await fs.writeFile(tmpPath, Buffer.from("RIFF")); - const ctx: MsgContext = { MediaPath: tmpPath, MediaType: "audio/wav" }; - const media = normalizeMediaAttachments(ctx); - const cache = createMediaAttachmentCache(media, { - localPathRoots: [path.dirname(tmpPath)], - }); - - try { - await run({ ctx, media, cache }); - } finally { - process.env.PATH = originalPath; - await cache.cleanup(); - await fs.unlink(tmpPath).catch(() => {}); - } -} +import { buildProviderRegistry, runCapability } from "./runner.js"; +import { withAudioFixture } from "./runner.test-utils.js"; describe("runCapability deepgram provider options", () => { it("merges provider options, headers, and baseUrl overrides", async () => { - await withAudioFixture(async ({ ctx, media, cache }) => { + await withAudioFixture("openclaw-deepgram", async ({ ctx, media, cache }) => { let seenQuery: Record | undefined; let seenBaseUrl: string | undefined; let seenHeaders: Record | undefined; diff --git a/src/media-understanding/runner.test-utils.ts b/src/media-understanding/runner.test-utils.ts new file mode 100644 index 00000000000..823d63ea943 --- /dev/null +++ b/src/media-understanding/runner.test-utils.ts @@ -0,0 +1,34 @@ +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import type { MsgContext } from "../auto-reply/templating.js"; +import { withEnvAsync } from "../test-utils/env.js"; +import { createMediaAttachmentCache, normalizeMediaAttachments } from "./runner.js"; + +type AudioFixtureParams = { + ctx: MsgContext; + media: ReturnType; + cache: ReturnType; +}; + +export async function withAudioFixture( + filePrefix: string, + run: (params: AudioFixtureParams) => Promise, +) { + const tmpPath = path.join(os.tmpdir(), `${filePrefix}-${Date.now()}.wav`); + await fs.writeFile(tmpPath, Buffer.from("RIFF")); + const ctx: MsgContext = { MediaPath: tmpPath, MediaType: "audio/wav" }; + const media = normalizeMediaAttachments(ctx); + const cache = createMediaAttachmentCache(media, { + localPathRoots: [path.dirname(tmpPath)], + }); + + try { + await withEnvAsync({ PATH: "" }, async () => { + await run({ ctx, media, cache }); + }); + } finally { + await cache.cleanup(); + await fs.unlink(tmpPath).catch(() => {}); + } +}