Skip to content

Commit f9f6780

Browse files
authored
rename gm to groundingMeta for clarity
refactor(search): rename gm to groundingMeta for clarity
2 parents ce49176 + 861ee33 commit f9f6780

2 files changed

Lines changed: 143 additions & 5 deletions

File tree

src/plugin/search.test.ts

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2+
import { executeSearch } from "./search";
3+
4+
// ─── Helpers ──────────────────────────────────────────────────────────────────
5+
6+
function makeResponse(
7+
text: string,
8+
opts: {
9+
searchQueries?: string[];
10+
chunks?: Array<{ title: string; uri: string }>;
11+
urlMetadata?: Array<{ retrieved_url: string; url_retrieval_status: string }>;
12+
} = {},
13+
) {
14+
return {
15+
response: {
16+
candidates: [
17+
{
18+
content: { role: "model", parts: [{ text }] },
19+
finishReason: "STOP",
20+
groundingMetadata: {
21+
webSearchQueries: opts.searchQueries ?? [],
22+
groundingChunks: (opts.chunks ?? []).map((c) => ({ web: c })),
23+
},
24+
urlContextMetadata: { url_metadata: opts.urlMetadata ?? [] },
25+
},
26+
],
27+
},
28+
};
29+
}
30+
31+
function mockFetch(body: unknown, status = 200) {
32+
return vi.fn().mockResolvedValue({
33+
ok: status >= 200 && status < 300,
34+
status,
35+
statusText: status === 200 ? "OK" : "Error",
36+
json: () => Promise.resolve(body),
37+
text: () => Promise.resolve(JSON.stringify(body)),
38+
});
39+
}
40+
41+
// ─── executeSearch ────────────────────────────────────────────────────────────
42+
43+
describe("executeSearch", () => {
44+
beforeEach(() => {
45+
vi.stubGlobal("fetch", mockFetch(makeResponse("Default result")));
46+
});
47+
48+
afterEach(() => {
49+
vi.restoreAllMocks();
50+
});
51+
52+
it("returns formatted text from the response", async () => {
53+
vi.stubGlobal("fetch", mockFetch(makeResponse("The answer is 42.")));
54+
const result = await executeSearch({ query: "what is 42?" }, "tok", "proj");
55+
expect(result).toContain("The answer is 42.");
56+
expect(result).toContain("## Search Results");
57+
});
58+
59+
it("lists sources from groundingChunks (uses groundingMeta internally)", async () => {
60+
vi.stubGlobal(
61+
"fetch",
62+
mockFetch(
63+
makeResponse("answer", {
64+
chunks: [{ title: "Example", uri: "https://example.com/page" }],
65+
}),
66+
),
67+
);
68+
const result = await executeSearch({ query: "q" }, "tok", "proj");
69+
expect(result).toContain("### Sources");
70+
expect(result).toContain("Example");
71+
expect(result).toContain("https://example.com/page");
72+
});
73+
74+
it("includes search queries section when queries are present", async () => {
75+
vi.stubGlobal(
76+
"fetch",
77+
mockFetch(makeResponse("res", { searchQueries: ["my query"] })),
78+
);
79+
const result = await executeSearch({ query: "my query" }, "tok", "proj");
80+
expect(result).toContain("### Search Queries Used");
81+
expect(result).toContain('"my query"');
82+
});
83+
84+
it("marks successful URL retrieval with ✓", async () => {
85+
vi.stubGlobal(
86+
"fetch",
87+
mockFetch(
88+
makeResponse("ok", {
89+
urlMetadata: [
90+
{ retrieved_url: "https://docs.example.com", url_retrieval_status: "URL_RETRIEVAL_STATUS_SUCCESS" },
91+
],
92+
}),
93+
),
94+
);
95+
const result = await executeSearch({ query: "q", urls: ["https://docs.example.com"] }, "tok", "proj");
96+
expect(result).toContain("✓");
97+
expect(result).toContain("https://docs.example.com");
98+
});
99+
100+
it("marks failed URL retrieval with ✗", async () => {
101+
vi.stubGlobal(
102+
"fetch",
103+
mockFetch(
104+
makeResponse("ok", {
105+
urlMetadata: [
106+
{ retrieved_url: "https://broken.example.com", url_retrieval_status: "URL_RETRIEVAL_STATUS_ERROR" },
107+
],
108+
}),
109+
),
110+
);
111+
const result = await executeSearch({ query: "q", urls: ["https://broken.example.com"] }, "tok", "proj");
112+
expect(result).toContain("✗");
113+
});
114+
115+
it("returns error block on non-OK HTTP response", async () => {
116+
vi.stubGlobal("fetch", mockFetch({ error: "bad" }, 400));
117+
const result = await executeSearch({ query: "q" }, "tok", "proj");
118+
expect(result).toContain("## Search Error");
119+
expect(result).toContain("400");
120+
});
121+
122+
it("returns error block when fetch throws", async () => {
123+
vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new Error("Network down")));
124+
const result = await executeSearch({ query: "q" }, "tok", "proj");
125+
expect(result).toContain("## Search Error");
126+
expect(result).toContain("Network down");
127+
});
128+
129+
it("includes Authorization header with the provided token", async () => {
130+
const spy = mockFetch(makeResponse("ok"));
131+
vi.stubGlobal("fetch", spy);
132+
await executeSearch({ query: "q" }, "bearer-token-xyz", "proj");
133+
const [, init] = spy.mock.calls[0] as [string, RequestInit];
134+
expect((init.headers as Record<string, string>)["Authorization"]).toBe(
135+
"Bearer bearer-token-xyz",
136+
);
137+
});
138+
});

src/plugin/search.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,14 @@ function parseSearchResponse(data: AntigravitySearchResponse): SearchResult {
177177

178178
// Extract grounding metadata
179179
if (candidate.groundingMetadata) {
180-
const gm = candidate.groundingMetadata;
180+
const groundingMeta = candidate.groundingMetadata;
181181

182-
if (gm.webSearchQueries) {
183-
result.searchQueries = gm.webSearchQueries;
182+
if (groundingMeta.webSearchQueries) {
183+
result.searchQueries = groundingMeta.webSearchQueries;
184184
}
185185

186-
if (gm.groundingChunks) {
187-
for (const chunk of gm.groundingChunks) {
186+
if (groundingMeta.groundingChunks) {
187+
for (const chunk of groundingMeta.groundingChunks) {
188188
if (chunk.web?.uri && chunk.web?.title) {
189189
result.sources.push({
190190
title: chunk.web.title,

0 commit comments

Comments
 (0)