opencode-antigravity-auth 1.2.0 → 1.2.1

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.
Files changed (44) hide show
  1. package/README.md +198 -99
  2. package/dist/src/hooks/auto-update-checker/cache.d.ts +3 -0
  3. package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -0
  4. package/dist/src/hooks/auto-update-checker/cache.js +71 -0
  5. package/dist/src/hooks/auto-update-checker/cache.js.map +1 -0
  6. package/dist/src/hooks/auto-update-checker/checker.d.ts +16 -0
  7. package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -0
  8. package/dist/src/hooks/auto-update-checker/checker.js +237 -0
  9. package/dist/src/hooks/auto-update-checker/checker.js.map +1 -0
  10. package/dist/src/hooks/auto-update-checker/constants.d.ts +9 -0
  11. package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -0
  12. package/dist/src/hooks/auto-update-checker/constants.js +23 -0
  13. package/dist/src/hooks/auto-update-checker/constants.js.map +1 -0
  14. package/dist/src/hooks/auto-update-checker/index.d.ts +34 -0
  15. package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -0
  16. package/dist/src/hooks/auto-update-checker/index.js +121 -0
  17. package/dist/src/hooks/auto-update-checker/index.js.map +1 -0
  18. package/dist/src/hooks/auto-update-checker/types.d.ts +25 -0
  19. package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -0
  20. package/dist/src/hooks/auto-update-checker/types.js +1 -0
  21. package/dist/src/hooks/auto-update-checker/types.js.map +1 -0
  22. package/dist/src/plugin/accounts.d.ts +21 -10
  23. package/dist/src/plugin/accounts.d.ts.map +1 -1
  24. package/dist/src/plugin/accounts.js +101 -55
  25. package/dist/src/plugin/accounts.js.map +1 -1
  26. package/dist/src/plugin/debug.d.ts +32 -0
  27. package/dist/src/plugin/debug.d.ts.map +1 -1
  28. package/dist/src/plugin/debug.js +140 -12
  29. package/dist/src/plugin/debug.js.map +1 -1
  30. package/dist/src/plugin/request.d.ts +3 -1
  31. package/dist/src/plugin/request.d.ts.map +1 -1
  32. package/dist/src/plugin/request.js +352 -16
  33. package/dist/src/plugin/request.js.map +1 -1
  34. package/dist/src/plugin/storage.d.ts +23 -7
  35. package/dist/src/plugin/storage.d.ts.map +1 -1
  36. package/dist/src/plugin/storage.js +54 -10
  37. package/dist/src/plugin/storage.js.map +1 -1
  38. package/dist/src/plugin/types.d.ts +8 -0
  39. package/dist/src/plugin/types.d.ts.map +1 -1
  40. package/dist/src/plugin.d.ts +3 -3
  41. package/dist/src/plugin.d.ts.map +1 -1
  42. package/dist/src/plugin.js +779 -476
  43. package/dist/src/plugin.js.map +1 -1
  44. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import crypto from "node:crypto";
2
2
  import { ANTIGRAVITY_HEADERS, ANTIGRAVITY_ENDPOINT, } from "../constants";
3
3
  import { cacheSignature, getCachedSignature } from "./cache";
