opencode-antigravity-auth 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,197 +0,0 @@
1
- const ANTIGRAVITY_PREVIEW_LINK = "https://goo.gle/enable-preview-features"; // TODO: Update to Antigravity link if available
2
-
3
- export interface AntigravityApiError {
4
- code?: number;
5
- message?: string;
6
- status?: string;
7
- [key: string]: unknown;
8
- }
9
-
10
- /**
11
- * Minimal representation of Antigravity API responses we touch.
12
- */
13
- export interface AntigravityApiBody {
14
- response?: unknown;
15
- error?: AntigravityApiError;
16
- [key: string]: unknown;
17
- }
18
-
19
- /**
20
- * Usage metadata exposed by Antigravity responses. Fields are optional to reflect partial payloads.
21
- */
22
- export interface AntigravityUsageMetadata {
23
- totalTokenCount?: number;
24
- promptTokenCount?: number;
25
- candidatesTokenCount?: number;
26
- cachedContentTokenCount?: number;
27
- }
28
-
29
- /**
30
- * Normalized thinking configuration accepted by Antigravity.
31
- */
32
- export interface ThinkingConfig {
33
- thinkingBudget?: number;
34
- includeThoughts?: boolean;
35
- }
36
-
37
- /**
38
- * Ensures thinkingConfig is valid: includeThoughts only allowed when budget > 0.
39
- */
40
- export function normalizeThinkingConfig(config: unknown): ThinkingConfig | undefined {
41
- if (!config || typeof config !== "object") {
42
- return undefined;
43
- }
44
-
45
- const record = config as Record<string, unknown>;
46
- const budgetRaw = record.thinkingBudget ?? record.thinking_budget;
47
- const includeRaw = record.includeThoughts ?? record.include_thoughts;
48
-
49
- const thinkingBudget = typeof budgetRaw === "number" && Number.isFinite(budgetRaw) ? budgetRaw : undefined;
50
- const includeThoughts = typeof includeRaw === "boolean" ? includeRaw : undefined;
51
-
52
- const enableThinking = thinkingBudget !== undefined && thinkingBudget > 0;
53
- const finalInclude = enableThinking ? includeThoughts ?? false : false;
54
-
55
- if (!enableThinking && finalInclude === false && thinkingBudget === undefined && includeThoughts === undefined) {
56
- return undefined;
57
- }
58
-
59
- const normalized: ThinkingConfig = {};
60
- if (thinkingBudget !== undefined) {
61
- normalized.thinkingBudget = thinkingBudget;
62
- }
63
- if (finalInclude !== undefined) {
64
- normalized.includeThoughts = finalInclude;
65
- }
66
- return normalized;
67
- }
68
-
69
- /**
70
- * Parses an Antigravity API body; handles array-wrapped responses the API sometimes returns.
71
- */
72
- export function parseAntigravityApiBody(rawText: string): AntigravityApiBody | null {
73
- try {
74
- const parsed = JSON.parse(rawText);
75
- if (Array.isArray(parsed)) {
76
- const firstObject = parsed.find((item: unknown) => typeof item === "object" && item !== null);
77
- if (firstObject && typeof firstObject === "object") {
78
- return firstObject as AntigravityApiBody;
79
- }
80
- return null;
81
- }
82
-
83
- if (parsed && typeof parsed === "object") {
84
- return parsed as AntigravityApiBody;
85
- }
86
-
87
- return null;
88
- } catch {
89
- return null;
90
- }
91
- }
92
-
93
- /**
94
- * Extracts usageMetadata from a response object, guarding types.
95
- */
96
- export function extractUsageMetadata(body: AntigravityApiBody): AntigravityUsageMetadata | null {
97
- const usage = (body.response && typeof body.response === "object"
98
- ? (body.response as { usageMetadata?: unknown }).usageMetadata
99
- : undefined) as AntigravityUsageMetadata | undefined;
100
-
101
- if (!usage || typeof usage !== "object") {
102
- return null;
103
- }
104
-
105
- const asRecord = usage as Record<string, unknown>;
106
- const toNumber = (value: unknown): number | undefined =>
107
- typeof value === "number" && Number.isFinite(value) ? value : undefined;
108
-
109
- return {
110
- totalTokenCount: toNumber(asRecord.totalTokenCount),
111
- promptTokenCount: toNumber(asRecord.promptTokenCount),
112
- candidatesTokenCount: toNumber(asRecord.candidatesTokenCount),
113
- cachedContentTokenCount: toNumber(asRecord.cachedContentTokenCount),
114
- };
115
- }
116
-
117
- /**
118
- * Walks SSE lines to find a usage-bearing response chunk.
119
- */
120
- export function extractUsageFromSsePayload(payload: string): AntigravityUsageMetadata | null {
121
- const lines = payload.split("\n");
122
- for (const line of lines) {
123
- if (!line.startsWith("data:")) {
124
- continue;
125
- }
126
- const jsonText = line.slice(5).trim();
127
- if (!jsonText) {
128
- continue;
129
- }
130
- try {
131
- const parsed = JSON.parse(jsonText);
132
- if (parsed && typeof parsed === "object") {
133
- const usage = extractUsageMetadata({ response: (parsed as Record<string, unknown>).response });
134
- if (usage) {
135
- return usage;
136
- }
137
- }
138
- } catch {
139
- continue;
140
- }
141
- }
142
- return null;
143
- }
144
-
145
- /**
146
- * Enhances 404 errors for Antigravity models with a direct preview-access message.
147
- */
148
- export function rewriteAntigravityPreviewAccessError(
149
- body: AntigravityApiBody,
150
- status: number,
151
- requestedModel?: string,
152
- ): AntigravityApiBody | null {
153
- if (!needsPreviewAccessOverride(status, body, requestedModel)) {
154
- return null;
155
- }
156
-
157
- const error: AntigravityApiError = body.error ?? {};
158
- const trimmedMessage = typeof error.message === "string" ? error.message.trim() : "";
159
- const messagePrefix = trimmedMessage.length > 0
160
- ? trimmedMessage
161
- : "Antigravity preview features are not enabled for this account.";
162
- const enhancedMessage = `${messagePrefix} Request preview access at ${ANTIGRAVITY_PREVIEW_LINK} before using this model.`;
163
-
164
- return {
165
- ...body,
166
- error: {
167
- ...error,
168
- message: enhancedMessage,
169
- },
170
- };
171
- }
172
-
173
- function needsPreviewAccessOverride(
174
- status: number,
175
- body: AntigravityApiBody,
176
- requestedModel?: string,
177
- ): boolean {
178
- if (status !== 404) {
179
- return false;
180
- }
181
-
182
- if (isAntigravityModel(requestedModel)) {
183
- return true;
184
- }
185
-
186
- const errorMessage = typeof body.error?.message === "string" ? body.error.message : "";
187
- return isAntigravityModel(errorMessage);
188
- }
189
-
190
- function isAntigravityModel(target?: string): boolean {
191
- if (!target) {
192
- return false;
193
- }
194
-
195
- // Check for Antigravity models instead of Gemini 3
196
- return /antigravity/i.test(target) || /opus/i.test(target) || /claude/i.test(target);
197
- }
@@ -1,457 +0,0 @@
1
- import crypto from "node:crypto";
2
- import {
3
- ANTIGRAVITY_HEADERS,
4
- ANTIGRAVITY_ENDPOINT,
5
- } from "../constants";
6
- import { logAntigravityDebugResponse, type AntigravityDebugContext } from "./debug";
7
- import {
8
- extractUsageFromSsePayload,
9
- extractUsageMetadata,
10
- normalizeThinkingConfig,
11
- parseAntigravityApiBody,
12
- rewriteAntigravityPreviewAccessError,
13
- type AntigravityApiBody,
14
- } from "./request-helpers";
15
-
16
- function generateSyntheticProjectId(): string {
17
- const adjectives = ["useful", "bright", "swift", "calm", "bold"];
18
- const nouns = ["fuze", "wave", "spark", "flow", "core"];
19
- const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
20
- const noun = nouns[Math.floor(Math.random() * nouns.length)];
21
- const randomPart = crypto.randomUUID().slice(0, 5).toLowerCase();
22
- return `${adj}-${noun}-${randomPart}`;
23
- }
24
-
25
- const STREAM_ACTION = "streamGenerateContent";
26
- /**
27
- * Detects requests headed to the Google Generative Language API so we can intercept them.
28
- */
29
- export function isGenerativeLanguageRequest(input: RequestInfo): input is string {
30
- return typeof input === "string" && input.includes("generativelanguage.googleapis.com");
31
- }
32
-
33
- /**
34
- * Rewrites SSE payloads so downstream consumers see only the inner `response` objects.
35
- */
36
- function transformStreamingPayload(payload: string): string {
37
- return payload
38
- .split("\n")
39
- .map((line) => {
40
- if (!line.startsWith("data:")) {
41
- return line;
42
- }
43
- const json = line.slice(5).trim();
44
- if (!json) {
45
- return line;
46
- }
47
- try {
48
- const parsed = JSON.parse(json) as { response?: unknown };
49
- if (parsed.response !== undefined) {
50
- return `data: ${JSON.stringify(parsed.response)}`;
51
- }
52
- } catch (_) {}
53
- return line;
54
- })
55
- .join("\n");
56
- }
57
-
58
- /**
59
- * Rewrites OpenAI-style requests into Antigravity shape, normalizing model, headers,
60
- * optional cached_content, and thinking config. Also toggles streaming mode for SSE actions.
61
- */
62
- export function prepareAntigravityRequest(
63
- input: RequestInfo,
64
- init: RequestInit | undefined,
65
- accessToken: string,
66
- projectId: string,
67
- endpointOverride?: string,
68
- ): { request: RequestInfo; init: RequestInit; streaming: boolean; requestedModel?: string; effectiveModel?: string; projectId?: string; endpoint?: string; toolDebugMissing?: number; toolDebugSummary?: string; toolDebugPayload?: string } {
69
- const baseInit: RequestInit = { ...init };
70
- const headers = new Headers(init?.headers ?? {});
71
- let resolvedProjectId = projectId?.trim() || "";
72
- let toolDebugMissing = 0;
73
- const toolDebugSummaries: string[] = [];
74
- let toolDebugPayload: string | undefined;
75
-
76
- if (!isGenerativeLanguageRequest(input)) {
77
- return {
78
- request: input,
79
- init: { ...baseInit, headers },
80
- streaming: false,
81
- };
82
- }
83
-
84
- headers.set("Authorization", `Bearer ${accessToken}`);
85
- headers.delete("x-api-key");
86
-
87
- const match = input.match(/\/models\/([^:]+):(\w+)/);
88
- if (!match) {
89
- return {
90
- request: input,
91
- init: { ...baseInit, headers },
92
- streaming: false,
93
- };
94
- }
95
-
96
- const [, rawModel = "", rawAction = ""] = match;
97
- const effectiveModel = rawModel;
98
- const upstreamModel = rawModel;
99
- const streaming = rawAction === STREAM_ACTION;
100
- const baseEndpoint = endpointOverride ?? ANTIGRAVITY_ENDPOINT;
101
- const transformedUrl = `${baseEndpoint}/v1internal:${rawAction}${
102
- streaming ? "?alt=sse" : ""
103
- }`;
104
- const isClaudeModel = upstreamModel.toLowerCase().includes("claude");
105
-
106
- let body = baseInit.body;
107
- if (typeof baseInit.body === "string" && baseInit.body) {
108
- try {
109
- const parsedBody = JSON.parse(baseInit.body) as Record<string, unknown>;
110
- const isWrapped = typeof parsedBody.project === "string" && "request" in parsedBody;
111
-
112
- if (isWrapped) {
113
- const wrappedBody = {
114
- ...parsedBody,
115
- model: effectiveModel,
116
- } as Record<string, unknown>;
117
- body = JSON.stringify(wrappedBody);
118
- } else {
119
- const requestPayload: Record<string, unknown> = { ...parsedBody };
120
-
121
- const rawGenerationConfig = requestPayload.generationConfig as Record<string, unknown> | undefined;
122
- const normalizedThinking = normalizeThinkingConfig(rawGenerationConfig?.thinkingConfig);
123
- if (normalizedThinking) {
124
- if (rawGenerationConfig) {
125
- rawGenerationConfig.thinkingConfig = normalizedThinking;
126
- requestPayload.generationConfig = rawGenerationConfig;
127
- } else {
128
- requestPayload.generationConfig = { thinkingConfig: normalizedThinking };
129
- }
130
- } else if (rawGenerationConfig?.thinkingConfig) {
131
- delete rawGenerationConfig.thinkingConfig;
132
- requestPayload.generationConfig = rawGenerationConfig;
133
- }
134
-
135
- if ("system_instruction" in requestPayload) {
136
- requestPayload.systemInstruction = requestPayload.system_instruction;
137
- delete requestPayload.system_instruction;
138
- }
139
-
140
- const cachedContentFromExtra =
141
- typeof requestPayload.extra_body === "object" && requestPayload.extra_body
142
- ? (requestPayload.extra_body as Record<string, unknown>).cached_content ??
143
- (requestPayload.extra_body as Record<string, unknown>).cachedContent
144
- : undefined;
145
- const cachedContent =
146
- (requestPayload.cached_content as string | undefined) ??
147
- (requestPayload.cachedContent as string | undefined) ??
148
- (cachedContentFromExtra as string | undefined);
149
- if (cachedContent) {
150
- requestPayload.cachedContent = cachedContent;
151
- }
152
-
153
- delete requestPayload.cached_content;
154
- delete requestPayload.cachedContent;
155
- if (requestPayload.extra_body && typeof requestPayload.extra_body === "object") {
156
- delete (requestPayload.extra_body as Record<string, unknown>).cached_content;
157
- delete (requestPayload.extra_body as Record<string, unknown>).cachedContent;
158
- if (Object.keys(requestPayload.extra_body as Record<string, unknown>).length === 0) {
159
- delete requestPayload.extra_body;
160
- }
161
- }
162
-
163
- // Normalize tools. For Claude models, send functionDeclarations with parameters (no custom).
164
- if (Array.isArray(requestPayload.tools)) {
165
- if (isClaudeModel) {
166
- // Use functionDeclarations with parameters (mirrors CLIProxy path that Antigravity accepts).
167
- const claudeTools: any[] = requestPayload.tools.map((tool: any, idx: number) => {
168
- const schema =
169
- tool.function?.parameters ||
170
- tool.function?.input_schema ||
171
- tool.function?.inputSchema ||
172
- tool.parameters ||
173
- tool.input_schema ||
174
- tool.inputSchema ||
175
- tool.custom?.parameters ||
176
- tool.custom?.input_schema ||
177
- { type: "object", properties: {} };
178
- const name =
179
- tool.name ||
180
- tool.function?.name ||
181
- tool.custom?.name ||
182
- `tool-${idx}`;
183
- const description =
184
- tool.description || tool.function?.description || tool.custom?.description || "";
185
-
186
- return {
187
- functionDeclarations: [
188
- {
189
- name,
190
- description,
191
- parameters: schema,
192
- },
193
- ],
194
- };
195
- });
196
-
197
- requestPayload.tools = claudeTools;
198
- } else {
199
- // Default normalization for non-Claude models
200
- requestPayload.tools = requestPayload.tools.map((tool: any, toolIndex: number) => {
201
- const newTool = { ...tool };
202
-
203
- const schemaCandidates = [
204
- newTool.function?.input_schema,
205
- newTool.function?.parameters,
206
- newTool.function?.inputSchema,
207
- newTool.custom?.input_schema,
208
- newTool.custom?.parameters,
209
- newTool.parameters,
210
- newTool.input_schema,
211
- newTool.inputSchema,
212
- ].filter(Boolean);
213
- const schema = schemaCandidates[0];
214
-
215
- const nameCandidate =
216
- newTool.name ||
217
- newTool.function?.name ||
218
- newTool.custom?.name ||
219
- `tool-${toolIndex}`;
220
-
221
- if (newTool.function && !newTool.function.input_schema && schema) {
222
- newTool.function.input_schema = schema;
223
- }
224
- if (newTool.custom && !newTool.custom.input_schema && schema) {
225
- newTool.custom.input_schema = schema;
226
- }
227
- if (!newTool.custom && newTool.function) {
228
- newTool.custom = {
229
- name: newTool.function.name || nameCandidate,
230
- description: newTool.function.description,
231
- input_schema: schema ?? { type: "object", properties: {} },
232
- };
233
- }
234
- if (!newTool.custom && !newTool.function) {
235
- newTool.custom = {
236
- name: nameCandidate,
237
- description: newTool.description,
238
- input_schema: schema ?? { type: "object", properties: {} },
239
- };
240
- }
241
- if (newTool.custom && !newTool.custom.input_schema) {
242
- newTool.custom.input_schema = { type: "object", properties: {} };
243
- toolDebugMissing += 1;
244
- }
245
-
246
- toolDebugSummaries.push(
247
- `idx=${toolIndex}, hasCustom=${!!newTool.custom}, customSchema=${!!newTool.custom?.input_schema}, hasFunction=${!!newTool.function}, functionSchema=${!!newTool.function?.input_schema}`,
248
- );
249
-
250
- // Strip custom wrappers for Gemini; only function-style is accepted.
251
- if (newTool.custom) {
252
- delete newTool.custom;
253
- }
254
-
255
- return newTool;
256
- });
257
- }
258
-
259
- try {
260
- toolDebugPayload = JSON.stringify(requestPayload.tools);
261
- } catch {
262
- toolDebugPayload = undefined;
263
- }
264
- }
265
-
266
- if ("model" in requestPayload) {
267
- delete requestPayload.model;
268
- }
269
-
270
- const effectiveProjectId = projectId?.trim() || generateSyntheticProjectId();
271
- resolvedProjectId = effectiveProjectId;
272
-
273
- const wrappedBody = {
274
- project: effectiveProjectId,
275
- model: upstreamModel,
276
- request: requestPayload,
277
- };
278
-
279
- // Add additional Antigravity fields
280
- Object.assign(wrappedBody, {
281
- userAgent: "antigravity",
282
- requestId: "agent-" + crypto.randomUUID(),
283
- });
284
- if (wrappedBody.request && typeof wrappedBody.request === 'object') {
285
- (wrappedBody.request as any).sessionId = "-" + Math.floor(Math.random() * 9000000000000000000).toString();
286
- }
287
-
288
- body = JSON.stringify(wrappedBody);
289
-
290
- if (wrappedBody.request && typeof wrappedBody.request === 'object') {
291
- (wrappedBody.request as any).sessionId = "-" + Math.floor(Math.random() * 9000000000000000000).toString();
292
- }
293
-
294
- body = JSON.stringify(wrappedBody);
295
- }
296
- } catch (error) {
297
- throw error;
298
- }
299
- }
300
-
301
- if (streaming) {
302
- headers.set("Accept", "text/event-stream");
303
- }
304
-
305
- headers.set("User-Agent", ANTIGRAVITY_HEADERS["User-Agent"]);
306
- headers.set("X-Goog-Api-Client", ANTIGRAVITY_HEADERS["X-Goog-Api-Client"]);
307
- headers.set("Client-Metadata", ANTIGRAVITY_HEADERS["Client-Metadata"]);
308
- // Optional debug header to observe tool normalization on the backend if surfaced
309
- if (toolDebugMissing > 0) {
310
- headers.set("X-Opencode-Tools-Debug", String(toolDebugMissing));
311
- }
312
-
313
- return {
314
- request: transformedUrl,
315
- init: {
316
- ...baseInit,
317
- headers,
318
- body,
319
- },
320
- streaming,
321
- requestedModel: rawModel,
322
- effectiveModel: upstreamModel,
323
- projectId: resolvedProjectId,
324
- endpoint: transformedUrl,
325
- toolDebugMissing,
326
- toolDebugSummary: toolDebugSummaries.slice(0, 20).join(" | "),
327
- toolDebugPayload,
328
- };
329
- }
330
-
331
- /**
332
- * Normalizes Antigravity responses: applies retry headers, extracts cache usage into headers,
333
- * rewrites preview errors, flattens streaming payloads, and logs debug metadata.
334
- */
335
- export async function transformAntigravityResponse(
336
- response: Response,
337
- streaming: boolean,
338
- debugContext?: AntigravityDebugContext | null,
339
- requestedModel?: string,
340
- projectId?: string,
341
- endpoint?: string,
342
- effectiveModel?: string,
343
- toolDebugMissing?: number,
344
- toolDebugSummary?: string,
345
- toolDebugPayload?: string,
346
- ): Promise<Response> {
347
- const contentType = response.headers.get("content-type") ?? "";
348
- const isJsonResponse = contentType.includes("application/json");
349
- const isEventStreamResponse = contentType.includes("text/event-stream");
350
-
351
- if (!isJsonResponse && !isEventStreamResponse) {
352
- logAntigravityDebugResponse(debugContext, response, {
353
- note: "Non-JSON response (body omitted)",
354
- });
355
- return response;
356
- }
357
-
358
- try {
359
- const text = await response.text();
360
- const headers = new Headers(response.headers);
361
-
362
- if (!response.ok) {
363
- let errorBody;
364
- try {
365
- errorBody = JSON.parse(text);
366
- } catch {
367
- errorBody = { error: { message: text } };
368
- }
369
-
370
- // Inject Debug Info
371
- if (errorBody?.error) {
372
- const debugInfo = `\n\n[Debug Info]\nRequested Model: ${requestedModel || "Unknown"}\nEffective Model: ${effectiveModel || "Unknown"}\nProject: ${projectId || "Unknown"}\nEndpoint: ${endpoint || "Unknown"}\nStatus: ${response.status}\nRequest ID: ${headers.get('x-request-id') || "N/A"}${toolDebugMissing !== undefined ? `\nTool Debug Missing: ${toolDebugMissing}` : ""}${toolDebugSummary ? `\nTool Debug Summary: ${toolDebugSummary}` : ""}${toolDebugPayload ? `\nTool Debug Payload: ${toolDebugPayload}` : ""}`;
373
- errorBody.error.message = (errorBody.error.message || "Unknown error") + debugInfo;
374
-
375
- return new Response(JSON.stringify(errorBody), {
376
- status: response.status,
377
- statusText: response.statusText,
378
- headers
379
- });
380
- }
381
-
382
- if (errorBody?.error?.details && Array.isArray(errorBody.error.details)) {
383
- const retryInfo = errorBody.error.details.find(
384
- (detail: any) => detail['@type'] === 'type.googleapis.com/google.rpc.RetryInfo'
385
- );
386
-
387
- if (retryInfo?.retryDelay) {
388
- const match = retryInfo.retryDelay.match(/^([\d.]+)s$/);
389
- if (match && match[1]) {
390
- const retrySeconds = parseFloat(match[1]);
391
- if (!isNaN(retrySeconds) && retrySeconds > 0) {
392
- const retryAfterSec = Math.ceil(retrySeconds).toString();
393
- const retryAfterMs = Math.ceil(retrySeconds * 1000).toString();
394
- headers.set('Retry-After', retryAfterSec);
395
- headers.set('retry-after-ms', retryAfterMs);
396
- }
397
- }
398
- }
399
- }
400
- }
401
-
402
- const init = {
403
- status: response.status,
404
- statusText: response.statusText,
405
- headers,
406
- };
407
-
408
- const usageFromSse = streaming && isEventStreamResponse ? extractUsageFromSsePayload(text) : null;
409
- const parsed: AntigravityApiBody | null = !streaming || !isEventStreamResponse ? parseAntigravityApiBody(text) : null;
410
- const patched = parsed ? rewriteAntigravityPreviewAccessError(parsed, response.status, requestedModel) : null;
411
- const effectiveBody = patched ?? parsed ?? undefined;
412
-
413
- const usage = usageFromSse ?? (effectiveBody ? extractUsageMetadata(effectiveBody) : null);
414
- if (usage?.cachedContentTokenCount !== undefined) {
415
- headers.set("x-antigravity-cached-content-token-count", String(usage.cachedContentTokenCount));
416
- if (usage.totalTokenCount !== undefined) {
417
- headers.set("x-antigravity-total-token-count", String(usage.totalTokenCount));
418
- }
419
- if (usage.promptTokenCount !== undefined) {
420
- headers.set("x-antigravity-prompt-token-count", String(usage.promptTokenCount));
421
- }
422
- if (usage.candidatesTokenCount !== undefined) {
423
- headers.set("x-antigravity-candidates-token-count", String(usage.candidatesTokenCount));
424
- }
425
- }
426
-
427
- logAntigravityDebugResponse(debugContext, response, {
428
- body: text,
429
- note: streaming ? "Streaming SSE payload" : undefined,
430
- headersOverride: headers,
431
- });
432
-
433
- if (streaming && response.ok && isEventStreamResponse) {
434
- return new Response(transformStreamingPayload(text), init);
435
- }
436
-
437
- if (!parsed) {
438
- return new Response(text, init);
439
- }
440
-
441
- if (effectiveBody?.response !== undefined) {
442
- return new Response(JSON.stringify(effectiveBody.response), init);
443
- }
444
-
445
- if (patched) {
446
- return new Response(JSON.stringify(patched), init);
447
- }
448
-
449
- return new Response(text, init);
450
- } catch (error) {
451
- logAntigravityDebugResponse(debugContext, response, {
452
- error,
453
- note: "Failed to transform Antigravity response",
454
- });
455
- return response;
456
- }
457
- }