copilot-api-plus 1.0.7 → 1.0.9
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 +140 -75
- package/dist/{auth-KlL1W4gV.js → auth-BO-mwvoU.js} +1 -1
- package/dist/auth-Cm_0h9bp.js +268 -0
- package/dist/auth-Cm_0h9bp.js.map +1 -0
- package/dist/{auth-C5zV8JbW.js → auth-Cua-c0dq.js} +1 -1
- package/dist/auth-Cua-c0dq.js.map +1 -0
- package/dist/auth-D2wtETTq.js +4 -0
- package/dist/get-models-Bbb8B5jI.js +218 -0
- package/dist/get-models-Bbb8B5jI.js.map +1 -0
- package/dist/{get-models-Hlxa1hWY.js → get-models-DJfPj_Rg.js} +2 -2
- package/dist/get-models-DJfPj_Rg.js.map +1 -0
- package/dist/get-models-Dq2ZDU9m.js +5 -0
- package/dist/{get-user-DgPgvnrS.js → get-user-BFf5xJXg.js} +2 -2
- package/dist/{get-user-DgPgvnrS.js.map → get-user-BFf5xJXg.js.map} +1 -1
- package/dist/get-user-hpkh0FzZ.js +5 -0
- package/dist/main.js +783 -32
- package/dist/main.js.map +1 -1
- package/dist/{state-DAw5jMjc.js → state-CcLGr8VN.js} +3 -2
- package/dist/state-CcLGr8VN.js.map +1 -0
- package/dist/{token-DYeOMeid.js → token-B8crDDoA.js} +14 -12
- package/dist/token-B8crDDoA.js.map +1 -0
- package/dist/{token-BssxOyqn.js → token-DS09XjQ5.js} +3 -3
- package/package.json +3 -2
- package/dist/auth-C5zV8JbW.js.map +0 -1
- package/dist/get-models-Hlxa1hWY.js.map +0 -1
- package/dist/get-user-M3sQS0U8.js +0 -5
- package/dist/state-DAw5jMjc.js.map +0 -1
- package/dist/token-DYeOMeid.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { PATHS, ensurePaths } from "./paths-Ch0ixSo2.js";
|
|
3
|
-
import { state } from "./state-
|
|
4
|
-
import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders, githubHeaders } from "./get-user-
|
|
3
|
+
import { state } from "./state-CcLGr8VN.js";
|
|
4
|
+
import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders, githubHeaders } from "./get-user-BFf5xJXg.js";
|
|
5
5
|
import { HTTPError, forwardError } from "./error-CvU5otz-.js";
|
|
6
|
-
import { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep } from "./token-
|
|
7
|
-
import {
|
|
6
|
+
import { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep } from "./token-B8crDDoA.js";
|
|
7
|
+
import { clearAntigravityAuth, disableCurrentAccount, getAntigravityAuthPath, getValidAccessToken, rotateAccount } from "./auth-Cm_0h9bp.js";
|
|
8
|
+
import { clearZenAuth, getZenAuthPath } from "./auth-Cua-c0dq.js";
|
|
9
|
+
import { getAntigravityModels, isThinkingModel } from "./get-models-Bbb8B5jI.js";
|
|
8
10
|
import { defineCommand, runMain } from "citty";
|
|
9
11
|
import consola from "consola";
|
|
10
12
|
import fs from "node:fs/promises";
|
|
@@ -185,9 +187,11 @@ async function runLogout(options) {
|
|
|
185
187
|
if (options.all) {
|
|
186
188
|
await clearGithubToken();
|
|
187
189
|
await clearZenAuth();
|
|
190
|
+
await clearAntigravityAuth();
|
|
188
191
|
consola.success("Logged out from all services");
|
|
189
192
|
consola.info(`GitHub token: ${PATHS.GITHUB_TOKEN_PATH}`);
|
|
190
193
|
consola.info(`Zen API key: ${getZenAuthPath()}`);
|
|
194
|
+
consola.info(`Antigravity accounts: ${getAntigravityAuthPath()}`);
|
|
191
195
|
return;
|
|
192
196
|
}
|
|
193
197
|
if (options.zen) {
|
|
@@ -196,26 +200,42 @@ async function runLogout(options) {
|
|
|
196
200
|
consola.info(`Zen API key location: ${getZenAuthPath()}`);
|
|
197
201
|
return;
|
|
198
202
|
}
|
|
199
|
-
|
|
203
|
+
if (options.antigravity) {
|
|
204
|
+
await clearAntigravityAuth();
|
|
205
|
+
consola.success("Logged out from Google Antigravity");
|
|
206
|
+
consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
switch (await consola.prompt("Which credentials do you want to clear?", {
|
|
200
210
|
type: "select",
|
|
201
211
|
options: [
|
|
202
212
|
"GitHub Copilot token",
|
|
203
213
|
"OpenCode Zen API key",
|
|
204
|
-
"
|
|
214
|
+
"Google Antigravity accounts",
|
|
215
|
+
"All credentials"
|
|
205
216
|
]
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
})) {
|
|
218
|
+
case "GitHub Copilot token":
|
|
219
|
+
await clearGithubToken();
|
|
220
|
+
consola.success("Logged out from GitHub Copilot");
|
|
221
|
+
consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
|
|
222
|
+
break;
|
|
223
|
+
case "OpenCode Zen API key":
|
|
224
|
+
await clearZenAuth();
|
|
225
|
+
consola.success("Logged out from OpenCode Zen");
|
|
226
|
+
consola.info(`Zen API key location: ${getZenAuthPath()}`);
|
|
227
|
+
break;
|
|
228
|
+
case "Google Antigravity accounts":
|
|
229
|
+
await clearAntigravityAuth();
|
|
230
|
+
consola.success("Logged out from Google Antigravity");
|
|
231
|
+
consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
|
|
232
|
+
break;
|
|
233
|
+
case "All credentials":
|
|
234
|
+
await clearGithubToken();
|
|
235
|
+
await clearZenAuth();
|
|
236
|
+
await clearAntigravityAuth();
|
|
237
|
+
consola.success("Logged out from all services");
|
|
238
|
+
break;
|
|
219
239
|
}
|
|
220
240
|
}
|
|
221
241
|
const logout = defineCommand({
|
|
@@ -230,16 +250,22 @@ const logout = defineCommand({
|
|
|
230
250
|
default: false,
|
|
231
251
|
description: "Clear only OpenCode Zen API key"
|
|
232
252
|
},
|
|
253
|
+
antigravity: {
|
|
254
|
+
type: "boolean",
|
|
255
|
+
default: false,
|
|
256
|
+
description: "Clear only Google Antigravity accounts"
|
|
257
|
+
},
|
|
233
258
|
all: {
|
|
234
259
|
alias: "a",
|
|
235
260
|
type: "boolean",
|
|
236
261
|
default: false,
|
|
237
|
-
description: "Clear all credentials (GitHub and
|
|
262
|
+
description: "Clear all credentials (GitHub, Zen, and Antigravity)"
|
|
238
263
|
}
|
|
239
264
|
},
|
|
240
265
|
run({ args }) {
|
|
241
266
|
return runLogout({
|
|
242
267
|
zen: args.zen,
|
|
268
|
+
antigravity: args.antigravity,
|
|
243
269
|
all: args.all
|
|
244
270
|
});
|
|
245
271
|
}
|
|
@@ -376,6 +402,700 @@ const apiKeyAuthMiddleware = async (c, next) => {
|
|
|
376
402
|
await next();
|
|
377
403
|
};
|
|
378
404
|
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/services/antigravity/create-chat-completions.ts
|
|
407
|
+
const ANTIGRAVITY_API_HOST$1 = "daily-cloudcode-pa.sandbox.googleapis.com";
|
|
408
|
+
const ANTIGRAVITY_STREAM_URL$1 = `https://${ANTIGRAVITY_API_HOST$1}/v1internal:streamGenerateContent?alt=sse`;
|
|
409
|
+
const ANTIGRAVITY_NO_STREAM_URL$1 = `https://${ANTIGRAVITY_API_HOST$1}/v1internal:generateContent`;
|
|
410
|
+
const ANTIGRAVITY_USER_AGENT$1 = "antigravity/1.11.3 windows/amd64";
|
|
411
|
+
/**
|
|
412
|
+
* Convert OpenAI format messages to Antigravity format
|
|
413
|
+
*/
|
|
414
|
+
function convertMessages$1(messages) {
|
|
415
|
+
const contents = [];
|
|
416
|
+
let systemInstruction = void 0;
|
|
417
|
+
for (const message of messages) {
|
|
418
|
+
if (message.role === "system") {
|
|
419
|
+
systemInstruction = {
|
|
420
|
+
role: "user",
|
|
421
|
+
parts: [{ text: typeof message.content === "string" ? message.content : message.content.map((c) => c.text || "").join("") }]
|
|
422
|
+
};
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
const role = message.role === "assistant" ? "model" : "user";
|
|
426
|
+
if (typeof message.content === "string") contents.push({
|
|
427
|
+
role,
|
|
428
|
+
parts: [{ text: message.content }]
|
|
429
|
+
});
|
|
430
|
+
else {
|
|
431
|
+
const parts = [];
|
|
432
|
+
for (const part of message.content) if (part.type === "text") parts.push({ text: part.text });
|
|
433
|
+
else if (part.type === "image_url" && part.image_url?.url) {
|
|
434
|
+
const url = part.image_url.url;
|
|
435
|
+
if (url.startsWith("data:")) {
|
|
436
|
+
const match = url.match(/^data:([^;]+);base64,(.+)$/);
|
|
437
|
+
if (match) parts.push({ inlineData: {
|
|
438
|
+
mimeType: match[1],
|
|
439
|
+
data: match[2]
|
|
440
|
+
} });
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
contents.push({
|
|
444
|
+
role,
|
|
445
|
+
parts
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
contents,
|
|
451
|
+
systemInstruction
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Convert tools to Antigravity format
|
|
456
|
+
*/
|
|
457
|
+
function convertTools$1(tools) {
|
|
458
|
+
if (!tools || tools.length === 0) return;
|
|
459
|
+
return tools.map((tool) => {
|
|
460
|
+
const t = tool;
|
|
461
|
+
if (t.type === "function" && t.function) return { functionDeclarations: [{
|
|
462
|
+
name: t.function.name,
|
|
463
|
+
description: t.function.description || "",
|
|
464
|
+
parameters: t.function.parameters || {}
|
|
465
|
+
}] };
|
|
466
|
+
return tool;
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Create chat completion with Antigravity
|
|
471
|
+
*/
|
|
472
|
+
async function createAntigravityChatCompletion(request) {
|
|
473
|
+
const accessToken = await getValidAccessToken();
|
|
474
|
+
if (!accessToken) return new Response(JSON.stringify({ error: {
|
|
475
|
+
message: "No valid Antigravity access token available. Please run login first.",
|
|
476
|
+
type: "auth_error"
|
|
477
|
+
} }), {
|
|
478
|
+
status: 401,
|
|
479
|
+
headers: { "Content-Type": "application/json" }
|
|
480
|
+
});
|
|
481
|
+
const { contents, systemInstruction } = convertMessages$1(request.messages);
|
|
482
|
+
const tools = convertTools$1(request.tools);
|
|
483
|
+
const antigravityRequest = {
|
|
484
|
+
model: request.model,
|
|
485
|
+
contents,
|
|
486
|
+
generationConfig: {
|
|
487
|
+
temperature: request.temperature ?? 1,
|
|
488
|
+
topP: request.top_p ?? .85,
|
|
489
|
+
topK: request.top_k ?? 50,
|
|
490
|
+
maxOutputTokens: request.max_tokens ?? 8096
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
if (systemInstruction) antigravityRequest.systemInstruction = systemInstruction;
|
|
494
|
+
if (tools) antigravityRequest.tools = tools;
|
|
495
|
+
if (isThinkingModel(request.model)) antigravityRequest.generationConfig = {
|
|
496
|
+
...antigravityRequest.generationConfig,
|
|
497
|
+
thinkingConfig: { includeThoughts: true }
|
|
498
|
+
};
|
|
499
|
+
const endpoint = request.stream ? ANTIGRAVITY_STREAM_URL$1 : ANTIGRAVITY_NO_STREAM_URL$1;
|
|
500
|
+
consola.debug(`Antigravity request to ${endpoint} with model ${request.model}`);
|
|
501
|
+
try {
|
|
502
|
+
const response = await fetch(endpoint, {
|
|
503
|
+
method: "POST",
|
|
504
|
+
headers: {
|
|
505
|
+
Host: ANTIGRAVITY_API_HOST$1,
|
|
506
|
+
"User-Agent": ANTIGRAVITY_USER_AGENT$1,
|
|
507
|
+
Authorization: `Bearer ${accessToken}`,
|
|
508
|
+
"Content-Type": "application/json",
|
|
509
|
+
"Accept-Encoding": "gzip"
|
|
510
|
+
},
|
|
511
|
+
body: JSON.stringify(antigravityRequest)
|
|
512
|
+
});
|
|
513
|
+
if (!response.ok) {
|
|
514
|
+
const errorText = await response.text();
|
|
515
|
+
consola.error(`Antigravity error: ${response.status} ${errorText}`);
|
|
516
|
+
if (response.status === 403) await disableCurrentAccount();
|
|
517
|
+
if (response.status === 429 || response.status === 503) await rotateAccount();
|
|
518
|
+
return new Response(JSON.stringify({ error: {
|
|
519
|
+
message: `Antigravity API error: ${response.status}`,
|
|
520
|
+
type: "api_error",
|
|
521
|
+
details: errorText
|
|
522
|
+
} }), {
|
|
523
|
+
status: response.status,
|
|
524
|
+
headers: { "Content-Type": "application/json" }
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
if (request.stream) return transformStreamResponse(response, request.model);
|
|
528
|
+
else return transformNonStreamResponse(response, request.model);
|
|
529
|
+
} catch (error) {
|
|
530
|
+
consola.error("Antigravity request error:", error);
|
|
531
|
+
return new Response(JSON.stringify({ error: {
|
|
532
|
+
message: `Request failed: ${error}`,
|
|
533
|
+
type: "request_error"
|
|
534
|
+
} }), {
|
|
535
|
+
status: 500,
|
|
536
|
+
headers: { "Content-Type": "application/json" }
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Transform Antigravity stream response to OpenAI format
|
|
542
|
+
*/
|
|
543
|
+
function transformStreamResponse(response, model) {
|
|
544
|
+
const reader = response.body?.getReader();
|
|
545
|
+
if (!reader) return new Response("No response body", { status: 500 });
|
|
546
|
+
const encoder = new TextEncoder();
|
|
547
|
+
const decoder = new TextDecoder();
|
|
548
|
+
const stream = new ReadableStream({ async start(controller) {
|
|
549
|
+
let buffer = "";
|
|
550
|
+
const requestId = `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
551
|
+
try {
|
|
552
|
+
while (true) {
|
|
553
|
+
const { done, value } = await reader.read();
|
|
554
|
+
if (done) {
|
|
555
|
+
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
|
|
556
|
+
controller.close();
|
|
557
|
+
break;
|
|
558
|
+
}
|
|
559
|
+
buffer += decoder.decode(value, { stream: true });
|
|
560
|
+
const lines = buffer.split("\n");
|
|
561
|
+
buffer = lines.pop() || "";
|
|
562
|
+
for (const line of lines) if (line.startsWith("data: ")) {
|
|
563
|
+
const data = line.slice(6).trim();
|
|
564
|
+
if (data === "[DONE]" || data === "") continue;
|
|
565
|
+
try {
|
|
566
|
+
const parsed = JSON.parse(data);
|
|
567
|
+
const candidate = (parsed.response?.candidates || parsed.candidates)?.[0];
|
|
568
|
+
const parts = candidate?.content?.parts || [];
|
|
569
|
+
for (const part of parts) {
|
|
570
|
+
if (part.thought && part.text) {
|
|
571
|
+
const chunk = {
|
|
572
|
+
id: requestId,
|
|
573
|
+
object: "chat.completion.chunk",
|
|
574
|
+
created: Math.floor(Date.now() / 1e3),
|
|
575
|
+
model,
|
|
576
|
+
choices: [{
|
|
577
|
+
index: 0,
|
|
578
|
+
delta: { reasoning_content: part.text },
|
|
579
|
+
finish_reason: null
|
|
580
|
+
}]
|
|
581
|
+
};
|
|
582
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
if (part.text) {
|
|
586
|
+
const chunk = {
|
|
587
|
+
id: requestId,
|
|
588
|
+
object: "chat.completion.chunk",
|
|
589
|
+
created: Math.floor(Date.now() / 1e3),
|
|
590
|
+
model,
|
|
591
|
+
choices: [{
|
|
592
|
+
index: 0,
|
|
593
|
+
delta: { content: part.text },
|
|
594
|
+
finish_reason: candidate?.finishReason === "STOP" ? "stop" : null
|
|
595
|
+
}]
|
|
596
|
+
};
|
|
597
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
|
|
598
|
+
}
|
|
599
|
+
if (part.functionCall) {
|
|
600
|
+
const chunk = {
|
|
601
|
+
id: requestId,
|
|
602
|
+
object: "chat.completion.chunk",
|
|
603
|
+
created: Math.floor(Date.now() / 1e3),
|
|
604
|
+
model,
|
|
605
|
+
choices: [{
|
|
606
|
+
index: 0,
|
|
607
|
+
delta: { tool_calls: [{
|
|
608
|
+
index: 0,
|
|
609
|
+
id: `call_${Date.now()}`,
|
|
610
|
+
type: "function",
|
|
611
|
+
function: {
|
|
612
|
+
name: part.functionCall.name,
|
|
613
|
+
arguments: JSON.stringify(part.functionCall.args)
|
|
614
|
+
}
|
|
615
|
+
}] },
|
|
616
|
+
finish_reason: null
|
|
617
|
+
}]
|
|
618
|
+
};
|
|
619
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
} catch {}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
} catch (error) {
|
|
626
|
+
consola.error("Stream transform error:", error);
|
|
627
|
+
controller.error(error);
|
|
628
|
+
}
|
|
629
|
+
} });
|
|
630
|
+
return new Response(stream, { headers: {
|
|
631
|
+
"Content-Type": "text/event-stream",
|
|
632
|
+
"Cache-Control": "no-cache",
|
|
633
|
+
Connection: "keep-alive"
|
|
634
|
+
} });
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Transform Antigravity non-stream response to OpenAI format
|
|
638
|
+
*/
|
|
639
|
+
async function transformNonStreamResponse(response, model) {
|
|
640
|
+
const data = await response.json();
|
|
641
|
+
const candidate = data.candidates?.[0];
|
|
642
|
+
const parts = candidate?.content?.parts || [];
|
|
643
|
+
let content = "";
|
|
644
|
+
let reasoningContent = "";
|
|
645
|
+
const toolCalls = [];
|
|
646
|
+
for (const part of parts) {
|
|
647
|
+
if (part.thought && part.text) reasoningContent += part.text;
|
|
648
|
+
else if (part.text) content += part.text;
|
|
649
|
+
if (part.functionCall) toolCalls.push({
|
|
650
|
+
id: `call_${Date.now()}`,
|
|
651
|
+
type: "function",
|
|
652
|
+
function: {
|
|
653
|
+
name: part.functionCall.name,
|
|
654
|
+
arguments: JSON.stringify(part.functionCall.args)
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
const message = {
|
|
659
|
+
role: "assistant",
|
|
660
|
+
content: content || null
|
|
661
|
+
};
|
|
662
|
+
if (reasoningContent) message.reasoning_content = reasoningContent;
|
|
663
|
+
if (toolCalls.length > 0) message.tool_calls = toolCalls;
|
|
664
|
+
const openaiResponse = {
|
|
665
|
+
id: `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
666
|
+
object: "chat.completion",
|
|
667
|
+
created: Math.floor(Date.now() / 1e3),
|
|
668
|
+
model,
|
|
669
|
+
choices: [{
|
|
670
|
+
index: 0,
|
|
671
|
+
message,
|
|
672
|
+
finish_reason: candidate?.finishReason === "STOP" ? "stop" : "stop"
|
|
673
|
+
}],
|
|
674
|
+
usage: {
|
|
675
|
+
prompt_tokens: data.usageMetadata?.promptTokenCount || 0,
|
|
676
|
+
completion_tokens: data.usageMetadata?.candidatesTokenCount || 0,
|
|
677
|
+
total_tokens: data.usageMetadata?.totalTokenCount || 0
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
return new Response(JSON.stringify(openaiResponse), { headers: { "Content-Type": "application/json" } });
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
//#endregion
|
|
684
|
+
//#region src/routes/antigravity/chat-completions/route.ts
|
|
685
|
+
const app$1 = new Hono();
|
|
686
|
+
app$1.post("/", async (c) => {
|
|
687
|
+
const body = await c.req.json();
|
|
688
|
+
const response = await createAntigravityChatCompletion(body);
|
|
689
|
+
const headers = new Headers(response.headers);
|
|
690
|
+
if (body.stream) return new Response(response.body, {
|
|
691
|
+
status: response.status,
|
|
692
|
+
headers
|
|
693
|
+
});
|
|
694
|
+
return new Response(await response.text(), {
|
|
695
|
+
status: response.status,
|
|
696
|
+
headers
|
|
697
|
+
});
|
|
698
|
+
});
|
|
699
|
+
const antigravityChatCompletionsRoute = app$1;
|
|
700
|
+
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/services/antigravity/create-messages.ts
|
|
703
|
+
const ANTIGRAVITY_API_HOST = "daily-cloudcode-pa.sandbox.googleapis.com";
|
|
704
|
+
const ANTIGRAVITY_STREAM_URL = `https://${ANTIGRAVITY_API_HOST}/v1internal:streamGenerateContent?alt=sse`;
|
|
705
|
+
const ANTIGRAVITY_NO_STREAM_URL = `https://${ANTIGRAVITY_API_HOST}/v1internal:generateContent`;
|
|
706
|
+
const ANTIGRAVITY_USER_AGENT = "antigravity/1.11.3 windows/amd64";
|
|
707
|
+
/**
|
|
708
|
+
* Convert Anthropic messages to Antigravity format
|
|
709
|
+
*/
|
|
710
|
+
function convertMessages(messages, system) {
|
|
711
|
+
const contents = [];
|
|
712
|
+
let systemInstruction = void 0;
|
|
713
|
+
if (system) systemInstruction = {
|
|
714
|
+
role: "user",
|
|
715
|
+
parts: [{ text: system }]
|
|
716
|
+
};
|
|
717
|
+
for (const message of messages) {
|
|
718
|
+
const role = message.role === "assistant" ? "model" : "user";
|
|
719
|
+
if (typeof message.content === "string") contents.push({
|
|
720
|
+
role,
|
|
721
|
+
parts: [{ text: message.content }]
|
|
722
|
+
});
|
|
723
|
+
else {
|
|
724
|
+
const parts = [];
|
|
725
|
+
for (const block of message.content) if (block.type === "text" && block.text) parts.push({ text: block.text });
|
|
726
|
+
else if (block.type === "image" && block.source) parts.push({ inlineData: {
|
|
727
|
+
mimeType: block.source.media_type,
|
|
728
|
+
data: block.source.data
|
|
729
|
+
} });
|
|
730
|
+
if (parts.length > 0) contents.push({
|
|
731
|
+
role,
|
|
732
|
+
parts
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return {
|
|
737
|
+
contents,
|
|
738
|
+
systemInstruction
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Convert tools to Antigravity format
|
|
743
|
+
*/
|
|
744
|
+
function convertTools(tools) {
|
|
745
|
+
if (!tools || tools.length === 0) return;
|
|
746
|
+
return tools.map((tool) => {
|
|
747
|
+
const t = tool;
|
|
748
|
+
return { functionDeclarations: [{
|
|
749
|
+
name: t.name,
|
|
750
|
+
description: t.description || "",
|
|
751
|
+
parameters: t.input_schema || {}
|
|
752
|
+
}] };
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Create Anthropic-compatible message response using Antigravity
|
|
757
|
+
*/
|
|
758
|
+
async function createAntigravityMessages(request) {
|
|
759
|
+
const accessToken = await getValidAccessToken();
|
|
760
|
+
if (!accessToken) return new Response(JSON.stringify({
|
|
761
|
+
type: "error",
|
|
762
|
+
error: {
|
|
763
|
+
type: "authentication_error",
|
|
764
|
+
message: "No valid Antigravity access token available. Please run login first."
|
|
765
|
+
}
|
|
766
|
+
}), {
|
|
767
|
+
status: 401,
|
|
768
|
+
headers: { "Content-Type": "application/json" }
|
|
769
|
+
});
|
|
770
|
+
const { contents, systemInstruction } = convertMessages(request.messages, request.system);
|
|
771
|
+
const tools = convertTools(request.tools);
|
|
772
|
+
const antigravityRequest = {
|
|
773
|
+
model: request.model,
|
|
774
|
+
contents,
|
|
775
|
+
generationConfig: {
|
|
776
|
+
temperature: request.temperature ?? 1,
|
|
777
|
+
topP: request.top_p ?? .85,
|
|
778
|
+
topK: request.top_k ?? 50,
|
|
779
|
+
maxOutputTokens: request.max_tokens ?? 8096
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
if (systemInstruction) antigravityRequest.systemInstruction = systemInstruction;
|
|
783
|
+
if (tools) antigravityRequest.tools = tools;
|
|
784
|
+
if (isThinkingModel(request.model)) antigravityRequest.generationConfig = {
|
|
785
|
+
...antigravityRequest.generationConfig,
|
|
786
|
+
thinkingConfig: { includeThoughts: true }
|
|
787
|
+
};
|
|
788
|
+
const endpoint = request.stream ? ANTIGRAVITY_STREAM_URL : ANTIGRAVITY_NO_STREAM_URL;
|
|
789
|
+
consola.debug(`Antigravity messages request to ${endpoint} with model ${request.model}`);
|
|
790
|
+
try {
|
|
791
|
+
const response = await fetch(endpoint, {
|
|
792
|
+
method: "POST",
|
|
793
|
+
headers: {
|
|
794
|
+
Host: ANTIGRAVITY_API_HOST,
|
|
795
|
+
"User-Agent": ANTIGRAVITY_USER_AGENT,
|
|
796
|
+
Authorization: `Bearer ${accessToken}`,
|
|
797
|
+
"Content-Type": "application/json",
|
|
798
|
+
"Accept-Encoding": "gzip"
|
|
799
|
+
},
|
|
800
|
+
body: JSON.stringify(antigravityRequest)
|
|
801
|
+
});
|
|
802
|
+
if (!response.ok) {
|
|
803
|
+
const errorText = await response.text();
|
|
804
|
+
consola.error(`Antigravity error: ${response.status} ${errorText}`);
|
|
805
|
+
if (response.status === 403) await disableCurrentAccount();
|
|
806
|
+
if (response.status === 429 || response.status === 503) await rotateAccount();
|
|
807
|
+
return new Response(JSON.stringify({
|
|
808
|
+
type: "error",
|
|
809
|
+
error: {
|
|
810
|
+
type: "api_error",
|
|
811
|
+
message: `Antigravity API error: ${response.status}`
|
|
812
|
+
}
|
|
813
|
+
}), {
|
|
814
|
+
status: response.status,
|
|
815
|
+
headers: { "Content-Type": "application/json" }
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
if (request.stream) return transformStreamToAnthropic(response, request.model);
|
|
819
|
+
else return transformNonStreamToAnthropic(response, request.model);
|
|
820
|
+
} catch (error) {
|
|
821
|
+
consola.error("Antigravity messages request error:", error);
|
|
822
|
+
return new Response(JSON.stringify({
|
|
823
|
+
type: "error",
|
|
824
|
+
error: {
|
|
825
|
+
type: "api_error",
|
|
826
|
+
message: `Request failed: ${error}`
|
|
827
|
+
}
|
|
828
|
+
}), {
|
|
829
|
+
status: 500,
|
|
830
|
+
headers: { "Content-Type": "application/json" }
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Transform Antigravity stream response to Anthropic format
|
|
836
|
+
*/
|
|
837
|
+
function transformStreamToAnthropic(response, model) {
|
|
838
|
+
const reader = response.body?.getReader();
|
|
839
|
+
if (!reader) return new Response("No response body", { status: 500 });
|
|
840
|
+
const encoder = new TextEncoder();
|
|
841
|
+
const decoder = new TextDecoder();
|
|
842
|
+
const stream = new ReadableStream({ async start(controller) {
|
|
843
|
+
let buffer = "";
|
|
844
|
+
const messageId = `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
845
|
+
let inputTokens = 0;
|
|
846
|
+
let outputTokens = 0;
|
|
847
|
+
let contentBlockIndex = 0;
|
|
848
|
+
let thinkingBlockStarted = false;
|
|
849
|
+
let textBlockStarted = false;
|
|
850
|
+
const messageStart = {
|
|
851
|
+
type: "message_start",
|
|
852
|
+
message: {
|
|
853
|
+
id: messageId,
|
|
854
|
+
type: "message",
|
|
855
|
+
role: "assistant",
|
|
856
|
+
content: [],
|
|
857
|
+
model,
|
|
858
|
+
stop_reason: null,
|
|
859
|
+
stop_sequence: null,
|
|
860
|
+
usage: {
|
|
861
|
+
input_tokens: 0,
|
|
862
|
+
output_tokens: 0
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
controller.enqueue(encoder.encode(`event: message_start\ndata: ${JSON.stringify(messageStart)}\n\n`));
|
|
867
|
+
try {
|
|
868
|
+
while (true) {
|
|
869
|
+
const { done, value } = await reader.read();
|
|
870
|
+
if (done) {
|
|
871
|
+
controller.enqueue(encoder.encode(`event: message_stop\ndata: ${JSON.stringify({ type: "message_stop" })}\n\n`));
|
|
872
|
+
controller.close();
|
|
873
|
+
break;
|
|
874
|
+
}
|
|
875
|
+
buffer += decoder.decode(value, { stream: true });
|
|
876
|
+
const lines = buffer.split("\n");
|
|
877
|
+
buffer = lines.pop() || "";
|
|
878
|
+
for (const line of lines) if (line.startsWith("data: ")) {
|
|
879
|
+
const data = line.slice(6).trim();
|
|
880
|
+
if (data === "[DONE]" || data === "") continue;
|
|
881
|
+
try {
|
|
882
|
+
const parsed = JSON.parse(data);
|
|
883
|
+
const candidate = (parsed.response?.candidates || parsed.candidates)?.[0];
|
|
884
|
+
const parts = candidate?.content?.parts || [];
|
|
885
|
+
const usage = parsed.response?.usageMetadata || parsed.usageMetadata;
|
|
886
|
+
if (usage) {
|
|
887
|
+
inputTokens = usage.promptTokenCount || inputTokens;
|
|
888
|
+
outputTokens = usage.candidatesTokenCount || outputTokens;
|
|
889
|
+
}
|
|
890
|
+
for (const part of parts) {
|
|
891
|
+
if (part.thought && part.text) {
|
|
892
|
+
if (!thinkingBlockStarted) {
|
|
893
|
+
const blockStart = {
|
|
894
|
+
type: "content_block_start",
|
|
895
|
+
index: contentBlockIndex,
|
|
896
|
+
content_block: {
|
|
897
|
+
type: "thinking",
|
|
898
|
+
thinking: ""
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
controller.enqueue(encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(blockStart)}\n\n`));
|
|
902
|
+
thinkingBlockStarted = true;
|
|
903
|
+
}
|
|
904
|
+
const thinkingDelta = {
|
|
905
|
+
type: "content_block_delta",
|
|
906
|
+
index: contentBlockIndex,
|
|
907
|
+
delta: {
|
|
908
|
+
type: "thinking_delta",
|
|
909
|
+
thinking: part.text
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
controller.enqueue(encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(thinkingDelta)}\n\n`));
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (part.text && !part.thought) {
|
|
916
|
+
if (thinkingBlockStarted && !textBlockStarted) {
|
|
917
|
+
const blockStop = {
|
|
918
|
+
type: "content_block_stop",
|
|
919
|
+
index: contentBlockIndex
|
|
920
|
+
};
|
|
921
|
+
controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}\n\n`));
|
|
922
|
+
contentBlockIndex++;
|
|
923
|
+
}
|
|
924
|
+
if (!textBlockStarted) {
|
|
925
|
+
const blockStart = {
|
|
926
|
+
type: "content_block_start",
|
|
927
|
+
index: contentBlockIndex,
|
|
928
|
+
content_block: {
|
|
929
|
+
type: "text",
|
|
930
|
+
text: ""
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
controller.enqueue(encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(blockStart)}\n\n`));
|
|
934
|
+
textBlockStarted = true;
|
|
935
|
+
}
|
|
936
|
+
const textDelta = {
|
|
937
|
+
type: "content_block_delta",
|
|
938
|
+
index: contentBlockIndex,
|
|
939
|
+
delta: {
|
|
940
|
+
type: "text_delta",
|
|
941
|
+
text: part.text
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
controller.enqueue(encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(textDelta)}\n\n`));
|
|
945
|
+
}
|
|
946
|
+
if (part.functionCall) {
|
|
947
|
+
if (textBlockStarted || thinkingBlockStarted) {
|
|
948
|
+
const blockStop = {
|
|
949
|
+
type: "content_block_stop",
|
|
950
|
+
index: contentBlockIndex
|
|
951
|
+
};
|
|
952
|
+
controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}\n\n`));
|
|
953
|
+
contentBlockIndex++;
|
|
954
|
+
textBlockStarted = false;
|
|
955
|
+
thinkingBlockStarted = false;
|
|
956
|
+
}
|
|
957
|
+
const toolBlockStart = {
|
|
958
|
+
type: "content_block_start",
|
|
959
|
+
index: contentBlockIndex,
|
|
960
|
+
content_block: {
|
|
961
|
+
type: "tool_use",
|
|
962
|
+
id: `toolu_${Date.now()}`,
|
|
963
|
+
name: part.functionCall.name,
|
|
964
|
+
input: {}
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
controller.enqueue(encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(toolBlockStart)}\n\n`));
|
|
968
|
+
const toolDelta = {
|
|
969
|
+
type: "content_block_delta",
|
|
970
|
+
index: contentBlockIndex,
|
|
971
|
+
delta: {
|
|
972
|
+
type: "input_json_delta",
|
|
973
|
+
partial_json: JSON.stringify(part.functionCall.args)
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
controller.enqueue(encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(toolDelta)}\n\n`));
|
|
977
|
+
const toolBlockStop = {
|
|
978
|
+
type: "content_block_stop",
|
|
979
|
+
index: contentBlockIndex
|
|
980
|
+
};
|
|
981
|
+
controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(toolBlockStop)}\n\n`));
|
|
982
|
+
contentBlockIndex++;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (candidate?.finishReason === "STOP") {
|
|
986
|
+
if (textBlockStarted || thinkingBlockStarted) {
|
|
987
|
+
const blockStop = {
|
|
988
|
+
type: "content_block_stop",
|
|
989
|
+
index: contentBlockIndex
|
|
990
|
+
};
|
|
991
|
+
controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}\n\n`));
|
|
992
|
+
}
|
|
993
|
+
const messageDelta = {
|
|
994
|
+
type: "message_delta",
|
|
995
|
+
delta: {
|
|
996
|
+
stop_reason: "end_turn",
|
|
997
|
+
stop_sequence: null
|
|
998
|
+
},
|
|
999
|
+
usage: { output_tokens: outputTokens }
|
|
1000
|
+
};
|
|
1001
|
+
controller.enqueue(encoder.encode(`event: message_delta\ndata: ${JSON.stringify(messageDelta)}\n\n`));
|
|
1002
|
+
}
|
|
1003
|
+
} catch {}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
consola.error("Stream transform error:", error);
|
|
1008
|
+
controller.error(error);
|
|
1009
|
+
}
|
|
1010
|
+
} });
|
|
1011
|
+
return new Response(stream, { headers: {
|
|
1012
|
+
"Content-Type": "text/event-stream",
|
|
1013
|
+
"Cache-Control": "no-cache",
|
|
1014
|
+
Connection: "keep-alive"
|
|
1015
|
+
} });
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Transform Antigravity non-stream response to Anthropic format
|
|
1019
|
+
*/
|
|
1020
|
+
async function transformNonStreamToAnthropic(response, model) {
|
|
1021
|
+
const data = await response.json();
|
|
1022
|
+
const candidate = data.candidates?.[0];
|
|
1023
|
+
const parts = candidate?.content?.parts || [];
|
|
1024
|
+
const content = [];
|
|
1025
|
+
for (const part of parts) {
|
|
1026
|
+
if (part.thought && part.text) content.push({
|
|
1027
|
+
type: "thinking",
|
|
1028
|
+
thinking: part.text
|
|
1029
|
+
});
|
|
1030
|
+
else if (part.text) content.push({
|
|
1031
|
+
type: "text",
|
|
1032
|
+
text: part.text
|
|
1033
|
+
});
|
|
1034
|
+
if (part.functionCall) content.push({
|
|
1035
|
+
type: "tool_use",
|
|
1036
|
+
id: `toolu_${Date.now()}`,
|
|
1037
|
+
name: part.functionCall.name,
|
|
1038
|
+
input: part.functionCall.args
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
const anthropicResponse = {
|
|
1042
|
+
id: `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
1043
|
+
type: "message",
|
|
1044
|
+
role: "assistant",
|
|
1045
|
+
content,
|
|
1046
|
+
model,
|
|
1047
|
+
stop_reason: candidate?.finishReason === "STOP" ? "end_turn" : "end_turn",
|
|
1048
|
+
stop_sequence: null,
|
|
1049
|
+
usage: {
|
|
1050
|
+
input_tokens: data.usageMetadata?.promptTokenCount || 0,
|
|
1051
|
+
output_tokens: data.usageMetadata?.candidatesTokenCount || 0
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
return new Response(JSON.stringify(anthropicResponse), { headers: { "Content-Type": "application/json" } });
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
//#endregion
|
|
1058
|
+
//#region src/routes/antigravity/messages/route.ts
|
|
1059
|
+
const antigravityMessagesRoute = new Hono();
|
|
1060
|
+
antigravityMessagesRoute.post("/", async (c) => {
|
|
1061
|
+
if (!state.antigravityMode) return c.json({ error: "Antigravity mode is not enabled. Start with --antigravity flag." }, 400);
|
|
1062
|
+
try {
|
|
1063
|
+
const body = await c.req.json();
|
|
1064
|
+
consola.debug("Antigravity message request:", body.model);
|
|
1065
|
+
const response = await createAntigravityMessages(body);
|
|
1066
|
+
if (body.stream) {
|
|
1067
|
+
const headers = new Headers();
|
|
1068
|
+
headers.set("Content-Type", "text/event-stream");
|
|
1069
|
+
headers.set("Cache-Control", "no-cache");
|
|
1070
|
+
headers.set("Connection", "keep-alive");
|
|
1071
|
+
return new Response(response.body, {
|
|
1072
|
+
status: response.status,
|
|
1073
|
+
headers
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
const data = await response.json();
|
|
1077
|
+
return c.json(data);
|
|
1078
|
+
} catch (error) {
|
|
1079
|
+
consola.error("Antigravity message error:", error);
|
|
1080
|
+
return c.json({
|
|
1081
|
+
type: "error",
|
|
1082
|
+
error: {
|
|
1083
|
+
type: "antigravity_error",
|
|
1084
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
1085
|
+
}
|
|
1086
|
+
}, 500);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
//#endregion
|
|
1091
|
+
//#region src/routes/antigravity/models/route.ts
|
|
1092
|
+
const app = new Hono();
|
|
1093
|
+
app.get("/", async (c) => {
|
|
1094
|
+
const models = await getAntigravityModels();
|
|
1095
|
+
return c.json(models);
|
|
1096
|
+
});
|
|
1097
|
+
const antigravityModelsRoute = app;
|
|
1098
|
+
|
|
379
1099
|
//#endregion
|
|
380
1100
|
//#region src/lib/approval.ts
|
|
381
1101
|
const awaitApproval = async () => {
|
|
@@ -1312,7 +2032,7 @@ zenModelRoutes.get("/", async (c) => {
|
|
|
1312
2032
|
if (!state.zenMode || !state.zenApiKey) return c.json({ error: "Zen mode is not enabled. Start with --zen flag." }, 400);
|
|
1313
2033
|
try {
|
|
1314
2034
|
if (state.zenModels) return c.json(state.zenModels);
|
|
1315
|
-
const { getZenModels } = await import("./get-models-
|
|
2035
|
+
const { getZenModels } = await import("./get-models-DJfPj_Rg.js");
|
|
1316
2036
|
const models = await getZenModels();
|
|
1317
2037
|
state.zenModels = models;
|
|
1318
2038
|
return c.json(models);
|
|
@@ -1332,33 +2052,41 @@ server.use(logger());
|
|
|
1332
2052
|
server.use(cors());
|
|
1333
2053
|
server.use(apiKeyAuthMiddleware);
|
|
1334
2054
|
server.get("/", (c) => c.text("Server running"));
|
|
1335
|
-
server.route("/chat/completions", new Hono().all("/*", async (c,
|
|
2055
|
+
server.route("/chat/completions", new Hono().all("/*", async (c, _next) => {
|
|
1336
2056
|
if (state.zenMode) return zenCompletionRoutes.fetch(c.req.raw, c.env);
|
|
2057
|
+
if (state.antigravityMode) return antigravityChatCompletionsRoute.fetch(c.req.raw, c.env);
|
|
1337
2058
|
return completionRoutes.fetch(c.req.raw, c.env);
|
|
1338
2059
|
}));
|
|
1339
|
-
server.route("/models", new Hono().all("/*", async (c,
|
|
2060
|
+
server.route("/models", new Hono().all("/*", async (c, _next) => {
|
|
1340
2061
|
if (state.zenMode) return zenModelRoutes.fetch(c.req.raw, c.env);
|
|
2062
|
+
if (state.antigravityMode) return antigravityModelsRoute.fetch(c.req.raw, c.env);
|
|
1341
2063
|
return modelRoutes.fetch(c.req.raw, c.env);
|
|
1342
2064
|
}));
|
|
1343
2065
|
server.route("/embeddings", embeddingRoutes);
|
|
1344
2066
|
server.route("/usage", usageRoute);
|
|
1345
2067
|
server.route("/token", tokenRoute);
|
|
1346
|
-
server.route("/v1/chat/completions", new Hono().all("/*", async (c,
|
|
2068
|
+
server.route("/v1/chat/completions", new Hono().all("/*", async (c, _next) => {
|
|
1347
2069
|
if (state.zenMode) return zenCompletionRoutes.fetch(c.req.raw, c.env);
|
|
2070
|
+
if (state.antigravityMode) return antigravityChatCompletionsRoute.fetch(c.req.raw, c.env);
|
|
1348
2071
|
return completionRoutes.fetch(c.req.raw, c.env);
|
|
1349
2072
|
}));
|
|
1350
|
-
server.route("/v1/models", new Hono().all("/*", async (c,
|
|
2073
|
+
server.route("/v1/models", new Hono().all("/*", async (c, _next) => {
|
|
1351
2074
|
if (state.zenMode) return zenModelRoutes.fetch(c.req.raw, c.env);
|
|
2075
|
+
if (state.antigravityMode) return antigravityModelsRoute.fetch(c.req.raw, c.env);
|
|
1352
2076
|
return modelRoutes.fetch(c.req.raw, c.env);
|
|
1353
2077
|
}));
|
|
1354
2078
|
server.route("/v1/embeddings", embeddingRoutes);
|
|
1355
|
-
server.route("/v1/messages", new Hono().all("/*", async (c,
|
|
2079
|
+
server.route("/v1/messages", new Hono().all("/*", async (c, _next) => {
|
|
1356
2080
|
if (state.zenMode) return zenMessageRoutes.fetch(c.req.raw, c.env);
|
|
2081
|
+
if (state.antigravityMode) return antigravityMessagesRoute.fetch(c.req.raw, c.env);
|
|
1357
2082
|
return messageRoutes.fetch(c.req.raw, c.env);
|
|
1358
2083
|
}));
|
|
1359
2084
|
server.route("/zen/v1/chat/completions", zenCompletionRoutes);
|
|
1360
2085
|
server.route("/zen/v1/models", zenModelRoutes);
|
|
1361
2086
|
server.route("/zen/v1/messages", zenMessageRoutes);
|
|
2087
|
+
server.route("/antigravity/v1/chat/completions", antigravityChatCompletionsRoute);
|
|
2088
|
+
server.route("/antigravity/v1/models", antigravityModelsRoute);
|
|
2089
|
+
server.route("/antigravity/v1/messages", antigravityMessagesRoute);
|
|
1362
2090
|
|
|
1363
2091
|
//#endregion
|
|
1364
2092
|
//#region src/start.ts
|
|
@@ -1407,23 +2135,40 @@ async function runServer(options) {
|
|
|
1407
2135
|
state.zenApiKey = options.zenApiKey;
|
|
1408
2136
|
consola.info("Using provided Zen API key");
|
|
1409
2137
|
} else {
|
|
1410
|
-
const { setupZenApiKey, loadZenAuth } = await import("./auth-
|
|
2138
|
+
const { setupZenApiKey, loadZenAuth } = await import("./auth-BO-mwvoU.js");
|
|
1411
2139
|
const existingAuth = await loadZenAuth();
|
|
1412
2140
|
if (existingAuth) {
|
|
1413
2141
|
state.zenApiKey = existingAuth.apiKey;
|
|
1414
2142
|
consola.info("Using existing Zen API key");
|
|
1415
2143
|
} else state.zenApiKey = await setupZenApiKey();
|
|
1416
2144
|
}
|
|
1417
|
-
const { cacheZenModels } = await import("./get-models-
|
|
2145
|
+
const { cacheZenModels } = await import("./get-models-DJfPj_Rg.js");
|
|
1418
2146
|
await cacheZenModels();
|
|
1419
2147
|
consola.info(`Available Zen models: \n${state.zenModels?.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
2148
|
+
} else if (options.antigravity) {
|
|
2149
|
+
consola.info("Google Antigravity mode enabled");
|
|
2150
|
+
state.antigravityMode = true;
|
|
2151
|
+
const { loadAntigravityAuth, setupAntigravity, getCurrentAccount } = await import("./auth-D2wtETTq.js");
|
|
2152
|
+
const existingAuth = await loadAntigravityAuth();
|
|
2153
|
+
if (!existingAuth || existingAuth.accounts.length === 0) {
|
|
2154
|
+
consola.warn("No Antigravity accounts found");
|
|
2155
|
+
await setupAntigravity();
|
|
2156
|
+
} else {
|
|
2157
|
+
const enabledCount = existingAuth.accounts.filter((a) => a.enable).length;
|
|
2158
|
+
consola.info(`Found ${existingAuth.accounts.length} Antigravity accounts (${enabledCount} enabled)`);
|
|
2159
|
+
}
|
|
2160
|
+
if (!await getCurrentAccount()) throw new Error("No enabled Antigravity accounts available");
|
|
2161
|
+
const { getAntigravityModels: getAntigravityModels$1 } = await import("./get-models-Dq2ZDU9m.js");
|
|
2162
|
+
const models = await getAntigravityModels$1();
|
|
2163
|
+
state.antigravityModels = models;
|
|
2164
|
+
consola.info(`Available Antigravity models: \n${models.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
1420
2165
|
} else {
|
|
1421
2166
|
await cacheVSCodeVersion();
|
|
1422
2167
|
if (options.githubToken) {
|
|
1423
2168
|
state.githubToken = options.githubToken;
|
|
1424
2169
|
consola.info("Using provided GitHub token");
|
|
1425
2170
|
try {
|
|
1426
|
-
const { getGitHubUser } = await import("./get-user-
|
|
2171
|
+
const { getGitHubUser } = await import("./get-user-hpkh0FzZ.js");
|
|
1427
2172
|
const user = await getGitHubUser();
|
|
1428
2173
|
consola.info(`Logged in as ${user.login}`);
|
|
1429
2174
|
} catch (error) {
|
|
@@ -1437,7 +2182,7 @@ async function runServer(options) {
|
|
|
1437
2182
|
const { HTTPError: HTTPError$1 } = await import("./error-CsShqJjE.js");
|
|
1438
2183
|
if (error instanceof HTTPError$1 && error.response.status === 401) {
|
|
1439
2184
|
consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
|
|
1440
|
-
const { clearGithubToken: clearGithubToken$1 } = await import("./token-
|
|
2185
|
+
const { clearGithubToken: clearGithubToken$1 } = await import("./token-DS09XjQ5.js");
|
|
1441
2186
|
await clearGithubToken$1();
|
|
1442
2187
|
consola.info("Please restart to re-authenticate");
|
|
1443
2188
|
}
|
|
@@ -1448,7 +2193,7 @@ async function runServer(options) {
|
|
|
1448
2193
|
}
|
|
1449
2194
|
const serverUrl = `http://localhost:${options.port}`;
|
|
1450
2195
|
if (options.claudeCode) {
|
|
1451
|
-
const models = state.zenMode ? state.zenModels : state.models;
|
|
2196
|
+
const models = state.zenMode ? state.zenModels : state.antigravityMode ? state.antigravityModels : state.models;
|
|
1452
2197
|
invariant(models, "Models should be loaded by now");
|
|
1453
2198
|
const selectedModel = await consola.prompt("Select a model to use with Claude Code", {
|
|
1454
2199
|
type: "select",
|
|
@@ -1556,6 +2301,11 @@ const start = defineCommand({
|
|
|
1556
2301
|
"zen-api-key": {
|
|
1557
2302
|
type: "string",
|
|
1558
2303
|
description: "OpenCode Zen API key (get from https://opencode.ai/zen)"
|
|
2304
|
+
},
|
|
2305
|
+
antigravity: {
|
|
2306
|
+
type: "boolean",
|
|
2307
|
+
default: false,
|
|
2308
|
+
description: "Enable Google Antigravity mode (proxy to Antigravity instead of GitHub Copilot)"
|
|
1559
2309
|
}
|
|
1560
2310
|
},
|
|
1561
2311
|
run({ args }) {
|
|
@@ -1577,7 +2327,8 @@ const start = defineCommand({
|
|
|
1577
2327
|
proxyEnv: args["proxy-env"],
|
|
1578
2328
|
apiKeys,
|
|
1579
2329
|
zen: args.zen,
|
|
1580
|
-
zenApiKey: args["zen-api-key"]
|
|
2330
|
+
zenApiKey: args["zen-api-key"],
|
|
2331
|
+
antigravity: args.antigravity
|
|
1581
2332
|
});
|
|
1582
2333
|
}
|
|
1583
2334
|
});
|