jinzd-ai-cli 0.4.218 → 0.4.220

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 (33) hide show
  1. package/README.md +102 -99
  2. package/README.zh-CN.md +40 -38
  3. package/dist/{batch-7V7OTMUP.js → batch-QBSKTLTO.js} +3 -3
  4. package/dist/{chunk-TZQHYZKT.js → chunk-5ULLIOVC.js} +1 -0
  5. package/dist/{chunk-P4VBLXKS.js → chunk-5WBNXYDJ.js} +2 -2
  6. package/dist/chunk-ALQN7VUJ.js +604 -0
  7. package/dist/{chunk-C2Z42DI5.js → chunk-CAUHLHDR.js} +1 -1
  8. package/dist/{chunk-GX3HSGJX.js → chunk-IZW5LMI6.js} +166 -638
  9. package/dist/chunk-P3LKFA54.js +639 -0
  10. package/dist/{chunk-5CA2TJ5F.js → chunk-P4DYAGUI.js} +1 -1
  11. package/dist/{chunk-L4UREAID.js → chunk-P4PTXCHY.js} +6 -5
  12. package/dist/{chunk-QMXC327F.js → chunk-PUBCJF7E.js} +213 -175
  13. package/dist/{chunk-NTCB7CMT.js → chunk-QZYNRCPX.js} +1 -1
  14. package/dist/{chunk-H2UIHGHH.js → chunk-VHX7KZDY.js} +29 -189
  15. package/dist/{chunk-VGFTM3XT.js → chunk-Y25MSSUP.js} +1 -1
  16. package/dist/{ci-L6GH2WVC.js → ci-5SNXGM3M.js} +6 -6
  17. package/dist/{ci-format-WW7454AY.js → ci-format-57QQTHQE.js} +2 -2
  18. package/dist/{constants-NCTFSHDU.js → constants-ML5KFEOH.js} +1 -1
  19. package/dist/doctor-cli-ZRH3XZ3R.js +17 -0
  20. package/dist/electron-server.js +836 -470
  21. package/dist/{hub-CDL6T7CP.js → hub-IPLMJ6TJ.js} +1 -1
  22. package/dist/index.js +125 -194
  23. package/dist/{pr-D6PEKEGK.js → pr-GJYDAPK4.js} +8 -7
  24. package/dist/{run-tests-NXVVKAK2.js → run-tests-GK5AIAV2.js} +1 -1
  25. package/dist/{run-tests-SWU2XEV7.js → run-tests-KLQAI5CX.js} +2 -2
  26. package/dist/{server-WUT7VYTD.js → server-5FZDALHH.js} +10 -10
  27. package/dist/{server-LHYSS6CK.js → server-RU36PRSH.js} +74 -83
  28. package/dist/{task-orchestrator-C5AA2BI5.js → task-orchestrator-JMHPVNUO.js} +10 -10
  29. package/dist/{usage-6ZUUJBI2.js → usage-IRMRCCKN.js} +3 -3
  30. package/package.json +1 -1
  31. package/dist/chunk-MWKE2TNS.js +0 -129
  32. package/dist/chunk-OUC75QCF.js +0 -166
  33. package/dist/doctor-cli-EWMFBP5Q.js +0 -226
@@ -9,7 +9,10 @@ import {
9
9
  ProviderError,
10
10
  ProviderNotFoundError,
11
11
  RateLimitError
12
- } from "./chunk-TZQHYZKT.js";
12
+ } from "./chunk-5ULLIOVC.js";
13
+ import {
14
+ atomicWriteFileSync
15
+ } from "./chunk-IW3Q7AE5.js";
13
16
 
14
17
  // src/providers/claude.ts
15
18
  import Anthropic from "@anthropic-ai/sdk";
