Groundwork for the transcribe operation and for creating Studio when it is first needed. - Contracts: TranscribeInputSchema (artifact id, optional language code). - transcribeChunks uploads audio chunks in order and stitches them into one transcript on the original timeline; transcriptionChunkSeconds sizes 16 kHz mono WAV chunks below the server's upload limit; transcriptSummary hands the bot the transcript, cut at a word. - ensureStudioWhenMediaConfigured creates Studio once a media server (generation or transcription) is configured. Local edits alone do not count, because ffmpeg and image tools are present on most installs and a specialist nobody asked for would appear for everyone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
import type { MediaCapabilities } from "@rakazo/adapter-kit";
|
|
import type { PrismaClient } from "@rakazo/db";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const ensureStudioBot = vi.fn();
|
|
vi.mock("@rakazo/db", () => ({
|
|
ensureStudioBot: (...args: unknown[]) => ensureStudioBot(...args),
|
|
}));
|
|
|
|
import { ensureStudioWhenMediaConfigured, mediaBackendsConfigured } from "./studio-specialist.js";
|
|
|
|
const none: MediaCapabilities = {
|
|
generate_image: false,
|
|
generate_video: false,
|
|
edit_image: false,
|
|
edit_video: false,
|
|
export_video: false,
|
|
transcribe: false,
|
|
};
|
|
const prisma = {} as PrismaClient;
|
|
const run = { userId: "user-1", spaceId: "space-1" };
|
|
|
|
describe("Studio specialist", () => {
|
|
beforeEach(() => {
|
|
ensureStudioBot.mockReset();
|
|
});
|
|
|
|
it("counts only media servers, not local edits, as media being set up", () => {
|
|
expect(mediaBackendsConfigured({ ...none, edit_image: true, edit_video: true })).toBe(false);
|
|
expect(mediaBackendsConfigured({ ...none, transcribe: true })).toBe(true);
|
|
expect(mediaBackendsConfigured({ ...none, generate_image: true })).toBe(true);
|
|
});
|
|
|
|
it("creates Studio once a media server is configured", async () => {
|
|
await ensureStudioWhenMediaConfigured(
|
|
{ prisma, media: { capabilities: async () => ({ ...none, edit_video: true }) } },
|
|
run,
|
|
);
|
|
await ensureStudioWhenMediaConfigured({ prisma }, run);
|
|
expect(ensureStudioBot).not.toHaveBeenCalled();
|
|
await ensureStudioWhenMediaConfigured(
|
|
{ prisma, media: { capabilities: async () => ({ ...none, transcribe: true }) } },
|
|
run,
|
|
);
|
|
expect(ensureStudioBot).toHaveBeenCalledWith(prisma, "user-1");
|
|
});
|
|
|
|
it("never fails the run", async () => {
|
|
ensureStudioBot.mockRejectedValue(new Error("database unavailable"));
|
|
await expect(
|
|
ensureStudioWhenMediaConfigured(
|
|
{ prisma, media: { capabilities: async () => ({ ...none, generate_video: true }) } },
|
|
run,
|
|
),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
});
|