@eddyskywalker/dsh-chatgpt-subscription 0.2.2 → 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/README.md CHANGED
@@ -128,8 +128,16 @@ DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。6 Astra 与 G
128
128
 
129
129
  > Windows 文件只能由创建它的用户通过 DPAPI 解密。macOS 凭据由登录钥匙串在本机加密保存。Linux 文件是未额外加密的 JSON,依赖目录 `0700` 和文件 `0600` 隔离;不要复制、打印或提交该文件。跨平台迁移需要重新登录。
130
130
 
131
- ## 安全边界
132
-
131
+ ## 安全边界
132
+
133
+ Antigravity 的 access token / refresh token 使用独立的系统凭据存储:Windows 使用 CurrentUser DPAPI(`$DSH_HOME/storages/antigravity-oauth.json.dpapi`),macOS 使用登录钥匙串,Linux 使用 Secret Service。macOS / Linux 的服务名为 `dsh-antigravity`,账号键按旧凭据文件的绝对路径生成,隔离不同的 `DSH_HOME`。
134
+
135
+ 升级后首次访问 Antigravity 凭据时,会读取旧 `storages/antigravity-oauth.json`,加密保存并读回校验;成功后删除旧 JSON,通常无需重新登录。失败会保留旧文件并报告错误,不会回退到明文存储。注销同时清理旧文件和新凭据。Linux 需要 `secret-tool`(libsecret 工具包)及可用、已解锁的 Secret Service 钥匙环;无桌面服务的主机也需要配置该服务。系统凭据存储保护落盘数据,不防御当前用户下已获权限的进程。
136
+
137
+ Antigravity 的 Gemini 用量以流结束时的上游累计计数为准,缓存输入单列、思考 token 计入输出并另行提供明细;DSH 使用该输出计数计算 tok/s。Gemini 工具往返会保留原始思考签名,并在支持的运行时请求思考摘要;若上游没有返回摘要文本,插件不会生成替代内容。
138
+
139
+ 以下为 Codex(ChatGPT 订阅)Provider 的存储与网络边界:
140
+
133
141
  - OAuth 回调固定为 `http://localhost:1455/auth/callback`,登录任务五分钟超时,同一时刻只允许一个;
134
142
  - OAuth token 只发送到 `https://auth.openai.com/oauth/token`;
135
143
  - 模型、图片、搜索与额度地址分别固定为 `https://chatgpt.com/backend-api/codex/responses`、`https://chatgpt.com/backend-api/codex/images/generations`、`https://chatgpt.com/backend-api/codex/alpha/search` 和 `https://chatgpt.com/backend-api/wham/usage`,没有 endpoint override;
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
  /**
@@ -3191,16 +3192,18 @@ const DEFAULT_ACCOUNT = "oauth";
3191
3192
  * `security` command-line tool. The payload is encrypted at rest by the
3192
3193
  * Keychain, so this store reports itself as encrypted like Windows DPAPI.
3193
3194
  */
