



















@@ -402,7 +402,9 @@ describe("google web search provider", () => {
402402403403it("passes freshness to Gemini Google Search grounding as a time range", async () => {
404404vi.useFakeTimers();
405-vi.setSystemTime(new Date("2026-04-15T12:00:00Z"));
405+// Use a wall-clock-realistic moment with non-zero milliseconds; the helper
406+// must strip them to avoid Gemini's "Granularity of nano is not supported".
407+vi.setSystemTime(new Date("2026-04-15T12:00:00.123Z"));
406408const mockFetch = installGeminiFetch();
407409const provider = createGeminiWebSearchProvider();
408410const tool = provider.createTool({
@@ -426,8 +428,47 @@ describe("google web search provider", () => {
426428427429const body = parseGeminiFetchBody(mockFetch);
428430expect(body.tools?.[0]?.google_search?.timeRangeFilter).toEqual({
429-startTime: "2026-04-08T12:00:00.000Z",
430-endTime: "2026-04-15T12:00:00.000Z",
431+startTime: "2026-04-08T12:00:00Z",
432+endTime: "2026-04-15T12:00:00Z",
433+});
434+});
435+436+it("strips sub-second precision from freshness timestamps so Gemini accepts them", async () => {
437+vi.useFakeTimers();
438+// "now" with non-zero milliseconds. Without stripping, toISOString() emits
439+// "2026-04-15T12:00:00.123Z", which Gemini's google_search.time_range_filter
440+// rejects with "Granularity of nano is not supported".
441+vi.setSystemTime(new Date("2026-04-15T12:00:00.123Z"));
442+const mockFetch = installGeminiFetch();
443+const provider = createGeminiWebSearchProvider();
444+const tool = provider.createTool({
445+config: {
446+plugins: {
447+entries: {
448+google: {
449+config: {
450+webSearch: {
451+apiKey: "AIza-plugin-test",
452+},
453+},
454+},
455+},
456+},
457+},
458+searchConfig: { provider: "gemini" },
459+});
460+461+await tool?.execute({ query: "latest ai news", freshness: "week" });
462+463+const body = parseGeminiFetchBody(mockFetch);
464+const filter = body.tools?.[0]?.google_search?.timeRangeFilter as
465+| { startTime: string; endTime: string }
466+| undefined;
467+expect(filter?.startTime).not.toMatch(/\.\d+Z$/);
468+expect(filter?.endTime).not.toMatch(/\.\d+Z$/);
469+expect(filter).toEqual({
470+startTime: "2026-04-08T12:00:00Z",
471+endTime: "2026-04-15T12:00:00Z",
431472});
432473});
433474@@ -460,7 +501,7 @@ describe("google web search provider", () => {
460501const body = parseGeminiFetchBody(mockFetch);
461502expect(body.tools?.[0]?.google_search?.timeRangeFilter).toEqual({
462503startTime: "2026-04-01T00:00:00Z",
463-endTime: "2026-05-01T00:00:00.000Z",
504+endTime: "2026-05-01T00:00:00Z",
464505});
465506});
466507此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。