openllmprovider 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +192 -0
  2. package/dist/auth/index.cjs +6 -0
  3. package/dist/auth/index.d.cts +3 -0
  4. package/dist/auth/index.d.mts +3 -0
  5. package/dist/auth/index.mjs +3 -0
  6. package/dist/auto-C2hXJY13.d.cts +33 -0
  7. package/dist/auto-C2hXJY13.d.cts.map +1 -0
  8. package/dist/auto-CBqNYBXs.mjs +48 -0
  9. package/dist/auto-CBqNYBXs.mjs.map +1 -0
  10. package/dist/auto-CInerwvs.d.mts +33 -0
  11. package/dist/auto-CInerwvs.d.mts.map +1 -0
  12. package/dist/auto-D77wgMqO.cjs +59 -0
  13. package/dist/auto-D77wgMqO.cjs.map +1 -0
  14. package/dist/file-DB-rxfzi.mjs +77 -0
  15. package/dist/file-DB-rxfzi.mjs.map +1 -0
  16. package/dist/file-DZ7FGcSW.cjs +73 -0
  17. package/dist/file-DZ7FGcSW.cjs.map +1 -0
  18. package/dist/index.cjs +1909 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.cts +1239 -0
  21. package/dist/index.d.cts.map +1 -0
  22. package/dist/index.d.mts +1241 -0
  23. package/dist/index.d.mts.map +1 -0
  24. package/dist/index.mjs +1891 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/logger-BsHpI_fH.mjs +11 -0
  27. package/dist/logger-BsHpI_fH.mjs.map +1 -0
  28. package/dist/logger-jRimlMFR.cjs +69 -0
  29. package/dist/logger-jRimlMFR.cjs.map +1 -0
  30. package/dist/plugin/index.cjs +29 -0
  31. package/dist/plugin/index.cjs.map +1 -0
  32. package/dist/plugin/index.d.cts +10 -0
  33. package/dist/plugin/index.d.cts.map +1 -0
  34. package/dist/plugin/index.d.mts +10 -0
  35. package/dist/plugin/index.d.mts.map +1 -0
  36. package/dist/plugin/index.mjs +25 -0
  37. package/dist/plugin/index.mjs.map +1 -0
  38. package/dist/plugin-BkeUu5LW.d.mts +46 -0
  39. package/dist/plugin-BkeUu5LW.d.mts.map +1 -0
  40. package/dist/plugin-wK7RmJhZ.d.cts +46 -0
  41. package/dist/plugin-wK7RmJhZ.d.cts.map +1 -0
  42. package/dist/resolver-BA7LWSJO.mjs +645 -0
  43. package/dist/resolver-BA7LWSJO.mjs.map +1 -0
  44. package/dist/resolver-BMTvzTt9.cjs +662 -0
  45. package/dist/resolver-BMTvzTt9.cjs.map +1 -0
  46. package/dist/resolver-MgJryMWG.d.cts +75 -0
  47. package/dist/resolver-MgJryMWG.d.cts.map +1 -0
  48. package/dist/resolver-_gfXzr_S.d.mts +76 -0
  49. package/dist/resolver-_gfXzr_S.d.mts.map +1 -0
  50. package/dist/storage/index.cjs +7 -0
  51. package/dist/storage/index.d.cts +12 -0
  52. package/dist/storage/index.d.cts.map +1 -0
  53. package/dist/storage/index.d.mts +12 -0
  54. package/dist/storage/index.d.mts.map +1 -0
  55. package/dist/storage/index.mjs +4 -0
  56. package/package.json +137 -0
  57. package/src/auth/.gitkeep +0 -0
  58. package/src/auth/index.ts +10 -0
  59. package/src/auth/resolver.ts +46 -0
  60. package/src/auth/scanners.ts +462 -0
  61. package/src/auth/store.ts +357 -0
  62. package/src/catalog/.gitkeep +0 -0
  63. package/src/catalog/catalog.ts +302 -0
  64. package/src/catalog/index.ts +17 -0
  65. package/src/catalog/mapper.ts +129 -0
  66. package/src/catalog/merger.ts +99 -0
  67. package/src/index.ts +37 -0
  68. package/src/logger.ts +7 -0
  69. package/src/plugin/.gitkeep +0 -0
  70. package/src/plugin/anthropic.test.ts +505 -0
  71. package/src/plugin/anthropic.ts +324 -0
  72. package/src/plugin/codex.ts +656 -0
  73. package/src/plugin/copilot.ts +161 -0
  74. package/src/plugin/google.ts +454 -0
  75. package/src/plugin/index.ts +30 -0
  76. package/src/provider/.gitkeep +0 -0
  77. package/src/provider/bundled.ts +59 -0
  78. package/src/provider/index.ts +249 -0
  79. package/src/provider/state.ts +163 -0
  80. package/src/storage/.gitkeep +0 -0
  81. package/src/storage/auto.ts +32 -0
  82. package/src/storage/file.ts +84 -0
  83. package/src/storage/index.ts +10 -0
  84. package/src/storage/memory.ts +23 -0
  85. package/src/types/.gitkeep +0 -0
  86. package/src/types/auth.ts +18 -0
  87. package/src/types/errors.ts +87 -0
  88. package/src/types/index.ts +26 -0
  89. package/src/types/model.ts +88 -0
  90. package/src/types/plugin.ts +49 -0
  91. package/src/types/provider.ts +48 -0
