@eddyskywalker/dsh-chatgpt-subscription 0.1.4 → 0.1.6

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/lib/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { CallId, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, attributionHeaders, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
2
2
  import { createHash, randomBytes, randomUUID } from "node:crypto";
3
3
  import http from "node:http";
4
+ import { constants } from "node:fs";
5
+ import { chmod, lstat, mkdir, open, rename, stat, unlink } from "node:fs/promises";
4
6
  import { homedir } from "node:os";
5
7
  import { dirname, join } from "node:path";
6
8
  import { spawn } from "node:child_process";
@@ -122,6 +124,141 @@ var CodexChatGptAdapter = class extends LlmAdapter {
122
124
  }
123
125
  };
124
126
  //#endregion
127
+ //#region src/host/subagent-report-scheduling-compat.ts
128
+ /**
129
+ * DSH_COMPAT_REMOVE(subagent-report-settlement-dedup)
130
+ *
131
+ * Temporary compatibility shim for DSH 0.1.0-rc.6. A continuable child is told
132
+ * to report its result before finishing, while DSH also unconditionally sends
133
+ * the same closing output in a `subagent-settled` notice. The report is often
134
+ * still queued when the settlement reaches the parent, so the parent sees the
135
+ * result once and the equivalent report remains as duplicate next-turn work.
136
+ *
137
+ * Remove this module, its installation in `src/index.ts`, and its focused test
138
+ * once upstream coalesces an equivalent final report with settlement delivery.
139
+ */
140
+ const DSH_SUBAGENT_REPORT_DEDUP_COMPAT_MARKER = "__dshChatgptSubscriptionSubagentReportDedupCompatV1";
141
+ function sourceOf(message) {
142
+ return message.source;
143
+ }
144
+ function isTextBlock(value, text) {
145
+ return typeof value === "object" && value !== null && value.type === "text" && value.text === text;
146
+ }
147
+ function sameValue(left, right) {
148
+ if (left === right) return true;
149
+ if (Array.isArray(left) || Array.isArray(right)) return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => sameValue(value, right[index]));
150
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
151
+ const leftRecord = left;
152
+ const rightRecord = right;
153
+ const leftKeys = Object.keys(leftRecord).sort();
154
+ const rightKeys = Object.keys(rightRecord).sort();
155
+ return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && sameValue(leftRecord[key], rightRecord[key]));
156
+ }
157
+ function duplicatePendingReports(agent, settlement) {
158
+ const settlementSource = sourceOf(settlement);
159
+ if (settlementSource.kind !== "subagent-settled" || settlementSource.senderSessionId === void 0) return [];
160
+ if (settlement.content.length < 2 || !isTextBlock(settlement.content[1], "Its closing message:")) return [];
161
+ const closingContent = settlement.content.slice(2);
162
+ return [...agent.inbox.nextStep, ...agent.inbox.nextTurn].filter((pending) => {
163
+ const pendingSource = sourceOf(pending);
164
+ return pendingSource.kind === "subagent-report" && pendingSource.senderSessionId === settlementSource.senderSessionId && sameValue(pending.content.slice(1), closingContent);
165
+ });
166
+ }
167
+ function errorMessage(error) {
168
+ return error instanceof Error ? error.message : String(error);
169
+ }
170
+ /**
171
+ * Discard only an exact, same-child report duplicate immediately before DSH
172
+ * delivers the corresponding settlement notice. Partial reports, reports with
173
+ * different content, and all unrelated inbox work remain untouched.
174
+ */
175
+ function installSubagentReportDedupCompat(ctx) {
176
+ const patches = /* @__PURE__ */ new Map();
177
+ const patch = (agent) => {
178
+ if (patches.has(agent)) return;
179
+ const shared = agent.followup[DSH_SUBAGENT_REPORT_DEDUP_COMPAT_MARKER];
180
+ if (shared?.wrappers.followup === agent.followup && shared.wrappers.steer === agent.steer && shared.wrappers.inject === agent.inject) {
181
+ shared.owners += 1;
182
+ patches.set(agent, shared);
183
+ return;
184
+ }
185
+ const originals = {
186
+ followup: agent.followup,
187
+ steer: agent.steer,
188
+ inject: agent.inject
189
+ };
190
+ let record;
191
+ const deliver = (name, message) => {
192
+ for (const duplicate of duplicatePendingReports(agent, message)) try {
193
+ agent.inbox.remove(duplicate.id);
194
+ } catch (error) {
195
+ ctx.logger.warn("[dsh-chatgpt-subscription] Could not discard a duplicate DSH subagent report: " + errorMessage(error));
196
+ }
197
+ originals[name].call(agent, message);
198
+ };
199
+ const wrappers = {
200
+ followup(message) {
201
+ deliver("followup", message);
202
+ },
203
+ steer(message) {
204
+ deliver("steer", message);
205
+ },
206
+ inject(message) {
207
+ deliver("inject", message);
208
+ }
209
+ };
210
+ record = {
211
+ originals,
212
+ wrappers,
213
+ owners: 1
214
+ };
215
+ for (const wrapper of Object.values(wrappers)) Object.defineProperty(wrapper, DSH_SUBAGENT_REPORT_DEDUP_COMPAT_MARKER, { value: record });
216
+ try {
217
+ agent.followup = wrappers.followup;
218
+ agent.steer = wrappers.steer;
219
+ agent.inject = wrappers.inject;
220
+ patches.set(agent, record);
221
+ } catch (error) {
222
+ record.owners = 0;
223
+ for (const name of [
224
+ "followup",
225
+ "steer",
226
+ "inject"
227
+ ]) if (agent[name] === wrappers[name]) try {
228
+ agent[name] = originals[name];
229
+ } catch {}
230
+ ctx.logger.warn("[dsh-chatgpt-subscription] Could not install temporary DSH subagent dedup compatibility: " + errorMessage(error));
231
+ }
232
+ };
233
+ const unpatch = (agent) => {
234
+ const record = patches.get(agent);
235
+ if (!record) return;
236
+ patches.delete(agent);
237
+ record.owners -= 1;
238
+ if (record.owners > 0) return;
239
+ for (const name of [
240
+ "followup",
241
+ "steer",
242
+ "inject"
243
+ ]) {
244
+ if (agent[name] !== record.wrappers[name]) continue;
245
+ try {
246
+ agent[name] = record.originals[name];
247
+ } catch (error) {
248
+ ctx.logger.warn("[dsh-chatgpt-subscription] Could not remove temporary DSH subagent dedup compatibility: " + errorMessage(error));
249
+ }
250
+ }
251
+ };
252
+ for (const agent of ctx.agents.list()) patch(agent);
253
+ const disposeCreated = ctx.on("agent/created", ({ agent }) => patch(agent));
254
+ const disposeDisposed = ctx.on("agent/disposed", ({ agent }) => unpatch(agent));
255
+ return () => {
256
+ disposeDisposed();
257
+ disposeCreated();
258
+ for (const agent of [...patches.keys()]) unpatch(agent);
259
+ };
260
+ }
261
+ //#endregion
125
262
  //#region src/compat.ts
