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.
- package/README.md +102 -99
- package/README.zh-CN.md +40 -38
- package/dist/{batch-7V7OTMUP.js → batch-QBSKTLTO.js} +3 -3
- package/dist/{chunk-TZQHYZKT.js → chunk-5ULLIOVC.js} +1 -0
- package/dist/{chunk-P4VBLXKS.js → chunk-5WBNXYDJ.js} +2 -2
- package/dist/chunk-ALQN7VUJ.js +604 -0
- package/dist/{chunk-C2Z42DI5.js → chunk-CAUHLHDR.js} +1 -1
- package/dist/{chunk-GX3HSGJX.js → chunk-IZW5LMI6.js} +166 -638
- package/dist/chunk-P3LKFA54.js +639 -0
- package/dist/{chunk-5CA2TJ5F.js → chunk-P4DYAGUI.js} +1 -1
- package/dist/{chunk-L4UREAID.js → chunk-P4PTXCHY.js} +6 -5
- package/dist/{chunk-QMXC327F.js → chunk-PUBCJF7E.js} +213 -175
- package/dist/{chunk-NTCB7CMT.js → chunk-QZYNRCPX.js} +1 -1
- package/dist/{chunk-H2UIHGHH.js → chunk-VHX7KZDY.js} +29 -189
- package/dist/{chunk-VGFTM3XT.js → chunk-Y25MSSUP.js} +1 -1
- package/dist/{ci-L6GH2WVC.js → ci-5SNXGM3M.js} +6 -6
- package/dist/{ci-format-WW7454AY.js → ci-format-57QQTHQE.js} +2 -2
- package/dist/{constants-NCTFSHDU.js → constants-ML5KFEOH.js} +1 -1
- package/dist/doctor-cli-ZRH3XZ3R.js +17 -0
- package/dist/electron-server.js +836 -470
- package/dist/{hub-CDL6T7CP.js → hub-IPLMJ6TJ.js} +1 -1
- package/dist/index.js +125 -194
- package/dist/{pr-D6PEKEGK.js → pr-GJYDAPK4.js} +8 -7
- package/dist/{run-tests-NXVVKAK2.js → run-tests-GK5AIAV2.js} +1 -1
- package/dist/{run-tests-SWU2XEV7.js → run-tests-KLQAI5CX.js} +2 -2
- package/dist/{server-WUT7VYTD.js → server-5FZDALHH.js} +10 -10
- package/dist/{server-LHYSS6CK.js → server-RU36PRSH.js} +74 -83
- package/dist/{task-orchestrator-C5AA2BI5.js → task-orchestrator-JMHPVNUO.js} +10 -10
- package/dist/{usage-6ZUUJBI2.js → usage-IRMRCCKN.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-MWKE2TNS.js +0 -129
- package/dist/chunk-OUC75QCF.js +0 -166
- 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-
|
|
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: "
|
|
1869
|
-
displayName: "
|
|
1870
|
-
contextWindow:
|
|
1831
|
+
id: "qwen-max",
|
|
1832
|
+
displayName: "Qwen Max",
|
|
1833
|
+
contextWindow: 131072,
|
|
1871
1834
|
supportsStreaming: true
|
|
1872
1835
|
},
|
|
1873
1836
|
{
|
|
1874
|
-
id: "
|
|
1875
|
-
displayName: "
|
|
1876
|
-
contextWindow:
|
|
1837
|
+
id: "qwen-turbo",
|
|
1838
|
+
displayName: "Qwen Turbo",
|
|
1839
|
+
contextWindow: 131072,
|
|
1877
1840
|
supportsStreaming: true
|
|
1878
1841
|
},
|
|
1879
1842
|
{
|
|
1880
|
-
id: "
|
|
1881
|
-
displayName: "
|
|
1882
|
-
contextWindow:
|
|
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-
|
|
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
|
-
|
|
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
|
}
|