






















@@ -8,6 +8,13 @@ import { testing as geminiWebSearchTesting } from "./src/gemini-web-search-provi
8899let ssrfMock: { mockRestore: () => void } | undefined;
101011+function jsonResponse(payload: unknown): Response {
12+return new Response(JSON.stringify(payload), {
13+status: 200,
14+headers: { "Content-Type": "application/json" },
15+});
16+}
17+1118function mockGoogleApiKeyAuth() {
1219vi.spyOn(providerAuthRuntime, "resolveApiKeyForProvider").mockResolvedValue({
1320apiKey: "google-test-key",
@@ -24,9 +31,8 @@ function installGoogleFetchMock(params?: {
2431const mimeType = params?.mimeType ?? "image/png";
2532const data = params?.data ?? "png-data";
2633const inlineDataKey = params?.inlineDataKey ?? "inlineData";
27-const fetchMock = vi.fn().mockResolvedValue({
28-ok: true,
29-json: async () => ({
34+const fetchMock = vi.fn().mockResolvedValue(
35+jsonResponse({
3036candidates: [
3137{
3238content: {
@@ -42,7 +48,7 @@ function installGoogleFetchMock(params?: {
4248},
4349],
4450}),
45-});
51+);
4652vi.stubGlobal("fetch", fetchMock);
4753return fetchMock;
4854}
@@ -100,9 +106,8 @@ describe("Google image-generation provider", () => {
100106source: "env",
101107mode: "api-key",
102108});
103-const fetchMock = vi.fn().mockResolvedValue({
104-ok: true,
105-json: async () => ({
109+const fetchMock = vi.fn().mockResolvedValue(
110+jsonResponse({
106111candidates: [
107112{
108113content: {
@@ -119,7 +124,7 @@ describe("Google image-generation provider", () => {
119124},
120125],
121126}),
122-});
127+);
123128vi.stubGlobal("fetch", fetchMock);
124129125130const provider = buildGoogleImageGenerationProvider();
@@ -208,10 +213,7 @@ describe("Google image-generation provider", () => {
208213mockGoogleApiKeyAuth();
209214vi.stubGlobal(
210215"fetch",
211-vi.fn().mockResolvedValue({
212-ok: true,
213-json: async () => ({ candidates: { content: { parts: [] } } }),
214-}),
216+vi.fn().mockResolvedValue(jsonResponse({ candidates: { content: { parts: [] } } })),
215217);
216218217219const provider = buildGoogleImageGenerationProvider();
@@ -229,9 +231,8 @@ describe("Google image-generation provider", () => {
229231mockGoogleApiKeyAuth();
230232vi.stubGlobal(
231233"fetch",
232-vi.fn().mockResolvedValue({
233-ok: true,
234-json: async () => ({
234+vi.fn().mockResolvedValue(
235+jsonResponse({
235236candidates: [
236237{
237238content: {
@@ -240,7 +241,7 @@ describe("Google image-generation provider", () => {
240241},
241242],
242243}),
243-}),
244+),
244245);
245246246247const provider = buildGoogleImageGenerationProvider();
@@ -260,9 +261,8 @@ describe("Google image-generation provider", () => {
260261source: "profile",
261262mode: "token",
262263});
263-const fetchMock = vi.fn().mockResolvedValue({
264-ok: true,
265-json: async () => ({
264+const fetchMock = vi.fn().mockResolvedValue(
265+jsonResponse({
266266candidates: [
267267{
268268content: {
@@ -278,7 +278,7 @@ describe("Google image-generation provider", () => {
278278},
279279],
280280}),
281-});
281+);
282282vi.stubGlobal("fetch", fetchMock);
283283284284const provider = buildGoogleImageGenerationProvider();
@@ -305,6 +305,74 @@ describe("Google image-generation provider", () => {
305305});
306306});
307307308+it("accepts valid multi-image inline JSON responses above the generic provider JSON cap", async () => {
309+mockGoogleApiKeyAuth();
310+const imageBytes = Buffer.alloc(6 * 1024 * 1024, 1);
311+const imagePayload = imageBytes.toString("base64");
312+vi.stubGlobal(
313+"fetch",
314+vi.fn().mockResolvedValue(
315+jsonResponse({
316+candidates: [
317+{
318+content: {
319+parts: Array.from({ length: 3 }, () => ({
320+inlineData: {
321+mimeType: "image/png",
322+data: imagePayload,
323+},
324+})),
325+},
326+},
327+],
328+}),
329+),
330+);
331+332+const provider = buildGoogleImageGenerationProvider();
333+const result = await provider.generateImage({
334+provider: "google",
335+model: "gemini-3.1-flash-image-preview",
336+prompt: "draw a cat",
337+cfg: {},
338+});
339+340+expect(result.images).toHaveLength(3);
341+expect(result.images.map((image) => image.buffer.byteLength)).toEqual([
342+imageBytes.byteLength,
343+imageBytes.byteLength,
344+imageBytes.byteLength,
345+]);
346+});
347+348+it("still rejects oversized Google image JSON responses", async () => {
349+mockGoogleApiKeyAuth();
350+vi.stubGlobal(
351+"fetch",
352+vi.fn().mockResolvedValue(
353+jsonResponse({
354+candidates: [
355+{
356+content: {
357+parts: [{ text: "x".repeat(35 * 1024 * 1024) }],
358+},
359+},
360+],
361+}),
362+),
363+);
364+365+const provider = buildGoogleImageGenerationProvider();
366+await expect(
367+provider.generateImage({
368+provider: "google",
369+model: "gemini-3.1-flash-image-preview",
370+prompt: "draw a cat",
371+cfg: {},
372+}),
373+).rejects.toThrow("google.image-generation: JSON response exceeds");
374+});
375+308376it("sends reference images and explicit resolution for edit flows", async () => {
309377mockGoogleApiKeyAuth();
310378const fetchMock = installGoogleFetchMock();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。