opencode-antigravity-auth 1.2.0 → 1.2.2
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.
- package/README.md +212 -98
- package/dist/src/constants.d.ts +6 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +5 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/cache.d.ts +3 -0
- package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/cache.js +71 -0
- package/dist/src/hooks/auto-update-checker/cache.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/checker.d.ts +16 -0
- package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/checker.js +237 -0
- package/dist/src/hooks/auto-update-checker/checker.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/constants.d.ts +9 -0
- package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/constants.js +23 -0
- package/dist/src/hooks/auto-update-checker/constants.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/index.d.ts +34 -0
- package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/index.js +121 -0
- package/dist/src/hooks/auto-update-checker/index.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/types.d.ts +25 -0
- package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/types.js +1 -0
- package/dist/src/hooks/auto-update-checker/types.js.map +1 -0
- package/dist/src/plugin/accounts.d.ts +25 -11
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +161 -55
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/debug.d.ts +32 -0
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +140 -12
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/request.d.ts +6 -2
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +361 -21
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/storage.d.ts +52 -9
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js +91 -10
- package/dist/src/plugin/storage.js.map +1 -1
- package/dist/src/plugin/types.d.ts +8 -0
- package/dist/src/plugin/types.d.ts.map +1 -1
- package/dist/src/plugin.d.ts +3 -3
- package/dist/src/plugin.d.ts.map +1 -1
- package/dist/src/plugin.js +865 -486
- package/dist/src/plugin.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import { ANTIGRAVITY_HEADERS, ANTIGRAVITY_ENDPOINT, } from "../constants";
|
|
2
|
+
import { ANTIGRAVITY_HEADERS, GEMINI_CLI_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
|
-
|
|
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
|
}
|
|
@@ -169,7 +427,7 @@ function cacheThinkingSignatures(response, sessionId, thoughtBuffer) {
|
|
|
169
427
|
* Rewrites OpenAI-style requests into Antigravity shape, normalizing model, headers,
|
|
170
428
|
* optional cached_content, and thinking config. Also toggles streaming mode for SSE actions.
|
|
171
429
|
*/
|
|
172
|
-
export function prepareAntigravityRequest(input, init, accessToken, projectId, endpointOverride) {
|
|
430
|
+
export function prepareAntigravityRequest(input, init, accessToken, projectId, endpointOverride, headerStyle = "antigravity") {
|
|
173
431
|
const baseInit = { ...init };
|
|
174
432
|
const headers = new Headers(init?.headers ?? {});
|
|
175
433
|
let resolvedProjectId = projectId?.trim() || "";
|
|
@@ -177,11 +435,13 @@ 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,
|
|
183
442
|
init: { ...baseInit, headers },
|
|
184
443
|
streaming: false,
|
|
444
|
+
headerStyle,
|
|
185
445
|
};
|
|
186
446
|
}
|
|
187
447
|
headers.set("Authorization", `Bearer ${accessToken}`);
|
|
@@ -192,11 +452,16 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
192
452
|
request: input,
|
|
193
453
|
init: { ...baseInit, headers },
|
|
194
454
|
streaming: false,
|
|
455
|
+
headerStyle,
|
|
195
456
|
};
|
|
196
457
|
}
|
|
197
458
|
const [, rawModel = "", rawAction = ""] = match;
|
|
198
|
-
const
|
|
199
|
-
|
|
459
|
+
const requestedModel = rawModel;
|
|
460
|
+
let upstreamModel = rawModel;
|
|
461
|
+
if (upstreamModel === "gemini-2.5-flash-image") {
|
|
462
|
+
upstreamModel = "gemini-2.5-flash";
|
|
463
|
+
}
|
|
464
|
+
const effectiveModel = upstreamModel;
|
|
200
465
|
const streaming = rawAction === STREAM_ACTION;
|
|
201
466
|
const baseEndpoint = endpointOverride ?? ANTIGRAVITY_ENDPOINT;
|
|
202
467
|
const transformedUrl = `${baseEndpoint}/v1internal:${rawAction}${streaming ? "?alt=sse" : ""}`;
|
|
@@ -230,7 +495,14 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
230
495
|
for (const req of requestObjects) {
|
|
231
496
|
// Use stable session ID for signature caching across multi-turn conversations
|
|
232
497
|
req.sessionId = PLUGIN_SESSION_ID;
|
|
498
|
+
stripInjectedDebugFromRequestPayload(req);
|
|
233
499
|
if (isClaudeModel) {
|
|
500
|
+
if (isClaudeThinkingModel && Array.isArray(req.contents)) {
|
|
501
|
+
req.contents = ensureThinkingBeforeToolUseInContents(req.contents, PLUGIN_SESSION_ID);
|
|
502
|
+
}
|
|
503
|
+
if (isClaudeThinkingModel && Array.isArray(req.messages)) {
|
|
504
|
+
req.messages = ensureThinkingBeforeToolUseInMessages(req.messages, PLUGIN_SESSION_ID);
|
|
505
|
+
}
|
|
234
506
|
if (Array.isArray(req.contents)) {
|
|
235
507
|
req.contents = filterUnsignedThinkingBlocks(req.contents, PLUGIN_SESSION_ID, getCachedSignature);
|
|
236
508
|
}
|
|
@@ -239,6 +511,14 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
239
511
|
}
|
|
240
512
|
}
|
|
241
513
|
}
|
|
514
|
+
if (isClaudeThinkingModel && sessionId) {
|
|
515
|
+
const hasToolUse = requestObjects.some((req) => (Array.isArray(req.contents) && hasToolUseInContents(req.contents)) ||
|
|
516
|
+
(Array.isArray(req.messages) && hasToolUseInMessages(req.messages)));
|
|
517
|
+
const hasSignedThinking = requestObjects.some((req) => (Array.isArray(req.contents) && hasSignedThinkingInContents(req.contents)) ||
|
|
518
|
+
(Array.isArray(req.messages) && hasSignedThinkingInMessages(req.messages)));
|
|
519
|
+
const hasCachedThinking = lastSignedThinkingBySessionId.has(sessionId);
|
|
520
|
+
needsSignedThinkingWarmup = hasToolUse && !hasSignedThinking && !hasCachedThinking;
|
|
521
|
+
}
|
|
242
522
|
body = JSON.stringify(wrappedBody);
|
|
243
523
|
}
|
|
244
524
|
else {
|
|
@@ -575,6 +855,21 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
575
855
|
// Attempts to restore signatures from cache for multi-turn conversations
|
|
576
856
|
// Handle both Gemini-style contents[] and Anthropic-style messages[] payloads.
|
|
577
857
|
if (isClaudeModel) {
|
|
858
|
+
if (isClaudeThinkingModel && Array.isArray(requestPayload.contents)) {
|
|
859
|
+
requestPayload.contents = ensureThinkingBeforeToolUseInContents(requestPayload.contents, PLUGIN_SESSION_ID);
|
|
860
|
+
}
|
|
861
|
+
if (isClaudeThinkingModel && Array.isArray(requestPayload.messages)) {
|
|
862
|
+
requestPayload.messages = ensureThinkingBeforeToolUseInMessages(requestPayload.messages, PLUGIN_SESSION_ID);
|
|
863
|
+
}
|
|
864
|
+
if (isClaudeThinkingModel) {
|
|
865
|
+
const sessionKey = PLUGIN_SESSION_ID;
|
|
866
|
+
const hasToolUse = (Array.isArray(requestPayload.contents) && hasToolUseInContents(requestPayload.contents)) ||
|
|
867
|
+
(Array.isArray(requestPayload.messages) && hasToolUseInMessages(requestPayload.messages));
|
|
868
|
+
const hasSignedThinking = (Array.isArray(requestPayload.contents) && hasSignedThinkingInContents(requestPayload.contents)) ||
|
|
869
|
+
(Array.isArray(requestPayload.messages) && hasSignedThinkingInMessages(requestPayload.messages));
|
|
870
|
+
const hasCachedThinking = lastSignedThinkingBySessionId.has(sessionKey);
|
|
871
|
+
needsSignedThinkingWarmup = hasToolUse && !hasSignedThinking && !hasCachedThinking;
|
|
872
|
+
}
|
|
578
873
|
if (Array.isArray(requestPayload.contents)) {
|
|
579
874
|
requestPayload.contents = filterUnsignedThinkingBlocks(requestPayload.contents, PLUGIN_SESSION_ID, getCachedSignature);
|
|
580
875
|
}
|
|
@@ -637,6 +932,7 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
637
932
|
if ("model" in requestPayload) {
|
|
638
933
|
delete requestPayload.model;
|
|
639
934
|
}
|
|
935
|
+
stripInjectedDebugFromRequestPayload(requestPayload);
|
|
640
936
|
const effectiveProjectId = projectId?.trim() || generateSyntheticProjectId();
|
|
641
937
|
resolvedProjectId = effectiveProjectId;
|
|
642
938
|
const wrappedBody = {
|
|
@@ -678,9 +974,10 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
678
974
|
headers.set("anthropic-beta", interleavedHeader);
|
|
679
975
|
}
|
|
680
976
|
}
|
|
681
|
-
|
|
682
|
-
headers.set("
|
|
683
|
-
headers.set("Client
|
|
977
|
+
const selectedHeaders = headerStyle === "gemini-cli" ? GEMINI_CLI_HEADERS : ANTIGRAVITY_HEADERS;
|
|
978
|
+
headers.set("User-Agent", selectedHeaders["User-Agent"]);
|
|
979
|
+
headers.set("X-Goog-Api-Client", selectedHeaders["X-Goog-Api-Client"]);
|
|
980
|
+
headers.set("Client-Metadata", selectedHeaders["Client-Metadata"]);
|
|
684
981
|
// Optional debug header to observe tool normalization on the backend if surfaced
|
|
685
982
|
if (toolDebugMissing > 0) {
|
|
686
983
|
headers.set("X-Opencode-Tools-Debug", String(toolDebugMissing));
|
|
@@ -693,7 +990,7 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
693
990
|
body,
|
|
694
991
|
},
|
|
695
992
|
streaming,
|
|
696
|
-
requestedModel
|
|
993
|
+
requestedModel,
|
|
697
994
|
effectiveModel: upstreamModel,
|
|
698
995
|
projectId: resolvedProjectId,
|
|
699
996
|
endpoint: transformedUrl,
|
|
@@ -701,8 +998,46 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
701
998
|
toolDebugMissing,
|
|
702
999
|
toolDebugSummary: toolDebugSummaries.slice(0, 20).join(" | "),
|
|
703
1000
|
toolDebugPayload,
|
|
1001
|
+
needsSignedThinkingWarmup,
|
|
1002
|
+
headerStyle,
|
|
704
1003
|
};
|
|
705
1004
|
}
|
|
1005
|
+
export function buildThinkingWarmupBody(bodyText, isClaudeThinkingModel) {
|
|
1006
|
+
if (!bodyText || !isClaudeThinkingModel) {
|
|
1007
|
+
return null;
|
|
1008
|
+
}
|
|
1009
|
+
let parsed;
|
|
1010
|
+
try {
|
|
1011
|
+
parsed = JSON.parse(bodyText);
|
|
1012
|
+
}
|
|
1013
|
+
catch {
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
const warmupPrompt = "Warmup request for thinking signature.";
|
|
1017
|
+
const updateRequest = (req) => {
|
|
1018
|
+
req.contents = [{ role: "user", parts: [{ text: warmupPrompt }] }];
|
|
1019
|
+
delete req.tools;
|
|
1020
|
+
delete req.toolConfig;
|
|
1021
|
+
const generationConfig = (req.generationConfig ?? {});
|
|
1022
|
+
generationConfig.thinkingConfig = {
|
|
1023
|
+
include_thoughts: true,
|
|
1024
|
+
thinking_budget: DEFAULT_THINKING_BUDGET,
|
|
1025
|
+
};
|
|
1026
|
+
generationConfig.maxOutputTokens = CLAUDE_THINKING_MAX_OUTPUT_TOKENS;
|
|
1027
|
+
req.generationConfig = generationConfig;
|
|
1028
|
+
};
|
|
1029
|
+
if (parsed.request && typeof parsed.request === "object") {
|
|
1030
|
+
updateRequest(parsed.request);
|
|
1031
|
+
const nested = parsed.request.request;
|
|
1032
|
+
if (nested && typeof nested === "object") {
|
|
1033
|
+
updateRequest(nested);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
updateRequest(parsed);
|
|
1038
|
+
}
|
|
1039
|
+
return JSON.stringify(parsed);
|
|
1040
|
+
}
|
|
706
1041
|
/**
|
|
707
1042
|
* Normalizes Antigravity responses: applies retry headers, extracts cache usage into headers,
|
|
708
1043
|
* rewrites preview errors, flattens streaming payloads, and logs debug metadata.
|
|
@@ -710,10 +1045,13 @@ export function prepareAntigravityRequest(input, init, accessToken, projectId, e
|
|
|
710
1045
|
* For streaming SSE responses, uses TransformStream for true real-time incremental streaming.
|
|
711
1046
|
* Thinking/reasoning tokens are transformed and forwarded immediately as they arrive.
|
|
712
1047
|
*/
|
|
713
|
-
export async function transformAntigravityResponse(response, streaming, debugContext, requestedModel, projectId, endpoint, effectiveModel, sessionId, toolDebugMissing, toolDebugSummary, toolDebugPayload) {
|
|
1048
|
+
export async function transformAntigravityResponse(response, streaming, debugContext, requestedModel, projectId, endpoint, effectiveModel, sessionId, toolDebugMissing, toolDebugSummary, toolDebugPayload, debugLines) {
|
|
714
1049
|
const contentType = response.headers.get("content-type") ?? "";
|
|
715
1050
|
const isJsonResponse = contentType.includes("application/json");
|
|
716
1051
|
const isEventStreamResponse = contentType.includes("text/event-stream");
|
|
1052
|
+
const debugText = isDebugEnabled() && Array.isArray(debugLines) && debugLines.length > 0
|
|
1053
|
+
? formatDebugLinesForThinking(debugLines)
|
|
1054
|
+
: undefined;
|
|
717
1055
|
if (!isJsonResponse && !isEventStreamResponse) {
|
|
718
1056
|
logAntigravityDebugResponse(debugContext, response, {
|
|
719
1057
|
note: "Non-JSON response (body omitted)",
|
|
@@ -730,7 +1068,7 @@ export async function transformAntigravityResponse(response, streaming, debugCon
|
|
|
730
1068
|
});
|
|
731
1069
|
// Use the optimized line-by-line transformer for immediate forwarding
|
|
732
1070
|
// This ensures thinking/reasoning content streams in real-time
|
|
733
|
-
return new Response(response.body.pipeThrough(createStreamingTransformer(sessionId)), {
|
|
1071
|
+
return new Response(response.body.pipeThrough(createStreamingTransformer(sessionId, debugText)), {
|
|
734
1072
|
status: response.status,
|
|
735
1073
|
statusText: response.statusText,
|
|
736
1074
|
headers,
|
|
@@ -749,8 +1087,9 @@ export async function transformAntigravityResponse(response, streaming, debugCon
|
|
|
749
1087
|
}
|
|
750
1088
|
// Inject Debug Info
|
|
751
1089
|
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(
|
|
753
|
-
|
|
1090
|
+
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}` : ""}`;
|
|
1091
|
+
const injectedDebug = debugText ? `\n\n${debugText}` : "";
|
|
1092
|
+
errorBody.error.message = (errorBody.error.message || "Unknown error") + debugInfo + injectedDebug;
|
|
754
1093
|
return new Response(JSON.stringify(errorBody), {
|
|
755
1094
|
status: response.status,
|
|
756
1095
|
statusText: response.statusText,
|
|
@@ -806,7 +1145,8 @@ export async function transformAntigravityResponse(response, streaming, debugCon
|
|
|
806
1145
|
return new Response(text, init);
|
|
807
1146
|
}
|
|
808
1147
|
if (effectiveBody?.response !== undefined) {
|
|
809
|
-
const
|
|
1148
|
+
const responseBody = debugText ? injectDebugThinking(effectiveBody.response, debugText) : effectiveBody.response;
|
|
1149
|
+
const transformed = transformThinkingParts(responseBody);
|
|
810
1150
|
return new Response(JSON.stringify(transformed), init);
|
|
811
1151
|
}
|
|
812
1152
|
if (patched) {
|