@eddyskywalker/dsh-chatgpt-subscription 0.2.1 → 0.2.3
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 +7 -2
- package/README.md +21 -8
- package/lib/client.js +28 -10
- package/lib/client.js.map +1 -1
- package/lib/index.js +408 -148
- package/lib/types/client/CodexSubscriptionSection.d.ts +1 -1
- package/lib/types/client/CodexSubscriptionSection.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +6 -6
- package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
- package/lib/types/host/antigravity/mapper.d.ts +9 -4
- package/lib/types/host/antigravity/mapper.d.ts.map +1 -1
- package/lib/types/host/antigravity/token-store.d.ts +8 -1
- package/lib/types/host/antigravity/token-store.d.ts.map +1 -1
- package/lib/types/host/credential-store-secret-service.d.ts +13 -0
- package/lib/types/host/credential-store-secret-service.d.ts.map +1 -0
- package/lib/types/host/preferences.d.ts.map +1 -1
- package/lib/types/host/responses-mapper.d.ts.map +1 -1
- package/lib/types/host/token-store-macos.d.ts +9 -5
- package/lib/types/host/token-store-macos.d.ts.map +1 -1
- package/lib/types/host/token-store-windows.d.ts +9 -5
- package/lib/types/host/token-store-windows.d.ts.map +1 -1
- package/lib/types/host/token-store.d.ts +6 -4
- package/lib/types/host/token-store.d.ts.map +1 -1
- package/lib/types/shared/contracts.d.ts +1 -0
- package/lib/types/shared/contracts.d.ts.map +1 -1
- package/lib/types/shared/model-catalog.d.ts +14 -3
- package/lib/types/shared/model-catalog.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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import * as LlmModule from "@deepseek-ai/dsh-llm";
|
|
3
|
-
import { HarnessError, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, attributionHeaders, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
3
|
+
import { CallId, HarnessError, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, attributionHeaders, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
4
4
|
import { WebError } from "@deepseek-ai/dsh-web";
|
|
5
5
|
import { createUserMessage } from "@deepseek-ai/dsh-llm/message";
|
|
6
6
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
@@ -14,6 +14,7 @@ import fs, { constants } from "node:fs";
|
|
|
14
14
|
import fsPromises, { chmod, lstat, mkdir, open, rename, stat, unlink } from "node:fs/promises";
|
|
15
15
|
import os, { homedir } from "node:os";
|
|
16
16
|
import path, { dirname, join } from "node:path";
|
|
17
|
+
import { isDeepStrictEqual } from "node:util";
|
|
17
18
|
import { URL as URL$1, URLSearchParams as URLSearchParams$1 } from "node:url";
|
|
18
19
|
//#region src/compat.ts
|
|
19
20
|
/**
|
|
@@ -49,6 +50,7 @@ const OAUTH_TOKEN_URL = `${CHATGPT_OAUTH_ISSUER}/oauth/token`;
|
|
|
49
50
|
//#endregion
|
|
50
51
|
//#region src/shared/model-catalog.ts
|
|
51
52
|
const GPT_56_MAX_CONTEXT_WINDOW = 1e6;
|
|
53
|
+
const GPT_6_ASTRA_MAX_CONTEXT_WINDOW = 872e3;
|
|
52
54
|
const CODEX_MODEL_CATALOG = [
|
|
53
55
|
{
|
|
54
56
|
id: "gpt-5.6-sol",
|
|
@@ -60,6 +62,15 @@ const CODEX_MODEL_CATALOG = [
|
|
|
60
62
|
supportsReasoningSummary: true,
|
|
61
63
|
fallbackModelId: "gpt-5.6-terra"
|
|
62
64
|
},
|
|
65
|
+
{
|
|
66
|
+
id: "gpt-6-astra",
|
|
67
|
+
name: "6 Astra",
|
|
68
|
+
contextWindow: 272e3,
|
|
69
|
+
inputModalities: ["text", "image"],
|
|
70
|
+
defaultReasoningEffort: "medium",
|
|
71
|
+
reasoningProfile: "gpt-6-astra",
|
|
72
|
+
supportsReasoningSummary: true
|
|
73
|
+
},
|
|
63
74
|
{
|
|
64
75
|
id: "gpt-5.6-terra",
|
|
65
76
|
name: "5.6 Terra",
|
|
@@ -120,11 +131,13 @@ const CODEX_MODEL_CATALOG = [
|
|
|
120
131
|
];
|
|
121
132
|
const DEFAULT_VISIBLE_CODEX_MODEL_IDS = [
|
|
122
133
|
"gpt-5.6-sol",
|
|
134
|
+
"gpt-6-astra",
|
|
123
135
|
"gpt-5.6-terra",
|
|
124
136
|
"gpt-5.6-luna"
|
|
125
137
|
];
|
|
126
138
|
const DEFAULT_CODEX_MODEL = CODEX_MODEL_CATALOG[0];
|
|
127
139
|
const CONFIGURABLE_CONTEXT_MODEL_IDS = [
|
|
140
|
+
"gpt-6-astra",
|
|
128
141
|
"gpt-5.6-sol",
|
|
129
142
|
"gpt-5.6-terra",
|
|
130
143
|
"gpt-5.6-luna"
|
|
@@ -137,8 +150,17 @@ const STANDARD_REASONING_EFFORTS = [
|
|
|
137
150
|
"xhigh"
|
|
138
151
|
];
|
|
139
152
|
const GPT_56_REASONING_EFFORTS = [...STANDARD_REASONING_EFFORTS, "max"];
|
|
153
|
+
const GPT_6_ASTRA_REASONING_EFFORTS = [
|
|
154
|
+
"low",
|
|
155
|
+
"medium",
|
|
156
|
+
"high",
|
|
157
|
+
"xhigh",
|
|
158
|
+
"max"
|
|
159
|
+
];
|
|
140
160
|
function reasoningEffortsForModel(model) {
|
|
141
|
-
|
|
161
|
+
const profile = resolveCodexCatalogEntry(model).reasoningProfile;
|
|
162
|
+
if (profile === "gpt-6-astra") return GPT_6_ASTRA_REASONING_EFFORTS;
|
|
163
|
+
return profile === "gpt-5.6" ? GPT_56_REASONING_EFFORTS : STANDARD_REASONING_EFFORTS;
|
|
142
164
|
}
|
|
143
165
|
function isCodexModelId(model) {
|
|
144
166
|
return typeof model === "string" && CODEX_MODEL_CATALOG.some((entry) => entry.id === model);
|
|
@@ -146,6 +168,9 @@ function isCodexModelId(model) {
|
|
|
146
168
|
function isConfigurableContextModelId(model) {
|
|
147
169
|
return typeof model === "string" && CONFIGURABLE_CONTEXT_MODEL_IDS.some((id) => id === model);
|
|
148
170
|
}
|
|
171
|
+
function contextWindowLimitForModel(model) {
|
|
172
|
+
return model === "gpt-6-astra" ? GPT_6_ASTRA_MAX_CONTEXT_WINDOW : GPT_56_MAX_CONTEXT_WINDOW;
|
|
173
|
+
}
|
|
149
174
|
function resolveCodexCatalogEntry(model) {
|
|
150
175
|
return CODEX_MODEL_CATALOG.find((entry) => entry.id === model) ?? DEFAULT_CODEX_MODEL;
|
|
151
176
|
}
|
|
@@ -1321,6 +1346,7 @@ const DEFAULT_PREFERENCES = {
|
|
|
1321
1346
|
visibleModelIds: [...DEFAULT_VISIBLE_CODEX_MODEL_IDS],
|
|
1322
1347
|
searchProvider: "dsh",
|
|
1323
1348
|
contextWindowOverrides: {
|
|
1349
|
+
"gpt-6-astra": 272e3,
|
|
1324
1350
|
"gpt-5.6-sol": 272e3,
|
|
1325
1351
|
"gpt-5.6-terra": 272e3,
|
|
1326
1352
|
"gpt-5.6-luna": 272e3
|
|
@@ -1366,6 +1392,7 @@ function registerPreferenceStore(settings) {
|
|
|
1366
1392
|
visibleModelIds: z.array(z.string()).default(DEFAULT_PREFERENCES.visibleModelIds),
|
|
1367
1393
|
searchProvider: z.union([z.const("dsh"), z.const(SEARCH_PROVIDER_CODEX)]).default(DEFAULT_PREFERENCES.searchProvider),
|
|
1368
1394
|
contextWindowOverrides: z.object({
|
|
1395
|
+
"gpt-6-astra": z.number().step(1).min(1).max(GPT_6_ASTRA_MAX_CONTEXT_WINDOW).default(DEFAULT_PREFERENCES.contextWindowOverrides["gpt-6-astra"]),
|
|
1369
1396
|
"gpt-5.6-sol": z.number().step(1).min(1).max(GPT_56_MAX_CONTEXT_WINDOW).default(DEFAULT_PREFERENCES.contextWindowOverrides["gpt-5.6-sol"]),
|
|
1370
1397
|
"gpt-5.6-terra": z.number().step(1).min(1).max(GPT_56_MAX_CONTEXT_WINDOW).default(DEFAULT_PREFERENCES.contextWindowOverrides["gpt-5.6-terra"]),
|
|
1371
1398
|
"gpt-5.6-luna": z.number().step(1).min(1).max(GPT_56_MAX_CONTEXT_WINDOW).default(DEFAULT_PREFERENCES.contextWindowOverrides["gpt-5.6-luna"])
|
|
@@ -1691,10 +1718,13 @@ async function buildResponsesPayload(options, attachments, localRawImages = {},
|
|
|
1691
1718
|
}
|
|
1692
1719
|
if (outputVerbosity !== null) payload.text = { verbosity: outputVerbosity };
|
|
1693
1720
|
if (fastMode) payload.service_tier = "priority";
|
|
1694
|
-
if (options.reasoningEffort !== void 0)
|
|
1695
|
-
effort: options.reasoningEffort
|
|
1696
|
-
|
|
1697
|
-
|
|
1721
|
+
if (options.reasoningEffort !== void 0) {
|
|
1722
|
+
const effort = options.model === "gpt-6-astra" && ["none", "minimal"].includes(options.reasoningEffort) ? "low" : options.reasoningEffort;
|
|
1723
|
+
payload.reasoning = codexModelSupportsReasoningSummary(options.model) ? {
|
|
1724
|
+
effort,
|
|
1725
|
+
summary: reasoningSummary ?? "auto"
|
|
1726
|
+
} : { effort };
|
|
1727
|
+
}
|
|
1698
1728
|
return payload;
|
|
1699
1729
|
}
|
|
1700
1730
|
function progressExplanationInstruction(tools) {
|
|
@@ -3083,8 +3113,8 @@ function readPreferencesUpdate(value, current) {
|
|
|
3083
3113
|
if (!isRecord$1(value.contextWindowOverrides)) throw new PreferenceError("contextWindowOverrides must be an object.");
|
|
3084
3114
|
const overrides = {};
|
|
3085
3115
|
for (const [model, contextWindow] of Object.entries(value.contextWindowOverrides)) {
|
|
3086
|
-
if (!isConfigurableContextModelId(model)) throw new PreferenceError("
|
|
3087
|
-
if (!Number.isSafeInteger(contextWindow) || contextWindow < 1 || contextWindow >
|
|
3116
|
+
if (!isConfigurableContextModelId(model)) throw new PreferenceError("This model does not support a configurable context window.");
|
|
3117
|
+
if (!Number.isSafeInteger(contextWindow) || contextWindow < 1 || contextWindow > contextWindowLimitForModel(model)) throw new PreferenceError(`contextWindowOverrides.${model} must be a positive integer no greater than the provider limit.`);
|
|
3088
3118
|
overrides[model] = contextWindow;
|
|
3089
3119
|
}
|
|
3090
3120
|
patch.contextWindowOverrides = overrides;
|
|
@@ -3162,16 +3192,18 @@ const DEFAULT_ACCOUNT = "oauth";
|
|
|
3162
3192
|
* `security` command-line tool. The payload is encrypted at rest by the
|
|
3163
3193
|
* Keychain, so this store reports itself as encrypted like Windows DPAPI.
|
|
3164
3194
|
*/
|
|
3165
|
-
var
|
|
3195
|
+
var MacKeychainCredentialStore = class {
|
|
3166
3196
|
service;
|
|
3167
3197
|
account;
|
|
3198
|
+
parse;
|
|
3168
3199
|
storage = {
|
|
3169
3200
|
kind: "macos-keychain",
|
|
3170
3201
|
encrypted: true
|
|
3171
3202
|
};
|
|
3172
|
-
constructor(service
|
|
3203
|
+
constructor(service, account, parse) {
|
|
3173
3204
|
this.service = service;
|
|
3174
3205
|
this.account = account;
|
|
3206
|
+
this.parse = parse;
|
|
3175
3207
|
if (process.platform !== "darwin") throw new Error("macOS Keychain storage requires macOS");
|
|
3176
3208
|
}
|
|
3177
3209
|
async load() {
|
|
@@ -3187,7 +3219,7 @@ var MacKeychainTokenStore = class {
|
|
|
3187
3219
|
if (result.code !== 0) throw new Error("Keychain credential read failed");
|
|
3188
3220
|
try {
|
|
3189
3221
|
const payload = result.stdout.replace(/\r?\n$/, "");
|
|
3190
|
-
return
|
|
3222
|
+
return this.parse(JSON.parse(payload));
|
|
3191
3223
|
} catch {
|
|
3192
3224
|
throw new Error("Keychain credential payload is invalid");
|
|
3193
3225
|
}
|
|
@@ -3215,6 +3247,11 @@ var MacKeychainTokenStore = class {
|
|
|
3215
3247
|
if (result.code !== 0 && result.code !== 44) throw new Error("Keychain credential deletion failed");
|
|
3216
3248
|
}
|
|
3217
3249
|
};
|
|
3250
|
+
var MacKeychainTokenStore = class extends MacKeychainCredentialStore {
|
|
3251
|
+
constructor(service = DEFAULT_SERVICE, account = DEFAULT_ACCOUNT) {
|
|
3252
|
+
super(service, account, parseStoredCredentials);
|
|
3253
|
+
}
|
|
3254
|
+
};
|
|
3218
3255
|
function runSecurity(args) {
|
|
3219
3256
|
return new Promise((resolve, reject) => {
|
|
3220
3257
|
const child = spawn("security", args, {
|
|
@@ -3359,8 +3396,16 @@ $cipher = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, [Securit
|
|
|
3359
3396
|
$directory = [IO.Path]::GetDirectoryName($path)
|
|
3360
3397
|
[IO.Directory]::CreateDirectory($directory) | Out-Null
|
|
3361
3398
|
$temporary = $path + '.tmp-' + [Guid]::NewGuid().ToString('N')
|
|
3362
|
-
|
|
3363
|
-
|
|
3399
|
+
try {
|
|
3400
|
+
[IO.File]::WriteAllBytes($temporary, $cipher)
|
|
3401
|
+
if ([IO.File]::Exists($path)) {
|
|
3402
|
+
[IO.File]::Replace($temporary, $path, [System.Management.Automation.Language.NullString]::Value)
|
|
3403
|
+
} else {
|
|
3404
|
+
[IO.File]::Move($temporary, $path)
|
|
3405
|
+
}
|
|
3406
|
+
} finally {
|
|
3407
|
+
if ([IO.File]::Exists($temporary)) { [IO.File]::Delete($temporary) }
|
|
3408
|
+
}
|
|
3364
3409
|
`;
|
|
3365
3410
|
const UNPROTECT_SCRIPT = String.raw`
|
|
3366
3411
|
$ErrorActionPreference = 'Stop'
|
|
@@ -3379,14 +3424,16 @@ if ([IO.File]::Exists($path)) { [IO.File]::Delete($path) }
|
|
|
3379
3424
|
function defaultDpapiCredentialPath() {
|
|
3380
3425
|
return join(process.env.DSH_HOME?.trim() || join(homedir(), ".dsh"), "storages", "dsh-chatgpt-subscription", "oauth.dpapi");
|
|
3381
3426
|
}
|
|
3382
|
-
var
|
|
3427
|
+
var WindowsDpapiCredentialStore = class {
|
|
3383
3428
|
path;
|
|
3429
|
+
parse;
|
|
3384
3430
|
storage = {
|
|
3385
3431
|
kind: "windows-dpapi",
|
|
3386
3432
|
encrypted: true
|
|
3387
3433
|
};
|
|
3388
|
-
constructor(path
|
|
3434
|
+
constructor(path, parse) {
|
|
3389
3435
|
this.path = path;
|
|
3436
|
+
this.parse = parse;
|
|
3390
3437
|
if (process.platform !== "win32") throw new Error("Windows DPAPI storage requires Windows");
|
|
3391
3438
|
if (dirname(path) === path) throw new Error("invalid DPAPI credential path");
|
|
3392
3439
|
}
|
|
@@ -3395,7 +3442,7 @@ var WindowsDpapiTokenStore = class {
|
|
|
3395
3442
|
if (result.code === 3) return null;
|
|
3396
3443
|
if (result.code !== 0) throw new Error("DPAPI credential read failed");
|
|
3397
3444
|
try {
|
|
3398
|
-
return
|
|
3445
|
+
return this.parse(JSON.parse(result.stdout));
|
|
3399
3446
|
} catch {
|
|
3400
3447
|
throw new Error("DPAPI credential payload is invalid");
|
|
3401
3448
|
}
|
|
@@ -3407,6 +3454,11 @@ var WindowsDpapiTokenStore = class {
|
|
|
3407
3454
|
if ((await runPowerShell(CLEAR_SCRIPT, this.path, "")).code !== 0) throw new Error("DPAPI credential deletion failed");
|
|
3408
3455
|
}
|
|
3409
3456
|
};
|
|
3457
|
+
var WindowsDpapiTokenStore = class extends WindowsDpapiCredentialStore {
|
|
3458
|
+
constructor(path = defaultDpapiCredentialPath()) {
|
|
3459
|
+
super(path, parseStoredCredentials);
|
|
3460
|
+
}
|
|
3461
|
+
};
|
|
3410
3462
|
function runPowerShell(script, path, stdin) {
|
|
3411
3463
|
return new Promise((resolve, reject) => {
|
|
3412
3464
|
const child = spawn("powershell.exe", [
|
|
@@ -3827,6 +3879,96 @@ const MODELS = [
|
|
|
3827
3879
|
}
|
|
3828
3880
|
];
|
|
3829
3881
|
//#endregion
|
|
3882
|
+
//#region src/host/credential-store-secret-service.ts
|
|
3883
|
+
const UNAVAILABLE = "Linux encrypted credential storage requires secret-tool (libsecret) and an unlocked Secret Service keyring.";
|
|
3884
|
+
/** Secrets travel over stdin/stdout; command arguments contain only lookup attributes. */
|
|
3885
|
+
var SecretServiceCredentialStore = class {
|
|
3886
|
+
service;
|
|
3887
|
+
account;
|
|
3888
|
+
parse;
|
|
3889
|
+
constructor(service, account, parse) {
|
|
3890
|
+
this.service = service;
|
|
3891
|
+
this.account = account;
|
|
3892
|
+
this.parse = parse;
|
|
3893
|
+
}
|
|
3894
|
+
attributes() {
|
|
3895
|
+
return [
|
|
3896
|
+
"service",
|
|
3897
|
+
this.service,
|
|
3898
|
+
"account",
|
|
3899
|
+
this.account
|
|
3900
|
+
];
|
|
3901
|
+
}
|
|
3902
|
+
async load() {
|
|
3903
|
+
const result = await runSecretTool(["lookup", ...this.attributes()]);
|
|
3904
|
+
if (result.code === 1 && !result.hasStderr && result.stdout === "") return null;
|
|
3905
|
+
if (result.code !== 0) throw new Error(UNAVAILABLE);
|
|
3906
|
+
try {
|
|
3907
|
+
return this.parse(JSON.parse(result.stdout));
|
|
3908
|
+
} catch {
|
|
3909
|
+
throw new Error("Secret Service credential payload is invalid");
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
async save(value) {
|
|
3913
|
+
const payload = JSON.stringify(value);
|
|
3914
|
+
if (Buffer.byteLength(payload, "utf8") >= 8192) throw new Error("Secret Service credential payload is too large");
|
|
3915
|
+
if ((await runSecretTool([
|
|
3916
|
+
"store",
|
|
3917
|
+
"--label=DSH Antigravity OAuth",
|
|
3918
|
+
...this.attributes()
|
|
3919
|
+
], payload)).code !== 0) throw new Error(UNAVAILABLE);
|
|
3920
|
+
}
|
|
3921
|
+
async clear() {
|
|
3922
|
+
const result = await runSecretTool(["clear", ...this.attributes()]);
|
|
3923
|
+
if (result.code !== 0 && !(result.code === 1 && !result.hasStderr)) throw new Error(UNAVAILABLE);
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
function runSecretTool(args, stdin = "") {
|
|
3927
|
+
return new Promise((resolve, reject) => {
|
|
3928
|
+
const child = spawn("secret-tool", args, {
|
|
3929
|
+
stdio: [
|
|
3930
|
+
"pipe",
|
|
3931
|
+
"pipe",
|
|
3932
|
+
"pipe"
|
|
3933
|
+
],
|
|
3934
|
+
windowsHide: true
|
|
3935
|
+
});
|
|
3936
|
+
let stdout = "";
|
|
3937
|
+
let stderrLength = 0;
|
|
3938
|
+
let settled = false;
|
|
3939
|
+
const fail = () => {
|
|
3940
|
+
if (settled) return;
|
|
3941
|
+
settled = true;
|
|
3942
|
+
clearTimeout(timer);
|
|
3943
|
+
child.kill();
|
|
3944
|
+
reject(/* @__PURE__ */ new Error(UNAVAILABLE));
|
|
3945
|
+
};
|
|
3946
|
+
const timer = setTimeout(fail, 1e4);
|
|
3947
|
+
child.stdout.setEncoding("utf8");
|
|
3948
|
+
child.stdout.on("data", (chunk) => {
|
|
3949
|
+
stdout += chunk;
|
|
3950
|
+
if (stdout.length > 1 << 20) fail();
|
|
3951
|
+
});
|
|
3952
|
+
child.stderr.on("data", (chunk) => {
|
|
3953
|
+
stderrLength += chunk.length;
|
|
3954
|
+
if (stderrLength > 1 << 20) fail();
|
|
3955
|
+
});
|
|
3956
|
+
child.once("error", fail);
|
|
3957
|
+
child.stdin.once("error", fail);
|
|
3958
|
+
child.once("close", (code) => {
|
|
3959
|
+
if (settled) return;
|
|
3960
|
+
settled = true;
|
|
3961
|
+
clearTimeout(timer);
|
|
3962
|
+
resolve({
|
|
3963
|
+
code: code ?? 1,
|
|
3964
|
+
stdout,
|
|
3965
|
+
hasStderr: stderrLength > 0
|
|
3966
|
+
});
|
|
3967
|
+
});
|
|
3968
|
+
child.stdin.end(stdin);
|
|
3969
|
+
});
|
|
3970
|
+
}
|
|
3971
|
+
//#endregion
|
|
3830
3972
|
//#region src/host/antigravity/token-store.ts
|
|
3831
3973
|
const ANTIGRAVITY_PREFERENCES_NAMESPACE = "dsh-antigravity";
|
|
3832
3974
|
function registerAntigravityPreferenceStore(settings, fallbackStore = new FileModelSettingsStore()) {
|
|
@@ -3888,36 +4030,110 @@ function credentialPath() {
|
|
|
3888
4030
|
function modelSettingsPath() {
|
|
3889
4031
|
return path.join(dshHomeDir(), "storages", "antigravity-models.json");
|
|
3890
4032
|
}
|
|
4033
|
+
function parseAntigravityCredentials(value) {
|
|
4034
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("Antigravity credential payload is invalid");
|
|
4035
|
+
const record = value;
|
|
4036
|
+
const credentials = {};
|
|
4037
|
+
for (const key of [
|
|
4038
|
+
"access",
|
|
4039
|
+
"access_token",
|
|
4040
|
+
"refresh",
|
|
4041
|
+
"refresh_token",
|
|
4042
|
+
"email",
|
|
4043
|
+
"projectId"
|
|
4044
|
+
]) {
|
|
4045
|
+
if (record[key] === void 0) continue;
|
|
4046
|
+
if (typeof record[key] !== "string") throw new Error("Antigravity credential payload is invalid");
|
|
4047
|
+
credentials[key] = record[key];
|
|
4048
|
+
}
|
|
4049
|
+
for (const key of ["expires", "expires_at"]) {
|
|
4050
|
+
if (record[key] === void 0) continue;
|
|
4051
|
+
if (typeof record[key] !== "number" || !Number.isFinite(record[key])) throw new Error("Antigravity credential expiry is invalid");
|
|
4052
|
+
credentials[key] = record[key];
|
|
4053
|
+
}
|
|
4054
|
+
if (!(credentials.access || credentials.access_token || credentials.refresh || credentials.refresh_token)) throw new Error("Antigravity credential tokens are missing");
|
|
4055
|
+
return credentials;
|
|
4056
|
+
}
|
|
4057
|
+
function credentialAccount(filePath) {
|
|
4058
|
+
return createHash("sha256").update(path.resolve(filePath)).digest("hex");
|
|
4059
|
+
}
|
|
4060
|
+
function createCredentialBackend(filePath) {
|
|
4061
|
+
if (process.platform === "win32") return new WindowsDpapiCredentialStore(`${filePath}.dpapi`, parseAntigravityCredentials);
|
|
4062
|
+
if (process.platform === "darwin") return new MacKeychainCredentialStore("dsh-antigravity", credentialAccount(filePath), parseAntigravityCredentials);
|
|
4063
|
+
if (process.platform === "linux") return new SecretServiceCredentialStore("dsh-antigravity", credentialAccount(filePath), parseAntigravityCredentials);
|
|
4064
|
+
throw new Error("Antigravity encrypted credential storage requires Windows, macOS, or Linux.");
|
|
4065
|
+
}
|
|
4066
|
+
const credentialOperations = /* @__PURE__ */ new Map();
|
|
4067
|
+
/** Keeps the public API; filePath identifies the legacy JSON that is migrated on first use. */
|
|
3891
4068
|
var FileCredentialStore = class {
|
|
3892
4069
|
filePath;
|
|
3893
|
-
|
|
4070
|
+
backend;
|
|
4071
|
+
constructor(filePath = credentialPath(), backend = createCredentialBackend(filePath)) {
|
|
3894
4072
|
this.filePath = filePath;
|
|
4073
|
+
this.backend = backend;
|
|
3895
4074
|
}
|
|
3896
4075
|
path() {
|
|
3897
|
-
return this.filePath
|
|
4076
|
+
if (process.platform === "win32") return `${this.filePath}.dpapi`;
|
|
4077
|
+
return `${process.platform === "darwin" ? "Keychain" : "Secret Service"}: dsh-antigravity/${credentialAccount(this.filePath)}`;
|
|
4078
|
+
}
|
|
4079
|
+
serialize(operation) {
|
|
4080
|
+
const key = path.resolve(this.filePath);
|
|
4081
|
+
const result = (credentialOperations.get(key) || Promise.resolve()).then(operation);
|
|
4082
|
+
const settled = result.then(() => void 0, () => void 0);
|
|
4083
|
+
credentialOperations.set(key, settled);
|
|
4084
|
+
settled.then(() => {
|
|
4085
|
+
if (credentialOperations.get(key) === settled) credentialOperations.delete(key);
|
|
4086
|
+
});
|
|
4087
|
+
return result;
|
|
3898
4088
|
}
|
|
3899
|
-
async
|
|
4089
|
+
async removeLegacy() {
|
|
3900
4090
|
try {
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
if (
|
|
3904
|
-
return null;
|
|
3905
|
-
} catch {
|
|
3906
|
-
return null;
|
|
4091
|
+
await fsPromises.unlink(this.filePath);
|
|
4092
|
+
} catch (error) {
|
|
4093
|
+
if (error.code !== "ENOENT") throw new Error("Antigravity legacy credential removal failed");
|
|
3907
4094
|
}
|
|
3908
4095
|
}
|
|
3909
|
-
async
|
|
3910
|
-
await
|
|
3911
|
-
|
|
3912
|
-
await
|
|
3913
|
-
|
|
4096
|
+
async saveVerified(credentials) {
|
|
4097
|
+
await this.backend.save(credentials);
|
|
4098
|
+
if (!isDeepStrictEqual(await this.backend.load(), credentials)) throw new Error("Antigravity encrypted credential verification failed");
|
|
4099
|
+
await this.removeLegacy();
|
|
4100
|
+
}
|
|
4101
|
+
read() {
|
|
4102
|
+
return this.serialize(async () => {
|
|
4103
|
+
const current = await this.backend.load();
|
|
4104
|
+
if (current !== null) {
|
|
4105
|
+
await this.removeLegacy();
|
|
4106
|
+
return current;
|
|
4107
|
+
}
|
|
4108
|
+
let legacy;
|
|
4109
|
+
try {
|
|
4110
|
+
const stats = await fsPromises.lstat(this.filePath);
|
|
4111
|
+
if (!stats.isFile() || stats.isSymbolicLink()) throw new Error("Invalid credential file");
|
|
4112
|
+
if (process.getuid && stats.uid !== process.getuid()) throw new Error("Invalid credential owner");
|
|
4113
|
+
if (process.platform !== "win32") await fsPromises.chmod(this.filePath, 384);
|
|
4114
|
+
legacy = await fsPromises.readFile(this.filePath, "utf8");
|
|
4115
|
+
} catch (error) {
|
|
4116
|
+
if (error.code === "ENOENT") return null;
|
|
4117
|
+
throw new Error("Antigravity legacy credential read failed");
|
|
4118
|
+
}
|
|
4119
|
+
let credentials;
|
|
4120
|
+
try {
|
|
4121
|
+
credentials = parseAntigravityCredentials(JSON.parse(legacy));
|
|
4122
|
+
} catch {
|
|
4123
|
+
throw new Error("Antigravity legacy credential payload is invalid");
|
|
4124
|
+
}
|
|
4125
|
+
await this.saveVerified(credentials);
|
|
4126
|
+
return credentials;
|
|
4127
|
+
});
|
|
3914
4128
|
}
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
4129
|
+
write(credentials) {
|
|
4130
|
+
return this.serialize(() => this.saveVerified(parseAntigravityCredentials(credentials)));
|
|
4131
|
+
}
|
|
4132
|
+
delete() {
|
|
4133
|
+
return this.serialize(async () => {
|
|
4134
|
+
await this.removeLegacy();
|
|
4135
|
+
await this.backend.clear();
|
|
4136
|
+
});
|
|
3921
4137
|
}
|
|
3922
4138
|
};
|
|
3923
4139
|
var FileModelSettingsStore = class {
|
|
@@ -4549,15 +4765,27 @@ function toolResultText(blocks) {
|
|
|
4549
4765
|
}
|
|
4550
4766
|
function replayBlockFor(message, index) {
|
|
4551
4767
|
const source = message.source;
|
|
4552
|
-
if (!source || source.kind !== "model") return void 0;
|
|
4768
|
+
if (!source || source.kind !== "model" || source.provider !== "antigravity") return void 0;
|
|
4553
4769
|
const state = source.replayState;
|
|
4554
4770
|
if (!isRecord(state)) return void 0;
|
|
4771
|
+
if (Array.isArray(state.blocks)) return state.blocks[index];
|
|
4555
4772
|
const resp = isRecord(state.response) ? state.response : void 0;
|
|
4556
4773
|
if (resp) {
|
|
4557
4774
|
if (Array.isArray(resp.outputItems)) return resp.outputItems[index];
|
|
4558
4775
|
if (Array.isArray(resp.blocks)) return resp.blocks[index];
|
|
4559
4776
|
}
|
|
4560
|
-
|
|
4777
|
+
}
|
|
4778
|
+
function thoughtSignature(part) {
|
|
4779
|
+
return asString(part?.thoughtSignature) || asString(part?.thought_signature) || asString(part?.thinkingSignature) || asString(part?.textSignature);
|
|
4780
|
+
}
|
|
4781
|
+
function replayPart(part) {
|
|
4782
|
+
const copy = { ...part };
|
|
4783
|
+
const signature = thoughtSignature(part);
|
|
4784
|
+
delete copy.thought_signature;
|
|
4785
|
+
delete copy.thinkingSignature;
|
|
4786
|
+
if (signature) copy.thoughtSignature = signature;
|
|
4787
|
+
if (typeof copy.text === "string") copy.text = sanitizeText(copy.text);
|
|
4788
|
+
return copy;
|
|
4561
4789
|
}
|
|
4562
4790
|
function assistantParts(message, model, runtimeModel, toolNames) {
|
|
4563
4791
|
const parts = [];
|
|
@@ -4566,30 +4794,39 @@ function assistantParts(message, model, runtimeModel, toolNames) {
|
|
|
4566
4794
|
const block = message.content[index];
|
|
4567
4795
|
if (!isRecord(block)) continue;
|
|
4568
4796
|
const replay = replayBlockFor(message, index);
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4797
|
+
const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord) : [];
|
|
4798
|
+
if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString(part.text) || "").join("") === sanitizeText(String(block.text || ""))) {
|
|
4799
|
+
parts.push(...originalParts.map(replayPart));
|
|
4800
|
+
continue;
|
|
4801
|
+
}
|
|
4802
|
+
if (block.type === "text" && String(block.text || "").trim()) {
|
|
4803
|
+
const sig = thoughtSignature(replay) || thoughtSignature(block);
|
|
4804
|
+
parts.push({
|
|
4805
|
+
text: sanitizeText(String(block.text)),
|
|
4806
|
+
...sig ? { thoughtSignature: sig } : {}
|
|
4807
|
+
});
|
|
4808
|
+
} else if (block.type === "reasoning" && String(block.text || "").trim()) {
|
|
4809
|
+
const sig = thoughtSignature(replay) || thoughtSignature(block);
|
|
4810
|
+
parts.push({
|
|
4573
4811
|
thought: true,
|
|
4574
4812
|
text: sanitizeText(String(block.text)),
|
|
4575
|
-
|
|
4576
|
-
thoughtSignature: sig
|
|
4813
|
+
...sig ? { thoughtSignature: sig } : {}
|
|
4577
4814
|
});
|
|
4578
|
-
else parts.push({ text: sanitizeText(String(block.text)) });
|
|
4579
4815
|
} else if (block.type === "tool-call") {
|
|
4580
4816
|
const toolId = String(block.id || "");
|
|
4581
4817
|
const toolName = String(block.name || "");
|
|
4582
4818
|
toolNames.set(toolId, toolName);
|
|
4583
|
-
const
|
|
4819
|
+
const originalCall = originalParts.find((part) => isRecord(part.functionCall));
|
|
4820
|
+
const effectiveSignature = thoughtSignature(originalCall) || thoughtSignature(replay) || thoughtSignature(block) || (originalCall ? void 0 : "skip_thought_signature_validator");
|
|
4584
4821
|
parts.push({
|
|
4585
4822
|
functionCall: {
|
|
4586
4823
|
name: toolName,
|
|
4587
4824
|
args: parseArguments(block.arguments),
|
|
4588
4825
|
...toolCallIdNeeded(model.id, runtimeModel) ? { id: sanitizeToolCallId(toolId, toolName) } : {}
|
|
4589
4826
|
},
|
|
4590
|
-
|
|
4591
|
-
thoughtSignature: sig
|
|
4827
|
+
...effectiveSignature ? { thoughtSignature: effectiveSignature } : {}
|
|
4592
4828
|
});
|
|
4829
|
+
parts.push(...originalParts.filter((part) => !part.functionCall).map(replayPart));
|
|
4593
4830
|
}
|
|
4594
4831
|
}
|
|
4595
4832
|
return parts;
|
|
@@ -4693,6 +4930,8 @@ function buildRequest(options, model, projectId, runtimeModel, effort) {
|
|
|
4693
4930
|
const isTiered = runtimeModel === "gemini-3.8-flash-tiered" || runtimeModel === "gemini-3.7-flash-tiered";
|
|
4694
4931
|
const isSuffixed = /^gemini-.+(?:-(?:extra-)?low|-medium|-high|-xhigh)$/.test(runtimeModel);
|
|
4695
4932
|
const isGemini25 = runtimeModel.startsWith("gemini-2.5-") || model.id.startsWith("gemini-2.5-");
|
|
4933
|
+
const isGemini3 = /^gemini-3[.-]/.test(runtimeModel) && !runtimeModel.includes("image");
|
|
4934
|
+
const isGeminiAgent = runtimeModel === "gemini-pro-agent" || runtimeModel === "gemini-3-flash-agent";
|
|
4696
4935
|
if (isTiered) {
|
|
4697
4936
|
const selected = (effort || "medium").toLowerCase();
|
|
4698
4937
|
const isOff = selected === "off" || selected === "none";
|
|
@@ -4700,7 +4939,7 @@ function buildRequest(options, model, projectId, runtimeModel, effort) {
|
|
|
4700
4939
|
thinkingLevel: isOff ? "MINIMAL" : selected === "high" || selected === "xhigh" ? "HIGH" : selected === "medium" ? "MEDIUM" : "LOW",
|
|
4701
4940
|
includeThoughts: !isOff
|
|
4702
4941
|
};
|
|
4703
|
-
} else if (isSuffixed) {
|
|
4942
|
+
} else if (isSuffixed || isGemini3 || isGeminiAgent) {
|
|
4704
4943
|
const selected = (effort || "medium").toLowerCase();
|
|
4705
4944
|
generationConfig.thinkingConfig = { includeThoughts: !(selected === "off" || selected === "none") };
|
|
4706
4945
|
} else if (isGemini25) {
|
|
@@ -4736,58 +4975,90 @@ function createStreamState() {
|
|
|
4736
4975
|
replayBlocks: [],
|
|
4737
4976
|
currentBlock: null,
|
|
4738
4977
|
hasContent: false,
|
|
4739
|
-
hasToolCall: false
|
|
4978
|
+
hasToolCall: false,
|
|
4979
|
+
usageMetadata: null,
|
|
4980
|
+
done: false,
|
|
4981
|
+
finished: false
|
|
4982
|
+
};
|
|
4983
|
+
}
|
|
4984
|
+
function closeCurrentBlock(state) {
|
|
4985
|
+
if (!state.currentBlock) return [];
|
|
4986
|
+
const { index, type, text } = state.currentBlock;
|
|
4987
|
+
const block = {
|
|
4988
|
+
type,
|
|
4989
|
+
text
|
|
4990
|
+
};
|
|
4991
|
+
state.blocks[index] = block;
|
|
4992
|
+
state.currentBlock = null;
|
|
4993
|
+
return [{
|
|
4994
|
+
type: "block-end",
|
|
4995
|
+
index,
|
|
4996
|
+
block
|
|
4997
|
+
}];
|
|
4998
|
+
}
|
|
4999
|
+
const USAGE_FIELDS = [
|
|
5000
|
+
"promptTokenCount",
|
|
5001
|
+
"cachedContentTokenCount",
|
|
5002
|
+
"candidatesTokenCount",
|
|
5003
|
+
"thoughtsTokenCount",
|
|
5004
|
+
"totalTokenCount"
|
|
5005
|
+
];
|
|
5006
|
+
function collectUsage(value, state) {
|
|
5007
|
+
if (!isRecord(value)) return;
|
|
5008
|
+
for (const key of USAGE_FIELDS) {
|
|
5009
|
+
const count = value[key];
|
|
5010
|
+
if (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) continue;
|
|
5011
|
+
state.usageMetadata ??= {};
|
|
5012
|
+
state.usageMetadata[key] = count;
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
function tokenUsage(u) {
|
|
5016
|
+
const prompt = u.promptTokenCount ?? 0;
|
|
5017
|
+
const cache = Math.min(prompt, u.cachedContentTokenCount ?? 0);
|
|
5018
|
+
const thoughts = u.thoughtsTokenCount ?? 0;
|
|
5019
|
+
const explicitOutput = (u.candidatesTokenCount ?? 0) + thoughts;
|
|
5020
|
+
const totalOutput = u.totalTokenCount !== void 0 && u.promptTokenCount !== void 0 ? Math.max(0, u.totalTokenCount - prompt) : 0;
|
|
5021
|
+
return {
|
|
5022
|
+
inputTokens: prompt - cache,
|
|
5023
|
+
outputTokens: Math.max(explicitOutput, totalOutput),
|
|
5024
|
+
...cache > 0 ? { cacheReadTokens: cache } : {},
|
|
5025
|
+
...u.thoughtsTokenCount !== void 0 ? { reasoningTokens: thoughts } : {}
|
|
4740
5026
|
};
|
|
4741
5027
|
}
|
|
4742
5028
|
function processStreamLine(line, state) {
|
|
4743
|
-
if (!line.startsWith("data:")) return [];
|
|
5029
|
+
if (state.finished || !line.startsWith("data:")) return [];
|
|
4744
5030
|
const json = line.slice(5).trim();
|
|
4745
|
-
if (
|
|
5031
|
+
if (json === "[DONE]") {
|
|
5032
|
+
state.done = true;
|
|
5033
|
+
return closeStream(state);
|
|
5034
|
+
}
|
|
5035
|
+
if (!json) return [];
|
|
4746
5036
|
const chunk = safeJsonParse(json);
|
|
4747
5037
|
if (!isRecord(chunk)) return [];
|
|
4748
5038
|
const responseData = isRecord(chunk.response) ? chunk.response : chunk;
|
|
4749
|
-
const
|
|
5039
|
+
const candidates = Array.isArray(responseData.candidates) ? responseData.candidates : [];
|
|
5040
|
+
const candidate = isRecord(candidates[0]) ? candidates[0] : void 0;
|
|
4750
5041
|
const content = isRecord(candidate?.content) ? candidate.content : void 0;
|
|
4751
5042
|
const parts = Array.isArray(content?.parts) ? content.parts : [];
|
|
4752
5043
|
const out = [];
|
|
4753
|
-
const closeCurrentBlock = () => {
|
|
4754
|
-
if (!state.currentBlock) return;
|
|
4755
|
-
const index = state.blocks.length - 1;
|
|
4756
|
-
if (state.currentBlock.type === "text") out.push({
|
|
4757
|
-
type: "block-end",
|
|
4758
|
-
index,
|
|
4759
|
-
block: {
|
|
4760
|
-
type: "text",
|
|
4761
|
-
text: state.currentBlock.text
|
|
4762
|
-
}
|
|
4763
|
-
});
|
|
4764
|
-
else out.push({
|
|
4765
|
-
type: "block-end",
|
|
4766
|
-
index,
|
|
4767
|
-
block: {
|
|
4768
|
-
type: "reasoning",
|
|
4769
|
-
text: state.currentBlock.text
|
|
4770
|
-
}
|
|
4771
|
-
});
|
|
4772
|
-
state.currentBlock = null;
|
|
4773
|
-
};
|
|
4774
5044
|
for (const part of parts) {
|
|
4775
5045
|
if (!isRecord(part)) continue;
|
|
4776
|
-
if (part.text
|
|
5046
|
+
if (typeof part.text === "string" && part.text !== "") {
|
|
4777
5047
|
const isThinking = Boolean(part.thought);
|
|
4778
5048
|
const blockType = isThinking ? "reasoning" : "text";
|
|
4779
5049
|
if (!state.currentBlock || state.currentBlock.type !== blockType) {
|
|
4780
|
-
closeCurrentBlock();
|
|
5050
|
+
out.push(...closeCurrentBlock(state));
|
|
5051
|
+
const index = state.blocks.length;
|
|
4781
5052
|
state.currentBlock = {
|
|
5053
|
+
index,
|
|
4782
5054
|
type: blockType,
|
|
4783
5055
|
text: ""
|
|
4784
5056
|
};
|
|
4785
|
-
const index = state.blocks.length;
|
|
4786
5057
|
state.blocks.push({
|
|
4787
5058
|
type: blockType,
|
|
4788
5059
|
text: ""
|
|
4789
5060
|
});
|
|
4790
|
-
state.replayBlocks.push({
|
|
5061
|
+
state.replayBlocks.push({ parts: [] });
|
|
4791
5062
|
out.push({
|
|
4792
5063
|
type: "block-start",
|
|
4793
5064
|
index,
|
|
@@ -4797,45 +5068,55 @@ function processStreamLine(line, state) {
|
|
|
4797
5068
|
const delta = sanitizeText(part.text);
|
|
4798
5069
|
state.currentBlock.text += delta;
|
|
4799
5070
|
state.hasContent = true;
|
|
4800
|
-
|
|
4801
|
-
state.currentBlock.thinkingSignature = part.thoughtSignature;
|
|
4802
|
-
state.replayBlocks[state.blocks.length - 1].thinkingSignature = part.thoughtSignature;
|
|
4803
|
-
} else if (!isThinking && part.thoughtSignature) {
|
|
4804
|
-
state.currentBlock.textSignature = part.thoughtSignature;
|
|
4805
|
-
state.replayBlocks[state.blocks.length - 1].textSignature = part.thoughtSignature;
|
|
4806
|
-
}
|
|
5071
|
+
state.replayBlocks[state.currentBlock.index].parts.push(replayPart(part));
|
|
4807
5072
|
out.push({
|
|
4808
5073
|
type: isThinking ? "reasoning-delta" : "text-delta",
|
|
4809
|
-
index: state.
|
|
5074
|
+
index: state.currentBlock.index,
|
|
4810
5075
|
text: delta
|
|
4811
5076
|
});
|
|
5077
|
+
} else if (!isRecord(part.functionCall) && thoughtSignature(part)) {
|
|
5078
|
+
if (state.replayBlocks.length === 0) {
|
|
5079
|
+
const type = part.thought ? "reasoning" : "text";
|
|
5080
|
+
state.blocks.push({
|
|
5081
|
+
type,
|
|
5082
|
+
text: ""
|
|
5083
|
+
});
|
|
5084
|
+
state.replayBlocks.push({ parts: [] });
|
|
5085
|
+
out.push({
|
|
5086
|
+
type: "block-start",
|
|
5087
|
+
index: 0,
|
|
5088
|
+
blockType: type
|
|
5089
|
+
});
|
|
5090
|
+
out.push({
|
|
5091
|
+
type: "block-end",
|
|
5092
|
+
index: 0,
|
|
5093
|
+
block: {
|
|
5094
|
+
type,
|
|
5095
|
+
text: ""
|
|
5096
|
+
}
|
|
5097
|
+
});
|
|
5098
|
+
}
|
|
5099
|
+
state.replayBlocks[state.replayBlocks.length - 1].parts.push(replayPart(part));
|
|
4812
5100
|
}
|
|
4813
5101
|
if (isRecord(part.functionCall)) {
|
|
4814
|
-
closeCurrentBlock();
|
|
5102
|
+
out.push(...closeCurrentBlock(state));
|
|
4815
5103
|
const fc = part.functionCall;
|
|
4816
5104
|
const toolName = asString(fc.name) || "";
|
|
4817
5105
|
const toolId = sanitizeToolCallId(asString(fc.id) || "", toolName);
|
|
4818
5106
|
const argsText = JSON.stringify(isRecord(fc.args) ? fc.args : {});
|
|
4819
5107
|
const index = state.blocks.length;
|
|
4820
|
-
const sig = asString(part.thought_signature) || asString(part.thoughtSignature) || asString(part.thinkingSignature) || asString(fc.thought_signature) || asString(fc.thoughtSignature) || state.currentBlock?.thinkingSignature;
|
|
4821
5108
|
const block = {
|
|
4822
5109
|
type: "tool-call",
|
|
4823
|
-
id: toolId,
|
|
5110
|
+
id: CallId(toolId),
|
|
4824
5111
|
name: toolName,
|
|
4825
|
-
arguments: argsText
|
|
4826
|
-
...sig ? {
|
|
4827
|
-
thought_signature: sig,
|
|
4828
|
-
thoughtSignature: sig
|
|
4829
|
-
} : {}
|
|
5112
|
+
arguments: argsText
|
|
4830
5113
|
};
|
|
4831
5114
|
state.blocks.push(block);
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
...
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
} : {}
|
|
4838
|
-
});
|
|
5115
|
+
const sig = thoughtSignature(part) || thoughtSignature(fc);
|
|
5116
|
+
state.replayBlocks.push({ parts: [{
|
|
5117
|
+
...replayPart(part),
|
|
5118
|
+
...sig ? { thoughtSignature: sig } : {}
|
|
5119
|
+
}] });
|
|
4839
5120
|
state.hasContent = true;
|
|
4840
5121
|
state.hasToolCall = true;
|
|
4841
5122
|
out.push({
|
|
@@ -4846,7 +5127,7 @@ function processStreamLine(line, state) {
|
|
|
4846
5127
|
out.push({
|
|
4847
5128
|
type: "tool-call-delta",
|
|
4848
5129
|
index,
|
|
4849
|
-
id: toolId,
|
|
5130
|
+
id: CallId(toolId),
|
|
4850
5131
|
name: toolName,
|
|
4851
5132
|
argumentsDelta: argsText
|
|
4852
5133
|
});
|
|
@@ -4857,55 +5138,33 @@ function processStreamLine(line, state) {
|
|
|
4857
5138
|
});
|
|
4858
5139
|
}
|
|
4859
5140
|
}
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
inputTokens: Math.max(0, (u.promptTokenCount || 0) - (u.cachedContentTokenCount || 0)),
|
|
4864
|
-
outputTokens: (u.candidatesTokenCount || 0) + (u.thoughtsTokenCount || 0),
|
|
4865
|
-
...u.cachedContentTokenCount ? { cacheReadTokens: u.cachedContentTokenCount } : {}
|
|
4866
|
-
};
|
|
4867
|
-
out.push({
|
|
4868
|
-
type: "usage",
|
|
4869
|
-
usage
|
|
4870
|
-
});
|
|
4871
|
-
}
|
|
4872
|
-
const finishReason = candidate?.finishReason;
|
|
5141
|
+
collectUsage(chunk.usageMetadata, state);
|
|
5142
|
+
if (responseData !== chunk) collectUsage(responseData.usageMetadata, state);
|
|
5143
|
+
const finishReason = asString(candidate?.finishReason) || asString(responseData.finishReason);
|
|
4873
5144
|
if (finishReason) {
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
out.push({
|
|
4877
|
-
type: "finish",
|
|
4878
|
-
reason,
|
|
4879
|
-
replayState: { response: {
|
|
4880
|
-
outputItems: state.replayBlocks,
|
|
4881
|
-
blocks: state.replayBlocks
|
|
4882
|
-
} }
|
|
4883
|
-
});
|
|
5145
|
+
state.finishReason = finishReason;
|
|
5146
|
+
out.push(...closeCurrentBlock(state));
|
|
4884
5147
|
}
|
|
4885
5148
|
return out;
|
|
4886
5149
|
}
|
|
4887
5150
|
function closeStream(state) {
|
|
4888
|
-
|
|
4889
|
-
if (state.
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
}
|
|
4906
|
-
});
|
|
4907
|
-
state.currentBlock = null;
|
|
4908
|
-
}
|
|
5151
|
+
if (state.finished) return [];
|
|
5152
|
+
if (!state.finishReason && !state.done) throw new LlmError("Antigravity stream ended before its terminal response", "PROVIDER_ERROR");
|
|
5153
|
+
state.finished = true;
|
|
5154
|
+
const out = closeCurrentBlock(state);
|
|
5155
|
+
if (state.usageMetadata) out.push({
|
|
5156
|
+
type: "usage",
|
|
5157
|
+
usage: tokenUsage(state.usageMetadata)
|
|
5158
|
+
});
|
|
5159
|
+
const reason = state.finishReason === "MAX_TOKENS" ? { kind: "max-tokens" } : state.hasToolCall ? { kind: "tool-calls" } : { kind: "stop" };
|
|
5160
|
+
out.push({
|
|
5161
|
+
type: "finish",
|
|
5162
|
+
reason,
|
|
5163
|
+
replayState: {
|
|
5164
|
+
response: { provider: PROVIDER_ID },
|
|
5165
|
+
blocks: state.replayBlocks
|
|
5166
|
+
}
|
|
5167
|
+
});
|
|
4909
5168
|
return out;
|
|
4910
5169
|
}
|
|
4911
5170
|
//#endregion
|
|
@@ -4989,7 +5248,7 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
4989
5248
|
contextWindow: 128e3,
|
|
4990
5249
|
maxTokens: 65536
|
|
4991
5250
|
};
|
|
4992
|
-
const settings = await this.modelSettings.read();
|
|
5251
|
+
const settings = this.preferences ? this.preferences.status() : await this.modelSettings.read();
|
|
4993
5252
|
const effectiveEffort = options.reasoningEffort || settings.defaultReasoningEffort || void 0;
|
|
4994
5253
|
const effectiveOptions = effectiveEffort ? {
|
|
4995
5254
|
...options,
|
|
@@ -5010,7 +5269,6 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
5010
5269
|
for (const fc of routing.fallbackCandidates) if (!candidates.includes(fc)) candidates.push(fc);
|
|
5011
5270
|
}
|
|
5012
5271
|
let response;
|
|
5013
|
-
candidates[0];
|
|
5014
5272
|
for (const runtimeModel of candidates) {
|
|
5015
5273
|
const body = JSON.stringify(buildRequest(options, model, projectId, runtimeModel, effort));
|
|
5016
5274
|
const headers = {
|
|
@@ -5054,8 +5312,10 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
5054
5312
|
if (!trimmed) continue;
|
|
5055
5313
|
const chunks = processStreamLine(trimmed, state);
|
|
5056
5314
|
for (const chunk of chunks) yield chunk;
|
|
5315
|
+
if (state.finished) return;
|
|
5057
5316
|
}
|
|
5058
5317
|
}
|
|
5318
|
+
buffer += decoder.decode();
|
|
5059
5319
|
if (buffer.trim()) {
|
|
5060
5320
|
const chunks = processStreamLine(buffer.trim(), state);
|
|
5061
5321
|
for (const chunk of chunks) yield chunk;
|