126
263
  /**
127
264
  * Compatibility constants for the ChatGPT-backed Codex flow. The backend and
@@ -293,13 +430,16 @@ var OAuthService = class {
293
430
  return this.statusFromCredentials(credentials);
294
431
  } catch {
295
432
  return {
296
- ...this.statusFromCredentials(null),
433
+ ...this.statusFromCredentials(null, false),
297
434
  error: publicError(new OAuthServiceError("storage-failed", "Secure credential storage could not be read."))
298
435
  };
299
436
  }
300
437
  }
301
438
  async startLogin() {
302
439
  this.assertAvailable();
440
+ await this.store.load().catch(() => {
441
+ throw new OAuthServiceError("storage-failed", "Secure credential storage is unavailable. Fix its ownership or permissions before signing in.");
442
+ });
303
443
  if (this.activeLogin !== null) throw new OAuthServiceError("login-active", "A ChatGPT sign-in is already in progress.");
304
444
  this.lastLoginError = void 0;
305
445
  const loginId = this.random(24).toString("base64url");
@@ -452,14 +592,14 @@ var OAuthService = class {
452
592
  if (stored === null) throw new OAuthServiceError("not-authenticated", "Sign in with ChatGPT first.");
453
593
  return stored;
454
594
  }
455
- statusFromCredentials(credentials) {
595
+ statusFromCredentials(credentials, storageAvailable = true) {
456
596
  const active = this.activeLogin;
457
597
  if (credentials === null) return {
458
598
  authenticated: false,
459
599
  account: null,
460
600
  storage: {
461
- kind: "windows-dpapi",
462
- encrypted: true
601
+ ...this.store.storage,
602
+ available: storageAvailable
463
603
  },
464
604
  login: {
465
605
  active: active !== null,
@@ -478,8 +618,8 @@ var OAuthService = class {
478
618
  tokenExpiresAt: Math.floor(credentials.expiresAt / 1e3)
479
619
  },
480
620
  storage: {
481
- kind: "windows-dpapi",
482
- encrypted: true
621
+ ...this.store.storage,
622
+ available: storageAvailable
483
623
  },
484
624
  login: {
485
625
  active: active !== null,
@@ -718,7 +858,7 @@ async function buildResponsesPayload(options, attachments, localRawImages = {})
718
858
  }
719
859
  function runCodeInstruction(tools) {
720
860
  if (!tools?.some((tool) => tool.name === "run_code")) return void 0;
721
- return "run_code compatibility rule: its code is parsed as strict JavaScript/TypeScript before execution. On Windows, do not embed PowerShell containing $, ${...}, backslashes, or here-strings in JavaScript template literals; String.raw does not disable ${...} interpolation. Prefer arrays of ordinary quoted strings joined with \"\\n\", escaping backslashes, or use a file-write tool for large scripts and then invoke pwsh.";
861
+ return "run_code compatibility rule: its code is parsed as strict JavaScript/TypeScript before execution. Shell commands are nested string data: JavaScript template literals may consume ${...}, backticks, backslashes, and escape sequences before PowerShell, Bash, or POSIX sh sees them. On Windows, avoid embedding PowerShell containing $, ${...}, backslashes, or here-strings in template literals; String.raw does not disable ${...} interpolation. On Linux, prefer ordinary quoted strings or write a script file before invoking bash/sh, especially for commands containing backticks or ${...}. Prefer arrays of ordinary quoted strings joined with \"\\n\", escaping backslashes, or use a file-write tool for large scripts.";
722
862
  }
723
863
  function localRawImageInstruction(stats) {
724
864
  if (stats.failed === 0) return void 0;
@@ -728,18 +868,25 @@ function supportsImageInput(options) {
728
868
  return options.provider === "codex-chatgpt" && options.model.toLowerCase().startsWith("gpt-");
729
869
  }
730
870
  function toolDescriptionForCodex(name, description) {
731
- if (name === "run_code") return `${description}\n\nCompatibility: code is strict JavaScript/TypeScript. When composing PowerShell, avoid JavaScript template literals containing $, \${...}, Windows backslashes, or PowerShell here-strings. Prefer ordinary quoted string arrays joined with "\\n", or write a script file with a dedicated file tool before invoking pwsh.`;
871
+ if (name === "run_code") return `${description}\n\nCompatibility: code is strict JavaScript/TypeScript and nested shell commands are string data. Template literals may consume \${...}, backticks, backslashes, and escape sequences before PowerShell, Bash, or POSIX sh sees them. Prefer ordinary quoted string arrays joined with "\\n", or write a script file with a dedicated file tool before invoking the shell.`;
732
872
  if (isCommandTool(name)) return `${description}\n\n${commandToolCompatibilityText(name)}`;
733
873
  return description;
734
874
  }
735
875
  function commandToolInstruction(tools) {
736
876
  const names = tools?.filter((tool) => isCommandTool(tool.name)).map((tool) => tool.name);
737
877
  if (!names?.length) return void 0;
738
- return `Command tool compatibility rule (${[...new Set(names)].join(", ")}): each command call runs in a fresh process, so do not rely on cd, aliases, functions, or variables from previous calls; set workdir when the tool supports it. On Windows/pwsh, keep commands in native PowerShell syntax and native Windows paths. For deletion or move operations, first resolve and verify exact absolute target paths, then operate on those literal paths only; avoid dynamically deleting paths built from $HOME, wildcards, command substitution, or another shell's output. Treat [auto-mode hard deny] and similar policy denials as non-retriable; choose a safer non-destructive inspection or report the limitation instead of repeating the same command or adding sandbox escalation. If downloads fail with TLS credential or connection-closed errors, treat that as an environment/network failure and use local sources or report the limitation instead of cycling through equivalent download commands.`;
878
+ const uniqueNames = [...new Set(names)];
879
+ const normalized = uniqueNames.map((name) => name.toLowerCase());
880
+ const shellGuidance = [
881
+ normalized.some((name) => name === "pwsh" || name.includes("powershell")) ? "For pwsh/PowerShell, use native PowerShell syntax and native Windows paths." : void 0,
882
+ normalized.includes("bash") ? "For bash, use native POSIX paths and Bash syntax in a fresh non-interactive process." : void 0,
883
+ normalized.some((name) => name === "sh" || name === "shell") ? "For sh/generic shell, prefer portable POSIX syntax and avoid Bash-only arrays, [[ ... ]], process substitution, and source." : void 0
884
+ ].filter((value) => value !== void 0).join(" ");
885
+ return `Command tool compatibility rule (${uniqueNames.join(", ")}): each command call runs in a fresh process, so do not rely on cd, aliases, functions, or variables from previous calls; set workdir when the tool supports it. ${shellGuidance} For deletion or move operations, first resolve and verify exact absolute target paths, then operate on those literal paths only; avoid dynamically deleting paths built from home-directory expansion, wildcards, command substitution, or another shell's output. Treat [auto-mode hard deny] and similar policy denials as non-retriable; choose a safer non-destructive inspection or report the limitation instead of repeating the same command or adding sandbox escalation. If downloads fail with TLS credential or connection-closed errors, treat that as an environment/network failure and use local sources or report the limitation instead of cycling through equivalent download commands.`;
739
886
  }
740
887
  function commandToolCompatibilityText(name) {
741
888
  const shell = name.toLowerCase();
742
- return `Compatibility: command execution is stateless between calls.${shell === "pwsh" || shell.includes("powershell") ? " Use native PowerShell syntax and native Windows paths; prefer workdir over cd because every call starts a fresh process." : " Prefer workdir over cd because every call starts a fresh process."} For destructive operations, verify exact absolute targets first and use literal paths; policy hard-deny results require a safer command shape, not sandbox escalation.`;
889
+ return `Compatibility: command execution is stateless between calls.${shell === "pwsh" || shell.includes("powershell") ? " Use native PowerShell syntax and native Windows paths." : shell === "bash" ? " Use Bash syntax and native POSIX paths." : " Use portable POSIX syntax and native POSIX paths; avoid Bash-only arrays, [[ ... ]], process substitution, and source."} Prefer workdir over cd because every call starts a fresh process. For destructive operations, verify exact absolute targets first and use literal paths; policy hard-deny results require a safer command shape, not sandbox escalation.`;
743
890
  }
744
891
  function sandboxToolInstruction(tools, sandboxRetryTools) {
745
892
  if (!tools?.some((tool) => hasSandboxControls(tool.parameters))) return void 0;
@@ -761,7 +908,7 @@ function toolParametersForCodex(toolName, parameters, allowSandboxRetry) {
761
908
  const code = record$2(properties.code);
762
909
  if (code !== null) {
763
910
  const current = typeof code.description === "string" ? code.description.trim() : "";
764
- const compatibility = "Strict JavaScript/TypeScript source. For PowerShell on Windows, avoid JavaScript template literals containing $, ${...}, backslashes, or here-strings; String.raw still performs ${...} interpolation. Prefer ordinary quoted string arrays joined with \"\\n\" and escape backslashes, or write a script file with a dedicated file tool.";
911
+ const compatibility = "Strict JavaScript/TypeScript source. Nested shell commands are string data: template literals may consume ${...}, backticks, backslashes, and escape sequences before PowerShell, Bash, or POSIX sh sees them; String.raw still performs ${...} interpolation. Prefer ordinary quoted string arrays joined with \"\\n\", or write a script file with a dedicated file tool.";
765
912
  code.description = current ? `${current}\n\n${compatibility}` : compatibility;
766
913
  }
767
914
  }
@@ -784,7 +931,7 @@ function appendPropertyDescription(value, addition) {
784
931
  }
785
932
  function isCommandTool(name) {
786
933
  const normalized = name.toLowerCase();
787
- return normalized === "pwsh" || normalized === "powershell" || normalized === "bash" || normalized === "shell";
934
+ return normalized === "pwsh" || normalized === "powershell" || normalized === "bash" || normalized === "sh" || normalized === "shell";
788
935
  }
789
936
  function hasSandboxControls(parameters) {
790
937
  const properties = record$2(parameters.properties);
@@ -828,7 +975,7 @@ function appendMissingToolCalls(input, knownToolCalls, message) {
828
975
  }
829
976
  function runCodeErrorOutput(output) {
830
977
  if (!isRunCodeParserError(output)) return output;
831
- return `${output}\n\nCompatibility hint: run_code failed while parsing strict JavaScript/TypeScript, before the nested tool ran. Avoid JavaScript template literals for PowerShell containing $, \${...}, Windows backslashes, or here-strings; String.raw does not prevent \${...} interpolation. Build the script from ordinary quoted strings joined with "\\n" (escaping backslashes), or write a script file with a dedicated file tool and then invoke pwsh.`;
978
+ return `${output}\n\nCompatibility hint: run_code failed while parsing strict JavaScript/TypeScript, before the nested tool ran. Shell commands are nested string data; template literals can consume \${...}, backticks, backslashes, and escape sequences before PowerShell, Bash, or POSIX sh sees them, and String.raw does not prevent \${...} interpolation. Build the script from ordinary quoted strings joined with "\\n", or write a script file with a dedicated file tool and then invoke the shell.`;
832
979
  }
833
980
  function isRunCodeParserError(output) {
834
981
  return /(?:Legacy octal escape is not permitted in strict mode|Unexpected token|Invalid or unexpected token|Unterminated template|Expected ['"]?\}['"]?)/i.test(output);
@@ -1833,6 +1980,100 @@ function parseStoredCredentials(value) {
1833
1980
  };
1834
1981
  }
1835
1982
  //#endregion
1983
+ //#region src/host/token-store-linux.ts
1984
+ const DIRECTORY_MODE = 448;
1985
+ const FILE_MODE = 384;
1986
+ function defaultLinuxCredentialPath() {
1987
+ return join(process.env.DSH_HOME?.trim() || join(homedir(), ".dsh"), "storages", "dsh-chatgpt-subscription", "oauth.json");
1988
+ }
1989
+ /**
1990
+ * Linux credential storage protected by owner-only filesystem permissions.
1991
+ * The payload is not encrypted at rest, so callers must report that distinction
1992
+ * instead of presenting this store as equivalent to Windows DPAPI.
1993
+ */
1994
+ var LinuxFileTokenStore = class {
1995
+ path;
1996
+ storage = {
1997
+ kind: "linux-file",
1998
+ encrypted: false
1999
+ };
2000
+ noFollow = constants.O_NOFOLLOW;
2001
+ constructor(path = defaultLinuxCredentialPath()) {
2002
+ this.path = path;
2003
+ if (process.platform !== "linux") throw new Error("Linux credential storage requires Linux");
2004
+ if (this.noFollow === void 0) throw new Error("Linux credential storage requires O_NOFOLLOW support");
2005
+ if (dirname(path) === path) throw new Error("invalid Linux credential path");
2006
+ }
2007
+ async load() {
2008
+ let handle;
2009
+ try {
2010
+ handle = await open(this.path, constants.O_RDONLY | this.noFollow);
2011
+ } catch (error) {
2012
+ if (isMissing(error)) return null;
2013
+ throw new Error("Linux credential read failed", { cause: error });
2014
+ }
2015
+ try {
2016
+ const stats = await handle.stat();
2017
+ if (!stats.isFile()) throw new Error("credential path is not a regular file");
2018
+ if (typeof process.getuid === "function" && stats.uid !== process.getuid()) throw new Error("credential file is owned by another user");
2019
+ if ((stats.mode & 511) !== FILE_MODE) throw new Error("credential file permissions must be 0600");
2020
+ const payload = await handle.readFile({ encoding: "utf8" });
2021
+ return parseStoredCredentials(JSON.parse(payload));
2022
+ } catch (error) {
2023
+ throw new Error("Linux credential payload is invalid or insecure", { cause: error });
2024
+ } finally {
2025
+ await handle.close();
2026
+ }
2027
+ }
2028
+ async save(value) {
2029
+ const directory = dirname(this.path);
2030
+ const temporary = `${this.path}.tmp-${randomUUID()}`;
2031
+ try {
2032
+ const existing = await lstat(this.path);
2033
+ if (existing.isSymbolicLink() || !existing.isFile()) throw new Error("credential path is not a regular file");
2034
+ assertOwnedByCurrentUser(existing.uid, "credential file");
2035
+ } catch (error) {
2036
+ if (!isMissing(error)) throw new Error("Linux credential write failed", { cause: error });
2037
+ }
2038
+ await mkdir(directory, {
2039
+ recursive: true,
2040
+ mode: DIRECTORY_MODE
2041
+ });
2042
+ const directoryStats = await stat(directory);
2043
+ if (!directoryStats.isDirectory()) throw new Error("Linux credential directory is invalid");
2044
+ assertOwnedByCurrentUser(directoryStats.uid, "credential directory");
2045
+ await chmod(directory, DIRECTORY_MODE);
2046
+ let handle;
2047
+ try {
2048
+ handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, FILE_MODE);
2049
+ await handle.writeFile(JSON.stringify(value), { encoding: "utf8" });
2050
+ await handle.sync();
2051
+ await handle.close();
2052
+ handle = void 0;
2053
+ await rename(temporary, this.path);
2054
+ await chmod(this.path, FILE_MODE);
2055
+ } catch (error) {
2056
+ await handle?.close().catch(() => void 0);
2057
+ await unlink(temporary).catch(() => void 0);
2058
+ throw new Error("Linux credential write failed", { cause: error });
2059
+ }
2060
+ }
2061
+ async clear() {
2062
+ try {
2063
+ await unlink(this.path);
2064
+ } catch (error) {
2065
+ if (isMissing(error)) return;
2066
+ throw new Error("Linux credential deletion failed", { cause: error });
2067
+ }
2068
+ }
2069
+ };
2070
+ function assertOwnedByCurrentUser(owner, label) {
2071
+ if (typeof process.getuid === "function" && owner !== process.getuid()) throw new Error(`${label} is owned by another user`);
2072
+ }
2073
+ function isMissing(error) {
2074
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
2075
+ }
2076
+ //#endregion
1836
2077
  //#region src/host/token-store-windows.ts
