@cjhyy/code-shell 0.1.0-alpha.3 → 0.1.5

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 (156) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/dist/anthropic-IBTI4WL2.cjs +10 -0
  3. package/dist/anthropic-PRZZKHEZ.js +10 -0
  4. package/dist/arena/index.cjs +7 -6
  5. package/dist/arena/index.js +6 -5
  6. package/dist/arena/model-presets.d.ts +10 -1
  7. package/dist/{arena-HHDYYVHJ.cjs → arena-KBQOPLFV.cjs} +25 -23
  8. package/dist/{arena-ENHBHB2W.js → arena-O2L4TN6A.js} +9 -7
  9. package/dist/{chunk-SW3L7HIM.js → chunk-2EP3CLEN.js} +2 -2
  10. package/dist/{chunk-EL2RL5DG.cjs → chunk-2YW4FPFG.cjs} +2 -2
  11. package/dist/chunk-3OA5G4TM.js +47 -0
  12. package/dist/chunk-52LGZKT3.cjs +47 -0
  13. package/dist/{chunk-KOGV6PDQ.cjs → chunk-55XGPMAP.cjs} +44 -9
  14. package/dist/chunk-5ECBT4YA.js +450 -0
  15. package/dist/{chunk-YD7XTI7T.cjs → chunk-6QVAYW7C.cjs} +116 -28
  16. package/dist/{chunk-SCDKLTN3.js → chunk-6S4BJ65N.js} +5 -4
  17. package/dist/{chunk-ZLPJJZUW.js → chunk-76HYEPDM.js} +2 -2
  18. package/dist/{chunk-TDXBHD24.js → chunk-76W334S4.js} +2 -2
  19. package/dist/{chunk-GZBD6QRS.cjs → chunk-7EG3V4JY.cjs} +13 -12
  20. package/dist/{chunk-LMEKCQX4.js → chunk-7JVTYEEC.js} +6 -6
  21. package/dist/{chunk-ID6EJUHP.js → chunk-7K6SDRRF.js} +1262 -212
  22. package/dist/{chunk-5C5HIOML.js → chunk-7Y6S3OCX.js} +109 -21
  23. package/dist/{chunk-VIPLU4RY.cjs → chunk-A5LCRPDP.cjs} +4 -4
  24. package/dist/{chunk-F5BS3GUC.js → chunk-BSW22MPA.js} +39 -4
  25. package/dist/{chunk-VWFET3MG.cjs → chunk-BUU5PZK2.cjs} +1474 -423
  26. package/dist/{chunk-HOXQLX5R.cjs → chunk-BWTOS5BH.cjs} +444 -103
  27. package/dist/{chunk-ZRVPCXI7.js → chunk-BXCY2FSE.js} +2 -1
  28. package/dist/{chunk-Y7TSCDF6.js → chunk-C5YQBIRK.js} +347 -6
  29. package/dist/{chunk-C7C7ZZY4.cjs → chunk-HEKQCI7B.cjs} +10 -10
  30. package/dist/{chunk-JHXNOB5G.cjs → chunk-HS2MFNUC.cjs} +6 -6
  31. package/dist/{chunk-JHNCK7JP.cjs → chunk-IK4EWJBP.cjs} +4 -3
  32. package/dist/{chunk-M2QI5X3X.cjs → chunk-JMR33QVF.cjs} +2 -2
  33. package/dist/{chunk-YAFCN7ZW.cjs → chunk-KOVYSDHZ.cjs} +15 -15
  34. package/dist/{chunk-IJSHQGMP.cjs → chunk-KS3RYAYL.cjs} +4 -4
  35. package/dist/{chunk-DI7RDLOS.js → chunk-MD32R22I.js} +7 -4
  36. package/dist/chunk-MY5XHADU.cjs +216 -0
  37. package/dist/{chunk-OP57WUWQ.cjs → chunk-NUNC3VFB.cjs} +6 -6
  38. package/dist/{chunk-BF4LXLQV.cjs → chunk-QRM7IF2S.cjs} +133 -175
  39. package/dist/chunk-R47ROHGL.cjs +298 -0
  40. package/dist/{chunk-OUC2DFA7.js → chunk-RMYKO74M.js} +3 -3
  41. package/dist/{chunk-FUOKLKR2.js → chunk-SFXHZSRF.js} +1 -1
  42. package/dist/{chunk-2EUAE7AY.js → chunk-SIHHIQLO.js} +2 -2
  43. package/dist/{chunk-3CAZIWUA.cjs → chunk-SNT563K3.cjs} +9 -9
  44. package/dist/{chunk-SK62UVS6.js → chunk-T6VYG46N.js} +1 -1
  45. package/dist/{chunk-3QR52LL5.cjs → chunk-TUY2T5KP.cjs} +2 -2
  46. package/dist/{chunk-I57ZD5IQ.js → chunk-VIAGTYYW.js} +1 -1
  47. package/dist/{chunk-X2DNIMPC.cjs → chunk-VYL4EFRC.cjs} +32 -32
  48. package/dist/chunk-W22P377T.js +299 -0
  49. package/dist/chunk-WASS5YWB.js +215 -0
  50. package/dist/{chunk-FPFTIKEJ.js → chunk-XDIQWQJ4.js} +132 -174
  51. package/dist/{chunk-BUJ5KYCI.cjs → chunk-YIQBXAYU.cjs} +13 -13
  52. package/dist/{chunk-REFCCVDM.js → chunk-YJ77GQK5.js} +2 -2
  53. package/dist/chunk-YUI524OE.cjs +450 -0
  54. package/dist/{chunk-M2SVOKC6.js → chunk-ZBPSQCPU.js} +6 -6
  55. package/dist/cli/commands/builtin/export-md.d.ts +19 -0
  56. package/dist/cli/commands/builtin/init/detect.d.ts +25 -0
  57. package/dist/cli/commands/builtin/init/index.d.ts +19 -0
  58. package/dist/cli/main.cjs +2343 -1447
  59. package/dist/cli/main.js +2476 -1580
  60. package/dist/cli/migrate-models.d.ts +45 -0
  61. package/dist/cli/onboarding.d.ts +110 -5
  62. package/dist/cli/updater.d.ts +51 -4
  63. package/dist/client-base-HTF236ZD.cjs +9 -0
  64. package/dist/client-base-QKRKCOWB.js +9 -0
  65. package/dist/{compaction-YNWCEF7B.js → compaction-6VU2T643.js} +4 -2
  66. package/dist/compaction-OKUNTCA7.cjs +33 -0
  67. package/dist/context/compaction.d.ts +35 -3
  68. package/dist/context/manager.d.ts +40 -3
  69. package/dist/context/tool-result-storage.d.ts +96 -0
  70. package/dist/devtools-T2NIZBJK.cjs +6 -0
  71. package/dist/{devtools-IRQQPIRY.js → devtools-YXWHOVKR.js} +1 -1
  72. package/dist/engine/engine.d.ts +40 -0
  73. package/dist/engine/turn-loop.d.ts +6 -0
  74. package/dist/export-md-RXDW6F5W.cjs +135 -0
  75. package/dist/export-md-XXKZANW5.js +135 -0
  76. package/dist/file-history-KYPE3ECT.cjs +7 -0
  77. package/dist/file-history-LF4F7X26.js +7 -0
  78. package/dist/index.cjs +42 -22
  79. package/dist/index.d.ts +5 -2
  80. package/dist/index.js +40 -20
  81. package/dist/llm/client-base.d.ts +1 -1
  82. package/dist/llm/model-cache.d.ts +21 -0
  83. package/dist/llm/model-fetcher.d.ts +29 -0
  84. package/dist/llm/model-pool.d.ts +13 -0
  85. package/dist/llm/provider-catalog.d.ts +30 -0
  86. package/dist/llm/provider-kinds.d.ts +21 -0
  87. package/dist/llm/types.d.ts +8 -0
  88. package/dist/logging/session-recorder.d.ts +77 -0
  89. package/dist/manager-C2IUXKRC.js +7 -0
  90. package/dist/manager-YYKWYTRM.cjs +7 -0
  91. package/dist/mcp-manager-QMKWPBZ4.js +8 -0
  92. package/dist/mcp-manager-Z3OKI74O.cjs +8 -0
  93. package/dist/memory-5LWZ6FI2.cjs +9 -0
  94. package/dist/{memory-EPFDBPII.js → memory-VIJLBAMQ.js} +2 -2
  95. package/dist/model-cache-5KIYL5SL.js +13 -0
  96. package/dist/model-cache-OED3IM4R.cjs +13 -0
  97. package/dist/model-fetcher-HKGICACL.js +8 -0
  98. package/dist/model-fetcher-UR6WJOQP.cjs +8 -0
  99. package/dist/openai-JR2WEKOF.js +10 -0
  100. package/dist/openai-YBTOET4O.cjs +10 -0
  101. package/dist/openrouter-models-OU4GRZQY.cjs +15 -0
  102. package/dist/{openrouter-models-2FM3H4SQ.js → openrouter-models-TGKDKY52.js} +2 -2
  103. package/dist/openrouter-sync-BBHUM3R6.cjs +11 -0
  104. package/dist/{openrouter-sync-SO3AWEAM.js → openrouter-sync-UXUSJCIR.js} +3 -3
  105. package/dist/product/index.cjs +17 -15
  106. package/dist/product/index.js +16 -14
  107. package/dist/protocol/server.d.ts +3 -1
  108. package/dist/protocol/types.d.ts +36 -2
  109. package/dist/run/index.cjs +17 -15
  110. package/dist/run/index.js +16 -14
  111. package/dist/services/index.d.ts +0 -1
  112. package/dist/session-manager-Q22BBMD3.js +8 -0
  113. package/dist/session-manager-XODQVL3C.cjs +8 -0
  114. package/dist/settings/schema.d.ts +267 -42
  115. package/dist/{tool-summary-RYNR4DDB.cjs → tool-summary-63DPIS7G.cjs} +4 -4
  116. package/dist/{tool-summary-2RUFL5QK.js → tool-summary-NP5CDBKG.js} +2 -2
  117. package/dist/tool-system/builtin/ask-user.d.ts +9 -1
  118. package/dist/tool-system/context.d.ts +31 -2
  119. package/dist/tool-system/executor.d.ts +4 -0
  120. package/dist/tool-system/investigation-guard.d.ts +37 -0
  121. package/dist/types.d.ts +13 -2
  122. package/dist/ui/components/AskUserPrompt.d.ts +8 -1
  123. package/dist/ui/components/DiffLine.d.ts +33 -0
  124. package/dist/ui/components/ModelManager.d.ts +34 -1
  125. package/dist/ui/components/OnboardingPrompt.d.ts +10 -1
  126. package/dist/ui/components/ProviderModelFlow.d.ts +58 -0
  127. package/dist/ui/components/UpdateBanner.d.ts +1 -0
  128. package/dist/updater-QW473OF4.cjs +17 -0
  129. package/dist/updater-VFUAHCVY.js +17 -0
  130. package/dist/utils/semver.d.ts +1 -0
  131. package/dist/utils/task-sanitizer.d.ts +6 -0
  132. package/package.json +1 -1
  133. package/dist/anthropic-P5VETAFI.cjs +0 -10
  134. package/dist/anthropic-W2GU3D76.js +0 -10
  135. package/dist/chunk-75E4BBFC.js +0 -224
  136. package/dist/chunk-FV2ARONZ.cjs +0 -224
  137. package/dist/client-base-TOVE25FA.js +0 -9
  138. package/dist/client-base-VDDIADAC.cjs +0 -9
  139. package/dist/compaction-D3KV2NWY.cjs +0 -31
  140. package/dist/devtools-WTC3NFNE.cjs +0 -6
  141. package/dist/file-history-HZWO2WQ5.js +0 -7
  142. package/dist/file-history-UQQILIY7.cjs +0 -7
  143. package/dist/manager-FWLOVEEK.cjs +0 -7
  144. package/dist/manager-GEXJLOIS.js +0 -7
  145. package/dist/mcp-manager-37GQLFGX.js +0 -8
  146. package/dist/mcp-manager-U77NEXBY.cjs +0 -8
  147. package/dist/memory-ADGOWADP.cjs +0 -9
  148. package/dist/openai-RXU5URYI.js +0 -10
  149. package/dist/openai-SQW4H2K4.cjs +0 -10
  150. package/dist/openrouter-models-PLCWZZYE.cjs +0 -15
  151. package/dist/openrouter-sync-K2WK3A2A.cjs +0 -11
  152. package/dist/services/compact.d.ts +0 -56
  153. package/dist/session-manager-HRSKENKB.cjs +0 -8
  154. package/dist/session-manager-NEKFEHF3.js +0 -8
  155. package/dist/updater-J7L7R6BY.cjs +0 -185
  156. package/dist/updater-LDBNYCAO.js +0 -185