4
- import { logAntigravityDebugResponse } from "./debug";
5
- import { extractThinkingConfig, extractUsageFromSsePayload, extractUsageMetadata, filterUnsignedThinkingBlocks, filterMessagesThinkingBlocks, isThinkingCapableModel, normalizeThinkingConfig, parseAntigravityApiBody, resolveThinkingConfig, rewriteAntigravityPreviewAccessError, transformThinkingParts, } from "./request-helpers";
4
+ import { DEBUG_MESSAGE_PREFIX, isDebugEnabled, logAntigravityDebugResponse, } from "./debug";
5
+ import { DEFAULT_THINKING_BUDGET, extractThinkingConfig, extractUsageFromSsePayload, extractUsageMetadata, filterUnsignedThinkingBlocks, filterMessagesThinkingBlocks, isThinkingCapableModel, normalizeThinkingConfig, parseAntigravityApiBody, resolveThinkingConfig, rewriteAntigravityPreviewAccessError, transformThinkingParts, } from "./request-helpers";
6
6
  /**
7
7
  * Stable session ID for the plugin's lifetime.
8
8
  * This is used for caching thinking signatures across multi-turn conversations.
@@ -11,6 +11,257 @@ import { extractThinkingConfig, extractUsageFromSsePayload, extractUsageMetadata
11
11
  const PLUGIN_SESSION_ID = `-${crypto.randomUUID()}`;
12
12
  // Claude thinking models need a sufficiently large max output token limit when thinking is enabled.
13
13
  const CLAUDE_THINKING_MAX_OUTPUT_TOKENS = 64_000;
14
+ const MIN_SIGNATURE_LENGTH = 50;
15
+ const lastSignedThinkingBySessionId = new Map();
16
+ function formatDebugLinesForThinking(lines) {
17
+ const cleaned = lines
18
+ .map((line) => line.trim())
19
+ .filter((line) => line.length > 0)
20
+ .slice(-50);
21
+ return `${DEBUG_MESSAGE_PREFIX}\n${cleaned.map((line) => `- ${line}`).join("\n")}`;
22
+ }
23
+ function injectDebugThinking(response, debugText) {
24
+ if (!response || typeof response !== "object") {
25
+ return response;
26
+ }
27
+ const resp = response;
28
+ if (Array.isArray(resp.candidates) && resp.candidates.length > 0) {
29
+ const candidates = resp.candidates.slice();
30
+ const first = candidates[0];
31
+ if (first &&
32
+ typeof first === "object" &&
33
+ first.content &&
34
+ typeof first.content === "object" &&
35
+ Array.isArray(first.content.parts)) {
36
+ const parts = [{ thought: true, text: debugText }, ...first.content.parts];
37
+ candidates[0] = { ...first, content: { ...first.content, parts } };
38
+ return { ...resp, candidates };
39
+ }
40
+ return resp;
41
+ }
42
+ if (Array.isArray(resp.content)) {
43
+ const content = [{ type: "thinking", thinking: debugText }, ...resp.content];
44
+ return { ...resp, content };
45
+ }
46
+ if (!resp.reasoning_content) {
47
+ return { ...resp, reasoning_content: debugText };
48
+ }
49
+ return resp;
50
+ }
51
+ function stripInjectedDebugFromParts(parts) {
52
+ if (!Array.isArray(parts)) {
53
+ return parts;
54
+ }
55
+ return parts.filter((part) => {
56
+ if (!part || typeof part !== "object") {
57
+ return true;
58
+ }
59
+ const record = part;
60
+ const text = typeof record.text === "string"
61
+ ? record.text
62
+ : typeof record.thinking === "string"
63
+ ? record.thinking
64
+ : undefined;
65
+ if (text && text.startsWith(DEBUG_MESSAGE_PREFIX)) {
66
+ return false;
67
+ }
68
+ return true;
69
+ });
70
+ }
71
+ function stripInjectedDebugFromRequestPayload(payload) {
72
+ const anyPayload = payload;
73
+ if (Array.isArray(anyPayload.contents)) {
74
+ anyPayload.contents = anyPayload.contents.map((content) => {
75
+ if (!content || typeof content !== "object") {
76
+ return content;
77
+ }
78
+ if (Array.isArray(content.parts)) {
79
+ return { ...content, parts: stripInjectedDebugFromParts(content.parts) };
80
+ }
81
+ if (Array.isArray(content.content)) {
82
+ return { ...content, content: stripInjectedDebugFromParts(content.content) };
83
+ }
84
+ return content;
85
+ });
86
+ }
87
+ if (Array.isArray(anyPayload.messages)) {
88
+ anyPayload.messages = anyPayload.messages.map((message) => {
89
+ if (!message || typeof message !== "object") {
90
+ return message;
91
+ }
92
+ if (Array.isArray(message.content)) {
93
+ return { ...message, content: stripInjectedDebugFromParts(message.content) };
94
+ }
95
+ return message;
96
+ });
97
+ }
98
+ }
99
+ function isGeminiToolUsePart(part) {
100
+ return !!(part && typeof part === "object" && (part.functionCall || part.tool_use || part.toolUse));
101
+ }
102
+ function isGeminiThinkingPart(part) {
103
+ return !!(part &&
104
+ typeof part === "object" &&
105
+ (part.thought === true || part.type === "thinking" || part.type === "reasoning"));
106
+ }
107
+ function ensureThoughtSignature(part, sessionId) {
108
+ if (!part || typeof part !== "object") {
109
+ return part;
110
+ }
111
+ const text = typeof part.text === "string" ? part.text : typeof part.thinking === "string" ? part.thinking : "";
112
+ if (!text) {
113
+ return part;
114
+ }
115
+ if (part.thought === true) {
116
+ if (!part.thoughtSignature) {
117
+ const cached = getCachedSignature(sessionId, text);
118
+ if (cached) {
119
+ return { ...part, thoughtSignature: cached };
120
+ }
121
+ }
122
+ return part;
123
+ }
124
+ if ((part.type === "thinking" || part.type === "reasoning") && !part.signature) {
125
+ const cached = getCachedSignature(sessionId, text);
126
+ if (cached) {
127
+ return { ...part, signature: cached };
128
+ }
129
+ }
130
+ return part;
131
+ }
132
+ function hasSignedThinkingPart(part) {
133
+ if (!part || typeof part !== "object") {
134
+ return false;
135
+ }
136
+ if (part.thought === true) {
137
+ return typeof part.thoughtSignature === "string" && part.thoughtSignature.length >= MIN_SIGNATURE_LENGTH;
138
+ }
139
+ if (part.type === "thinking" || part.type === "reasoning") {
140
+ return typeof part.signature === "string" && part.signature.length >= MIN_SIGNATURE_LENGTH;
141
+ }
142
+ return false;
143
+ }
144
+ function ensureThinkingBeforeToolUseInContents(contents, sessionId) {
145
+ return contents.map((content) => {
146
+ if (!content || typeof content !== "object" || !Array.isArray(content.parts)) {
147
+ return content;
148
+ }
149
+ const role = content.role;
150
+ if (role !== "model" && role !== "assistant") {
151
+ return content;
152
+ }
153
+ const parts = content.parts;
154
+ const hasToolUse = parts.some(isGeminiToolUsePart);
155
+ if (!hasToolUse) {
156
+ return content;
157
+ }
158
+ const thinkingParts = parts.filter(isGeminiThinkingPart).map((p) => ensureThoughtSignature(p, sessionId));
159
+ const otherParts = parts.filter((p) => !isGeminiThinkingPart(p));
160
+ const hasSignedThinking = thinkingParts.some(hasSignedThinkingPart);
161
+ if (hasSignedThinking) {
162
+ return { ...content, parts: [...thinkingParts, ...otherParts] };
163
+ }
164
+ const lastThinking = lastSignedThinkingBySessionId.get(sessionId);
165
+ if (!lastThinking) {
166
+ return content;
167
+ }
168
+ const injected = {
169
+ thought: true,
170
+ text: lastThinking.text,
171
+ thoughtSignature: lastThinking.signature,
172
+ };
173
+ return { ...content, parts: [injected, ...otherParts] };
174
+ });
175
+ }
176
+ function ensureMessageThinkingSignature(block, sessionId) {
177
+ if (!block || typeof block !== "object") {
178
+ return block;
179
+ }
180
+ if (block.type !== "thinking" && block.type !== "redacted_thinking") {
181
+ return block;
182
+ }
183
+ if (typeof block.signature === "string" && block.signature.length >= MIN_SIGNATURE_LENGTH) {
184
+ return block;
185
+ }
186
+ const text = typeof block.thinking === "string" ? block.thinking : typeof block.text === "string" ? block.text : "";
187
+ if (!text) {
188
+ return block;
189
+ }
190
+ const cached = getCachedSignature(sessionId, text);
191
+ if (cached) {
192
+ return { ...block, signature: cached };
193
+ }
194
+ return block;
195
+ }
196
+ function hasToolUseInContents(contents) {
197
+ return contents.some((content) => {
198
+ if (!content || typeof content !== "object" || !Array.isArray(content.parts)) {
199
+ return false;
200
+ }
201
+ return content.parts.some(isGeminiToolUsePart);
202
+ });
203
+ }
204
+ function hasSignedThinkingInContents(contents) {
205
+ return contents.some((content) => {
206
+ if (!content || typeof content !== "object" || !Array.isArray(content.parts)) {
207
+ return false;
208
+ }
209
+ return content.parts.some(hasSignedThinkingPart);
210
+ });
211
+ }
212
+ function hasToolUseInMessages(messages) {
213
+ return messages.some((message) => {
214
+ if (!message || typeof message !== "object" || !Array.isArray(message.content)) {
215
+ return false;
216
+ }
217
+ return message.content.some((block) => block && typeof block === "object" && (block.type === "tool_use" || block.type === "tool_result"));
218
+ });
219
+ }
220
+ function hasSignedThinkingInMessages(messages) {
221
+ return messages.some((message) => {
222
+ if (!message || typeof message !== "object" || !Array.isArray(message.content)) {
223
+ return false;
224
+ }
225
+ return message.content.some((block) => block &&
226
+ typeof block === "object" &&
227
+ (block.type === "thinking" || block.type === "redacted_thinking") &&
228
+ typeof block.signature === "string" &&
229
+ block.signature.length >= MIN_SIGNATURE_LENGTH);
230
+ });
231
+ }
232
+ function ensureThinkingBeforeToolUseInMessages(messages, sessionId) {
233
+ return messages.map((message) => {
234
+ if (!message || typeof message !== "object" || !Array.isArray(message.content)) {
235
+ return message;
236
+ }
237
+ if (message.role !== "assistant") {
238
+ return message;
239
+ }
240
+ const blocks = message.content;
241
+ const hasToolUse = blocks.some((b) => b && typeof b === "object" && (b.type === "tool_use" || b.type === "tool_result"));
242
+ if (!hasToolUse) {
243
+ return message;
244
+ }
245
+ const thinkingBlocks = blocks
246
+ .filter((b) => b && typeof b === "object" && (b.type === "thinking" || b.type === "redacted_thinking"))
247
+ .map((b) => ensureMessageThinkingSignature(b, sessionId));
248
+ const otherBlocks = blocks.filter((b) => !(b && typeof b === "object" && (b.type === "thinking" || b.type === "redacted_thinking")));
249
+ const hasSignedThinking = thinkingBlocks.some((b) => typeof b.signature === "string" && b.signature.length >= MIN_SIGNATURE_LENGTH);
250
+ if (hasSignedThinking) {
251
+ return { ...message, content: [...thinkingBlocks, ...otherBlocks] };
252
+ }
253
+ const lastThinking = lastSignedThinkingBySessionId.get(sessionId);
254
+ if (!lastThinking) {
255
+ return message;
256
+ }
257
+ const injected = {
258
+ type: "thinking",
259
+ thinking: lastThinking.text,
260
+ signature: lastThinking.signature,
261
+ };
262
+ return { ...message, content: [injected, ...otherBlocks] };
263
+ });
264
+ }
14
265
  /**
15
266
  * Gets the stable session ID for this plugin instance.
16
267
  */
