




















@@ -450,6 +450,21 @@ describe("capability cli", () => {
450450return calls[0]?.[0];
451451}
452452453+function firstImageGenerationCall() {
454+const calls = mocks.generateImage.mock.calls as unknown as Array<[Record<string, unknown>]>;
455+return calls[0]?.[0];
456+}
457+458+function firstVideoGenerationCall() {
459+const calls = mocks.generateVideo.mock.calls as unknown as Array<[Record<string, unknown>]>;
460+return calls[0]?.[0];
461+}
462+463+function firstAudioTranscriptionCall() {
464+const calls = mocks.transcribeAudioFile.mock.calls as unknown as Array<[{ filePath?: string }]>;
465+return calls[0]?.[0];
466+}
467+453468function expectModelRunDispatch(transport: "local" | "gateway", modelRef: string) {
454469if (transport === "gateway") {
455470const slash = modelRef.indexOf("/");
@@ -1195,16 +1210,10 @@ describe("capability cli", () => {
11951210],
11961211});
119712121198-expect(mocks.runtime.writeJson).toHaveBeenCalledWith(
1199-expect.objectContaining({
1200-outputs: [
1201-expect.objectContaining({
1202-path: tempOutput.replace(/\.png$/, ".jpg"),
1203-mimeType: "image/jpeg",
1204-}),
1205-],
1206-}),
1207-);
1213+const outputs = firstJsonOutput()?.outputs as Array<Record<string, unknown>>;
1214+expect(outputs).toHaveLength(1);
1215+expect(outputs[0]?.path).toBe(tempOutput.replace(/\.png$/, ".jpg"));
1216+expect(outputs[0]?.mimeType).toBe("image/jpeg");
12081217});
1209121812101219it("passes image generation timeout through to runtime", async () => {
@@ -1235,12 +1244,8 @@ describe("capability cli", () => {
12351244],
12361245});
123712461238-expect(mocks.generateImage).toHaveBeenCalledWith(
1239-expect.objectContaining({
1240-prompt: "friendly lobster",
1241-timeoutMs: 180000,
1242-}),
1243-);
1247+expect(firstImageGenerationCall()?.prompt).toBe("friendly lobster");
1248+expect(firstImageGenerationCall()?.timeoutMs).toBe(180000);
12441249});
1245125012461251it("passes image output format and generic background hints through to generation runtime", async () => {
@@ -1275,15 +1280,12 @@ describe("capability cli", () => {
12751280],
12761281});
127712821278-expect(mocks.generateImage).toHaveBeenCalledWith(
1279-expect.objectContaining({
1280-prompt: "transparent sticker",
1281-modelOverride: "openai/gpt-image-1.5",
1282-outputFormat: "png",
1283-background: "transparent",
1284-providerOptions: undefined,
1285-}),
1286-);
1283+const generationCall = firstImageGenerationCall();
1284+expect(generationCall?.prompt).toBe("transparent sticker");
1285+expect(generationCall?.modelOverride).toBe("openai/gpt-image-1.5");
1286+expect(generationCall?.outputFormat).toBe("png");
1287+expect(generationCall?.background).toBe("transparent");
1288+expect(generationCall?.providerOptions).toBeUndefined();
12871289});
1288129012891291it("passes image output format and OpenAI background hints through to edit runtime", async () => {
@@ -1322,24 +1324,19 @@ describe("capability cli", () => {
13221324],
13231325});
132413261325-expect(mocks.generateImage).toHaveBeenCalledWith(
1326-expect.objectContaining({
1327-prompt: "make background transparent",
1328-modelOverride: "openai/gpt-image-1.5",
1329-outputFormat: "png",
1330-background: undefined,
1331-providerOptions: {
1332-openai: {
1333-background: "transparent",
1334-},
1335-},
1336-inputImages: [
1337-expect.objectContaining({
1338-fileName: path.basename(inputPath),
1339-}),
1340-],
1341-}),
1342-);
1327+const generationCall = firstImageGenerationCall();
1328+const inputImages = generationCall?.inputImages as Array<Record<string, unknown>>;
1329+expect(generationCall?.prompt).toBe("make background transparent");
1330+expect(generationCall?.modelOverride).toBe("openai/gpt-image-1.5");
1331+expect(generationCall?.outputFormat).toBe("png");
1332+expect(generationCall?.background).toBeUndefined();
1333+expect(generationCall?.providerOptions).toEqual({
1334+openai: {
1335+background: "transparent",
1336+},
1337+});
1338+expect(inputImages).toHaveLength(1);
1339+expect(inputImages[0]?.fileName).toBe(path.basename(inputPath));
13431340});
1344134113451342it("rejects unsupported image output format and background hints", async () => {
@@ -1448,21 +1445,16 @@ describe("capability cli", () => {
14481445],
14491446});
145014471451-expect(mocks.generateImage).toHaveBeenCalledWith(
1452-expect.objectContaining({
1453-prompt: "remove the background object",
1454-modelOverride: "openai/gpt-image-2",
1455-size: "2160x3840",
1456-aspectRatio: "9:16",
1457-resolution: "4K",
1458-inputImages: [
1459-expect.objectContaining({
1460-fileName: path.basename(tempInput),
1461-mimeType: "image/png",
1462-}),
1463-],
1464-}),
1465-);
1448+const generationCall = firstImageGenerationCall();
1449+const inputImages = generationCall?.inputImages as Array<Record<string, unknown>>;
1450+expect(generationCall?.prompt).toBe("remove the background object");
1451+expect(generationCall?.modelOverride).toBe("openai/gpt-image-2");
1452+expect(generationCall?.size).toBe("2160x3840");
1453+expect(generationCall?.aspectRatio).toBe("9:16");
1454+expect(generationCall?.resolution).toBe("4K");
1455+expect(inputImages).toHaveLength(1);
1456+expect(inputImages[0]?.fileName).toBe(path.basename(tempInput));
1457+expect(inputImages[0]?.mimeType).toBe("image/png");
14661458});
1467145914681460it("reports the expanded image.edit flags in capability inspect", async () => {
@@ -1471,25 +1463,21 @@ describe("capability cli", () => {
14711463argv: ["capability", "inspect", "--name", "image.edit", "--json"],
14721464});
147314651474-expect(mocks.runtime.writeJson).toHaveBeenCalledWith(
1475-expect.objectContaining({
1476-id: "image.edit",
1477-flags: [
1478-"--file",
1479-"--prompt",
1480-"--model",
1481-"--size",
1482-"--aspect-ratio",
1483-"--resolution",
1484-"--output-format",
1485-"--background",
1486-"--openai-background",
1487-"--timeout-ms",
1488-"--output",
1489-"--json",
1490-],
1491-}),
1492-);
1466+expect(firstJsonOutput()?.id).toBe("image.edit");
1467+expect(firstJsonOutput()?.flags).toEqual([
1468+"--file",
1469+"--prompt",
1470+"--model",
1471+"--size",
1472+"--aspect-ratio",
1473+"--resolution",
1474+"--output-format",
1475+"--background",
1476+"--openai-background",
1477+"--timeout-ms",
1478+"--output",
1479+"--json",
1480+]);
14931481});
1494148214951483it("streams url-only generated videos to --output paths", async () => {
@@ -1532,24 +1520,20 @@ describe("capability cli", () => {
15321520});
1533152115341522const outputPath = `${outputBase}.mp4`;
1535-expect(fetchMock).toHaveBeenCalledWith(
1536-"https://example.com/generated-video.mp4",
1537-expect.objectContaining({ signal: expect.any(AbortSignal) }),
1538-);
1523+const fetchCall = fetchMock.mock.calls[0] as unknown as
1524+| [string, { signal?: unknown }]
1525+| undefined;
1526+expect(fetchCall?.[0]).toBe("https://example.com/generated-video.mp4");
1527+expect(fetchCall?.[1]?.signal).toBeInstanceOf(AbortSignal);
15391528expect(await fs.readFile(outputPath, "utf8")).toBe("video-bytes");
1540-expect(mocks.runtime.writeJson).toHaveBeenCalledWith(
1541-expect.objectContaining({
1542-capability: "video.generate",
1543-provider: "vydra",
1544-outputs: [
1545-expect.objectContaining({
1546-path: outputPath,
1547-mimeType: "video/mp4",
1548-size: 11,
1549-}),
1550-],
1551-}),
1552-);
1529+const output = firstJsonOutput();
1530+const outputs = output?.outputs as Array<Record<string, unknown>>;
1531+expect(output?.capability).toBe("video.generate");
1532+expect(output?.provider).toBe("vydra");
1533+expect(outputs).toHaveLength(1);
1534+expect(outputs[0]?.path).toBe(outputPath);
1535+expect(outputs[0]?.mimeType).toBe("video/mp4");
1536+expect(outputs[0]?.size).toBe(11);
15531537});
1554153815551539it("passes video generation parameters through to runtime", async () => {
@@ -1592,19 +1576,16 @@ describe("capability cli", () => {
15921576],
15931577});
159415781595-expect(mocks.generateVideo).toHaveBeenCalledWith(
1596-expect.objectContaining({
1597-prompt: "friendly lobster",
1598-modelOverride: "minimax/MiniMax-Hailuo-2.3",
1599-size: "1280x768",
1600-aspectRatio: "16:9",
1601-resolution: "768P",
1602-durationSeconds: 6,
1603-audio: true,
1604-watermark: true,
1605-timeoutMs: 300000,
1606-}),
1607-);
1579+const videoCall = firstVideoGenerationCall();
1580+expect(videoCall?.prompt).toBe("friendly lobster");
1581+expect(videoCall?.modelOverride).toBe("minimax/MiniMax-Hailuo-2.3");
1582+expect(videoCall?.size).toBe("1280x768");
1583+expect(videoCall?.aspectRatio).toBe("16:9");
1584+expect(videoCall?.resolution).toBe("768P");
1585+expect(videoCall?.durationSeconds).toBe(6);
1586+expect(videoCall?.audio).toBe(true);
1587+expect(videoCall?.watermark).toBe(true);
1588+expect(videoCall?.timeoutMs).toBe(300000);
16081589});
1609159016101591it("fails video generate when a provider returns an undeliverable asset", async () => {
@@ -1632,15 +1613,12 @@ describe("capability cli", () => {
16321613argv: ["capability", "audio", "transcribe", "--file", "memo.m4a", "--json"],
16331614});
163416151635-expect(mocks.transcribeAudioFile).toHaveBeenCalledWith(
1636-expect.objectContaining({ filePath: expect.stringMatching(/memo\.m4a$/) }),
1637-);
1638-expect(mocks.runtime.writeJson).toHaveBeenCalledWith(
1639-expect.objectContaining({
1640-capability: "audio.transcribe",
1641-outputs: [expect.objectContaining({ kind: "audio.transcription" })],
1642-}),
1643-);
1616+expect(path.basename(firstAudioTranscriptionCall()?.filePath ?? "")).toBe("memo.m4a");
1617+const output = firstJsonOutput();
1618+const outputs = output?.outputs as Array<Record<string, unknown>>;
1619+expect(output?.capability).toBe("audio.transcribe");
1620+expect(outputs).toHaveLength(1);
1621+expect(outputs[0]?.kind).toBe("audio.transcription");
16441622});
1645162316461624it("fails audio transcribe when no transcript text is returned", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。