@@ -574,6 +577,23 @@ var ClaudeProvider = class extends BaseProvider {
574
577
  async listModels() {
575
578
  return this.info.models;
576
579
  }
580
+ async refreshModels() {
581
+ try {
582
+ const response = await this.client.models.list();
583
+ const data = response.data ?? [];
584
+ return data.map((model) => ({
585
+ id: model.id,
586
+ displayName: model.id,
587
+ contextWindow: 2e5,
588
+ supportsStreaming: true,
589
+ source: "live",
590
+ available: true,
591
+ metadataUnknown: true
592
+ }));
593
+ } catch (err) {
594
+ throw this.wrapError(err);
595
+ }
596
+ }
577
597
  wrapError(err) {
578
598
  if (err instanceof Anthropic.AuthenticationError) {
579
599
  return new AuthError("claude");
@@ -1370,6 +1390,22 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1370
1390
  async listModels() {
1371
1391
  return this.info.models;
1372
1392
  }
1393
+ async refreshModels() {
1394
+ try {
1395
+ const response = await this.client.models.list();
1396
+ return response.data.map((model) => ({
1397
+ id: model.id,
1398
+ displayName: model.id,
1399
+ contextWindow: 128e3,
1400
+ supportsStreaming: true,
1401
+ source: "live",
1402
+ available: true,
1403
+ metadataUnknown: true
1404
+ }));
1405
+ } catch (err) {
1406
+ throw this.wrapError(err);
1407
+ }
1408
+ }
1373
1409
  wrapError(err) {
1374
1410
  if (err instanceof OpenAI.AuthenticationError) {
1375
1411
  return new AuthError(this.info.id);
@@ -1560,54 +1596,6 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1560
1596
  displayName: "GLM-4.6 (200K, \u4E2D\u6587\u5199\u4F5C\u63A8\u8350)",
1561
1597
  contextWindow: 204800,
1562
1598
  supportsStreaming: true
1563
- },
1564
- {
1565
- id: "glm-4.6v",
1566
- displayName: "GLM-4.6V (Vision + Thinking)",
1567
- contextWindow: 131072,
1568
- supportsStreaming: true,
1569
- supportsThinking: true
1570
- },
1571
- // ── GLM-Z1 推理系列 ──
1572
- {
1573
- id: "glm-z1",
1574
- displayName: "GLM-Z1 (Reasoning Flagship)",
1575
- contextWindow: 131072,
1576
- supportsStreaming: true,
1577
- supportsThinking: true
1578
- },
1579
- {
1580
- id: "glm-z1-air",
1581
- displayName: "GLM-Z1 Air (Lightweight Reasoning)",
1582
- contextWindow: 131072,
1583
- supportsStreaming: true,
1584
- supportsThinking: true
1585
- },
1586
- {
1587
- id: "glm-z1-flash",
1588
- displayName: "GLM-Z1 Flash (Free Reasoning)",
1589
- contextWindow: 128e3,
1590
- supportsStreaming: true,
1591
- supportsThinking: true
1592
- },
1593
- // ── GLM-4 系列(稳定,价格低) ──
1594
- {
1595
- id: "glm-4-plus",
1596
- displayName: "GLM-4 Plus",
1597
- contextWindow: 128e3,
1598
- supportsStreaming: true
1599
- },
1600
- {
1601
- id: "glm-4-air",
1602
- displayName: "GLM-4 Air",
1603
- contextWindow: 128e3,
1604
- supportsStreaming: true
1605
- },
1606
- {
1607
- id: "glm-4-flash",
1608
- displayName: "GLM-4 Flash (Free)",
1609
- contextWindow: 128e3,
1610
- supportsStreaming: true
1611
1599
  }
1612
1600
  ]
1613
1601
  };
@@ -1644,8 +1632,7 @@ var KimiProvider = class _KimiProvider extends OpenAICompatibleProvider {
1644
1632
  "kimi-k2.6",
1645
1633
  "kimi-k2.5",
1646
1634
  "kimi-k2-thinking",
1647
- "kimi-k2-thinking-turbo",
1648
- "kimi-k2-0905-preview"
1635
+ "kimi-k2-thinking-turbo"
1649
1636
  ]);
1650
1637
  /** 对需要固定 temperature=1 的模型自动修正请求。 */
1651
1638
  fixTemp(req) {
@@ -1693,51 +1680,6 @@ var KimiProvider = class _KimiProvider extends OpenAICompatibleProvider {
1693
1680
  displayName: "Kimi K2 Thinking Turbo",
1694
1681
  contextWindow: 262144,
1695
1682
  supportsStreaming: true
1696
- },
1697
- // Kimi K2 Preview 系列
1698
- {
1699
- id: "kimi-k2-0905-preview",
1700
- displayName: "Kimi K2 0905 Preview",
1701
- contextWindow: 262144,
1702
- supportsStreaming: true
1703
- },
1704
- // moonshot-v1 系列(老一代,稳定)
1705
- {
1706
- id: "moonshot-v1-8k",
1707
- displayName: "Moonshot V1 8K",
1708
- contextWindow: 8192,
1709
- supportsStreaming: true
1710
- },
1711
- {
1712
- id: "moonshot-v1-32k",
1713
- displayName: "Moonshot V1 32K",
1714
- contextWindow: 32768,
1715
- supportsStreaming: true
1716
- },
1717
- {
1718
- id: "moonshot-v1-128k",
1719
- displayName: "Moonshot V1 128K",
1720
- contextWindow: 131072,
1721
- supportsStreaming: true
1722
- },
1723
- // moonshot-v1 Vision 系列(支持图片输入)
1724
- {
1725
- id: "moonshot-v1-8k-vision-preview",
1726
- displayName: "Moonshot V1 8K Vision",
1727
- contextWindow: 8192,
1728
- supportsStreaming: true
1729
- },
1730
- {
1731
- id: "moonshot-v1-32k-vision-preview",
1732
- displayName: "Moonshot V1 32K Vision",
1733
- contextWindow: 32768,
1734
- supportsStreaming: true
1735
- },
1736
- {
1737
- id: "moonshot-v1-128k-vision-preview",
1738
- displayName: "Moonshot V1 128K Vision",
1739
- contextWindow: 131072,
1740
- supportsStreaming: true
1741
1683
  }
1742
1684
  ]
1743
1685
  };