@@ -0,0 +1,299 @@
1
+ import {
2
+ __dirname,
3
+ __filename,
4
+ __require,
5
+ init_esm_shims
6
+ } from "./chunk-MD32R22I.js";
7
+
8
+ // src/cli/updater.ts
9
+ init_esm_shims();
10
+ import { execFile, spawn } from "child_process";
11
+ import { constants as fsConstants } from "fs";
12
+ import { access, mkdir, readFile, stat, unlink, writeFile } from "fs/promises";
13
+ import { createRequire } from "module";
14
+ import { homedir } from "os";
15
+ import { dirname, join, resolve } from "path";
16
+ import { readFileSync } from "fs";
17
+ import { fileURLToPath } from "url";
18
+ import { promisify } from "util";
19
+
20
+ // src/utils/semver.ts
21
+ init_esm_shims();
22
+ import { gte as semverGte, gt as semverGt, lt as semverLt } from "semver";
23
+ function gt(a, b) {
24
+ return semverGt(a, b);
25
+ }
26
+
27
+ // src/cli/updater.ts
28
+ var execFileAsync = promisify(execFile);
29
+ var PACKAGE_NAME = "@cjhyy/code-shell";
30
+ var LOCK_FILE = ".update.lock";
31
+ var LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
32
+ var NPM_VIEW_TIMEOUT_MS = 5e3;
33
+ var _updateInfo;
34
+ var _exitHookInstalled = false;
35
+ var _disabledReason = null;
36
+ function checkForUpdate(packageName = PACKAGE_NAME) {
37
+ void runCheck(packageName);
38
+ }
39
+ function getUpdateAvailable() {
40
+ return _updateInfo;
41
+ }
42
+ function getAutoUpdateDisabledReason() {
43
+ return _disabledReason;
44
+ }
45
+ function scheduleAutoInstallOnExit() {
46
+ if (_exitHookInstalled) return;
47
+ _exitHookInstalled = true;
48
+ const fire = () => {
49
+ const info = _updateInfo;
50
+ if (!info || !info.canAutoInstall) return;
51
+ try {
52
+ launchDetachedInstall(info.latestVersion);
53
+ } catch {
54
+ }
55
+ };
56
+ process.once("exit", fire);
57
+ }
58
+ var _cachedVersion;
59
+ function getCurrentVersion() {
60
+ if (_cachedVersion) return _cachedVersion;
61
+ const found = resolveVersion();
62
+ _cachedVersion = found;
63
+ return found;
64
+ }
65
+ function resolveVersion() {
66
+ try {
67
+ const here = typeof import.meta !== "undefined" && import.meta.url ? dirname(fileURLToPath(import.meta.url)) : __dirname;
68
+ let dir = here;
69
+ for (let i = 0; i < 6; i++) {
70
+ try {
71
+ const pkg = JSON.parse(readFileSync(resolve(dir, "package.json"), "utf-8"));
72
+ if (pkg && typeof pkg.version === "string") return pkg.version;
73
+ } catch {
74
+ }
75
+ const parent = dirname(dir);
76
+ if (parent === dir) break;
77
+ dir = parent;
78
+ }
79
+ } catch {
80
+ }
81
+ try {
82
+ const req = createRequire(import.meta.url ?? __filename);
83
+ const pkg = req("../../package.json");
84
+ if (pkg?.version) return pkg.version;
85
+ } catch {
86
+ }
87
+ return "0.0.0";
88
+ }
89
+ async function runCheck(packageName) {
90
+ const disabled = isAutoUpdaterDisabled();
91
+ if (disabled) {
92
+ _disabledReason = disabled;
93
+ return;
94
+ }
95
+ _disabledReason = null;
96
+ try {
97
+ const currentVersion = getCurrentVersion();
98
+ const latestVersion = await getLatestVersion(packageName);
99
+ if (!latestVersion) return;
100
+ let isNewer = false;
101
+ try {
102
+ isNewer = gt(latestVersion, currentVersion);
103
+ } catch {
104
+ isNewer = latestVersion !== currentVersion;
105
+ }
106
+ if (!isNewer) {
107
+ _updateInfo = void 0;
108
+ return;
109
+ }
110
+ const { hasPermissions, npmPrefix } = await checkGlobalInstallPermissions();
111
+ _updateInfo = { latestVersion, canAutoInstall: hasPermissions, npmPrefix };
112
+ } catch {
113
+ }
114
+ }
115
+ async function getLatestVersion(packageName) {
116
+ try {
117
+ const { stdout } = await execFileAsync(
118
+ "npm",
119
+ ["view", `${packageName}@latest`, "version", "--prefer-online"],
120
+ { cwd: homedir(), timeout: NPM_VIEW_TIMEOUT_MS }
121
+ );
122
+ const v = stdout.trim();
123
+ return v.length > 0 ? v : null;
124
+ } catch {
125
+ return null;
126
+ }
127
+ }
128
+ async function checkGlobalInstallPermissions() {
129
+ let prefix = null;
130
+ try {
131
+ const { stdout } = await execFileAsync(
132
+ "npm",
133
+ ["-g", "config", "get", "prefix"],
134
+ { cwd: homedir(), timeout: 5e3 }
135
+ );
136
+ prefix = stdout.trim();
137
+ } catch {
138
+ return { hasPermissions: false, npmPrefix: null };
139
+ }
140
+ if (!prefix) return { hasPermissions: false, npmPrefix: null };
141
+ try {
142
+ await access(prefix, fsConstants.W_OK);
143
+ return { hasPermissions: true, npmPrefix: prefix };
144
+ } catch {
145
+ return { hasPermissions: false, npmPrefix: prefix };
146
+ }
147
+ }
148
+ function userHome() {
149
+ return process.env.HOME ?? homedir();
150
+ }
151
+ function configDir() {
152
+ return join(userHome(), ".code-shell");
153
+ }
154
+ function getLockFilePath() {
155
+ return join(configDir(), LOCK_FILE);
156
+ }
157
+ function getUpdateLogPath() {
158
+ return join(configDir(), "update.log");
159
+ }
160
+ async function acquireLock() {
161
+ const lockPath = getLockFilePath();
162
+ try {
163
+ const s = await stat(lockPath);
164
+ if (Date.now() - s.mtimeMs < LOCK_TIMEOUT_MS) return false;
165
+ try {
166
+ const recheck = await stat(lockPath);
167
+ if (Date.now() - recheck.mtimeMs < LOCK_TIMEOUT_MS) return false;
168
+ await unlink(lockPath);
169
+ } catch (err) {
170
+ if (!isENOENT(err)) return false;
171
+ }
172
+ } catch (err) {
173
+ if (!isENOENT(err)) return false;
174
+ }
175
+ try {
176
+ await writeFile(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
177
+ return true;
178
+ } catch (err) {
179
+ const code = errnoCode(err);
180
+ if (code === "EEXIST") return false;
181
+ if (code === "ENOENT") {
182
+ try {
183
+ await mkdir(configDir(), { recursive: true });
184
+ await writeFile(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
185
+ return true;
186
+ } catch {
187
+ return false;
188
+ }
189
+ }
190
+ return false;
191
+ }
192
+ }
193
+ async function releaseLock() {
194
+ const lockPath = getLockFilePath();
195
+ try {
196
+ const data = await readFile(lockPath, "utf8");
197
+ if (data === String(process.pid)) await unlink(lockPath);
198
+ } catch {
199
+ }
200
+ }
201
+ function launchDetachedInstall(version) {
202
+ const lockPath = getLockFilePath();
203
+ try {
204
+ try {
205
+ const fs2 = __require("fs");
206
+ fs2.mkdirSync(configDir(), { recursive: true });
207
+ fs2.writeFileSync(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
208
+ } catch (err) {
209
+ if (errnoCode(err) === "EEXIST") {
210
+ try {
211
+ const fs2 = __require("fs");
212
+ const s = fs2.statSync(lockPath);
213
+ if (Date.now() - s.mtimeMs < LOCK_TIMEOUT_MS) return;
214
+ fs2.unlinkSync(lockPath);
215
+ fs2.writeFileSync(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
216
+ } catch {
217
+ return;
218
+ }
219
+ } else {
220
+ return;
221
+ }
222
+ }
223
+ } catch {
224
+ return;
225
+ }
226
+ const fs = __require("fs");
227
+ const logFd = fs.openSync(getUpdateLogPath(), "a");
228
+ try {
229
+ fs.writeSync(
230
+ logFd,
231
+ `
232
+ [${(/* @__PURE__ */ new Date()).toISOString()}] code-shell auto-update: installing ${PACKAGE_NAME}@${version} (pid=${process.pid})
233
+ `
234
+ );
235
+ } catch {
236
+ }
237
+ const cmd = [
238
+ `npm install -g ${PACKAGE_NAME}@${shellEscape(version)}`,
239
+ `; rm -f ${shellEscape(lockPath)}`
240
+ ].join(" ");
241
+ try {
242
+ const child = spawn("sh", ["-c", cmd], {
243
+ detached: true,
244
+ stdio: ["ignore", logFd, logFd],
245
+ cwd: homedir()
246
+ });
247
+ child.unref();
248
+ } catch {
249
+ try {
250
+ fs.unlinkSync(lockPath);
251
+ } catch {
252
+ }
253
+ }
254
+ }
255
+ function isAutoUpdaterDisabled() {
256
+ if (process.env.NODE_ENV === "development") return "development build";
257
+ if (isEnvTruthy(process.env.DISABLE_AUTOUPDATER)) return "DISABLE_AUTOUPDATER set";
258
+ if (readAutoUpdatesFlagFromDisk() === false) return "settings.autoUpdates = false";
259
+ return null;
260
+ }
261
+ function readAutoUpdatesFlagFromDisk() {
262
+ const candidates = [
263
+ join(userHome(), ".code-shell", "settings.json"),
264
+ join(userHome(), ".claude", "settings.json")
265
+ ];
266
+ for (const path of candidates) {
267
+ try {
268
+ const raw = readFileSync(path, "utf8");
269
+ const parsed = JSON.parse(raw);
270
+ if (typeof parsed.autoUpdates === "boolean") return parsed.autoUpdates;
271
+ } catch {
272
+ }
273
+ }
274
+ return void 0;
275
+ }
276
+ function isEnvTruthy(v) {
277
+ if (!v) return false;
278
+ const lower = v.toLowerCase();
279
+ return lower === "1" || lower === "true" || lower === "yes" || lower === "on";
280
+ }
281
+ function errnoCode(err) {
282
+ return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
283
+ }
284
+ function isENOENT(err) {
285
+ return errnoCode(err) === "ENOENT";
286
+ }
287
+ function shellEscape(s) {
288
+ return `'${s.replace(/'/g, `'\\''`)}'`;
289
+ }
290
+ var __internal = { acquireLock, releaseLock, getLockFilePath };
291
+
292
+ export {
293
+ checkForUpdate,
294
+ getUpdateAvailable,
295
+ getAutoUpdateDisabledReason,
296
+ scheduleAutoInstallOnExit,
297
+ getCurrentVersion,
298
+ __internal
299
+ };
@@ -0,0 +1,215 @@
1
+ import {
2
+ isStale,
3
+ readCache,
4
+ writeCache
5
+ } from "./chunk-3OA5G4TM.js";
6
+ import {
7
+ init_esm_shims
8
+ } from "./chunk-MD32R22I.js";
9
+
10
+ // src/llm/model-fetcher.ts
11
+ init_esm_shims();
12
+ import { readFileSync, existsSync } from "fs";
13
+ import { fileURLToPath } from "url";
14
+ import { dirname, join } from "path";
15
+
16
+ // src/llm/provider-kinds.ts
17
+ init_esm_shims();
18
+ var NON_CHAT_PATTERNS = /(?:^|[-_/])(?:embed(?:ding)?|whisper|tts|audio|image|dall-?e|moderation|rerank|guard|vision-only)(?:$|[-_/])/i;
19
+ var isChatLike = (id) => !NON_CHAT_PATTERNS.test(id);
20
+ var bearer = (k) => k ? { Authorization: `Bearer ${k}` } : {};
21
+ var PROVIDER_KINDS = {
22
+ openai: {
23
+ label: "OpenAI",
24
+ defaultBaseUrl: "https://api.openai.com/v1",
25
+ modelsPath: "/models",
26
+ protocol: "openai-compat",
27
+ authHeader: bearer,
28
+ chatFilter: isChatLike
29
+ },
30
+ anthropic: {
31
+ label: "Anthropic",
32
+ defaultBaseUrl: "https://api.anthropic.com/v1",
33
+ modelsPath: "/models",
34
+ protocol: "anthropic-style",
35
+ authHeader: (k) => k ? { "x-api-key": k, "anthropic-version": "2023-06-01" } : { "anthropic-version": "2023-06-01" },
36
+ chatFilter: isChatLike
37
+ },
38
+ deepseek: {
39
+ label: "DeepSeek",
40
+ defaultBaseUrl: "https://api.deepseek.com/v1",
41
+ modelsPath: "/models",
42
+ protocol: "openai-compat",
43
+ authHeader: bearer,
44
+ chatFilter: isChatLike
45
+ },
46
+ xai: {
47
+ label: "xAI (Grok)",
48
+ defaultBaseUrl: "https://api.x.ai/v1",
49
+ modelsPath: "/models",
50
+ protocol: "openai-compat",
51
+ authHeader: bearer,
52
+ chatFilter: isChatLike
53
+ },
54
+ mistral: {
55
+ label: "Mistral",
56
+ defaultBaseUrl: "https://api.mistral.ai/v1",
57
+ modelsPath: "/models",
58
+ protocol: "openai-compat",
59
+ authHeader: bearer,
60
+ chatFilter: isChatLike
61
+ },
62
+ groq: {
63
+ label: "Groq",
64
+ defaultBaseUrl: "https://api.groq.com/openai/v1",
65
+ modelsPath: "/models",
66
+ protocol: "openai-compat",
67
+ authHeader: bearer,
68
+ chatFilter: isChatLike
69
+ },
70
+ google: {
71
+ label: "Google Gemini",
72
+ defaultBaseUrl: "https://generativelanguage.googleapis.com/v1beta",
73
+ modelsPath: "/models",
74
+ protocol: "gemini",
75
+ authHeader: () => ({}),
76
+ authQuery: (k) => k ? { key: k } : {},
77
+ chatFilter: (id) => isChatLike(id) && /gemini/i.test(id)
78
+ },
79
+ openrouter: {
80
+ label: "OpenRouter",
81
+ defaultBaseUrl: "https://openrouter.ai/api/v1",
82
+ modelsPath: "/models",
83
+ protocol: "openai-compat",
84
+ authHeader: bearer,
85
+ chatFilter: isChatLike
86
+ },
87
+ ollama: {
88
+ label: "Ollama (local)",
89
+ defaultBaseUrl: "http://localhost:11434",
90
+ modelsPath: "/api/tags",
91
+ protocol: "ollama",
92
+ authHeader: () => ({}),
93
+ chatFilter: isChatLike
94
+ },
95
+ custom: {
96
+ label: "Custom",
97
+ defaultBaseUrl: "",
98
+ modelsPath: "/models",
99
+ protocol: "openai-compat",
100
+ authHeader: bearer,
101
+ chatFilter: isChatLike
102
+ }
103
+ };
104
+ function getKindMeta(kind) {
105
+ return PROVIDER_KINDS[kind] ?? PROVIDER_KINDS.custom;
106
+ }
107
+
108
+ // src/llm/model-fetcher.ts
109
+ var HERE = dirname(fileURLToPath(import.meta.url));
110
+ var OPENROUTER_SNAPSHOT = join(HERE, "..", "data", "openrouter-models.json");
111
+ async function fetchModelList(provider, opts) {
112
+ const meta = getKindMeta(provider.kind);
113
+ if (!opts.refresh) {
114
+ const cached = readCache(opts.cacheDir, provider.key);
115
+ if (cached && !isStale(cached)) return { ...cached, fromCache: true };
116
+ }
117
+ if (provider.kind === "openrouter") {
118
+ return loadOpenRouterSnapshot(provider.key, opts.cacheDir);
119
+ }
120
+ try {
121
+ const path = provider.modelsPath ?? meta.modelsPath;
122
+ const url = new URL(joinUrl(provider.baseUrl, path));
123
+ const headers = meta.authHeader(provider.apiKey ?? "");
124
+ if (meta.authQuery) {
125
+ const q = meta.authQuery(provider.apiKey ?? "");
126
+ for (const [k, v] of Object.entries(q)) url.searchParams.set(k, v);
127
+ }
128
+ const res = await fetch(url.toString(), {
129
+ headers: { Accept: "application/json", ...headers },
130
+ signal: AbortSignal.timeout(opts.timeoutMs ?? 2e4)
131
+ });
132
+ if (!res.ok) {
133
+ return errorResult(provider.key, opts.cacheDir, `HTTP ${res.status}`);
134
+ }
135
+ const payload = await res.json();
136
+ const raw = normalize(payload, meta.protocol);
137
+ const filtered = raw.filter((m) => meta.chatFilter(m.id));
138
+ const file = writeCache(opts.cacheDir, provider.key, filtered);
139
+ return file;
140
+ } catch (err) {
141
+ const msg = err.message || String(err);
142
+ return errorResult(provider.key, opts.cacheDir, msg);
143
+ }
144
+ }
145
+ function normalize(payload, protocol) {
146
+ switch (protocol) {
147
+ case "ollama": {
148
+ const p = payload;
149
+ return (p.models ?? []).map((m) => ({ id: m.name, contextLength: 0, maxOutputTokens: 0 }));
150
+ }
151
+ case "anthropic-style": {
152
+ const p = payload;
153
+ return (p.data ?? []).map((m) => ({
154
+ id: m.id,
155
+ contextLength: m.context_window ?? 2e5,
156
+ maxOutputTokens: m.max_output_tokens ?? 0
157
+ }));
158
+ }
159
+ case "gemini": {
160
+ const p = payload;
161
+ return (p.models ?? []).map((m) => ({
162
+ id: m.name.replace(/^models\//, ""),
163
+ contextLength: m.inputTokenLimit ?? 0,
164
+ maxOutputTokens: m.outputTokenLimit ?? 0
165
+ }));
166
+ }
167
+ case "openai-compat": {
168
+ const p = payload;
169
+ return (p.data ?? []).map((m) => ({
170
+ id: m.id,
171
+ contextLength: m.context_window ?? m.context_length ?? 0,
172
+ maxOutputTokens: m.max_completion_tokens ?? 0
173
+ }));
174
+ }
175
+ }
176
+ const _exhaustive = protocol;
177
+ return _exhaustive;
178
+ }
179
+ function loadOpenRouterSnapshot(providerKey, cacheDir) {
180
+ if (!existsSync(OPENROUTER_SNAPSHOT)) {
181
+ return errorResult(providerKey, cacheDir, "openrouter snapshot missing");
182
+ }
183
+ try {
184
+ const snapshot = JSON.parse(
185
+ readFileSync(OPENROUTER_SNAPSHOT, "utf-8")
186
+ );
187
+ const models = (snapshot.models ?? []).map((m) => ({
188
+ id: m.id,
189
+ contextLength: m.contextLength ?? 0,
190
+ maxOutputTokens: m.maxOutputTokens ?? 0
191
+ }));
192
+ return writeCache(cacheDir, providerKey, models);
193
+ } catch (err) {
194
+ return errorResult(providerKey, cacheDir, err.message);
195
+ }
196
+ }
197
+ function errorResult(providerKey, cacheDir, error) {
198
+ const stale = readCache(cacheDir, providerKey);
199
+ if (stale) return { ...stale, error, fromCache: true };
200
+ return {
201
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
202
+ providerKey,
203
+ models: [],
204
+ error
205
+ };
206
+ }
207
+ function joinUrl(base, path) {
208
+ if (!base) return path;
209
+ return `${base.replace(/\/$/, "")}${path.startsWith("/") ? "" : "/"}${path}`;
210
+ }
211
+
212
+ export {
213
+ PROVIDER_KINDS,
214
+ fetchModelList
215
+ };