@kontextmind/kxm 0.7.15 → 0.7.16
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/.claude-plugin/marketplace.json +1 -1
- package/docs/configuration.md +1 -2
- package/docs/operator-pi-packages.md +5 -2
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +4 -0
- package/plugins/kxm/dist/core.js +4 -0
- package/plugins/kxm/dist/extension.js +3066 -2
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime.js +4 -0
- package/plugins/kxm/dist/server.js +4 -0
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/extension.ts +9 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/providers/antigravity/LICENSE +21 -0
- package/plugins/kxm/src/providers/antigravity/README.md +19 -0
- package/plugins/kxm/src/providers/antigravity/auth/index.ts +17 -0
- package/plugins/kxm/src/providers/antigravity/auth/oauth.ts +449 -0
- package/plugins/kxm/src/providers/antigravity/client/client.ts +562 -0
- package/plugins/kxm/src/providers/antigravity/client/index.ts +1 -0
- package/plugins/kxm/src/providers/antigravity/diagnostics/diagnostics.ts +97 -0
- package/plugins/kxm/src/providers/antigravity/diagnostics/index.ts +1 -0
- package/plugins/kxm/src/providers/antigravity/index.ts +24 -0
- package/plugins/kxm/src/providers/antigravity/models/discovery.ts +155 -0
- package/plugins/kxm/src/providers/antigravity/models/grouping.ts +425 -0
- package/plugins/kxm/src/providers/antigravity/models/index.ts +3 -0
- package/plugins/kxm/src/providers/antigravity/models/models.ts +501 -0
- package/plugins/kxm/src/providers/antigravity/pi-compat.ts +279 -0
- package/plugins/kxm/src/providers/antigravity/register.ts +123 -0
- package/plugins/kxm/src/providers/antigravity/stream/index.ts +1 -0
- package/plugins/kxm/src/providers/antigravity/stream/stream.ts +1461 -0
- package/plugins/kxm/src/providers/antigravity/types/enums.ts +50 -0
- package/plugins/kxm/src/providers/antigravity/types/index.ts +2 -0
- package/plugins/kxm/src/providers/antigravity/types/types.ts +293 -0
- package/plugins/kxm/src/providers/antigravity/usage/index.ts +1 -0
- package/plugins/kxm/src/providers/antigravity/usage/usage.ts +361 -0
- package/plugins/kxm/src/providers/antigravity/utils/http.ts +32 -0
- package/plugins/kxm/src/providers/antigravity/utils/index.ts +3 -0
- package/plugins/kxm/src/providers/antigravity/utils/security.ts +75 -0
- package/plugins/kxm/src/providers/antigravity/utils/util.ts +133 -0
- package/plugins/kxm/src/redact.ts +4 -0
|
@@ -8646,6 +8646,10 @@ var SECRET_PATTERNS = [
|
|
|
8646
8646
|
/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
8647
8647
|
/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/gi,
|
|
8648
8648
|
/\bBearer\s+[A-Za-z0-9._~+/=-]+\b/gi,
|
|
8649
|
+
/\bya29\.[A-Za-z0-9._~+/-]+=*/g,
|
|
8650
|
+
/\b1\/\/[A-Za-z0-9_-]+/g,
|
|
8651
|
+
/\b1\/[A-Za-z0-9_-]{20,}/g,
|
|
8652
|
+
/("?(?:access_token|refresh_token|id_token)"?\s*[:=]\s*")[^"]*(")/gi,
|
|
8649
8653
|
/\bKXM_[A-Z0-9_]*(TOKEN|SECRET|KEY)[A-Z0-9_]*=\S+/gi,
|
|
8650
8654
|
/\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET)=\S+/gi,
|
|
8651
8655
|
/\b[A-Fa-f0-9]{64}\b/g
|
|
@@ -9388,6 +9392,3062 @@ async function loadCatalog(path, deps) {
|
|
|
9388
9392
|
}
|
|
9389
9393
|
}
|
|
9390
9394
|
|
|
9395
|
+
// plugins/kxm/src/providers/antigravity/auth/oauth.ts
|
|
9396
|
+
import { createHash as createHash5, randomBytes } from "node:crypto";
|
|
9397
|
+
import { createServer } from "node:http";
|
|
9398
|
+
|
|
9399
|
+
// plugins/kxm/src/providers/antigravity/client/client.ts
|
|
9400
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
9401
|
+
|
|
9402
|
+
// plugins/kxm/src/providers/antigravity/diagnostics/diagnostics.ts
|
|
9403
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9404
|
+
|
|
9405
|
+
// plugins/kxm/src/providers/antigravity/utils/util.ts
|
|
9406
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
9407
|
+
|
|
9408
|
+
// plugins/kxm/src/providers/antigravity/types/enums.ts
|
|
9409
|
+
var ThinkingEffort = {
|
|
9410
|
+
Off: "off",
|
|
9411
|
+
Minimal: "minimal",
|
|
9412
|
+
Low: "low",
|
|
9413
|
+
Medium: "medium",
|
|
9414
|
+
High: "high",
|
|
9415
|
+
Xhigh: "xhigh"
|
|
9416
|
+
};
|
|
9417
|
+
var ToolChoice = {
|
|
9418
|
+
Auto: "auto",
|
|
9419
|
+
None: "none",
|
|
9420
|
+
Any: "any",
|
|
9421
|
+
Required: "required"
|
|
9422
|
+
};
|
|
9423
|
+
var GeminiToolCallingMode = {
|
|
9424
|
+
None: "NONE",
|
|
9425
|
+
Any: "ANY",
|
|
9426
|
+
Auto: "AUTO",
|
|
9427
|
+
Validated: "VALIDATED"
|
|
9428
|
+
};
|
|
9429
|
+
var GeminiRole = {
|
|
9430
|
+
User: "user",
|
|
9431
|
+
Model: "model"
|
|
9432
|
+
};
|
|
9433
|
+
var AntigravityRequestType = {
|
|
9434
|
+
Agent: "agent"
|
|
9435
|
+
};
|
|
9436
|
+
var AntigravityUserAgent = {
|
|
9437
|
+
Antigravity: "antigravity"
|
|
9438
|
+
};
|
|
9439
|
+
var StopReason = {
|
|
9440
|
+
Stop: "stop",
|
|
9441
|
+
Length: "length",
|
|
9442
|
+
ToolUse: "toolUse",
|
|
9443
|
+
Error: "error"
|
|
9444
|
+
};
|
|
9445
|
+
|
|
9446
|
+
// plugins/kxm/src/providers/antigravity/models/models.ts
|
|
9447
|
+
var PROVIDER_ID = "antigravity";
|
|
9448
|
+
var PROVIDER_NAME = "Antigravity";
|
|
9449
|
+
var ANTIGRAVITY_ROUTING = {
|
|
9450
|
+
"claude-opus-4-6": {
|
|
9451
|
+
routing: {
|
|
9452
|
+
minimal: "claude-opus-4-6-thinking",
|
|
9453
|
+
low: "claude-opus-4-6-thinking",
|
|
9454
|
+
medium: "claude-opus-4-6-thinking",
|
|
9455
|
+
high: "claude-opus-4-6-thinking"
|
|
9456
|
+
},
|
|
9457
|
+
defaultRequestId: "claude-opus-4-6-thinking"
|
|
9458
|
+
},
|
|
9459
|
+
// Live fetchAvailableModels exposes `claude-sonnet-4-6` (display: Thinking), not a separate *-thinking id.
|
|
9460
|
+
"claude-sonnet-4-6": {
|
|
9461
|
+
off: "claude-sonnet-4-6",
|
|
9462
|
+
routing: {
|
|
9463
|
+
minimal: "claude-sonnet-4-6",
|
|
9464
|
+
low: "claude-sonnet-4-6",
|
|
9465
|
+
medium: "claude-sonnet-4-6",
|
|
9466
|
+
high: "claude-sonnet-4-6",
|
|
9467
|
+
xhigh: "claude-sonnet-4-6"
|
|
9468
|
+
},
|
|
9469
|
+
defaultRequestId: "claude-sonnet-4-6"
|
|
9470
|
+
},
|
|
9471
|
+
"gemini-3.1-pro": {
|
|
9472
|
+
// `gemini-3.1-pro-high` is advertised but currently 400s for agent streamGenerateContent;
|
|
9473
|
+
// `gemini-pro-agent` is the working High runtime id (same display name in fetchAvailableModels).
|
|
9474
|
+
off: "gemini-3.1-pro-low",
|
|
9475
|
+
routing: {
|
|
9476
|
+
minimal: "gemini-3.1-pro-low",
|
|
9477
|
+
low: "gemini-3.1-pro-low",
|
|
9478
|
+
medium: "gemini-3.1-pro-low",
|
|
9479
|
+
high: "gemini-pro-agent",
|
|
9480
|
+
xhigh: "gemini-pro-agent"
|
|
9481
|
+
},
|
|
9482
|
+
defaultRequestId: "gemini-3.1-pro-low"
|
|
9483
|
+
},
|
|
9484
|
+
"gemini-3.8-flash": {
|
|
9485
|
+
off: "gemini-3.8-flash-low",
|
|
9486
|
+
routing: {
|
|
9487
|
+
minimal: "gemini-3.8-flash-low",
|
|
9488
|
+
low: "gemini-3.8-flash-low",
|
|
9489
|
+
medium: "gemini-3.8-flash-medium",
|
|
9490
|
+
high: "gemini-3.8-flash-high",
|
|
9491
|
+
xhigh: "gemini-3.8-flash-high"
|
|
9492
|
+
},
|
|
9493
|
+
defaultRequestId: "gemini-3.8-flash-low"
|
|
9494
|
+
},
|
|
9495
|
+
"gemini-3.7-flash": {
|
|
9496
|
+
off: "gemini-3.7-flash-low",
|
|
9497
|
+
routing: {
|
|
9498
|
+
minimal: "gemini-3.7-flash-low",
|
|
9499
|
+
low: "gemini-3.7-flash-low",
|
|
9500
|
+
medium: "gemini-3.7-flash-medium",
|
|
9501
|
+
high: "gemini-3.7-flash-high",
|
|
9502
|
+
xhigh: "gemini-3.7-flash-high"
|
|
9503
|
+
},
|
|
9504
|
+
defaultRequestId: "gemini-3.7-flash-low"
|
|
9505
|
+
},
|
|
9506
|
+
"gemini-3.6-flash": {
|
|
9507
|
+
// agy models: gemini-3.6-flash-low / -medium / -high
|
|
9508
|
+
off: "gemini-3.6-flash-low",
|
|
9509
|
+
routing: {
|
|
9510
|
+
minimal: "gemini-3.6-flash-low",
|
|
9511
|
+
low: "gemini-3.6-flash-low",
|
|
9512
|
+
medium: "gemini-3.6-flash-medium",
|
|
9513
|
+
high: "gemini-3.6-flash-high",
|
|
9514
|
+
xhigh: "gemini-3.6-flash-high"
|
|
9515
|
+
},
|
|
9516
|
+
defaultRequestId: "gemini-3.6-flash-low"
|
|
9517
|
+
},
|
|
9518
|
+
"gemini-3.5-flash": {
|
|
9519
|
+
off: "gemini-3.5-flash-extra-low",
|
|
9520
|
+
routing: {
|
|
9521
|
+
minimal: "gemini-3.5-flash-extra-low",
|
|
9522
|
+
low: "gemini-3.5-flash-extra-low",
|
|
9523
|
+
medium: "gemini-3.5-flash-low",
|
|
9524
|
+
high: "gemini-3-flash-agent",
|
|
9525
|
+
xhigh: "gemini-3-flash-agent"
|
|
9526
|
+
},
|
|
9527
|
+
defaultRequestId: "gemini-3.5-flash-extra-low"
|
|
9528
|
+
},
|
|
9529
|
+
"gpt-oss-120b": {
|
|
9530
|
+
off: "gpt-oss-120b-medium",
|
|
9531
|
+
routing: {
|
|
9532
|
+
minimal: "gpt-oss-120b-medium",
|
|
9533
|
+
low: "gpt-oss-120b-medium",
|
|
9534
|
+
medium: "gpt-oss-120b-medium",
|
|
9535
|
+
high: "gpt-oss-120b-medium"
|
|
9536
|
+
},
|
|
9537
|
+
defaultRequestId: "gpt-oss-120b-medium"
|
|
9538
|
+
}
|
|
9539
|
+
};
|
|
9540
|
+
var RUNTIME_MAX_OUTPUT_TOKENS = {
|
|
9541
|
+
"gemini-3.8-flash": 65536,
|
|
9542
|
+
"gemini-3.8-flash-low": 65536,
|
|
9543
|
+
"gemini-3.8-flash-medium": 65536,
|
|
9544
|
+
"gemini-3.8-flash-high": 65536,
|
|
9545
|
+
"gemini-3.7-flash": 65536,
|
|
9546
|
+
"gemini-3.7-flash-tiered": 65536,
|
|
9547
|
+
// Retain rollout-era IDs for compatibility with pinned runtime overrides.
|
|
9548
|
+
"gemini-3.7-flash-low": 65536,
|
|
9549
|
+
"gemini-3.7-flash-medium": 65536,
|
|
9550
|
+
"gemini-3.7-flash-high": 65536,
|
|
9551
|
+
"gemini-3.6-flash": 65536,
|
|
9552
|
+
"gemini-3.6-flash-low": 65536,
|
|
9553
|
+
"gemini-3.6-flash-medium": 65536,
|
|
9554
|
+
"gemini-3.6-flash-high": 65536,
|
|
9555
|
+
"gemini-3.5-flash": 65536,
|
|
9556
|
+
"gemini-3.5-flash-extra-low": 65536,
|
|
9557
|
+
"gemini-3.5-flash-low": 65536,
|
|
9558
|
+
"gemini-3-flash-agent": 65536,
|
|
9559
|
+
"gemini-3.1-pro": 65535,
|
|
9560
|
+
"gemini-3.1-pro-low": 65535,
|
|
9561
|
+
"gemini-3.1-pro-high": 65535,
|
|
9562
|
+
"gemini-pro-agent": 65535,
|
|
9563
|
+
"claude-opus-4-6": 64e3,
|
|
9564
|
+
"claude-opus-4-6-thinking": 64e3,
|
|
9565
|
+
"claude-sonnet-4-6": 64e3,
|
|
9566
|
+
"gpt-oss-120b": 32768,
|
|
9567
|
+
"gpt-oss-120b-medium": 32768
|
|
9568
|
+
};
|
|
9569
|
+
function getMaxOutputTokens(modelId, runtimeModel) {
|
|
9570
|
+
if (runtimeModel && RUNTIME_MAX_OUTPUT_TOKENS[runtimeModel] !== void 0) {
|
|
9571
|
+
return RUNTIME_MAX_OUTPUT_TOKENS[runtimeModel];
|
|
9572
|
+
}
|
|
9573
|
+
if (RUNTIME_MAX_OUTPUT_TOKENS[modelId] !== void 0) {
|
|
9574
|
+
return RUNTIME_MAX_OUTPUT_TOKENS[modelId];
|
|
9575
|
+
}
|
|
9576
|
+
if (runtimeModel) {
|
|
9577
|
+
if (runtimeModel.startsWith("claude-")) return 64e3;
|
|
9578
|
+
if (runtimeModel.startsWith("gpt-oss-")) return 32768;
|
|
9579
|
+
if (runtimeModel.startsWith("gemini-3.1-pro") || runtimeModel === "gemini-pro-agent")
|
|
9580
|
+
return 65535;
|
|
9581
|
+
if (runtimeModel.startsWith("gemini-")) return 65536;
|
|
9582
|
+
}
|
|
9583
|
+
return 8192;
|
|
9584
|
+
}
|
|
9585
|
+
var geminiFlashCost = { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0.1 };
|
|
9586
|
+
var geminiProCost = { input: 1.25, output: 5, cacheRead: 0.3125, cacheWrite: 1.25 };
|
|
9587
|
+
var claudeSonnetCost = { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 };
|
|
9588
|
+
var claudeOpusCost = { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 };
|
|
9589
|
+
var gptOssCost = { input: 0.6, output: 2.4, cacheRead: 0.15, cacheWrite: 0.6 };
|
|
9590
|
+
var thinkingLevelMaps = {
|
|
9591
|
+
lowMediumHigh: {
|
|
9592
|
+
off: null,
|
|
9593
|
+
minimal: null,
|
|
9594
|
+
low: "low",
|
|
9595
|
+
medium: "medium",
|
|
9596
|
+
high: "high",
|
|
9597
|
+
xhigh: null,
|
|
9598
|
+
max: null
|
|
9599
|
+
},
|
|
9600
|
+
lowHigh: {
|
|
9601
|
+
off: null,
|
|
9602
|
+
minimal: null,
|
|
9603
|
+
low: "low",
|
|
9604
|
+
medium: null,
|
|
9605
|
+
high: "high",
|
|
9606
|
+
xhigh: null,
|
|
9607
|
+
max: null
|
|
9608
|
+
},
|
|
9609
|
+
thinking: {
|
|
9610
|
+
off: null,
|
|
9611
|
+
minimal: null,
|
|
9612
|
+
low: null,
|
|
9613
|
+
medium: null,
|
|
9614
|
+
high: "high",
|
|
9615
|
+
xhigh: null,
|
|
9616
|
+
max: null
|
|
9617
|
+
},
|
|
9618
|
+
medium: {
|
|
9619
|
+
off: null,
|
|
9620
|
+
minimal: null,
|
|
9621
|
+
low: null,
|
|
9622
|
+
medium: "medium",
|
|
9623
|
+
high: null,
|
|
9624
|
+
xhigh: null,
|
|
9625
|
+
max: null
|
|
9626
|
+
}
|
|
9627
|
+
};
|
|
9628
|
+
var ANTIGRAVITY_MODELS = [
|
|
9629
|
+
{
|
|
9630
|
+
id: "gemini-3.8-flash",
|
|
9631
|
+
name: "Gemini 3.8 Flash (Antigravity)",
|
|
9632
|
+
reasoning: true,
|
|
9633
|
+
thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
|
|
9634
|
+
input: ["text", "image"],
|
|
9635
|
+
cost: geminiFlashCost,
|
|
9636
|
+
contextWindow: 1048576,
|
|
9637
|
+
maxTokens: 65536
|
|
9638
|
+
},
|
|
9639
|
+
{
|
|
9640
|
+
id: "gemini-3.7-flash",
|
|
9641
|
+
name: "Gemini 3.7 Flash (Antigravity)",
|
|
9642
|
+
reasoning: true,
|
|
9643
|
+
thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
|
|
9644
|
+
input: ["text", "image"],
|
|
9645
|
+
cost: geminiFlashCost,
|
|
9646
|
+
contextWindow: 1048576,
|
|
9647
|
+
maxTokens: 65536
|
|
9648
|
+
},
|
|
9649
|
+
{
|
|
9650
|
+
id: "gemini-3.6-flash",
|
|
9651
|
+
name: "Gemini 3.6 Flash (Antigravity)",
|
|
9652
|
+
reasoning: true,
|
|
9653
|
+
thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
|
|
9654
|
+
input: ["text", "image"],
|
|
9655
|
+
cost: geminiFlashCost,
|
|
9656
|
+
contextWindow: 1048576,
|
|
9657
|
+
maxTokens: 65536
|
|
9658
|
+
},
|
|
9659
|
+
{
|
|
9660
|
+
id: "claude-opus-4-6",
|
|
9661
|
+
name: "Claude Opus 4.6 (Antigravity)",
|
|
9662
|
+
reasoning: true,
|
|
9663
|
+
thinkingLevelMap: thinkingLevelMaps.thinking,
|
|
9664
|
+
input: ["text", "image"],
|
|
9665
|
+
cost: claudeOpusCost,
|
|
9666
|
+
contextWindow: 25e4,
|
|
9667
|
+
maxTokens: 64e3
|
|
9668
|
+
},
|
|
9669
|
+
{
|
|
9670
|
+
id: "claude-sonnet-4-6",
|
|
9671
|
+
name: "Claude Sonnet 4.6 (Antigravity)",
|
|
9672
|
+
reasoning: true,
|
|
9673
|
+
thinkingLevelMap: thinkingLevelMaps.thinking,
|
|
9674
|
+
input: ["text", "image"],
|
|
9675
|
+
cost: claudeSonnetCost,
|
|
9676
|
+
contextWindow: 2e5,
|
|
9677
|
+
maxTokens: 64e3
|
|
9678
|
+
},
|
|
9679
|
+
{
|
|
9680
|
+
id: "gemini-3.1-pro",
|
|
9681
|
+
name: "Gemini 3.1 Pro (Antigravity)",
|
|
9682
|
+
reasoning: true,
|
|
9683
|
+
thinkingLevelMap: thinkingLevelMaps.lowHigh,
|
|
9684
|
+
input: ["text", "image"],
|
|
9685
|
+
cost: geminiProCost,
|
|
9686
|
+
contextWindow: 1048576,
|
|
9687
|
+
maxTokens: 65535
|
|
9688
|
+
},
|
|
9689
|
+
{
|
|
9690
|
+
id: "gemini-3.5-flash",
|
|
9691
|
+
name: "Gemini 3.5 Flash (Antigravity)",
|
|
9692
|
+
reasoning: true,
|
|
9693
|
+
thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
|
|
9694
|
+
input: ["text", "image"],
|
|
9695
|
+
cost: geminiFlashCost,
|
|
9696
|
+
contextWindow: 1048576,
|
|
9697
|
+
maxTokens: 65536
|
|
9698
|
+
},
|
|
9699
|
+
{
|
|
9700
|
+
id: "gpt-oss-120b",
|
|
9701
|
+
name: "GPT-OSS 120B (Antigravity)",
|
|
9702
|
+
reasoning: true,
|
|
9703
|
+
thinkingLevelMap: thinkingLevelMaps.medium,
|
|
9704
|
+
input: ["text"],
|
|
9705
|
+
cost: gptOssCost,
|
|
9706
|
+
contextWindow: 131072,
|
|
9707
|
+
maxTokens: 32768
|
|
9708
|
+
}
|
|
9709
|
+
];
|
|
9710
|
+
var currentModels = ANTIGRAVITY_MODELS;
|
|
9711
|
+
var currentRouting = { ...ANTIGRAVITY_ROUTING };
|
|
9712
|
+
function getCurrentAntigravityRouting() {
|
|
9713
|
+
return currentRouting;
|
|
9714
|
+
}
|
|
9715
|
+
function getCurrentAntigravityCatalog() {
|
|
9716
|
+
return { models: currentModels, routing: currentRouting };
|
|
9717
|
+
}
|
|
9718
|
+
function applyAntigravityCatalog(catalog) {
|
|
9719
|
+
currentModels = catalog.models;
|
|
9720
|
+
currentRouting = catalog.routing;
|
|
9721
|
+
}
|
|
9722
|
+
function getAntigravityRequestModelId(modelId, effort) {
|
|
9723
|
+
const r = currentRouting[modelId] ?? ANTIGRAVITY_ROUTING[modelId];
|
|
9724
|
+
if (!r) return modelId;
|
|
9725
|
+
if (effort === void 0 || effort === "off") {
|
|
9726
|
+
return r.off ?? r.routing?.minimal ?? r.routing?.low ?? r.defaultRequestId ?? modelId;
|
|
9727
|
+
}
|
|
9728
|
+
const effortKey = effort;
|
|
9729
|
+
if (effortKey === ThinkingEffort.Xhigh) {
|
|
9730
|
+
return r.routing?.xhigh ?? r.routing?.high ?? r.routing?.low ?? r.routing?.minimal ?? r.off ?? r.defaultRequestId ?? modelId;
|
|
9731
|
+
}
|
|
9732
|
+
return r.routing?.[effortKey] ?? r.routing?.low ?? r.routing?.minimal ?? r.off ?? r.defaultRequestId ?? modelId;
|
|
9733
|
+
}
|
|
9734
|
+
function getFallbackRuntimeModel(runtimeModel, effort) {
|
|
9735
|
+
if (runtimeModel.startsWith("gemini-3.8-flash-")) {
|
|
9736
|
+
return runtimeModel.replace("gemini-3.8-flash-", "gemini-3.7-flash-");
|
|
9737
|
+
}
|
|
9738
|
+
if (runtimeModel === "gemini-3.8-flash") {
|
|
9739
|
+
return "gemini-3.7-flash-low";
|
|
9740
|
+
}
|
|
9741
|
+
if (runtimeModel === "gemini-3.7-flash-tiered") {
|
|
9742
|
+
return getAntigravityRequestModelId("gemini-3.6-flash", effort);
|
|
9743
|
+
}
|
|
9744
|
+
if (runtimeModel.startsWith("gemini-3.7-flash-")) {
|
|
9745
|
+
return runtimeModel.replace("gemini-3.7-flash-", "gemini-3.6-flash-");
|
|
9746
|
+
}
|
|
9747
|
+
if (runtimeModel === "gemini-3.7-flash") {
|
|
9748
|
+
return "gemini-3.6-flash-low";
|
|
9749
|
+
}
|
|
9750
|
+
return void 0;
|
|
9751
|
+
}
|
|
9752
|
+
var ANTIGRAVITY_MODEL_ENUM = {
|
|
9753
|
+
// Gemini 3.8 Flash
|
|
9754
|
+
"gemini-3.8-flash": "MODEL_PLACEHOLDER_M318",
|
|
9755
|
+
"gemini-3.8-flash-high": "MODEL_PLACEHOLDER_M318",
|
|
9756
|
+
"gemini-3.8-flash-medium": "MODEL_PLACEHOLDER_M319",
|
|
9757
|
+
"gemini-3.8-flash-low": "MODEL_PLACEHOLDER_M320",
|
|
9758
|
+
"gemini-3.8-flash-tiered": "MODEL_PLACEHOLDER_M322",
|
|
9759
|
+
// Gemini 3.7 Flash
|
|
9760
|
+
"gemini-3.7-flash": "MODEL_PLACEHOLDER_M298",
|
|
9761
|
+
"gemini-3.7-flash-high": "MODEL_PLACEHOLDER_M298",
|
|
9762
|
+
"gemini-3.7-flash-medium": "MODEL_PLACEHOLDER_M299",
|
|
9763
|
+
"gemini-3.7-flash-low": "MODEL_PLACEHOLDER_M300",
|
|
9764
|
+
"gemini-3.7-flash-tiered": "MODEL_PLACEHOLDER_M301",
|
|
9765
|
+
// Gemini 3.6 Flash
|
|
9766
|
+
"gemini-3.6-flash": "MODEL_PLACEHOLDER_M71",
|
|
9767
|
+
"gemini-3.6-flash-high": "MODEL_PLACEHOLDER_M71",
|
|
9768
|
+
"gemini-3.6-flash-medium": "MODEL_PLACEHOLDER_M72",
|
|
9769
|
+
"gemini-3.6-flash-low": "MODEL_PLACEHOLDER_M73",
|
|
9770
|
+
"gemini-3.6-flash-tiered": "MODEL_PLACEHOLDER_M196",
|
|
9771
|
+
// Gemini 3.5 Flash
|
|
9772
|
+
"gemini-3.5-flash": "MODEL_PLACEHOLDER_M20",
|
|
9773
|
+
"gemini-3.5-flash-extra-low": "MODEL_PLACEHOLDER_M187",
|
|
9774
|
+
"gemini-3.5-flash-low": "MODEL_PLACEHOLDER_M20",
|
|
9775
|
+
"gemini-3-flash-agent": "MODEL_PLACEHOLDER_M84",
|
|
9776
|
+
// Gemini 3.1 Pro
|
|
9777
|
+
"gemini-3.1-pro": "MODEL_PLACEHOLDER_M36",
|
|
9778
|
+
"gemini-3.1-pro-low": "MODEL_PLACEHOLDER_M36",
|
|
9779
|
+
"gemini-3.1-pro-high": "MODEL_PLACEHOLDER_M37",
|
|
9780
|
+
"gemini-pro-agent": "MODEL_PLACEHOLDER_M16",
|
|
9781
|
+
// Claude
|
|
9782
|
+
"claude-sonnet-4-6": "MODEL_PLACEHOLDER_M35",
|
|
9783
|
+
"claude-opus-4-6": "MODEL_PLACEHOLDER_M26",
|
|
9784
|
+
"claude-opus-4-6-thinking": "MODEL_PLACEHOLDER_M26",
|
|
9785
|
+
// GPT-OSS
|
|
9786
|
+
"gpt-oss-120b": "MODEL_OPENAI_GPT_OSS_120B_MEDIUM",
|
|
9787
|
+
"gpt-oss-120b-medium": "MODEL_OPENAI_GPT_OSS_120B_MEDIUM"
|
|
9788
|
+
};
|
|
9789
|
+
var modelEnumCache = /* @__PURE__ */ new Map();
|
|
9790
|
+
function registerModelEnum(wireModelId, modelEnum) {
|
|
9791
|
+
if (wireModelId && modelEnum) {
|
|
9792
|
+
modelEnumCache.set(wireModelId, modelEnum);
|
|
9793
|
+
}
|
|
9794
|
+
}
|
|
9795
|
+
function registerDiscoveredModelEnums(models) {
|
|
9796
|
+
if (!models) return;
|
|
9797
|
+
for (const [wireId, info] of Object.entries(models)) {
|
|
9798
|
+
if (typeof info?.model === "string" && info.model) {
|
|
9799
|
+
modelEnumCache.set(wireId, info.model);
|
|
9800
|
+
}
|
|
9801
|
+
}
|
|
9802
|
+
}
|
|
9803
|
+
function getModelEnum(wireModelId) {
|
|
9804
|
+
const direct = modelEnumCache.get(wireModelId) || ANTIGRAVITY_MODEL_ENUM[wireModelId];
|
|
9805
|
+
if (direct) return direct;
|
|
9806
|
+
const routed = getAntigravityRequestModelId(wireModelId, void 0);
|
|
9807
|
+
return modelEnumCache.get(routed) || ANTIGRAVITY_MODEL_ENUM[routed];
|
|
9808
|
+
}
|
|
9809
|
+
function snapshotDynamicModelEnums() {
|
|
9810
|
+
return Object.fromEntries(modelEnumCache);
|
|
9811
|
+
}
|
|
9812
|
+
function restoreDynamicModelEnums(modelEnums) {
|
|
9813
|
+
modelEnumCache.clear();
|
|
9814
|
+
for (const [wireModelId, modelEnum] of Object.entries(modelEnums)) {
|
|
9815
|
+
if (wireModelId && modelEnum) modelEnumCache.set(wireModelId, modelEnum);
|
|
9816
|
+
}
|
|
9817
|
+
}
|
|
9818
|
+
function getThinkingConfig(modelId, effort) {
|
|
9819
|
+
if (modelId.startsWith("claude-")) {
|
|
9820
|
+
if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
|
|
9821
|
+
return { includeThoughts: true, thinkingBudget: 1024 };
|
|
9822
|
+
}
|
|
9823
|
+
if (modelId.startsWith("gpt-oss-")) {
|
|
9824
|
+
if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
|
|
9825
|
+
return { includeThoughts: true, thinkingBudget: 8192 };
|
|
9826
|
+
}
|
|
9827
|
+
if (modelId.startsWith("gemini-3.5-flash") || modelId === "gemini-3-flash-agent") {
|
|
9828
|
+
if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
|
|
9829
|
+
const thinkingBudget = effort === "high" || effort === "xhigh" ? 1e4 : effort === "medium" ? 4e3 : 1e3;
|
|
9830
|
+
return { includeThoughts: true, thinkingBudget };
|
|
9831
|
+
}
|
|
9832
|
+
if (modelId.startsWith("gemini-3.1-pro") || modelId === "gemini-pro-agent") {
|
|
9833
|
+
if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
|
|
9834
|
+
return {
|
|
9835
|
+
includeThoughts: true,
|
|
9836
|
+
thinkingBudget: effort === "high" || effort === "xhigh" ? 10001 : 1001
|
|
9837
|
+
};
|
|
9838
|
+
}
|
|
9839
|
+
if (modelId.startsWith("gemini-")) {
|
|
9840
|
+
if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
|
|
9841
|
+
const thinkingBudget = effort === "high" || effort === "xhigh" ? -1 : effort === "medium" ? 4e3 : 1e3;
|
|
9842
|
+
return { includeThoughts: true, thinkingBudget };
|
|
9843
|
+
}
|
|
9844
|
+
return void 0;
|
|
9845
|
+
}
|
|
9846
|
+
|
|
9847
|
+
// plugins/kxm/src/providers/antigravity/utils/util.ts
|
|
9848
|
+
function antigravityEnv(name) {
|
|
9849
|
+
return process.env[`ANTIGRAVITY_${name}`] || process.env[`NOAGY_${name}`];
|
|
9850
|
+
}
|
|
9851
|
+
function isRecord2(value) {
|
|
9852
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9853
|
+
}
|
|
9854
|
+
function asString(value) {
|
|
9855
|
+
return typeof value === "string" && value ? value : void 0;
|
|
9856
|
+
}
|
|
9857
|
+
function sanitizeText(text) {
|
|
9858
|
+
return String(text ?? "").replace(/[\uD800-\uDFFF]/g, "\uFFFD");
|
|
9859
|
+
}
|
|
9860
|
+
function escapeHtml(text) {
|
|
9861
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
9862
|
+
}
|
|
9863
|
+
function escapeRegExp(text) {
|
|
9864
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9865
|
+
}
|
|
9866
|
+
function stableUuid(seed) {
|
|
9867
|
+
const bytes = createHash3("sha1").update(seed).digest().subarray(0, 16);
|
|
9868
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
9869
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
9870
|
+
const hex = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
9871
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
9872
|
+
}
|
|
9873
|
+
var sessionTrajectoryMap = /* @__PURE__ */ new Map();
|
|
9874
|
+
function resolveSessionTrajectory(context) {
|
|
9875
|
+
const firstMsg = context?.messages?.[0];
|
|
9876
|
+
if (!firstMsg) {
|
|
9877
|
+
return { conversationId: crypto.randomUUID(), trajectoryId: crypto.randomUUID() };
|
|
9878
|
+
}
|
|
9879
|
+
const contentSeed = typeof firstMsg.content === "string" ? firstMsg.content.slice(0, 64) : Array.isArray(firstMsg.content) ? JSON.stringify(firstMsg.content[0] ?? "").slice(0, 64) : "";
|
|
9880
|
+
const seed = `${firstMsg.role || "user"}:${firstMsg.timestamp || ""}:${contentSeed}`;
|
|
9881
|
+
let entry = sessionTrajectoryMap.get(seed);
|
|
9882
|
+
if (!entry) {
|
|
9883
|
+
entry = {
|
|
9884
|
+
conversationId: stableUuid(`antigravity:conv:${seed}`),
|
|
9885
|
+
trajectoryId: stableUuid(`antigravity:traj:${seed}`)
|
|
9886
|
+
};
|
|
9887
|
+
sessionTrajectoryMap.set(seed, entry);
|
|
9888
|
+
if (sessionTrajectoryMap.size > 64) {
|
|
9889
|
+
const oldestKey = sessionTrajectoryMap.keys().next().value;
|
|
9890
|
+
if (oldestKey !== void 0) sessionTrajectoryMap.delete(oldestKey);
|
|
9891
|
+
}
|
|
9892
|
+
}
|
|
9893
|
+
return entry;
|
|
9894
|
+
}
|
|
9895
|
+
function antigravityRequestEnvelope(wireModelId, optionsOrIsClaude = false) {
|
|
9896
|
+
const options = typeof optionsOrIsClaude === "boolean" ? { isClaude: optionsOrIsClaude } : optionsOrIsClaude;
|
|
9897
|
+
const isClaude = Boolean(options.isClaude);
|
|
9898
|
+
const isNonGemini = Boolean(options.isNonGemini || isClaude);
|
|
9899
|
+
const step = Math.max(1, options.step ?? 1);
|
|
9900
|
+
const lastStepIndex = options.lastStepIndex ?? String(Math.max(0, step - 1));
|
|
9901
|
+
const requestIndex = options.requestIndex ?? options.userTurnIndex ?? Math.max(0, step - 1);
|
|
9902
|
+
const agentId = options.conversationId || crypto.randomUUID();
|
|
9903
|
+
const trajectoryId = options.trajectoryId || crypto.randomUUID();
|
|
9904
|
+
const bytes = crypto.getRandomValues(new Uint8Array(8));
|
|
9905
|
+
const sessionId = String(new DataView(bytes.buffer, bytes.byteOffset, 8).getBigInt64(0, true));
|
|
9906
|
+
const claudeLabel = isClaude ? "true" : "false";
|
|
9907
|
+
const nonGeminiLabel = isNonGemini ? "true" : "false";
|
|
9908
|
+
const labels = {
|
|
9909
|
+
last_step_index: lastStepIndex,
|
|
9910
|
+
request_id: `${trajectoryId}-${requestIndex}`,
|
|
9911
|
+
trajectory_id: trajectoryId,
|
|
9912
|
+
used_claude: claudeLabel,
|
|
9913
|
+
used_claude_conservative: claudeLabel,
|
|
9914
|
+
used_non_gemini_model: nonGeminiLabel
|
|
9915
|
+
};
|
|
9916
|
+
const modelEnum = getModelEnum(wireModelId);
|
|
9917
|
+
if (modelEnum) {
|
|
9918
|
+
labels.model_enum = modelEnum;
|
|
9919
|
+
}
|
|
9920
|
+
return {
|
|
9921
|
+
requestId: `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`,
|
|
9922
|
+
sessionId,
|
|
9923
|
+
labels
|
|
9924
|
+
};
|
|
9925
|
+
}
|
|
9926
|
+
|
|
9927
|
+
// plugins/kxm/src/providers/antigravity/utils/security.ts
|
|
9928
|
+
var LOOPBACK_HOSTS2 = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
|
|
9929
|
+
var ALLOWED_API_HOST_SUFFIXES = [".googleapis.com", ".sandbox.googleapis.com"];
|
|
9930
|
+
function resolveCallbackHost(raw = antigravityEnv("CALLBACK_HOST")) {
|
|
9931
|
+
const host = (raw || "127.0.0.1").trim().toLowerCase();
|
|
9932
|
+
if (!LOOPBACK_HOSTS2.has(host)) {
|
|
9933
|
+
throw new Error(
|
|
9934
|
+
`Unsafe ANTIGRAVITY_CALLBACK_HOST="${host}". Only loopback hosts are allowed: 127.0.0.1, ::1, localhost.`
|
|
9935
|
+
);
|
|
9936
|
+
}
|
|
9937
|
+
return host === "localhost" ? "127.0.0.1" : host;
|
|
9938
|
+
}
|
|
9939
|
+
function assertSafeApiBaseUrl(raw) {
|
|
9940
|
+
let url;
|
|
9941
|
+
try {
|
|
9942
|
+
url = new URL(raw);
|
|
9943
|
+
} catch {
|
|
9944
|
+
throw new Error(`Invalid ANTIGRAVITY_BASE_URL: ${raw}`);
|
|
9945
|
+
}
|
|
9946
|
+
if (url.protocol !== "https:") {
|
|
9947
|
+
throw new Error(`ANTIGRAVITY_BASE_URL must use https (got ${url.protocol})`);
|
|
9948
|
+
}
|
|
9949
|
+
if (url.username || url.password) {
|
|
9950
|
+
throw new Error("ANTIGRAVITY_BASE_URL must not include credentials");
|
|
9951
|
+
}
|
|
9952
|
+
const host = url.hostname.toLowerCase();
|
|
9953
|
+
const allowed = host === "googleapis.com" || ALLOWED_API_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix));
|
|
9954
|
+
if (!allowed) {
|
|
9955
|
+
throw new Error(
|
|
9956
|
+
`ANTIGRAVITY_BASE_URL host "${host}" is not allowed. Use a *.googleapis.com endpoint.`
|
|
9957
|
+
);
|
|
9958
|
+
}
|
|
9959
|
+
const path = url.pathname.replace(/\/+$/, "");
|
|
9960
|
+
return `${url.origin}${path === "/" ? "" : path}`;
|
|
9961
|
+
}
|
|
9962
|
+
function redactSecrets2(text) {
|
|
9963
|
+
return text.replace(/\bya29\.[A-Za-z0-9._~+/-]+=*/g, "[redacted-access-token]").replace(/\b1\/\/[A-Za-z0-9_-]+/g, "[redacted-refresh-token]").replace(/\b1\/[A-Za-z0-9_-]{20,}/g, "[redacted-refresh-token]").replace(/\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi, "Bearer [redacted]").replace(
|
|
9964
|
+
/("?(?:access_token|refresh_token|id_token|token|client_secret|code_verifier|authorization)"?\s*[:=]\s*")[^"]*(")/gi,
|
|
9965
|
+
"$1[redacted]$2"
|
|
9966
|
+
).replace(
|
|
9967
|
+
/("?(?:access_token|refresh_token|id_token|token|client_secret|code_verifier|authorization)"?\s*[:=]\s*)[^\s&,}]+/gi,
|
|
9968
|
+
"$1[redacted]"
|
|
9969
|
+
);
|
|
9970
|
+
}
|
|
9971
|
+
function safeError(error) {
|
|
9972
|
+
const raw = error instanceof Error ? error.message : String(error);
|
|
9973
|
+
return redactSecrets2(raw);
|
|
9974
|
+
}
|
|
9975
|
+
|
|
9976
|
+
// plugins/kxm/src/providers/antigravity/diagnostics/diagnostics.ts
|
|
9977
|
+
var storage = new AsyncLocalStorage();
|
|
9978
|
+
var lastSnapshot = {};
|
|
9979
|
+
function currentBag() {
|
|
9980
|
+
return storage.getStore() ?? lastSnapshot;
|
|
9981
|
+
}
|
|
9982
|
+
async function runWithDiagnostics(fn) {
|
|
9983
|
+
const bag = {};
|
|
9984
|
+
return storage.run(bag, async () => {
|
|
9985
|
+
try {
|
|
9986
|
+
return await fn();
|
|
9987
|
+
} finally {
|
|
9988
|
+
lastSnapshot = { ...bag };
|
|
9989
|
+
}
|
|
9990
|
+
});
|
|
9991
|
+
}
|
|
9992
|
+
function getCurrentEndpoint() {
|
|
9993
|
+
return currentBag().endpoint;
|
|
9994
|
+
}
|
|
9995
|
+
function getCurrentMatchedModelDebug() {
|
|
9996
|
+
return currentBag().matchedModelDebug;
|
|
9997
|
+
}
|
|
9998
|
+
function getCurrentAvailableModels() {
|
|
9999
|
+
return currentBag().availableModels;
|
|
10000
|
+
}
|
|
10001
|
+
function setLastStatus(status) {
|
|
10002
|
+
currentBag().status = status;
|
|
10003
|
+
}
|
|
10004
|
+
function setLastEndpoint(endpoint) {
|
|
10005
|
+
currentBag().endpoint = endpoint;
|
|
10006
|
+
}
|
|
10007
|
+
function setLastError(error) {
|
|
10008
|
+
currentBag().error = error === void 0 ? void 0 : redactSecrets2(error).slice(0, 800);
|
|
10009
|
+
}
|
|
10010
|
+
function setLastProjectId(projectId) {
|
|
10011
|
+
currentBag().projectId = projectId;
|
|
10012
|
+
}
|
|
10013
|
+
function setLastResolvedRuntimeModel(model) {
|
|
10014
|
+
currentBag().resolvedRuntimeModel = model;
|
|
10015
|
+
}
|
|
10016
|
+
function setLastAvailableModels(models) {
|
|
10017
|
+
currentBag().availableModels = models;
|
|
10018
|
+
}
|
|
10019
|
+
function setLastMatchedModelDebug(debug) {
|
|
10020
|
+
currentBag().matchedModelDebug = debug === void 0 ? void 0 : redactSecrets2(debug).slice(0, 1200);
|
|
10021
|
+
}
|
|
10022
|
+
function setLastLatencyMs(ms) {
|
|
10023
|
+
currentBag().latencyMs = ms;
|
|
10024
|
+
}
|
|
10025
|
+
function setLastToolSchemaWarnings(warnings) {
|
|
10026
|
+
currentBag().toolSchemaWarnings = warnings === void 0 ? void 0 : redactSecrets2(warnings.join(" | ")).slice(0, 1200);
|
|
10027
|
+
}
|
|
10028
|
+
|
|
10029
|
+
// plugins/kxm/src/providers/antigravity/utils/http.ts
|
|
10030
|
+
var PREWARM_TIMEOUT_MS = 5e3;
|
|
10031
|
+
async function antigravityFetch(input, init = {}) {
|
|
10032
|
+
return fetch(input, init);
|
|
10033
|
+
}
|
|
10034
|
+
function prewarmConnection(url) {
|
|
10035
|
+
if (antigravityEnv("NO_PREWARM") === "1") return;
|
|
10036
|
+
if (process.env.NODE_TEST_CONTEXT) return;
|
|
10037
|
+
void (async () => {
|
|
10038
|
+
try {
|
|
10039
|
+
const res = await antigravityFetch(url, {
|
|
10040
|
+
method: "HEAD",
|
|
10041
|
+
signal: AbortSignal.timeout(PREWARM_TIMEOUT_MS)
|
|
10042
|
+
});
|
|
10043
|
+
await res.arrayBuffer();
|
|
10044
|
+
} catch {
|
|
10045
|
+
}
|
|
10046
|
+
})();
|
|
10047
|
+
}
|
|
10048
|
+
|
|
10049
|
+
// plugins/kxm/src/providers/antigravity/client/client.ts
|
|
10050
|
+
var DEFAULT_ENDPOINT = "https://daily-cloudcode-pa.googleapis.com";
|
|
10051
|
+
var ENDPOINT_FALLBACKS = [
|
|
10052
|
+
DEFAULT_ENDPOINT,
|
|
10053
|
+
"https://daily-cloudcode-pa.sandbox.googleapis.com",
|
|
10054
|
+
"https://cloudcode-pa.googleapis.com"
|
|
10055
|
+
];
|
|
10056
|
+
var PROJECT_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
10057
|
+
var projectCache = /* @__PURE__ */ new Map();
|
|
10058
|
+
var MODEL_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
10059
|
+
var modelCache = /* @__PURE__ */ new Map();
|
|
10060
|
+
var DISCOVERY_TIMEOUT_MS = 8e3;
|
|
10061
|
+
var inFlightModelLookups = /* @__PURE__ */ new Map();
|
|
10062
|
+
function stableProjectId(seed) {
|
|
10063
|
+
const bytes = createHash4("sha1").update(`antigravity:${seed}`).digest().subarray(0, 16);
|
|
10064
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
10065
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
10066
|
+
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
10067
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
10068
|
+
}
|
|
10069
|
+
function defaultProjectId(seed = "antigravity-default") {
|
|
10070
|
+
return antigravityEnv("PROJECT_ID")?.trim() || stableProjectId(seed);
|
|
10071
|
+
}
|
|
10072
|
+
var DEFAULT_PROJECT_ID = defaultProjectId();
|
|
10073
|
+
function endpointCandidates() {
|
|
10074
|
+
const explicit = antigravityEnv("BASE_URL")?.trim();
|
|
10075
|
+
return explicit ? [assertSafeApiBaseUrl(explicit)] : ENDPOINT_FALLBACKS;
|
|
10076
|
+
}
|
|
10077
|
+
var DEFAULT_USER_AGENT = "antigravity/cli/1.1.23 (aidev_client; os_type=linux; arch=amd64; cl=974125021; auth_method=consumer)";
|
|
10078
|
+
function defaultUserAgent() {
|
|
10079
|
+
return DEFAULT_USER_AGENT;
|
|
10080
|
+
}
|
|
10081
|
+
function antigravityHeaders(token) {
|
|
10082
|
+
return {
|
|
10083
|
+
Authorization: `Bearer ${token}`,
|
|
10084
|
+
"Content-Type": "application/json",
|
|
10085
|
+
"User-Agent": antigravityEnv("USER_AGENT") || defaultUserAgent()
|
|
10086
|
+
};
|
|
10087
|
+
}
|
|
10088
|
+
function jsonOrTextError(text) {
|
|
10089
|
+
try {
|
|
10090
|
+
const parsed = JSON.parse(text);
|
|
10091
|
+
if (parsed.error?.message) return parsed.error.message;
|
|
10092
|
+
} catch {
|
|
10093
|
+
}
|
|
10094
|
+
return text;
|
|
10095
|
+
}
|
|
10096
|
+
function parseApiKey(apiKeyRaw) {
|
|
10097
|
+
if (!apiKeyRaw) {
|
|
10098
|
+
throw new Error("No Antigravity OAuth credentials. Run /login antigravity.");
|
|
10099
|
+
}
|
|
10100
|
+
try {
|
|
10101
|
+
const parsed = JSON.parse(apiKeyRaw);
|
|
10102
|
+
if (!parsed.token || !parsed.projectId) throw new Error("missing token or projectId");
|
|
10103
|
+
return { token: parsed.token, projectId: parsed.projectId };
|
|
10104
|
+
} catch (error) {
|
|
10105
|
+
throw new Error(
|
|
10106
|
+
`Invalid Antigravity credentials. Run /login antigravity. (${safeError(error)})`,
|
|
10107
|
+
{ cause: error }
|
|
10108
|
+
);
|
|
10109
|
+
}
|
|
10110
|
+
}
|
|
10111
|
+
function extractProjectId(data) {
|
|
10112
|
+
if (!isRecord2(data)) return void 0;
|
|
10113
|
+
const direct = data.antigravityProjectId ?? data.projectId ?? data.backendProjectId ?? data.userDefinedCloudaicompanionProject ?? data.cloudaicompanionProject ?? data.project;
|
|
10114
|
+
const directId = asString(direct);
|
|
10115
|
+
if (directId) return directId;
|
|
10116
|
+
if (isRecord2(direct)) {
|
|
10117
|
+
const nestedId = asString(direct.id);
|
|
10118
|
+
if (nestedId) return nestedId;
|
|
10119
|
+
}
|
|
10120
|
+
for (const key of ["projects", "projectIds", "cloudaicompanionProjects"]) {
|
|
10121
|
+
const value = data[key];
|
|
10122
|
+
if (Array.isArray(value)) {
|
|
10123
|
+
for (const item of value) {
|
|
10124
|
+
const nested = extractProjectId(item);
|
|
10125
|
+
if (nested) return nested;
|
|
10126
|
+
const itemId = asString(item);
|
|
10127
|
+
if (itemId) return itemId;
|
|
10128
|
+
}
|
|
10129
|
+
}
|
|
10130
|
+
}
|
|
10131
|
+
return void 0;
|
|
10132
|
+
}
|
|
10133
|
+
async function listCloudAICompanionProjects(token) {
|
|
10134
|
+
for (const endpoint of endpointCandidates()) {
|
|
10135
|
+
try {
|
|
10136
|
+
const res = await antigravityFetch(`${endpoint}/v1internal:listCloudAICompanionProjects`, {
|
|
10137
|
+
method: "POST",
|
|
10138
|
+
headers: antigravityHeaders(token),
|
|
10139
|
+
body: JSON.stringify({}),
|
|
10140
|
+
signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)
|
|
10141
|
+
});
|
|
10142
|
+
setLastStatus(res.status);
|
|
10143
|
+
setLastEndpoint(endpoint);
|
|
10144
|
+
if (!res.ok) continue;
|
|
10145
|
+
return extractProjectId(await res.json());
|
|
10146
|
+
} catch (error) {
|
|
10147
|
+
setLastError(safeError(error));
|
|
10148
|
+
}
|
|
10149
|
+
}
|
|
10150
|
+
return void 0;
|
|
10151
|
+
}
|
|
10152
|
+
function collectModelLabels(value, out = []) {
|
|
10153
|
+
if (!value || out.length > 50) return out;
|
|
10154
|
+
if (typeof value === "string") {
|
|
10155
|
+
if (/gemini|claude|gpt-oss/i.test(value)) out.push(value);
|
|
10156
|
+
return out;
|
|
10157
|
+
}
|
|
10158
|
+
if (Array.isArray(value)) {
|
|
10159
|
+
for (const item of value) collectModelLabels(item, out);
|
|
10160
|
+
return out;
|
|
10161
|
+
}
|
|
10162
|
+
if (isRecord2(value)) {
|
|
10163
|
+
for (const key of ["id", "name", "label", "displayName", "model", "modelId"]) {
|
|
10164
|
+
collectModelLabels(value[key], out);
|
|
10165
|
+
}
|
|
10166
|
+
for (const nested of Object.values(value)) {
|
|
10167
|
+
if (nested && typeof nested === "object") collectModelLabels(nested, out);
|
|
10168
|
+
}
|
|
10169
|
+
}
|
|
10170
|
+
return out;
|
|
10171
|
+
}
|
|
10172
|
+
function summarizeModelCandidate(value) {
|
|
10173
|
+
if (!isRecord2(value)) return String(value ?? "none");
|
|
10174
|
+
const out = {};
|
|
10175
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
10176
|
+
if (/token|auth|credential|secret|email/i.test(key)) continue;
|
|
10177
|
+
if (raw === null || ["string", "number", "boolean"].includes(typeof raw)) out[key] = raw;
|
|
10178
|
+
else if (Array.isArray(raw)) out[key] = `[array:${String(raw.length)}]`;
|
|
10179
|
+
else if (isRecord2(raw)) {
|
|
10180
|
+
out[key] = `{${Object.keys(raw).slice(0, 12).join(",")}}`;
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
10183
|
+
return JSON.stringify(out).slice(0, 1200);
|
|
10184
|
+
}
|
|
10185
|
+
function isUsableRuntimeModelId(id) {
|
|
10186
|
+
return /^(gemini-|claude-|gpt-oss-)/i.test(id) && !/\s/.test(id) && !/^MODEL_/i.test(id);
|
|
10187
|
+
}
|
|
10188
|
+
function buildModelMatchRegex(requestedId) {
|
|
10189
|
+
const req = requestedId.toLowerCase();
|
|
10190
|
+
if (req === "gemini-3.8-flash-low") return /gemini[- ]3\.8[- ]flash \(low\)/i;
|
|
10191
|
+
if (req === "gemini-3.8-flash-medium") return /gemini[- ]3\.8[- ]flash \(medium\)/i;
|
|
10192
|
+
if (req === "gemini-3.8-flash-high") return /gemini[- ]3\.8[- ]flash \(high\)/i;
|
|
10193
|
+
if (req === "gemini-3.7-flash-low") return /gemini[- ]3\.7[- ]flash \(low\)/i;
|
|
10194
|
+
if (req === "gemini-3.7-flash-medium") return /gemini[- ]3\.7[- ]flash \(medium\)/i;
|
|
10195
|
+
if (req === "gemini-3.7-flash-high") return /gemini[- ]3\.7[- ]flash \(high\)/i;
|
|
10196
|
+
if (req === "gemini-3.6-flash-low") return /gemini[- ]3\.6[- ]flash \(low\)/i;
|
|
10197
|
+
if (req === "gemini-3.6-flash-medium") return /gemini[- ]3\.6[- ]flash \(medium\)/i;
|
|
10198
|
+
if (req === "gemini-3.6-flash-high") return /gemini[- ]3\.6[- ]flash \(high\)/i;
|
|
10199
|
+
if (req === "gemini-3.5-flash-extra-low") return /gemini[- ]3\.5[- ]flash \(low\)/i;
|
|
10200
|
+
if (req === "gemini-3.5-flash-low" || req === "gemini-3.5-flash-medium")
|
|
10201
|
+
return /gemini[- ]3\.5[- ]flash \(medium\)/i;
|
|
10202
|
+
if (req === "gemini-3.5-flash-high" || req === "gemini-3-flash-agent")
|
|
10203
|
+
return /gemini[- ]3\.5[- ]flash \(high\)/i;
|
|
10204
|
+
if (req.includes("claude-opus-4-6")) return /claude.*opus.*4\.6/i;
|
|
10205
|
+
if (req.includes("claude-sonnet-4-6")) return /claude.*sonnet.*4\.6/i;
|
|
10206
|
+
if (req.includes("gpt-oss-120b")) return /gpt.*oss.*120b/i;
|
|
10207
|
+
if (req === "gemini-3.1-pro-low") return /gemini[- ]3\.1[- ]pro \(low\)/i;
|
|
10208
|
+
if (req === "gemini-3.1-pro-high" || req === "gemini-pro-agent")
|
|
10209
|
+
return /gemini[- ]3\.1[- ]pro \(high\)/i;
|
|
10210
|
+
const escaped = escapeRegExp(req).replace(/\\-/g, "[- ]");
|
|
10211
|
+
return new RegExp(escaped, "i");
|
|
10212
|
+
}
|
|
10213
|
+
function dynamicModelFromInfo(modelId, info) {
|
|
10214
|
+
if (!isRecord2(info)) return { id: modelId };
|
|
10215
|
+
setLastMatchedModelDebug(summarizeModelCandidate({ modelId, ...info }));
|
|
10216
|
+
const experiments = Array.isArray(info.modelExperiments) ? info.modelExperiments.filter((item) => typeof item === "string") : void 0;
|
|
10217
|
+
const modelEnum = asString(info.model);
|
|
10218
|
+
if (modelEnum) {
|
|
10219
|
+
registerModelEnum(modelId, modelEnum);
|
|
10220
|
+
}
|
|
10221
|
+
return {
|
|
10222
|
+
id: modelId,
|
|
10223
|
+
experiments,
|
|
10224
|
+
apiProvider: asString(info.apiProvider),
|
|
10225
|
+
modelProvider: asString(info.modelProvider),
|
|
10226
|
+
model: modelEnum
|
|
10227
|
+
};
|
|
10228
|
+
}
|
|
10229
|
+
function findDynamicModel(value, requestedId) {
|
|
10230
|
+
if (!value) return void 0;
|
|
10231
|
+
if (isRecord2(value) && isRecord2(value.models)) {
|
|
10232
|
+
const modelsMap = value.models;
|
|
10233
|
+
if (isUsableRuntimeModelId(requestedId) && requestedId in modelsMap) {
|
|
10234
|
+
return dynamicModelFromInfo(requestedId, modelsMap[requestedId]);
|
|
10235
|
+
}
|
|
10236
|
+
const targetRegex2 = buildModelMatchRegex(requestedId);
|
|
10237
|
+
for (const [modelId, info] of Object.entries(modelsMap)) {
|
|
10238
|
+
if (!isUsableRuntimeModelId(modelId)) continue;
|
|
10239
|
+
if (targetRegex2.test(modelId)) return dynamicModelFromInfo(modelId, info);
|
|
10240
|
+
if (isRecord2(info)) {
|
|
10241
|
+
const label = info.label ?? info.displayName ?? info.name;
|
|
10242
|
+
if (typeof label === "string" && targetRegex2.test(label)) {
|
|
10243
|
+
return dynamicModelFromInfo(modelId, info);
|
|
10244
|
+
}
|
|
10245
|
+
}
|
|
10246
|
+
}
|
|
10247
|
+
return void 0;
|
|
10248
|
+
}
|
|
10249
|
+
const targetRegex = buildModelMatchRegex(requestedId);
|
|
10250
|
+
if (typeof value === "string") {
|
|
10251
|
+
return targetRegex.test(value) && isUsableRuntimeModelId(value) ? { id: value } : void 0;
|
|
10252
|
+
}
|
|
10253
|
+
if (Array.isArray(value)) {
|
|
10254
|
+
for (const item of value) {
|
|
10255
|
+
const found = findDynamicModel(item, requestedId);
|
|
10256
|
+
if (found) return found;
|
|
10257
|
+
}
|
|
10258
|
+
return void 0;
|
|
10259
|
+
}
|
|
10260
|
+
if (isRecord2(value)) {
|
|
10261
|
+
for (const nested of Object.values(value)) {
|
|
10262
|
+
if (nested && typeof nested === "object") {
|
|
10263
|
+
const found = findDynamicModel(nested, requestedId);
|
|
10264
|
+
if (found) return found;
|
|
10265
|
+
}
|
|
10266
|
+
}
|
|
10267
|
+
}
|
|
10268
|
+
return void 0;
|
|
10269
|
+
}
|
|
10270
|
+
async function fetchAvailableRuntimeModelUncached(token, projectId, requestedRuntimeModel) {
|
|
10271
|
+
const body = JSON.stringify({ project: projectId });
|
|
10272
|
+
const endpoints = endpointCandidates();
|
|
10273
|
+
let lastLabels = "";
|
|
10274
|
+
for (const endpoint of endpoints) {
|
|
10275
|
+
try {
|
|
10276
|
+
const res = await antigravityFetch(`${endpoint}/v1internal:fetchAvailableModels`, {
|
|
10277
|
+
method: "POST",
|
|
10278
|
+
headers: antigravityHeaders(token),
|
|
10279
|
+
body,
|
|
10280
|
+
signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)
|
|
10281
|
+
});
|
|
10282
|
+
setLastStatus(res.status);
|
|
10283
|
+
if (!res.ok) continue;
|
|
10284
|
+
setLastEndpoint(endpoint);
|
|
10285
|
+
const data = await res.json();
|
|
10286
|
+
if (isRecord2(data) && isRecord2(data.models)) {
|
|
10287
|
+
registerDiscoveredModelEnums(data.models);
|
|
10288
|
+
}
|
|
10289
|
+
const labels = [...new Set(collectModelLabels(data))].slice(0, 16);
|
|
10290
|
+
if (labels.length) lastLabels = labels.join(",");
|
|
10291
|
+
const found = findDynamicModel(data, requestedRuntimeModel);
|
|
10292
|
+
if (found) {
|
|
10293
|
+
if (lastLabels) setLastAvailableModels(lastLabels);
|
|
10294
|
+
return found;
|
|
10295
|
+
}
|
|
10296
|
+
} catch (error) {
|
|
10297
|
+
setLastError(safeError(error));
|
|
10298
|
+
}
|
|
10299
|
+
}
|
|
10300
|
+
if (lastLabels) setLastAvailableModels(lastLabels);
|
|
10301
|
+
return void 0;
|
|
10302
|
+
}
|
|
10303
|
+
async function fetchAvailableRuntimeModel(token, projectId, requestedRuntimeModel) {
|
|
10304
|
+
const cacheKey = `${token}::${projectId}::${requestedRuntimeModel}`;
|
|
10305
|
+
const cached = modelCache.get(cacheKey);
|
|
10306
|
+
if (cached && cached.expiresAt > Date.now()) return cached.result;
|
|
10307
|
+
const inFlight = inFlightModelLookups.get(cacheKey);
|
|
10308
|
+
if (inFlight) return inFlight;
|
|
10309
|
+
const promise = fetchAvailableRuntimeModelUncached(token, projectId, requestedRuntimeModel).then(
|
|
10310
|
+
(result2) => {
|
|
10311
|
+
modelCache.set(cacheKey, { result: result2, expiresAt: Date.now() + MODEL_CACHE_TTL_MS });
|
|
10312
|
+
return result2;
|
|
10313
|
+
}
|
|
10314
|
+
);
|
|
10315
|
+
inFlightModelLookups.set(cacheKey, promise);
|
|
10316
|
+
try {
|
|
10317
|
+
return await promise;
|
|
10318
|
+
} finally {
|
|
10319
|
+
inFlightModelLookups.delete(cacheKey);
|
|
10320
|
+
if (modelCache.size > 64) {
|
|
10321
|
+
const now = Date.now();
|
|
10322
|
+
for (const [key, entry] of modelCache) {
|
|
10323
|
+
if (entry.expiresAt <= now) modelCache.delete(key);
|
|
10324
|
+
}
|
|
10325
|
+
}
|
|
10326
|
+
}
|
|
10327
|
+
}
|
|
10328
|
+
async function fetchAvailableModelsFromEndpoint(endpoint, token, projectId, signal) {
|
|
10329
|
+
try {
|
|
10330
|
+
const res = await antigravityFetch(`${endpoint}/v1internal:fetchAvailableModels`, {
|
|
10331
|
+
method: "POST",
|
|
10332
|
+
headers: antigravityHeaders(token),
|
|
10333
|
+
body: JSON.stringify({ project: projectId }),
|
|
10334
|
+
signal: catalogSignal(signal)
|
|
10335
|
+
});
|
|
10336
|
+
const text = await res.text();
|
|
10337
|
+
let data;
|
|
10338
|
+
try {
|
|
10339
|
+
data = JSON.parse(text);
|
|
10340
|
+
} catch {
|
|
10341
|
+
data = { raw: text };
|
|
10342
|
+
}
|
|
10343
|
+
if (!res.ok) {
|
|
10344
|
+
const message = isRecord2(data) && isRecord2(data.error) && typeof data.error.message === "string" ? data.error.message : text;
|
|
10345
|
+
setLastError(message);
|
|
10346
|
+
return void 0;
|
|
10347
|
+
}
|
|
10348
|
+
return { endpoint, status: res.status, data };
|
|
10349
|
+
} catch (error) {
|
|
10350
|
+
setLastError(safeError(error));
|
|
10351
|
+
return void 0;
|
|
10352
|
+
}
|
|
10353
|
+
}
|
|
10354
|
+
function catalogSignal(signal) {
|
|
10355
|
+
const timeout = AbortSignal.timeout(DISCOVERY_TIMEOUT_MS);
|
|
10356
|
+
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
10357
|
+
}
|
|
10358
|
+
function mergeAvailableModelsResults(results) {
|
|
10359
|
+
const mergedModels = {};
|
|
10360
|
+
let defaultAgentModelId;
|
|
10361
|
+
let defaultAgentModel;
|
|
10362
|
+
let lastEndpoint = "";
|
|
10363
|
+
let lastStatus = 0;
|
|
10364
|
+
for (const result2 of results) {
|
|
10365
|
+
if (!result2) continue;
|
|
10366
|
+
setLastEndpoint(result2.endpoint);
|
|
10367
|
+
setLastStatus(result2.status);
|
|
10368
|
+
lastEndpoint = result2.endpoint;
|
|
10369
|
+
lastStatus = result2.status;
|
|
10370
|
+
const data = result2.data;
|
|
10371
|
+
if (isRecord2(data) && isRecord2(data.models)) {
|
|
10372
|
+
Object.assign(mergedModels, data.models);
|
|
10373
|
+
registerDiscoveredModelEnums(data.models);
|
|
10374
|
+
}
|
|
10375
|
+
if (isRecord2(data) && typeof data.defaultAgentModelId === "string") {
|
|
10376
|
+
defaultAgentModelId = data.defaultAgentModelId;
|
|
10377
|
+
}
|
|
10378
|
+
if (isRecord2(data) && typeof data.defaultAgentModel === "string") {
|
|
10379
|
+
defaultAgentModel = data.defaultAgentModel;
|
|
10380
|
+
}
|
|
10381
|
+
}
|
|
10382
|
+
if (!lastEndpoint) {
|
|
10383
|
+
throw new Error(`/v1internal:fetchAvailableModels failed: no endpoint available`);
|
|
10384
|
+
}
|
|
10385
|
+
return {
|
|
10386
|
+
endpoint: lastEndpoint,
|
|
10387
|
+
status: lastStatus,
|
|
10388
|
+
data: {
|
|
10389
|
+
models: mergedModels,
|
|
10390
|
+
defaultAgentModelId,
|
|
10391
|
+
defaultAgentModel
|
|
10392
|
+
}
|
|
10393
|
+
};
|
|
10394
|
+
}
|
|
10395
|
+
async function fetchAvailableModelsCatalog(token, projectId, signal) {
|
|
10396
|
+
const results = await Promise.all(
|
|
10397
|
+
endpointCandidates().map(
|
|
10398
|
+
(endpoint) => fetchAvailableModelsFromEndpoint(endpoint, token, projectId, signal)
|
|
10399
|
+
)
|
|
10400
|
+
);
|
|
10401
|
+
return mergeAvailableModelsResults(results);
|
|
10402
|
+
}
|
|
10403
|
+
async function loadCodeAssistUncached(token) {
|
|
10404
|
+
const body = JSON.stringify({
|
|
10405
|
+
metadata: {
|
|
10406
|
+
ideType: "ANTIGRAVITY"
|
|
10407
|
+
}
|
|
10408
|
+
});
|
|
10409
|
+
for (const endpoint of endpointCandidates()) {
|
|
10410
|
+
try {
|
|
10411
|
+
const res = await antigravityFetch(`${endpoint}/v1internal:loadCodeAssist`, {
|
|
10412
|
+
method: "POST",
|
|
10413
|
+
headers: antigravityHeaders(token),
|
|
10414
|
+
body,
|
|
10415
|
+
signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)
|
|
10416
|
+
});
|
|
10417
|
+
setLastStatus(res.status);
|
|
10418
|
+
setLastEndpoint(endpoint);
|
|
10419
|
+
if (!res.ok) continue;
|
|
10420
|
+
const project = extractProjectId(await res.json());
|
|
10421
|
+
if (project) return project;
|
|
10422
|
+
return await listCloudAICompanionProjects(token);
|
|
10423
|
+
} catch (error) {
|
|
10424
|
+
setLastError(safeError(error));
|
|
10425
|
+
}
|
|
10426
|
+
}
|
|
10427
|
+
return void 0;
|
|
10428
|
+
}
|
|
10429
|
+
async function loadCodeAssist(token) {
|
|
10430
|
+
const cached = projectCache.get(token);
|
|
10431
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
10432
|
+
projectCache.delete(token);
|
|
10433
|
+
projectCache.set(token, cached);
|
|
10434
|
+
return cached.projectId;
|
|
10435
|
+
}
|
|
10436
|
+
const projectId = await loadCodeAssistUncached(token);
|
|
10437
|
+
projectCache.set(token, { projectId, expiresAt: Date.now() + PROJECT_CACHE_TTL_MS });
|
|
10438
|
+
if (projectCache.size > 32) {
|
|
10439
|
+
const oldestKey = projectCache.keys().next().value;
|
|
10440
|
+
if (oldestKey !== void 0) projectCache.delete(oldestKey);
|
|
10441
|
+
}
|
|
10442
|
+
return projectId;
|
|
10443
|
+
}
|
|
10444
|
+
function resolveProjectId(opts) {
|
|
10445
|
+
return antigravityEnv("PROJECT_ID")?.trim() || opts.warmedProject || opts.credentialProjectId || defaultProjectId(opts.email || "antigravity-default");
|
|
10446
|
+
}
|
|
10447
|
+
function formatRequestDiagnostics(extra) {
|
|
10448
|
+
return `endpoint=${getCurrentEndpoint() || "unknown"}, project=${extra.projectId}, runtimeModel=${extra.runtimeModel}, matched=${getCurrentMatchedModelDebug() || "none"}, available=${getCurrentAvailableModels() || "unknown"}`;
|
|
10449
|
+
}
|
|
10450
|
+
|
|
10451
|
+
// plugins/kxm/src/providers/antigravity/auth/oauth.ts
|
|
10452
|
+
var REDIRECT_URI = "http://localhost:51121/oauth-callback";
|
|
10453
|
+
var AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
10454
|
+
var TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
10455
|
+
var OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
10456
|
+
var SCOPES = [
|
|
10457
|
+
"https://www.googleapis.com/auth/aicode",
|
|
10458
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
|
10459
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
10460
|
+
"https://www.googleapis.com/auth/userinfo.profile",
|
|
10461
|
+
"https://www.googleapis.com/auth/cclog",
|
|
10462
|
+
"https://www.googleapis.com/auth/experimentsandconfigs"
|
|
10463
|
+
];
|
|
10464
|
+
var CLIENT_ID = antigravityEnv("CLIENT_ID") || atob(
|
|
10465
|
+
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
|
|
10466
|
+
);
|
|
10467
|
+
var CLIENT_SECRET = antigravityEnv("CLIENT_SECRET") || atob("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
|
|
10468
|
+
var CALLBACK_HOST = resolveCallbackHost();
|
|
10469
|
+
function oauthCallbackHeaders(contentType = "text/html; charset=utf-8") {
|
|
10470
|
+
return {
|
|
10471
|
+
"Content-Type": contentType,
|
|
10472
|
+
"Cache-Control": "no-store",
|
|
10473
|
+
"X-Content-Type-Options": "nosniff",
|
|
10474
|
+
"Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'",
|
|
10475
|
+
"Referrer-Policy": "no-referrer"
|
|
10476
|
+
};
|
|
10477
|
+
}
|
|
10478
|
+
function sanitizeOAuthProviderError(text) {
|
|
10479
|
+
const redacted = redactSecrets2(text).trim();
|
|
10480
|
+
try {
|
|
10481
|
+
const parsed = JSON.parse(redacted);
|
|
10482
|
+
const parts = [parsed.error, parsed.error_description].filter(
|
|
10483
|
+
(part) => typeof part === "string" && part.length > 0
|
|
10484
|
+
);
|
|
10485
|
+
if (parts.length) return parts.join(": ").slice(0, 300);
|
|
10486
|
+
} catch {
|
|
10487
|
+
}
|
|
10488
|
+
return redacted.slice(0, 300) || "unknown OAuth provider error";
|
|
10489
|
+
}
|
|
10490
|
+
function base64Url(buffer) {
|
|
10491
|
+
return buffer.toString("base64url");
|
|
10492
|
+
}
|
|
10493
|
+
function generatePKCE() {
|
|
10494
|
+
const verifier = base64Url(randomBytes(32));
|
|
10495
|
+
const challenge = base64Url(createHash5("sha256").update(verifier).digest());
|
|
10496
|
+
return { verifier, challenge };
|
|
10497
|
+
}
|
|
10498
|
+
function buildAuthorizationUrl(challenge, state) {
|
|
10499
|
+
const authParams = new URLSearchParams({
|
|
10500
|
+
client_id: CLIENT_ID,
|
|
10501
|
+
response_type: "code",
|
|
10502
|
+
redirect_uri: REDIRECT_URI,
|
|
10503
|
+
scope: SCOPES.join(" "),
|
|
10504
|
+
code_challenge: challenge,
|
|
10505
|
+
code_challenge_method: "S256",
|
|
10506
|
+
state,
|
|
10507
|
+
access_type: "offline",
|
|
10508
|
+
prompt: "consent"
|
|
10509
|
+
});
|
|
10510
|
+
return `${AUTH_URL}?${authParams.toString()}`;
|
|
10511
|
+
}
|
|
10512
|
+
async function getUserEmail(token) {
|
|
10513
|
+
try {
|
|
10514
|
+
const res = await fetch("https://www.googleapis.com/oauth2/v1/userinfo?alt=json", {
|
|
10515
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
10516
|
+
});
|
|
10517
|
+
if (!res.ok) return void 0;
|
|
10518
|
+
const data = await res.json();
|
|
10519
|
+
return data.email;
|
|
10520
|
+
} catch {
|
|
10521
|
+
return void 0;
|
|
10522
|
+
}
|
|
10523
|
+
}
|
|
10524
|
+
function closeServerGracefully(server) {
|
|
10525
|
+
if ("closeAllConnections" in server && typeof server.closeAllConnections === "function") {
|
|
10526
|
+
server.closeAllConnections();
|
|
10527
|
+
}
|
|
10528
|
+
server.close();
|
|
10529
|
+
}
|
|
10530
|
+
function startCallbackServer(expectedState) {
|
|
10531
|
+
return new Promise((resolve5, reject) => {
|
|
10532
|
+
let settled = false;
|
|
10533
|
+
let timeout;
|
|
10534
|
+
let resolveCode;
|
|
10535
|
+
let rejectCode;
|
|
10536
|
+
const codePromise = new Promise((res, rej) => {
|
|
10537
|
+
resolveCode = res;
|
|
10538
|
+
rejectCode = rej;
|
|
10539
|
+
});
|
|
10540
|
+
const finish = (fn) => {
|
|
10541
|
+
if (settled) return;
|
|
10542
|
+
settled = true;
|
|
10543
|
+
if (timeout) clearTimeout(timeout);
|
|
10544
|
+
fn();
|
|
10545
|
+
};
|
|
10546
|
+
const server = createServer((req, res) => {
|
|
10547
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
10548
|
+
res.writeHead(405, oauthCallbackHeaders("text/plain; charset=utf-8"));
|
|
10549
|
+
res.end("Method Not Allowed");
|
|
10550
|
+
return;
|
|
10551
|
+
}
|
|
10552
|
+
const url = new URL(req.url || "", REDIRECT_URI);
|
|
10553
|
+
if (url.pathname !== "/oauth-callback") {
|
|
10554
|
+
res.writeHead(404, oauthCallbackHeaders());
|
|
10555
|
+
res.end("Antigravity OAuth callback route not found.");
|
|
10556
|
+
return;
|
|
10557
|
+
}
|
|
10558
|
+
const error = url.searchParams.get("error");
|
|
10559
|
+
const code = url.searchParams.get("code");
|
|
10560
|
+
const state = url.searchParams.get("state");
|
|
10561
|
+
if (error) {
|
|
10562
|
+
const safe = escapeHtml(error.slice(0, 200));
|
|
10563
|
+
res.writeHead(400, oauthCallbackHeaders());
|
|
10564
|
+
res.end(`Antigravity authentication failed: ${safe}`);
|
|
10565
|
+
finish(() => rejectCode(new Error(`OAuth error: ${error.slice(0, 200)}`)));
|
|
10566
|
+
return;
|
|
10567
|
+
}
|
|
10568
|
+
if (!code || !state) {
|
|
10569
|
+
res.writeHead(400, oauthCallbackHeaders());
|
|
10570
|
+
res.end("Antigravity authentication failed: missing code or state.");
|
|
10571
|
+
finish(() => rejectCode(new Error("Missing code or state in OAuth callback")));
|
|
10572
|
+
return;
|
|
10573
|
+
}
|
|
10574
|
+
if (state !== expectedState) {
|
|
10575
|
+
res.writeHead(400, oauthCallbackHeaders());
|
|
10576
|
+
res.end("Antigravity authentication failed: invalid state.");
|
|
10577
|
+
finish(() => rejectCode(new Error("OAuth state mismatch")));
|
|
10578
|
+
return;
|
|
10579
|
+
}
|
|
10580
|
+
res.writeHead(200, oauthCallbackHeaders());
|
|
10581
|
+
res.end("Antigravity authentication complete. You can close this window and return to Pi.");
|
|
10582
|
+
finish(() => resolveCode({ code, state }));
|
|
10583
|
+
});
|
|
10584
|
+
server.on("error", (err) => {
|
|
10585
|
+
if (err.code === "EADDRINUSE") {
|
|
10586
|
+
reject(
|
|
10587
|
+
new Error(
|
|
10588
|
+
"Port 51121 is already in use by another process. Please close the process using port 51121 and retry /login antigravity."
|
|
10589
|
+
)
|
|
10590
|
+
);
|
|
10591
|
+
} else {
|
|
10592
|
+
reject(err);
|
|
10593
|
+
}
|
|
10594
|
+
});
|
|
10595
|
+
let closed = false;
|
|
10596
|
+
const close = () => {
|
|
10597
|
+
if (closed) return;
|
|
10598
|
+
closed = true;
|
|
10599
|
+
closeServerGracefully(server);
|
|
10600
|
+
};
|
|
10601
|
+
const cleanup = () => {
|
|
10602
|
+
finish(() => rejectCode(new Error("OAuth callback cancelled")));
|
|
10603
|
+
close();
|
|
10604
|
+
};
|
|
10605
|
+
server.listen(51121, CALLBACK_HOST, () => {
|
|
10606
|
+
timeout = setTimeout(() => {
|
|
10607
|
+
finish(() => rejectCode(new Error("OAuth callback timed out waiting for browser login")));
|
|
10608
|
+
close();
|
|
10609
|
+
}, OAUTH_CALLBACK_TIMEOUT_MS);
|
|
10610
|
+
resolve5({ server, waitForCode: () => codePromise, cleanup });
|
|
10611
|
+
});
|
|
10612
|
+
});
|
|
10613
|
+
}
|
|
10614
|
+
function credentialProjectId(credentials) {
|
|
10615
|
+
const projectId = credentials.projectId;
|
|
10616
|
+
return typeof projectId === "string" ? projectId : void 0;
|
|
10617
|
+
}
|
|
10618
|
+
function credentialEmail(credentials) {
|
|
10619
|
+
const email = credentials.email;
|
|
10620
|
+
return typeof email === "string" ? email : void 0;
|
|
10621
|
+
}
|
|
10622
|
+
function parsePastedCallback(raw, expectedState) {
|
|
10623
|
+
const text = (raw ?? "").trim();
|
|
10624
|
+
if (!text) {
|
|
10625
|
+
throw new Error(
|
|
10626
|
+
"No callback pasted. Paste the full URL from your browser's address bar (http://localhost:51121/oauth-callback?\u2026)."
|
|
10627
|
+
);
|
|
10628
|
+
}
|
|
10629
|
+
let url;
|
|
10630
|
+
try {
|
|
10631
|
+
url = new URL(text);
|
|
10632
|
+
} catch {
|
|
10633
|
+
const qs = text.startsWith("?") ? text.slice(1) : text;
|
|
10634
|
+
url = new URL(`http://localhost:51121/oauth-callback?${qs}`);
|
|
10635
|
+
}
|
|
10636
|
+
const error = url.searchParams.get("error");
|
|
10637
|
+
if (error) throw new Error(`OAuth error from browser: ${error.slice(0, 200)}`);
|
|
10638
|
+
const code = url.searchParams.get("code");
|
|
10639
|
+
const state = url.searchParams.get("state");
|
|
10640
|
+
if (!code || !state) {
|
|
10641
|
+
throw new Error(
|
|
10642
|
+
"Pasted text is missing 'code' or 'state'. Paste the FULL callback URL from your browser's address bar (http://localhost:51121/oauth-callback?\u2026)."
|
|
10643
|
+
);
|
|
10644
|
+
}
|
|
10645
|
+
if (state !== expectedState) {
|
|
10646
|
+
throw new Error(
|
|
10647
|
+
"State mismatch: that callback is from a different sign-in. Re-run /login antigravity, sign in again, and paste the new URL."
|
|
10648
|
+
);
|
|
10649
|
+
}
|
|
10650
|
+
return { code, state };
|
|
10651
|
+
}
|
|
10652
|
+
async function acquireAuthCode(expectedState, opts) {
|
|
10653
|
+
const { waitForCode, callbacks } = opts;
|
|
10654
|
+
const settle = new AbortController();
|
|
10655
|
+
const candidates = [waitForCode()];
|
|
10656
|
+
if (typeof callbacks.onPrompt === "function") {
|
|
10657
|
+
const promptLoop = async () => {
|
|
10658
|
+
let promptMessage = "Remote/headless machine (your browser can't reach localhost:51121)? After signing in, paste the full callback URL shown in your browser's address bar.";
|
|
10659
|
+
while (true) {
|
|
10660
|
+
if (callbacks.signal?.aborted || settle.signal.aborted) {
|
|
10661
|
+
throw new Error("Login cancelled");
|
|
10662
|
+
}
|
|
10663
|
+
let text;
|
|
10664
|
+
try {
|
|
10665
|
+
text = await callbacks.onPrompt({
|
|
10666
|
+
message: promptMessage,
|
|
10667
|
+
placeholder: "http://localhost:51121/oauth-callback?state=\u2026&code=\u2026"
|
|
10668
|
+
});
|
|
10669
|
+
} catch (err) {
|
|
10670
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
10671
|
+
}
|
|
10672
|
+
if (callbacks.signal?.aborted || settle.signal.aborted) {
|
|
10673
|
+
throw new Error("Login cancelled");
|
|
10674
|
+
}
|
|
10675
|
+
try {
|
|
10676
|
+
return parsePastedCallback(text, expectedState);
|
|
10677
|
+
} catch (err) {
|
|
10678
|
+
if (callbacks.signal?.aborted || settle.signal.aborted) {
|
|
10679
|
+
throw new Error("Login cancelled", { cause: err });
|
|
10680
|
+
}
|
|
10681
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
10682
|
+
promptMessage = `Invalid callback (${errorMessage}). Please paste the full URL:`;
|
|
10683
|
+
}
|
|
10684
|
+
}
|
|
10685
|
+
};
|
|
10686
|
+
candidates.push(promptLoop());
|
|
10687
|
+
}
|
|
10688
|
+
let removeAbortListener;
|
|
10689
|
+
if (callbacks.signal) {
|
|
10690
|
+
candidates.push(
|
|
10691
|
+
new Promise((_resolve, reject) => {
|
|
10692
|
+
const signal = callbacks.signal;
|
|
10693
|
+
if (signal.aborted) return reject(new Error("Login cancelled"));
|
|
10694
|
+
const onAbort = () => reject(new Error("Login cancelled"));
|
|
10695
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
10696
|
+
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
10697
|
+
})
|
|
10698
|
+
);
|
|
10699
|
+
}
|
|
10700
|
+
for (const candidate of candidates) {
|
|
10701
|
+
candidate.catch(() => {
|
|
10702
|
+
});
|
|
10703
|
+
}
|
|
10704
|
+
try {
|
|
10705
|
+
return await Promise.race(candidates);
|
|
10706
|
+
} finally {
|
|
10707
|
+
settle.abort();
|
|
10708
|
+
removeAbortListener?.();
|
|
10709
|
+
}
|
|
10710
|
+
}
|
|
10711
|
+
async function loginAntigravity(callbacks) {
|
|
10712
|
+
const { verifier, challenge } = generatePKCE();
|
|
10713
|
+
const state = base64Url(randomBytes(32));
|
|
10714
|
+
const { waitForCode, cleanup } = await startCallbackServer(state);
|
|
10715
|
+
try {
|
|
10716
|
+
callbacks.onAuth({
|
|
10717
|
+
url: buildAuthorizationUrl(challenge, state),
|
|
10718
|
+
instructions: "Complete Google sign-in. Pi captures the local callback automatically \u2014 or, on a remote/headless machine, paste the callback URL when prompted."
|
|
10719
|
+
});
|
|
10720
|
+
const { code, state: returnedState } = await acquireAuthCode(state, {
|
|
10721
|
+
waitForCode,
|
|
10722
|
+
callbacks
|
|
10723
|
+
});
|
|
10724
|
+
if (returnedState !== state) throw new Error("OAuth state mismatch");
|
|
10725
|
+
const tokenResponse = await fetch(TOKEN_URL, {
|
|
10726
|
+
method: "POST",
|
|
10727
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
10728
|
+
body: new URLSearchParams({
|
|
10729
|
+
client_id: CLIENT_ID,
|
|
10730
|
+
client_secret: CLIENT_SECRET,
|
|
10731
|
+
code,
|
|
10732
|
+
grant_type: "authorization_code",
|
|
10733
|
+
redirect_uri: REDIRECT_URI,
|
|
10734
|
+
code_verifier: verifier
|
|
10735
|
+
}).toString()
|
|
10736
|
+
});
|
|
10737
|
+
if (!tokenResponse.ok) {
|
|
10738
|
+
throw new Error(
|
|
10739
|
+
`Token exchange failed: ${sanitizeOAuthProviderError(await tokenResponse.text())}`
|
|
10740
|
+
);
|
|
10741
|
+
}
|
|
10742
|
+
const tokenData = await tokenResponse.json();
|
|
10743
|
+
if (!tokenData.refresh_token) {
|
|
10744
|
+
throw new Error(
|
|
10745
|
+
"No refresh token received. Re-run /login antigravity and allow offline access."
|
|
10746
|
+
);
|
|
10747
|
+
}
|
|
10748
|
+
const [email, discoveredProject] = await Promise.all([
|
|
10749
|
+
getUserEmail(tokenData.access_token),
|
|
10750
|
+
loadCodeAssist(tokenData.access_token)
|
|
10751
|
+
]);
|
|
10752
|
+
return {
|
|
10753
|
+
refresh: tokenData.refresh_token,
|
|
10754
|
+
access: tokenData.access_token,
|
|
10755
|
+
expires: Date.now() + tokenData.expires_in * 1e3 - 5 * 60 * 1e3,
|
|
10756
|
+
projectId: discoveredProject || defaultProjectId(email || "antigravity-default"),
|
|
10757
|
+
email
|
|
10758
|
+
};
|
|
10759
|
+
} finally {
|
|
10760
|
+
cleanup();
|
|
10761
|
+
}
|
|
10762
|
+
}
|
|
10763
|
+
async function refreshAntigravityToken(credentials, signal) {
|
|
10764
|
+
const response = await fetch(TOKEN_URL, {
|
|
10765
|
+
method: "POST",
|
|
10766
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
10767
|
+
body: new URLSearchParams({
|
|
10768
|
+
client_id: CLIENT_ID,
|
|
10769
|
+
client_secret: CLIENT_SECRET,
|
|
10770
|
+
refresh_token: credentials.refresh,
|
|
10771
|
+
grant_type: "refresh_token"
|
|
10772
|
+
}).toString(),
|
|
10773
|
+
signal
|
|
10774
|
+
});
|
|
10775
|
+
if (!response.ok) {
|
|
10776
|
+
throw new Error(
|
|
10777
|
+
`Antigravity token refresh failed: ${sanitizeOAuthProviderError(await response.text())}`
|
|
10778
|
+
);
|
|
10779
|
+
}
|
|
10780
|
+
const data = await response.json();
|
|
10781
|
+
const existingProjectId = credentialProjectId(credentials);
|
|
10782
|
+
const discoveredProject = existingProjectId ? void 0 : await loadCodeAssist(data.access_token);
|
|
10783
|
+
const email = credentialEmail(credentials);
|
|
10784
|
+
return {
|
|
10785
|
+
...credentials,
|
|
10786
|
+
refresh: data.refresh_token || credentials.refresh,
|
|
10787
|
+
access: data.access_token,
|
|
10788
|
+
expires: Date.now() + data.expires_in * 1e3 - 5 * 60 * 1e3,
|
|
10789
|
+
projectId: existingProjectId || discoveredProject || defaultProjectId(email || "antigravity-default")
|
|
10790
|
+
};
|
|
10791
|
+
}
|
|
10792
|
+
function getApiKey(credentials) {
|
|
10793
|
+
const email = credentialEmail(credentials);
|
|
10794
|
+
return JSON.stringify({
|
|
10795
|
+
token: credentials.access,
|
|
10796
|
+
projectId: credentialProjectId(credentials) || defaultProjectId(email || "antigravity-default")
|
|
10797
|
+
});
|
|
10798
|
+
}
|
|
10799
|
+
|
|
10800
|
+
// plugins/kxm/src/providers/antigravity/models/grouping.ts
|
|
10801
|
+
var THINKING_SUFFIXES = [
|
|
10802
|
+
{ suffix: "extra-low", level: ThinkingEffort.Low },
|
|
10803
|
+
{ suffix: "extra-high", level: ThinkingEffort.Xhigh },
|
|
10804
|
+
{ suffix: "thinking", level: ThinkingEffort.High },
|
|
10805
|
+
{ suffix: "minimal", level: ThinkingEffort.Minimal },
|
|
10806
|
+
{ suffix: "medium", level: ThinkingEffort.Medium },
|
|
10807
|
+
{ suffix: "high", level: ThinkingEffort.High },
|
|
10808
|
+
{ suffix: "low", level: ThinkingEffort.Low }
|
|
10809
|
+
];
|
|
10810
|
+
var DISPLAY_LEVELS = [
|
|
10811
|
+
{ pattern: /\(\s*extra\s*low\s*\)/i, level: ThinkingEffort.Low },
|
|
10812
|
+
{ pattern: /\(\s*extra\s*high\s*\)/i, level: ThinkingEffort.Xhigh },
|
|
10813
|
+
{ pattern: /\(\s*thinking\s*\)/i, level: ThinkingEffort.High },
|
|
10814
|
+
{ pattern: /\(\s*minimal\s*\)/i, level: ThinkingEffort.Minimal },
|
|
10815
|
+
{ pattern: /\(\s*medium\s*\)/i, level: ThinkingEffort.Medium },
|
|
10816
|
+
{ pattern: /\(\s*high\s*\)/i, level: ThinkingEffort.High },
|
|
10817
|
+
{ pattern: /\(\s*low\s*\)/i, level: ThinkingEffort.Low }
|
|
10818
|
+
];
|
|
10819
|
+
var RUNTIME_ALIASES = {
|
|
10820
|
+
"gemini-3-flash-agent": { publicId: "gemini-3.5-flash", level: ThinkingEffort.High },
|
|
10821
|
+
"gemini-pro-agent": { publicId: "gemini-3.1-pro", level: ThinkingEffort.High }
|
|
10822
|
+
};
|
|
10823
|
+
var PI_LEVELS = [
|
|
10824
|
+
ThinkingEffort.Off,
|
|
10825
|
+
ThinkingEffort.Minimal,
|
|
10826
|
+
ThinkingEffort.Low,
|
|
10827
|
+
ThinkingEffort.Medium,
|
|
10828
|
+
ThinkingEffort.High,
|
|
10829
|
+
ThinkingEffort.Xhigh,
|
|
10830
|
+
"max"
|
|
10831
|
+
];
|
|
10832
|
+
var ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
10833
|
+
function isSelectableRuntimeModelId(id) {
|
|
10834
|
+
if (!/^(gemini-|claude-|gpt-oss-)/i.test(id) || /\s/.test(id) || /^MODEL_/i.test(id)) {
|
|
10835
|
+
return false;
|
|
10836
|
+
}
|
|
10837
|
+
if (/^(chat_|tab_)/i.test(id)) return false;
|
|
10838
|
+
if (/image/i.test(id)) return false;
|
|
10839
|
+
return true;
|
|
10840
|
+
}
|
|
10841
|
+
function resolvedCatalog(discovered, current) {
|
|
10842
|
+
if (discovered && discovered.models.length > 0) return discovered;
|
|
10843
|
+
return current;
|
|
10844
|
+
}
|
|
10845
|
+
function buildAntigravityCatalog(rawModels, fallback) {
|
|
10846
|
+
const groups = /* @__PURE__ */ new Map();
|
|
10847
|
+
for (const [runtimeId, info] of Object.entries(rawModels)) {
|
|
10848
|
+
if (!isSelectableRuntimeModelId(runtimeId)) continue;
|
|
10849
|
+
if (info?.isInternal) continue;
|
|
10850
|
+
const displayName = modelDisplayName(info);
|
|
10851
|
+
if (runtimeId.endsWith("-tiered")) {
|
|
10852
|
+
const baseId = runtimeId.slice(0, -"-tiered".length);
|
|
10853
|
+
const group2 = ensureGroup(groups, baseId);
|
|
10854
|
+
absorbMetadata(group2, info, displayName);
|
|
10855
|
+
if (!group2.unsuffixed) group2.unsuffixed = runtimeId;
|
|
10856
|
+
continue;
|
|
10857
|
+
}
|
|
10858
|
+
const alias = RUNTIME_ALIASES[runtimeId];
|
|
10859
|
+
const suffix = alias ? void 0 : parseThinkingSuffix(runtimeId);
|
|
10860
|
+
const publicId = alias?.publicId ?? suffix?.baseId ?? runtimeId;
|
|
10861
|
+
const group = ensureGroup(groups, publicId);
|
|
10862
|
+
absorbMetadata(group, info, displayName);
|
|
10863
|
+
const level = alias?.level ?? levelFromDisplayName(displayName) ?? suffix?.level;
|
|
10864
|
+
if (level) group.variants[level] = runtimeId;
|
|
10865
|
+
else group.unsuffixed = runtimeId;
|
|
10866
|
+
}
|
|
10867
|
+
mergeAgentSingletons(groups);
|
|
10868
|
+
if (groups.size === 0) return fallback;
|
|
10869
|
+
const models = [];
|
|
10870
|
+
const routing = {};
|
|
10871
|
+
for (const group of groups.values()) {
|
|
10872
|
+
const fallbackModel = fallback.models.find((model) => model.id === group.publicId);
|
|
10873
|
+
const fallbackRouting = fallback.routing[group.publicId];
|
|
10874
|
+
if (fallbackModel && fallbackRouting) {
|
|
10875
|
+
models.push(fallbackModel);
|
|
10876
|
+
routing[group.publicId] = fallbackRouting;
|
|
10877
|
+
continue;
|
|
10878
|
+
}
|
|
10879
|
+
const synthesized = synthesizeModel(group, fallback.models);
|
|
10880
|
+
models.push(synthesized.model);
|
|
10881
|
+
routing[group.publicId] = synthesized.routing;
|
|
10882
|
+
}
|
|
10883
|
+
for (const fallbackModel of fallback.models) {
|
|
10884
|
+
if (routing[fallbackModel.id]) continue;
|
|
10885
|
+
const fallbackRouting = fallback.routing[fallbackModel.id];
|
|
10886
|
+
if (!fallbackRouting) continue;
|
|
10887
|
+
models.push(fallbackModel);
|
|
10888
|
+
routing[fallbackModel.id] = fallbackRouting;
|
|
10889
|
+
}
|
|
10890
|
+
models.sort(comparePublicModels);
|
|
10891
|
+
return { models, routing };
|
|
10892
|
+
}
|
|
10893
|
+
function ensureGroup(groups, publicId) {
|
|
10894
|
+
const existing = groups.get(publicId);
|
|
10895
|
+
if (existing) return existing;
|
|
10896
|
+
const created = {
|
|
10897
|
+
publicId,
|
|
10898
|
+
variants: {},
|
|
10899
|
+
displayNames: []
|
|
10900
|
+
};
|
|
10901
|
+
groups.set(publicId, created);
|
|
10902
|
+
return created;
|
|
10903
|
+
}
|
|
10904
|
+
function absorbMetadata(group, info, displayName) {
|
|
10905
|
+
if (displayName) group.displayNames.push(displayName);
|
|
10906
|
+
if (info?.supportsThinking === true) group.supportsThinking = true;
|
|
10907
|
+
else if (info?.supportsThinking === false && group.supportsThinking !== true) {
|
|
10908
|
+
group.supportsThinking = false;
|
|
10909
|
+
}
|
|
10910
|
+
if (info?.supportsImages === true) group.supportsImages = true;
|
|
10911
|
+
if (info?.supportsImages === false && group.supportsImages === void 0) {
|
|
10912
|
+
group.supportsImages = false;
|
|
10913
|
+
}
|
|
10914
|
+
}
|
|
10915
|
+
function mergeAgentSingletons(groups) {
|
|
10916
|
+
for (const [publicId, group] of [...groups.entries()]) {
|
|
10917
|
+
if (!publicId.endsWith("-agent")) continue;
|
|
10918
|
+
if (Object.keys(group.variants).length > 0) continue;
|
|
10919
|
+
const family = displayFamily(group.displayNames[0]);
|
|
10920
|
+
if (!family) continue;
|
|
10921
|
+
const target = [...groups.values()].find(
|
|
10922
|
+
(candidate) => candidate.publicId !== publicId && candidate.displayNames.some((name) => displayFamily(name) === family)
|
|
10923
|
+
);
|
|
10924
|
+
if (!target || !group.unsuffixed) continue;
|
|
10925
|
+
const level = levelFromDisplayName(group.displayNames[0]) ?? ThinkingEffort.High;
|
|
10926
|
+
target.variants[level] = group.unsuffixed;
|
|
10927
|
+
absorbMetadata(target, { supportsThinking: group.supportsThinking }, group.displayNames[0]);
|
|
10928
|
+
groups.delete(publicId);
|
|
10929
|
+
}
|
|
10930
|
+
}
|
|
10931
|
+
function parseThinkingSuffix(runtimeId) {
|
|
10932
|
+
const lower = runtimeId.toLowerCase();
|
|
10933
|
+
for (const { suffix, level } of THINKING_SUFFIXES) {
|
|
10934
|
+
if (lower.endsWith(`-${suffix}`)) {
|
|
10935
|
+
return { baseId: runtimeId.slice(0, -(suffix.length + 1)), level };
|
|
10936
|
+
}
|
|
10937
|
+
}
|
|
10938
|
+
return void 0;
|
|
10939
|
+
}
|
|
10940
|
+
function levelFromDisplayName(displayName) {
|
|
10941
|
+
if (!displayName) return void 0;
|
|
10942
|
+
for (const { pattern, level } of DISPLAY_LEVELS) {
|
|
10943
|
+
if (pattern.test(displayName)) return level;
|
|
10944
|
+
}
|
|
10945
|
+
return void 0;
|
|
10946
|
+
}
|
|
10947
|
+
function modelDisplayName(info) {
|
|
10948
|
+
if (!info) return void 0;
|
|
10949
|
+
if (typeof info.displayName === "string" && info.displayName) return info.displayName;
|
|
10950
|
+
if (typeof info.label === "string" && info.label) return info.label;
|
|
10951
|
+
if (typeof info.modelName === "string" && info.modelName) return info.modelName;
|
|
10952
|
+
return void 0;
|
|
10953
|
+
}
|
|
10954
|
+
function displayFamily(displayName) {
|
|
10955
|
+
if (!displayName) return void 0;
|
|
10956
|
+
return displayName.replace(/\s*\((?:extra\s*low|extra\s*high|low|medium|high|minimal|thinking)\)\s*$/i, "").trim().toLowerCase();
|
|
10957
|
+
}
|
|
10958
|
+
function synthesizeModel(group, fallbackModels) {
|
|
10959
|
+
const template = familyTemplate(group.publicId, fallbackModels);
|
|
10960
|
+
const advertisedLevels = advertisedThinkingLevels(group);
|
|
10961
|
+
const routing = routingFromVariants(group.publicId, group.variants, group.unsuffixed);
|
|
10962
|
+
const supportsImages = group.supportsImages ?? template?.input.includes("image") ?? true;
|
|
10963
|
+
const reasoning = advertisedLevels.size > 0 || group.supportsThinking === true || group.supportsThinking === void 0 && Boolean(template?.reasoning);
|
|
10964
|
+
return {
|
|
10965
|
+
model: {
|
|
10966
|
+
id: group.publicId,
|
|
10967
|
+
name: publicModelName(group),
|
|
10968
|
+
reasoning,
|
|
10969
|
+
...reasoning ? { thinkingLevelMap: thinkingLevelMapFromLevels(advertisedLevels) } : {},
|
|
10970
|
+
input: supportsImages ? ["text", "image"] : ["text"],
|
|
10971
|
+
cost: template?.cost ?? ZERO_COST,
|
|
10972
|
+
contextWindow: template?.contextWindow ?? 128e3,
|
|
10973
|
+
maxTokens: template?.maxTokens ?? 8192
|
|
10974
|
+
},
|
|
10975
|
+
routing
|
|
10976
|
+
};
|
|
10977
|
+
}
|
|
10978
|
+
function advertisedThinkingLevels(group) {
|
|
10979
|
+
const levels = new Set(Object.keys(group.variants));
|
|
10980
|
+
if (levels.size > 0) return levels;
|
|
10981
|
+
if (group.supportsThinking === false) return levels;
|
|
10982
|
+
if (group.supportsThinking === true || group.unsuffixed) {
|
|
10983
|
+
levels.add(ThinkingEffort.High);
|
|
10984
|
+
}
|
|
10985
|
+
return levels;
|
|
10986
|
+
}
|
|
10987
|
+
function routingFromVariants(publicId, variants, unsuffixed) {
|
|
10988
|
+
const defaultRequestId = variants[ThinkingEffort.Low] ?? variants[ThinkingEffort.Minimal] ?? variants[ThinkingEffort.Medium] ?? variants[ThinkingEffort.High] ?? unsuffixed ?? publicId;
|
|
10989
|
+
const pick = (...keys) => {
|
|
10990
|
+
for (const key of keys) {
|
|
10991
|
+
const id = variants[key];
|
|
10992
|
+
if (id) return id;
|
|
10993
|
+
}
|
|
10994
|
+
return unsuffixed ?? defaultRequestId;
|
|
10995
|
+
};
|
|
10996
|
+
return {
|
|
10997
|
+
off: pick(
|
|
10998
|
+
ThinkingEffort.Low,
|
|
10999
|
+
ThinkingEffort.Minimal,
|
|
11000
|
+
ThinkingEffort.Medium,
|
|
11001
|
+
ThinkingEffort.High
|
|
11002
|
+
),
|
|
11003
|
+
routing: {
|
|
11004
|
+
minimal: pick(
|
|
11005
|
+
ThinkingEffort.Minimal,
|
|
11006
|
+
ThinkingEffort.Low,
|
|
11007
|
+
ThinkingEffort.Medium,
|
|
11008
|
+
ThinkingEffort.High
|
|
11009
|
+
),
|
|
11010
|
+
low: pick(
|
|
11011
|
+
ThinkingEffort.Low,
|
|
11012
|
+
ThinkingEffort.Minimal,
|
|
11013
|
+
ThinkingEffort.Medium,
|
|
11014
|
+
ThinkingEffort.High
|
|
11015
|
+
),
|
|
11016
|
+
medium: pick(
|
|
11017
|
+
ThinkingEffort.Medium,
|
|
11018
|
+
ThinkingEffort.Low,
|
|
11019
|
+
ThinkingEffort.High,
|
|
11020
|
+
ThinkingEffort.Minimal
|
|
11021
|
+
),
|
|
11022
|
+
high: pick(
|
|
11023
|
+
ThinkingEffort.High,
|
|
11024
|
+
ThinkingEffort.Medium,
|
|
11025
|
+
ThinkingEffort.Low,
|
|
11026
|
+
ThinkingEffort.Minimal
|
|
11027
|
+
),
|
|
11028
|
+
xhigh: pick(
|
|
11029
|
+
ThinkingEffort.Xhigh,
|
|
11030
|
+
ThinkingEffort.High,
|
|
11031
|
+
ThinkingEffort.Medium,
|
|
11032
|
+
ThinkingEffort.Low
|
|
11033
|
+
)
|
|
11034
|
+
},
|
|
11035
|
+
defaultRequestId
|
|
11036
|
+
};
|
|
11037
|
+
}
|
|
11038
|
+
function thinkingLevelMapFromLevels(levels) {
|
|
11039
|
+
const map = {};
|
|
11040
|
+
for (const level of PI_LEVELS) {
|
|
11041
|
+
map[level] = levels.has(level) ? level : null;
|
|
11042
|
+
}
|
|
11043
|
+
if (levels.size === 0) map.high = "high";
|
|
11044
|
+
return map;
|
|
11045
|
+
}
|
|
11046
|
+
function familyTemplate(publicId, fallbackModels) {
|
|
11047
|
+
if (/^gemini-.*-flash/i.test(publicId)) {
|
|
11048
|
+
return fallbackModels.find((model) => /^gemini-.*-flash/i.test(model.id));
|
|
11049
|
+
}
|
|
11050
|
+
if (/^gemini-.*-pro/i.test(publicId)) {
|
|
11051
|
+
return fallbackModels.find((model) => /^gemini-.*-pro/i.test(model.id));
|
|
11052
|
+
}
|
|
11053
|
+
if (publicId.startsWith("claude-opus")) {
|
|
11054
|
+
return fallbackModels.find((model) => model.id.startsWith("claude-opus"));
|
|
11055
|
+
}
|
|
11056
|
+
if (publicId.startsWith("claude-")) {
|
|
11057
|
+
return fallbackModels.find((model) => model.id.startsWith("claude-sonnet")) ?? fallbackModels.find((model) => model.id.startsWith("claude-"));
|
|
11058
|
+
}
|
|
11059
|
+
if (publicId.startsWith("gpt-oss")) {
|
|
11060
|
+
return fallbackModels.find((model) => model.id.startsWith("gpt-oss"));
|
|
11061
|
+
}
|
|
11062
|
+
if (publicId.startsWith("gemini-")) {
|
|
11063
|
+
return fallbackModels.find((model) => model.id.startsWith("gemini-"));
|
|
11064
|
+
}
|
|
11065
|
+
return void 0;
|
|
11066
|
+
}
|
|
11067
|
+
function publicModelName(group) {
|
|
11068
|
+
const family = group.displayNames.map((name) => displayFamily(name)).find(Boolean);
|
|
11069
|
+
if (family) {
|
|
11070
|
+
return `${titleCase(family)} (Antigravity)`;
|
|
11071
|
+
}
|
|
11072
|
+
return `${humanizePublicId(group.publicId)} (Antigravity)`;
|
|
11073
|
+
}
|
|
11074
|
+
function titleCase(value) {
|
|
11075
|
+
return value.replace(/\b([a-z])/g, (char) => char.toUpperCase());
|
|
11076
|
+
}
|
|
11077
|
+
function humanizePublicId(id) {
|
|
11078
|
+
const tokens = id.split("-");
|
|
11079
|
+
const words = [];
|
|
11080
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
11081
|
+
const token = tokens[i];
|
|
11082
|
+
if (!token) continue;
|
|
11083
|
+
const next = tokens[i + 1];
|
|
11084
|
+
if (token === "gpt" && next === "oss") {
|
|
11085
|
+
words.push("GPT-OSS");
|
|
11086
|
+
i++;
|
|
11087
|
+
continue;
|
|
11088
|
+
}
|
|
11089
|
+
if (/^\d+$/.test(token) && next && /^\d+$/.test(next)) {
|
|
11090
|
+
words.push(`${token}.${next}`);
|
|
11091
|
+
i++;
|
|
11092
|
+
continue;
|
|
11093
|
+
}
|
|
11094
|
+
if (/^\d/.test(token)) {
|
|
11095
|
+
words.push(token.toUpperCase());
|
|
11096
|
+
continue;
|
|
11097
|
+
}
|
|
11098
|
+
words.push(token.charAt(0).toUpperCase() + token.slice(1));
|
|
11099
|
+
}
|
|
11100
|
+
return words.join(" ");
|
|
11101
|
+
}
|
|
11102
|
+
function parseGeminiVersion(id) {
|
|
11103
|
+
const match = id.match(/^gemini-(\d+)(?:\.(\d+))?/i);
|
|
11104
|
+
if (!match) return 0;
|
|
11105
|
+
return Number(match[1]) * 1e3 + Number(match[2] || 0);
|
|
11106
|
+
}
|
|
11107
|
+
function comparePublicModels(a, b) {
|
|
11108
|
+
const rankA = modelRank(a.id);
|
|
11109
|
+
const rankB = modelRank(b.id);
|
|
11110
|
+
if (rankA[0] !== rankB[0]) return rankA[0] - rankB[0];
|
|
11111
|
+
if (rankA[1] !== rankB[1]) return rankA[1] - rankB[1];
|
|
11112
|
+
return a.id.localeCompare(b.id);
|
|
11113
|
+
}
|
|
11114
|
+
function modelRank(id) {
|
|
11115
|
+
const version = parseGeminiVersion(id);
|
|
11116
|
+
if (/^gemini-.*flash/i.test(id) && !/pro/i.test(id)) return [0, -version];
|
|
11117
|
+
if (id.startsWith("claude-opus")) return [1, 0];
|
|
11118
|
+
if (id.startsWith("claude-sonnet")) return [2, 0];
|
|
11119
|
+
if (id.startsWith("claude-")) return [3, 0];
|
|
11120
|
+
if (/^gemini-.*pro/i.test(id)) return [4, -version];
|
|
11121
|
+
if (id.startsWith("gemini-")) return [5, -version];
|
|
11122
|
+
if (id.startsWith("gpt-oss")) return [6, 0];
|
|
11123
|
+
return [7, 0];
|
|
11124
|
+
}
|
|
11125
|
+
|
|
11126
|
+
// plugins/kxm/src/providers/antigravity/types/types.ts
|
|
11127
|
+
var ANTIGRAVITY_API = "antigravity-api";
|
|
11128
|
+
|
|
11129
|
+
// plugins/kxm/src/providers/antigravity/models/discovery.ts
|
|
11130
|
+
var DEFAULT_CATALOG_REFRESH_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
11131
|
+
var ANTIGRAVITY_PERSIST_KEY = "pi-antigravity";
|
|
11132
|
+
function getCatalogRefreshIntervalMs() {
|
|
11133
|
+
const envVal = antigravityEnv("CATALOG_REFRESH_INTERVAL_MS") ?? antigravityEnv("REFRESH_INTERVAL_MS");
|
|
11134
|
+
if (envVal) {
|
|
11135
|
+
const parsed = Number.parseInt(envVal, 10);
|
|
11136
|
+
if (!Number.isNaN(parsed) && parsed >= 0) return parsed;
|
|
11137
|
+
}
|
|
11138
|
+
return DEFAULT_CATALOG_REFRESH_INTERVAL_MS;
|
|
11139
|
+
}
|
|
11140
|
+
var fallbackCatalog = () => ({
|
|
11141
|
+
models: ANTIGRAVITY_MODELS,
|
|
11142
|
+
routing: { ...ANTIGRAVITY_ROUTING }
|
|
11143
|
+
});
|
|
11144
|
+
function hydrateAntigravityCatalog(stored) {
|
|
11145
|
+
if (!isRecord2(stored)) return 0;
|
|
11146
|
+
const persisted = stored[ANTIGRAVITY_PERSIST_KEY];
|
|
11147
|
+
if (!isRecord2(persisted)) return 0;
|
|
11148
|
+
if (isStringMap(persisted.modelEnums)) restoreDynamicModelEnums(persisted.modelEnums);
|
|
11149
|
+
if (isCatalog(persisted.catalog)) applyAntigravityCatalog(persisted.catalog);
|
|
11150
|
+
return typeof persisted.checkedAt === "number" && persisted.checkedAt > 0 ? persisted.checkedAt : 0;
|
|
11151
|
+
}
|
|
11152
|
+
async function discoverAntigravityModels(apiKey, signal) {
|
|
11153
|
+
const creds = parseApiKey(apiKey);
|
|
11154
|
+
const available = await fetchAvailableModelsCatalog(creds.token, creds.projectId, signal);
|
|
11155
|
+
const models = available.data.models;
|
|
11156
|
+
if (!models || Object.keys(models).length === 0) {
|
|
11157
|
+
return { models: [], routing: {} };
|
|
11158
|
+
}
|
|
11159
|
+
registerDiscoveredModelEnums(models);
|
|
11160
|
+
return buildAntigravityCatalog(models, fallbackCatalog());
|
|
11161
|
+
}
|
|
11162
|
+
async function refreshAntigravityModels(context) {
|
|
11163
|
+
const checkedAt = hydrateAntigravityCatalog(context.stored);
|
|
11164
|
+
const current = getCurrentAntigravityCatalog();
|
|
11165
|
+
if (!context.allowNetwork) return current.models;
|
|
11166
|
+
const apiKey = apiKeyFromCredential(context.credential);
|
|
11167
|
+
if (!apiKey || context.signal.aborted) return current.models;
|
|
11168
|
+
const now = Date.now();
|
|
11169
|
+
if (!context.force && checkedAt > 0 && now >= checkedAt && now - checkedAt < getCatalogRefreshIntervalMs()) {
|
|
11170
|
+
return current.models;
|
|
11171
|
+
}
|
|
11172
|
+
try {
|
|
11173
|
+
const discovered = await discoverAntigravityModels(apiKey, context.signal);
|
|
11174
|
+
if (context.signal.aborted) return current.models;
|
|
11175
|
+
const next = resolvedCatalog(discovered, current);
|
|
11176
|
+
if (next.models.length > 0 && discovered.models.length > 0) {
|
|
11177
|
+
applyAntigravityCatalog(next);
|
|
11178
|
+
const refreshedAt = Date.now();
|
|
11179
|
+
await context.publish({
|
|
11180
|
+
persist: {
|
|
11181
|
+
models: toStoredModels(next.models),
|
|
11182
|
+
[ANTIGRAVITY_PERSIST_KEY]: {
|
|
11183
|
+
catalog: next,
|
|
11184
|
+
checkedAt: refreshedAt,
|
|
11185
|
+
modelEnums: snapshotDynamicModelEnums()
|
|
11186
|
+
}
|
|
11187
|
+
}
|
|
11188
|
+
});
|
|
11189
|
+
return next.models;
|
|
11190
|
+
}
|
|
11191
|
+
} catch (error) {
|
|
11192
|
+
if (context.force) throw error;
|
|
11193
|
+
}
|
|
11194
|
+
return getCurrentAntigravityCatalog().models;
|
|
11195
|
+
}
|
|
11196
|
+
function isCatalog(value) {
|
|
11197
|
+
return isRecord2(value) && Array.isArray(value.models) && value.models.length > 0 && isRecord2(value.routing);
|
|
11198
|
+
}
|
|
11199
|
+
function isStringMap(value) {
|
|
11200
|
+
return isRecord2(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
11201
|
+
}
|
|
11202
|
+
function apiKeyFromCredential(credential) {
|
|
11203
|
+
if (!credential) return void 0;
|
|
11204
|
+
if (credential.type === "api_key") {
|
|
11205
|
+
return typeof credential.key === "string" && credential.key ? credential.key : void 0;
|
|
11206
|
+
}
|
|
11207
|
+
if (credential.type === "oauth" && typeof credential.access === "string") {
|
|
11208
|
+
return getApiKey(credential);
|
|
11209
|
+
}
|
|
11210
|
+
return void 0;
|
|
11211
|
+
}
|
|
11212
|
+
function toStoredModels(models) {
|
|
11213
|
+
return models.map((model) => ({
|
|
11214
|
+
...model,
|
|
11215
|
+
api: ANTIGRAVITY_API,
|
|
11216
|
+
provider: "antigravity",
|
|
11217
|
+
baseUrl: DEFAULT_ENDPOINT
|
|
11218
|
+
}));
|
|
11219
|
+
}
|
|
11220
|
+
|
|
11221
|
+
// plugins/kxm/src/providers/antigravity/pi-compat.ts
|
|
11222
|
+
var AssistantMessageEventStream = class {
|
|
11223
|
+
queue = [];
|
|
11224
|
+
waiting = [];
|
|
11225
|
+
done = false;
|
|
11226
|
+
finalResultPromise;
|
|
11227
|
+
resolveFinalResult;
|
|
11228
|
+
constructor() {
|
|
11229
|
+
this.finalResultPromise = new Promise((resolve5) => {
|
|
11230
|
+
this.resolveFinalResult = resolve5;
|
|
11231
|
+
});
|
|
11232
|
+
}
|
|
11233
|
+
push(event) {
|
|
11234
|
+
if (this.done) return;
|
|
11235
|
+
if (event.type === "done") {
|
|
11236
|
+
this.done = true;
|
|
11237
|
+
this.resolveFinalResult(event.message);
|
|
11238
|
+
} else if (event.type === "error") {
|
|
11239
|
+
this.done = true;
|
|
11240
|
+
this.resolveFinalResult(event.error);
|
|
11241
|
+
}
|
|
11242
|
+
const waiter = this.waiting.shift();
|
|
11243
|
+
if (waiter) waiter({ value: event, done: false });
|
|
11244
|
+
else this.queue.push(event);
|
|
11245
|
+
}
|
|
11246
|
+
end(result2) {
|
|
11247
|
+
this.done = true;
|
|
11248
|
+
if (result2 !== void 0) this.resolveFinalResult(result2);
|
|
11249
|
+
while (this.waiting.length > 0) {
|
|
11250
|
+
this.waiting.shift()?.({ done: true });
|
|
11251
|
+
}
|
|
11252
|
+
}
|
|
11253
|
+
async *[Symbol.asyncIterator]() {
|
|
11254
|
+
while (true) {
|
|
11255
|
+
if (this.queue.length > 0) {
|
|
11256
|
+
yield this.queue.shift();
|
|
11257
|
+
} else if (this.done) {
|
|
11258
|
+
return;
|
|
11259
|
+
} else {
|
|
11260
|
+
const next = await new Promise((resolve5) => {
|
|
11261
|
+
this.waiting.push(resolve5);
|
|
11262
|
+
});
|
|
11263
|
+
if (next.done) return;
|
|
11264
|
+
if (next.value) yield next.value;
|
|
11265
|
+
}
|
|
11266
|
+
}
|
|
11267
|
+
}
|
|
11268
|
+
result() {
|
|
11269
|
+
return this.finalResultPromise;
|
|
11270
|
+
}
|
|
11271
|
+
};
|
|
11272
|
+
function createAssistantMessageEventStream() {
|
|
11273
|
+
return new AssistantMessageEventStream();
|
|
11274
|
+
}
|
|
11275
|
+
function calculateCost(model, usage) {
|
|
11276
|
+
const rates = model.cost;
|
|
11277
|
+
if (!rates) {
|
|
11278
|
+
usage.cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
11279
|
+
return usage.cost;
|
|
11280
|
+
}
|
|
11281
|
+
const inputTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
11282
|
+
let applied = rates;
|
|
11283
|
+
let matchedThreshold = -1;
|
|
11284
|
+
for (const tier of rates.tiers ?? []) {
|
|
11285
|
+
if (inputTokens > tier.inputTokensAbove && tier.inputTokensAbove > matchedThreshold) {
|
|
11286
|
+
applied = tier;
|
|
11287
|
+
matchedThreshold = tier.inputTokensAbove;
|
|
11288
|
+
}
|
|
11289
|
+
}
|
|
11290
|
+
const longWrite = usage.cacheWrite1h ?? 0;
|
|
11291
|
+
const shortWrite = usage.cacheWrite - longWrite;
|
|
11292
|
+
usage.cost.input = applied.input / 1e6 * usage.input;
|
|
11293
|
+
usage.cost.output = applied.output / 1e6 * usage.output;
|
|
11294
|
+
usage.cost.cacheRead = applied.cacheRead / 1e6 * usage.cacheRead;
|
|
11295
|
+
usage.cost.cacheWrite = (applied.cacheWrite * shortWrite + applied.input * 2 * longWrite) / 1e6;
|
|
11296
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
11297
|
+
return usage.cost;
|
|
11298
|
+
}
|
|
11299
|
+
|
|
11300
|
+
// plugins/kxm/src/providers/antigravity/stream/stream.ts
|
|
11301
|
+
var ANTIGRAVITY_SYSTEM_INSTRUCTION = "You are Antigravity, a powerful agentic AI coding assistant designed by Google DeepMind. You are pair programming with a user to solve coding tasks. Be concise, practical, and tool-aware.";
|
|
11302
|
+
var ANTIGRAVITY_NO_PREAMBLE_INSTRUCTION = 'CRITICAL: NEVER output rule checks, formatting guidelines, constraint checklists (e.g. "No emdashes"), or your thinking/personality preambles in the final response. Output only the final response.';
|
|
11303
|
+
var toolCallCounter = 0;
|
|
11304
|
+
function sanitizeToolCallId(id, fallbackName) {
|
|
11305
|
+
const cleaned = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
11306
|
+
const capped = cleaned.slice(0, 64);
|
|
11307
|
+
return capped || `${fallbackName || "tool"}_${++toolCallCounter}`;
|
|
11308
|
+
}
|
|
11309
|
+
function toolCallIdNeeded(modelId, runtimeModel) {
|
|
11310
|
+
return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-") || runtimeModel.startsWith("claude-") || runtimeModel.startsWith("gpt-oss-");
|
|
11311
|
+
}
|
|
11312
|
+
var base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
11313
|
+
function isValidThoughtSignature(signature) {
|
|
11314
|
+
if (!signature || typeof signature !== "string" || signature.length === 0) return false;
|
|
11315
|
+
if (signature.length % 4 !== 0) return false;
|
|
11316
|
+
return base64SignaturePattern.test(signature);
|
|
11317
|
+
}
|
|
11318
|
+
function geminiRequiresThoughtSignature(runtimeModel) {
|
|
11319
|
+
if (!runtimeModel.startsWith("gemini-")) return false;
|
|
11320
|
+
const match = runtimeModel.match(/^gemini-(\d+)/);
|
|
11321
|
+
if (match) {
|
|
11322
|
+
const major = Number.parseInt(match[1], 10);
|
|
11323
|
+
return major >= 3;
|
|
11324
|
+
}
|
|
11325
|
+
return true;
|
|
11326
|
+
}
|
|
11327
|
+
function parseImageData(raw, explicitMime) {
|
|
11328
|
+
const match = raw.match(/^data:([^;]+);base64,(.+)$/s);
|
|
11329
|
+
if (match) {
|
|
11330
|
+
return {
|
|
11331
|
+
mimeType: explicitMime || match[1] || "image/png",
|
|
11332
|
+
data: match[2].trim()
|
|
11333
|
+
};
|
|
11334
|
+
}
|
|
11335
|
+
return {
|
|
11336
|
+
mimeType: explicitMime || "image/png",
|
|
11337
|
+
data: raw.trim()
|
|
11338
|
+
};
|
|
11339
|
+
}
|
|
11340
|
+
var SKILL_BLOCK_PATTERN = /<skill\b[^>]*>[\s\S]*?<\/skill\s*>/gi;
|
|
11341
|
+
function skillBlocks(content) {
|
|
11342
|
+
const texts = typeof content === "string" ? [content] : Array.isArray(content) ? content.flatMap(
|
|
11343
|
+
(item) => isRecord2(item) && item.type === "text" && typeof item.text === "string" ? [item.text] : []
|
|
11344
|
+
) : [];
|
|
11345
|
+
return texts.flatMap((text) => text.match(SKILL_BLOCK_PATTERN) || []);
|
|
11346
|
+
}
|
|
11347
|
+
function withoutSkillBlocks(text) {
|
|
11348
|
+
return text.replace(SKILL_BLOCK_PATTERN, "");
|
|
11349
|
+
}
|
|
11350
|
+
function asTextParts(content) {
|
|
11351
|
+
const textPart = (text) => {
|
|
11352
|
+
const userText = withoutSkillBlocks(text);
|
|
11353
|
+
return userText.trim() ? [{ text: sanitizeText(userText) }] : [];
|
|
11354
|
+
};
|
|
11355
|
+
if (typeof content === "string") return textPart(content);
|
|
11356
|
+
if (!Array.isArray(content)) return [];
|
|
11357
|
+
return content.flatMap((item) => {
|
|
11358
|
+
if (!isRecord2(item)) return [];
|
|
11359
|
+
const block = item;
|
|
11360
|
+
if (block.type === "text") return textPart(block.text);
|
|
11361
|
+
if (block.type === "image") {
|
|
11362
|
+
const rawData = block.data || block.source?.data;
|
|
11363
|
+
if (!rawData) return [];
|
|
11364
|
+
const explicitMime = block.mimeType || block.mediaType || block.source?.mediaType;
|
|
11365
|
+
const { data, mimeType } = parseImageData(rawData, explicitMime);
|
|
11366
|
+
return data ? [{ inlineData: { mimeType, data } }] : [];
|
|
11367
|
+
}
|
|
11368
|
+
return [];
|
|
11369
|
+
});
|
|
11370
|
+
}
|
|
11371
|
+
function asImageParts(content) {
|
|
11372
|
+
if (!Array.isArray(content)) return [];
|
|
11373
|
+
return content.flatMap((item) => {
|
|
11374
|
+
if (!isRecord2(item)) return [];
|
|
11375
|
+
const block = item;
|
|
11376
|
+
if (block.type === "image") {
|
|
11377
|
+
const rawData = block.data || block.source?.data;
|
|
11378
|
+
if (!rawData) return [];
|
|
11379
|
+
const explicitMime = block.mimeType || block.mediaType || block.source?.mediaType;
|
|
11380
|
+
const { data, mimeType } = parseImageData(rawData, explicitMime);
|
|
11381
|
+
return data ? [{ inlineData: { mimeType, data } }] : [];
|
|
11382
|
+
}
|
|
11383
|
+
return [];
|
|
11384
|
+
});
|
|
11385
|
+
}
|
|
11386
|
+
function appendTurn(contents, role, parts) {
|
|
11387
|
+
if (!parts.length) return;
|
|
11388
|
+
const last = contents[contents.length - 1];
|
|
11389
|
+
if (last && last.role === role) {
|
|
11390
|
+
last.parts.push(...parts);
|
|
11391
|
+
} else {
|
|
11392
|
+
contents.push({ role, parts });
|
|
11393
|
+
}
|
|
11394
|
+
}
|
|
11395
|
+
function convertMessages(model, context, runtimeModel) {
|
|
11396
|
+
const contents = [];
|
|
11397
|
+
const requiresSig = geminiRequiresThoughtSignature(runtimeModel);
|
|
11398
|
+
const droppedToolCallIds = /* @__PURE__ */ new Map();
|
|
11399
|
+
for (const msg of context.messages) {
|
|
11400
|
+
if (msg.role === "user") {
|
|
11401
|
+
const parts = asTextParts(msg.content);
|
|
11402
|
+
appendTurn(contents, GeminiRole.User, parts);
|
|
11403
|
+
} else if (msg.role === "assistant") {
|
|
11404
|
+
if (msg.stopReason === "error" || msg.stopReason === "aborted") {
|
|
11405
|
+
continue;
|
|
11406
|
+
}
|
|
11407
|
+
const parts = [];
|
|
11408
|
+
const isSameModel = msg.provider === PROVIDER_ID && msg.model === model.id;
|
|
11409
|
+
const toolCalls = msg.content.filter((b) => b.type === "toolCall");
|
|
11410
|
+
const firstCallHasSig = toolCalls.length > 0 && isValidThoughtSignature(toolCalls[0]?.thoughtSignature);
|
|
11411
|
+
const allSigsValid = toolCalls.every(
|
|
11412
|
+
(tc) => !tc.thoughtSignature || isValidThoughtSignature(tc.thoughtSignature)
|
|
11413
|
+
);
|
|
11414
|
+
const groupIsSigned = isSameModel && firstCallHasSig && allSigsValid;
|
|
11415
|
+
for (const block of msg.content) {
|
|
11416
|
+
if (block.type === "text") {
|
|
11417
|
+
const textSig = isSameModel && isValidThoughtSignature(block.textSignature) ? block.textSignature : void 0;
|
|
11418
|
+
if ((!block.text || block.text.trim() === "") && !textSig) {
|
|
11419
|
+
continue;
|
|
11420
|
+
}
|
|
11421
|
+
parts.push({
|
|
11422
|
+
text: sanitizeText(block.text),
|
|
11423
|
+
...textSig ? { thoughtSignature: textSig } : {}
|
|
11424
|
+
});
|
|
11425
|
+
} else if (block.type === "thinking" && String(block.thinking || "").trim()) {
|
|
11426
|
+
if (!isSameModel) continue;
|
|
11427
|
+
parts.push({
|
|
11428
|
+
thought: true,
|
|
11429
|
+
text: sanitizeText(block.thinking),
|
|
11430
|
+
...block.thinkingSignature ? { thoughtSignature: block.thinkingSignature } : {}
|
|
11431
|
+
});
|
|
11432
|
+
} else if (block.type === "toolCall") {
|
|
11433
|
+
if (requiresSig && !groupIsSigned) {
|
|
11434
|
+
const rawId = block.id || "";
|
|
11435
|
+
const argsText = (() => {
|
|
11436
|
+
try {
|
|
11437
|
+
return JSON.stringify(block.arguments ?? {});
|
|
11438
|
+
} catch {
|
|
11439
|
+
return "{}";
|
|
11440
|
+
}
|
|
11441
|
+
})();
|
|
11442
|
+
if (rawId) {
|
|
11443
|
+
droppedToolCallIds.set(rawId, argsText);
|
|
11444
|
+
droppedToolCallIds.set(sanitizeToolCallId(rawId, block.name), argsText);
|
|
11445
|
+
} else {
|
|
11446
|
+
droppedToolCallIds.set(`empty:${block.name}`, argsText);
|
|
11447
|
+
}
|
|
11448
|
+
} else {
|
|
11449
|
+
parts.push({
|
|
11450
|
+
functionCall: {
|
|
11451
|
+
name: block.name,
|
|
11452
|
+
args: block.arguments ?? {},
|
|
11453
|
+
...toolCallIdNeeded(model.id, runtimeModel) ? { id: sanitizeToolCallId(block.id || "", block.name) } : {}
|
|
11454
|
+
},
|
|
11455
|
+
...block.thoughtSignature ? { thoughtSignature: block.thoughtSignature } : {}
|
|
11456
|
+
});
|
|
11457
|
+
}
|
|
11458
|
+
}
|
|
11459
|
+
}
|
|
11460
|
+
appendTurn(contents, GeminiRole.Model, parts);
|
|
11461
|
+
} else if (msg.role === "toolResult") {
|
|
11462
|
+
const text = msg.content.filter((c) => c.type === "text").map((c) => sanitizeText(c.text)).join("\n");
|
|
11463
|
+
const responseText = text || (msg.isError ? "Tool failed" : "");
|
|
11464
|
+
const imageParts = asImageParts(msg.content);
|
|
11465
|
+
const rawId = msg.toolCallId || "";
|
|
11466
|
+
const sanitizedId = toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(rawId, msg.toolName) : rawId;
|
|
11467
|
+
const droppedArgs = requiresSig ? droppedToolCallIds.get(rawId) ?? droppedToolCallIds.get(sanitizedId) ?? (rawId === "" ? droppedToolCallIds.get(`empty:${msg.toolName}`) : void 0) : void 0;
|
|
11468
|
+
if (droppedArgs !== void 0) {
|
|
11469
|
+
const label = droppedArgs === "{}" ? `\`${msg.toolName}\`` : `\`${msg.toolName}\` (${droppedArgs})`;
|
|
11470
|
+
appendTurn(contents, GeminiRole.User, [
|
|
11471
|
+
{ text: sanitizeText(`[Observation from ${label}:
|
|
11472
|
+
${responseText}]`) },
|
|
11473
|
+
...imageParts
|
|
11474
|
+
]);
|
|
11475
|
+
} else {
|
|
11476
|
+
const part = {
|
|
11477
|
+
functionResponse: {
|
|
11478
|
+
name: msg.toolName,
|
|
11479
|
+
response: msg.isError ? { error: responseText } : { output: responseText },
|
|
11480
|
+
...toolCallIdNeeded(model.id, runtimeModel) ? { id: sanitizeToolCallId(msg.toolCallId || "", msg.toolName) } : {}
|
|
11481
|
+
}
|
|
11482
|
+
};
|
|
11483
|
+
appendTurn(contents, GeminiRole.User, [part, ...imageParts]);
|
|
11484
|
+
}
|
|
11485
|
+
}
|
|
11486
|
+
}
|
|
11487
|
+
const hasUserText = contents.some(
|
|
11488
|
+
(turn) => turn.role === GeminiRole.User && turn.parts.some((part) => "text" in part && Boolean(part.text.trim()))
|
|
11489
|
+
);
|
|
11490
|
+
if (!hasUserText && contents.length > 0) {
|
|
11491
|
+
const bridge = {
|
|
11492
|
+
text: "Continue the active task using the available instructions and context."
|
|
11493
|
+
};
|
|
11494
|
+
const userTurn = contents.find((turn) => turn.role === GeminiRole.User);
|
|
11495
|
+
if (userTurn) userTurn.parts.push(bridge);
|
|
11496
|
+
else contents.unshift({ role: GeminiRole.User, parts: [bridge] });
|
|
11497
|
+
}
|
|
11498
|
+
return contents;
|
|
11499
|
+
}
|
|
11500
|
+
var MAX_SCHEMA_DEREFERENCE_DEPTH = 64;
|
|
11501
|
+
var MAX_SCHEMA_DEREFERENCE_NODES = 1e4;
|
|
11502
|
+
var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
|
|
11503
|
+
"properties",
|
|
11504
|
+
"patternProperties",
|
|
11505
|
+
"dependentSchemas",
|
|
11506
|
+
"dependencies"
|
|
11507
|
+
]);
|
|
11508
|
+
var SCHEMA_VALUE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
11509
|
+
"additionalItems",
|
|
11510
|
+
"additionalProperties",
|
|
11511
|
+
"contains",
|
|
11512
|
+
"contentSchema",
|
|
11513
|
+
"else",
|
|
11514
|
+
"if",
|
|
11515
|
+
"items",
|
|
11516
|
+
"not",
|
|
11517
|
+
"propertyNames",
|
|
11518
|
+
"then",
|
|
11519
|
+
"unevaluatedItems",
|
|
11520
|
+
"unevaluatedProperties"
|
|
11521
|
+
]);
|
|
11522
|
+
var SCHEMA_ARRAY_KEYWORDS = /* @__PURE__ */ new Set(["allOf", "anyOf", "oneOf", "prefixItems"]);
|
|
11523
|
+
function resolveLocalJsonPointer(ref, rootSchema) {
|
|
11524
|
+
if (ref === "#") return rootSchema;
|
|
11525
|
+
if (!ref.startsWith("#/")) return void 0;
|
|
11526
|
+
let current = rootSchema;
|
|
11527
|
+
for (const token of ref.slice(2).split("/")) {
|
|
11528
|
+
const key = token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
11529
|
+
if (Array.isArray(current)) {
|
|
11530
|
+
if (!/^(0|[1-9]\d*)$/.test(key)) return void 0;
|
|
11531
|
+
const index = Number(key);
|
|
11532
|
+
if (!Number.isSafeInteger(index) || index >= current.length) return void 0;
|
|
11533
|
+
current = current[index];
|
|
11534
|
+
continue;
|
|
11535
|
+
}
|
|
11536
|
+
if (!current || typeof current !== "object") return void 0;
|
|
11537
|
+
if (!Object.prototype.hasOwnProperty.call(current, key)) return void 0;
|
|
11538
|
+
current = current[key];
|
|
11539
|
+
}
|
|
11540
|
+
return current;
|
|
11541
|
+
}
|
|
11542
|
+
function dereferenceSchemaMap(schemaMap, rootSchema, refStack, objectStack, state, path, depth) {
|
|
11543
|
+
if (!isRecord2(schemaMap)) {
|
|
11544
|
+
return dereferenceSchema(schemaMap, rootSchema, refStack, objectStack, state, path, depth);
|
|
11545
|
+
}
|
|
11546
|
+
const out = {};
|
|
11547
|
+
const issues = [];
|
|
11548
|
+
for (const [key, value] of Object.entries(schemaMap)) {
|
|
11549
|
+
const result2 = dereferenceSchema(
|
|
11550
|
+
value,
|
|
11551
|
+
rootSchema,
|
|
11552
|
+
refStack,
|
|
11553
|
+
objectStack,
|
|
11554
|
+
state,
|
|
11555
|
+
`${path}.${key}`,
|
|
11556
|
+
depth
|
|
11557
|
+
);
|
|
11558
|
+
out[key] = result2.schema;
|
|
11559
|
+
issues.push(...result2.issues);
|
|
11560
|
+
}
|
|
11561
|
+
return { schema: out, issues };
|
|
11562
|
+
}
|
|
11563
|
+
function dereferenceSchema(schema, rootSchema = schema, refStack = /* @__PURE__ */ new Set(), objectStack = /* @__PURE__ */ new Set(), state = { nodes: 0 }, path = "$", depth = 0) {
|
|
11564
|
+
if (depth > MAX_SCHEMA_DEREFERENCE_DEPTH) {
|
|
11565
|
+
return {
|
|
11566
|
+
schema: {},
|
|
11567
|
+
issues: [
|
|
11568
|
+
{
|
|
11569
|
+
path,
|
|
11570
|
+
ref: "(depth limit)",
|
|
11571
|
+
reason: `schema expansion exceeded ${MAX_SCHEMA_DEREFERENCE_DEPTH} levels`
|
|
11572
|
+
}
|
|
11573
|
+
]
|
|
11574
|
+
};
|
|
11575
|
+
}
|
|
11576
|
+
state.nodes += 1;
|
|
11577
|
+
if (state.nodes > MAX_SCHEMA_DEREFERENCE_NODES) {
|
|
11578
|
+
return {
|
|
11579
|
+
schema: {},
|
|
11580
|
+
issues: [
|
|
11581
|
+
{
|
|
11582
|
+
path,
|
|
11583
|
+
ref: "(node limit)",
|
|
11584
|
+
reason: `schema expansion exceeded ${MAX_SCHEMA_DEREFERENCE_NODES} nodes`
|
|
11585
|
+
}
|
|
11586
|
+
]
|
|
11587
|
+
};
|
|
11588
|
+
}
|
|
11589
|
+
if (!schema || typeof schema !== "object") return { schema, issues: [] };
|
|
11590
|
+
if (Array.isArray(schema)) {
|
|
11591
|
+
const results = schema.map(
|
|
11592
|
+
(item, index) => dereferenceSchema(
|
|
11593
|
+
item,
|
|
11594
|
+
rootSchema,
|
|
11595
|
+
refStack,
|
|
11596
|
+
objectStack,
|
|
11597
|
+
state,
|
|
11598
|
+
`${path}[${index}]`,
|
|
11599
|
+
depth + 1
|
|
11600
|
+
)
|
|
11601
|
+
);
|
|
11602
|
+
return {
|
|
11603
|
+
schema: results.map((result2) => result2.schema),
|
|
11604
|
+
issues: results.flatMap((result2) => result2.issues)
|
|
11605
|
+
};
|
|
11606
|
+
}
|
|
11607
|
+
const s = schema;
|
|
11608
|
+
if (objectStack.has(s)) {
|
|
11609
|
+
return {
|
|
11610
|
+
schema: {},
|
|
11611
|
+
issues: [{ path, ref: "(object cycle)", reason: "circular schema object" }]
|
|
11612
|
+
};
|
|
11613
|
+
}
|
|
11614
|
+
const nextObjectStack = new Set(objectStack);
|
|
11615
|
+
nextObjectStack.add(s);
|
|
11616
|
+
if (typeof s.$ref === "string") {
|
|
11617
|
+
const ref = s.$ref;
|
|
11618
|
+
if (refStack.has(ref)) {
|
|
11619
|
+
return {
|
|
11620
|
+
schema: {},
|
|
11621
|
+
issues: [{ path, ref, reason: "circular local reference" }]
|
|
11622
|
+
};
|
|
11623
|
+
}
|
|
11624
|
+
const target = resolveLocalJsonPointer(ref, rootSchema);
|
|
11625
|
+
if (target === void 0) {
|
|
11626
|
+
return {
|
|
11627
|
+
schema: {},
|
|
11628
|
+
issues: [{ path, ref, reason: "target is not present in the root schema" }]
|
|
11629
|
+
};
|
|
11630
|
+
}
|
|
11631
|
+
const nextRefStack = new Set(refStack);
|
|
11632
|
+
nextRefStack.add(ref);
|
|
11633
|
+
const resolved = dereferenceSchema(
|
|
11634
|
+
target,
|
|
11635
|
+
rootSchema,
|
|
11636
|
+
nextRefStack,
|
|
11637
|
+
nextObjectStack,
|
|
11638
|
+
state,
|
|
11639
|
+
path,
|
|
11640
|
+
depth + 1
|
|
11641
|
+
);
|
|
11642
|
+
const { $ref: _, ...siblings } = s;
|
|
11643
|
+
const siblingResult = dereferenceSchema(
|
|
11644
|
+
siblings,
|
|
11645
|
+
rootSchema,
|
|
11646
|
+
refStack,
|
|
11647
|
+
nextObjectStack,
|
|
11648
|
+
state,
|
|
11649
|
+
path,
|
|
11650
|
+
depth + 1
|
|
11651
|
+
);
|
|
11652
|
+
if (isRecord2(resolved.schema) && isRecord2(siblingResult.schema)) {
|
|
11653
|
+
return {
|
|
11654
|
+
schema: { ...resolved.schema, ...siblingResult.schema },
|
|
11655
|
+
issues: [...resolved.issues, ...siblingResult.issues]
|
|
11656
|
+
};
|
|
11657
|
+
}
|
|
11658
|
+
return {
|
|
11659
|
+
schema: resolved.schema,
|
|
11660
|
+
issues: [...resolved.issues, ...siblingResult.issues]
|
|
11661
|
+
};
|
|
11662
|
+
}
|
|
11663
|
+
const out = {};
|
|
11664
|
+
const issues = [];
|
|
11665
|
+
for (const [key, value] of Object.entries(s)) {
|
|
11666
|
+
if (key === "$defs" || key === "definitions") continue;
|
|
11667
|
+
let result2;
|
|
11668
|
+
if (SCHEMA_MAP_KEYWORDS.has(key)) {
|
|
11669
|
+
result2 = dereferenceSchemaMap(
|
|
11670
|
+
value,
|
|
11671
|
+
rootSchema,
|
|
11672
|
+
refStack,
|
|
11673
|
+
nextObjectStack,
|
|
11674
|
+
state,
|
|
11675
|
+
`${path}.${key}`,
|
|
11676
|
+
depth + 1
|
|
11677
|
+
);
|
|
11678
|
+
} else if (SCHEMA_VALUE_KEYWORDS.has(key) || SCHEMA_ARRAY_KEYWORDS.has(key)) {
|
|
11679
|
+
result2 = dereferenceSchema(
|
|
11680
|
+
value,
|
|
11681
|
+
rootSchema,
|
|
11682
|
+
refStack,
|
|
11683
|
+
nextObjectStack,
|
|
11684
|
+
state,
|
|
11685
|
+
`${path}.${key}`,
|
|
11686
|
+
depth + 1
|
|
11687
|
+
);
|
|
11688
|
+
}
|
|
11689
|
+
if (result2) {
|
|
11690
|
+
out[key] = result2.schema;
|
|
11691
|
+
issues.push(...result2.issues);
|
|
11692
|
+
} else {
|
|
11693
|
+
out[key] = value;
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11696
|
+
return { schema: out, issues };
|
|
11697
|
+
}
|
|
11698
|
+
function ensureRootObjectSchema(schema) {
|
|
11699
|
+
if (!isRecord2(schema)) {
|
|
11700
|
+
return { type: "object", properties: {} };
|
|
11701
|
+
}
|
|
11702
|
+
if (!schema.type) {
|
|
11703
|
+
return { ...schema, type: "object", properties: schema.properties || {} };
|
|
11704
|
+
}
|
|
11705
|
+
return schema;
|
|
11706
|
+
}
|
|
11707
|
+
var META_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
11708
|
+
"$schema",
|
|
11709
|
+
"$id",
|
|
11710
|
+
"$anchor",
|
|
11711
|
+
"$dynamicAnchor",
|
|
11712
|
+
"$vocabulary",
|
|
11713
|
+
"$comment",
|
|
11714
|
+
"$defs",
|
|
11715
|
+
"definitions"
|
|
11716
|
+
]);
|
|
11717
|
+
function stripMetaSchemaMap(schemaMap) {
|
|
11718
|
+
if (!isRecord2(schemaMap)) return stripMetaSchema(schemaMap);
|
|
11719
|
+
return Object.fromEntries(
|
|
11720
|
+
Object.entries(schemaMap).map(([key, value]) => [key, stripMetaSchema(value)])
|
|
11721
|
+
);
|
|
11722
|
+
}
|
|
11723
|
+
function stripMetaSchema(schema) {
|
|
11724
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
11725
|
+
if (Array.isArray(schema)) return schema.map(stripMetaSchema);
|
|
11726
|
+
const out = {};
|
|
11727
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
11728
|
+
if (META_SCHEMA_KEYWORDS.has(key)) continue;
|
|
11729
|
+
if (SCHEMA_MAP_KEYWORDS.has(key)) {
|
|
11730
|
+
out[key] = stripMetaSchemaMap(value);
|
|
11731
|
+
} else if (SCHEMA_VALUE_KEYWORDS.has(key) || SCHEMA_ARRAY_KEYWORDS.has(key)) {
|
|
11732
|
+
out[key] = stripMetaSchema(value);
|
|
11733
|
+
} else {
|
|
11734
|
+
out[key] = value;
|
|
11735
|
+
}
|
|
11736
|
+
}
|
|
11737
|
+
return out;
|
|
11738
|
+
}
|
|
11739
|
+
var CUSTOM_TOOL_SCHEMA_ALLOW = /* @__PURE__ */ new Set([
|
|
11740
|
+
"type",
|
|
11741
|
+
"description",
|
|
11742
|
+
"properties",
|
|
11743
|
+
"required",
|
|
11744
|
+
"items",
|
|
11745
|
+
"enum"
|
|
11746
|
+
]);
|
|
11747
|
+
function normalizeCustomToolType(value) {
|
|
11748
|
+
if (typeof value === "string") return value;
|
|
11749
|
+
if (!Array.isArray(value)) return void 0;
|
|
11750
|
+
const entries = value;
|
|
11751
|
+
const scalar = entries.find(
|
|
11752
|
+
(entry) => typeof entry === "string" && entry !== "null"
|
|
11753
|
+
);
|
|
11754
|
+
return scalar;
|
|
11755
|
+
}
|
|
11756
|
+
function normalizeCustomToolSchema(schema) {
|
|
11757
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
11758
|
+
if (Array.isArray(schema)) return schema.map(normalizeCustomToolSchema);
|
|
11759
|
+
const out = {};
|
|
11760
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
11761
|
+
if (!CUSTOM_TOOL_SCHEMA_ALLOW.has(key)) continue;
|
|
11762
|
+
if (key === "type") {
|
|
11763
|
+
const normalizedType = normalizeCustomToolType(value);
|
|
11764
|
+
if (normalizedType !== void 0) out.type = normalizedType;
|
|
11765
|
+
continue;
|
|
11766
|
+
}
|
|
11767
|
+
if (key === "properties" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
11768
|
+
const props = {};
|
|
11769
|
+
for (const [propName, propSchema] of Object.entries(value)) {
|
|
11770
|
+
props[propName] = normalizeCustomToolSchema(propSchema);
|
|
11771
|
+
}
|
|
11772
|
+
out.properties = props;
|
|
11773
|
+
continue;
|
|
11774
|
+
}
|
|
11775
|
+
if (key === "enum" && Array.isArray(value) && !value.every((entry) => typeof entry === "string")) {
|
|
11776
|
+
continue;
|
|
11777
|
+
}
|
|
11778
|
+
out[key] = normalizeCustomToolSchema(value);
|
|
11779
|
+
}
|
|
11780
|
+
return out;
|
|
11781
|
+
}
|
|
11782
|
+
function convertTools(tools, useLegacyParameters = false) {
|
|
11783
|
+
if (!tools?.length) return void 0;
|
|
11784
|
+
const warnings = [];
|
|
11785
|
+
const functionDeclarations = tools.flatMap((tool) => {
|
|
11786
|
+
const dereferenced = dereferenceSchema(tool.parameters);
|
|
11787
|
+
if (dereferenced.issues.length > 0) {
|
|
11788
|
+
const detail = dereferenced.issues.map((issue) => `${issue.path} (${issue.ref}: ${issue.reason})`).join(", ");
|
|
11789
|
+
warnings.push(`Skipped tool '${tool.name}' due to unresolved schema reference: ${detail}`);
|
|
11790
|
+
return [];
|
|
11791
|
+
}
|
|
11792
|
+
const rootObject = ensureRootObjectSchema(dereferenced.schema);
|
|
11793
|
+
const schema = stripMetaSchema(rootObject);
|
|
11794
|
+
return [
|
|
11795
|
+
{
|
|
11796
|
+
name: tool.name,
|
|
11797
|
+
description: tool.description,
|
|
11798
|
+
...useLegacyParameters ? { parameters: normalizeCustomToolSchema(schema) } : { parametersJsonSchema: schema }
|
|
11799
|
+
}
|
|
11800
|
+
];
|
|
11801
|
+
});
|
|
11802
|
+
setLastToolSchemaWarnings(warnings.length ? warnings : void 0);
|
|
11803
|
+
if (!functionDeclarations.length) return void 0;
|
|
11804
|
+
return [{ functionDeclarations }];
|
|
11805
|
+
}
|
|
11806
|
+
function mapToolChoiceMode(toolChoice) {
|
|
11807
|
+
if (toolChoice === ToolChoice.None) return GeminiToolCallingMode.None;
|
|
11808
|
+
if (toolChoice === ToolChoice.Any || toolChoice === ToolChoice.Required)
|
|
11809
|
+
return GeminiToolCallingMode.Any;
|
|
11810
|
+
return GeminiToolCallingMode.Auto;
|
|
11811
|
+
}
|
|
11812
|
+
function buildRequest(model, context, projectId, options, runtimeModel) {
|
|
11813
|
+
const injectedSkills = context.messages.flatMap(
|
|
11814
|
+
(msg) => msg.role === "user" ? skillBlocks(msg.content) : []
|
|
11815
|
+
);
|
|
11816
|
+
const systemParts = context.systemPrompt ? [{ text: sanitizeText(context.systemPrompt) }] : [{ text: ANTIGRAVITY_SYSTEM_INSTRUCTION }, { text: ANTIGRAVITY_NO_PREAMBLE_INSTRUCTION }];
|
|
11817
|
+
systemParts.push(...injectedSkills.map((skill) => ({ text: sanitizeText(skill) })));
|
|
11818
|
+
const contents = convertMessages(model, context, runtimeModel);
|
|
11819
|
+
const hasUserText = contents.some(
|
|
11820
|
+
(turn) => turn.role === GeminiRole.User && turn.parts.some((part) => "text" in part && Boolean(part.text.trim()))
|
|
11821
|
+
);
|
|
11822
|
+
if (!hasUserText && (injectedSkills.length > 0 || Boolean(context.systemPrompt))) {
|
|
11823
|
+
contents.unshift({
|
|
11824
|
+
role: GeminiRole.User,
|
|
11825
|
+
parts: [{ text: "Apply the active system instructions." }]
|
|
11826
|
+
});
|
|
11827
|
+
}
|
|
11828
|
+
const request = {
|
|
11829
|
+
contents,
|
|
11830
|
+
systemInstruction: {
|
|
11831
|
+
role: GeminiRole.User,
|
|
11832
|
+
parts: systemParts
|
|
11833
|
+
}
|
|
11834
|
+
};
|
|
11835
|
+
const generationConfig = {};
|
|
11836
|
+
if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
|
|
11837
|
+
const thinking = getThinkingConfig(runtimeModel, options.reasoning ?? "off");
|
|
11838
|
+
if (thinking) generationConfig.thinkingConfig = thinking;
|
|
11839
|
+
const maxAllowed = getMaxOutputTokens(model.id, runtimeModel);
|
|
11840
|
+
if (options.maxTokens !== void 0) {
|
|
11841
|
+
generationConfig.maxOutputTokens = Math.min(options.maxTokens, maxAllowed);
|
|
11842
|
+
} else {
|
|
11843
|
+
generationConfig.maxOutputTokens = Math.min(maxAllowed, model.maxTokens || maxAllowed);
|
|
11844
|
+
}
|
|
11845
|
+
if (Object.keys(generationConfig).length) request.generationConfig = generationConfig;
|
|
11846
|
+
const isClaude = model.id.startsWith("claude-") || runtimeModel.startsWith("claude-");
|
|
11847
|
+
const tools = convertTools(context.tools, isClaude || model.id.startsWith("gpt-oss-"));
|
|
11848
|
+
if (tools) {
|
|
11849
|
+
request.tools = tools;
|
|
11850
|
+
}
|
|
11851
|
+
if (options.toolChoice && options.toolChoice !== ToolChoice.Auto) {
|
|
11852
|
+
request.toolConfig = {
|
|
11853
|
+
functionCallingConfig: {
|
|
11854
|
+
mode: mapToolChoiceMode(options.toolChoice)
|
|
11855
|
+
}
|
|
11856
|
+
};
|
|
11857
|
+
}
|
|
11858
|
+
const isNonGemini = isClaude || model.id.startsWith("gpt-oss-") || runtimeModel.startsWith("gpt-oss-") || !model.id.startsWith("gemini-") && !runtimeModel.startsWith("gemini-");
|
|
11859
|
+
const step = Math.max(1, request.contents.length);
|
|
11860
|
+
const lastStepIndex = String(Math.max(0, request.contents.length - 1));
|
|
11861
|
+
const requestIndex = context.messages?.filter(
|
|
11862
|
+
(m) => m.role === "assistant" && m.stopReason !== "error" && m.stopReason !== "aborted"
|
|
11863
|
+
).length ?? 0;
|
|
11864
|
+
const { conversationId, trajectoryId } = resolveSessionTrajectory(context);
|
|
11865
|
+
const envelope = antigravityRequestEnvelope(runtimeModel, {
|
|
11866
|
+
isClaude,
|
|
11867
|
+
isNonGemini,
|
|
11868
|
+
step,
|
|
11869
|
+
lastStepIndex,
|
|
11870
|
+
requestIndex,
|
|
11871
|
+
conversationId,
|
|
11872
|
+
trajectoryId
|
|
11873
|
+
});
|
|
11874
|
+
request.sessionId = options.sessionId || envelope.sessionId;
|
|
11875
|
+
request.labels = envelope.labels;
|
|
11876
|
+
return {
|
|
11877
|
+
project: projectId,
|
|
11878
|
+
model: runtimeModel,
|
|
11879
|
+
request,
|
|
11880
|
+
requestType: AntigravityRequestType.Agent,
|
|
11881
|
+
userAgent: AntigravityUserAgent.Antigravity,
|
|
11882
|
+
requestId: envelope.requestId
|
|
11883
|
+
};
|
|
11884
|
+
}
|
|
11885
|
+
function mapStopReason(reason) {
|
|
11886
|
+
if (reason === "STOP") return StopReason.Stop;
|
|
11887
|
+
if (reason === "MAX_TOKENS") return StopReason.Length;
|
|
11888
|
+
return reason ? StopReason.Error : StopReason.Stop;
|
|
11889
|
+
}
|
|
11890
|
+
function friendlyAntigravityError(status, text) {
|
|
11891
|
+
const msg = redactSecrets2(jsonOrTextError(text)).slice(0, 500);
|
|
11892
|
+
if (status === 400) {
|
|
11893
|
+
if (/API key not valid|API_KEY_INVALID/i.test(msg)) {
|
|
11894
|
+
return "Antigravity login expired or credentials are invalid. Next: run /login antigravity, then retry.";
|
|
11895
|
+
}
|
|
11896
|
+
if (/Invalid JSON payload|Unknown name/i.test(msg)) {
|
|
11897
|
+
return `Antigravity request format was rejected by the backend (${msg}). Next: switch to a simpler model or retry after updating the extension.`;
|
|
11898
|
+
}
|
|
11899
|
+
if (/Request contains an invalid argument/i.test(msg)) {
|
|
11900
|
+
return `Antigravity rejected this request (${msg}). Next: retry once; if it keeps failing, switch models or re-login.`;
|
|
11901
|
+
}
|
|
11902
|
+
return `Bad request from Antigravity. Next: retry once, then run /login antigravity if it keeps failing. Backend said: ${msg}`;
|
|
11903
|
+
}
|
|
11904
|
+
if (status === 401) {
|
|
11905
|
+
return "Antigravity authentication failed. Next: run /login antigravity, then retry.";
|
|
11906
|
+
}
|
|
11907
|
+
if (status === 403) {
|
|
11908
|
+
if (/permission|forbidden|access/i.test(msg)) {
|
|
11909
|
+
return "Antigravity access was denied for this account or project. Next: try another model, re-login, or use an account with access.";
|
|
11910
|
+
}
|
|
11911
|
+
return `Antigravity denied this request. Next: re-login or try another model. Backend said: ${msg}`;
|
|
11912
|
+
}
|
|
11913
|
+
if (status === 404) {
|
|
11914
|
+
if (/Requested entity was not found/i.test(msg)) {
|
|
11915
|
+
return "This model is not available right now. Next: switch to gemini-3.8-flash, gemini-3.7-flash, gemini-3.6-flash, gemini-3.5-flash, gemini-3.1-pro, or another working model.";
|
|
11916
|
+
}
|
|
11917
|
+
return `Antigravity could not find the requested resource. Next: retry or switch models. Backend said: ${msg}`;
|
|
11918
|
+
}
|
|
11919
|
+
if (status === 408) return "Antigravity timed out. Next: retry the same request.";
|
|
11920
|
+
if (status === 409) {
|
|
11921
|
+
return "Antigravity reported a conflict for this request. Next: retry once or start a new chat session.";
|
|
11922
|
+
}
|
|
11923
|
+
if (status === 429) {
|
|
11924
|
+
const wait = msg.match(/Resets? in ([^.\n]+)/i)?.[1]?.trim();
|
|
11925
|
+
if (/Individual quota reached/i.test(msg)) {
|
|
11926
|
+
return `Quota reached. Please wait ${wait || "for reset"}. Next: switch models or try again after reset.`;
|
|
11927
|
+
}
|
|
11928
|
+
if (/quota/i.test(msg)) {
|
|
11929
|
+
return `Quota reached.${wait ? ` Please wait ${wait}.` : ""} Next: switch models or retry later.`;
|
|
11930
|
+
}
|
|
11931
|
+
return `Rate limited by Antigravity. Next: wait a bit and retry.${wait ? ` Reset: ${wait}.` : ""}`;
|
|
11932
|
+
}
|
|
11933
|
+
if (status === 500) {
|
|
11934
|
+
return "Antigravity had an internal server error. Next: retry in a moment or switch models.";
|
|
11935
|
+
}
|
|
11936
|
+
if (status === 502) return "Antigravity returned a bad gateway error. Next: retry in a moment.";
|
|
11937
|
+
if (status === 503) {
|
|
11938
|
+
if (/No capacity available/i.test(msg)) {
|
|
11939
|
+
return "This model has no capacity right now. Next: retry later or switch to another model.";
|
|
11940
|
+
}
|
|
11941
|
+
return "Antigravity is temporarily unavailable. Next: retry in a moment or switch models.";
|
|
11942
|
+
}
|
|
11943
|
+
if (status === 504) return "Antigravity timed out upstream. Next: retry in a moment.";
|
|
11944
|
+
return msg;
|
|
11945
|
+
}
|
|
11946
|
+
function createOutput(model) {
|
|
11947
|
+
return {
|
|
11948
|
+
role: "assistant",
|
|
11949
|
+
content: [],
|
|
11950
|
+
api: ANTIGRAVITY_API,
|
|
11951
|
+
provider: PROVIDER_ID,
|
|
11952
|
+
model: model.id,
|
|
11953
|
+
usage: {
|
|
11954
|
+
input: 0,
|
|
11955
|
+
output: 0,
|
|
11956
|
+
cacheRead: 0,
|
|
11957
|
+
cacheWrite: 0,
|
|
11958
|
+
totalTokens: 0,
|
|
11959
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
11960
|
+
},
|
|
11961
|
+
stopReason: "stop",
|
|
11962
|
+
timestamp: Date.now()
|
|
11963
|
+
};
|
|
11964
|
+
}
|
|
11965
|
+
function asToolCallArguments(args) {
|
|
11966
|
+
return args ?? {};
|
|
11967
|
+
}
|
|
11968
|
+
var STREAM_HEADER_TIMEOUT_DEFAULT_MS = 18e4;
|
|
11969
|
+
var STREAM_STALL_TIMEOUT_DEFAULT_MS = 12e4;
|
|
11970
|
+
function envTimeoutMs(name, fallback) {
|
|
11971
|
+
const raw = antigravityEnv(name);
|
|
11972
|
+
if (!raw || !/^\d+$/.test(raw)) return fallback;
|
|
11973
|
+
const value = Number(raw);
|
|
11974
|
+
return Number.isSafeInteger(value) ? value : fallback;
|
|
11975
|
+
}
|
|
11976
|
+
function streamHeaderTimeoutMs() {
|
|
11977
|
+
return envTimeoutMs("STREAM_HEADER_TIMEOUT_MS", STREAM_HEADER_TIMEOUT_DEFAULT_MS);
|
|
11978
|
+
}
|
|
11979
|
+
function streamStallTimeoutMs() {
|
|
11980
|
+
return envTimeoutMs("STREAM_STALL_TIMEOUT_MS", STREAM_STALL_TIMEOUT_DEFAULT_MS);
|
|
11981
|
+
}
|
|
11982
|
+
function stallError(stallMs) {
|
|
11983
|
+
return new Error(`stream stalled: no data for ${stallMs}ms`);
|
|
11984
|
+
}
|
|
11985
|
+
function guardResponseBody(response, controller, stallMs, cleanup) {
|
|
11986
|
+
if (!response.body) {
|
|
11987
|
+
cleanup();
|
|
11988
|
+
return response;
|
|
11989
|
+
}
|
|
11990
|
+
const reader = response.body.getReader();
|
|
11991
|
+
let timer;
|
|
11992
|
+
let finished = false;
|
|
11993
|
+
const finish = () => {
|
|
11994
|
+
if (finished) return;
|
|
11995
|
+
finished = true;
|
|
11996
|
+
if (timer) clearTimeout(timer);
|
|
11997
|
+
cleanup();
|
|
11998
|
+
};
|
|
11999
|
+
const reset = () => {
|
|
12000
|
+
if (stallMs <= 0) return;
|
|
12001
|
+
if (timer) clearTimeout(timer);
|
|
12002
|
+
timer = setTimeout(() => controller.abort(stallError(stallMs)), stallMs);
|
|
12003
|
+
timer.unref?.();
|
|
12004
|
+
};
|
|
12005
|
+
let streamController;
|
|
12006
|
+
const abortBody = () => {
|
|
12007
|
+
streamController?.error(controller.signal.reason);
|
|
12008
|
+
void reader.cancel(controller.signal.reason).catch(() => void 0);
|
|
12009
|
+
finish();
|
|
12010
|
+
};
|
|
12011
|
+
controller.signal.addEventListener("abort", abortBody, { once: true });
|
|
12012
|
+
reset();
|
|
12013
|
+
const guarded = new ReadableStream({
|
|
12014
|
+
start(controller2) {
|
|
12015
|
+
streamController = controller2;
|
|
12016
|
+
},
|
|
12017
|
+
async pull(streamController2) {
|
|
12018
|
+
try {
|
|
12019
|
+
const chunk = await reader.read();
|
|
12020
|
+
if (chunk.done) {
|
|
12021
|
+
finish();
|
|
12022
|
+
streamController2.close();
|
|
12023
|
+
return;
|
|
12024
|
+
}
|
|
12025
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
12026
|
+
throw new Error("Response body yielded an invalid chunk");
|
|
12027
|
+
}
|
|
12028
|
+
reset();
|
|
12029
|
+
streamController2.enqueue(chunk.value);
|
|
12030
|
+
} catch (error) {
|
|
12031
|
+
finish();
|
|
12032
|
+
streamController2.error(error);
|
|
12033
|
+
}
|
|
12034
|
+
},
|
|
12035
|
+
async cancel(reason) {
|
|
12036
|
+
finish();
|
|
12037
|
+
await reader.cancel(reason);
|
|
12038
|
+
}
|
|
12039
|
+
});
|
|
12040
|
+
return new Response(guarded, response);
|
|
12041
|
+
}
|
|
12042
|
+
async function fetchWithHeaderDeadline(url, init, callerSignal, timeoutMs, stallMs = 0, fetchFn = antigravityFetch) {
|
|
12043
|
+
if (timeoutMs <= 0 && stallMs <= 0) {
|
|
12044
|
+
return fetchFn(url, { ...init, signal: callerSignal ?? init.signal });
|
|
12045
|
+
}
|
|
12046
|
+
const controller = new AbortController();
|
|
12047
|
+
const forward = () => controller.abort(callerSignal?.reason);
|
|
12048
|
+
const cleanup = () => callerSignal?.removeEventListener("abort", forward);
|
|
12049
|
+
callerSignal?.addEventListener("abort", forward, { once: true });
|
|
12050
|
+
if (callerSignal?.aborted) forward();
|
|
12051
|
+
const timer = timeoutMs > 0 ? setTimeout(
|
|
12052
|
+
() => controller.abort(new Error(`no response headers within ${timeoutMs}ms`)),
|
|
12053
|
+
timeoutMs
|
|
12054
|
+
) : void 0;
|
|
12055
|
+
let responseBodyGuarded = false;
|
|
12056
|
+
try {
|
|
12057
|
+
const response = await fetchFn(url, { ...init, signal: controller.signal });
|
|
12058
|
+
responseBodyGuarded = Boolean(response.body);
|
|
12059
|
+
return guardResponseBody(response, controller, stallMs, cleanup);
|
|
12060
|
+
} finally {
|
|
12061
|
+
if (timer) clearTimeout(timer);
|
|
12062
|
+
if (!responseBodyGuarded) cleanup();
|
|
12063
|
+
}
|
|
12064
|
+
}
|
|
12065
|
+
async function streamResponse(response, stream, output, model) {
|
|
12066
|
+
if (!response.body) throw new Error("No response body");
|
|
12067
|
+
const reader = response.body.getReader();
|
|
12068
|
+
const decoder = new TextDecoder();
|
|
12069
|
+
let buffer = "";
|
|
12070
|
+
let scanStart = 0;
|
|
12071
|
+
let started = false;
|
|
12072
|
+
let currentBlock = null;
|
|
12073
|
+
let hasContent = false;
|
|
12074
|
+
const blocks = output.content;
|
|
12075
|
+
const blockIndex = () => blocks.length - 1;
|
|
12076
|
+
const ensureStarted = () => {
|
|
12077
|
+
if (!started) {
|
|
12078
|
+
stream.push({ type: "start", partial: output });
|
|
12079
|
+
started = true;
|
|
12080
|
+
}
|
|
12081
|
+
};
|
|
12082
|
+
const finishCurrent = () => {
|
|
12083
|
+
if (!currentBlock) return;
|
|
12084
|
+
if (currentBlock.type === "text") {
|
|
12085
|
+
stream.push({
|
|
12086
|
+
type: "text_end",
|
|
12087
|
+
contentIndex: blockIndex(),
|
|
12088
|
+
content: currentBlock.text,
|
|
12089
|
+
partial: output
|
|
12090
|
+
});
|
|
12091
|
+
} else {
|
|
12092
|
+
stream.push({
|
|
12093
|
+
type: "thinking_end",
|
|
12094
|
+
contentIndex: blockIndex(),
|
|
12095
|
+
content: currentBlock.thinking,
|
|
12096
|
+
partial: output
|
|
12097
|
+
});
|
|
12098
|
+
}
|
|
12099
|
+
currentBlock = null;
|
|
12100
|
+
};
|
|
12101
|
+
while (true) {
|
|
12102
|
+
const result2 = await reader.read();
|
|
12103
|
+
if (result2.done) break;
|
|
12104
|
+
if (!(result2.value instanceof Uint8Array)) continue;
|
|
12105
|
+
buffer += decoder.decode(result2.value, { stream: true });
|
|
12106
|
+
let newlineIdx;
|
|
12107
|
+
while ((newlineIdx = buffer.indexOf("\n", scanStart)) !== -1) {
|
|
12108
|
+
const line = buffer.slice(scanStart, newlineIdx);
|
|
12109
|
+
scanStart = newlineIdx + 1;
|
|
12110
|
+
if (!line.startsWith("data:")) continue;
|
|
12111
|
+
const json = line.slice(5).trim();
|
|
12112
|
+
if (!json || json === "[DONE]") continue;
|
|
12113
|
+
let chunk;
|
|
12114
|
+
try {
|
|
12115
|
+
chunk = JSON.parse(json);
|
|
12116
|
+
} catch {
|
|
12117
|
+
continue;
|
|
12118
|
+
}
|
|
12119
|
+
if (chunk.error) {
|
|
12120
|
+
throw new Error(chunk.error.message || JSON.stringify(chunk.error));
|
|
12121
|
+
}
|
|
12122
|
+
const responseData = chunk.response || chunk;
|
|
12123
|
+
const candidate = responseData.candidates?.[0];
|
|
12124
|
+
for (const part of candidate?.content?.parts || []) {
|
|
12125
|
+
if (part.text !== void 0) {
|
|
12126
|
+
hasContent = true;
|
|
12127
|
+
const isThinking = part.thought === true;
|
|
12128
|
+
const type = isThinking ? "thinking" : "text";
|
|
12129
|
+
if (!currentBlock || currentBlock.type !== type) {
|
|
12130
|
+
finishCurrent();
|
|
12131
|
+
currentBlock = isThinking ? { type: "thinking", thinking: "", thinkingSignature: void 0 } : { type: "text", text: "" };
|
|
12132
|
+
blocks.push(currentBlock);
|
|
12133
|
+
ensureStarted();
|
|
12134
|
+
stream.push({
|
|
12135
|
+
type: isThinking ? "thinking_start" : "text_start",
|
|
12136
|
+
contentIndex: blockIndex(),
|
|
12137
|
+
partial: output
|
|
12138
|
+
});
|
|
12139
|
+
}
|
|
12140
|
+
if (isThinking && currentBlock.type === "thinking") {
|
|
12141
|
+
currentBlock.thinking += part.text;
|
|
12142
|
+
if (part.thoughtSignature) currentBlock.thinkingSignature = part.thoughtSignature;
|
|
12143
|
+
stream.push({
|
|
12144
|
+
type: "thinking_delta",
|
|
12145
|
+
contentIndex: blockIndex(),
|
|
12146
|
+
delta: part.text,
|
|
12147
|
+
partial: output
|
|
12148
|
+
});
|
|
12149
|
+
} else if (!isThinking && currentBlock.type === "text") {
|
|
12150
|
+
currentBlock.text += part.text;
|
|
12151
|
+
if (part.thoughtSignature) currentBlock.textSignature = part.thoughtSignature;
|
|
12152
|
+
stream.push({
|
|
12153
|
+
type: "text_delta",
|
|
12154
|
+
contentIndex: blockIndex(),
|
|
12155
|
+
delta: part.text,
|
|
12156
|
+
partial: output
|
|
12157
|
+
});
|
|
12158
|
+
}
|
|
12159
|
+
}
|
|
12160
|
+
if (part.functionCall) {
|
|
12161
|
+
hasContent = true;
|
|
12162
|
+
finishCurrent();
|
|
12163
|
+
const rawId = part.functionCall.id || "";
|
|
12164
|
+
const toolCall = {
|
|
12165
|
+
type: "toolCall",
|
|
12166
|
+
id: sanitizeToolCallId(rawId, part.functionCall.name),
|
|
12167
|
+
name: part.functionCall.name || "",
|
|
12168
|
+
arguments: asToolCallArguments(part.functionCall.args),
|
|
12169
|
+
...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
|
|
12170
|
+
};
|
|
12171
|
+
blocks.push(toolCall);
|
|
12172
|
+
ensureStarted();
|
|
12173
|
+
stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
|
|
12174
|
+
stream.push({
|
|
12175
|
+
type: "toolcall_delta",
|
|
12176
|
+
contentIndex: blockIndex(),
|
|
12177
|
+
delta: JSON.stringify(toolCall.arguments),
|
|
12178
|
+
partial: output
|
|
12179
|
+
});
|
|
12180
|
+
stream.push({
|
|
12181
|
+
type: "toolcall_end",
|
|
12182
|
+
contentIndex: blockIndex(),
|
|
12183
|
+
toolCall,
|
|
12184
|
+
partial: output
|
|
12185
|
+
});
|
|
12186
|
+
}
|
|
12187
|
+
}
|
|
12188
|
+
if (candidate?.finishReason) {
|
|
12189
|
+
output.rawStopReason = candidate.finishReason;
|
|
12190
|
+
output.stopReason = blocks.some((b) => b.type === "toolCall") ? StopReason.ToolUse : mapStopReason(candidate.finishReason);
|
|
12191
|
+
}
|
|
12192
|
+
if (responseData.usageMetadata) {
|
|
12193
|
+
const prompt = responseData.usageMetadata.promptTokenCount || 0;
|
|
12194
|
+
const cacheRead = responseData.usageMetadata.cachedContentTokenCount || 0;
|
|
12195
|
+
const thoughts = responseData.usageMetadata.thoughtsTokenCount || 0;
|
|
12196
|
+
output.usage.input = prompt - cacheRead;
|
|
12197
|
+
output.usage.output = (responseData.usageMetadata.candidatesTokenCount || 0) + thoughts;
|
|
12198
|
+
output.usage.reasoning = thoughts;
|
|
12199
|
+
output.usage.cacheRead = cacheRead;
|
|
12200
|
+
output.usage.totalTokens = responseData.usageMetadata.totalTokenCount || 0;
|
|
12201
|
+
if (model?.cost) {
|
|
12202
|
+
calculateCost(model, output.usage);
|
|
12203
|
+
} else {
|
|
12204
|
+
output.usage.cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
12205
|
+
}
|
|
12206
|
+
}
|
|
12207
|
+
}
|
|
12208
|
+
if (scanStart > 0) {
|
|
12209
|
+
buffer = buffer.slice(scanStart);
|
|
12210
|
+
scanStart = 0;
|
|
12211
|
+
}
|
|
12212
|
+
}
|
|
12213
|
+
finishCurrent();
|
|
12214
|
+
return hasContent;
|
|
12215
|
+
}
|
|
12216
|
+
function streamAntigravity(model, context, options) {
|
|
12217
|
+
const stream = createAssistantMessageEventStream();
|
|
12218
|
+
const opts = options ?? {};
|
|
12219
|
+
void runWithDiagnostics(async () => {
|
|
12220
|
+
const startTime = Date.now();
|
|
12221
|
+
const output = createOutput(model);
|
|
12222
|
+
try {
|
|
12223
|
+
const creds = parseApiKey(opts.apiKey);
|
|
12224
|
+
const warmedProject = creds.projectId ? null : await loadCodeAssist(creds.token);
|
|
12225
|
+
const projectId = resolveProjectId({
|
|
12226
|
+
token: creds.token,
|
|
12227
|
+
warmedProject,
|
|
12228
|
+
credentialProjectId: creds.projectId
|
|
12229
|
+
});
|
|
12230
|
+
setLastProjectId(projectId);
|
|
12231
|
+
const effort = opts.reasoning ?? "off";
|
|
12232
|
+
const isKnownModel = model.id in getCurrentAntigravityRouting();
|
|
12233
|
+
const baseRuntimeModel = antigravityEnv("RUNTIME_MODEL")?.trim() || getAntigravityRequestModelId(model.id, effort);
|
|
12234
|
+
let initialRuntimeModel = baseRuntimeModel;
|
|
12235
|
+
if (!isKnownModel && !antigravityEnv("RUNTIME_MODEL")) {
|
|
12236
|
+
const dynamic = await fetchAvailableRuntimeModel(creds.token, projectId, baseRuntimeModel);
|
|
12237
|
+
if (dynamic?.id && /^(gemini-|claude-|gpt-oss-)/i.test(dynamic.id)) {
|
|
12238
|
+
initialRuntimeModel = dynamic.id;
|
|
12239
|
+
}
|
|
12240
|
+
}
|
|
12241
|
+
const runtimeCandidates = [initialRuntimeModel];
|
|
12242
|
+
const fallback = getFallbackRuntimeModel(initialRuntimeModel, effort);
|
|
12243
|
+
if (fallback && fallback !== initialRuntimeModel) {
|
|
12244
|
+
runtimeCandidates.push(fallback);
|
|
12245
|
+
}
|
|
12246
|
+
const requestHeaders = antigravityHeaders(creds.token);
|
|
12247
|
+
let response;
|
|
12248
|
+
let lastText = "";
|
|
12249
|
+
let received = false;
|
|
12250
|
+
let runtimeModel = initialRuntimeModel;
|
|
12251
|
+
for (let emptyAttempt = 0; emptyAttempt <= 2; emptyAttempt++) {
|
|
12252
|
+
if (opts.signal?.aborted) throw new Error("Request was aborted");
|
|
12253
|
+
if (emptyAttempt > 0) {
|
|
12254
|
+
const delay = 500 * 2 ** (emptyAttempt - 1);
|
|
12255
|
+
await new Promise((res) => setTimeout(res, delay));
|
|
12256
|
+
}
|
|
12257
|
+
for (let candIdx = 0; candIdx < runtimeCandidates.length; candIdx++) {
|
|
12258
|
+
runtimeModel = runtimeCandidates[candIdx];
|
|
12259
|
+
setLastResolvedRuntimeModel(runtimeModel);
|
|
12260
|
+
const body = JSON.stringify(buildRequest(model, context, projectId, opts, runtimeModel));
|
|
12261
|
+
for (const endpoint of endpointCandidates()) {
|
|
12262
|
+
setLastEndpoint(endpoint);
|
|
12263
|
+
response = await fetchWithHeaderDeadline(
|
|
12264
|
+
`${endpoint}/v1internal:streamGenerateContent?alt=sse`,
|
|
12265
|
+
{
|
|
12266
|
+
method: "POST",
|
|
12267
|
+
headers: requestHeaders,
|
|
12268
|
+
body
|
|
12269
|
+
},
|
|
12270
|
+
opts.signal,
|
|
12271
|
+
streamHeaderTimeoutMs(),
|
|
12272
|
+
streamStallTimeoutMs()
|
|
12273
|
+
);
|
|
12274
|
+
setLastStatus(response.status);
|
|
12275
|
+
if (response.ok) break;
|
|
12276
|
+
lastText = await response.text();
|
|
12277
|
+
if (response.status === 429 && /Individual quota reached/i.test(lastText)) break;
|
|
12278
|
+
if (![403, 404, 429, 500, 502, 503, 504].includes(response.status)) break;
|
|
12279
|
+
}
|
|
12280
|
+
if (response?.ok) break;
|
|
12281
|
+
if (response?.status === 404) {
|
|
12282
|
+
if (candIdx + 1 < runtimeCandidates.length) {
|
|
12283
|
+
continue;
|
|
12284
|
+
}
|
|
12285
|
+
if (isKnownModel && candIdx === runtimeCandidates.length - 1) {
|
|
12286
|
+
const dynamic = await fetchAvailableRuntimeModel(
|
|
12287
|
+
creds.token,
|
|
12288
|
+
projectId,
|
|
12289
|
+
baseRuntimeModel
|
|
12290
|
+
);
|
|
12291
|
+
if (dynamic?.id && !runtimeCandidates.includes(dynamic.id) && /^(gemini-|claude-|gpt-oss-)/i.test(dynamic.id)) {
|
|
12292
|
+
runtimeCandidates.push(dynamic.id);
|
|
12293
|
+
continue;
|
|
12294
|
+
}
|
|
12295
|
+
}
|
|
12296
|
+
}
|
|
12297
|
+
break;
|
|
12298
|
+
}
|
|
12299
|
+
if (!response || !response.ok) {
|
|
12300
|
+
if (antigravityEnv("DEBUG_DUMP") === "1") {
|
|
12301
|
+
try {
|
|
12302
|
+
const body = JSON.stringify(
|
|
12303
|
+
buildRequest(model, context, projectId, opts, runtimeModel)
|
|
12304
|
+
);
|
|
12305
|
+
let parsedBody = body;
|
|
12306
|
+
try {
|
|
12307
|
+
parsedBody = JSON.parse(body);
|
|
12308
|
+
} catch {
|
|
12309
|
+
parsedBody = body;
|
|
12310
|
+
}
|
|
12311
|
+
await (await import("node:fs/promises")).writeFile(
|
|
12312
|
+
"/tmp/antigravity-last-request.json",
|
|
12313
|
+
JSON.stringify(
|
|
12314
|
+
{
|
|
12315
|
+
status: response?.status,
|
|
12316
|
+
runtimeModel,
|
|
12317
|
+
lastText: lastText.slice(0, 4e3),
|
|
12318
|
+
body: parsedBody
|
|
12319
|
+
},
|
|
12320
|
+
null,
|
|
12321
|
+
2
|
|
12322
|
+
)
|
|
12323
|
+
);
|
|
12324
|
+
} catch {
|
|
12325
|
+
}
|
|
12326
|
+
}
|
|
12327
|
+
const friendly = friendlyAntigravityError(response?.status, lastText);
|
|
12328
|
+
if (response?.status === 429 && /Quota reached\./i.test(friendly)) {
|
|
12329
|
+
throw new Error(friendly);
|
|
12330
|
+
}
|
|
12331
|
+
throw new Error(
|
|
12332
|
+
`Antigravity API error (${response?.status ?? "no response"}, ${formatRequestDiagnostics({ projectId, runtimeModel })}): ${friendly}`
|
|
12333
|
+
);
|
|
12334
|
+
}
|
|
12335
|
+
output.content = [];
|
|
12336
|
+
output.usage = {
|
|
12337
|
+
input: 0,
|
|
12338
|
+
output: 0,
|
|
12339
|
+
cacheRead: 0,
|
|
12340
|
+
cacheWrite: 0,
|
|
12341
|
+
totalTokens: 0,
|
|
12342
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
12343
|
+
};
|
|
12344
|
+
output.stopReason = "stop";
|
|
12345
|
+
received = await streamResponse(response, stream, output, model);
|
|
12346
|
+
if (received) break;
|
|
12347
|
+
}
|
|
12348
|
+
if (!received) throw new Error("Antigravity API returned an empty response");
|
|
12349
|
+
setLastLatencyMs(Date.now() - startTime);
|
|
12350
|
+
if (output.stopReason === "error" || output.stopReason === "aborted") {
|
|
12351
|
+
const errorDetail = output.rawStopReason ? `Provider stopped with: ${output.rawStopReason}` : "An unknown error occurred";
|
|
12352
|
+
output.errorMessage = output.errorMessage || errorDetail;
|
|
12353
|
+
setLastError(output.errorMessage);
|
|
12354
|
+
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
12355
|
+
} else if (output.stopReason === "pending") {
|
|
12356
|
+
throw new Error("Antigravity API returned no stop reason");
|
|
12357
|
+
} else {
|
|
12358
|
+
stream.push({ type: "done", reason: output.stopReason, message: output });
|
|
12359
|
+
}
|
|
12360
|
+
stream.end();
|
|
12361
|
+
} catch (error) {
|
|
12362
|
+
setLastLatencyMs(Date.now() - startTime);
|
|
12363
|
+
output.stopReason = opts.signal?.aborted ? "aborted" : "error";
|
|
12364
|
+
output.errorMessage = safeError(error);
|
|
12365
|
+
setLastError(output.errorMessage);
|
|
12366
|
+
if (!getCurrentEndpoint() && endpointCandidates()[0]) {
|
|
12367
|
+
setLastEndpoint(endpointCandidates()[0]);
|
|
12368
|
+
}
|
|
12369
|
+
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
12370
|
+
stream.end();
|
|
12371
|
+
}
|
|
12372
|
+
});
|
|
12373
|
+
return stream;
|
|
12374
|
+
}
|
|
12375
|
+
|
|
12376
|
+
// plugins/kxm/src/providers/antigravity/register.ts
|
|
12377
|
+
var ANTIGRAVITY_DOUBLE_REGISTRATION_WARNING = "kxm: standalone pi-antigravity is still installed. Remove that extension and reload. KXM will not double-register provider id antigravity.";
|
|
12378
|
+
var STANDALONE_ANTIGRAVITY_COMMANDS = Object.freeze([
|
|
12379
|
+
"antigravity.image",
|
|
12380
|
+
"antigravity.models",
|
|
12381
|
+
"antigravity.doctor",
|
|
12382
|
+
"antigravity.usage",
|
|
12383
|
+
"antigravity.refresh"
|
|
12384
|
+
]);
|
|
12385
|
+
function asProbe(pi) {
|
|
12386
|
+
return pi;
|
|
12387
|
+
}
|
|
12388
|
+
function registeredProviderIds(probe) {
|
|
12389
|
+
return [
|
|
12390
|
+
...probe.getRegisteredProviderIds?.() ?? [],
|
|
12391
|
+
...probe.modelRegistry?.getRegisteredProviderIds?.() ?? []
|
|
12392
|
+
];
|
|
12393
|
+
}
|
|
12394
|
+
function antigravityStandaloneCommandsPresent(pi) {
|
|
12395
|
+
const probe = asProbe(pi);
|
|
12396
|
+
let names = [];
|
|
12397
|
+
try {
|
|
12398
|
+
names = (probe.getCommands?.() ?? []).map((command) => command.name).filter((name) => typeof name === "string");
|
|
12399
|
+
} catch {
|
|
12400
|
+
return false;
|
|
12401
|
+
}
|
|
12402
|
+
return STANDALONE_ANTIGRAVITY_COMMANDS.some((name) => names.includes(name));
|
|
12403
|
+
}
|
|
12404
|
+
function antigravityProviderRegistered(pi) {
|
|
12405
|
+
const probe = asProbe(pi);
|
|
12406
|
+
const ids = registeredProviderIds(probe);
|
|
12407
|
+
if (ids.includes(PROVIDER_ID)) return true;
|
|
12408
|
+
if (probe.modelRegistry?.getProvider?.(PROVIDER_ID)) return true;
|
|
12409
|
+
return false;
|
|
12410
|
+
}
|
|
12411
|
+
function shouldSkipAntigravityRegistration(pi) {
|
|
12412
|
+
return antigravityProviderRegistered(pi) || antigravityStandaloneCommandsPresent(pi);
|
|
12413
|
+
}
|
|
12414
|
+
function antigravityRegistrationNotice(report, pi) {
|
|
12415
|
+
const conflict = Boolean(report?.conflict) || (pi ? antigravityStandaloneCommandsPresent(pi) : false);
|
|
12416
|
+
if (!conflict) return void 0;
|
|
12417
|
+
const warning = (report?.warning ?? ANTIGRAVITY_DOUBLE_REGISTRATION_WARNING).slice(0, 400);
|
|
12418
|
+
return { message: warning, type: "warning" };
|
|
12419
|
+
}
|
|
12420
|
+
function registerAntigravityProvider(pi) {
|
|
12421
|
+
if (shouldSkipAntigravityRegistration(pi)) {
|
|
12422
|
+
return {
|
|
12423
|
+
registered: false,
|
|
12424
|
+
conflict: true,
|
|
12425
|
+
warning: ANTIGRAVITY_DOUBLE_REGISTRATION_WARNING
|
|
12426
|
+
};
|
|
12427
|
+
}
|
|
12428
|
+
if (typeof pi.registerProvider !== "function") {
|
|
12429
|
+
return { registered: false, conflict: false };
|
|
12430
|
+
}
|
|
12431
|
+
const primaryEndpoint = endpointCandidates()[0];
|
|
12432
|
+
if (primaryEndpoint) prewarmConnection(primaryEndpoint);
|
|
12433
|
+
pi.registerProvider(PROVIDER_ID, {
|
|
12434
|
+
name: PROVIDER_NAME,
|
|
12435
|
+
baseUrl: DEFAULT_ENDPOINT,
|
|
12436
|
+
api: ANTIGRAVITY_API,
|
|
12437
|
+
models: getCurrentAntigravityCatalog().models,
|
|
12438
|
+
refreshModels: refreshAntigravityModels,
|
|
12439
|
+
oauth: {
|
|
12440
|
+
name: PROVIDER_NAME,
|
|
12441
|
+
isSubscription: true,
|
|
12442
|
+
login: loginAntigravity,
|
|
12443
|
+
refreshToken: refreshAntigravityToken,
|
|
12444
|
+
getApiKey
|
|
12445
|
+
},
|
|
12446
|
+
streamSimple: streamAntigravity
|
|
12447
|
+
});
|
|
12448
|
+
return { registered: true, conflict: false };
|
|
12449
|
+
}
|
|
12450
|
+
|
|
9391
12451
|
// plugins/kxm/src/diagnostics.ts
|
|
9392
12452
|
var NEXT_ACTIONS = [
|
|
9393
12453
|
"use_assigned_coordinator",
|
|
@@ -9501,13 +12561,13 @@ function diagnosticSummary(diagnostic) {
|
|
|
9501
12561
|
}
|
|
9502
12562
|
|
|
9503
12563
|
// plugins/kxm/src/recovery.ts
|
|
9504
|
-
import { createHash as
|
|
12564
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
9505
12565
|
import { lstatSync, readFileSync as readFileSync2, renameSync, rmSync } from "node:fs";
|
|
9506
12566
|
import { join as join2 } from "node:path";
|
|
9507
12567
|
function workerStateKey(project, agentName) {
|
|
9508
12568
|
const safeProject = project.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 24) || "project";
|
|
9509
12569
|
const safeName = agentName.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 32) || "agent";
|
|
9510
|
-
const digest =
|
|
12570
|
+
const digest = createHash6("sha256").update(JSON.stringify({ project, agentName })).digest("hex").slice(0, 24);
|
|
9511
12571
|
return `${safeProject}-${safeName}-${digest}`;
|
|
9512
12572
|
}
|
|
9513
12573
|
function legacyRecoveryEnvelopePath(stateDir, agentName) {
|
|
@@ -10784,6 +13844,7 @@ function assistantFailure(messages) {
|
|
|
10784
13844
|
function piMeshExtension(pi) {
|
|
10785
13845
|
let client;
|
|
10786
13846
|
let nousReport;
|
|
13847
|
+
let antigravityReport;
|
|
10787
13848
|
let pending = [];
|
|
10788
13849
|
let activatingInbound;
|
|
10789
13850
|
let awaitingActivation;
|
|
@@ -11196,6 +14257,8 @@ function piMeshExtension(pi) {
|
|
|
11196
14257
|
}
|
|
11197
14258
|
pi.on("session_start", async (event, ctx) => {
|
|
11198
14259
|
shuttingDown = false;
|
|
14260
|
+
const antigravityNotice = antigravityRegistrationNotice(antigravityReport, pi);
|
|
14261
|
+
if (antigravityNotice) ctx.ui.notify(antigravityNotice.message, antigravityNotice.type);
|
|
11199
14262
|
if (nousReport?.guidance.length) {
|
|
11200
14263
|
for (const item of nousReport.guidance) {
|
|
11201
14264
|
ctx.ui.notify(item.message, item.level);
|
|
@@ -11458,6 +14521,7 @@ function piMeshExtension(pi) {
|
|
|
11458
14521
|
}
|
|
11459
14522
|
}
|
|
11460
14523
|
});
|
|
14524
|
+
antigravityReport = registerAntigravityProvider(pi);
|
|
11461
14525
|
return nousFactoryWork(pi, (report) => {
|
|
11462
14526
|
nousReport = report;
|
|
11463
14527
|
});
|