3194
- var MacKeychainTokenStore = class {
3195
+ var MacKeychainCredentialStore = class {
3195
3196
  service;
3196
3197
  account;
3198
+ parse;
3197
3199
  storage = {
3198
3200
  kind: "macos-keychain",
3199
3201
  encrypted: true
3200
3202
  };
3201
- constructor(service = DEFAULT_SERVICE, account = DEFAULT_ACCOUNT) {
3203
+ constructor(service, account, parse) {
3202
3204
  this.service = service;
3203
3205
  this.account = account;
3206
+ this.parse = parse;
3204
3207
  if (process.platform !== "darwin") throw new Error("macOS Keychain storage requires macOS");
3205
3208
  }
3206
3209
  async load() {
@@ -3216,7 +3219,7 @@ var MacKeychainTokenStore = class {
3216
3219
  if (result.code !== 0) throw new Error("Keychain credential read failed");
3217
3220
  try {
3218
3221
  const payload = result.stdout.replace(/\r?\n$/, "");
3219
- return parseStoredCredentials(JSON.parse(payload));
3222
+ return this.parse(JSON.parse(payload));
3220
3223
  } catch {
3221
3224
  throw new Error("Keychain credential payload is invalid");
3222
3225
  }
@@ -3244,6 +3247,11 @@ var MacKeychainTokenStore = class {
3244
3247
  if (result.code !== 0 && result.code !== 44) throw new Error("Keychain credential deletion failed");
3245
3248
  }
3246
3249
  };
3250
+ var MacKeychainTokenStore = class extends MacKeychainCredentialStore {
3251
+ constructor(service = DEFAULT_SERVICE, account = DEFAULT_ACCOUNT) {
3252
+ super(service, account, parseStoredCredentials);
3253
+ }
3254
+ };
3247
3255
  function runSecurity(args) {
3248
3256
  return new Promise((resolve, reject) => {
3249
3257
  const child = spawn("security", args, {
@@ -3388,8 +3396,16 @@ $cipher = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, [Securit
3388
3396
  $directory = [IO.Path]::GetDirectoryName($path)
3389
3397
  [IO.Directory]::CreateDirectory($directory) | Out-Null
3390
3398
  $temporary = $path + '.tmp-' + [Guid]::NewGuid().ToString('N')
3391
- [IO.File]::WriteAllBytes($temporary, $cipher)
3392
- if ([IO.File]::Exists($path)) { [IO.File]::Replace($temporary, $path, $null) } else { [IO.File]::Move($temporary, $path) }
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
+ }
3393
3409
  `;
3394
3410
  const UNPROTECT_SCRIPT = String.raw`
3395
3411
  $ErrorActionPreference = 'Stop'
@@ -3408,14 +3424,16 @@ if ([IO.File]::Exists($path)) { [IO.File]::Delete($path) }
3408
3424
  function defaultDpapiCredentialPath() {
3409
3425
  return join(process.env.DSH_HOME?.trim() || join(homedir(), ".dsh"), "storages", "dsh-chatgpt-subscription", "oauth.dpapi");
3410
3426
  }
3411
- var WindowsDpapiTokenStore = class {
3427
+ var WindowsDpapiCredentialStore = class {
3412
3428
  path;
3429
+ parse;
3413
3430
  storage = {
3414
3431
  kind: "windows-dpapi",
3415
3432
  encrypted: true
3416
3433
  };
3417
- constructor(path = defaultDpapiCredentialPath()) {
3434
+ constructor(path, parse) {
3418
3435
  this.path = path;
3436
+ this.parse = parse;
3419
3437
  if (process.platform !== "win32") throw new Error("Windows DPAPI storage requires Windows");
3420
3438
  if (dirname(path) === path) throw new Error("invalid DPAPI credential path");
3421
3439
  }
@@ -3424,7 +3442,7 @@ var WindowsDpapiTokenStore = class {
3424
3442
  if (result.code === 3) return null;
3425
3443
  if (result.code !== 0) throw new Error("DPAPI credential read failed");
3426
3444
  try {
3427
- return parseStoredCredentials(JSON.parse(result.stdout));
3445
+ return this.parse(JSON.parse(result.stdout));
3428
3446
  } catch {
3429
3447
  throw new Error("DPAPI credential payload is invalid");
3430
3448
  }
@@ -3436,6 +3454,11 @@ var WindowsDpapiTokenStore = class {
3436
3454
  if ((await runPowerShell(CLEAR_SCRIPT, this.path, "")).code !== 0) throw new Error("DPAPI credential deletion failed");
3437
3455
  }
3438
3456
  };
3457
+ var WindowsDpapiTokenStore = class extends WindowsDpapiCredentialStore {
3458
+ constructor(path = defaultDpapiCredentialPath()) {
3459
+ super(path, parseStoredCredentials);
3460
+ }
3461
+ };
3439
3462
  function runPowerShell(script, path, stdin) {
3440
3463
  return new Promise((resolve, reject) => {
3441
3464
  const child = spawn("powershell.exe", [
@@ -3856,6 +3879,96 @@ const MODELS = [
3856
3879
  }
3857
3880
  ];
3858
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
3859
3972
  //#region src/host/antigravity/token-store.ts
3860
3973
  const ANTIGRAVITY_PREFERENCES_NAMESPACE = "dsh-antigravity";
3861
3974
  function registerAntigravityPreferenceStore(settings, fallbackStore = new FileModelSettingsStore()) {
@@ -3917,36 +4030,110 @@ function credentialPath() {
3917
4030
  function modelSettingsPath() {
3918
4031
  return path.join(dshHomeDir(), "storages", "antigravity-models.json");
3919
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. */
3920
4068
  var FileCredentialStore = class {
3921
4069
  filePath;
3922
- constructor(filePath = credentialPath()) {
4070
+ backend;
4071
+ constructor(filePath = credentialPath(), backend = createCredentialBackend(filePath)) {
3923
4072
  this.filePath = filePath;
4073
+ this.backend = backend;
3924
4074
  }
3925
4075
  path() {
3926
- 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;
3927
4088
  }
3928
- async read() {
4089
+ async removeLegacy() {
3929
4090
  try {
3930
- const content = await fsPromises.readFile(this.filePath, "utf8");
3931
- const parsed = JSON.parse(content);
3932
- if (typeof parsed === "object" && parsed !== null && ("access_token" in parsed || "access" in parsed)) return parsed;
3933
- return null;
3934
- } catch {
3935
- return null;
4091
+ await fsPromises.unlink(this.filePath);
4092
+ } catch (error) {
4093
+ if (error.code !== "ENOENT") throw new Error("Antigravity legacy credential removal failed");
3936
4094
  }
3937
4095
  }
3938
- async write(credentials) {
3939
- await fsPromises.mkdir(path.dirname(this.filePath), { recursive: true });
3940
- const tmp = `${this.filePath}.tmp.${Date.now()}`;
3941
- await fsPromises.writeFile(tmp, JSON.stringify(credentials, null, 2), "utf8");
3942
- await fsPromises.rename(tmp, this.filePath);
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
+ });
3943
4128
  }
3944
- async delete() {
3945
- try {
3946
- await fsPromises.unlink(this.filePath);
3947
- } catch (err) {
3948
- if (err.code !== "ENOENT") throw err;
3949
- }
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
+ });
3950
4137
  }
3951
4138
  };
3952
4139
  var FileModelSettingsStore = class {
@@ -4578,15 +4765,27 @@ function toolResultText(blocks) {
4578
4765
  }
4579
4766
  function replayBlockFor(message, index) {
4580
4767
  const source = message.source;
4581
- if (!source || source.kind !== "model") return void 0;
4768
+ if (!source || source.kind !== "model" || source.provider !== "antigravity") return void 0;
4582
4769
  const state = source.replayState;
4583
4770
  if (!isRecord(state)) return void 0;
4771
+ if (Array.isArray(state.blocks)) return state.blocks[index];
4584
4772
  const resp = isRecord(state.response) ? state.response : void 0;
4585
4773
  if (resp) {
4586
4774
  if (Array.isArray(resp.outputItems)) return resp.outputItems[index];
4587
4775
  if (Array.isArray(resp.blocks)) return resp.blocks[index];
4588
4776
  }
4589
- if (Array.isArray(state.blocks)) return state.blocks[index];
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;
4590
4789
  }
4591
4790
  function assistantParts(message, model, runtimeModel, toolNames) {
4592
4791
  const parts = [];
@@ -4595,30 +4794,39 @@ function assistantParts(message, model, runtimeModel, toolNames) {
4595
4794
  const block = message.content[index];
4596
4795
  if (!isRecord(block)) continue;
4597
4796
  const replay = replayBlockFor(message, index);
4598
- if (block.type === "text" && String(block.text || "").trim()) parts.push({ text: sanitizeText(String(block.text)) });
4599
- else if (block.type === "reasoning" && String(block.text || "").trim()) {
4600
- const sig = asString(replay?.thinkingSignature) || asString(replay?.thought_signature) || asString(block.thought_signature);
4601
- if (sig) parts.push({
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({
4602
4811
  thought: true,
4603
4812
  text: sanitizeText(String(block.text)),
4604
- thought_signature: sig,
4605
- thoughtSignature: sig
4813
+ ...sig ? { thoughtSignature: sig } : {}
4606
4814
  });
4607
- else parts.push({ text: sanitizeText(String(block.text)) });
4608
4815
  } else if (block.type === "tool-call") {
4609
4816
  const toolId = String(block.id || "");
4610
4817
  const toolName = String(block.name || "");
4611
4818
  toolNames.set(toolId, toolName);
4612
- const sig = asString(replay?.thought_signature) || asString(replay?.thoughtSignature) || asString(block.thought_signature) || asString(block.thoughtSignature) || "skip_thought_signature_validator";
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");
4613
4821
  parts.push({
4614
4822
  functionCall: {
4615
4823
  name: toolName,
4616
4824
  args: parseArguments(block.arguments),
4617
4825
  ...toolCallIdNeeded(model.id, runtimeModel) ? { id: sanitizeToolCallId(toolId, toolName) } : {}
4618
4826
  },
4619
- thought_signature: sig,
4620
- thoughtSignature: sig
4827
+ ...effectiveSignature ? { thoughtSignature: effectiveSignature } : {}
4621
4828
  });
4829
+ parts.push(...originalParts.filter((part) => !part.functionCall).map(replayPart));
4622
4830
  }
4623
4831
  }
4624
4832
  return parts;
@@ -4722,6 +4930,8 @@ function buildRequest(options, model, projectId, runtimeModel, effort) {
4722
4930
  const isTiered = runtimeModel === "gemini-3.8-flash-tiered" || runtimeModel === "gemini-3.7-flash-tiered";
4723
4931
  const isSuffixed = /^gemini-.+(?:-(?:extra-)?low|-medium|-high|-xhigh)$/.test(runtimeModel);
4724
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";
4725
4935
  if (isTiered) {
4726
4936
  const selected = (effort || "medium").toLowerCase();
4727
4937
  const isOff = selected === "off" || selected === "none";
@@ -4729,7 +4939,7 @@ function buildRequest(options, model, projectId, runtimeModel, effort) {
4729
4939
  thinkingLevel: isOff ? "MINIMAL" : selected === "high" || selected === "xhigh" ? "HIGH" : selected === "medium" ? "MEDIUM" : "LOW",
4730
4940
  includeThoughts: !isOff
4731
4941
  };
4732
- } else if (isSuffixed) {
4942
+ } else if (isSuffixed || isGemini3 || isGeminiAgent) {
4733
4943
  const selected = (effort || "medium").toLowerCase();
4734
4944
  generationConfig.thinkingConfig = { includeThoughts: !(selected === "off" || selected === "none") };
4735
4945
  } else if (isGemini25) {
@@ -4765,58 +4975,90 @@ function createStreamState() {
4765
4975
  replayBlocks: [],
4766
4976
  currentBlock: null,
4767
4977
  hasContent: false,
4768
- 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 } : {}
4769
5026
  };
4770
5027
  }
4771
5028
  function processStreamLine(line, state) {
4772
- if (!line.startsWith("data:")) return [];
5029
+ if (state.finished || !line.startsWith("data:")) return [];
4773
5030
  const json = line.slice(5).trim();
4774
- if (!json || json === "[DONE]") return [];
5031
+ if (json === "[DONE]") {
5032
+ state.done = true;
5033
+ return closeStream(state);
5034
+ }
5035
+ if (!json) return [];
4775
5036
  const chunk = safeJsonParse(json);
4776
5037
  if (!isRecord(chunk)) return [];
4777
5038
  const responseData = isRecord(chunk.response) ? chunk.response : chunk;
4778
- const candidate = (Array.isArray(responseData.candidates) ? responseData.candidates : [])[0];
5039
+ const candidates = Array.isArray(responseData.candidates) ? responseData.candidates : [];
5040
+ const candidate = isRecord(candidates[0]) ? candidates[0] : void 0;
4779
5041
  const content = isRecord(candidate?.content) ? candidate.content : void 0;
4780
5042
  const parts = Array.isArray(content?.parts) ? content.parts : [];
4781
5043
  const out = [];
4782
- const closeCurrentBlock = () => {
4783
- if (!state.currentBlock) return;
4784
- const index = state.blocks.length - 1;
4785
- if (state.currentBlock.type === "text") out.push({
4786
- type: "block-end",
4787
- index,
4788
- block: {
4789
- type: "text",
4790
- text: state.currentBlock.text
4791
- }
4792
- });
4793
- else out.push({
4794
- type: "block-end",
4795
- index,
4796
- block: {
4797
- type: "reasoning",
4798
- text: state.currentBlock.text
4799
- }
4800
- });
4801
- state.currentBlock = null;
4802
- };
4803
5044
  for (const part of parts) {
4804
5045
  if (!isRecord(part)) continue;
4805
- if (part.text !== void 0 && typeof part.text === "string") {
5046
+ if (typeof part.text === "string" && part.text !== "") {
4806
5047
  const isThinking = Boolean(part.thought);
4807
5048
  const blockType = isThinking ? "reasoning" : "text";
4808
5049
  if (!state.currentBlock || state.currentBlock.type !== blockType) {
4809
- closeCurrentBlock();
5050
+ out.push(...closeCurrentBlock(state));
5051
+ const index = state.blocks.length;
4810
5052
  state.currentBlock = {
5053
+ index,
4811
5054
  type: blockType,
4812
5055
  text: ""
4813
5056
  };
4814
- const index = state.blocks.length;
4815
5057
  state.blocks.push({
4816
5058
  type: blockType,
4817
5059
  text: ""
4818
5060
  });
4819
- state.replayBlocks.push({ type: blockType });
5061
+ state.replayBlocks.push({ parts: [] });
4820
5062
  out.push({
4821
5063
  type: "block-start",
4822
5064
  index,
@@ -4826,45 +5068,55 @@ function processStreamLine(line, state) {
4826
5068
  const delta = sanitizeText(part.text);
4827
5069
  state.currentBlock.text += delta;
4828
5070
  state.hasContent = true;
4829
- if (isThinking && part.thoughtSignature) {
4830
- state.currentBlock.thinkingSignature = part.thoughtSignature;
4831
- state.replayBlocks[state.blocks.length - 1].thinkingSignature = part.thoughtSignature;
4832
- } else if (!isThinking && part.thoughtSignature) {
4833
- state.currentBlock.textSignature = part.thoughtSignature;
4834
- state.replayBlocks[state.blocks.length - 1].textSignature = part.thoughtSignature;
4835
- }
5071
+ state.replayBlocks[state.currentBlock.index].parts.push(replayPart(part));
4836
5072
  out.push({
4837
5073
  type: isThinking ? "reasoning-delta" : "text-delta",
4838
- index: state.blocks.length - 1,
5074
+ index: state.currentBlock.index,
4839
5075
  text: delta
4840
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));
4841
5100
  }
4842
5101
  if (isRecord(part.functionCall)) {
4843
- closeCurrentBlock();
5102
+ out.push(...closeCurrentBlock(state));
4844
5103
  const fc = part.functionCall;
4845
5104
  const toolName = asString(fc.name) || "";
4846
5105
  const toolId = sanitizeToolCallId(asString(fc.id) || "", toolName);
4847
5106
  const argsText = JSON.stringify(isRecord(fc.args) ? fc.args : {});
4848
5107
  const index = state.blocks.length;
4849
- const sig = asString(part.thought_signature) || asString(part.thoughtSignature) || asString(part.thinkingSignature) || asString(fc.thought_signature) || asString(fc.thoughtSignature) || state.currentBlock?.thinkingSignature;
4850
5108
  const block = {
4851
5109
  type: "tool-call",
4852
- id: toolId,
5110
+ id: CallId(toolId),
4853
5111
  name: toolName,
4854
- arguments: argsText,
4855
- ...sig ? {
4856
- thought_signature: sig,
4857
- thoughtSignature: sig
4858
- } : {}
5112
+ arguments: argsText
4859
5113
  };
4860
5114
  state.blocks.push(block);
4861
- state.replayBlocks.push({
4862
- type: "tool-call",
4863
- ...sig ? {
4864
- thought_signature: sig,
4865
- thoughtSignature: sig
4866
- } : {}
4867
- });
5115
+ const sig = thoughtSignature(part) || thoughtSignature(fc);
5116
+ state.replayBlocks.push({ parts: [{
5117
+ ...replayPart(part),
5118
+ ...sig ? { thoughtSignature: sig } : {}
5119
+ }] });
4868
5120
  state.hasContent = true;
4869
5121
  state.hasToolCall = true;
4870
5122
  out.push({
@@ -4875,7 +5127,7 @@ function processStreamLine(line, state) {
4875
5127
  out.push({
4876
5128
  type: "tool-call-delta",
4877
5129
  index,
4878
- id: toolId,
5130
+ id: CallId(toolId),
4879
5131
  name: toolName,
4880
5132
  argumentsDelta: argsText
4881
5133
  });
@@ -4886,55 +5138,33 @@ function processStreamLine(line, state) {
4886
5138
  });
4887
5139
  }
4888
5140
  }
4889
- if (responseData.usageMetadata && isRecord(responseData.usageMetadata)) {
4890
- const u = responseData.usageMetadata;
4891
- const usage = {
4892
- inputTokens: Math.max(0, (u.promptTokenCount || 0) - (u.cachedContentTokenCount || 0)),
4893
- outputTokens: (u.candidatesTokenCount || 0) + (u.thoughtsTokenCount || 0),
4894
- ...u.cachedContentTokenCount ? { cacheReadTokens: u.cachedContentTokenCount } : {}
4895
- };
4896
- out.push({
4897
- type: "usage",
4898
- usage
4899
- });
4900
- }
4901
- 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);
4902
5144
  if (finishReason) {
4903
- closeCurrentBlock();
4904
- const reason = state.hasToolCall ? { kind: "tool-calls" } : finishReason === "MAX_TOKENS" ? { kind: "max-tokens" } : { kind: "stop" };
4905
- out.push({
4906
- type: "finish",
4907
- reason,
4908
- replayState: { response: {
4909
- outputItems: state.replayBlocks,
4910
- blocks: state.replayBlocks
4911
- } }
4912
- });
5145
+ state.finishReason = finishReason;
5146
+ out.push(...closeCurrentBlock(state));
4913
5147
  }
4914
5148
  return out;
4915
5149
  }
4916
5150
  function closeStream(state) {
4917
- const out = [];
4918
- if (state.currentBlock) {
4919
- const index = state.blocks.length - 1;
4920
- if (state.currentBlock.type === "text") out.push({
4921
- type: "block-end",
4922
- index,
4923
- block: {
4924
- type: "text",
4925
- text: state.currentBlock.text
4926
- }
4927
- });
4928
- else out.push({
4929
- type: "block-end",
4930
- index,
4931
- block: {
4932
- type: "reasoning",
4933
- text: state.currentBlock.text
4934
- }
4935
- });
4936
- state.currentBlock = null;
4937
- }
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
+ });
4938
5168
  return out;
4939
5169
  }
4940
5170
  //#endregion
@@ -5018,7 +5248,7 @@ var AntigravityAdapter = class extends LlmAdapter {
5018
5248
  contextWindow: 128e3,
5019
5249
  maxTokens: 65536
5020
5250
  };
5021
- const settings = await this.modelSettings.read();
5251
+ const settings = this.preferences ? this.preferences.status() : await this.modelSettings.read();
5022
5252
  const effectiveEffort = options.reasoningEffort || settings.defaultReasoningEffort || void 0;
5023
5253
  const effectiveOptions = effectiveEffort ? {
5024
5254
  ...options,
@@ -5039,7 +5269,6 @@ var AntigravityAdapter = class extends LlmAdapter {
5039
5269
  for (const fc of routing.fallbackCandidates) if (!candidates.includes(fc)) candidates.push(fc);
5040
5270
  }
5041
5271
  let response;
5042
- candidates[0];
5043
5272
  for (const runtimeModel of candidates) {
5044
5273
  const body = JSON.stringify(buildRequest(options, model, projectId, runtimeModel, effort));
5045
5274
  const headers = {
@@ -5083,8 +5312,10 @@ var AntigravityAdapter = class extends LlmAdapter {
5083
5312
  if (!trimmed) continue;
5084
5313
  const chunks = processStreamLine(trimmed, state);
5085
5314
  for (const chunk of chunks) yield chunk;
5315
+ if (state.finished) return;
5086
5316
  }
5087
5317
  }
5318
+ buffer += decoder.decode();
5088
5319
  if (buffer.trim()) {
5089
5320
  const chunks = processStreamLine(buffer.trim(), state);
5090
5321
  for (const chunk of chunks) yield chunk;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/host/antigravity/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAGV,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAA;AAU7B,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,MAAM,kBAAkB,CAAA;AAM/G,qBAAa,kBAAmB,SAAQ,UAAU;IAE9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAFZ,KAAK,sBAA4B,EACjC,aAAa,yBAA+B,EAC5C,WAAW,CAAC,EAAE,0BAA0B,YAAA;IAK3D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe;IAIzC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;IAkB/D,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAqCpG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO/F,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAAC,WAAW,CAAC;YAwBpD,aAAa;CAsG7B"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/host/antigravity/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAGV,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAA;AAU7B,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,MAAM,kBAAkB,CAAA;AAM/G,qBAAa,kBAAmB,SAAQ,UAAU;IAE9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAFZ,KAAK,sBAA4B,EACjC,aAAa,yBAA+B,EAC5C,WAAW,CAAC,EAAE,0BAA0B,YAAA;IAK3D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe;IAIzC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;IAkB/D,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAqCpG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO/F,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAAC,WAAW,CAAC;YAwBpD,aAAa;CAqG7B"}
@@ -1,4 +1,4 @@
1
- import type { ContentBlock, GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm';
1
+ import { type ContentBlock, type GenerateOptions, type StreamChunk } from '@deepseek-ai/dsh-llm';
2
2
  import { type AntigravityModelDef } from './types.ts';
3
3
  export declare function sanitizeToolCallId(id: string, fallbackName: string): string;
4
4
  export declare function convertMessages(options: GenerateOptions, model: AntigravityModelDef, runtimeModel: string): Array<{
@@ -12,15 +12,20 @@ export declare function getMaxOutputTokens(modelId: string, runtimeModel: string
12
12
  export declare function buildRequest(options: GenerateOptions, model: AntigravityModelDef, projectId: string, runtimeModel: string, effort?: string): Record<string, unknown>;
13
13
  export interface StreamState {
14
14
  blocks: ContentBlock[];
15
- replayBlocks: Array<Record<string, unknown>>;
15
+ replayBlocks: Array<{
16
+ parts: Array<Record<string, unknown>>;
17
+ }>;
16
18
  currentBlock: {
19
+ index: number;
17
20
  type: 'text' | 'reasoning';
18
21
  text: string;
19
- thinkingSignature?: unknown;
20
- textSignature?: unknown;
21
22
  } | null;
22
23
  hasContent: boolean;
23
24
  hasToolCall: boolean;
25
+ usageMetadata: Record<string, number> | null;
26
+ finishReason?: string;
27
+ done: boolean;
28
+ finished: boolean;
24
29
  }
25
30
  export declare function createStreamState(): StreamState;
26
31
  export declare function processStreamLine(line: string, state: StreamState): StreamChunk[];
@@ -1 +1 @@
1
- {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/host/antigravity/mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEZ,eAAe,EAEf,WAAW,EAEZ,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAOL,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAA;AAwBnB,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAI3E;AAmKD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,mBAAmB,EAC1B,YAAY,EAAE,MAAM,GACnB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,CAAC,CA2BhE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAiBxD;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAC9B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAQ5C;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAI7D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsFzB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC5C,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IACvH,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAQ/C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAsIjF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAoB7D"}
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/host/antigravity/mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAEjB,KAAK,eAAe,EAEpB,KAAK,WAAW,EAEjB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAOL,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAA;AAwBnB,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAI3E;AAoLD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,mBAAmB,EAC1B,YAAY,EAAE,MAAM,GACnB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,CAAC,CA2BhE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAiBxD;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAC9B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAQ5C;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAI7D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwFzB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,CAAC,CAAA;IAC9D,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAChF,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAW/C;AA2CD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CA0FjF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAmB7D"}
@@ -1,4 +1,5 @@
1
1
  import type { SettingsProvider } from '@deepseek-ai/dsh-settings';
2
+ import type { CredentialStore } from '../token-store.ts';
2
3
  export declare const ANTIGRAVITY_PREFERENCES_NAMESPACE = "dsh-antigravity";
3
4
  export interface AntigravityCredentials {
4
5
  access?: string;
@@ -33,10 +34,16 @@ export declare function registerAntigravityPreferenceStore(settings?: SettingsPr
33
34
  export declare function dshHomeDir(): string;
34
35
  export declare function credentialPath(): string;
35
36
  export declare function modelSettingsPath(): string;
37
+ export declare function parseAntigravityCredentials(value: unknown): AntigravityCredentials;
38
+ /** Keeps the public API; filePath identifies the legacy JSON that is migrated on first use. */
36
39
  export declare class FileCredentialStore {
37
40
  private readonly filePath;
38
- constructor(filePath?: string);
41
+ private readonly backend;
42
+ constructor(filePath?: string, backend?: CredentialStore<AntigravityCredentials>);
39
43
  path(): string;
44
+ private serialize;
45
+ private removeLegacy;
46
+ private saveVerified;
40
47
  read(): Promise<AntigravityCredentials | null>;
41
48
  write(credentials: AntigravityCredentials): Promise<void>;
42
49
  delete(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../../src/host/antigravity/token-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAA;AAKhF,eAAO,MAAM,iCAAiC,oBAAoB,CAAA;AAElE,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,EAAE,uBAAuB,EAAE,CAAA;IACxC,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C,sBAAsB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAA;CAC1D;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,IAAI,wBAAwB,CAAA;IAClC,MAAM,CAAC,KAAK,EAAE;QACZ,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;QAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,sBAAsB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAA;KAC1D,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;CACtC;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,aAAa,yBAA+B,GAC3C,0BAA0B,CAyD5B;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,SAAmB;IAExD,IAAI,IAAI,MAAM;IAIR,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAa9C,KAAK,CAAC,WAAW,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAO9B;AAED,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,SAAsB;IAE3D,IAAI,IAAI,MAAM;IAIR,IAAI,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAyCzC,KAAK,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,cAAc,CAAC,KAAK,EAAE;QAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;QAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,sBAAsB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAA;KAC1D,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAqB/B,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAIhF,gBAAgB,CACpB,aAAa,EAAE,uBAAuB,EAAE,EACxC,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GACvC,OAAO,CAAC,wBAAwB,CAAC;CAUrC"}
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../../src/host/antigravity/token-store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAA;AAIhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAKxD,eAAO,MAAM,iCAAiC,oBAAoB,CAAA;AAElE,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,EAAE,uBAAuB,EAAE,CAAA;IACxC,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C,sBAAsB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAA;CAC1D;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,IAAI,wBAAwB,CAAA;IAClC,MAAM,CAAC,KAAK,EAAE;QACZ,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;QAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,sBAAsB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAA;KAC1D,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;CACtC;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,aAAa,yBAA+B,GAC3C,0BAA0B,CAyD5B;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAsBlF;AAsBD,+FAA+F;AAC/F,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,QAAQ,SAAmB,EAC3B,OAAO,GAAE,eAAe,CAAC,sBAAsB,CAAqC;IAGvG,IAAI,IAAI,MAAM;IAMd,OAAO,CAAC,SAAS;YAWH,YAAY;YAUZ,YAAY;IAO1B,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IA8B9C,KAAK,CAAC,WAAW,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAOxB;AAED,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,SAAsB;IAE3D,IAAI,IAAI,MAAM;IAIR,IAAI,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAyCzC,KAAK,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,cAAc,CAAC,KAAK,EAAE;QAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;QAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,sBAAsB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAA;KAC1D,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAqB/B,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAIhF,gBAAgB,CACpB,aAAa,EAAE,uBAAuB,EAAE,EACxC,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GACvC,OAAO,CAAC,wBAAwB,CAAC;CAUrC"}
@@ -0,0 +1,13 @@
1
+ import type { CredentialStore } from './token-store.ts';
2
+ /** Secrets travel over stdin/stdout; command arguments contain only lookup attributes. */
3
+ export declare class SecretServiceCredentialStore<T> implements CredentialStore<T> {
4
+ private readonly service;
5
+ private readonly account;
6
+ private readonly parse;
7
+ constructor(service: string, account: string, parse: (value: unknown) => T);
8
+ private attributes;
9
+ load(): Promise<T | null>;
10
+ save(value: T): Promise<void>;
11
+ clear(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=credential-store-secret-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store-secret-service.d.ts","sourceRoot":"","sources":["../../../src/host/credential-store-secret-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIvD,0FAA0F;AAC1F,qBAAa,4BAA4B,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAEtE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IAG/C,OAAO,CAAC,UAAU;IAIZ,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAWzB,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -1,19 +1,23 @@
1
- import type { TokenStore, StoredOAuthCredentials } from './token-store.ts';
1
+ import type { CredentialStore, TokenStore, StoredOAuthCredentials } from './token-store.ts';
2
2
  /**
3
3
  * macOS credential storage backed by the login Keychain through the built-in
4
4
  * `security` command-line tool. The payload is encrypted at rest by the
5
5
  * Keychain, so this store reports itself as encrypted like Windows DPAPI.
6
6
  */
7
- export declare class MacKeychainTokenStore implements TokenStore {
7
+ export declare class MacKeychainCredentialStore<T> implements CredentialStore<T> {
8
8
  private readonly service;
9
9
  private readonly account;
10
+ private readonly parse;
10
11
  readonly storage: {
11
12
  readonly kind: "macos-keychain";
12
13
  readonly encrypted: true;
13
14
  };
14
- constructor(service?: string, account?: string);
15
- load(): Promise<StoredOAuthCredentials | null>;
16
- save(value: StoredOAuthCredentials): Promise<void>;
15
+ constructor(service: string, account: string, parse: (value: unknown) => T);
16
+ load(): Promise<T | null>;
17
+ save(value: T): Promise<void>;
17
18
  clear(): Promise<void>;
18
19
  }
20
+ export declare class MacKeychainTokenStore extends MacKeychainCredentialStore<StoredOAuthCredentials> implements TokenStore {
21
+ constructor(service?: string, account?: string);
22
+ }
19
23
  //# sourceMappingURL=token-store-macos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-store-macos.d.ts","sourceRoot":"","sources":["../../../src/host/token-store-macos.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAM1E;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,UAAU;IAIpD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,QAAQ,CAAC,OAAO;;;MAAuD;gBAGpD,OAAO,SAAkB,EACzB,OAAO,SAAkB;IAKtC,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAY9C,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
1
+ {"version":3,"file":"token-store-macos.d.ts","sourceRoot":"","sources":["../../../src/host/token-store-macos.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAM3F;;;;GAIG;AACH,qBAAa,0BAA0B,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAIpE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IALxB,QAAQ,CAAC,OAAO;;;MAAuD;gBAGpD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IAKzC,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAYzB,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B;AAED,qBAAa,qBAAsB,SAAQ,0BAA0B,CAAC,sBAAsB,CAAE,YAAW,UAAU;gBACrG,OAAO,SAAkB,EAAE,OAAO,SAAkB;CAGjE"}
@@ -1,14 +1,18 @@
1
- import type { TokenStore, StoredOAuthCredentials } from './token-store.ts';
1
+ import type { CredentialStore, TokenStore, StoredOAuthCredentials } from './token-store.ts';
2
2
  export declare function defaultDpapiCredentialPath(): string;
3
- export declare class WindowsDpapiTokenStore implements TokenStore {
3
+ export declare class WindowsDpapiCredentialStore<T> implements CredentialStore<T> {
4
4
  private readonly path;
5
+ private readonly parse;
5
6
  readonly storage: {
6
7
  readonly kind: "windows-dpapi";
7
8
  readonly encrypted: true;
8
9
  };
9
- constructor(path?: string);
10
- load(): Promise<StoredOAuthCredentials | null>;
11
- save(value: StoredOAuthCredentials): Promise<void>;
10
+ constructor(path: string, parse: (value: unknown) => T);
11
+ load(): Promise<T | null>;
12
+ save(value: T): Promise<void>;
12
13
  clear(): Promise<void>;
13
14
  }
15
+ export declare class WindowsDpapiTokenStore extends WindowsDpapiCredentialStore<StoredOAuthCredentials> implements TokenStore {
16
+ constructor(path?: string);
17
+ }
14
18
  //# sourceMappingURL=token-store-windows.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-store-windows.d.ts","sourceRoot":"","sources":["../../../src/host/token-store-windows.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAiC1E,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD;AAED,qBAAa,sBAAuB,YAAW,UAAU;IAG3C,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,OAAO;;;MAAsD;gBAEzC,IAAI,SAA+B;IAK1D,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAW9C,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
1
+ {"version":3,"file":"token-store-windows.d.ts","sourceRoot":"","sources":["../../../src/host/token-store-windows.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAyC3F,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD;AAED,qBAAa,2BAA2B,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAG3D,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAU,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFjE,QAAQ,CAAC,OAAO;;;MAAsD;gBAEzC,IAAI,EAAE,MAAM,EAAmB,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IAKlF,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAWzB,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B;AAED,qBAAa,sBAAuB,SAAQ,2BAA2B,CAAC,sBAAsB,CAAE,YAAW,UAAU;gBACvG,IAAI,SAA+B;CAGhD"}
@@ -8,12 +8,14 @@ export interface StoredOAuthCredentials {
8
8
  email?: string;
9
9
  planType?: string;
10
10
  }
11
- export interface TokenStore {
12
- readonly storage: Omit<CredentialStorageDto, 'available'>;
13
- load(): Promise<StoredOAuthCredentials | null>;
14
- save(value: StoredOAuthCredentials): Promise<void>;
11
+ export interface CredentialStore<T> {
12
+ load(): Promise<T | null>;
13
+ save(value: T): Promise<void>;
15
14
  clear(): Promise<void>;
16
15
  }
16
+ export interface TokenStore extends CredentialStore<StoredOAuthCredentials> {
17
+ readonly storage: Omit<CredentialStorageDto, 'available'>;
18
+ }
17
19
  /** Test seam and non-persistent development store. Never used by apply(). */
18
20
  export declare class MemoryTokenStore implements TokenStore {
19
21
  readonly storage: {
@@ -1 +1 @@
1
- {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../src/host/token-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAA;IACzD,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAA;IAC9C,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,YAAW,UAAU;IACjD,QAAQ,CAAC,OAAO;;;MAAgD;IAChE,OAAO,CAAC,KAAK,CAAsC;IAE7C,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAI9C,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAqB7E"}
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../src/host/token-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IACzB,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,MAAM,WAAW,UAAW,SAAQ,eAAe,CAAC,sBAAsB,CAAC;IACzE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAA;CAC1D;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,YAAW,UAAU;IACjD,QAAQ,CAAC,OAAO;;;MAAgD;IAChE,OAAO,CAAC,KAAK,CAAsC;IAE7C,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAI9C,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAqB7E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eddyskywalker/dsh-chatgpt-subscription",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "DSH provider plugin for Codex access through a ChatGPT subscription.",
5
5
  "author": {
6
6
  "name": "eddyskywalker",