Skip to content

Commit f3805cc

Browse files
hugenshenPeter Steinberger
authored andcommitted
test(moonshot): add bounds and malformed-JSON coverage for video description
1 parent 2190fb2 commit f3805cc

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

extensions/moonshot/media-understanding-provider.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,39 @@ import { describeMoonshotVideo } from "./media-understanding-provider.js";
88

99
installPinnedHostnameTestHooks();
1010

11+
function oversizedJsonResponse(params: { chunkCount: number; chunkSize: number }): {
12+
response: Response;
13+
getReadCount: () => number;
14+
wasCanceled: () => boolean;
15+
} {
16+
const chunk = new Uint8Array(params.chunkSize);
17+
let readCount = 0;
18+
let canceled = false;
19+
return {
20+
response: new Response(
21+
new ReadableStream<Uint8Array>({
22+
pull(controller) {
23+
if (readCount >= params.chunkCount) {
24+
controller.close();
25+
return;
26+
}
27+
readCount += 1;
28+
controller.enqueue(chunk);
29+
},
30+
cancel() {
31+
canceled = true;
32+
},
33+
}),
34+
{
35+
status: 200,
36+
headers: { "Content-Type": "application/json" },
37+
},
38+
),
39+
getReadCount: () => readCount,
40+
wasCanceled: () => canceled,
41+
};
42+
}
43+
1144
describe("describeMoonshotVideo", () => {
1245
it("builds an OpenAI-compatible video request", async () => {
1346
const { fetchFn, getRequest } = createRequestCaptureJsonFetch({
@@ -90,4 +123,42 @@ describe("describeMoonshotVideo", () => {
90123
expect(result.text).toBe("reasoned answer");
91124
expect(result.model).toBe("kimi-k2.6");
92125
});
126+
127+
it("bounds successful Moonshot video JSON bodies instead of buffering the whole response", async () => {
128+
const streamed = oversizedJsonResponse({ chunkCount: 64, chunkSize: 1024 * 1024 });
129+
130+
await expect(
131+
describeMoonshotVideo({
132+
buffer: Buffer.from("video-bytes"),
133+
fileName: "clip.mp4",
134+
mime: "video/mp4",
135+
apiKey: "test-key",
136+
timeoutMs: 1500,
137+
baseUrl: "https://example.com/v1",
138+
fetchFn: async () => streamed.response,
139+
}),
140+
).rejects.toThrow("Moonshot video description failed: JSON response exceeds 16777216 bytes");
141+
142+
expect(streamed.getReadCount()).toBeLessThan(64);
143+
expect(streamed.wasCanceled()).toBe(true);
144+
});
145+
146+
it("reports malformed Moonshot video JSON with a provider-owned error", async () => {
147+
const response = new Response("not-json{", {
148+
status: 200,
149+
headers: { "Content-Type": "application/json" },
150+
});
151+
152+
await expect(
153+
describeMoonshotVideo({
154+
buffer: Buffer.from("video-bytes"),
155+
fileName: "clip.mp4",
156+
mime: "video/mp4",
157+
apiKey: "test-key",
158+
timeoutMs: 1500,
159+
baseUrl: "https://example.com/v1",
160+
fetchFn: async () => response,
161+
}),
162+
).rejects.toThrow("Moonshot video description failed: malformed JSON response");
163+
});
93164
});

extensions/moonshot/media-understanding-provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export async function describeMoonshotVideo(
6767
await assertOkOrThrowHttpError(res, "Moonshot video description failed");
6868
const payload = await readProviderJsonResponse<OpenAiCompatibleVideoPayload>(
6969
res,
70-
"moonshot.video-description",
70+
"Moonshot video description failed",
7171
);
7272
const text = coerceOpenAiCompatibleVideoText(payload);
7373
if (!text) {

0 commit comments

Comments
 (0)