@@ -0,0 +1,662 @@
1
+ const require_logger = require('./logger-jRimlMFR.cjs');
2
+ const require_auto = require('./auto-D77wgMqO.cjs');
3
+
4
+ //#region src/auth/scanners.ts
5
+ const log$2 = require_logger.createLogger("auth:scanners");
6
+ function createNodeScanContext() {
7
+ return {
8
+ async readFile(path) {
9
+ try {
10
+ return await (await import("node:fs/promises")).readFile(path, "utf-8");
11
+ } catch {
12
+ return;
13
+ }
14
+ },
15
+ homedir() {
16
+ return process.env.HOME ?? process.env.USERPROFILE ?? "";
17
+ },
18
+ platform() {
19
+ return process.platform;
20
+ },
21
+ env(name) {
22
+ return process.env[name];
23
+ },
24
+ async exec(command) {
25
+ try {
26
+ const { execSync } = await import("node:child_process");
27
+ return execSync(command, {
28
+ encoding: "utf-8",
29
+ timeout: 5e3,
30
+ stdio: [
31
+ "pipe",
32
+ "pipe",
33
+ "pipe"
34
+ ]
35
+ }).trim();
36
+ } catch {
37
+ return;
38
+ }
39
+ }
40
+ };
41
+ }
42
+ function join(base, ...segments) {
43
+ return [base, ...segments].join("/");
44
+ }
45
+ function parseJson(raw) {
46
+ try {
47
+ const parsed = JSON.parse(raw);
48
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
49
+ } catch {
50
+ return;
51
+ }
52
+ }
53
+ function stripJsonComments(raw) {
54
+ return raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
55
+ }
56
+ async function readJson(ctx, path) {
57
+ const raw = await ctx.readFile(path);
58
+ if (!raw) return void 0;
59
+ return parseJson(raw) ?? parseJson(stripJsonComments(raw));
60
+ }
61
+ function configDir(ctx) {
62
+ const xdg = ctx.env("XDG_CONFIG_HOME");
63
+ if (xdg) return xdg;
64
+ return join(ctx.homedir(), ".config");
65
+ }
66
+ const copilotScanner = {
67
+ name: "github-copilot",
68
+ async scan(ctx) {
69
+ const results = [];
70
+ const base = join(configDir(ctx), "github-copilot");
71
+ for (const file of ["hosts.json", "apps.json"]) {
72
+ const path = join(base, file);
73
+ const json = await readJson(ctx, path);
74
+ if (!json) continue;
75
+ for (const [key, value] of Object.entries(json)) {
76
+ if (!key.includes("github.com")) continue;
77
+ const token = value && typeof value === "object" ? value.oauth_token : void 0;
78
+ if (typeof token === "string" && token.length > 0) {
79
+ log$2("copilot: found token in %s", path);
80
+ results.push({
81
+ providerId: "github-copilot",
82
+ source: path,
83
+ key: token
84
+ });
85
+ return results;
86
+ }
87
+ }
88
+ }
89
+ return results;
90
+ }
91
+ };
92
+ const claudeCodeScanner = {
93
+ name: "claude-code",
94
+ async scan(ctx) {
95
+ const results = [];
96
+ const base = join(ctx.homedir(), ".claude");
97
+ for (const file of ["settings.json", "settings.local.json"]) {
98
+ const path = join(base, file);
99
+ const json = await readJson(ctx, path);
100
+ if (!json) continue;
101
+ for (const field of [
102
+ "anthropicApiKey",
103
+ "anthropic_api_key",
104
+ "ANTHROPIC_API_KEY",
105
+ "apiKey"
106
+ ]) {
107
+ const value = json[field];
108
+ if (typeof value === "string" && value.length > 0) {
109
+ log$2("claude-code: found key in %s (%s)", path, field);
110
+ results.push({
111
+ providerId: "anthropic",
112
+ source: path,
113
+ key: value
114
+ });
115
+ return results;
116
+ }
117
+ }
118
+ }
119
+ return results;
120
+ }
121
+ };
122
+ const codexCliScanner = {
123
+ name: "codex-cli",
124
+ async scan(ctx) {
125
+ const results = [];
126
+ const authPath = join(ctx.homedir(), ".codex", "auth.json");
127
+ const json = await readJson(ctx, authPath);
128
+ if (!json) return results;
129
+ const apiKey = json.OPENAI_API_KEY;
130
+ if (typeof apiKey === "string" && apiKey.length > 0) {
131
+ log$2("codex-cli: found OPENAI_API_KEY in %s", authPath);
132
+ results.push({
133
+ providerId: "openai",
134
+ source: authPath,
135
+ key: apiKey,
136
+ credentialType: "api"
137
+ });
138
+ return results;
139
+ }
140
+ const tokens = json.tokens;
141
+ if (tokens !== null && typeof tokens === "object" && !Array.isArray(tokens)) {
142
+ const t = tokens;
143
+ const accessToken = t.access_token;
144
+ if (typeof accessToken === "string" && accessToken.length > 0) {
145
+ const refreshToken = typeof t.refresh_token === "string" ? t.refresh_token : void 0;
146
+ const accountId = typeof t.account_id === "string" ? t.account_id : void 0;
147
+ log$2("codex-cli: found OAuth tokens in %s", authPath);
148
+ results.push({
149
+ providerId: "openai",
150
+ source: authPath,
151
+ key: accessToken,
152
+ credentialType: "oauth",
153
+ refresh: refreshToken,
154
+ accountId
155
+ });
156
+ return results;
157
+ }
158
+ }
159
+ const token = json.token ?? json.apiKey;
160
+ if (typeof token === "string" && token.length > 0) results.push({
161
+ providerId: "openai",
162
+ source: authPath,
163
+ key: token
164
+ });
165
+ return results;
166
+ }
167
+ };
168
+ const geminiCliScanner = {
169
+ name: "gemini-cli",
170
+ async scan(ctx) {
171
+ const results = [];
172
+ const geminiHome = ctx.env("GEMINI_CLI_HOME") ?? join(ctx.homedir(), ".gemini");
173
+ for (const file of ["oauth_creds.json", "google_accounts.json"]) {
174
+ const path = join(geminiHome, file);
175
+ const json = await readJson(ctx, path);
176
+ if (!json) continue;
177
+ const accessToken = typeof json.access_token === "string" ? json.access_token : void 0;
178
+ const refreshToken = typeof json.refresh_token === "string" ? json.refresh_token : void 0;
179
+ const expiryDate = typeof json.expiry_date === "number" ? json.expiry_date : void 0;
180
+ if (accessToken || refreshToken) {
181
+ log$2("gemini-cli: found credentials in %s", path);
182
+ results.push({
183
+ providerId: "google",
184
+ source: path,
185
+ key: accessToken,
186
+ credentialType: "oauth",
187
+ refresh: refreshToken,
188
+ expires: expiryDate
189
+ });
190
+ return results;
191
+ }
192
+ if (Array.isArray(json.accounts) && json.accounts.length > 0) {
193
+ log$2("gemini-cli: found credentials in %s", path);
194
+ results.push({
195
+ providerId: "google",
196
+ source: path
197
+ });
198
+ return results;
199
+ }
200
+ }
201
+ return results;
202
+ }
203
+ };
204
+ const gcloudAdcScanner = {
205
+ name: "gcloud-adc",
206
+ async scan(ctx) {
207
+ const results = [];
208
+ const cloudSdkConfig = ctx.env("CLOUDSDK_CONFIG");
209
+ const paths = [
210
+ ctx.env("GOOGLE_APPLICATION_CREDENTIALS"),
211
+ cloudSdkConfig ? join(cloudSdkConfig, "application_default_credentials.json") : void 0,
212
+ join(configDir(ctx), "gcloud", "application_default_credentials.json")
213
+ ].filter((p) => typeof p === "string");
214
+ for (const path of paths) {
215
+ const json = await readJson(ctx, path);
216
+ if (!json) continue;
217
+ if ("refresh_token" in json || "type" in json || "private_key" in json) {
218
+ log$2("gcloud-adc: found ADC in %s", path);
219
+ results.push({
220
+ providerId: "google-vertex",
221
+ source: path
222
+ });
223
+ return results;
224
+ }
225
+ }
226
+ return results;
227
+ }
228
+ };
229
+ const awsCredentialsScanner = {
230
+ name: "aws-credentials",
231
+ async scan(ctx) {
232
+ const results = [];
233
+ const credPath = ctx.env("AWS_SHARED_CREDENTIALS_FILE") ?? join(ctx.homedir(), ".aws", "credentials");
234
+ const raw = await ctx.readFile(credPath);
235
+ if (!raw) return results;
236
+ const profile = ctx.env("AWS_PROFILE") ?? "default";
237
+ if (parseIniProfileKey(raw, profile, "aws_access_key_id")) {
238
+ log$2("aws: found credentials for profile [%s] in %s", profile, credPath);
239
+ results.push({
240
+ providerId: "amazon-bedrock",
241
+ source: credPath
242
+ });
243
+ }
244
+ return results;
245
+ }
246
+ };
247
+ const opencodeAuthScanner = {
248
+ name: "opencode-auth",
249
+ async scan(ctx) {
250
+ const results = [];
251
+ const xdgData = ctx.env("XDG_DATA_HOME");
252
+ const home = ctx.homedir();
253
+ const platform = ctx.platform();
254
+ const paths = [
255
+ xdgData ? join(xdgData, "opencode", "auth.json") : void 0,
256
+ platform === "darwin" ? join(home, "Library", "Application Support", "opencode", "auth.json") : void 0,
257
+ join(home, ".local", "share", "opencode", "auth.json"),
258
+ join(home, ".config", "opencode", "auth.json")
259
+ ].filter((p) => typeof p === "string");
260
+ for (const path of paths) {
261
+ const json = await readJson(ctx, path);
262
+ if (!json) continue;
263
+ for (const [providerId, entry] of Object.entries(json)) {
264
+ if (!entry || typeof entry !== "object") continue;
265
+ const typed = entry;
266
+ const type = typed.type;
267
+ if (type !== "api" && type !== "oauth" && type !== "wellknown") continue;
268
+ const key = typeof typed.key === "string" ? typed.key : void 0;
269
+ const refresh = typeof typed.refresh === "string" ? typed.refresh : void 0;
270
+ const accountId = typeof typed.accountId === "string" ? typed.accountId : void 0;
271
+ const expires = typeof typed.expires === "number" ? typed.expires : void 0;
272
+ log$2("opencode-auth: found %s (%s) in %s", providerId, type, path);
273
+ results.push({
274
+ providerId,
275
+ source: path,
276
+ key,
277
+ credentialType: type,
278
+ refresh,
279
+ accountId,
280
+ expires
281
+ });
282
+ }
283
+ if (results.length > 0) return results;
284
+ }
285
+ return results;
286
+ }
287
+ };
288
+ const vscodeSettingsScanner = {
289
+ name: "vscode",
290
+ async scan(ctx) {
291
+ const results = [];
292
+ const home = ctx.homedir();
293
+ const vscodePaths = [ctx.platform() === "darwin" ? join(home, "Library", "Application Support", "Code", "User", "globalStorage", "github.copilot", "hosts.json") : void 0, join(configDir(ctx), "Code", "User", "globalStorage", "github.copilot", "hosts.json")].filter((p) => typeof p === "string");
294
+ for (const path of vscodePaths) {
295
+ const json = await readJson(ctx, path);
296
+ if (!json) continue;
297
+ for (const [key, value] of Object.entries(json)) {
298
+ if (!key.includes("github.com")) continue;
299
+ const token = value && typeof value === "object" ? value.oauth_token : void 0;
300
+ if (typeof token === "string" && token.length > 0) {
301
+ log$2("vscode: found copilot token in %s", path);
302
+ results.push({
303
+ providerId: "github-copilot",
304
+ source: path,
305
+ key: token
306
+ });
307
+ return results;
308
+ }
309
+ }
310
+ }
311
+ return results;
312
+ }
313
+ };
314
+ function parseIniProfileKey(raw, profile, key) {
315
+ const lines = raw.split("\n");
316
+ let inProfile = false;
317
+ for (const line of lines) {
318
+ const trimmed = line.trim();
319
+ if (trimmed.startsWith("[")) {
320
+ inProfile = trimmed.slice(1, trimmed.indexOf("]")).trim() === profile;
321
+ continue;
322
+ }
323
+ if (inProfile && trimmed.startsWith(key)) {
324
+ const eq = trimmed.indexOf("=");
325
+ if (eq !== -1) return trimmed.slice(eq + 1).trim();
326
+ }
327
+ }
328
+ }
329
+ const cursorScanner = {
330
+ name: "cursor",
331
+ async scan(ctx) {
332
+ const results = [];
333
+ const home = ctx.homedir();
334
+ const platform = ctx.platform();
335
+ const dbPaths = [
336
+ platform === "darwin" ? join(home, "Library", "Application Support", "Cursor", "User", "globalStorage", "state.vscdb") : void 0,
337
+ platform === "win32" ? join(ctx.env("APPDATA") ?? join(home, "AppData", "Roaming"), "Cursor", "User", "globalStorage", "state.vscdb") : void 0,
338
+ join(configDir(ctx), "Cursor", "User", "globalStorage", "state.vscdb")
339
+ ].filter((p) => typeof p === "string");
340
+ if (!ctx.exec) return results;
341
+ for (const dbPath of dbPaths) {
342
+ const value = await ctx.exec(`sqlite3 "${dbPath}" "SELECT value FROM ItemTable WHERE key='cursorAuth/openAIKey'"`);
343
+ if (value && value.length > 0) {
344
+ log$2("cursor: found openAIKey in %s", dbPath);
345
+ results.push({
346
+ providerId: "cursor",
347
+ source: dbPath,
348
+ key: value
349
+ });
350
+ return results;
351
+ }
352
+ }
353
+ return results;
354
+ }
355
+ };
356
+ const DEFAULT_SCANNERS = [
357
+ copilotScanner,
358
+ vscodeSettingsScanner,
359
+ claudeCodeScanner,
360
+ codexCliScanner,
361
+ geminiCliScanner,
362
+ gcloudAdcScanner,
363
+ awsCredentialsScanner,
364
+ cursorScanner,
365
+ opencodeAuthScanner
366
+ ];
367
+ async function runDiskScanners(scanners, ctx) {
368
+ const scanCtx = ctx ?? createNodeScanContext();
369
+ const results = [];
370
+ for (const scanner of scanners) try {
371
+ const found = await scanner.scan(scanCtx);
372
+ results.push(...found);
373
+ } catch (err) {
374
+ log$2("scanner %s failed: %s", scanner.name, err instanceof Error ? err.message : String(err));
375
+ }
376
+ return results;
377
+ }
378
+
379
+ //#endregion
380
+ //#region src/auth/store.ts
381
+ const log$1 = require_logger.createLogger("auth");
382
+ function pickBestCredential(creds, prefer = "api") {
383
+ if (creds.length === 0) return void 0;
384
+ const preferred = creds.find((c) => c.type === prefer && c.key !== void 0);
385
+ if (preferred !== void 0) return preferred;
386
+ const withKey = creds.find((c) => c.key !== void 0);
387
+ if (withKey !== void 0) return withKey;
388
+ return creds[0];
389
+ }
390
+ function createAuthStore(options) {
391
+ const externalData = options?.data;
392
+ let storagePromise;
393
+ const discoveredCredentials = /* @__PURE__ */ new Map();
394
+ log$1("auth store created, external=%s", externalData !== void 0);
395
+ function getStorage() {
396
+ if (storagePromise === void 0) storagePromise = options?.storage ? Promise.resolve(options.storage) : require_auto.createDefaultStorage();
397
+ return storagePromise;
398
+ }
399
+ async function readAuthState() {
400
+ if (externalData !== void 0) {
401
+ log$1("using external data, skipping file read");
402
+ return { ...externalData };
403
+ }
404
+ const raw = await (await getStorage()).get(AUTH_STORE_KEY);
405
+ if (raw === null) {
406
+ log$1("auth store not found, returning empty store");
407
+ return {};
408
+ }
409
+ const parsed = JSON.parse(raw);
410
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
411
+ log$1("auth store payload is malformed, returning empty store");
412
+ return {};
413
+ }
414
+ const normalized = normalizeAuthState(parsed);
415
+ log$1("read auth store with %d entries", Object.keys(normalized).length);
416
+ return normalized;
417
+ }
418
+ async function writeAuthState(data) {
419
+ if (externalData !== void 0) {
420
+ for (const [k, v] of Object.entries(data)) externalData[k] = v;
421
+ for (const k of Object.keys(externalData)) if (!(k in data)) delete externalData[k];
422
+ log$1("updated external data, %d entries", Object.keys(externalData).length);
423
+ return;
424
+ }
425
+ const content = JSON.stringify(data, null, 2);
426
+ await (await getStorage()).set(AUTH_STORE_KEY, content);
427
+ log$1("wrote auth store with %d entries", Object.keys(data).length);
428
+ }
429
+ function mergeWithDiscovered(fileData) {
430
+ if (discoveredCredentials.size === 0) return fileData;
431
+ const merged = { ...fileData };
432
+ for (const [pid, creds] of discoveredCredentials) if (merged[pid] === void 0 || !merged[pid].key) {
433
+ const best = pickBestCredential(creds, "api");
434
+ if (best !== void 0) merged[pid] = best;
435
+ }
436
+ log$1("merged %d discovered credentials with %d file entries", discoveredCredentials.size, Object.keys(fileData).length);
437
+ return merged;
438
+ }
439
+ function pushDiscoveredCredential(providerId, credential) {
440
+ const arr = discoveredCredentials.get(providerId) ?? [];
441
+ arr.push(credential);
442
+ discoveredCredentials.set(providerId, arr);
443
+ }
444
+ function pushDiscoveredResultOnce(seen, results, result) {
445
+ if (seen.has(result.providerId)) return false;
446
+ seen.add(result.providerId);
447
+ results.push(result);
448
+ return true;
449
+ }
450
+ function buildCredentialFromEnv(envVar, key) {
451
+ return buildCredential({
452
+ type: "api",
453
+ key,
454
+ location: `env:${envVar}`
455
+ });
456
+ }
457
+ function buildCredentialFromDisk(result) {
458
+ if (result.key === void 0) return void 0;
459
+ return buildCredential({
460
+ type: result.credentialType ?? "api",
461
+ key: result.key,
462
+ location: result.source,
463
+ refresh: result.refresh,
464
+ accountId: result.accountId,
465
+ expires: result.expires
466
+ });
467
+ }
468
+ return {
469
+ async all() {
470
+ return mergeWithDiscovered(await readAuthState());
471
+ },
472
+ async get(providerId) {
473
+ const credential = mergeWithDiscovered(await readAuthState())[providerId];
474
+ if (credential === void 0) {
475
+ log$1("get(%s): not found", providerId);
476
+ return null;
477
+ }
478
+ log$1("get(%s): found type=%s", providerId, credential.type);
479
+ return credential;
480
+ },
481
+ async set(providerId, credential) {
482
+ const store = await readAuthState();
483
+ store[providerId] = credential;
484
+ await writeAuthState(store);
485
+ log$1("set(%s): type=%s", providerId, credential.type);
486
+ },
487
+ async remove(providerId) {
488
+ const store = await readAuthState();
489
+ if (!(providerId in store)) {
490
+ log$1("remove(%s): not found, no-op", providerId);
491
+ return;
492
+ }
493
+ delete store[providerId];
494
+ await writeAuthState(store);
495
+ log$1("remove(%s): done", providerId);
496
+ },
497
+ async discover(discoverOptions) {
498
+ const results = [];
499
+ const seen = /* @__PURE__ */ new Set();
500
+ if (!discoverOptions?.skipEnvScan) for (const [envVar, providerId] of ENV_HINTS) {
501
+ const value = process.env[envVar];
502
+ if (value) {
503
+ pushDiscoveredCredential(providerId, buildCredentialFromEnv(envVar, value));
504
+ pushDiscoveredResultOnce(seen, results, {
505
+ providerId,
506
+ source: "env",
507
+ key: value
508
+ });
509
+ log$1("discover: %s [api] from env:%s", providerId, envVar);
510
+ }
511
+ }
512
+ if (!discoverOptions?.skipDiskScan) {
513
+ const diskResults = await runDiskScanners(discoverOptions?.scanners ?? DEFAULT_SCANNERS, discoverOptions?.scanContext ?? createNodeScanContext());
514
+ for (const disk of diskResults) {
515
+ const credType = disk.credentialType ?? "api";
516
+ pushDiscoveredResultOnce(seen, results, {
517
+ providerId: disk.providerId,
518
+ source: "disk",
519
+ key: disk.key,
520
+ location: disk.source
521
+ });
522
+ const cred = buildCredentialFromDisk(disk);
523
+ if (cred !== void 0) {
524
+ pushDiscoveredCredential(disk.providerId, cred);
525
+ log$1("discover: %s [%s] from %s", disk.providerId, credType, disk.source);
526
+ }
527
+ }
528
+ }
529
+ if (discoverOptions?.persist === true) log$1("discover: persisted %d providers to auth store", await persistDiscoveredCredentials());
530
+ let authData;
531
+ try {
532
+ authData = await readAuthState();
533
+ } catch (err) {
534
+ log$1("discover: failed to read auth store: %s", err instanceof Error ? err.message : String(err));
535
+ authData = {};
536
+ }
537
+ for (const [providerId, credential] of Object.entries(authData)) if (pushDiscoveredResultOnce(seen, results, {
538
+ providerId,
539
+ source: "auth",
540
+ credential
541
+ })) log$1("discover: %s via auth store", providerId);
542
+ log$1("discover: complete, %d providers found", results.length);
543
+ return results;
544
+ },
545
+ async getPreferred(providerId, prefer) {
546
+ const creds = discoveredCredentials.get(providerId);
547
+ if (creds !== void 0 && creds.length > 0) {
548
+ const best = pickBestCredential(creds, prefer);
549
+ if (best !== void 0) return best;
550
+ }
551
+ return mergeWithDiscovered(await readAuthState())[providerId] ?? null;
552
+ }
553
+ };
554
+ async function persistDiscoveredCredentials() {
555
+ if (discoveredCredentials.size === 0) return 0;
556
+ const store = await readAuthState();
557
+ let changed = 0;
558
+ for (const [providerId, creds] of discoveredCredentials) {
559
+ if (store[providerId]?.key) continue;
560
+ const best = pickBestCredential(creds, "api");
561
+ if (best === void 0) continue;
562
+ store[providerId] = best;
563
+ changed += 1;
564
+ }
565
+ if (changed > 0) await writeAuthState(store);
566
+ return changed;
567
+ }
568
+ }
569
+ const AUTH_STORE_KEY = "auth:store";
570
+ function buildCredential(input) {
571
+ const credential = {
572
+ type: input.type,
573
+ key: input.key,
574
+ location: input.location
575
+ };
576
+ if (input.refresh !== void 0) credential.refresh = input.refresh;
577
+ if (input.accountId !== void 0) credential.accountId = input.accountId;
578
+ if (input.expires !== void 0) credential.expires = input.expires;
579
+ return credential;
580
+ }
581
+ function normalizeAuthState(input) {
582
+ const normalized = {};
583
+ for (const [providerId, rawCredential] of Object.entries(input)) {
584
+ const credential = normalizeCredential(rawCredential);
585
+ if (credential !== void 0) normalized[providerId] = credential;
586
+ }
587
+ return normalized;
588
+ }
589
+ function normalizeCredential(rawCredential) {
590
+ if (typeof rawCredential !== "object" || rawCredential === null || Array.isArray(rawCredential)) return;
591
+ const typed = rawCredential;
592
+ const type = typed.type === "api" || typed.type === "oauth" || typed.type === "wellknown" ? typed.type : "api";
593
+ const key = typeof typed.key === "string" && typed.key.length > 0 ? typed.key : void 0;
594
+ return {
595
+ ...typed,
596
+ type,
597
+ key
598
+ };
599
+ }
600
+ const ENV_HINTS = [
601
+ ["ANTHROPIC_API_KEY", "anthropic"],
602
+ ["OPENAI_API_KEY", "openai"],
603
+ ["GOOGLE_GENERATIVE_AI_API_KEY", "google"],
604
+ ["GOOGLE_API_KEY", "google"],
605
+ ["AZURE_API_KEY", "azure"],
606
+ ["XAI_API_KEY", "xai"],
607
+ ["MISTRAL_API_KEY", "mistral"],
608
+ ["GROQ_API_KEY", "groq"],
609
+ ["OPENROUTER_API_KEY", "openrouter"]
610
+ ];
611
+
612
+ //#endregion
613
+ //#region src/auth/resolver.ts
614
+ const log = require_logger.createLogger("auth:resolver");
615
+ function createSecretResolver(storage) {
616
+ log("secret resolver created, storage=%s", storage !== void 0);
617
+ return { async resolve(ref) {
618
+ if (typeof ref === "string") {
619
+ log("resolve: plain string");
620
+ return ref;
621
+ }
622
+ if (ref.type === "plain") {
623
+ log("resolve: plain value");
624
+ return ref.value;
625
+ }
626
+ if (ref.type === "env") {
627
+ const value = process.env[ref.name];
628
+ if (value === void 0) throw new Error(`Environment variable not set: ${ref.name}`);
629
+ log("resolve: env %s", ref.name);
630
+ return value;
631
+ }
632
+ if (ref.type === "storage") {
633
+ if (!storage) throw new Error(`Storage not configured, cannot resolve key: ${ref.key}`);
634
+ const value = await storage.get(ref.key);
635
+ if (value === null) throw new Error(`Key not found in storage: ${ref.key}`);
636
+ log("resolve: storage key=%s", ref.key);
637
+ return value;
638
+ }
639
+ throw new Error(`Unknown SecretRef type: ${JSON.stringify(ref)}`);
640
+ } };
641
+ }
642
+
643
+ //#endregion
644
+ Object.defineProperty(exports, 'DEFAULT_SCANNERS', {
645
+ enumerable: true,
646
+ get: function () {
647
+ return DEFAULT_SCANNERS;
648
+ }
649
+ });
650
+ Object.defineProperty(exports, 'createAuthStore', {
651
+ enumerable: true,
652
+ get: function () {
653
+ return createAuthStore;
654
+ }
655
+ });
656
+ Object.defineProperty(exports, 'createSecretResolver', {
657
+ enumerable: true,
658
+ get: function () {
659
+ return createSecretResolver;
660
+ }
661
+ });
662
+ //# sourceMappingURL=resolver-BMTvzTt9.cjs.map