@agenr/agenr-plugin 1.6.0

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.
@@ -0,0 +1,712 @@
1
+ import {
2
+ convertMessages,
3
+ convertTools,
4
+ isThinkingPart,
5
+ mapStopReasonString,
6
+ mapToolChoice,
7
+ retainThoughtSignature
8
+ } from "./chunk-6DQXEU2A.js";
9
+ import {
10
+ buildBaseOptions,
11
+ clampReasoning,
12
+ sanitizeSurrogates
13
+ } from "./chunk-P5HNPYGQ.js";
14
+ import {
15
+ AssistantMessageEventStream,
16
+ calculateCost
17
+ } from "./chunk-OLOUBEE5.js";
18
+ import "./chunk-EAQYK3U2.js";
19
+
20
+ // ../../node_modules/.pnpm/@mariozechner+pi-ai@0.63.2_@modelcontextprotocol+sdk@1.27.1_zod@4.3.6__ws@8.20.0_zod@4.3.6/node_modules/@mariozechner/pi-ai/dist/providers/google-gemini-cli.js
21
+ var DEFAULT_ENDPOINT = "https://cloudcode-pa.googleapis.com";
22
+ var ANTIGRAVITY_DAILY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
23
+ var ANTIGRAVITY_AUTOPUSH_ENDPOINT = "https://autopush-cloudcode-pa.sandbox.googleapis.com";
24
+ var ANTIGRAVITY_ENDPOINT_FALLBACKS = [
25
+ ANTIGRAVITY_DAILY_ENDPOINT,
26
+ ANTIGRAVITY_AUTOPUSH_ENDPOINT,
27
+ DEFAULT_ENDPOINT
28
+ ];
29
+ var GEMINI_CLI_HEADERS = {
30
+ "User-Agent": "google-cloud-sdk vscode_cloudshelleditor/0.1",
31
+ "X-Goog-Api-Client": "gl-node/22.17.0",
32
+ "Client-Metadata": JSON.stringify({
33
+ ideType: "IDE_UNSPECIFIED",
34
+ platform: "PLATFORM_UNSPECIFIED",
35
+ pluginType: "GEMINI"
36
+ })
37
+ };
38
+ var DEFAULT_ANTIGRAVITY_VERSION = "1.18.4";
39
+ function getAntigravityHeaders() {
40
+ const version = process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION;
41
+ return {
42
+ "User-Agent": `antigravity/${version} darwin/arm64`
43
+ };
44
+ }
45
+ var ANTIGRAVITY_SYSTEM_INSTRUCTION = "You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding.You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.**Absolute paths only****Proactiveness**";
46
+ var toolCallCounter = 0;
47
+ var MAX_RETRIES = 3;
48
+ var BASE_DELAY_MS = 1e3;
49
+ var MAX_EMPTY_STREAM_RETRIES = 2;
50
+ var EMPTY_STREAM_BASE_DELAY_MS = 500;
51
+ var CLAUDE_THINKING_BETA_HEADER = "interleaved-thinking-2025-05-14";
52
+ function extractRetryDelay(errorText, response) {
53
+ const normalizeDelay = (ms) => ms > 0 ? Math.ceil(ms + 1e3) : void 0;
54
+ const headers = response instanceof Headers ? response : response?.headers;
55
+ if (headers) {
56
+ const retryAfter = headers.get("retry-after");
57
+ if (retryAfter) {
58
+ const retryAfterSeconds = Number(retryAfter);
59
+ if (Number.isFinite(retryAfterSeconds)) {
60
+ const delay = normalizeDelay(retryAfterSeconds * 1e3);
61
+ if (delay !== void 0) {
62
+ return delay;
63
+ }
64
+ }
65
+ const retryAfterDate = new Date(retryAfter);
66
+ const retryAfterMs = retryAfterDate.getTime();
67
+ if (!Number.isNaN(retryAfterMs)) {
68
+ const delay = normalizeDelay(retryAfterMs - Date.now());
69
+ if (delay !== void 0) {
70
+ return delay;
71
+ }
72
+ }
73
+ }
74
+ const rateLimitReset = headers.get("x-ratelimit-reset");
75
+ if (rateLimitReset) {
76
+ const resetSeconds = Number.parseInt(rateLimitReset, 10);
77
+ if (!Number.isNaN(resetSeconds)) {
78
+ const delay = normalizeDelay(resetSeconds * 1e3 - Date.now());
79
+ if (delay !== void 0) {
80
+ return delay;
81
+ }
82
+ }
83
+ }
84
+ const rateLimitResetAfter = headers.get("x-ratelimit-reset-after");
85
+ if (rateLimitResetAfter) {
86
+ const resetAfterSeconds = Number(rateLimitResetAfter);
87
+ if (Number.isFinite(resetAfterSeconds)) {
88
+ const delay = normalizeDelay(resetAfterSeconds * 1e3);
89
+ if (delay !== void 0) {
90
+ return delay;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ const durationMatch = errorText.match(/reset after (?:(\d+)h)?(?:(\d+)m)?(\d+(?:\.\d+)?)s/i);
96
+ if (durationMatch) {
97
+ const hours = durationMatch[1] ? parseInt(durationMatch[1], 10) : 0;
98
+ const minutes = durationMatch[2] ? parseInt(durationMatch[2], 10) : 0;
99
+ const seconds = parseFloat(durationMatch[3]);
100
+ if (!Number.isNaN(seconds)) {
101
+ const totalMs = ((hours * 60 + minutes) * 60 + seconds) * 1e3;
102
+ const delay = normalizeDelay(totalMs);
103
+ if (delay !== void 0) {
104
+ return delay;
105
+ }
106
+ }
107
+ }
108
+ const retryInMatch = errorText.match(/Please retry in ([0-9.]+)(ms|s)/i);
109
+ if (retryInMatch?.[1]) {
110
+ const value = parseFloat(retryInMatch[1]);
111
+ if (!Number.isNaN(value) && value > 0) {
112
+ const ms = retryInMatch[2].toLowerCase() === "ms" ? value : value * 1e3;
113
+ const delay = normalizeDelay(ms);
114
+ if (delay !== void 0) {
115
+ return delay;
116
+ }
117
+ }
118
+ }
119
+ const retryDelayMatch = errorText.match(/"retryDelay":\s*"([0-9.]+)(ms|s)"/i);
120
+ if (retryDelayMatch?.[1]) {
121
+ const value = parseFloat(retryDelayMatch[1]);
122
+ if (!Number.isNaN(value) && value > 0) {
123
+ const ms = retryDelayMatch[2].toLowerCase() === "ms" ? value : value * 1e3;
124
+ const delay = normalizeDelay(ms);
125
+ if (delay !== void 0) {
126
+ return delay;
127
+ }
128
+ }
129
+ }
130
+ return void 0;
131
+ }
132
+ function needsClaudeThinkingBetaHeader(model) {
133
+ return model.provider === "google-antigravity" && model.id.startsWith("claude-") && model.reasoning;
134
+ }
135
+ function isGemini3ProModel(modelId) {
136
+ return /gemini-3(?:\.1)?-pro/.test(modelId.toLowerCase());
137
+ }
138
+ function isGemini3FlashModel(modelId) {
139
+ return /gemini-3(?:\.1)?-flash/.test(modelId.toLowerCase());
140
+ }
141
+ function isGemini3Model(modelId) {
142
+ return isGemini3ProModel(modelId) || isGemini3FlashModel(modelId);
143
+ }
144
+ function isRetryableError(status, errorText) {
145
+ if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504) {
146
+ return true;
147
+ }
148
+ return /resource.?exhausted|rate.?limit|overloaded|service.?unavailable|other.?side.?closed/i.test(errorText);
149
+ }
150
+ function extractErrorMessage(errorText) {
151
+ try {
152
+ const parsed = JSON.parse(errorText);
153
+ if (parsed.error?.message) {
154
+ return parsed.error.message;
155
+ }
156
+ } catch {
157
+ }
158
+ return errorText;
159
+ }
160
+ function sleep(ms, signal) {
161
+ return new Promise((resolve, reject) => {
162
+ if (signal?.aborted) {
163
+ reject(new Error("Request was aborted"));
164
+ return;
165
+ }
166
+ const timeout = setTimeout(resolve, ms);
167
+ signal?.addEventListener("abort", () => {
168
+ clearTimeout(timeout);
169
+ reject(new Error("Request was aborted"));
170
+ });
171
+ });
172
+ }
173
+ var streamGoogleGeminiCli = (model, context, options) => {
174
+ const stream = new AssistantMessageEventStream();
175
+ (async () => {
176
+ const output = {
177
+ role: "assistant",
178
+ content: [],
179
+ api: "google-gemini-cli",
180
+ provider: model.provider,
181
+ model: model.id,
182
+ usage: {
183
+ input: 0,
184
+ output: 0,
185
+ cacheRead: 0,
186
+ cacheWrite: 0,
187
+ totalTokens: 0,
188
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
189
+ },
190
+ stopReason: "stop",
191
+ timestamp: Date.now()
192
+ };
193
+ try {
194
+ const apiKeyRaw = options?.apiKey;
195
+ if (!apiKeyRaw) {
196
+ throw new Error("Google Cloud Code Assist requires OAuth authentication. Use /login to authenticate.");
197
+ }
198
+ let accessToken;
199
+ let projectId;
200
+ try {
201
+ const parsed = JSON.parse(apiKeyRaw);
202
+ accessToken = parsed.token;
203
+ projectId = parsed.projectId;
204
+ } catch {
205
+ throw new Error("Invalid Google Cloud Code Assist credentials. Use /login to re-authenticate.");
206
+ }
207
+ if (!accessToken || !projectId) {
208
+ throw new Error("Missing token or projectId in Google Cloud credentials. Use /login to re-authenticate.");
209
+ }
210
+ const isAntigravity = model.provider === "google-antigravity";
211
+ const baseUrl = model.baseUrl?.trim();
212
+ const endpoints = baseUrl ? [baseUrl] : isAntigravity ? ANTIGRAVITY_ENDPOINT_FALLBACKS : [DEFAULT_ENDPOINT];
213
+ let requestBody = buildRequest(model, context, projectId, options, isAntigravity);
214
+ const nextRequestBody = await options?.onPayload?.(requestBody, model);
215
+ if (nextRequestBody !== void 0) {
216
+ requestBody = nextRequestBody;
217
+ }
218
+ const headers = isAntigravity ? getAntigravityHeaders() : GEMINI_CLI_HEADERS;
219
+ const requestHeaders = {
220
+ Authorization: `Bearer ${accessToken}`,
221
+ "Content-Type": "application/json",
222
+ Accept: "text/event-stream",
223
+ ...headers,
224
+ ...needsClaudeThinkingBetaHeader(model) ? { "anthropic-beta": CLAUDE_THINKING_BETA_HEADER } : {},
225
+ ...options?.headers
226
+ };
227
+ const requestBodyJson = JSON.stringify(requestBody);
228
+ let response;
229
+ let lastError;
230
+ let requestUrl;
231
+ let endpointIndex = 0;
232
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
233
+ if (options?.signal?.aborted) {
234
+ throw new Error("Request was aborted");
235
+ }
236
+ try {
237
+ const endpoint = endpoints[endpointIndex];
238
+ requestUrl = `${endpoint}/v1internal:streamGenerateContent?alt=sse`;
239
+ response = await fetch(requestUrl, {
240
+ method: "POST",
241
+ headers: requestHeaders,
242
+ body: requestBodyJson,
243
+ signal: options?.signal
244
+ });
245
+ if (response.ok) {
246
+ break;
247
+ }
248
+ const errorText = await response.text();
249
+ if ((response.status === 403 || response.status === 404) && endpointIndex < endpoints.length - 1) {
250
+ endpointIndex++;
251
+ continue;
252
+ }
253
+ if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) {
254
+ if (endpointIndex < endpoints.length - 1) {
255
+ endpointIndex++;
256
+ }
257
+ const serverDelay = extractRetryDelay(errorText, response);
258
+ const delayMs = serverDelay ?? BASE_DELAY_MS * 2 ** attempt;
259
+ const maxDelayMs = options?.maxRetryDelayMs ?? 6e4;
260
+ if (maxDelayMs > 0 && serverDelay && serverDelay > maxDelayMs) {
261
+ const delaySeconds = Math.ceil(serverDelay / 1e3);
262
+ throw new Error(`Server requested ${delaySeconds}s retry delay (max: ${Math.ceil(maxDelayMs / 1e3)}s). ${extractErrorMessage(errorText)}`);
263
+ }
264
+ await sleep(delayMs, options?.signal);
265
+ continue;
266
+ }
267
+ throw new Error(`Cloud Code Assist API error (${response.status}): ${extractErrorMessage(errorText)}`);
268
+ } catch (error) {
269
+ if (error instanceof Error) {
270
+ if (error.name === "AbortError" || error.message === "Request was aborted") {
271
+ throw new Error("Request was aborted");
272
+ }
273
+ }
274
+ lastError = error instanceof Error ? error : new Error(String(error));
275
+ if (lastError.message === "fetch failed" && lastError.cause instanceof Error) {
276
+ lastError = new Error(`Network error: ${lastError.cause.message}`);
277
+ }
278
+ if (attempt < MAX_RETRIES) {
279
+ const delayMs = BASE_DELAY_MS * 2 ** attempt;
280
+ await sleep(delayMs, options?.signal);
281
+ continue;
282
+ }
283
+ throw lastError;
284
+ }
285
+ }
286
+ if (!response || !response.ok) {
287
+ throw lastError ?? new Error("Failed to get response after retries");
288
+ }
289
+ let started = false;
290
+ const ensureStarted = () => {
291
+ if (!started) {
292
+ stream.push({ type: "start", partial: output });
293
+ started = true;
294
+ }
295
+ };
296
+ const resetOutput = () => {
297
+ output.content = [];
298
+ output.usage = {
299
+ input: 0,
300
+ output: 0,
301
+ cacheRead: 0,
302
+ cacheWrite: 0,
303
+ totalTokens: 0,
304
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
305
+ };
306
+ output.stopReason = "stop";
307
+ output.errorMessage = void 0;
308
+ output.timestamp = Date.now();
309
+ started = false;
310
+ };
311
+ const streamResponse = async (activeResponse) => {
312
+ if (!activeResponse.body) {
313
+ throw new Error("No response body");
314
+ }
315
+ let hasContent = false;
316
+ let currentBlock = null;
317
+ const blocks = output.content;
318
+ const blockIndex = () => blocks.length - 1;
319
+ const reader = activeResponse.body.getReader();
320
+ const decoder = new TextDecoder();
321
+ let buffer = "";
322
+ const abortHandler = () => {
323
+ void reader.cancel().catch(() => {
324
+ });
325
+ };
326
+ options?.signal?.addEventListener("abort", abortHandler);
327
+ try {
328
+ while (true) {
329
+ if (options?.signal?.aborted) {
330
+ throw new Error("Request was aborted");
331
+ }
332
+ const { done, value } = await reader.read();
333
+ if (done)
334
+ break;
335
+ buffer += decoder.decode(value, { stream: true });
336
+ const lines = buffer.split("\n");
337
+ buffer = lines.pop() || "";
338
+ for (const line of lines) {
339
+ if (!line.startsWith("data:"))
340
+ continue;
341
+ const jsonStr = line.slice(5).trim();
342
+ if (!jsonStr)
343
+ continue;
344
+ let chunk;
345
+ try {
346
+ chunk = JSON.parse(jsonStr);
347
+ } catch {
348
+ continue;
349
+ }
350
+ const responseData = chunk.response;
351
+ if (!responseData)
352
+ continue;
353
+ output.responseId ||= responseData.responseId;
354
+ const candidate = responseData.candidates?.[0];
355
+ if (candidate?.content?.parts) {
356
+ for (const part of candidate.content.parts) {
357
+ if (part.text !== void 0) {
358
+ hasContent = true;
359
+ const isThinking = isThinkingPart(part);
360
+ if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
361
+ if (currentBlock) {
362
+ if (currentBlock.type === "text") {
363
+ stream.push({
364
+ type: "text_end",
365
+ contentIndex: blocks.length - 1,
366
+ content: currentBlock.text,
367
+ partial: output
368
+ });
369
+ } else {
370
+ stream.push({
371
+ type: "thinking_end",
372
+ contentIndex: blockIndex(),
373
+ content: currentBlock.thinking,
374
+ partial: output
375
+ });
376
+ }
377
+ }
378
+ if (isThinking) {
379
+ currentBlock = { type: "thinking", thinking: "", thinkingSignature: void 0 };
380
+ output.content.push(currentBlock);
381
+ ensureStarted();
382
+ stream.push({
383
+ type: "thinking_start",
384
+ contentIndex: blockIndex(),
385
+ partial: output
386
+ });
387
+ } else {
388
+ currentBlock = { type: "text", text: "" };
389
+ output.content.push(currentBlock);
390
+ ensureStarted();
391
+ stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
392
+ }
393
+ }
394
+ if (currentBlock.type === "thinking") {
395
+ currentBlock.thinking += part.text;
396
+ currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
397
+ stream.push({
398
+ type: "thinking_delta",
399
+ contentIndex: blockIndex(),
400
+ delta: part.text,
401
+ partial: output
402
+ });
403
+ } else {
404
+ currentBlock.text += part.text;
405
+ currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
406
+ stream.push({
407
+ type: "text_delta",
408
+ contentIndex: blockIndex(),
409
+ delta: part.text,
410
+ partial: output
411
+ });
412
+ }
413
+ }
414
+ if (part.functionCall) {
415
+ hasContent = true;
416
+ if (currentBlock) {
417
+ if (currentBlock.type === "text") {
418
+ stream.push({
419
+ type: "text_end",
420
+ contentIndex: blockIndex(),
421
+ content: currentBlock.text,
422
+ partial: output
423
+ });
424
+ } else {
425
+ stream.push({
426
+ type: "thinking_end",
427
+ contentIndex: blockIndex(),
428
+ content: currentBlock.thinking,
429
+ partial: output
430
+ });
431
+ }
432
+ currentBlock = null;
433
+ }
434
+ const providedId = part.functionCall.id;
435
+ const needsNewId = !providedId || output.content.some((b) => b.type === "toolCall" && b.id === providedId);
436
+ const toolCallId = needsNewId ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}` : providedId;
437
+ const toolCall = {
438
+ type: "toolCall",
439
+ id: toolCallId,
440
+ name: part.functionCall.name || "",
441
+ arguments: part.functionCall.args ?? {},
442
+ ...part.thoughtSignature && { thoughtSignature: part.thoughtSignature }
443
+ };
444
+ output.content.push(toolCall);
445
+ ensureStarted();
446
+ stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
447
+ stream.push({
448
+ type: "toolcall_delta",
449
+ contentIndex: blockIndex(),
450
+ delta: JSON.stringify(toolCall.arguments),
451
+ partial: output
452
+ });
453
+ stream.push({
454
+ type: "toolcall_end",
455
+ contentIndex: blockIndex(),
456
+ toolCall,
457
+ partial: output
458
+ });
459
+ }
460
+ }
461
+ }
462
+ if (candidate?.finishReason) {
463
+ output.stopReason = mapStopReasonString(candidate.finishReason);
464
+ if (output.content.some((b) => b.type === "toolCall")) {
465
+ output.stopReason = "toolUse";
466
+ }
467
+ }
468
+ if (responseData.usageMetadata) {
469
+ const promptTokens = responseData.usageMetadata.promptTokenCount || 0;
470
+ const cacheReadTokens = responseData.usageMetadata.cachedContentTokenCount || 0;
471
+ output.usage = {
472
+ input: promptTokens - cacheReadTokens,
473
+ output: (responseData.usageMetadata.candidatesTokenCount || 0) + (responseData.usageMetadata.thoughtsTokenCount || 0),
474
+ cacheRead: cacheReadTokens,
475
+ cacheWrite: 0,
476
+ totalTokens: responseData.usageMetadata.totalTokenCount || 0,
477
+ cost: {
478
+ input: 0,
479
+ output: 0,
480
+ cacheRead: 0,
481
+ cacheWrite: 0,
482
+ total: 0
483
+ }
484
+ };
485
+ calculateCost(model, output.usage);
486
+ }
487
+ }
488
+ }
489
+ } finally {
490
+ options?.signal?.removeEventListener("abort", abortHandler);
491
+ }
492
+ if (currentBlock) {
493
+ if (currentBlock.type === "text") {
494
+ stream.push({
495
+ type: "text_end",
496
+ contentIndex: blockIndex(),
497
+ content: currentBlock.text,
498
+ partial: output
499
+ });
500
+ } else {
501
+ stream.push({
502
+ type: "thinking_end",
503
+ contentIndex: blockIndex(),
504
+ content: currentBlock.thinking,
505
+ partial: output
506
+ });
507
+ }
508
+ }
509
+ return hasContent;
510
+ };
511
+ let receivedContent = false;
512
+ let currentResponse = response;
513
+ for (let emptyAttempt = 0; emptyAttempt <= MAX_EMPTY_STREAM_RETRIES; emptyAttempt++) {
514
+ if (options?.signal?.aborted) {
515
+ throw new Error("Request was aborted");
516
+ }
517
+ if (emptyAttempt > 0) {
518
+ const backoffMs = EMPTY_STREAM_BASE_DELAY_MS * 2 ** (emptyAttempt - 1);
519
+ await sleep(backoffMs, options?.signal);
520
+ if (!requestUrl) {
521
+ throw new Error("Missing request URL");
522
+ }
523
+ currentResponse = await fetch(requestUrl, {
524
+ method: "POST",
525
+ headers: requestHeaders,
526
+ body: requestBodyJson,
527
+ signal: options?.signal
528
+ });
529
+ if (!currentResponse.ok) {
530
+ const retryErrorText = await currentResponse.text();
531
+ throw new Error(`Cloud Code Assist API error (${currentResponse.status}): ${retryErrorText}`);
532
+ }
533
+ }
534
+ const streamed = await streamResponse(currentResponse);
535
+ if (streamed) {
536
+ receivedContent = true;
537
+ break;
538
+ }
539
+ if (emptyAttempt < MAX_EMPTY_STREAM_RETRIES) {
540
+ resetOutput();
541
+ }
542
+ }
543
+ if (!receivedContent) {
544
+ throw new Error("Cloud Code Assist API returned an empty response");
545
+ }
546
+ if (options?.signal?.aborted) {
547
+ throw new Error("Request was aborted");
548
+ }
549
+ if (output.stopReason === "aborted" || output.stopReason === "error") {
550
+ throw new Error("An unknown error occurred");
551
+ }
552
+ stream.push({ type: "done", reason: output.stopReason, message: output });
553
+ stream.end();
554
+ } catch (error) {
555
+ for (const block of output.content) {
556
+ if ("index" in block) {
557
+ delete block.index;
558
+ }
559
+ }
560
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
561
+ output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
562
+ stream.push({ type: "error", reason: output.stopReason, error: output });
563
+ stream.end();
564
+ }
565
+ })();
566
+ return stream;
567
+ };
568
+ var streamSimpleGoogleGeminiCli = (model, context, options) => {
569
+ const apiKey = options?.apiKey;
570
+ if (!apiKey) {
571
+ throw new Error("Google Cloud Code Assist requires OAuth authentication. Use /login to authenticate.");
572
+ }
573
+ const base = buildBaseOptions(model, options, apiKey);
574
+ if (!options?.reasoning) {
575
+ return streamGoogleGeminiCli(model, context, {
576
+ ...base,
577
+ thinking: { enabled: false }
578
+ });
579
+ }
580
+ const effort = clampReasoning(options.reasoning);
581
+ if (isGemini3Model(model.id)) {
582
+ return streamGoogleGeminiCli(model, context, {
583
+ ...base,
584
+ thinking: {
585
+ enabled: true,
586
+ level: getGeminiCliThinkingLevel(effort, model.id)
587
+ }
588
+ });
589
+ }
590
+ const defaultBudgets = {
591
+ minimal: 1024,
592
+ low: 2048,
593
+ medium: 8192,
594
+ high: 16384
595
+ };
596
+ const budgets = { ...defaultBudgets, ...options.thinkingBudgets };
597
+ const minOutputTokens = 1024;
598
+ let thinkingBudget = budgets[effort];
599
+ const maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);
600
+ if (maxTokens <= thinkingBudget) {
601
+ thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
602
+ }
603
+ return streamGoogleGeminiCli(model, context, {
604
+ ...base,
605
+ maxTokens,
606
+ thinking: {
607
+ enabled: true,
608
+ budgetTokens: thinkingBudget
609
+ }
610
+ });
611
+ };
612
+ function buildRequest(model, context, projectId, options = {}, isAntigravity = false) {
613
+ const contents = convertMessages(model, context);
614
+ const generationConfig = {};
615
+ if (options.temperature !== void 0) {
616
+ generationConfig.temperature = options.temperature;
617
+ }
618
+ if (options.maxTokens !== void 0) {
619
+ generationConfig.maxOutputTokens = options.maxTokens;
620
+ }
621
+ if (options.thinking?.enabled && model.reasoning) {
622
+ generationConfig.thinkingConfig = {
623
+ includeThoughts: true
624
+ };
625
+ if (options.thinking.level !== void 0) {
626
+ generationConfig.thinkingConfig.thinkingLevel = options.thinking.level;
627
+ } else if (options.thinking.budgetTokens !== void 0) {
628
+ generationConfig.thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
629
+ }
630
+ } else if (model.reasoning && options.thinking && !options.thinking.enabled) {
631
+ generationConfig.thinkingConfig = getDisabledThinkingConfig(model.id);
632
+ }
633
+ const request = {
634
+ contents
635
+ };
636
+ request.sessionId = options.sessionId;
637
+ if (context.systemPrompt) {
638
+ request.systemInstruction = {
639
+ parts: [{ text: sanitizeSurrogates(context.systemPrompt) }]
640
+ };
641
+ }
642
+ if (Object.keys(generationConfig).length > 0) {
643
+ request.generationConfig = generationConfig;
644
+ }
645
+ if (context.tools && context.tools.length > 0) {
646
+ const useParameters = model.id.startsWith("claude-");
647
+ request.tools = convertTools(context.tools, useParameters);
648
+ if (options.toolChoice) {
649
+ request.toolConfig = {
650
+ functionCallingConfig: {
651
+ mode: mapToolChoice(options.toolChoice)
652
+ }
653
+ };
654
+ }
655
+ }
656
+ if (isAntigravity) {
657
+ const existingParts = request.systemInstruction?.parts ?? [];
658
+ request.systemInstruction = {
659
+ role: "user",
660
+ parts: [
661
+ { text: ANTIGRAVITY_SYSTEM_INSTRUCTION },
662
+ { text: `Please ignore following [ignore]${ANTIGRAVITY_SYSTEM_INSTRUCTION}[/ignore]` },
663
+ ...existingParts
664
+ ]
665
+ };
666
+ }
667
+ return {
668
+ project: projectId,
669
+ model: model.id,
670
+ request,
671
+ ...isAntigravity ? { requestType: "agent" } : {},
672
+ userAgent: isAntigravity ? "antigravity" : "pi-coding-agent",
673
+ requestId: `${isAntigravity ? "agent" : "pi"}-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`
674
+ };
675
+ }
676
+ function getDisabledThinkingConfig(modelId) {
677
+ if (isGemini3ProModel(modelId)) {
678
+ return { thinkingLevel: "LOW" };
679
+ }
680
+ if (isGemini3FlashModel(modelId)) {
681
+ return { thinkingLevel: "MINIMAL" };
682
+ }
683
+ return { thinkingBudget: 0 };
684
+ }
685
+ function getGeminiCliThinkingLevel(effort, modelId) {
686
+ if (isGemini3ProModel(modelId)) {
687
+ switch (effort) {
688
+ case "minimal":
689
+ case "low":
690
+ return "LOW";
691
+ case "medium":
692
+ case "high":
693
+ return "HIGH";
694
+ }
695
+ }
696
+ switch (effort) {
697
+ case "minimal":
698
+ return "MINIMAL";
699
+ case "low":
700
+ return "LOW";
701
+ case "medium":
702
+ return "MEDIUM";
703
+ case "high":
704
+ return "HIGH";
705
+ }
706
+ }
707
+ export {
708
+ buildRequest,
709
+ extractRetryDelay,
710
+ streamGoogleGeminiCli,
711
+ streamSimpleGoogleGeminiCli
712
+ };