1837
2078
  const PROTECT_SCRIPT = String.raw`
1838
2079
  $ErrorActionPreference = 'Stop'
@@ -1866,6 +2107,10 @@ function defaultDpapiCredentialPath() {
1866
2107
  }
1867
2108
  var WindowsDpapiTokenStore = class {
1868
2109
  path;
2110
+ storage = {
2111
+ kind: "windows-dpapi",
2112
+ encrypted: true
2113
+ };
1869
2114
  constructor(path = defaultDpapiCredentialPath()) {
1870
2115
  this.path = path;
1871
2116
  if (process.platform !== "win32") throw new Error("Windows DPAPI storage requires Windows");
@@ -1938,14 +2183,22 @@ function runPowerShell(script, path, stdin) {
1938
2183
  });
1939
2184
  }
1940
2185
  //#endregion
2186
+ //#region src/host/platform-token-store.ts
2187
+ function createPlatformTokenStore(platform = process.platform) {
2188
+ if (platform === "win32") return new WindowsDpapiTokenStore();
2189
+ if (platform === "linux") return new LinuxFileTokenStore();
2190
+ throw new Error(`Unsupported platform ${platform}; dsh-chatgpt-subscription supports Windows and Linux.`);
2191
+ }
2192
+ //#endregion
1941
2193
  //#region src/index.ts
1942
2194
  const inject = [
1943
2195
  "webServer",
1944
2196
  "llm",
1945
- "attachments"
2197
+ "attachments",
2198
+ "agents"
1946
2199
  ];
1947
2200
  function apply(ctx) {
1948
- const oauth = new OAuthService(new WindowsDpapiTokenStore(), { logger: ctx.logger });
2201
+ const oauth = new OAuthService(createPlatformTokenStore(), { logger: ctx.logger });
1949
2202
  const usage = new UsageService(oauth);
1950
2203
  const adapter = new CodexChatGptAdapter(new ResponsesClient(oauth, ctx.attachments, {
1951
2204
  localRawImages: { baseUrl: localWebServerBaseUrl(ctx.webServer.host, ctx.webServer.port) },
@@ -1954,7 +2207,9 @@ function apply(ctx) {
1954
2207
  ctx.effect(() => {
1955
2208
  const disposeRoutes = registerRoutes(ctx, oauth, usage);
1956
2209
  const disposeAdapter = ctx.llm.registerAdapter([PROVIDER_ID], adapter);
2210
+ const disposeSubagentReportCompat = installSubagentReportDedupCompat(ctx);
1957
2211
  return () => {
2212
+ disposeSubagentReportCompat();
1958
2213
  disposeAdapter();
1959
2214
  disposeRoutes();
1960
2215
  oauth.dispose();
@@ -1965,4 +2220,4 @@ function localWebServerBaseUrl(host, port) {
1965
2220
  return `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${port}`;
1966
2221
  }
1967
2222
  //#endregion
1968
- export { CodexChatGptAdapter, OAuthService, ResponsesClient, UsageService, apply, inject, mapCodexUsage, parseResponsesStream };
2223
+ export { CodexChatGptAdapter, LinuxFileTokenStore, OAuthService, ResponsesClient, UsageService, WindowsDpapiTokenStore, apply, createPlatformTokenStore, inject, mapCodexUsage, parseResponsesStream };
@@ -1,9 +1,11 @@
1
1
  import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
- import type { QuotaWindowDto } from '../shared/contracts.ts';
2
+ import type { CredentialStorageDto, QuotaWindowDto } from '../shared/contracts.ts';
3
3
  import { NS } from './locales.ts';
4
4
  type Props = PropsRuntime<'settings.section'> & PropsLocale<typeof NS>;
5
5
  type Translate = Props['t'];
6
6
  export declare function CodexSubscriptionSection({ t }: Props): React.JSX.Element;
7
+ export declare function storageLabel(storage: CredentialStorageDto | undefined, t: Translate): string;
8
+ export declare function storageNotice(storage: CredentialStorageDto | undefined, t: Translate): string;
7
9
  export declare function QuotaBar({ label, window, t }: {
8
10
  label: string;
9
11
  window: QuotaWindowDto;
@@ -1 +1 @@
1
- {"version":3,"file":"CodexSubscriptionSection.d.ts","sourceRoot":"","sources":["../../../src/client/CodexSubscriptionSection.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE7F,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAEjC,KAAK,KAAK,GAAG,YAAY,CAAC,kBAAkB,CAAC,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;AAEtE,KAAK,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;AAI3B,wBAAgB,wBAAwB,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAoMxE;AAyBD,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAczH;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAQxE;AAWD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUnD"}
1
+ {"version":3,"file":"CodexSubscriptionSection.d.ts","sourceRoot":"","sources":["../../../src/client/CodexSubscriptionSection.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,EAAE,oBAAoB,EAAmC,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEnH,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAEjC,KAAK,KAAK,GAAG,YAAY,CAAC,kBAAkB,CAAC,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;AAEtE,KAAK,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;AAI3B,wBAAgB,wBAAwB,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAoMxE;AAiBD,wBAAgB,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAM5F;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAM7F;AAUD,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAczH;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAQxE;AAWD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAI/D,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,0BAA0B,EAAE,SAAS,CAAA;KACtC;CACF;AAED,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAW9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAG/D,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,0BAA0B,EAAE,SAAS,CAAA;KACtC;CACF;AAED,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAU9C"}
@@ -9,8 +9,14 @@ export declare const zh: {
9
9
  readonly accountId: "账号 ID";
10
10
  readonly expires: "令牌到期";
11
11
  readonly storage: "凭据存储";
12
- readonly storageValue: "Windows DPAPI(当前用户加密)";
13
- readonly securityNotice: "令牌仅保存在 Host 端的 DPAPI 加密文件中,不会进入浏览器、settings.yaml 或日志。";
12
+ readonly storageWindows: "Windows DPAPI(当前用户加密)";
13
+ readonly storageLinuxFile: "Linux 用户私有文件(权限 0600)";
14
+ readonly storageMemory: "仅 Host 内存(不持久化)";
15
+ readonly storageUnavailable: "凭据存储不可用";
16
+ readonly securityWindows: "令牌 Windows CurrentUser DPAPI 加密。";
17
+ readonly securityLinuxFile: "令牌仅写入 Host 上当前 Linux 用户可读的 0600 文件。";
18
+ readonly securityMemory: "令牌仅保留在 Host 内存中,Host 退出后丢失。";
19
+ readonly securityUnavailable: "Host 无法安全访问凭据存储;请修复文件所有者或权限后重试。";
14
20
  readonly signIn: "使用 ChatGPT 登录";
15
21
  readonly signInAgain: "重新登录";
16
22
  readonly cancel: "取消登录";
@@ -60,8 +66,14 @@ export declare const dictionaries: {
60
66
  readonly accountId: "账号 ID";
61
67
  readonly expires: "令牌到期";
62
68
  readonly storage: "凭据存储";
63
- readonly storageValue: "Windows DPAPI(当前用户加密)";
64
- readonly securityNotice: "令牌仅保存在 Host 端的 DPAPI 加密文件中,不会进入浏览器、settings.yaml 或日志。";
69
+ readonly storageWindows: "Windows DPAPI(当前用户加密)";
70
+ readonly storageLinuxFile: "Linux 用户私有文件(权限 0600)";
71
+ readonly storageMemory: "仅 Host 内存(不持久化)";
72
+ readonly storageUnavailable: "凭据存储不可用";
73
+ readonly securityWindows: "令牌由 Host 使用 Windows CurrentUser DPAPI 加密,不会进入浏览器、settings.yaml 或日志。";
74
+ readonly securityLinuxFile: "令牌仅写入 Host 上当前 Linux 用户可读的 0600 文件,但不会额外加密;同 UID 进程、root、备份和磁盘快照仍可能读取。";
75
+ readonly securityMemory: "令牌仅保留在 Host 内存中,Host 退出后丢失。";
76
+ readonly securityUnavailable: "Host 无法安全访问凭据存储;请修复文件所有者或权限后重试。";
65
77
  readonly signIn: "使用 ChatGPT 登录";
66
78
  readonly signInAgain: "重新登录";
67
79
  readonly cancel: "取消登录";
@@ -98,6 +110,6 @@ export declare const dictionaries: {
98
110
  readonly retry: "重试";
99
111
  readonly unknown: "未知";
100
112
  };
101
- en: Record<"title" | "intro" | "account" | "signedOut" | "signedIn" | "plan" | "accountId" | "expires" | "storage" | "storageValue" | "securityNotice" | "signIn" | "signInAgain" | "cancel" | "signOut" | "refreshToken" | "pending" | "popupBlocked" | "continueLogin" | "loading" | "connection" | "provider" | "connectionState" | "connected" | "untested" | "testConnection" | "testing" | "latency" | "models" | "quota" | "quotaIntro" | "refreshQuota" | "refreshing" | "noQuota" | "quotaSignedOut" | "stale" | "updated" | "primary" | "secondary" | "limitWindow" | "used" | "remaining" | "exhausted" | "resets" | "retry" | "unknown", string>;
113
+ en: Record<"quota" | "account" | "storage" | "stale" | "pending" | "title" | "intro" | "signedOut" | "signedIn" | "plan" | "accountId" | "expires" | "storageWindows" | "storageLinuxFile" | "storageMemory" | "storageUnavailable" | "securityWindows" | "securityLinuxFile" | "securityMemory" | "securityUnavailable" | "signIn" | "signInAgain" | "cancel" | "signOut" | "refreshToken" | "popupBlocked" | "continueLogin" | "loading" | "connection" | "provider" | "connectionState" | "connected" | "untested" | "testConnection" | "testing" | "latency" | "models" | "quotaIntro" | "refreshQuota" | "refreshing" | "noQuota" | "quotaSignedOut" | "updated" | "primary" | "secondary" | "limitWindow" | "used" | "remaining" | "exhausted" | "resets" | "retry" | "unknown", string>;
102
114
  };
103
115
  //# sourceMappingURL=locales.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE,EAAG,0BAAmC,CAAA;AAErD,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CL,CAAA;AAEV,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,CA+C9C,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,EAAE,CAAA;AACvC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAa,CAAA"}
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE,EAAG,0BAAmC,CAAA;AAErD,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDL,CAAA;AAEV,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,CAqD9C,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,EAAE,CAAA;AACvC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAa,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/client/styles.ts"],"names":[],"mappings":"AAwDA,wBAAgB,aAAa,IAAI,MAAM,IAAI,CAQ1C"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/client/styles.ts"],"names":[],"mappings":"AAiDA,wBAAgB,aAAa,IAAI,MAAM,IAAI,CAQ1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-service.d.ts","sourceRoot":"","sources":["../../../src/host/oauth-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oauth-service.d.ts","sourceRoot":"","sources":["../../../src/host/oauth-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TokenStore } from './token-store.ts';
2
+ export declare function createPlatformTokenStore(platform?: NodeJS.Platform): TokenStore;
3
+ //# sourceMappingURL=platform-token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-token-store.d.ts","sourceRoot":"","sources":["../../../src/host/platform-token-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,wBAAgB,wBAAwB,CAAC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,UAAU,CAIjG"}
@@ -0,0 +1,21 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ /**
3
+ * DSH_COMPAT_REMOVE(subagent-report-settlement-dedup)
4
+ *
5
+ * Temporary compatibility shim for DSH 0.1.0-rc.6. A continuable child is told
6
+ * to report its result before finishing, while DSH also unconditionally sends
7
+ * the same closing output in a `subagent-settled` notice. The report is often
8
+ * still queued when the settlement reaches the parent, so the parent sees the
9
+ * result once and the equivalent report remains as duplicate next-turn work.
10
+ *
11
+ * Remove this module, its installation in `src/index.ts`, and its focused test
12
+ * once upstream coalesces an equivalent final report with settlement delivery.
13
+ */
14
+ export declare const DSH_SUBAGENT_REPORT_DEDUP_COMPAT_MARKER: "__dshChatgptSubscriptionSubagentReportDedupCompatV1";
15
+ /**
16
+ * Discard only an exact, same-child report duplicate immediately before DSH
17
+ * delivers the corresponding settlement notice. Partial reports, reports with
18
+ * different content, and all unrelated inbox work remain untouched.
19
+ */
20
+ export declare function installSubagentReportDedupCompat(ctx: Context): () => void;
21
+ //# sourceMappingURL=subagent-report-scheduling-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-report-scheduling-compat.d.ts","sourceRoot":"","sources":["../../../src/host/subagent-report-scheduling-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uCAAuC,EAClD,qDAA8D,CAAA;AA4EhE;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,IAAI,CAyGzE"}
@@ -0,0 +1,20 @@
1
+ import type { TokenStore, StoredOAuthCredentials } from './token-store.ts';
2
+ export declare function defaultLinuxCredentialPath(): string;
3
+ /**
4
+ * Linux credential storage protected by owner-only filesystem permissions.
5
+ * The payload is not encrypted at rest, so callers must report that distinction
6
+ * instead of presenting this store as equivalent to Windows DPAPI.
7
+ */
8
+ export declare class LinuxFileTokenStore implements TokenStore {
9
+ private readonly path;
10
+ readonly storage: {
11
+ readonly kind: "linux-file";
12
+ readonly encrypted: false;
13
+ };
14
+ private readonly noFollow;
15
+ constructor(path?: string);
16
+ load(): Promise<StoredOAuthCredentials | null>;
17
+ save(value: StoredOAuthCredentials): Promise<void>;
18
+ clear(): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=token-store-linux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store-linux.d.ts","sourceRoot":"","sources":["../../../src/host/token-store-linux.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAM1E,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,YAAW,UAAU;IAIxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,OAAO;;;MAAoD;IACpE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;gBAEnB,IAAI,SAA+B;IAM1D,IAAI,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IA2B9C,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
@@ -2,6 +2,10 @@ import type { TokenStore, StoredOAuthCredentials } from './token-store.ts';
2
2
  export declare function defaultDpapiCredentialPath(): string;
3
3
  export declare class WindowsDpapiTokenStore implements TokenStore {
4
4
  private readonly path;
5
+ readonly storage: {
6
+ readonly kind: "windows-dpapi";
7
+ readonly encrypted: true;
8
+ };
5
9
  constructor(path?: string);
6
10
  load(): Promise<StoredOAuthCredentials | null>;
7
11
  save(value: StoredOAuthCredentials): Promise<void>;
@@ -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;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,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,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,3 +1,4 @@
1
+ import type { CredentialStorageDto } from '../shared/contracts.ts';
1
2
  export interface StoredOAuthCredentials {
2
3
  accessToken: string;
3
4
  refreshToken: string;
@@ -8,12 +9,17 @@ export interface StoredOAuthCredentials {
8
9
  planType?: string;
9
10
  }
10
11
  export interface TokenStore {
12
+ readonly storage: Omit<CredentialStorageDto, 'available'>;
11
13
  load(): Promise<StoredOAuthCredentials | null>;
12
14
  save(value: StoredOAuthCredentials): Promise<void>;
13
15
  clear(): Promise<void>;
14
16
  }
15
17
  /** Test seam and non-persistent development store. Never used by apply(). */
16
18
  export declare class MemoryTokenStore implements TokenStore {
19
+ readonly storage: {
20
+ readonly kind: "memory";
21
+ readonly encrypted: false;
22
+ };
17
23
  private value;
18
24
  load(): Promise<StoredOAuthCredentials | null>;
19
25
  save(value: StoredOAuthCredentials): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../src/host/token-store.ts"],"names":[],"mappings":"AAAA,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,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,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,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"}
@@ -5,5 +5,8 @@ export { OAuthService } from './host/oauth-service.ts';
5
5
  export { CodexChatGptAdapter } from './host/adapter.ts';
6
6
  export { ResponsesClient, parseResponsesStream } from './host/responses-client.ts';
7
7
  export { UsageService, mapCodexUsage } from './host/usage-service.ts';
8
+ export { createPlatformTokenStore } from './host/platform-token-store.ts';
9
+ export { LinuxFileTokenStore } from './host/token-store-linux.ts';
10
+ export { WindowsDpapiTokenStore } from './host/token-store-windows.ts';
8
11
  export type { TokenStore, StoredOAuthCredentials } from './host/token-store.ts';
9
12
  //# sourceMappingURL=index.d.ts.map