@@ -1863,23 +1805,44 @@ var MiniMaxProvider = class extends OpenAICompatibleProvider {
1863
1805
  displayName: "MiniMax M2.5 Highspeed",
1864
1806
  contextWindow: 1e6,
1865
1807
  supportsStreaming: true
1808
+ }
1809
+ ]
1810
+ };
1811
+ };
1812
+
1813
+ // src/providers/qwen.ts
1814
+ var QwenProvider = class extends OpenAICompatibleProvider {
1815
+ defaultBaseUrl = "https://dashscope.aliyuncs.com/compatible-mode/v1";
1816
+ info = {
1817
+ id: "qwen",
1818
+ displayName: "Qwen (Alibaba Cloud)",
1819
+ defaultModel: "qwen-plus",
1820
+ apiKeyEnvVar: "AICLI_API_KEY_QWEN",
1821
+ requiresApiKey: true,
1822
+ baseUrl: this.defaultBaseUrl,
1823
+ models: [
1824
+ {
1825
+ id: "qwen-plus",
1826
+ displayName: "Qwen Plus",
1827
+ contextWindow: 131072,
1828
+ supportsStreaming: true
1866
1829
  },
1867
1830
  {
1868
- id: "MiniMax-M2.1",
1869
- displayName: "MiniMax M2.1",
1870
- contextWindow: 1e6,
1831
+ id: "qwen-max",
1832
+ displayName: "Qwen Max",
1833
+ contextWindow: 131072,
1871
1834
  supportsStreaming: true
1872
1835
  },
1873
1836
  {
1874
- id: "MiniMax-M2.1-highspeed",
1875
- displayName: "MiniMax M2.1 Highspeed",
1876
- contextWindow: 1e6,
1837
+ id: "qwen-turbo",
1838
+ displayName: "Qwen Turbo",
1839
+ contextWindow: 131072,
1877
1840
  supportsStreaming: true
1878
1841
  },
1879
1842
  {
1880
- id: "MiniMax-M2",
1881
- displayName: "MiniMax M2",
1882
- contextWindow: 1e6,
1843
+ id: "qwen-coder-plus",
1844
+ displayName: "Qwen Coder Plus",
1845
+ contextWindow: 131072,
1883
1846
  supportsStreaming: true
1884
1847
  }
1885
1848
  ]
@@ -1892,7 +1855,7 @@ var OpenAIProvider = class extends OpenAICompatibleProvider {
1892
1855
  info = {
1893
1856
  id: "openai",
1894
1857
  displayName: "OpenAI",
1895
- defaultModel: "gpt-4o",
1858
+ defaultModel: "gpt-5.4",
1896
1859
  apiKeyEnvVar: "AICLI_API_KEY_OPENAI",
1897
1860
  requiresApiKey: true,
1898
1861
  baseUrl: this.defaultBaseUrl,
@@ -1948,19 +1911,6 @@ var OpenAIProvider = class extends OpenAICompatibleProvider {
1948
1911
  contextWindow: 1048576,
1949
1912
  supportsStreaming: true
1950
1913
  },
1951
- // GPT-4o 系列(128K 上下文)
1952
- {
1953
- id: "gpt-4o",
1954
- displayName: "GPT-4o",
1955
- contextWindow: 128e3,
1956
- supportsStreaming: true
1957
- },
1958
- {
1959
- id: "gpt-4o-mini",
1960
- displayName: "GPT-4o Mini",
1961
- contextWindow: 128e3,
1962
- supportsStreaming: true
1963
- },
1964
1914
  // 推理模型(200K 上下文)
1965
1915
  {
1966
1916
  id: "o3",
@@ -1968,12 +1918,6 @@ var OpenAIProvider = class extends OpenAICompatibleProvider {
1968
1918
  contextWindow: 2e5,
1969
1919
  supportsStreaming: true
1970
1920
  },
1971
- {
1972
- id: "o3-mini",
1973
- displayName: "o3 Mini",
1974
- contextWindow: 2e5,
1975
- supportsStreaming: true
1976
- },
1977
1921
  {
1978
1922
  id: "o4-mini",
1979
1923
  displayName: "o4 Mini",
@@ -1995,7 +1939,6 @@ var OpenRouterProvider = class extends OpenAICompatibleProvider {
1995
1939
  requiresApiKey: true,
1996
1940
  baseUrl: this.defaultBaseUrl,
1997
1941
  models: [
1998
- // Anthropic Claude 系列
1999
1942
  {
2000
1943
  id: "anthropic/claude-opus-4",
2001
1944
  displayName: "Claude Opus 4",
@@ -2014,26 +1957,12 @@ var OpenRouterProvider = class extends OpenAICompatibleProvider {
2014
1957
  contextWindow: 2e5,
2015
1958
  supportsStreaming: true
2016
1959
  },
2017
- // OpenAI 系列
2018
1960
  {
2019
1961
  id: "openai/gpt-5.4",
2020
1962
  displayName: "GPT-5.4",
2021
1963
  contextWindow: 105e4,
2022
1964
  supportsStreaming: true
2023
1965
  },
2024
- {
2025
- id: "openai/gpt-4o",
2026
- displayName: "GPT-4o",
2027
- contextWindow: 128e3,
2028
- supportsStreaming: true
2029
- },
2030
- {
2031
- id: "openai/gpt-4o-mini",
2032
- displayName: "GPT-4o Mini",
2033
- contextWindow: 128e3,
2034
- supportsStreaming: true
2035
- },
2036
- // Google Gemini 系列
2037
1966
  {
2038
1967
  id: "google/gemini-2.5-pro",
2039
1968
  displayName: "Gemini 2.5 Pro",
@@ -2046,7 +1975,6 @@ var OpenRouterProvider = class extends OpenAICompatibleProvider {
2046
1975
  contextWindow: 1048576,
2047
1976
  supportsStreaming: true
2048
1977
  },
2049
- // Meta Llama 系列
2050
1978
  {
2051
1979
  id: "meta-llama/llama-4-maverick",
2052
1980
  displayName: "Llama 4 Maverick",
@@ -2059,44 +1987,17 @@ var OpenRouterProvider = class extends OpenAICompatibleProvider {
2059
1987
  contextWindow: 512e3,
2060
1988
  supportsStreaming: true
2061
1989
  },
2062
- // DeepSeek 系列
2063
- {
2064
- id: "deepseek/deepseek-chat-v3-0324",
2065
- displayName: "DeepSeek V3 0324",
2066
- contextWindow: 131072,
2067
- supportsStreaming: true
2068
- },
2069
- {
2070
- id: "deepseek/deepseek-r1",
2071
- displayName: "DeepSeek R1",
2072
- contextWindow: 163840,
2073
- supportsStreaming: true
2074
- },
2075
- // Qwen 系列
2076
1990
  {
2077
1991
  id: "qwen/qwen3-coder",
2078
1992
  displayName: "Qwen3 Coder",
2079
1993
  contextWindow: 262144,
2080
1994
  supportsStreaming: true
2081
1995
  },
2082
- {
2083
- id: "qwen/qwen-2.5-72b-instruct",
2084
- displayName: "Qwen 2.5 72B",
2085
- contextWindow: 131072,
2086
- supportsStreaming: true
2087
- },
2088
- // Mistral 系列
2089
1996
  {
2090
1997
  id: "mistralai/mistral-large",
2091
1998
  displayName: "Mistral Large",
2092
1999
  contextWindow: 131072,
2093
2000
  supportsStreaming: true
2094
- },
2095
- {
2096
- id: "mistralai/mistral-small-3.1-24b-instruct",
2097
- displayName: "Mistral Small 3.1 24B",
2098
- contextWindow: 128e3,
2099
- supportsStreaming: true
2100
2001
  }
2101
2002
  ]
2102
2003
  };
@@ -2181,6 +2082,10 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
2181
2082
  await this.tryConnect();
2182
2083
  return this.dynamicModels.length > 0 ? this.dynamicModels : this.info.models;
2183
2084
  }
2085
+ async refreshModels() {
2086
+ await this.tryConnect(false);
2087
+ return this.dynamicModels.length > 0 ? this.dynamicModels : this.info.models;
2088
+ }
2184
2089
  /** Ollama 无需验证 API Key,只检查服务是否可达 */
2185
2090
  async validateApiKey() {
2186
2091
  return this.tryConnect();
@@ -2221,6 +2126,111 @@ var CustomProvider = class extends OpenAICompatibleProvider {
2221
2126
  }
2222
2127
  };
2223
2128
 
2129
+ // src/providers/model-cache.ts
2130
+ import { existsSync, mkdirSync, readFileSync, unlinkSync } from "fs";
2131
+ import { dirname, join } from "path";
2132
+ var CACHE_FILE_NAME = "model-cache.json";
2133
+ var LIVE_DEFAULT_CONTEXT = 128e3;
2134
+ function modelCachePath(configDir) {
2135
+ return join(configDir, CACHE_FILE_NAME);
2136
+ }
2137
+ function loadModelCache(configDir) {
2138
+ const path = modelCachePath(configDir);
2139
+ if (!existsSync(path)) return { version: 1, providers: {} };
2140
+ try {
2141
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
2142
+ if (parsed.version !== 1 || !parsed.providers || typeof parsed.providers !== "object") {
2143
+ return { version: 1, providers: {} };
2144
+ }
2145
+ return { version: 1, providers: parsed.providers };
2146
+ } catch {
2147
+ return { version: 1, providers: {} };
2148
+ }
2149
+ }
2150
+ function saveModelCache(configDir, cache) {
2151
+ const path = modelCachePath(configDir);
2152
+ mkdirSync(dirname(path), { recursive: true });
2153
+ atomicWriteFileSync(path, `${JSON.stringify(cache, null, 2)}
2154
+ `);
2155
+ }
2156
+ function getCachedModels(configDir, providerId) {
2157
+ const entry = loadModelCache(configDir).providers[providerId];
2158
+ if (!entry) return [];
2159
+ return normalizeLiveModels(entry.models, entry.fetchedAt, "cache");
2160
+ }
2161
+ function getModelCacheSummary(configDir) {
2162
+ const cache = loadModelCache(configDir);
2163
+ return Object.entries(cache.providers).map(([providerId, entry]) => ({
2164
+ providerId,
2165
+ count: entry.models.length,
2166
+ fetchedAt: entry.fetchedAt,
2167
+ baseUrl: entry.baseUrl
2168
+ }));
2169
+ }
2170
+ function setCachedModels(configDir, providerId, models, baseUrl) {
2171
+ const cache = loadModelCache(configDir);
2172
+ const fetchedAt = (/* @__PURE__ */ new Date()).toISOString();
2173
+ const entry = {
2174
+ fetchedAt,
2175
+ ...baseUrl ? { baseUrl } : {},
2176
+ models: normalizeLiveModels(models, fetchedAt, "live"),
2177
+ lastError: null
2178
+ };
2179
+ cache.providers[providerId] = entry;
2180
+ saveModelCache(configDir, cache);
2181
+ return entry;
2182
+ }
2183
+ function clearModelCache(configDir, providerId) {
2184
+ const path = modelCachePath(configDir);
2185
+ if (!providerId) {
2186
+ if (existsSync(path)) unlinkSync(path);
2187
+ return;
2188
+ }
2189
+ const cache = loadModelCache(configDir);
2190
+ delete cache.providers[providerId];
2191
+ saveModelCache(configDir, cache);
2192
+ }
2193
+ function normalizeLiveModels(models, fetchedAt, source = "live") {
2194
+ const seen = /* @__PURE__ */ new Set();
2195
+ const normalized = [];
2196
+ for (const model of models) {
2197
+ if (!model.id || seen.has(model.id)) continue;
2198
+ seen.add(model.id);
2199
+ normalized.push({
2200
+ id: model.id,
2201
+ displayName: model.displayName || model.id,
2202
+ contextWindow: model.contextWindow || LIVE_DEFAULT_CONTEXT,
2203
+ supportsStreaming: model.supportsStreaming ?? true,
2204
+ ...model.supportsThinking !== void 0 ? { supportsThinking: model.supportsThinking } : {},
2205
+ source,
2206
+ available: true,
2207
+ metadataUnknown: model.metadataUnknown ?? !model.contextWindow,
2208
+ ...fetchedAt ? { fetchedAt } : {}
2209
+ });
2210
+ }
2211
+ return normalized;
2212
+ }
2213
+ function mergeModelLists(curatedModels, liveModels) {
2214
+ const liveById = new Map(liveModels.map((model) => [model.id, model]));
2215
+ const merged = curatedModels.map((model) => ({
2216
+ ...model,
2217
+ source: liveById.has(model.id) ? "curated+live" : model.source ?? "curated",
2218
+ available: liveById.has(model.id) ? true : model.available ?? "unknown",
2219
+ fetchedAt: liveById.get(model.id)?.fetchedAt
2220
+ }));
2221
+ const curatedIds = new Set(curatedModels.map((model) => model.id));
2222
+ for (const model of liveModels) {
2223
+ if (curatedIds.has(model.id)) continue;
2224
+ merged.push({
2225
+ ...model,
2226
+ source: model.source ?? "live",
2227
+ available: true,
2228
+ metadataUnknown: model.metadataUnknown ?? true
2229
+ });
2230
+ }
2231
+ return merged;
2232
+ }
2233
+
2224
2234
  // src/providers/registry.ts
2225
2235
  var BUILT_IN_PROVIDERS = [
2226
2236
  ClaudeProvider,
@@ -2229,15 +2239,17 @@ var BUILT_IN_PROVIDERS = [
2229
2239
  ZhipuProvider,
2230
2240
  KimiProvider,
2231
2241
  MiniMaxProvider,
2242
+ QwenProvider,
2232
2243
  OpenAIProvider,
2233
2244
  OpenRouterProvider,
2234
2245
  OllamaProvider
2235
2246
  ];
2236
2247
  var ProviderRegistry = class {
2237
2248
  providers = /* @__PURE__ */ new Map();
2238
- // 记录自定义 provider 的状态(用于 listAll 展示)
2239
2249
  customConfigs = [];
2240
- async initialize(getApiKey, getOptions, customProviderConfigs) {
2250
+ configDir;
2251
+ async initialize(getApiKey, getOptions, customProviderConfigs, configDir) {
2252
+ this.configDir = configDir;
2241
2253
  for (const ProviderClass of BUILT_IN_PROVIDERS) {
2242
2254
  const provider = new ProviderClass();
2243
2255
  const apiKey = getApiKey(provider.info.id);
@@ -2264,11 +2276,6 @@ var ProviderRegistry = class {
2264
2276
  this.providers.set(cfg.id, provider);
2265
2277
  }
2266
2278
  }
2267
- /**
2268
- * Register a provider instance under the given id (overwrites any existing).
2269
- * Primary uses: integration tests injecting MockProvider, and future hot-swap
2270
- * scenarios. The provider is assumed already initialized.
2271
- */
2272
2279
  register(id, provider) {
2273
2280
  this.providers.set(id, provider);
2274
2281
  }
@@ -2282,6 +2289,37 @@ var ProviderRegistry = class {
2282
2289
  has(id) {
2283
2290
  return this.providers.has(id);
2284
2291
  }
2292
+ async listModels(providerId) {
2293
+ const provider = this.get(providerId);
2294
+ const curated = await provider.listModels();
2295
+ if (!this.configDir) return curated;
2296
+ const cached = getCachedModels(this.configDir, providerId);
2297
+ return cached.length > 0 ? mergeModelLists(curated, cached) : curated;
2298
+ }
2299
+ async refreshModels(providerId) {
2300
+ const provider = this.get(providerId);
2301
+ if (!provider.refreshModels) {
2302
+ throw new Error(`Provider ${providerId} does not support model refresh`);
2303
+ }
2304
+ const liveModels = await provider.refreshModels();
2305
+ if (!this.configDir) {
2306
+ const merged2 = mergeModelLists(await provider.listModels(), liveModels);
2307
+ provider.info.models = merged2;
2308
+ return merged2;
2309
+ }
2310
+ setCachedModels(this.configDir, providerId, liveModels, provider.info.baseUrl);
2311
+ const merged = await this.listModels(providerId);
2312
+ provider.info.models = merged;
2313
+ return merged;
2314
+ }
2315
+ getModelCacheStatus() {
2316
+ if (!this.configDir) return [];
2317
+ return getModelCacheSummary(this.configDir);
2318
+ }
2319
+ clearModelCache(providerId) {
2320
+ if (!this.configDir) return;
2321
+ clearModelCache(this.configDir, providerId);
2322
+ }
2285
2323
  listAvailable() {
2286
2324
  return [...this.providers.values()];
2287
2325
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.218";
4
+ var VERSION = "0.4.220";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";