@eddyskywalker/dsh-chatgpt-subscription 0.3.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -1
- package/lib/client.js +386 -99
- package/lib/client.js.map +1 -1
- package/lib/index.js +853 -119
- package/lib/types/client/CodexSubscriptionSection.d.ts.map +1 -1
- package/lib/types/client/antigravity/AntigravitySection.d.ts.map +1 -1
- package/lib/types/client/antigravity/locales.d.ts +78 -0
- package/lib/types/client/antigravity/locales.d.ts.map +1 -1
- package/lib/types/client/antigravity/styles.d.ts.map +1 -1
- package/lib/types/client/command-code/CommandCodeSection.d.ts.map +1 -1
- package/lib/types/client/command-code/locales.d.ts +12 -6
- package/lib/types/client/command-code/locales.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -1
- package/lib/types/client/kimi-code/locales.d.ts +12 -6
- package/lib/types/client/kimi-code/locales.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +9 -3
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/host/antigravity/account-pool.d.ts +50 -0
- package/lib/types/host/antigravity/account-pool.d.ts.map +1 -0
- package/lib/types/host/antigravity/adapter.d.ts +3 -1
- package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
- package/lib/types/host/antigravity/mapper.d.ts +1 -0
- package/lib/types/host/antigravity/mapper.d.ts.map +1 -1
- package/lib/types/host/antigravity/oauth.d.ts +1 -1
- package/lib/types/host/antigravity/oauth.d.ts.map +1 -1
- package/lib/types/host/antigravity/routes.d.ts +3 -2
- package/lib/types/host/antigravity/routes.d.ts.map +1 -1
- package/lib/types/host/antigravity/token-store.d.ts +3 -0
- package/lib/types/host/antigravity/token-store.d.ts.map +1 -1
- package/lib/types/host/antigravity/types.d.ts +2 -1
- package/lib/types/host/antigravity/types.d.ts.map +1 -1
- package/lib/types/host/command-code/adapter.d.ts.map +1 -1
- package/lib/types/host/command-code/mapper.d.ts.map +1 -1
- package/lib/types/host/command-code/routes.d.ts +1 -1
- package/lib/types/host/command-code/routes.d.ts.map +1 -1
- package/lib/types/host/command-code/token-store.d.ts +3 -0
- package/lib/types/host/command-code/token-store.d.ts.map +1 -1
- package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
- package/lib/types/host/kimi-code/mapper.d.ts +9 -4
- package/lib/types/host/kimi-code/mapper.d.ts.map +1 -1
- package/lib/types/host/kimi-code/routes.d.ts +1 -1
- package/lib/types/host/kimi-code/routes.d.ts.map +1 -1
- package/lib/types/host/kimi-code/token-store.d.ts +3 -0
- package/lib/types/host/kimi-code/token-store.d.ts.map +1 -1
- package/lib/types/host/model-catalog.d.ts.map +1 -1
- package/lib/types/host/preferences.d.ts.map +1 -1
- package/lib/types/host/token-store-windows.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/antigravity-contracts.d.ts +18 -0
- package/lib/types/shared/antigravity-contracts.d.ts.map +1 -1
- package/lib/types/shared/command-code-contracts.d.ts +2 -0
- package/lib/types/shared/command-code-contracts.d.ts.map +1 -1
- package/lib/types/shared/contracts.d.ts +2 -0
- package/lib/types/shared/contracts.d.ts.map +1 -1
- package/lib/types/shared/kimi-code-contracts.d.ts +2 -0
- package/lib/types/shared/kimi-code-contracts.d.ts.map +1 -1
- package/lib/types/shared/preferences.d.ts.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -192,7 +192,9 @@ function resolveCodexFallbackModel(model) {
|
|
|
192
192
|
const PROVIDER_ID$3 = CODEX_CHATGPT_PROVIDER_ID;
|
|
193
193
|
const PROVIDER_NAME$3 = "Codex(ChatGPT 订阅)";
|
|
194
194
|
function listCodexModels(preferences) {
|
|
195
|
-
const
|
|
195
|
+
const status = preferences?.status();
|
|
196
|
+
if (status?.enabled === false) return [];
|
|
197
|
+
const visible = new Set(status?.visibleModelIds ?? CODEX_MODEL_CATALOG.map((entry) => entry.id));
|
|
196
198
|
return CODEX_MODEL_CATALOG.filter((entry) => visible.has(entry.id)).map((entry) => ({
|
|
197
199
|
provider: PROVIDER_ID$3,
|
|
198
200
|
id: entry.id,
|
|
@@ -1597,6 +1599,7 @@ var ProxyManager = class {
|
|
|
1597
1599
|
//#region src/shared/preferences.ts
|
|
1598
1600
|
const PREFERENCES_NAMESPACE = "dsh-chatgpt-subscription";
|
|
1599
1601
|
const DEFAULT_PREFERENCES = {
|
|
1602
|
+
enabled: true,
|
|
1600
1603
|
quickQuotaVisible: false,
|
|
1601
1604
|
fastMode: false,
|
|
1602
1605
|
outputVerbosity: null,
|
|
@@ -1630,6 +1633,7 @@ function isProxyMode(value) {
|
|
|
1630
1633
|
function registerPreferenceStore(settings) {
|
|
1631
1634
|
const ns = SettingsModule.settingsNamespace ? SettingsModule.settingsNamespace(PREFERENCES_NAMESPACE) : PREFERENCES_NAMESPACE;
|
|
1632
1635
|
return new SettingsPreferenceStore(settings.register.call(settings, ns, z.object({
|
|
1636
|
+
enabled: z.boolean().default(DEFAULT_PREFERENCES.enabled ?? true),
|
|
1633
1637
|
quickQuotaVisible: z.boolean().default(DEFAULT_PREFERENCES.quickQuotaVisible),
|
|
1634
1638
|
fastMode: z.boolean().default(DEFAULT_PREFERENCES.fastMode),
|
|
1635
1639
|
outputVerbosity: z.union([
|
|
@@ -1671,6 +1675,7 @@ var SettingsPreferenceStore = class {
|
|
|
1671
1675
|
}
|
|
1672
1676
|
async update(patch) {
|
|
1673
1677
|
const normalized = {};
|
|
1678
|
+
if (patch.enabled !== void 0) normalized.enabled = patch.enabled;
|
|
1674
1679
|
if (patch.quickQuotaVisible !== void 0) normalized.quickQuotaVisible = patch.quickQuotaVisible;
|
|
1675
1680
|
if (patch.fastMode !== void 0) normalized.fastMode = patch.fastMode;
|
|
1676
1681
|
if (patch.outputVerbosity !== void 0) {
|
|
@@ -1682,7 +1687,7 @@ var SettingsPreferenceStore = class {
|
|
|
1682
1687
|
normalized.reasoningSummary = patch.reasoningSummary;
|
|
1683
1688
|
}
|
|
1684
1689
|
if (patch.visibleModelIds !== void 0) {
|
|
1685
|
-
if (
|
|
1690
|
+
if (!patch.visibleModelIds.every(isCodexModelId)) throw new PreferenceError("Unsupported Codex model.");
|
|
1686
1691
|
normalized.visibleModelIds = [...new Set(patch.visibleModelIds)];
|
|
1687
1692
|
}
|
|
1688
1693
|
if (patch.searchProvider !== void 0) {
|
|
@@ -1899,7 +1904,7 @@ async function buildResponsesPayload(options, attachments, localRawImages = {},
|
|
|
1899
1904
|
const instructionParts = [
|
|
1900
1905
|
options.system?.trim(),
|
|
1901
1906
|
latestSystemPrompt(options.messages),
|
|
1902
|
-
progressExplanationInstruction(options.tools),
|
|
1907
|
+
progressExplanationInstruction$1(options.tools),
|
|
1903
1908
|
sandboxToolInstruction(options.tools, sandboxRetryTools),
|
|
1904
1909
|
commandToolInstruction(options.tools),
|
|
1905
1910
|
runCodeInstruction(options.tools)
|
|
@@ -1985,7 +1990,7 @@ async function buildResponsesPayload(options, attachments, localRawImages = {},
|
|
|
1985
1990
|
}
|
|
1986
1991
|
return payload;
|
|
1987
1992
|
}
|
|
1988
|
-
function progressExplanationInstruction(tools) {
|
|
1993
|
+
function progressExplanationInstruction$1(tools) {
|
|
1989
1994
|
if (!tools?.length) return void 0;
|
|
1990
1995
|
return "Progress and tool execution rule: when executing multi-step tasks or invoking tools, output 1-2 concise sentences of progress, intent, or intermediate findings before each tool call. Keep progress text brief, professional, and factual. Only present the comprehensive final answer and summary in the final turn after all tool operations are completed.";
|
|
1991
1996
|
}
|
|
@@ -3435,8 +3440,12 @@ function isRecord$6(value) {
|
|
|
3435
3440
|
}
|
|
3436
3441
|
function readPreferencesUpdate(value, current) {
|
|
3437
3442
|
const patch = {};
|
|
3443
|
+
if ("enabled" in value) {
|
|
3444
|
+
if (typeof value.enabled !== "boolean") throw new PreferenceError("enabled must be a boolean.");
|
|
3445
|
+
patch.enabled = value.enabled;
|
|
3446
|
+
}
|
|
3438
3447
|
if ("visibleModelIds" in value) {
|
|
3439
|
-
if (!Array.isArray(value.visibleModelIds) ||
|
|
3448
|
+
if (!Array.isArray(value.visibleModelIds) || !value.visibleModelIds.every(isCodexModelId)) throw new PreferenceError("visibleModelIds must be an array of supported Codex models.");
|
|
3440
3449
|
patch.visibleModelIds = [...new Set(value.visibleModelIds)];
|
|
3441
3450
|
}
|
|
3442
3451
|
if ("quickQuotaVisible" in value) {
|
|
@@ -3730,6 +3739,9 @@ function isMissing(error) {
|
|
|
3730
3739
|
//#region src/host/token-store-windows.ts
|
|
3731
3740
|
const PROTECT_SCRIPT = String.raw`
|
|
3732
3741
|
$ErrorActionPreference = 'Stop'
|
|
3742
|
+
[Console]::InputEncoding = [Text.Encoding]::UTF8
|
|
3743
|
+
[Console]::OutputEncoding = [Text.Encoding]::UTF8
|
|
3744
|
+
$OutputEncoding = [Text.Encoding]::UTF8
|
|
3733
3745
|
Add-Type -AssemblyName System.Security
|
|
3734
3746
|
$path = $env:DSH_CODEX_TOKEN_PATH
|
|
3735
3747
|
$plain = [Console]::In.ReadToEnd()
|
|
@@ -3751,6 +3763,9 @@ try {
|
|
|
3751
3763
|
`;
|
|
3752
3764
|
const UNPROTECT_SCRIPT = String.raw`
|
|
3753
3765
|
$ErrorActionPreference = 'Stop'
|
|
3766
|
+
[Console]::InputEncoding = [Text.Encoding]::UTF8
|
|
3767
|
+
[Console]::OutputEncoding = [Text.Encoding]::UTF8
|
|
3768
|
+
$OutputEncoding = [Text.Encoding]::UTF8
|
|
3754
3769
|
Add-Type -AssemblyName System.Security
|
|
3755
3770
|
$path = $env:DSH_CODEX_TOKEN_PATH
|
|
3756
3771
|
if (-not [IO.File]::Exists($path)) { exit 3 }
|
|
@@ -3965,7 +3980,8 @@ const SCOPES = [
|
|
|
3965
3980
|
const DEFAULT_CLIENT_ID = Buffer.from("MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ==", "base64").toString("utf8");
|
|
3966
3981
|
const DEFAULT_CLIENT_SECRET = Buffer.from("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=", "base64").toString("utf8");
|
|
3967
3982
|
const 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.";
|
|
3968
|
-
const ANTIGRAVITY_NO_PREAMBLE_INSTRUCTION = "CRITICAL: NEVER output rule checks, formatting guidelines, constraint checklists, or thinking/personality preambles in the final response. Output only the final response.";
|
|
3983
|
+
const ANTIGRAVITY_NO_PREAMBLE_INSTRUCTION = "CRITICAL: NEVER output rule checks, formatting guidelines, constraint checklists, or thinking/personality preambles in the final response. Output only the final response. This forbids meta commentary only; it does not forbid the short progress lines the next rule requires before tool calls.";
|
|
3984
|
+
const ANTIGRAVITY_PROGRESS_INSTRUCTION = "Progress and tool execution rule: before EVERY tool call, emit 1-2 short sentences of ordinary, visible assistant text stating what you are about to do and why, written as normal response text the user can read. Never write those sentences only inside your thinking/thought summary: the visible text part must exist, otherwise the progress is not delivered. These progress lines are required and take precedence over the no-preamble rule. Keep them brief, professional, and factual; do not restate the whole plan. Only present the comprehensive final answer and summary in the final turn, after all tool operations are completed.";
|
|
3969
3985
|
const GEMINI_ROLE = {
|
|
3970
3986
|
user: "user",
|
|
3971
3987
|
model: "model"
|
|
@@ -4357,6 +4373,7 @@ const ANTIGRAVITY_PREFERENCES_NAMESPACE = "dsh-antigravity";
|
|
|
4357
4373
|
function registerAntigravityPreferenceStore(settings, fallbackStore = new FileModelSettingsStore$1()) {
|
|
4358
4374
|
if (!settings) return {
|
|
4359
4375
|
status: () => ({
|
|
4376
|
+
enabled: true,
|
|
4360
4377
|
enabledModelIds: MODELS.map((m) => m.id),
|
|
4361
4378
|
catalogModels: [],
|
|
4362
4379
|
contextWindowOverrides: {},
|
|
@@ -4366,6 +4383,7 @@ function registerAntigravityPreferenceStore(settings, fallbackStore = new FileMo
|
|
|
4366
4383
|
};
|
|
4367
4384
|
const ns = SettingsModule.settingsNamespace ? SettingsModule.settingsNamespace(ANTIGRAVITY_PREFERENCES_NAMESPACE) : ANTIGRAVITY_PREFERENCES_NAMESPACE;
|
|
4368
4385
|
const scope = settings.register.call(settings, ns, z.object({
|
|
4386
|
+
enabled: z.boolean().default(true),
|
|
4369
4387
|
enabledModelIds: z.array(z.string()).default(MODELS.map((m) => m.id)),
|
|
4370
4388
|
contextWindowOverrides: z.dict(z.number()).default({}),
|
|
4371
4389
|
defaultReasoningEffort: z.union([
|
|
@@ -4379,6 +4397,7 @@ function registerAntigravityPreferenceStore(settings, fallbackStore = new FileMo
|
|
|
4379
4397
|
status: () => {
|
|
4380
4398
|
const val = scope.get();
|
|
4381
4399
|
return {
|
|
4400
|
+
enabled: val.enabled !== false,
|
|
4382
4401
|
enabledModelIds: val.enabledModelIds,
|
|
4383
4402
|
catalogModels: [],
|
|
4384
4403
|
contextWindowOverrides: val.contextWindowOverrides,
|
|
@@ -4388,6 +4407,7 @@ function registerAntigravityPreferenceStore(settings, fallbackStore = new FileMo
|
|
|
4388
4407
|
update: async (patch) => {
|
|
4389
4408
|
const current = scope.get();
|
|
4390
4409
|
const normalized = {
|
|
4410
|
+
enabled: patch.enabled !== void 0 ? patch.enabled : current.enabled !== false,
|
|
4391
4411
|
enabledModelIds: patch.enabledModelIds ?? current.enabledModelIds,
|
|
4392
4412
|
contextWindowOverrides: patch.contextWindowOverrides ? {
|
|
4393
4413
|
...current.contextWindowOverrides,
|
|
@@ -4533,15 +4553,21 @@ var FileModelSettingsStore$1 = class {
|
|
|
4533
4553
|
const parsed = JSON.parse(content);
|
|
4534
4554
|
if (typeof parsed === "object" && parsed !== null) {
|
|
4535
4555
|
const record = parsed;
|
|
4556
|
+
const enabledModelIds = Array.isArray(record.enabledModelIds) ? record.enabledModelIds.filter((id) => typeof id === "string") : MODELS.map((m) => m.id);
|
|
4557
|
+
const catalogModels = Array.isArray(record.catalogModels) ? record.catalogModels : [];
|
|
4558
|
+
const contextWindowOverrides = typeof record.contextWindowOverrides === "object" && record.contextWindowOverrides !== null ? record.contextWindowOverrides : {};
|
|
4559
|
+
const defaultReasoningEffort = record.defaultReasoningEffort === "low" || record.defaultReasoningEffort === "medium" || record.defaultReasoningEffort === "high" ? record.defaultReasoningEffort : null;
|
|
4536
4560
|
return {
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4561
|
+
enabled: record.enabled !== false,
|
|
4562
|
+
enabledModelIds,
|
|
4563
|
+
catalogModels,
|
|
4564
|
+
contextWindowOverrides,
|
|
4565
|
+
defaultReasoningEffort
|
|
4541
4566
|
};
|
|
4542
4567
|
}
|
|
4543
4568
|
} catch {}
|
|
4544
4569
|
return {
|
|
4570
|
+
enabled: true,
|
|
4545
4571
|
enabledModelIds: MODELS.map((m) => m.id),
|
|
4546
4572
|
catalogModels: [],
|
|
4547
4573
|
contextWindowOverrides: {},
|
|
@@ -4558,6 +4584,7 @@ var FileModelSettingsStore$1 = class {
|
|
|
4558
4584
|
const current = await this.read();
|
|
4559
4585
|
const next = {
|
|
4560
4586
|
...current,
|
|
4587
|
+
...patch.enabled !== void 0 ? { enabled: patch.enabled } : {},
|
|
4561
4588
|
...patch.enabledModelIds !== void 0 ? { enabledModelIds: patch.enabledModelIds } : {},
|
|
4562
4589
|
...patch.contextWindowOverrides !== void 0 ? { contextWindowOverrides: {
|
|
4563
4590
|
...current.contextWindowOverrides || {},
|
|
@@ -5064,7 +5091,7 @@ async function exchangeOAuthCode(code, verifier, callbackUrl, fetchFn = fetch, s
|
|
|
5064
5091
|
email
|
|
5065
5092
|
};
|
|
5066
5093
|
}
|
|
5067
|
-
async function beginWebLogin$1(store, fetchFn = fetch, signal) {
|
|
5094
|
+
async function beginWebLogin$1(store, fetchFn = fetch, signal, onSave) {
|
|
5068
5095
|
if (webLoginFlow$2.status === "pending") return { ...webLoginFlow$2 };
|
|
5069
5096
|
const { verifier, challenge } = generatePKCE();
|
|
5070
5097
|
const state = base64Url(randomBytes(32));
|
|
@@ -5096,6 +5123,7 @@ async function beginWebLogin$1(store, fetchFn = fetch, signal) {
|
|
|
5096
5123
|
webLoginFlow$2.progress = stage;
|
|
5097
5124
|
});
|
|
5098
5125
|
await store.write(credentials);
|
|
5126
|
+
if (onSave) await onSave(credentials).catch(() => void 0);
|
|
5099
5127
|
webLoginFlow$2.status = "complete";
|
|
5100
5128
|
webLoginFlow$2.email = credentials.email;
|
|
5101
5129
|
webLoginFlow$2.completedAt = Date.now();
|
|
@@ -5316,9 +5344,13 @@ function attachmentLabel$2(block) {
|
|
|
5316
5344
|
function collectImageRefs$2(content, refs) {
|
|
5317
5345
|
if (!Array.isArray(content)) return;
|
|
5318
5346
|
for (const block of content) {
|
|
5319
|
-
if (!isRecord$4(block)
|
|
5320
|
-
|
|
5321
|
-
|
|
5347
|
+
if (!isRecord$4(block)) continue;
|
|
5348
|
+
if (block.type === "image") {
|
|
5349
|
+
const attachment = attachmentOf$2(block);
|
|
5350
|
+
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
5351
|
+
continue;
|
|
5352
|
+
}
|
|
5353
|
+
if (block.type === "tool-result") collectImageRefs$2(block.content, refs);
|
|
5322
5354
|
}
|
|
5323
5355
|
}
|
|
5324
5356
|
function isAbort$2(error, signal) {
|
|
@@ -5487,6 +5519,24 @@ function contentToUserParts(content, images) {
|
|
|
5487
5519
|
}
|
|
5488
5520
|
return parts;
|
|
5489
5521
|
}
|
|
5522
|
+
/**
|
|
5523
|
+
* Image parts for one tool result, flattened the same way so a nested
|
|
5524
|
+
* `tool-result` cannot hide one. Gemini's `functionResponse` has nowhere to put
|
|
5525
|
+
* an image, so these become `inlineData` siblings on the same user content.
|
|
5526
|
+
*/
|
|
5527
|
+
function toolResultImageParts(blocks, images) {
|
|
5528
|
+
if (!Array.isArray(blocks)) return [];
|
|
5529
|
+
const parts = [];
|
|
5530
|
+
for (const block of blocks) {
|
|
5531
|
+
if (!isRecord$4(block)) continue;
|
|
5532
|
+
if (block.type === "image") {
|
|
5533
|
+
parts.push(imageBlockToPart(block, images) ?? { text: unavailableImageText$2(block) });
|
|
5534
|
+
continue;
|
|
5535
|
+
}
|
|
5536
|
+
if (block.type === "tool-result") parts.push(...toolResultImageParts(block.content, images));
|
|
5537
|
+
}
|
|
5538
|
+
return parts;
|
|
5539
|
+
}
|
|
5490
5540
|
function toolResultText$2(blocks) {
|
|
5491
5541
|
if (!Array.isArray(blocks)) return "";
|
|
5492
5542
|
return blocks.map((block) => {
|
|
@@ -5572,7 +5622,7 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
|
|
|
5572
5622
|
}
|
|
5573
5623
|
return parts;
|
|
5574
5624
|
}
|
|
5575
|
-
function pushToolResult(contents, result, toolCalls, model, runtimeModel) {
|
|
5625
|
+
function pushToolResult(contents, result, toolCalls, model, runtimeModel, images = NO_RESOLVED_IMAGES$2) {
|
|
5576
5626
|
const toolCallId = String(result.toolCallId || "");
|
|
5577
5627
|
const call = toolCalls.get(toolCallId);
|
|
5578
5628
|
const toolName = call?.name || "unknown";
|
|
@@ -5583,11 +5633,12 @@ function pushToolResult(contents, result, toolCalls, model, runtimeModel) {
|
|
|
5583
5633
|
response: result.isError ? { error: responseText } : { output: responseText },
|
|
5584
5634
|
...wireId ? { id: wireId } : {}
|
|
5585
5635
|
} };
|
|
5636
|
+
const extraParts = toolResultImageParts(result.content, images);
|
|
5586
5637
|
const last = contents[contents.length - 1];
|
|
5587
|
-
if (last?.role === GEMINI_ROLE.user && last.parts.some((entry) => "functionResponse" in entry)) last.parts.push(part);
|
|
5638
|
+
if (last?.role === GEMINI_ROLE.user && last.parts.some((entry) => "functionResponse" in entry)) last.parts.push(part, ...extraParts);
|
|
5588
5639
|
else contents.push({
|
|
5589
5640
|
role: GEMINI_ROLE.user,
|
|
5590
|
-
parts: [part]
|
|
5641
|
+
parts: [part, ...extraParts]
|
|
5591
5642
|
});
|
|
5592
5643
|
}
|
|
5593
5644
|
function convertMessages(options, model, runtimeModel, images = NO_RESOLVED_IMAGES$2) {
|
|
@@ -5616,7 +5667,7 @@ function convertMessages(options, model, runtimeModel, images = NO_RESOLVED_IMAG
|
|
|
5616
5667
|
role: GEMINI_ROLE.user,
|
|
5617
5668
|
parts: userParts
|
|
5618
5669
|
});
|
|
5619
|
-
for (const b of content) if (isRecord$4(b) && b.type === "tool-result") pushToolResult(contents, b, toolCalls, model, runtimeModel);
|
|
5670
|
+
for (const b of content) if (isRecord$4(b) && b.type === "tool-result") pushToolResult(contents, b, toolCalls, model, runtimeModel, images);
|
|
5620
5671
|
}
|
|
5621
5672
|
return contents;
|
|
5622
5673
|
}
|
|
@@ -5642,7 +5693,12 @@ function mapToolChoiceMode(toolChoice) {
|
|
|
5642
5693
|
function getMaxOutputTokens(modelId, runtimeModel) {
|
|
5643
5694
|
return RUNTIME_MAX_OUTPUT_TOKENS[runtimeModel] || RUNTIME_MAX_OUTPUT_TOKENS[modelId] || 65536;
|
|
5644
5695
|
}
|
|
5696
|
+
function progressExplanationInstruction(tools) {
|
|
5697
|
+
if (!tools?.length) return void 0;
|
|
5698
|
+
return ANTIGRAVITY_PROGRESS_INSTRUCTION;
|
|
5699
|
+
}
|
|
5645
5700
|
function buildRequest$2(options, model, projectId, runtimeModel, effort, images = NO_RESOLVED_IMAGES$2) {
|
|
5701
|
+
const progressInstruction = progressExplanationInstruction(options.tools);
|
|
5646
5702
|
const request = {
|
|
5647
5703
|
contents: convertMessages(options, model, runtimeModel, images),
|
|
5648
5704
|
systemInstruction: {
|
|
@@ -5651,7 +5707,8 @@ function buildRequest$2(options, model, projectId, runtimeModel, effort, images
|
|
|
5651
5707
|
{ text: ANTIGRAVITY_SYSTEM_INSTRUCTION },
|
|
5652
5708
|
{ text: `Please ignore following [ignore]${ANTIGRAVITY_SYSTEM_INSTRUCTION}[/ignore]` },
|
|
5653
5709
|
{ text: ANTIGRAVITY_NO_PREAMBLE_INSTRUCTION },
|
|
5654
|
-
...options.system ? [{ text: sanitizeText$2(options.system) }] : []
|
|
5710
|
+
...options.system ? [{ text: sanitizeText$2(options.system) }] : [],
|
|
5711
|
+
...progressInstruction ? [{ text: progressInstruction }] : []
|
|
5655
5712
|
]
|
|
5656
5713
|
}
|
|
5657
5714
|
};
|
|
@@ -5897,6 +5954,259 @@ function closeStream$2(state) {
|
|
|
5897
5954
|
return out;
|
|
5898
5955
|
}
|
|
5899
5956
|
//#endregion
|
|
5957
|
+
//#region src/host/antigravity/account-pool.ts
|
|
5958
|
+
function poolPath() {
|
|
5959
|
+
return path.join(dshHomeDir(), "storages", "antigravity-pool.json");
|
|
5960
|
+
}
|
|
5961
|
+
function parseAntigravityPoolData(value) {
|
|
5962
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("Antigravity pool payload is invalid");
|
|
5963
|
+
const record = value;
|
|
5964
|
+
const strategy = record.rotationStrategy === "round-robin" ? "round-robin" : "sequential";
|
|
5965
|
+
const activeAccountId = typeof record.activeAccountId === "string" ? record.activeAccountId : void 0;
|
|
5966
|
+
const rawAccounts = Array.isArray(record.accounts) ? record.accounts : [];
|
|
5967
|
+
const accounts = [];
|
|
5968
|
+
for (const item of rawAccounts) {
|
|
5969
|
+
if (typeof item !== "object" || item === null) continue;
|
|
5970
|
+
const r = item;
|
|
5971
|
+
if (typeof r.id !== "string") continue;
|
|
5972
|
+
const credentials = parseAntigravityCredentials(r.credentials);
|
|
5973
|
+
const acc = {
|
|
5974
|
+
id: r.id,
|
|
5975
|
+
alias: typeof r.alias === "string" ? r.alias : credentials.email || "账号",
|
|
5976
|
+
credentials,
|
|
5977
|
+
addedAt: typeof r.addedAt === "number" ? r.addedAt : Date.now(),
|
|
5978
|
+
isPrimary: r.isPrimary === true
|
|
5979
|
+
};
|
|
5980
|
+
if (typeof r.email === "string") acc.email = r.email;
|
|
5981
|
+
else if (credentials.email) acc.email = credentials.email;
|
|
5982
|
+
if (typeof r.projectId === "string") acc.projectId = r.projectId;
|
|
5983
|
+
else if (credentials.projectId) acc.projectId = credentials.projectId;
|
|
5984
|
+
if (typeof r.planLabel === "string") acc.planLabel = r.planLabel;
|
|
5985
|
+
if (typeof r.lastUsedAt === "number") acc.lastUsedAt = r.lastUsedAt;
|
|
5986
|
+
if (typeof r.cooldownUntil === "number") acc.cooldownUntil = r.cooldownUntil;
|
|
5987
|
+
if (typeof r.cooldownReason === "string") acc.cooldownReason = r.cooldownReason;
|
|
5988
|
+
accounts.push(acc);
|
|
5989
|
+
}
|
|
5990
|
+
const res = {
|
|
5991
|
+
version: 1,
|
|
5992
|
+
rotationStrategy: strategy,
|
|
5993
|
+
accounts
|
|
5994
|
+
};
|
|
5995
|
+
if (activeAccountId) res.activeAccountId = activeAccountId;
|
|
5996
|
+
return res;
|
|
5997
|
+
}
|
|
5998
|
+
function poolCredentialAccount(filePath) {
|
|
5999
|
+
return createHash("sha256").update(path.resolve(filePath)).digest("hex");
|
|
6000
|
+
}
|
|
6001
|
+
function createPoolCredentialBackend(filePath) {
|
|
6002
|
+
if (process.platform === "win32") return new WindowsDpapiCredentialStore(`${filePath}.dpapi`, parseAntigravityPoolData);
|
|
6003
|
+
if (process.platform === "darwin") return new MacKeychainCredentialStore("dsh-antigravity-pool", poolCredentialAccount(filePath), parseAntigravityPoolData);
|
|
6004
|
+
if (process.platform === "linux") return new SecretServiceCredentialStore("dsh-antigravity-pool", poolCredentialAccount(filePath), parseAntigravityPoolData);
|
|
6005
|
+
throw new Error("Antigravity pool encrypted storage requires Windows, macOS, or Linux.");
|
|
6006
|
+
}
|
|
6007
|
+
const poolOperations = /* @__PURE__ */ new Map();
|
|
6008
|
+
var AccountPoolStore = class {
|
|
6009
|
+
filePath;
|
|
6010
|
+
backend;
|
|
6011
|
+
legacyStore;
|
|
6012
|
+
constructor(filePath = poolPath(), backend = createPoolCredentialBackend(filePath), legacyStore = new FileCredentialStore$1()) {
|
|
6013
|
+
this.filePath = filePath;
|
|
6014
|
+
this.backend = backend;
|
|
6015
|
+
this.legacyStore = legacyStore;
|
|
6016
|
+
}
|
|
6017
|
+
path() {
|
|
6018
|
+
if (process.platform === "win32") return `${this.filePath}.dpapi`;
|
|
6019
|
+
return `${process.platform === "darwin" ? "Keychain" : "Secret Service"}: dsh-antigravity-pool/${poolCredentialAccount(this.filePath)}`;
|
|
6020
|
+
}
|
|
6021
|
+
serialize(operation) {
|
|
6022
|
+
const key = path.resolve(this.filePath);
|
|
6023
|
+
const result = (poolOperations.get(key) || Promise.resolve()).then(operation);
|
|
6024
|
+
const settled = result.then(() => void 0, () => void 0);
|
|
6025
|
+
poolOperations.set(key, settled);
|
|
6026
|
+
settled.then(() => {
|
|
6027
|
+
if (poolOperations.get(key) === settled) poolOperations.delete(key);
|
|
6028
|
+
});
|
|
6029
|
+
return result;
|
|
6030
|
+
}
|
|
6031
|
+
async saveVerified(data) {
|
|
6032
|
+
const normalized = parseAntigravityPoolData(data);
|
|
6033
|
+
await this.backend.save(normalized);
|
|
6034
|
+
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Antigravity pool encrypted verification failed");
|
|
6035
|
+
}
|
|
6036
|
+
read() {
|
|
6037
|
+
return this.serialize(async () => {
|
|
6038
|
+
let current = null;
|
|
6039
|
+
try {
|
|
6040
|
+
current = await this.backend.load();
|
|
6041
|
+
} catch {}
|
|
6042
|
+
if (current !== null && Array.isArray(current.accounts) && current.accounts.length > 0) return current;
|
|
6043
|
+
try {
|
|
6044
|
+
const legacy = await this.legacyStore.read();
|
|
6045
|
+
if (legacy && (legacy.access || legacy.access_token || legacy.refresh || legacy.refresh_token)) {
|
|
6046
|
+
const defaultAccount = {
|
|
6047
|
+
id: "acc_primary",
|
|
6048
|
+
alias: legacy.email || "主账号",
|
|
6049
|
+
email: legacy.email,
|
|
6050
|
+
projectId: legacy.projectId,
|
|
6051
|
+
credentials: legacy,
|
|
6052
|
+
addedAt: Date.now(),
|
|
6053
|
+
isPrimary: true
|
|
6054
|
+
};
|
|
6055
|
+
return {
|
|
6056
|
+
version: 1,
|
|
6057
|
+
activeAccountId: "acc_primary",
|
|
6058
|
+
rotationStrategy: current?.rotationStrategy || "sequential",
|
|
6059
|
+
accounts: [defaultAccount]
|
|
6060
|
+
};
|
|
6061
|
+
}
|
|
6062
|
+
} catch {}
|
|
6063
|
+
return current || {
|
|
6064
|
+
version: 1,
|
|
6065
|
+
rotationStrategy: "sequential",
|
|
6066
|
+
accounts: []
|
|
6067
|
+
};
|
|
6068
|
+
});
|
|
6069
|
+
}
|
|
6070
|
+
write(data) {
|
|
6071
|
+
return this.serialize(() => this.saveVerified(parseAntigravityPoolData(data)));
|
|
6072
|
+
}
|
|
6073
|
+
async listAccounts() {
|
|
6074
|
+
const data = await this.read();
|
|
6075
|
+
const now = Date.now();
|
|
6076
|
+
return data.accounts.map((acc) => {
|
|
6077
|
+
const expires = acc.credentials.expires || acc.credentials.expires_at;
|
|
6078
|
+
return {
|
|
6079
|
+
id: acc.id,
|
|
6080
|
+
alias: acc.alias,
|
|
6081
|
+
email: acc.email,
|
|
6082
|
+
projectId: acc.projectId,
|
|
6083
|
+
planLabel: acc.planLabel,
|
|
6084
|
+
isPrimary: acc.isPrimary === true,
|
|
6085
|
+
lastUsedAt: acc.lastUsedAt,
|
|
6086
|
+
cooldownUntil: acc.cooldownUntil && acc.cooldownUntil > now ? acc.cooldownUntil : void 0,
|
|
6087
|
+
cooldownReason: acc.cooldownUntil && acc.cooldownUntil > now ? acc.cooldownReason : void 0,
|
|
6088
|
+
expiresAt: expires
|
|
6089
|
+
};
|
|
6090
|
+
});
|
|
6091
|
+
}
|
|
6092
|
+
async addAccount(credentials, alias) {
|
|
6093
|
+
const data = await this.read();
|
|
6094
|
+
const email = credentials.email;
|
|
6095
|
+
const existingIndex = email ? data.accounts.findIndex((a) => a.email === email) : -1;
|
|
6096
|
+
const id = existingIndex >= 0 ? data.accounts[existingIndex].id : `acc_${randomBytes(6).toString("hex")}`;
|
|
6097
|
+
const isPrimary = data.accounts.length === 0 || existingIndex >= 0 && data.accounts[existingIndex].isPrimary;
|
|
6098
|
+
const account = {
|
|
6099
|
+
id,
|
|
6100
|
+
alias: alias?.trim() || email || `账号 ${data.accounts.length + 1}`,
|
|
6101
|
+
email,
|
|
6102
|
+
projectId: credentials.projectId,
|
|
6103
|
+
credentials,
|
|
6104
|
+
addedAt: Date.now(),
|
|
6105
|
+
isPrimary: !!isPrimary
|
|
6106
|
+
};
|
|
6107
|
+
if (existingIndex >= 0) data.accounts[existingIndex] = {
|
|
6108
|
+
...data.accounts[existingIndex],
|
|
6109
|
+
...account,
|
|
6110
|
+
isPrimary: data.accounts[existingIndex].isPrimary
|
|
6111
|
+
};
|
|
6112
|
+
else data.accounts.push(account);
|
|
6113
|
+
if (!data.activeAccountId || account.isPrimary) data.activeAccountId = account.id;
|
|
6114
|
+
await this.write(data);
|
|
6115
|
+
if (account.isPrimary) this.legacyStore.write(credentials).catch(() => void 0);
|
|
6116
|
+
return account;
|
|
6117
|
+
}
|
|
6118
|
+
async setPrimary(accountId) {
|
|
6119
|
+
const data = await this.read();
|
|
6120
|
+
for (const a of data.accounts) a.isPrimary = a.id === accountId;
|
|
6121
|
+
const primary = data.accounts.find((a) => a.isPrimary);
|
|
6122
|
+
if (primary) {
|
|
6123
|
+
data.activeAccountId = primary.id;
|
|
6124
|
+
this.legacyStore.write(primary.credentials).catch(() => void 0);
|
|
6125
|
+
}
|
|
6126
|
+
await this.write(data);
|
|
6127
|
+
}
|
|
6128
|
+
async setAlias(accountId, alias) {
|
|
6129
|
+
const data = await this.read();
|
|
6130
|
+
const target = data.accounts.find((a) => a.id === accountId);
|
|
6131
|
+
if (target && alias.trim()) {
|
|
6132
|
+
target.alias = alias.trim();
|
|
6133
|
+
await this.write(data);
|
|
6134
|
+
}
|
|
6135
|
+
}
|
|
6136
|
+
async deleteAccount(accountId) {
|
|
6137
|
+
const data = await this.read();
|
|
6138
|
+
const wasPrimary = data.accounts.find((a) => a.id === accountId)?.isPrimary;
|
|
6139
|
+
data.accounts = data.accounts.filter((a) => a.id !== accountId);
|
|
6140
|
+
if (wasPrimary && data.accounts.length > 0) {
|
|
6141
|
+
data.accounts[0].isPrimary = true;
|
|
6142
|
+
this.legacyStore.write(data.accounts[0].credentials).catch(() => void 0);
|
|
6143
|
+
} else if (data.accounts.length === 0) this.legacyStore.delete().catch(() => void 0);
|
|
6144
|
+
if (data.activeAccountId === accountId) data.activeAccountId = data.accounts.find((a) => a.isPrimary)?.id ?? data.accounts[0]?.id;
|
|
6145
|
+
await this.write(data);
|
|
6146
|
+
}
|
|
6147
|
+
async setStrategy(strategy) {
|
|
6148
|
+
const data = await this.read();
|
|
6149
|
+
data.rotationStrategy = strategy;
|
|
6150
|
+
await this.write(data);
|
|
6151
|
+
}
|
|
6152
|
+
async markCooldown(accountId, durationMs, reason) {
|
|
6153
|
+
const data = await this.read();
|
|
6154
|
+
const target = data.accounts.find((a) => a.id === accountId);
|
|
6155
|
+
if (target) {
|
|
6156
|
+
target.cooldownUntil = Date.now() + Math.max(1e4, durationMs);
|
|
6157
|
+
target.cooldownReason = reason;
|
|
6158
|
+
await this.write(data);
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
6161
|
+
async clearCooldown(accountId) {
|
|
6162
|
+
const data = await this.read();
|
|
6163
|
+
const target = data.accounts.find((a) => a.id === accountId);
|
|
6164
|
+
if (target) {
|
|
6165
|
+
target.cooldownUntil = void 0;
|
|
6166
|
+
target.cooldownReason = void 0;
|
|
6167
|
+
await this.write(data);
|
|
6168
|
+
}
|
|
6169
|
+
}
|
|
6170
|
+
async hasAnotherAvailableAccount(triedAccountIds) {
|
|
6171
|
+
const data = await this.read();
|
|
6172
|
+
const now = Date.now();
|
|
6173
|
+
return data.accounts.some((a) => !triedAccountIds.has(a.id) && (!a.cooldownUntil || a.cooldownUntil <= now));
|
|
6174
|
+
}
|
|
6175
|
+
async getEffectiveAccount(excludeIds, fetchFn = fetch) {
|
|
6176
|
+
const data = await this.read();
|
|
6177
|
+
if (data.accounts.length === 0) throw new Error("未登录 Antigravity 账号,请在「设置 → Antigravity」中添加并登录账号。");
|
|
6178
|
+
const now = Date.now();
|
|
6179
|
+
const eligible = data.accounts.filter((a) => (!excludeIds || !excludeIds.has(a.id)) && (!a.cooldownUntil || a.cooldownUntil <= now));
|
|
6180
|
+
if (eligible.length === 0) {
|
|
6181
|
+
let shortest = Infinity;
|
|
6182
|
+
for (const a of data.accounts) if (a.cooldownUntil && a.cooldownUntil > now) shortest = Math.min(shortest, a.cooldownUntil - now);
|
|
6183
|
+
const waitMins = Number.isFinite(shortest) ? Math.ceil(shortest / 6e4) : 15;
|
|
6184
|
+
throw new LlmError(`全部 ${data.accounts.length} 个 Antigravity 账号均处于配额限制或冷却中 (429)。最短预计在 ${waitMins} 分钟后解除冷却。`, "RATE_LIMIT", { status: 429 });
|
|
6185
|
+
}
|
|
6186
|
+
let selected;
|
|
6187
|
+
if (data.rotationStrategy === "round-robin") selected = [...eligible].sort((a, b) => (a.lastUsedAt || 0) - (b.lastUsedAt || 0))[0];
|
|
6188
|
+
else selected = eligible.find((a) => a.isPrimary) || eligible[0];
|
|
6189
|
+
const creds = selected.credentials;
|
|
6190
|
+
const expires = creds.expires || creds.expires_at || 0;
|
|
6191
|
+
if (!(creds.access || creds.access_token) || expires <= now + 6e4) {
|
|
6192
|
+
const refreshed = await refreshAntigravityToken(creds, fetchFn);
|
|
6193
|
+
selected.credentials = refreshed;
|
|
6194
|
+
selected.projectId = refreshed.projectId || selected.projectId;
|
|
6195
|
+
const idx = data.accounts.findIndex((a) => a.id === selected.id);
|
|
6196
|
+
if (idx >= 0) data.accounts[idx] = selected;
|
|
6197
|
+
if (selected.isPrimary) this.legacyStore.write(refreshed).catch(() => void 0);
|
|
6198
|
+
}
|
|
6199
|
+
selected.lastUsedAt = now;
|
|
6200
|
+
data.activeAccountId = selected.id;
|
|
6201
|
+
await this.write(data);
|
|
6202
|
+
return {
|
|
6203
|
+
account: selected,
|
|
6204
|
+
token: selected.credentials.access || selected.credentials.access_token,
|
|
6205
|
+
projectId: selected.projectId || selected.credentials.projectId
|
|
6206
|
+
};
|
|
6207
|
+
}
|
|
6208
|
+
};
|
|
6209
|
+
//#endregion
|
|
5900
6210
|
//#region src/host/antigravity/adapter.ts
|
|
5901
6211
|
function resolveDefaultReasoningEffort$2(efforts, configuredEffort) {
|
|
5902
6212
|
if (configuredEffort && efforts.includes(configuredEffort)) return ReasoningEffortId(configuredEffort);
|
|
@@ -5909,12 +6219,14 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
5909
6219
|
modelSettings;
|
|
5910
6220
|
preferences;
|
|
5911
6221
|
options;
|
|
5912
|
-
|
|
6222
|
+
accountPool;
|
|
6223
|
+
constructor(store = new FileCredentialStore$1(), modelSettings = new FileModelSettingsStore$1(), preferences, options = {}, accountPool) {
|
|
5913
6224
|
super();
|
|
5914
6225
|
this.store = store;
|
|
5915
6226
|
this.modelSettings = modelSettings;
|
|
5916
6227
|
this.preferences = preferences;
|
|
5917
6228
|
this.options = options;
|
|
6229
|
+
this.accountPool = accountPool ?? new AccountPoolStore(void 0, void 0, store);
|
|
5918
6230
|
}
|
|
5919
6231
|
providerInfo(provider) {
|
|
5920
6232
|
return {
|
|
@@ -5927,6 +6239,7 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
5927
6239
|
async listModels(provider) {
|
|
5928
6240
|
const prov = provider || "antigravity";
|
|
5929
6241
|
const settings = this.preferences ? this.preferences.status() : await this.modelSettings.read();
|
|
6242
|
+
if (settings.enabled === false) return [];
|
|
5930
6243
|
const enabledSet = new Set(settings.enabledModelIds);
|
|
5931
6244
|
const available = MODELS.filter((m) => enabledSet.has(m.id));
|
|
5932
6245
|
const overrides = settings.contextWindowOverrides || {};
|
|
@@ -5997,8 +6310,6 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
5997
6310
|
}
|
|
5998
6311
|
async *requestStream(options, model, signal) {
|
|
5999
6312
|
const fetchFn = this.options.fetchFn ?? fetch;
|
|
6000
|
-
const { token, projectId: defaultProj } = await ensureApiKey(this.store, fetchFn);
|
|
6001
|
-
const projectId = defaultProj || "antigravity-default";
|
|
6002
6313
|
const effort = String(options.reasoningEffort || "medium").toLowerCase();
|
|
6003
6314
|
const routing = ROUTING[model.id];
|
|
6004
6315
|
const initialRuntime = routing?.routing[effort] || routing?.defaultRequestId || model.id;
|
|
@@ -6010,26 +6321,54 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
6010
6321
|
}
|
|
6011
6322
|
const requestOptions = offloadOldestRequestImages$2(options);
|
|
6012
6323
|
const images = await resolveRequestImages$2(requestOptions, this.options.attachments, signal);
|
|
6324
|
+
const triedAccountIds = /* @__PURE__ */ new Set();
|
|
6013
6325
|
let response;
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
if (response.status === 404) break;
|
|
6029
|
-
} catch (err) {
|
|
6030
|
-
if (signal.aborted) throw new LlmError("Antigravity request aborted", "ABORTED", { cause: err });
|
|
6326
|
+
while (true) {
|
|
6327
|
+
let eff;
|
|
6328
|
+
try {
|
|
6329
|
+
eff = await this.accountPool.getEffectiveAccount(triedAccountIds, fetchFn);
|
|
6330
|
+
} catch (poolErr) {
|
|
6331
|
+
const poolData = await this.accountPool.read().catch(() => null);
|
|
6332
|
+
if (!poolData || poolData.accounts.length === 0) {
|
|
6333
|
+
const { token, projectId: defaultProj } = await ensureApiKey(this.store, fetchFn);
|
|
6334
|
+
eff = {
|
|
6335
|
+
account: { id: "legacy" },
|
|
6336
|
+
token,
|
|
6337
|
+
projectId: defaultProj
|
|
6338
|
+
};
|
|
6339
|
+
} else throw poolErr;
|
|
6031
6340
|
}
|
|
6032
|
-
|
|
6341
|
+
const { account, token, projectId: defaultProj } = eff;
|
|
6342
|
+
const projectId = defaultProj || "antigravity-default";
|
|
6343
|
+
triedAccountIds.add(account.id);
|
|
6344
|
+
for (const runtimeModel of candidates) {
|
|
6345
|
+
const body = JSON.stringify(buildRequest$2(requestOptions, model, projectId, runtimeModel, effort, images));
|
|
6346
|
+
const headers = {
|
|
6347
|
+
...antigravityHeaders(token),
|
|
6348
|
+
...model.id.startsWith("claude-") ? { "anthropic-beta": "interleaved-thinking-2025-05-14" } : {}
|
|
6349
|
+
};
|
|
6350
|
+
for (const endpoint of endpointCandidates()) try {
|
|
6351
|
+
response = await fetchFn(`${endpoint}/v1internal:streamGenerateContent?alt=sse`, {
|
|
6352
|
+
method: "POST",
|
|
6353
|
+
headers,
|
|
6354
|
+
body,
|
|
6355
|
+
signal
|
|
6356
|
+
});
|
|
6357
|
+
if (response.ok || response.status === 400) break;
|
|
6358
|
+
if (response.status === 404) break;
|
|
6359
|
+
} catch (err) {
|
|
6360
|
+
if (signal.aborted) throw new LlmError("Antigravity request aborted", "ABORTED", { cause: err });
|
|
6361
|
+
}
|
|
6362
|
+
if (response && (response.ok || response.status === 400)) break;
|
|
6363
|
+
}
|
|
6364
|
+
if (response && response.status === 429) {
|
|
6365
|
+
const retryAfterHeader = response.headers.get("retry-after");
|
|
6366
|
+
const retryAfterSec = retryAfterHeader ? Number(retryAfterHeader) : NaN;
|
|
6367
|
+
const cooldownMs = Number.isFinite(retryAfterSec) && retryAfterSec > 0 ? retryAfterSec * 1e3 : 900 * 1e3;
|
|
6368
|
+
await this.accountPool.markCooldown(account.id, cooldownMs, "429 Rate Limit");
|
|
6369
|
+
if (await this.accountPool.hasAnotherAvailableAccount(triedAccountIds)) continue;
|
|
6370
|
+
}
|
|
6371
|
+
break;
|
|
6033
6372
|
}
|
|
6034
6373
|
if (!response || !response.ok) {
|
|
6035
6374
|
const status = response?.status ?? 500;
|
|
@@ -6097,7 +6436,7 @@ async function readRequestJson$2(request) {
|
|
|
6097
6436
|
request.on("error", reject);
|
|
6098
6437
|
});
|
|
6099
6438
|
}
|
|
6100
|
-
async function getAntigravityWebStatus(store, modelSettings, preferences) {
|
|
6439
|
+
async function getAntigravityWebStatus(store, modelSettings, preferences, accountPool = new AccountPoolStore(void 0, void 0, store)) {
|
|
6101
6440
|
const credentials = await store.read();
|
|
6102
6441
|
const settings = preferences ? preferences.status() : await modelSettings.read();
|
|
6103
6442
|
const quota = getCachedQuota();
|
|
@@ -6111,20 +6450,27 @@ async function getAntigravityWebStatus(store, modelSettings, preferences) {
|
|
|
6111
6450
|
contextWindow: overrides[m.id] || m.contextWindow,
|
|
6112
6451
|
reasoningEfforts: m.reasoningEfforts
|
|
6113
6452
|
}));
|
|
6453
|
+
const accounts = await accountPool.listAccounts().catch(() => []);
|
|
6454
|
+
const poolData = await accountPool.read().catch(() => null);
|
|
6455
|
+
const activeAccount = accounts.find((a) => a.id === poolData?.activeAccountId) || accounts[0];
|
|
6114
6456
|
return {
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6457
|
+
enabled: settings.enabled !== false,
|
|
6458
|
+
authenticated: accounts.length > 0 || !!(credentials?.access || credentials?.access_token),
|
|
6459
|
+
email: activeAccount?.email || credentials?.email,
|
|
6460
|
+
projectId: activeAccount?.projectId || credentials?.projectId,
|
|
6461
|
+
hasCredentials: accounts.length > 0 || !!credentials,
|
|
6119
6462
|
storagePath: store.path(),
|
|
6120
6463
|
lastFetchedAt: quota?.fetchedAt,
|
|
6121
6464
|
quota,
|
|
6122
6465
|
models,
|
|
6123
6466
|
contextWindowOverrides: overrides,
|
|
6124
|
-
defaultReasoningEffort: settings.defaultReasoningEffort || null
|
|
6467
|
+
defaultReasoningEffort: settings.defaultReasoningEffort || null,
|
|
6468
|
+
accounts,
|
|
6469
|
+
activeAccountId: poolData?.activeAccountId || activeAccount?.id,
|
|
6470
|
+
rotationStrategy: poolData?.rotationStrategy || "sequential"
|
|
6125
6471
|
};
|
|
6126
6472
|
}
|
|
6127
|
-
function registerAntigravityRoutes(ctx, store, modelSettings, preferences, fetchFn = fetch) {
|
|
6473
|
+
function registerAntigravityRoutes(ctx, store, modelSettings, preferences, fetchFn = fetch, accountPool = new AccountPoolStore(void 0, void 0, store)) {
|
|
6128
6474
|
return ctx.webServer.register({
|
|
6129
6475
|
kind: "prefix",
|
|
6130
6476
|
path: "/antigravity/api",
|
|
@@ -6139,14 +6485,16 @@ function registerAntigravityRoutes(ctx, store, modelSettings, preferences, fetch
|
|
|
6139
6485
|
if (authenticated && (!cached || Date.now() - (cached.fetchedAt || 0) > 12e4)) await fetchAccountQuota(store, modelSettings, fetchFn).catch(() => void 0);
|
|
6140
6486
|
return sendJson$3(response, 200, {
|
|
6141
6487
|
ok: true,
|
|
6142
|
-
value: await getAntigravityWebStatus(store, modelSettings, preferences)
|
|
6488
|
+
value: await getAntigravityWebStatus(store, modelSettings, preferences, accountPool)
|
|
6143
6489
|
});
|
|
6144
6490
|
}
|
|
6145
|
-
if (path === "login") {
|
|
6491
|
+
if (path === "login" || path === "accounts/login") {
|
|
6146
6492
|
if (request.method !== "POST") return sendMethodNotAllowed$2(response);
|
|
6147
6493
|
return sendJson$3(response, 200, {
|
|
6148
6494
|
ok: true,
|
|
6149
|
-
value: await beginWebLogin$1(store, fetchFn)
|
|
6495
|
+
value: await beginWebLogin$1(store, fetchFn, void 0, async (creds) => {
|
|
6496
|
+
await accountPool.addAccount(creds);
|
|
6497
|
+
})
|
|
6150
6498
|
});
|
|
6151
6499
|
}
|
|
6152
6500
|
if (path === "login/status") {
|
|
@@ -6156,13 +6504,33 @@ function registerAntigravityRoutes(ctx, store, modelSettings, preferences, fetch
|
|
|
6156
6504
|
value: getWebLoginStatus$2()
|
|
6157
6505
|
});
|
|
6158
6506
|
}
|
|
6507
|
+
if (path === "accounts") {
|
|
6508
|
+
if (request.method === "GET") return sendJson$3(response, 200, {
|
|
6509
|
+
ok: true,
|
|
6510
|
+
value: await accountPool.listAccounts()
|
|
6511
|
+
});
|
|
6512
|
+
if (request.method === "POST") {
|
|
6513
|
+
const body = await readRequestJson$2(request);
|
|
6514
|
+
const action = String(body.action || "");
|
|
6515
|
+
if (action === "set-primary" && typeof body.accountId === "string") await accountPool.setPrimary(body.accountId);
|
|
6516
|
+
else if (action === "set-alias" && typeof body.accountId === "string" && typeof body.alias === "string") await accountPool.setAlias(body.accountId, body.alias);
|
|
6517
|
+
else if (action === "delete" && typeof body.accountId === "string") await accountPool.deleteAccount(body.accountId);
|
|
6518
|
+
else if (action === "strategy" && (body.strategy === "sequential" || body.strategy === "round-robin")) await accountPool.setStrategy(body.strategy);
|
|
6519
|
+
else if (action === "clear-cooldown" && typeof body.accountId === "string") await accountPool.clearCooldown(body.accountId);
|
|
6520
|
+
return sendJson$3(response, 200, {
|
|
6521
|
+
ok: true,
|
|
6522
|
+
value: await getAntigravityWebStatus(store, modelSettings, preferences, accountPool)
|
|
6523
|
+
});
|
|
6524
|
+
}
|
|
6525
|
+
return sendMethodNotAllowed$2(response);
|
|
6526
|
+
}
|
|
6159
6527
|
if (path === "quota") {
|
|
6160
6528
|
if (request.method !== "GET" && request.method !== "POST") return sendMethodNotAllowed$2(response);
|
|
6161
6529
|
const quota = await fetchAccountQuota(store, modelSettings, fetchFn, true);
|
|
6162
6530
|
return sendJson$3(response, 200, {
|
|
6163
6531
|
ok: true,
|
|
6164
6532
|
value: {
|
|
6165
|
-
...await getAntigravityWebStatus(store, modelSettings, preferences),
|
|
6533
|
+
...await getAntigravityWebStatus(store, modelSettings, preferences, accountPool),
|
|
6166
6534
|
quota
|
|
6167
6535
|
}
|
|
6168
6536
|
});
|
|
@@ -6174,32 +6542,39 @@ function registerAntigravityRoutes(ctx, store, modelSettings, preferences, fetch
|
|
|
6174
6542
|
else await modelSettings.updateSettings(body);
|
|
6175
6543
|
return sendJson$3(response, 200, {
|
|
6176
6544
|
ok: true,
|
|
6177
|
-
value: await getAntigravityWebStatus(store, modelSettings, preferences)
|
|
6545
|
+
value: await getAntigravityWebStatus(store, modelSettings, preferences, accountPool)
|
|
6178
6546
|
});
|
|
6179
6547
|
}
|
|
6180
6548
|
if (path === "models") {
|
|
6181
6549
|
if (request.method === "GET") return sendJson$3(response, 200, {
|
|
6182
6550
|
ok: true,
|
|
6183
|
-
value: (await getAntigravityWebStatus(store, modelSettings, preferences)).models
|
|
6551
|
+
value: (await getAntigravityWebStatus(store, modelSettings, preferences, accountPool)).models
|
|
6184
6552
|
});
|
|
6185
6553
|
if (request.method === "POST") {
|
|
6186
6554
|
const body = await readRequestJson$2(request);
|
|
6187
|
-
if (Array.isArray(body.enabledModelIds) || body.contextWindowOverrides || body.defaultReasoningEffort !== void 0) if (preferences) await preferences.update(body);
|
|
6555
|
+
if (Array.isArray(body.enabledModelIds) || body.enabled !== void 0 || body.contextWindowOverrides || body.defaultReasoningEffort !== void 0) if (preferences) await preferences.update(body);
|
|
6188
6556
|
else await modelSettings.updateSettings(body);
|
|
6189
6557
|
return sendJson$3(response, 200, {
|
|
6190
6558
|
ok: true,
|
|
6191
|
-
value: await getAntigravityWebStatus(store, modelSettings, preferences)
|
|
6559
|
+
value: await getAntigravityWebStatus(store, modelSettings, preferences, accountPool)
|
|
6192
6560
|
});
|
|
6193
6561
|
}
|
|
6194
6562
|
return sendMethodNotAllowed$2(response);
|
|
6195
6563
|
}
|
|
6196
6564
|
if (path === "logout") {
|
|
6197
6565
|
if (request.method !== "POST") return sendMethodNotAllowed$2(response);
|
|
6198
|
-
await
|
|
6566
|
+
const body = await readRequestJson$2(request).catch(() => ({}));
|
|
6567
|
+
const targetId = typeof body.accountId === "string" ? body.accountId : void 0;
|
|
6568
|
+
if (targetId) await accountPool.deleteAccount(targetId);
|
|
6569
|
+
else {
|
|
6570
|
+
const poolData = await accountPool.read().catch(() => null);
|
|
6571
|
+
if (poolData?.activeAccountId) await accountPool.deleteAccount(poolData.activeAccountId);
|
|
6572
|
+
else await store.delete();
|
|
6573
|
+
}
|
|
6199
6574
|
clearCachedQuota();
|
|
6200
6575
|
return sendJson$3(response, 200, {
|
|
6201
6576
|
ok: true,
|
|
6202
|
-
value: await getAntigravityWebStatus(store, modelSettings)
|
|
6577
|
+
value: await getAntigravityWebStatus(store, modelSettings, preferences, accountPool)
|
|
6203
6578
|
});
|
|
6204
6579
|
}
|
|
6205
6580
|
return sendJson$3(response, 404, {
|
|
@@ -7223,6 +7598,7 @@ const DEFAULT_ENABLED_MODEL_IDS$1 = FALLBACK_MODELS$1.map((model) => model.id);
|
|
|
7223
7598
|
function registerCommandCodePreferenceStore(settings, fallbackStore = new FileModelSettingsStore()) {
|
|
7224
7599
|
if (!settings) return {
|
|
7225
7600
|
status: () => ({
|
|
7601
|
+
enabled: true,
|
|
7226
7602
|
enabledModelIds: [...DEFAULT_ENABLED_MODEL_IDS$1],
|
|
7227
7603
|
catalogModels: [],
|
|
7228
7604
|
contextWindowOverrides: {},
|
|
@@ -7232,6 +7608,7 @@ function registerCommandCodePreferenceStore(settings, fallbackStore = new FileMo
|
|
|
7232
7608
|
};
|
|
7233
7609
|
const ns = SettingsModule.settingsNamespace ? SettingsModule.settingsNamespace(COMMAND_CODE_PREFERENCES_NAMESPACE) : COMMAND_CODE_PREFERENCES_NAMESPACE;
|
|
7234
7610
|
const scope = settings.register.call(settings, ns, z.object({
|
|
7611
|
+
enabled: z.boolean().default(true),
|
|
7235
7612
|
enabledModelIds: z.array(z.string()).default([...DEFAULT_ENABLED_MODEL_IDS$1]),
|
|
7236
7613
|
contextWindowOverrides: z.dict(z.number()).default({}),
|
|
7237
7614
|
defaultReasoningEffort: z.union([...COMMAND_CODE_REASONING_EFFORTS.map((effort) => z.const(effort)), z.const(null)]).default(null)
|
|
@@ -7240,6 +7617,7 @@ function registerCommandCodePreferenceStore(settings, fallbackStore = new FileMo
|
|
|
7240
7617
|
status: () => {
|
|
7241
7618
|
const value = scope.get();
|
|
7242
7619
|
return {
|
|
7620
|
+
enabled: value.enabled !== false,
|
|
7243
7621
|
enabledModelIds: value.enabledModelIds,
|
|
7244
7622
|
catalogModels: [],
|
|
7245
7623
|
contextWindowOverrides: value.contextWindowOverrides,
|
|
@@ -7249,6 +7627,7 @@ function registerCommandCodePreferenceStore(settings, fallbackStore = new FileMo
|
|
|
7249
7627
|
update: async (patch) => {
|
|
7250
7628
|
const current = scope.get();
|
|
7251
7629
|
const normalized = {
|
|
7630
|
+
enabled: patch.enabled !== void 0 ? patch.enabled : current.enabled !== false,
|
|
7252
7631
|
enabledModelIds: patch.enabledModelIds ?? current.enabledModelIds,
|
|
7253
7632
|
contextWindowOverrides: patch.contextWindowOverrides ? {
|
|
7254
7633
|
...current.contextWindowOverrides,
|
|
@@ -7404,15 +7783,21 @@ var FileModelSettingsStore = class {
|
|
|
7404
7783
|
const parsed = JSON.parse(content);
|
|
7405
7784
|
if (typeof parsed === "object" && parsed !== null) {
|
|
7406
7785
|
const record = parsed;
|
|
7786
|
+
const enabledModelIds = Array.isArray(record.enabledModelIds) ? record.enabledModelIds.filter((id) => typeof id === "string") : [...DEFAULT_ENABLED_MODEL_IDS$1];
|
|
7787
|
+
const catalogModels = Array.isArray(record.catalogModels) ? record.catalogModels : [];
|
|
7788
|
+
const contextWindowOverrides = typeof record.contextWindowOverrides === "object" && record.contextWindowOverrides !== null ? record.contextWindowOverrides : {};
|
|
7789
|
+
const defaultReasoningEffort = isReasoningEffort$1(record.defaultReasoningEffort) ? record.defaultReasoningEffort : null;
|
|
7407
7790
|
return {
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7791
|
+
enabled: record.enabled !== false,
|
|
7792
|
+
enabledModelIds,
|
|
7793
|
+
catalogModels,
|
|
7794
|
+
contextWindowOverrides,
|
|
7795
|
+
defaultReasoningEffort
|
|
7412
7796
|
};
|
|
7413
7797
|
}
|
|
7414
7798
|
} catch {}
|
|
7415
7799
|
return {
|
|
7800
|
+
enabled: true,
|
|
7416
7801
|
enabledModelIds: [...DEFAULT_ENABLED_MODEL_IDS$1],
|
|
7417
7802
|
catalogModels: [],
|
|
7418
7803
|
contextWindowOverrides: {},
|
|
@@ -7429,6 +7814,7 @@ var FileModelSettingsStore = class {
|
|
|
7429
7814
|
const current = await this.read();
|
|
7430
7815
|
const next = {
|
|
7431
7816
|
...current,
|
|
7817
|
+
...patch.enabled !== void 0 ? { enabled: patch.enabled } : {},
|
|
7432
7818
|
...patch.enabledModelIds !== void 0 ? { enabledModelIds: patch.enabledModelIds } : {},
|
|
7433
7819
|
...patch.contextWindowOverrides !== void 0 ? { contextWindowOverrides: {
|
|
7434
7820
|
...current.contextWindowOverrides,
|
|
@@ -8335,9 +8721,13 @@ function attachmentLabel$1(block) {
|
|
|
8335
8721
|
function collectImageRefs$1(content, refs) {
|
|
8336
8722
|
if (!Array.isArray(content)) return;
|
|
8337
8723
|
for (const block of content) {
|
|
8338
|
-
if (!isRecord$2(block)
|
|
8339
|
-
|
|
8340
|
-
|
|
8724
|
+
if (!isRecord$2(block)) continue;
|
|
8725
|
+
if (block.type === "image") {
|
|
8726
|
+
const attachment = attachmentOf$1(block);
|
|
8727
|
+
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
8728
|
+
continue;
|
|
8729
|
+
}
|
|
8730
|
+
if (block.type === "tool-result") collectImageRefs$1(block.content, refs);
|
|
8341
8731
|
}
|
|
8342
8732
|
}
|
|
8343
8733
|
function base64Length$1(bytes) {
|
|
@@ -8475,6 +8865,83 @@ function toolResultText$1(blocks) {
|
|
|
8475
8865
|
return "";
|
|
8476
8866
|
}).join("");
|
|
8477
8867
|
}
|
|
8868
|
+
/**
|
|
8869
|
+
* Anthropic `tool_result` content for one tool result, or `undefined` when the
|
|
8870
|
+
* result carries no image. Returning `undefined` is what keeps a plain tool
|
|
8871
|
+
* result a byte-identical string on the wire: the image-less path never changes
|
|
8872
|
+
* shape, so only results that actually hold pixels take the block-array form.
|
|
8873
|
+
*/
|
|
8874
|
+
function toolResultBlocks$1(blocks, images) {
|
|
8875
|
+
if (!Array.isArray(blocks)) return void 0;
|
|
8876
|
+
const out = [];
|
|
8877
|
+
let hasImage = false;
|
|
8878
|
+
for (const block of blocks) {
|
|
8879
|
+
if (!isRecord$2(block)) continue;
|
|
8880
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
8881
|
+
out.push({
|
|
8882
|
+
type: "text",
|
|
8883
|
+
text: sanitizeText$1(block.text)
|
|
8884
|
+
});
|
|
8885
|
+
continue;
|
|
8886
|
+
}
|
|
8887
|
+
if (block.type === "image") {
|
|
8888
|
+
hasImage = true;
|
|
8889
|
+
const inline = imageBlockToInline$1(block, images);
|
|
8890
|
+
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$1.has(inline.mediaType)) out.push({
|
|
8891
|
+
type: "image",
|
|
8892
|
+
source: {
|
|
8893
|
+
type: "base64",
|
|
8894
|
+
media_type: inline.mediaType,
|
|
8895
|
+
data: inline.data
|
|
8896
|
+
}
|
|
8897
|
+
});
|
|
8898
|
+
else out.push({
|
|
8899
|
+
type: "text",
|
|
8900
|
+
text: unavailableImageText$1(block)
|
|
8901
|
+
});
|
|
8902
|
+
continue;
|
|
8903
|
+
}
|
|
8904
|
+
if (block.type === "tool-result") {
|
|
8905
|
+
const nested = toolResultBlocks$1(block.content, images);
|
|
8906
|
+
if (nested) {
|
|
8907
|
+
hasImage = true;
|
|
8908
|
+
out.push(...nested);
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
}
|
|
8912
|
+
if (!hasImage) return void 0;
|
|
8913
|
+
if (out[0]?.type !== "text") out.unshift({
|
|
8914
|
+
type: "text",
|
|
8915
|
+
text: ""
|
|
8916
|
+
});
|
|
8917
|
+
return out;
|
|
8918
|
+
}
|
|
8919
|
+
/**
|
|
8920
|
+
* OpenAI `image_url` blocks for one tool result. A `role: "tool"` message can
|
|
8921
|
+
* only carry text, so these ride on a `user` message appended after the run of
|
|
8922
|
+
* tool messages rather than inside it.
|
|
8923
|
+
*/
|
|
8924
|
+
function toolResultImageBlocks$1(blocks, images) {
|
|
8925
|
+
if (!Array.isArray(blocks)) return [];
|
|
8926
|
+
const out = [];
|
|
8927
|
+
for (const block of blocks) {
|
|
8928
|
+
if (!isRecord$2(block)) continue;
|
|
8929
|
+
if (block.type === "image") {
|
|
8930
|
+
const inline = imageBlockToInline$1(block, images);
|
|
8931
|
+
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$1.has(inline.mediaType)) out.push({
|
|
8932
|
+
type: "image_url",
|
|
8933
|
+
image_url: { url: `data:${inline.mediaType};base64,${inline.data}` }
|
|
8934
|
+
});
|
|
8935
|
+
else out.push({
|
|
8936
|
+
type: "text",
|
|
8937
|
+
text: unavailableImageText$1(block)
|
|
8938
|
+
});
|
|
8939
|
+
continue;
|
|
8940
|
+
}
|
|
8941
|
+
if (block.type === "tool-result") out.push(...toolResultImageBlocks$1(block.content, images));
|
|
8942
|
+
}
|
|
8943
|
+
return out;
|
|
8944
|
+
}
|
|
8478
8945
|
function toolCallArguments$1(raw) {
|
|
8479
8946
|
if (typeof raw === "string") return raw;
|
|
8480
8947
|
if (raw === void 0 || raw === null) return "{}";
|
|
@@ -8571,14 +9038,27 @@ function buildOpenAIRequest$1(options, images = NO_RESOLVED_IMAGES$1) {
|
|
|
8571
9038
|
role: "system",
|
|
8572
9039
|
content: system
|
|
8573
9040
|
});
|
|
8574
|
-
|
|
9041
|
+
const conversation = nonSystemMessages$1(options);
|
|
9042
|
+
for (let index = 0; index < conversation.length; index++) {
|
|
9043
|
+
const message = conversation[index];
|
|
8575
9044
|
if (isToolResultMessage$1(message)) {
|
|
8576
|
-
const
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
9045
|
+
const imageBlocks = [];
|
|
9046
|
+
while (index < conversation.length && isToolResultMessage$1(conversation[index])) {
|
|
9047
|
+
const current = conversation[index];
|
|
9048
|
+
const block = current.content[0];
|
|
9049
|
+
const callId = isRecord$2(block) && typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
9050
|
+
messages.push({
|
|
9051
|
+
role: "tool",
|
|
9052
|
+
tool_call_id: callId,
|
|
9053
|
+
content: toolResultText$1(current.content)
|
|
9054
|
+
});
|
|
9055
|
+
imageBlocks.push(...toolResultImageBlocks$1(current.content, images));
|
|
9056
|
+
index += 1;
|
|
9057
|
+
}
|
|
9058
|
+
index -= 1;
|
|
9059
|
+
if (imageBlocks.length > 0) messages.push({
|
|
9060
|
+
role: "user",
|
|
9061
|
+
content: imageBlocks
|
|
8582
9062
|
});
|
|
8583
9063
|
continue;
|
|
8584
9064
|
}
|
|
@@ -8650,10 +9130,11 @@ function anthropicUserContent$1(message, images) {
|
|
|
8650
9130
|
});
|
|
8651
9131
|
} else if (block.type === "tool-result") {
|
|
8652
9132
|
const callId = typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
9133
|
+
const resultBlocks = toolResultBlocks$1(block.content, images);
|
|
8653
9134
|
blocks.push({
|
|
8654
9135
|
type: "tool_result",
|
|
8655
9136
|
tool_use_id: callId,
|
|
8656
|
-
content: toolResultText$1(block.content),
|
|
9137
|
+
content: resultBlocks ?? toolResultText$1(block.content),
|
|
8657
9138
|
...block.isError === true ? { is_error: true } : {}
|
|
8658
9139
|
});
|
|
8659
9140
|
}
|
|
@@ -9231,9 +9712,10 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
9231
9712
|
async listModels(provider) {
|
|
9232
9713
|
const prov = provider || "command-code";
|
|
9233
9714
|
const settings = await this.settings();
|
|
9715
|
+
if (settings.enabled === false) return [];
|
|
9234
9716
|
const catalog = await this.catalog();
|
|
9235
9717
|
const enabled = new Set(settings.enabledModelIds);
|
|
9236
|
-
return
|
|
9718
|
+
return catalog.filter((model) => enabled.has(model.id)).map((model) => ({
|
|
9237
9719
|
provider: prov,
|
|
9238
9720
|
id: model.id,
|
|
9239
9721
|
name: model.name ?? model.id,
|
|
@@ -9858,14 +10340,13 @@ function fallbackCatalog$1() {
|
|
|
9858
10340
|
* "everything currently offered" keeps a first run from hiding the whole
|
|
9859
10341
|
* catalog behind an unedited default. Any explicit edit is honoured exactly.
|
|
9860
10342
|
*/
|
|
9861
|
-
function resolveEnabledModelIds$1(stored, catalog) {
|
|
10343
|
+
function resolveEnabledModelIds$1(stored, catalog, enabled = true) {
|
|
10344
|
+
if (!enabled) return [];
|
|
9862
10345
|
const catalogIds = catalog.map((model) => model.id);
|
|
9863
10346
|
const shippedDefaults = new Set(FALLBACK_MODELS$1.map((model) => model.id));
|
|
9864
|
-
|
|
9865
|
-
if (stored.length === 0 || isUntouchedDefault) return catalogIds;
|
|
10347
|
+
if (stored.length > 0 && stored.length === shippedDefaults.size && stored.every((id) => shippedDefaults.has(id))) return catalogIds;
|
|
9866
10348
|
const known = new Set(catalogIds);
|
|
9867
|
-
|
|
9868
|
-
return kept.length === 0 ? catalogIds : kept;
|
|
10349
|
+
return stored.filter((id) => known.has(id));
|
|
9869
10350
|
}
|
|
9870
10351
|
function readOption$1(value, fallback) {
|
|
9871
10352
|
return typeof value === "function" ? value() : value ?? fallback;
|
|
@@ -9880,9 +10361,11 @@ async function getCommandCodeWebStatus(store, modelSettings, preferences, option
|
|
|
9880
10361
|
apiEnv
|
|
9881
10362
|
});
|
|
9882
10363
|
const catalog = live.length > 0 ? live : fallbackCatalog$1();
|
|
9883
|
-
const
|
|
10364
|
+
const enabled = settings.enabled !== false;
|
|
10365
|
+
const models = buildModelOptions$1(catalog, resolveEnabledModelIds$1(settings.enabledModelIds, catalog, enabled), settings.contextWindowOverrides);
|
|
9884
10366
|
const quota = getCachedQuota$1();
|
|
9885
10367
|
return {
|
|
10368
|
+
enabled,
|
|
9886
10369
|
authenticated: credentials !== null,
|
|
9887
10370
|
hasCredentials: credentials !== null,
|
|
9888
10371
|
storagePath: store.path(),
|
|
@@ -10014,6 +10497,7 @@ function registerCommandCodeRoutes(ctx, store, modelSettings, preferences, optio
|
|
|
10014
10497
|
});
|
|
10015
10498
|
const body = await readRequestJson$1(request);
|
|
10016
10499
|
const patch = {};
|
|
10500
|
+
if (typeof body.enabled === "boolean") patch.enabled = body.enabled;
|
|
10017
10501
|
if (Array.isArray(body.enabledModelIds)) patch.enabledModelIds = body.enabledModelIds.filter((id) => typeof id === "string");
|
|
10018
10502
|
if (typeof body.contextWindowOverrides === "object" && body.contextWindowOverrides !== null) {
|
|
10019
10503
|
const overrides = {};
|
|
@@ -10360,6 +10844,7 @@ const DEFAULT_ENABLED_MODEL_IDS = FALLBACK_MODELS.map((model) => model.id);
|
|
|
10360
10844
|
function registerKimiCodePreferenceStore(settings, fallbackStore = new FileModelSettingsStore$2()) {
|
|
10361
10845
|
if (!settings) return {
|
|
10362
10846
|
status: () => ({
|
|
10847
|
+
enabled: true,
|
|
10363
10848
|
enabledModelIds: [...DEFAULT_ENABLED_MODEL_IDS],
|
|
10364
10849
|
catalogModels: [],
|
|
10365
10850
|
contextWindowOverrides: {},
|
|
@@ -10369,6 +10854,7 @@ function registerKimiCodePreferenceStore(settings, fallbackStore = new FileModel
|
|
|
10369
10854
|
};
|
|
10370
10855
|
const ns = SettingsModule.settingsNamespace ? SettingsModule.settingsNamespace(KIMI_CODE_PREFERENCES_NAMESPACE) : KIMI_CODE_PREFERENCES_NAMESPACE;
|
|
10371
10856
|
const scope = settings.register.call(settings, ns, z.object({
|
|
10857
|
+
enabled: z.boolean().default(true),
|
|
10372
10858
|
enabledModelIds: z.array(z.string()).default([...DEFAULT_ENABLED_MODEL_IDS]),
|
|
10373
10859
|
contextWindowOverrides: z.dict(z.number()).default({}),
|
|
10374
10860
|
defaultReasoningEffort: z.union([...KIMI_CODE_REASONING_EFFORTS.map((effort) => z.const(effort)), z.const(null)]).default(null)
|
|
@@ -10377,6 +10863,7 @@ function registerKimiCodePreferenceStore(settings, fallbackStore = new FileModel
|
|
|
10377
10863
|
status: () => {
|
|
10378
10864
|
const value = scope.get();
|
|
10379
10865
|
return {
|
|
10866
|
+
enabled: value.enabled !== false,
|
|
10380
10867
|
enabledModelIds: value.enabledModelIds,
|
|
10381
10868
|
catalogModels: [],
|
|
10382
10869
|
contextWindowOverrides: value.contextWindowOverrides,
|
|
@@ -10386,6 +10873,7 @@ function registerKimiCodePreferenceStore(settings, fallbackStore = new FileModel
|
|
|
10386
10873
|
update: async (patch) => {
|
|
10387
10874
|
const current = scope.get();
|
|
10388
10875
|
const normalized = {
|
|
10876
|
+
enabled: patch.enabled !== void 0 ? patch.enabled : current.enabled !== false,
|
|
10389
10877
|
enabledModelIds: patch.enabledModelIds ?? current.enabledModelIds,
|
|
10390
10878
|
contextWindowOverrides: patch.contextWindowOverrides ? {
|
|
10391
10879
|
...current.contextWindowOverrides,
|
|
@@ -10576,15 +11064,21 @@ var FileModelSettingsStore$2 = class {
|
|
|
10576
11064
|
const parsed = JSON.parse(content);
|
|
10577
11065
|
if (typeof parsed === "object" && parsed !== null) {
|
|
10578
11066
|
const record = parsed;
|
|
11067
|
+
const enabledModelIds = Array.isArray(record.enabledModelIds) ? record.enabledModelIds.filter((id) => typeof id === "string") : [...DEFAULT_ENABLED_MODEL_IDS];
|
|
11068
|
+
const catalogModels = Array.isArray(record.catalogModels) ? record.catalogModels : [];
|
|
11069
|
+
const contextWindowOverrides = typeof record.contextWindowOverrides === "object" && record.contextWindowOverrides !== null ? record.contextWindowOverrides : {};
|
|
11070
|
+
const defaultReasoningEffort = isReasoningEffort(record.defaultReasoningEffort) ? record.defaultReasoningEffort : null;
|
|
10579
11071
|
return {
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
|
|
10583
|
-
|
|
11072
|
+
enabled: record.enabled !== false,
|
|
11073
|
+
enabledModelIds,
|
|
11074
|
+
catalogModels,
|
|
11075
|
+
contextWindowOverrides,
|
|
11076
|
+
defaultReasoningEffort
|
|
10584
11077
|
};
|
|
10585
11078
|
}
|
|
10586
11079
|
} catch {}
|
|
10587
11080
|
return {
|
|
11081
|
+
enabled: true,
|
|
10588
11082
|
enabledModelIds: [...DEFAULT_ENABLED_MODEL_IDS],
|
|
10589
11083
|
catalogModels: [],
|
|
10590
11084
|
contextWindowOverrides: {},
|
|
@@ -10601,6 +11095,7 @@ var FileModelSettingsStore$2 = class {
|
|
|
10601
11095
|
const current = await this.read();
|
|
10602
11096
|
const next = {
|
|
10603
11097
|
...current,
|
|
11098
|
+
...patch.enabled !== void 0 ? { enabled: patch.enabled } : {},
|
|
10604
11099
|
...patch.enabledModelIds !== void 0 ? { enabledModelIds: patch.enabledModelIds } : {},
|
|
10605
11100
|
...patch.contextWindowOverrides !== void 0 ? { contextWindowOverrides: {
|
|
10606
11101
|
...current.contextWindowOverrides,
|
|
@@ -12131,9 +12626,13 @@ function attachmentLabel(block) {
|
|
|
12131
12626
|
function collectImageRefs(content, refs) {
|
|
12132
12627
|
if (!Array.isArray(content)) return;
|
|
12133
12628
|
for (const block of content) {
|
|
12134
|
-
if (!isRecord(block)
|
|
12135
|
-
|
|
12136
|
-
|
|
12629
|
+
if (!isRecord(block)) continue;
|
|
12630
|
+
if (block.type === "image") {
|
|
12631
|
+
const attachment = attachmentOf(block);
|
|
12632
|
+
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
12633
|
+
continue;
|
|
12634
|
+
}
|
|
12635
|
+
if (block.type === "tool-result") collectImageRefs(block.content, refs);
|
|
12137
12636
|
}
|
|
12138
12637
|
}
|
|
12139
12638
|
function base64Length(bytes) {
|
|
@@ -12410,6 +12909,83 @@ function toolResultText(blocks) {
|
|
|
12410
12909
|
return "";
|
|
12411
12910
|
}).join("");
|
|
12412
12911
|
}
|
|
12912
|
+
/**
|
|
12913
|
+
* Anthropic `tool_result` content for one tool result, or `undefined` when the
|
|
12914
|
+
* result carries no image. Returning `undefined` is what keeps a plain tool
|
|
12915
|
+
* result a byte-identical string on the wire: the image-less path never changes
|
|
12916
|
+
* shape, so only results that actually hold pixels take the block-array form.
|
|
12917
|
+
*/
|
|
12918
|
+
function toolResultBlocks(blocks, images) {
|
|
12919
|
+
if (!Array.isArray(blocks)) return void 0;
|
|
12920
|
+
const out = [];
|
|
12921
|
+
let hasImage = false;
|
|
12922
|
+
for (const block of blocks) {
|
|
12923
|
+
if (!isRecord(block)) continue;
|
|
12924
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
12925
|
+
out.push({
|
|
12926
|
+
type: "text",
|
|
12927
|
+
text: sanitizeText(block.text)
|
|
12928
|
+
});
|
|
12929
|
+
continue;
|
|
12930
|
+
}
|
|
12931
|
+
if (block.type === "image") {
|
|
12932
|
+
hasImage = true;
|
|
12933
|
+
const inline = imageBlockToInline(block, images);
|
|
12934
|
+
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES.has(inline.mediaType)) out.push({
|
|
12935
|
+
type: "image",
|
|
12936
|
+
source: {
|
|
12937
|
+
type: "base64",
|
|
12938
|
+
media_type: inline.mediaType,
|
|
12939
|
+
data: inline.data
|
|
12940
|
+
}
|
|
12941
|
+
});
|
|
12942
|
+
else out.push({
|
|
12943
|
+
type: "text",
|
|
12944
|
+
text: unavailableImageText(block)
|
|
12945
|
+
});
|
|
12946
|
+
continue;
|
|
12947
|
+
}
|
|
12948
|
+
if (block.type === "tool-result") {
|
|
12949
|
+
const nested = toolResultBlocks(block.content, images);
|
|
12950
|
+
if (nested) {
|
|
12951
|
+
hasImage = true;
|
|
12952
|
+
out.push(...nested);
|
|
12953
|
+
}
|
|
12954
|
+
}
|
|
12955
|
+
}
|
|
12956
|
+
if (!hasImage) return void 0;
|
|
12957
|
+
if (out[0]?.type !== "text") out.unshift({
|
|
12958
|
+
type: "text",
|
|
12959
|
+
text: ""
|
|
12960
|
+
});
|
|
12961
|
+
return out;
|
|
12962
|
+
}
|
|
12963
|
+
/**
|
|
12964
|
+
* OpenAI `image_url` blocks for one tool result. A `role: "tool"` message can
|
|
12965
|
+
* only carry text, so these ride on a `user` message appended after the run of
|
|
12966
|
+
* tool messages rather than inside it.
|
|
12967
|
+
*/
|
|
12968
|
+
function toolResultImageBlocks(blocks, images) {
|
|
12969
|
+
if (!Array.isArray(blocks)) return [];
|
|
12970
|
+
const out = [];
|
|
12971
|
+
for (const block of blocks) {
|
|
12972
|
+
if (!isRecord(block)) continue;
|
|
12973
|
+
if (block.type === "image") {
|
|
12974
|
+
const inline = imageBlockToInline(block, images);
|
|
12975
|
+
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES.has(inline.mediaType)) out.push({
|
|
12976
|
+
type: "image_url",
|
|
12977
|
+
image_url: { url: `data:${inline.mediaType};base64,${inline.data}` }
|
|
12978
|
+
});
|
|
12979
|
+
else out.push({
|
|
12980
|
+
type: "text",
|
|
12981
|
+
text: unavailableImageText(block)
|
|
12982
|
+
});
|
|
12983
|
+
continue;
|
|
12984
|
+
}
|
|
12985
|
+
if (block.type === "tool-result") out.push(...toolResultImageBlocks(block.content, images));
|
|
12986
|
+
}
|
|
12987
|
+
return out;
|
|
12988
|
+
}
|
|
12413
12989
|
function toolCallArguments(raw) {
|
|
12414
12990
|
if (typeof raw === "string") return raw;
|
|
12415
12991
|
if (raw === void 0 || raw === null) return "{}";
|
|
@@ -12444,15 +13020,134 @@ function leadingSystemText(options) {
|
|
|
12444
13020
|
function nonSystemMessages(options) {
|
|
12445
13021
|
return options.messages.filter((message) => message.role !== "system");
|
|
12446
13022
|
}
|
|
12447
|
-
|
|
12448
|
-
|
|
13023
|
+
function cloneJsonValue(value) {
|
|
13024
|
+
if (Array.isArray(value)) return value.map(cloneJsonValue);
|
|
13025
|
+
if (isRecord(value)) {
|
|
13026
|
+
const res = {};
|
|
13027
|
+
for (const [k, v] of Object.entries(value)) res[k] = cloneJsonValue(v);
|
|
13028
|
+
return res;
|
|
13029
|
+
}
|
|
13030
|
+
return value;
|
|
13031
|
+
}
|
|
13032
|
+
function resolveLocalJsonPointer(root, ref) {
|
|
13033
|
+
if (ref === "#") return {
|
|
13034
|
+
found: true,
|
|
13035
|
+
value: root
|
|
13036
|
+
};
|
|
13037
|
+
let current = root;
|
|
13038
|
+
for (const rawPart of ref.slice(2).split("/")) {
|
|
13039
|
+
const part = rawPart.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
13040
|
+
if (isRecord(current)) {
|
|
13041
|
+
if (!Object.prototype.hasOwnProperty.call(current, part)) return { found: false };
|
|
13042
|
+
current = current[part];
|
|
13043
|
+
} else if (Array.isArray(current)) {
|
|
13044
|
+
const idx = Number(part);
|
|
13045
|
+
if (!/^(0|[1-9]\d*)$/.test(part) || idx >= current.length) return { found: false };
|
|
13046
|
+
current = current[idx];
|
|
13047
|
+
} else return { found: false };
|
|
13048
|
+
}
|
|
13049
|
+
return {
|
|
13050
|
+
found: true,
|
|
13051
|
+
value: current
|
|
13052
|
+
};
|
|
13053
|
+
}
|
|
13054
|
+
function derefNode(node, root, visited) {
|
|
13055
|
+
if (Array.isArray(node)) return node.map((item) => derefNode(item, root, visited));
|
|
13056
|
+
if (isRecord(node)) {
|
|
13057
|
+
if (typeof node["$ref"] === "string" && (node["$ref"] === "#" || node["$ref"].startsWith("#/"))) {
|
|
13058
|
+
const ref = node["$ref"];
|
|
13059
|
+
if (visited.has(ref)) return node;
|
|
13060
|
+
const resolved = resolveLocalJsonPointer(root, ref);
|
|
13061
|
+
if (resolved.found) {
|
|
13062
|
+
visited.add(ref);
|
|
13063
|
+
const inlined = derefNode(resolved.value, root, visited);
|
|
13064
|
+
visited.delete(ref);
|
|
13065
|
+
if (isRecord(inlined)) {
|
|
13066
|
+
const merged = { ...inlined };
|
|
13067
|
+
for (const [k, v] of Object.entries(node)) {
|
|
13068
|
+
if (k === "$ref") continue;
|
|
13069
|
+
merged[k] = derefNode(v, root, visited);
|
|
13070
|
+
}
|
|
13071
|
+
return merged;
|
|
13072
|
+
}
|
|
13073
|
+
return inlined;
|
|
13074
|
+
}
|
|
13075
|
+
return node;
|
|
13076
|
+
}
|
|
13077
|
+
const res = {};
|
|
13078
|
+
for (const [k, v] of Object.entries(node)) res[k] = derefNode(v, root, visited);
|
|
13079
|
+
return res;
|
|
13080
|
+
}
|
|
13081
|
+
return node;
|
|
13082
|
+
}
|
|
13083
|
+
function hasUnresolvedDefinitionRef(node, bucketKey) {
|
|
13084
|
+
if (Array.isArray(node)) return node.some((child) => hasUnresolvedDefinitionRef(child, bucketKey));
|
|
13085
|
+
if (isRecord(node)) {
|
|
13086
|
+
const ref = node["$ref"];
|
|
13087
|
+
if (typeof ref === "string" && ref.startsWith(`#/${bucketKey}/`)) return true;
|
|
13088
|
+
for (const [k, v] of Object.entries(node)) {
|
|
13089
|
+
if (k === bucketKey) continue;
|
|
13090
|
+
if (hasUnresolvedDefinitionRef(v, bucketKey)) return true;
|
|
13091
|
+
}
|
|
13092
|
+
}
|
|
13093
|
+
return false;
|
|
13094
|
+
}
|
|
13095
|
+
function inferValueType(val) {
|
|
13096
|
+
if (val === null) return "null";
|
|
13097
|
+
if (Array.isArray(val)) return "array";
|
|
13098
|
+
switch (typeof val) {
|
|
13099
|
+
case "string": return "string";
|
|
13100
|
+
case "number": return Number.isInteger(val) ? "integer" : "number";
|
|
13101
|
+
case "boolean": return "boolean";
|
|
13102
|
+
case "object": return "object";
|
|
13103
|
+
default: return;
|
|
13104
|
+
}
|
|
13105
|
+
}
|
|
13106
|
+
function inferTypeFromValues(values) {
|
|
13107
|
+
const types = /* @__PURE__ */ new Set();
|
|
13108
|
+
for (const v of values) {
|
|
13109
|
+
const t = inferValueType(v);
|
|
13110
|
+
if (t) types.add(t);
|
|
13111
|
+
}
|
|
13112
|
+
if (types.has("number") && types.has("integer")) types.delete("integer");
|
|
13113
|
+
if (types.size === 1) return types.values().next().value;
|
|
13114
|
+
}
|
|
13115
|
+
function normalizeSchemaProperties(node) {
|
|
13116
|
+
if (!isRecord(node)) return;
|
|
13117
|
+
if (isRecord(node.properties)) {
|
|
13118
|
+
for (const propSchema of Object.values(node.properties)) if (isRecord(propSchema)) {
|
|
13119
|
+
if (!propSchema.type && !propSchema.$ref) {
|
|
13120
|
+
if (Array.isArray(propSchema.enum) && propSchema.enum.length > 0) propSchema.type = inferTypeFromValues(propSchema.enum) ?? "string";
|
|
13121
|
+
else if (propSchema.const !== void 0) propSchema.type = inferValueType(propSchema.const) ?? "string";
|
|
13122
|
+
else if (isRecord(propSchema.properties)) propSchema.type = "object";
|
|
13123
|
+
else if (propSchema.items) propSchema.type = "array";
|
|
13124
|
+
}
|
|
13125
|
+
normalizeSchemaProperties(propSchema);
|
|
13126
|
+
}
|
|
13127
|
+
}
|
|
13128
|
+
if (isRecord(node.items)) normalizeSchemaProperties(node.items);
|
|
13129
|
+
else if (Array.isArray(node.items)) for (const item of node.items) normalizeSchemaProperties(item);
|
|
13130
|
+
}
|
|
13131
|
+
/**
|
|
13132
|
+
* Normalizes tool parameter schemas for Kimi by stripping meta keywords ($schema),
|
|
13133
|
+
* inlining definitions ($defs/definitions/$ref), and ensuring property types for enums/consts.
|
|
13134
|
+
*/
|
|
13135
|
+
function normalizeKimiToolSchema(schema) {
|
|
12449
13136
|
if (!isRecord(schema)) return {
|
|
12450
13137
|
type: "object",
|
|
12451
13138
|
properties: {}
|
|
12452
13139
|
};
|
|
12453
|
-
const
|
|
12454
|
-
delete
|
|
12455
|
-
|
|
13140
|
+
const cloned = cloneJsonValue(schema);
|
|
13141
|
+
delete cloned.$schema;
|
|
13142
|
+
const dereffed = derefNode(cloned, cloned, /* @__PURE__ */ new Set());
|
|
13143
|
+
if (!hasUnresolvedDefinitionRef(dereffed, "$defs")) delete dereffed.$defs;
|
|
13144
|
+
if (!hasUnresolvedDefinitionRef(dereffed, "definitions")) delete dereffed.definitions;
|
|
13145
|
+
normalizeSchemaProperties(dereffed);
|
|
13146
|
+
return dereffed;
|
|
13147
|
+
}
|
|
13148
|
+
/** Drop the JSON-Schema keywords provider gateways reject or ignore, and normalize properties. */
|
|
13149
|
+
function stripMetaSchema(schema) {
|
|
13150
|
+
return normalizeKimiToolSchema(schema);
|
|
12456
13151
|
}
|
|
12457
13152
|
/** Concatenated reasoning text one assistant message carries, when it has any. */
|
|
12458
13153
|
function reasoningText(message) {
|
|
@@ -12663,26 +13358,41 @@ function buildOpenAIRequest(options, images = NO_RESOLVED_IMAGES, preserveThinki
|
|
|
12663
13358
|
}
|
|
12664
13359
|
};
|
|
12665
13360
|
flushSlots(0);
|
|
12666
|
-
|
|
13361
|
+
const conversation = nonSystemMessages(options);
|
|
13362
|
+
for (let index = 0; index < conversation.length; index++) {
|
|
13363
|
+
const message = conversation[index];
|
|
12667
13364
|
flushSlots(nonSystemIndex);
|
|
12668
13365
|
nonSystemIndex += 1;
|
|
12669
13366
|
if (isToolResultMessage(message)) {
|
|
12670
|
-
const
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
13367
|
+
const imageBlocks = [];
|
|
13368
|
+
while (index < conversation.length && isToolResultMessage(conversation[index])) {
|
|
13369
|
+
const current = conversation[index];
|
|
13370
|
+
if (index > 0) {
|
|
13371
|
+
flushSlots(nonSystemIndex);
|
|
13372
|
+
nonSystemIndex += 1;
|
|
13373
|
+
}
|
|
13374
|
+
const block = current.content[0];
|
|
13375
|
+
const callId = isRecord(block) && typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
13376
|
+
messages.push({
|
|
13377
|
+
role: "tool",
|
|
13378
|
+
tool_call_id: clampToolCallId(callId),
|
|
13379
|
+
content: toolResultText(current.content)
|
|
13380
|
+
});
|
|
13381
|
+
imageBlocks.push(...toolResultImageBlocks(current.content, images));
|
|
13382
|
+
index += 1;
|
|
13383
|
+
}
|
|
13384
|
+
index -= 1;
|
|
13385
|
+
if (imageBlocks.length > 0) messages.push({
|
|
13386
|
+
role: "user",
|
|
13387
|
+
content: imageBlocks
|
|
12676
13388
|
});
|
|
12677
13389
|
continue;
|
|
12678
13390
|
}
|
|
12679
13391
|
if (message.role === "assistant") {
|
|
12680
13392
|
const { content, toolCalls, reasoning } = openAIAssistantContent(message);
|
|
12681
|
-
if (content === "" && toolCalls.length === 0) continue;
|
|
12682
|
-
const entry = {
|
|
12683
|
-
|
|
12684
|
-
content
|
|
12685
|
-
};
|
|
13393
|
+
if (content === "" && toolCalls.length === 0 && reasoning === "") continue;
|
|
13394
|
+
const entry = { role: "assistant" };
|
|
13395
|
+
if (content !== "" || toolCalls.length === 0) entry.content = content;
|
|
12686
13396
|
if (toolCalls.length > 0) entry.tool_calls = toolCalls;
|
|
12687
13397
|
if (thinkingOn) entry.reasoning_content = reasoning;
|
|
12688
13398
|
messages.push(entry);
|
|
@@ -12732,11 +13442,12 @@ function buildOpenAIRequest(options, images = NO_RESOLVED_IMAGES, preserveThinki
|
|
|
12732
13442
|
/**
|
|
12733
13443
|
* Stable identifier for the conversation this request belongs to.
|
|
12734
13444
|
*
|
|
12735
|
-
*
|
|
12736
|
-
*
|
|
12737
|
-
*
|
|
13445
|
+
* Prioritizes the session identifier (GenerateOptions.sessionId) if present,
|
|
13446
|
+
* ensuring the cache key stays strictly constant across turns, context compactions,
|
|
13447
|
+
* and multimodal message changes. Falls back to hashing the first user message text.
|
|
12738
13448
|
*/
|
|
12739
13449
|
function promptCacheKey(options) {
|
|
13450
|
+
if (typeof options.sessionId === "string" && options.sessionId.trim() !== "") return `dsh-${options.sessionId.trim()}`;
|
|
12740
13451
|
for (const message of options.messages) {
|
|
12741
13452
|
if (message.role !== "user") continue;
|
|
12742
13453
|
const text = textOf(message.content);
|
|
@@ -12778,10 +13489,11 @@ function anthropicUserContent(message, images) {
|
|
|
12778
13489
|
});
|
|
12779
13490
|
} else if (block.type === "tool-result") {
|
|
12780
13491
|
const callId = typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
13492
|
+
const resultBlocks = toolResultBlocks(block.content, images);
|
|
12781
13493
|
blocks.push({
|
|
12782
13494
|
type: "tool_result",
|
|
12783
13495
|
tool_use_id: clampToolCallId(callId),
|
|
12784
|
-
content: toolResultText(block.content),
|
|
13496
|
+
content: resultBlocks ?? toolResultText(block.content),
|
|
12785
13497
|
...block.isError === true ? { is_error: true } : {}
|
|
12786
13498
|
});
|
|
12787
13499
|
}
|
|
@@ -13540,9 +14252,10 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
13540
14252
|
async listModels(provider) {
|
|
13541
14253
|
const prov = provider || "kimi-code";
|
|
13542
14254
|
const settings = await this.settings();
|
|
14255
|
+
if (settings.enabled === false) return [];
|
|
13543
14256
|
const catalog = await this.catalog();
|
|
13544
14257
|
const enabled = new Set(settings.enabledModelIds);
|
|
13545
|
-
return
|
|
14258
|
+
return catalog.filter((model) => enabled.has(model.id)).map((model) => ({
|
|
13546
14259
|
provider: prov,
|
|
13547
14260
|
id: model.id,
|
|
13548
14261
|
name: model.name ?? model.id,
|
|
@@ -13742,14 +14455,13 @@ function fallbackCatalog() {
|
|
|
13742
14455
|
* "everything currently offered" keeps a first run from hiding the whole
|
|
13743
14456
|
* catalog behind an unedited default. Any explicit edit is honoured exactly.
|
|
13744
14457
|
*/
|
|
13745
|
-
function resolveEnabledModelIds(stored, catalog) {
|
|
14458
|
+
function resolveEnabledModelIds(stored, catalog, enabled = true) {
|
|
14459
|
+
if (!enabled) return [];
|
|
13746
14460
|
const catalogIds = catalog.map((model) => model.id);
|
|
13747
14461
|
const shippedDefaults = new Set(FALLBACK_MODELS.map((model) => model.id));
|
|
13748
|
-
|
|
13749
|
-
if (stored.length === 0 || isUntouchedDefault) return catalogIds;
|
|
14462
|
+
if (stored.length > 0 && stored.length === shippedDefaults.size && stored.every((id) => shippedDefaults.has(id))) return catalogIds;
|
|
13750
14463
|
const known = new Set(catalogIds);
|
|
13751
|
-
|
|
13752
|
-
return kept.length === 0 ? catalogIds : kept;
|
|
14464
|
+
return stored.filter((id) => known.has(id));
|
|
13753
14465
|
}
|
|
13754
14466
|
function readOption(value, fallback) {
|
|
13755
14467
|
return typeof value === "function" ? value() : value ?? fallback;
|
|
@@ -13766,10 +14478,12 @@ async function getKimiCodeWebStatus(store, modelSettings, preferences, options =
|
|
|
13766
14478
|
accessToken: credentials?.accessToken
|
|
13767
14479
|
}).catch(() => []);
|
|
13768
14480
|
const catalog = live.length > 0 ? live : fallbackCatalog();
|
|
13769
|
-
const
|
|
14481
|
+
const enabled = settings.enabled !== false;
|
|
14482
|
+
const models = buildModelOptions(catalog, resolveEnabledModelIds(settings.enabledModelIds, catalog, enabled), settings.contextWindowOverrides);
|
|
13770
14483
|
const quota = getCachedQuota$2();
|
|
13771
14484
|
const account = quota?.account ?? (credentials === null ? null : accountFromCredentials(credentials));
|
|
13772
14485
|
return {
|
|
14486
|
+
enabled,
|
|
13773
14487
|
authenticated: credentials !== null,
|
|
13774
14488
|
hasCredentials: credentials !== null,
|
|
13775
14489
|
storagePath: store.path(),
|
|
@@ -13922,6 +14636,7 @@ function registerKimiCodeRoutes(ctx, store, modelSettings, preferences, options
|
|
|
13922
14636
|
});
|
|
13923
14637
|
const body = await readRequestJson(request);
|
|
13924
14638
|
const patch = {};
|
|
14639
|
+
if (typeof body.enabled === "boolean") patch.enabled = body.enabled;
|
|
13925
14640
|
if (Array.isArray(body.enabledModelIds)) patch.enabledModelIds = body.enabledModelIds.filter((id) => typeof id === "string");
|
|
13926
14641
|
if (typeof body.contextWindowOverrides === "object" && body.contextWindowOverrides !== null) {
|
|
13927
14642
|
const overrides = {};
|
|
@@ -15727,6 +16442,7 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
15727
16442
|
const store = createPlatformTokenStore();
|
|
15728
16443
|
const preferences = registerPreferenceStore(ctx.settings);
|
|
15729
16444
|
const antigravityStore = new FileCredentialStore$1();
|
|
16445
|
+
const antigravityAccountPool = new AccountPoolStore(void 0, void 0, antigravityStore);
|
|
15730
16446
|
const antigravityModelSettings = new FileModelSettingsStore$1();
|
|
15731
16447
|
const antigravityPreferences = registerAntigravityPreferenceStore(ctx.settings, antigravityModelSettings);
|
|
15732
16448
|
const commandCodeStore = new FileCredentialStore();
|
|
@@ -15769,9 +16485,25 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
15769
16485
|
const antigravityAdapter = new AntigravityAdapter(antigravityStore, antigravityModelSettings, antigravityPreferences, {
|
|
15770
16486
|
fetchFn: proxyFetch,
|
|
15771
16487
|
attachments: ctx.attachments
|
|
15772
|
-
});
|
|
15773
|
-
|
|
15774
|
-
|
|
16488
|
+
}, antigravityAccountPool);
|
|
16489
|
+
let antigravityRegistration;
|
|
16490
|
+
let antigravityConflict = null;
|
|
16491
|
+
const claimAntigravityRoute = () => {
|
|
16492
|
+
if (antigravityRegistration !== void 0) return;
|
|
16493
|
+
try {
|
|
16494
|
+
antigravityRegistration = ctx.llm.registerAdapter([PROVIDER_ID$2], antigravityAdapter);
|
|
16495
|
+
if (antigravityConflict !== null) ctx.logger.info(`[dsh-chatgpt-subscription] Antigravity route "${PROVIDER_ID$2}" is now served by this plugin`);
|
|
16496
|
+
antigravityConflict = null;
|
|
16497
|
+
} catch (error) {
|
|
16498
|
+
antigravityConflict = error instanceof Error ? error.message : String(error);
|
|
16499
|
+
ctx.logger.warn(`[dsh-chatgpt-subscription] provider route "${PROVIDER_ID$2}" is already owned by another adapter; Antigravity models keep being served by that one until its configuration is removed (${antigravityConflict})`);
|
|
16500
|
+
}
|
|
16501
|
+
};
|
|
16502
|
+
claimAntigravityRoute();
|
|
16503
|
+
const antigravityRouteWatch = typeof ctx.on === "function" ? ctx.on("llm/adapters-updated", () => {
|
|
16504
|
+
claimAntigravityRoute();
|
|
16505
|
+
}) : void 0;
|
|
16506
|
+
const disposeAntigravityRoutes = registerAntigravityRoutes(ctx, antigravityStore, antigravityModelSettings, antigravityPreferences, proxyFetch, antigravityAccountPool);
|
|
15775
16507
|
const disposeCommandCodeRoutes = registerCommandCodeRoutes(ctx, commandCodeStore, commandCodeModelSettings, commandCodePreferences, {
|
|
15776
16508
|
fetchFn: proxyFetch,
|
|
15777
16509
|
serving: () => commandCodeRegistration !== void 0,
|
|
@@ -15894,7 +16626,9 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
15894
16626
|
disposeAdapter();
|
|
15895
16627
|
disposeRoutes();
|
|
15896
16628
|
disposeAntigravityRoutes();
|
|
15897
|
-
|
|
16629
|
+
releaseHandle(antigravityRouteWatch);
|
|
16630
|
+
antigravityRegistration?.();
|
|
16631
|
+
antigravityRegistration = void 0;
|
|
15898
16632
|
disposeCommandCodeRoutes();
|
|
15899
16633
|
releaseHandle(commandCodeRouteWatch);
|
|
15900
16634
|
commandCodeRegistration?.();
|
|
@@ -15920,4 +16654,4 @@ function localWebServerBaseUrl(host, port) {
|
|
|
15920
16654
|
return `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${port}`;
|
|
15921
16655
|
}
|
|
15922
16656
|
//#endregion
|
|
15923
|
-
export { AntigravityAdapter, CodexChatGptAdapter, CommandCodeAdapter, FileCredentialStore as CommandCodeCredentialStore, FileModelSettingsStore as CommandCodeModelSettingsStore, Config, DEFAULT_SUBAGENT_INHERIT_TOOLS, FileCredentialStore$1 as FileCredentialStore, FileModelSettingsStore$1 as FileModelSettingsStore, KIMI_CODE_MODELS, KIMI_CODE_RETRY_POLICY_CONFIG, KimiCodeAdapter, FileCredentialStore$2 as KimiCodeCredentialStore, FileModelSettingsStore$2 as KimiCodeModelSettingsStore, LinuxFileTokenStore, MacKeychainTokenStore, OAuthService, ProxyManager, RELAY_PROBE_ENV, RELAY_PROBE_FILE_ENV, RELAY_PROBE_FILE_NAME, RELAY_PROBE_MAX_BYTES, RELAY_SOURCE_KINDS, RelayProbe, ResponsesClient, SUBAGENT_MODEL_SELECTION_NAMESPACE, SUBAGENT_POLICY_EVENT, SearchProviderSwitcher, UsageService, WindowsDpapiTokenStore, apply, auditChildRoutes, auditedRoutesOf, authorizedRoutesFor, beginWebLogin as beginKimiCodeLogin, beginWebLogin$1 as beginWebLogin, childRoutesOf, classifyKimiFailure, clearCachedQuota, clearCachedQuota$1 as clearCommandCodeQuota, clearCachedQuota$2 as clearKimiCodeQuota, credentialPath as commandCodeCredentialPath, modelSettingsPath as commandCodeModelSettingsPath, createCodexFetchProvider, createCodexImageTool, createCodexSearchProvider, createFileRelayProbeSink, createPlatformTokenStore, createSubagentAuthorization, credentialPath$1 as credentialPath, delegationDenialReason, delegationModeOf, detectSystemProxy, effectiveRouteOf, ensureAccessToken as ensureKimiCodeAccessToken, fetchAccountQuota, fetchAccountQuota$1 as fetchCommandCodeQuota, fetchAccountQuota$2 as fetchKimiCodeQuota, fetchUserInfo as fetchKimiCodeUserInfo, getCachedQuota, getWebLoginStatus as getCommandCodeLoginStatus, getCachedQuota$1 as getCommandCodeQuota, getCommandCodeWebStatus, getWebLoginStatus$1 as getKimiCodeLoginStatus, getCachedQuota$2 as getKimiCodeQuota, getKimiCodeWebStatus, inheritOverrideReason, inheritRouteDenialReason, inheritedRouteOf, inject, installRelayProbe, installSubagentModelAuthorization, credentialPath$2 as kimiCodeCredentialPath, kimiCodeModelDef, modelSettingsPath$1 as kimiCodeModelSettingsPath, loadProviderModels as loadCommandCodeModels, loadProviderModels$1 as loadKimiCodeModels, loginAndSave, mapCodexUsage, modelSettingsPath$2 as modelSettingsPath, normalizeDelegationToolNames, normalizeInheritToolNames, parseAllowedRoutes, parseCodexUsage, parseResponsesStream, policyRoutesOf, readChildDescriptor, refreshAntigravityToken, refreshAccessToken as refreshKimiCodeToken, registerCommandCodePreferenceStore, registerCommandCodeRoutes, registerKimiCodePreferenceStore, registerKimiCodeRoutes, relayProbeEnabled, relayProbeEnvFile, relayProbeEnvValue, relayProbeLogPath, requestDeviceAuthorization as requestKimiCodeDeviceAuthorization, resolveRegion as resolveKimiCodeRegion, saveApiKey as saveCommandCodeApiKey, beginWebLogin$2 as startCommandCodeLogin, subagentModelSelectionPreference, unauthorizedRouteReason, validateAuthorizationScope, validateDelegationToolNames, validateInheritToolNames, violationText };
|
|
16657
|
+
export { AccountPoolStore, AntigravityAdapter, CodexChatGptAdapter, CommandCodeAdapter, FileCredentialStore as CommandCodeCredentialStore, FileModelSettingsStore as CommandCodeModelSettingsStore, Config, DEFAULT_SUBAGENT_INHERIT_TOOLS, FileCredentialStore$1 as FileCredentialStore, FileModelSettingsStore$1 as FileModelSettingsStore, KIMI_CODE_MODELS, KIMI_CODE_RETRY_POLICY_CONFIG, KimiCodeAdapter, FileCredentialStore$2 as KimiCodeCredentialStore, FileModelSettingsStore$2 as KimiCodeModelSettingsStore, LinuxFileTokenStore, MacKeychainTokenStore, OAuthService, ProxyManager, RELAY_PROBE_ENV, RELAY_PROBE_FILE_ENV, RELAY_PROBE_FILE_NAME, RELAY_PROBE_MAX_BYTES, RELAY_SOURCE_KINDS, RelayProbe, ResponsesClient, SUBAGENT_MODEL_SELECTION_NAMESPACE, SUBAGENT_POLICY_EVENT, SearchProviderSwitcher, UsageService, WindowsDpapiTokenStore, apply, auditChildRoutes, auditedRoutesOf, authorizedRoutesFor, beginWebLogin as beginKimiCodeLogin, beginWebLogin$1 as beginWebLogin, childRoutesOf, classifyKimiFailure, clearCachedQuota, clearCachedQuota$1 as clearCommandCodeQuota, clearCachedQuota$2 as clearKimiCodeQuota, credentialPath as commandCodeCredentialPath, modelSettingsPath as commandCodeModelSettingsPath, createCodexFetchProvider, createCodexImageTool, createCodexSearchProvider, createFileRelayProbeSink, createPlatformTokenStore, createSubagentAuthorization, credentialPath$1 as credentialPath, delegationDenialReason, delegationModeOf, detectSystemProxy, effectiveRouteOf, ensureAccessToken as ensureKimiCodeAccessToken, fetchAccountQuota, fetchAccountQuota$1 as fetchCommandCodeQuota, fetchAccountQuota$2 as fetchKimiCodeQuota, fetchUserInfo as fetchKimiCodeUserInfo, getCachedQuota, getWebLoginStatus as getCommandCodeLoginStatus, getCachedQuota$1 as getCommandCodeQuota, getCommandCodeWebStatus, getWebLoginStatus$1 as getKimiCodeLoginStatus, getCachedQuota$2 as getKimiCodeQuota, getKimiCodeWebStatus, inheritOverrideReason, inheritRouteDenialReason, inheritedRouteOf, inject, installRelayProbe, installSubagentModelAuthorization, credentialPath$2 as kimiCodeCredentialPath, kimiCodeModelDef, modelSettingsPath$1 as kimiCodeModelSettingsPath, loadProviderModels as loadCommandCodeModels, loadProviderModels$1 as loadKimiCodeModels, loginAndSave, mapCodexUsage, modelSettingsPath$2 as modelSettingsPath, normalizeDelegationToolNames, normalizeInheritToolNames, parseAllowedRoutes, parseCodexUsage, parseResponsesStream, policyRoutesOf, readChildDescriptor, refreshAntigravityToken, refreshAccessToken as refreshKimiCodeToken, registerCommandCodePreferenceStore, registerCommandCodeRoutes, registerKimiCodePreferenceStore, registerKimiCodeRoutes, relayProbeEnabled, relayProbeEnvFile, relayProbeEnvValue, relayProbeLogPath, requestDeviceAuthorization as requestKimiCodeDeviceAuthorization, resolveRegion as resolveKimiCodeRegion, saveApiKey as saveCommandCodeApiKey, beginWebLogin$2 as startCommandCodeLogin, subagentModelSelectionPreference, unauthorizedRouteReason, validateAuthorizationScope, validateDelegationToolNames, validateInheritToolNames, violationText };
|