@@ -64,12 +315,13 @@ function transformStreamingPayload(payload) {
64
315
  * transforming each line as it arrives for true real-time streaming support.
65
316
  * Optionally caches thinking signatures for Claude multi-turn conversations.
66
317
  */
67
- function createStreamingTransformer(sessionId) {
318
+ function createStreamingTransformer(sessionId, debugText) {
68
319
  const decoder = new TextDecoder();
69
320
  const encoder = new TextEncoder();
70
321
  let buffer = "";
71
322
  // Buffer for accumulating thinking text per candidate index (for signature caching)
72
323
  const thoughtBuffer = new Map();
324
+ const debugState = { injected: false };
73
325
  return new TransformStream({
74
326
  transform(chunk, controller) {
75
327
  // Decode chunk with stream: true to handle multi-byte characters correctly
@@ -80,7 +332,7 @@ function createStreamingTransformer(sessionId) {
80
332
  buffer = lines.pop() || "";
81
333
  for (const line of lines) {
82
334
  // Transform and forward each line immediately
83
- const transformedLine = transformSseLine(line, sessionId, thoughtBuffer);
335
+ const transformedLine = transformSseLine(line, sessionId, thoughtBuffer, debugText, debugState);
84
336
  controller.enqueue(encoder.encode(transformedLine + "\n"));
85
337
  }
86
338
  },
@@ -89,7 +341,7 @@ function createStreamingTransformer(sessionId) {
89
341
  buffer += decoder.decode();
90
342
  // Process any remaining data in buffer
91
343
  if (buffer) {
92
- const transformedLine = transformSseLine(buffer, sessionId, thoughtBuffer);
344
+ const transformedLine = transformSseLine(buffer, sessionId, thoughtBuffer, debugText, debugState);
93
345
  controller.enqueue(encoder.encode(transformedLine));
94
346
  }
95
347
  },
@@ -99,7 +351,7 @@ function createStreamingTransformer(sessionId) {
99
351
  * Transforms a single SSE line, extracting and transforming the inner response.
100
352
  * Optionally caches thinking signatures for Claude multi-turn support.
101
353
  */
102
- function transformSseLine(line, sessionId, thoughtBuffer) {
354
+ function transformSseLine(line, sessionId, thoughtBuffer, debugText, debugState) {
103
355
  if (!line.startsWith("data:")) {
104
356
  return line;
105
357
  }
@@ -110,11 +362,15 @@ function transformSseLine(line, sessionId, thoughtBuffer) {
110
362
  try {
111
363
  const parsed = JSON.parse(json);
112
364
  if (parsed.response !== undefined) {
113
- // Cache thinking signatures for Claude multi-turn support
114
365
  if (sessionId && thoughtBuffer) {
115
366
  cacheThinkingSignatures(parsed.response, sessionId, thoughtBuffer);
116
367
  }
117
- const transformed = transformThinkingParts(parsed.response);
368
+ let response = parsed.response;
369
+ if (debugText && debugState && !debugState.injected) {
370
+ response = injectDebugThinking(response, debugText);
371
+ debugState.injected = true;
372
+ }
373
+ const transformed = transformThinkingParts(response);
118
374
  return `data: ${JSON.stringify(transformed)}`;
119
375
  }
120
376
  }
@@ -147,6 +403,7 @@ function cacheThinkingSignatures(response, sessionId, thoughtBuffer) {
147
403
  const fullText = thoughtBuffer.get(index) ?? "";
148
404
  if (fullText && sessionId) {
149
405
  cacheSignature(sessionId, fullText, part.thoughtSignature);
406
+ lastSignedThinkingBySessionId.set(sessionId, { text: fullText, signature: part.thoughtSignature });
150
407
  }
151
408
  }
152
409
  });
@@ -161,6 +418,7 @@ function cacheThinkingSignatures(response, sessionId, thoughtBuffer) {
161
418
  }
162
419
  if (block?.signature && thinkingText && sessionId) {
163
420
  cacheSignature(sessionId, thinkingText, block.signature);
421
+ lastSignedThinkingBySessionId.set(sessionId, { text: thinkingText, signature: block.signature });
164
422
  }
165
423
  });
166
424
  }
@@ -177,6 +435,7 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
177
435
  const toolDebugSummaries = [];
178
436
  let toolDebugPayload;
179
437
  let sessionId;
438
+ let needsSignedThinkingWarmup = false;
180
439
  if (!isGenerativeLanguageRequest(input)) {
181
440
  return {
182
441
  request: input,
@@ -195,8 +454,12 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
195
454
  };
196
455
  }
197
456
  const [, rawModel = "", rawAction = ""] = match;
198
- const effectiveModel = rawModel;
199
- const upstreamModel = rawModel;
457
+ const requestedModel = rawModel;
458
+ let upstreamModel = rawModel;
459
+ if (upstreamModel === "gemini-2.5-flash-image") {
460
+ upstreamModel = "gemini-2.5-flash";
461
+ }
462
+ const effectiveModel = upstreamModel;
200
463
  const streaming = rawAction === STREAM_ACTION;
201
464
  const baseEndpoint = endpointOverride ?? ANTIGRAVITY_ENDPOINT;
202
465
  const transformedUrl = `${baseEndpoint}/v1internal:${rawAction}${streaming ? "?alt=sse" : ""}`;
@@ -230,7 +493,14 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
230
493
  for (const req of requestObjects) {
231
494
  // Use stable session ID for signature caching across multi-turn conversations
232
495
  req.sessionId = PLUGIN_SESSION_ID;
496
+ stripInjectedDebugFromRequestPayload(req);
233
497
  if (isClaudeModel) {
498
+ if (isClaudeThinkingModel && Array.isArray(req.contents)) {
499
+ req.contents = ensureThinkingBeforeToolUseInContents(req.contents, PLUGIN_SESSION_ID);
500
+ }
501
+ if (isClaudeThinkingModel && Array.isArray(req.messages)) {
502
+ req.messages = ensureThinkingBeforeToolUseInMessages(req.messages, PLUGIN_SESSION_ID);
503
+ }
234
504
  if (Array.isArray(req.contents)) {
235
505
  req.contents = filterUnsignedThinkingBlocks(req.contents, PLUGIN_SESSION_ID, getCachedSignature);
236
506
  }
@@ -239,6 +509,14 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
239
509
  }
240
510
  }
241
511
  }
512
+ if (isClaudeThinkingModel && sessionId) {
513
+ const hasToolUse = requestObjects.some((req) => (Array.isArray(req.contents) && hasToolUseInContents(req.contents)) ||
514
+ (Array.isArray(req.messages) && hasToolUseInMessages(req.messages)));
515
+ const hasSignedThinking = requestObjects.some((req) => (Array.isArray(req.contents) && hasSignedThinkingInContents(req.contents)) ||
516
+ (Array.isArray(req.messages) && hasSignedThinkingInMessages(req.messages)));
517
+ const hasCachedThinking = lastSignedThinkingBySessionId.has(sessionId);
518
+ needsSignedThinkingWarmup = hasToolUse && !hasSignedThinking && !hasCachedThinking;
519
+ }
242
520
  body = JSON.stringify(wrappedBody);
243
521
  }
244
522
  else {
@@ -575,6 +853,21 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
575
853
  // Attempts to restore signatures from cache for multi-turn conversations
576
854
  // Handle both Gemini-style contents[] and Anthropic-style messages[] payloads.
577
855
  if (isClaudeModel) {
856
+ if (isClaudeThinkingModel && Array.isArray(requestPayload.contents)) {
857
+ requestPayload.contents = ensureThinkingBeforeToolUseInContents(requestPayload.contents, PLUGIN_SESSION_ID);
858
+ }
859
+ if (isClaudeThinkingModel && Array.isArray(requestPayload.messages)) {
860
+ requestPayload.messages = ensureThinkingBeforeToolUseInMessages(requestPayload.messages, PLUGIN_SESSION_ID);
861
+ }
862
+ if (isClaudeThinkingModel) {
863
+ const sessionKey = PLUGIN_SESSION_ID;
864
+ const hasToolUse = (Array.isArray(requestPayload.contents) && hasToolUseInContents(requestPayload.contents)) ||
865
+ (Array.isArray(requestPayload.messages) && hasToolUseInMessages(requestPayload.messages));
866
+ const hasSignedThinking = (Array.isArray(requestPayload.contents) && hasSignedThinkingInContents(requestPayload.contents)) ||
867
+ (Array.isArray(requestPayload.messages) && hasSignedThinkingInMessages(requestPayload.messages));
868
+ const hasCachedThinking = lastSignedThinkingBySessionId.has(sessionKey);
869
+ needsSignedThinkingWarmup = hasToolUse && !hasSignedThinking && !hasCachedThinking;
870
+ }
578
871
  if (Array.isArray(requestPayload.contents)) {
579
872
  requestPayload.contents = filterUnsignedThinkingBlocks(requestPayload.contents, PLUGIN_SESSION_ID, getCachedSignature);
580
873
  }
@@ -637,6 +930,7 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
637
930
  if ("model" in requestPayload) {
638
931
  delete requestPayload.model;
639
932
  }
933
+ stripInjectedDebugFromRequestPayload(requestPayload);
640
934
  const effectiveProjectId = projectId?.trim() || generateSyntheticProjectId();
641
935
  resolvedProjectId = effectiveProjectId;
642
936
  const wrappedBody = {
@@ -693,7 +987,7 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
693
987
  body,
694
988
  },
695
989
  streaming,
696
- requestedModel: rawModel,
990
+ requestedModel,
697
991
  effectiveModel: upstreamModel,
698
992
  projectId: resolvedProjectId,
699
993
  endpoint: transformedUrl,
@@ -701,8 +995,45 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
701
995
  toolDebugMissing,
702
996
  toolDebugSummary: toolDebugSummaries.slice(0, 20).join(" | "),
703
997
  toolDebugPayload,
998
+ needsSignedThinkingWarmup,
704
999
  };
705
1000
  }
1001
+ export function buildThinkingWarmupBody(bodyText, isClaudeThinkingModel) {
1002
+ if (!bodyText || !isClaudeThinkingModel) {
1003
+ return null;
1004
+ }
1005
+ let parsed;
1006
+ try {
1007
+ parsed = JSON.parse(bodyText);
1008
+ }
1009
+ catch {
1010
+ return null;
1011
+ }
1012
+ const warmupPrompt = "Warmup request for thinking signature.";
1013
+ const updateRequest = (req) => {
1014
+ req.contents = [{ role: "user", parts: [{ text: warmupPrompt }] }];
1015
+ delete req.tools;
1016
+ delete req.toolConfig;
1017
+ const generationConfig = (req.generationConfig ?? {});
1018
+ generationConfig.thinkingConfig = {
1019
+ include_thoughts: true,
1020
+ thinking_budget: DEFAULT_THINKING_BUDGET,
1021
+ };
1022
+ generationConfig.maxOutputTokens = CLAUDE_THINKING_MAX_OUTPUT_TOKENS;
1023
+ req.generationConfig = generationConfig;
1024
+ };
1025
+ if (parsed.request && typeof parsed.request === "object") {
1026
+ updateRequest(parsed.request);
1027
+ const nested = parsed.request.request;
1028
+ if (nested && typeof nested === "object") {
1029
+ updateRequest(nested);
1030
+ }
1031
+ }
1032
+ else {
1033
+ updateRequest(parsed);
1034
+ }
1035
+ return JSON.stringify(parsed);
1036
+ }
706
1037
  /**
707
1038
  * Normalizes Antigravity responses: applies retry headers, extracts cache usage into headers,
708
1039
  * rewrites preview errors, flattens streaming payloads, and logs debug metadata.
@@ -710,10 +1041,13 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
710
1041
  * For streaming SSE responses, uses TransformStream for true real-time incremental streaming.
711
1042
  * Thinking/reasoning tokens are transformed and forwarded immediately as they arrive.
712
1043
  */
713
- export async function transformAntigravityResponse(response, streaming, debugContext, requestedModel, projectId, endpoint, effectiveModel, sessionId, toolDebugMissing, toolDebugSummary, toolDebugPayload) {
1044
+ export async function transformAntigravityResponse(response, streaming, debugContext, requestedModel, projectId, endpoint, effectiveModel, sessionId, toolDebugMissing, toolDebugSummary, toolDebugPayload, debugLines) {
714
1045
  const contentType = response.headers.get("content-type") ?? "";
715
1046
  const isJsonResponse = contentType.includes("application/json");
716
1047
  const isEventStreamResponse = contentType.includes("text/event-stream");
1048
+ const debugText = isDebugEnabled() && Array.isArray(debugLines) && debugLines.length > 0
1049
+ ? formatDebugLinesForThinking(debugLines)
1050
+ : undefined;
717
1051
  if (!isJsonResponse && !isEventStreamResponse) {
718
1052
  logAntigravityDebugResponse(debugContext, response, {
719
1053
  note: "Non-JSON response (body omitted)",
@@ -730,7 +1064,7 @@ export async function transformAntigravityResponse(response, streaming, debugCon
730
1064
  });
731
1065
  // Use the optimized line-by-line transformer for immediate forwarding
732
1066
  // This ensures thinking/reasoning content streams in real-time
733
- return new Response(response.body.pipeThrough(createStreamingTransformer(sessionId)), {
1067
+ return new Response(response.body.pipeThrough(createStreamingTransformer(sessionId, debugText)), {
734
1068
  status: response.status,
735
1069
  statusText: response.statusText,
736
1070
  headers,
@@ -749,8 +1083,9 @@ export async function transformAntigravityResponse(response, streaming, debugCon
749
1083
  }
750
1084
  // Inject Debug Info
751
1085
  if (errorBody?.error) {
752
- 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}` : ""}`;
753
- errorBody.error.message = (errorBody.error.message || "Unknown error") + debugInfo;
1086
+ 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}` : ""}`;
1087
+ const injectedDebug = debugText ? `\n\n${debugText}` : "";
1088
+ errorBody.error.message = (errorBody.error.message || "Unknown error") + debugInfo + injectedDebug;
754
1089
  return new Response(JSON.stringify(errorBody), {
755
1090
  status: response.status,
756
1091
  statusText: response.statusText,
@@ -806,7 +1141,8 @@ export async function transformAntigravityResponse(response, streaming, debugCon
806
1141
  return new Response(text, init);
807
1142
  }
808
1143
  if (effectiveBody?.response !== undefined) {
809
- const transformed = transformThinkingParts(effectiveBody.response);
1144
+ const responseBody = debugText ? injectDebugThinking(effectiveBody.response, debugText) : effectiveBody.response;
1145
+ const transformed = transformThinkingParts(responseBody);
810
1146
  return new Response(JSON.stringify(transformed), init);
811
1147
  }
812
1148
  if (patched) {