@clinebot/llms 0.0.18 → 0.0.21

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 (319) hide show
  1. package/dist/config-browser.d.ts +1 -0
  2. package/dist/config-browser.d.ts.map +1 -0
  3. package/dist/config.d.ts +1 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/index.browser.d.ts +1 -0
  6. package/dist/index.browser.d.ts.map +1 -0
  7. package/dist/index.browser.js +5 -5
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +12 -12
  11. package/dist/models/generated-access.d.ts +1 -0
  12. package/dist/models/generated-access.d.ts.map +1 -0
  13. package/dist/models/generated-provider-loaders.d.ts +1 -0
  14. package/dist/models/generated-provider-loaders.d.ts.map +1 -0
  15. package/dist/models/generated.d.ts +1 -0
  16. package/dist/models/generated.d.ts.map +1 -0
  17. package/dist/models/index.d.ts +1 -0
  18. package/dist/models/index.d.ts.map +1 -0
  19. package/dist/models/models-dev-catalog.d.ts +1 -0
  20. package/dist/models/models-dev-catalog.d.ts.map +1 -0
  21. package/dist/models/providers/aihubmix.d.ts +1 -0
  22. package/dist/models/providers/aihubmix.d.ts.map +1 -0
  23. package/dist/models/providers/anthropic.d.ts +1 -0
  24. package/dist/models/providers/anthropic.d.ts.map +1 -0
  25. package/dist/models/providers/asksage.d.ts +1 -0
  26. package/dist/models/providers/asksage.d.ts.map +1 -0
  27. package/dist/models/providers/baseten.d.ts +1 -0
  28. package/dist/models/providers/baseten.d.ts.map +1 -0
  29. package/dist/models/providers/bedrock.d.ts +1 -0
  30. package/dist/models/providers/bedrock.d.ts.map +1 -0
  31. package/dist/models/providers/cerebras.d.ts +1 -0
  32. package/dist/models/providers/cerebras.d.ts.map +1 -0
  33. package/dist/models/providers/claude-code.d.ts +1 -0
  34. package/dist/models/providers/claude-code.d.ts.map +1 -0
  35. package/dist/models/providers/cline.d.ts +1 -0
  36. package/dist/models/providers/cline.d.ts.map +1 -0
  37. package/dist/models/providers/deepseek.d.ts +1 -0
  38. package/dist/models/providers/deepseek.d.ts.map +1 -0
  39. package/dist/models/providers/dify.d.ts +1 -0
  40. package/dist/models/providers/dify.d.ts.map +1 -0
  41. package/dist/models/providers/doubao.d.ts +1 -0
  42. package/dist/models/providers/doubao.d.ts.map +1 -0
  43. package/dist/models/providers/fireworks.d.ts +1 -0
  44. package/dist/models/providers/fireworks.d.ts.map +1 -0
  45. package/dist/models/providers/gemini.d.ts +1 -0
  46. package/dist/models/providers/gemini.d.ts.map +1 -0
  47. package/dist/models/providers/groq.d.ts +1 -0
  48. package/dist/models/providers/groq.d.ts.map +1 -0
  49. package/dist/models/providers/hicap.d.ts +1 -0
  50. package/dist/models/providers/hicap.d.ts.map +1 -0
  51. package/dist/models/providers/huawei-cloud-maas.d.ts +1 -0
  52. package/dist/models/providers/huawei-cloud-maas.d.ts.map +1 -0
  53. package/dist/models/providers/huggingface.d.ts +1 -0
  54. package/dist/models/providers/huggingface.d.ts.map +1 -0
  55. package/dist/models/providers/index.d.ts +1 -0
  56. package/dist/models/providers/index.d.ts.map +1 -0
  57. package/dist/models/providers/litellm.d.ts +1 -0
  58. package/dist/models/providers/litellm.d.ts.map +1 -0
  59. package/dist/models/providers/lmstudio.d.ts +1 -0
  60. package/dist/models/providers/lmstudio.d.ts.map +1 -0
  61. package/dist/models/providers/minimax.d.ts +1 -0
  62. package/dist/models/providers/minimax.d.ts.map +1 -0
  63. package/dist/models/providers/mistral.d.ts +1 -0
  64. package/dist/models/providers/mistral.d.ts.map +1 -0
  65. package/dist/models/providers/moonshot.d.ts +1 -0
  66. package/dist/models/providers/moonshot.d.ts.map +1 -0
  67. package/dist/models/providers/nebius.d.ts +1 -0
  68. package/dist/models/providers/nebius.d.ts.map +1 -0
  69. package/dist/models/providers/nous-research.d.ts +1 -0
  70. package/dist/models/providers/nous-research.d.ts.map +1 -0
  71. package/dist/models/providers/oca.d.ts +1 -0
  72. package/dist/models/providers/oca.d.ts.map +1 -0
  73. package/dist/models/providers/ollama.d.ts +1 -0
  74. package/dist/models/providers/ollama.d.ts.map +1 -0
  75. package/dist/models/providers/openai-codex.d.ts +1 -0
  76. package/dist/models/providers/openai-codex.d.ts.map +1 -0
  77. package/dist/models/providers/openai.d.ts +1 -0
  78. package/dist/models/providers/openai.d.ts.map +1 -0
  79. package/dist/models/providers/opencode.d.ts +1 -0
  80. package/dist/models/providers/opencode.d.ts.map +1 -0
  81. package/dist/models/providers/openrouter.d.ts +1 -0
  82. package/dist/models/providers/openrouter.d.ts.map +1 -0
  83. package/dist/models/providers/qwen-code.d.ts +1 -0
  84. package/dist/models/providers/qwen-code.d.ts.map +1 -0
  85. package/dist/models/providers/qwen.d.ts +1 -0
  86. package/dist/models/providers/qwen.d.ts.map +1 -0
  87. package/dist/models/providers/requesty.d.ts +1 -0
  88. package/dist/models/providers/requesty.d.ts.map +1 -0
  89. package/dist/models/providers/sambanova.d.ts +1 -0
  90. package/dist/models/providers/sambanova.d.ts.map +1 -0
  91. package/dist/models/providers/sapaicore.d.ts +1 -0
  92. package/dist/models/providers/sapaicore.d.ts.map +1 -0
  93. package/dist/models/providers/together.d.ts +1 -0
  94. package/dist/models/providers/together.d.ts.map +1 -0
  95. package/dist/models/providers/vercel-ai-gateway.d.ts +1 -0
  96. package/dist/models/providers/vercel-ai-gateway.d.ts.map +1 -0
  97. package/dist/models/providers/vertex.d.ts +1 -0
  98. package/dist/models/providers/vertex.d.ts.map +1 -0
  99. package/dist/models/providers/xai.d.ts +1 -0
  100. package/dist/models/providers/xai.d.ts.map +1 -0
  101. package/dist/models/providers/zai.d.ts +1 -0
  102. package/dist/models/providers/zai.d.ts.map +1 -0
  103. package/dist/models/query.d.ts +1 -0
  104. package/dist/models/query.d.ts.map +1 -0
  105. package/dist/models/registry.d.ts +1 -0
  106. package/dist/models/registry.d.ts.map +1 -0
  107. package/dist/models/schemas/index.d.ts +1 -0
  108. package/dist/models/schemas/index.d.ts.map +1 -0
  109. package/dist/models/schemas/model.d.ts +1 -0
  110. package/dist/models/schemas/model.d.ts.map +1 -0
  111. package/dist/models/schemas/query.d.ts +1 -0
  112. package/dist/models/schemas/query.d.ts.map +1 -0
  113. package/dist/providers/handlers/ai-sdk-community.d.ts +1 -0
  114. package/dist/providers/handlers/ai-sdk-community.d.ts.map +1 -0
  115. package/dist/providers/handlers/ai-sdk-provider-base.d.ts +1 -0
  116. package/dist/providers/handlers/ai-sdk-provider-base.d.ts.map +1 -0
  117. package/dist/providers/handlers/anthropic-base.d.ts +1 -0
  118. package/dist/providers/handlers/anthropic-base.d.ts.map +1 -0
  119. package/dist/providers/handlers/asksage.d.ts +1 -0
  120. package/dist/providers/handlers/asksage.d.ts.map +1 -0
  121. package/dist/providers/handlers/auth.d.ts +1 -0
  122. package/dist/providers/handlers/auth.d.ts.map +1 -0
  123. package/dist/providers/handlers/base.d.ts +1 -0
  124. package/dist/providers/handlers/base.d.ts.map +1 -0
  125. package/dist/providers/handlers/bedrock-base.d.ts +1 -0
  126. package/dist/providers/handlers/bedrock-base.d.ts.map +1 -0
  127. package/dist/providers/handlers/bedrock-client.d.ts +1 -0
  128. package/dist/providers/handlers/bedrock-client.d.ts.map +1 -0
  129. package/dist/providers/handlers/community-sdk.d.ts +1 -0
  130. package/dist/providers/handlers/community-sdk.d.ts.map +1 -0
  131. package/dist/providers/handlers/fetch-base.d.ts +1 -0
  132. package/dist/providers/handlers/fetch-base.d.ts.map +1 -0
  133. package/dist/providers/handlers/gemini-base.d.ts +1 -0
  134. package/dist/providers/handlers/gemini-base.d.ts.map +1 -0
  135. package/dist/providers/handlers/index.d.ts +1 -0
  136. package/dist/providers/handlers/index.d.ts.map +1 -0
  137. package/dist/providers/handlers/openai-base.d.ts +1 -0
  138. package/dist/providers/handlers/openai-base.d.ts.map +1 -0
  139. package/dist/providers/handlers/openai-responses.d.ts +1 -0
  140. package/dist/providers/handlers/openai-responses.d.ts.map +1 -0
  141. package/dist/providers/handlers/providers.d.ts +1 -0
  142. package/dist/providers/handlers/providers.d.ts.map +1 -0
  143. package/dist/providers/handlers/r1-base.d.ts +1 -0
  144. package/dist/providers/handlers/r1-base.d.ts.map +1 -0
  145. package/dist/providers/handlers/registry.d.ts +1 -0
  146. package/dist/providers/handlers/registry.d.ts.map +1 -0
  147. package/dist/providers/handlers/vertex.d.ts +1 -0
  148. package/dist/providers/handlers/vertex.d.ts.map +1 -0
  149. package/dist/providers/index.d.ts +1 -0
  150. package/dist/providers/index.d.ts.map +1 -0
  151. package/dist/providers/public.browser.d.ts +1 -0
  152. package/dist/providers/public.browser.d.ts.map +1 -0
  153. package/dist/providers/public.d.ts +1 -0
  154. package/dist/providers/public.d.ts.map +1 -0
  155. package/dist/providers/shared/openai-compatible.d.ts +1 -0
  156. package/dist/providers/shared/openai-compatible.d.ts.map +1 -0
  157. package/dist/providers/transform/ai-sdk-community-format.d.ts +1 -0
  158. package/dist/providers/transform/ai-sdk-community-format.d.ts.map +1 -0
  159. package/dist/providers/transform/anthropic-format.d.ts +1 -0
  160. package/dist/providers/transform/anthropic-format.d.ts.map +1 -0
  161. package/dist/providers/transform/content-format.d.ts +1 -0
  162. package/dist/providers/transform/content-format.d.ts.map +1 -0
  163. package/dist/providers/transform/gemini-format.d.ts +1 -0
  164. package/dist/providers/transform/gemini-format.d.ts.map +1 -0
  165. package/dist/providers/transform/index.d.ts +1 -0
  166. package/dist/providers/transform/index.d.ts.map +1 -0
  167. package/dist/providers/transform/openai-format.d.ts +1 -0
  168. package/dist/providers/transform/openai-format.d.ts.map +1 -0
  169. package/dist/providers/transform/r1-format.d.ts +1 -0
  170. package/dist/providers/transform/r1-format.d.ts.map +1 -0
  171. package/dist/providers/types/config.d.ts +1 -0
  172. package/dist/providers/types/config.d.ts.map +1 -0
  173. package/dist/providers/types/handler.d.ts +1 -0
  174. package/dist/providers/types/handler.d.ts.map +1 -0
  175. package/dist/providers/types/index.d.ts +1 -0
  176. package/dist/providers/types/index.d.ts.map +1 -0
  177. package/dist/providers/types/messages.d.ts +1 -0
  178. package/dist/providers/types/messages.d.ts.map +1 -0
  179. package/dist/providers/types/model-info.d.ts +1 -0
  180. package/dist/providers/types/model-info.d.ts.map +1 -0
  181. package/dist/providers/types/provider-ids.d.ts +1 -1
  182. package/dist/providers/types/provider-ids.d.ts.map +1 -0
  183. package/dist/providers/types/settings.d.ts +1 -0
  184. package/dist/providers/types/settings.d.ts.map +1 -0
  185. package/dist/providers/types/stream.d.ts +1 -0
  186. package/dist/providers/types/stream.d.ts.map +1 -0
  187. package/dist/providers/utils/index.d.ts +1 -0
  188. package/dist/providers/utils/index.d.ts.map +1 -0
  189. package/dist/providers/utils/retry.d.ts +1 -0
  190. package/dist/providers/utils/retry.d.ts.map +1 -0
  191. package/dist/providers/utils/stream-processor.d.ts +1 -0
  192. package/dist/providers/utils/stream-processor.d.ts.map +1 -0
  193. package/dist/providers/utils/tool-processor.d.ts +1 -0
  194. package/dist/providers/utils/tool-processor.d.ts.map +1 -0
  195. package/dist/sdk.d.ts +1 -0
  196. package/dist/sdk.d.ts.map +1 -0
  197. package/dist/types.d.ts +1 -0
  198. package/dist/types.d.ts.map +1 -0
  199. package/package.json +3 -4
  200. package/src/catalog.ts +0 -20
  201. package/src/config-browser.ts +0 -11
  202. package/src/config.ts +0 -49
  203. package/src/index.browser.ts +0 -9
  204. package/src/index.ts +0 -10
  205. package/src/live-providers.test.ts +0 -138
  206. package/src/models/generated-access.ts +0 -41
  207. package/src/models/generated-provider-loaders.ts +0 -166
  208. package/src/models/generated.ts +0 -11785
  209. package/src/models/index.ts +0 -271
  210. package/src/models/models-dev-catalog.test.ts +0 -161
  211. package/src/models/models-dev-catalog.ts +0 -168
  212. package/src/models/providers/aihubmix.ts +0 -19
  213. package/src/models/providers/anthropic.ts +0 -60
  214. package/src/models/providers/asksage.ts +0 -19
  215. package/src/models/providers/baseten.ts +0 -21
  216. package/src/models/providers/bedrock.ts +0 -30
  217. package/src/models/providers/cerebras.ts +0 -24
  218. package/src/models/providers/claude-code.ts +0 -51
  219. package/src/models/providers/cline.ts +0 -25
  220. package/src/models/providers/deepseek.ts +0 -33
  221. package/src/models/providers/dify.ts +0 -17
  222. package/src/models/providers/doubao.ts +0 -33
  223. package/src/models/providers/fireworks.ts +0 -34
  224. package/src/models/providers/gemini.ts +0 -43
  225. package/src/models/providers/groq.ts +0 -33
  226. package/src/models/providers/hicap.ts +0 -18
  227. package/src/models/providers/huawei-cloud-maas.ts +0 -18
  228. package/src/models/providers/huggingface.ts +0 -22
  229. package/src/models/providers/index.ts +0 -162
  230. package/src/models/providers/litellm.ts +0 -19
  231. package/src/models/providers/lmstudio.ts +0 -22
  232. package/src/models/providers/minimax.ts +0 -34
  233. package/src/models/providers/mistral.ts +0 -19
  234. package/src/models/providers/moonshot.ts +0 -34
  235. package/src/models/providers/nebius.ts +0 -24
  236. package/src/models/providers/nous-research.ts +0 -21
  237. package/src/models/providers/oca.ts +0 -30
  238. package/src/models/providers/ollama.ts +0 -18
  239. package/src/models/providers/openai-codex.ts +0 -46
  240. package/src/models/providers/openai.ts +0 -43
  241. package/src/models/providers/opencode.ts +0 -28
  242. package/src/models/providers/openrouter.ts +0 -24
  243. package/src/models/providers/qwen-code.ts +0 -33
  244. package/src/models/providers/qwen.ts +0 -34
  245. package/src/models/providers/requesty.ts +0 -23
  246. package/src/models/providers/sambanova.ts +0 -23
  247. package/src/models/providers/sapaicore.ts +0 -34
  248. package/src/models/providers/together.ts +0 -35
  249. package/src/models/providers/vercel-ai-gateway.ts +0 -23
  250. package/src/models/providers/vertex.ts +0 -36
  251. package/src/models/providers/xai.ts +0 -34
  252. package/src/models/providers/zai.ts +0 -25
  253. package/src/models/query.ts +0 -407
  254. package/src/models/registry.ts +0 -511
  255. package/src/models/schemas/index.ts +0 -62
  256. package/src/models/schemas/model.ts +0 -308
  257. package/src/models/schemas/query.ts +0 -336
  258. package/src/providers/browser.ts +0 -4
  259. package/src/providers/handlers/ai-sdk-community.ts +0 -229
  260. package/src/providers/handlers/ai-sdk-provider-base.ts +0 -203
  261. package/src/providers/handlers/anthropic-base.test.ts +0 -30
  262. package/src/providers/handlers/anthropic-base.ts +0 -387
  263. package/src/providers/handlers/asksage.test.ts +0 -103
  264. package/src/providers/handlers/asksage.ts +0 -138
  265. package/src/providers/handlers/auth.test.ts +0 -19
  266. package/src/providers/handlers/auth.ts +0 -121
  267. package/src/providers/handlers/base.test.ts +0 -230
  268. package/src/providers/handlers/base.ts +0 -310
  269. package/src/providers/handlers/bedrock-base.ts +0 -390
  270. package/src/providers/handlers/bedrock-client.ts +0 -100
  271. package/src/providers/handlers/codex.test.ts +0 -160
  272. package/src/providers/handlers/community-sdk.test.ts +0 -321
  273. package/src/providers/handlers/community-sdk.ts +0 -391
  274. package/src/providers/handlers/fetch-base.ts +0 -68
  275. package/src/providers/handlers/gemini-base.test.ts +0 -261
  276. package/src/providers/handlers/gemini-base.ts +0 -307
  277. package/src/providers/handlers/index.ts +0 -67
  278. package/src/providers/handlers/openai-base.ts +0 -341
  279. package/src/providers/handlers/openai-responses.test.ts +0 -259
  280. package/src/providers/handlers/openai-responses.ts +0 -634
  281. package/src/providers/handlers/providers.test.ts +0 -120
  282. package/src/providers/handlers/providers.ts +0 -563
  283. package/src/providers/handlers/r1-base.ts +0 -283
  284. package/src/providers/handlers/registry.ts +0 -185
  285. package/src/providers/handlers/vertex.test.ts +0 -124
  286. package/src/providers/handlers/vertex.ts +0 -302
  287. package/src/providers/index.ts +0 -534
  288. package/src/providers/public.browser.ts +0 -20
  289. package/src/providers/public.ts +0 -51
  290. package/src/providers/shared/openai-compatible.ts +0 -63
  291. package/src/providers/transform/ai-sdk-community-format.test.ts +0 -73
  292. package/src/providers/transform/ai-sdk-community-format.ts +0 -115
  293. package/src/providers/transform/anthropic-format.ts +0 -230
  294. package/src/providers/transform/content-format.ts +0 -34
  295. package/src/providers/transform/format-conversion.test.ts +0 -413
  296. package/src/providers/transform/gemini-format.ts +0 -262
  297. package/src/providers/transform/index.ts +0 -22
  298. package/src/providers/transform/openai-format.ts +0 -290
  299. package/src/providers/transform/r1-format.ts +0 -287
  300. package/src/providers/types/config.ts +0 -396
  301. package/src/providers/types/handler.ts +0 -92
  302. package/src/providers/types/index.ts +0 -120
  303. package/src/providers/types/messages.ts +0 -162
  304. package/src/providers/types/model-info.test.ts +0 -57
  305. package/src/providers/types/model-info.ts +0 -65
  306. package/src/providers/types/provider-ids.test.ts +0 -12
  307. package/src/providers/types/provider-ids.ts +0 -89
  308. package/src/providers/types/settings.test.ts +0 -49
  309. package/src/providers/types/settings.ts +0 -533
  310. package/src/providers/types/stream.ts +0 -117
  311. package/src/providers/utils/index.ts +0 -27
  312. package/src/providers/utils/retry.test.ts +0 -140
  313. package/src/providers/utils/retry.ts +0 -188
  314. package/src/providers/utils/stream-processor.test.ts +0 -232
  315. package/src/providers/utils/stream-processor.ts +0 -472
  316. package/src/providers/utils/tool-processor.test.ts +0 -235
  317. package/src/providers/utils/tool-processor.ts +0 -146
  318. package/src/sdk.ts +0 -264
  319. package/src/types.ts +0 -79
@@ -1,120 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
- import type { ModelInfo, ProviderConfig } from "../types/index";
3
- import {
4
- clearLiveModelsCatalogCache,
5
- clearPrivateModelsCatalogCache,
6
- OPENAI_COMPATIBLE_PROVIDERS,
7
- resolveProviderConfig,
8
- } from "./providers";
9
-
10
- function createLiteLlmConfig(
11
- overrides?: Partial<ProviderConfig>,
12
- ): ProviderConfig {
13
- return {
14
- providerId: "litellm",
15
- modelId: "gpt-4o",
16
- apiKey: "test-key",
17
- baseUrl: "http://localhost:4000",
18
- ...overrides,
19
- };
20
- }
21
-
22
- describe("resolveProviderConfig", () => {
23
- const originalFetch = globalThis.fetch;
24
-
25
- beforeEach(() => {
26
- clearLiveModelsCatalogCache();
27
- clearPrivateModelsCatalogCache();
28
- });
29
-
30
- afterEach(() => {
31
- globalThis.fetch = originalFetch;
32
- vi.restoreAllMocks();
33
- });
34
-
35
- it("loads auth-gated private models and gives user knownModels highest priority", async () => {
36
- const fetchMock = vi.fn(async () => ({
37
- ok: true,
38
- json: async () => ({
39
- data: [
40
- {
41
- model_name: "gpt-4o",
42
- litellm_params: { model: "gpt-4o" },
43
- model_info: {
44
- max_tokens: 32000,
45
- max_input_tokens: 128000,
46
- },
47
- },
48
- ],
49
- }),
50
- }));
51
- globalThis.fetch = fetchMock as unknown as typeof fetch;
52
-
53
- const userModel: ModelInfo = {
54
- id: "gpt-4o",
55
- name: "User Override",
56
- contextWindow: 999_999,
57
- maxTokens: 9_999,
58
- capabilities: ["streaming", "tools"],
59
- };
60
-
61
- const resolved = await resolveProviderConfig(
62
- "litellm",
63
- { loadPrivateOnAuth: true },
64
- createLiteLlmConfig({
65
- knownModels: {
66
- "gpt-4o": userModel,
67
- },
68
- }),
69
- );
70
-
71
- expect(fetchMock).toHaveBeenCalledTimes(1);
72
- expect(resolved?.knownModels?.["gpt-4o"]).toEqual(userModel);
73
- });
74
-
75
- it("caches auth-gated private model responses by provider+baseUrl+token", async () => {
76
- const fetchMock = vi.fn(async () => ({
77
- ok: true,
78
- json: async () => ({
79
- data: [
80
- {
81
- model_name: "proxy-model",
82
- litellm_params: { model: "proxy-model" },
83
- model_info: {},
84
- },
85
- ],
86
- }),
87
- }));
88
- globalThis.fetch = fetchMock as unknown as typeof fetch;
89
-
90
- const config = createLiteLlmConfig();
91
- await resolveProviderConfig("litellm", { loadPrivateOnAuth: true }, config);
92
- await resolveProviderConfig("litellm", { loadPrivateOnAuth: true }, config);
93
-
94
- expect(fetchMock).toHaveBeenCalledTimes(1);
95
- });
96
-
97
- it("does not load auth-gated private models when disabled", async () => {
98
- const fetchMock = vi.fn();
99
- globalThis.fetch = fetchMock as unknown as typeof fetch;
100
-
101
- await resolveProviderConfig(
102
- "litellm",
103
- { loadPrivateOnAuth: false },
104
- createLiteLlmConfig(),
105
- );
106
-
107
- expect(fetchMock).not.toHaveBeenCalled();
108
- });
109
-
110
- it("includes lmstudio and zai as OpenAI-compatible providers", () => {
111
- expect(OPENAI_COMPATIBLE_PROVIDERS).toHaveProperty("lmstudio");
112
- expect(OPENAI_COMPATIBLE_PROVIDERS).toHaveProperty("zai");
113
- expect(OPENAI_COMPATIBLE_PROVIDERS.lmstudio?.baseUrl).toBe(
114
- "http://localhost:1234/v1",
115
- );
116
- expect(OPENAI_COMPATIBLE_PROVIDERS.zai?.baseUrl).toBe(
117
- "https://api.z.ai/api/paas/v4",
118
- );
119
- });
120
- });
@@ -1,563 +0,0 @@
1
- /**
2
- * Provider Configurations
3
- *
4
- * Pre-configured settings for all supported OpenAI-compatible providers.
5
- * Model data is sourced from @clinebot/models (the single registry).
6
- */
7
- /** biome-ignore-all lint/style/noNonNullAssertion: static */
8
-
9
- import {
10
- MODELS_DEV_PROVIDER_KEY_MAP,
11
- resolveProviderModelCatalogKeys,
12
- } from "@clinebot/shared";
13
- import {
14
- fetchModelsDevProviderModels,
15
- sortModelsByReleaseDate,
16
- } from "../../models/models-dev-catalog";
17
- import {
18
- buildOpenAICompatibleProviderDefaults,
19
- type OpenAICompatibleProviderDefaults,
20
- } from "../shared/openai-compatible";
21
- import type {
22
- ModelCatalogConfig,
23
- ModelInfo,
24
- ProviderCapability,
25
- ProviderConfig,
26
- } from "../types/index";
27
-
28
- /**
29
- * Provider defaults for OpenAI-compatible providers
30
- */
31
- export interface ProviderDefaults {
32
- /** Base URL for the API */
33
- baseUrl: string;
34
- /** Default model ID */
35
- modelId: string;
36
- /** Known models with their info */
37
- knownModels?: Record<string, ModelInfo>;
38
- /** Capabilities this provider supports */
39
- capabilities?: ProviderCapability[];
40
- }
41
-
42
- export const DEFAULT_MODELS_CATALOG_URL = "https://models.dev/api.json";
43
- const DEFAULT_MODELS_CATALOG_CACHE_TTL_MS = 10 * 60 * 1000;
44
- const DEFAULT_PRIVATE_MODELS_CACHE_TTL_MS = 5 * 60 * 1000;
45
-
46
- const MODELS_CATALOG_CACHE = new Map<
47
- string,
48
- { expiresAt: number; data: Record<string, Record<string, ModelInfo>> }
49
- >();
50
- const MODELS_CATALOG_IN_FLIGHT = new Map<
51
- string,
52
- Promise<Record<string, Record<string, ModelInfo>>>
53
- >();
54
- const PRIVATE_MODELS_CACHE = new Map<
55
- string,
56
- { expiresAt: number; data: Record<string, ModelInfo> }
57
- >();
58
- const PRIVATE_MODELS_IN_FLIGHT = new Map<
59
- string,
60
- Promise<Record<string, ModelInfo>>
61
- >();
62
-
63
- let generatedModelsLoader:
64
- | Promise<Record<string, Record<string, ModelInfo>>>
65
- | undefined;
66
-
67
- async function loadGeneratedProviderModels(): Promise<
68
- Record<string, Record<string, ModelInfo>>
69
- > {
70
- generatedModelsLoader ??= import("../../models/generated-access").then(
71
- ({ getGeneratedProviderModels }) => getGeneratedProviderModels(),
72
- );
73
- return generatedModelsLoader;
74
- }
75
-
76
- async function mergeKnownModels(
77
- providerId: string,
78
- defaultKnownModels: Record<string, ModelInfo> = {},
79
- liveModels: Record<string, ModelInfo> = {},
80
- privateModels: Record<string, ModelInfo> = {},
81
- userKnownModels: Record<string, ModelInfo> = {},
82
- ): Promise<Record<string, ModelInfo>> {
83
- const generatedProviderModels = await loadGeneratedProviderModels();
84
- const generatedKeys = resolveProviderModelCatalogKeys(providerId);
85
- const generated = Object.assign(
86
- {},
87
- ...generatedKeys.map(
88
- (generatedKey) => generatedProviderModels[generatedKey] ?? {},
89
- ),
90
- );
91
- return sortModelsByReleaseDate({
92
- ...generated,
93
- ...defaultKnownModels,
94
- ...liveModels,
95
- ...privateModels,
96
- ...userKnownModels,
97
- });
98
- }
99
-
100
- function normalizeBaseUrl(baseUrl: string | undefined): string {
101
- const value = baseUrl?.trim();
102
- return value && value.length > 0 ? value : "";
103
- }
104
-
105
- function resolveAuthToken(
106
- config: Pick<ProviderConfig, "apiKey" | "accessToken">,
107
- ): string | undefined {
108
- const token = config.apiKey?.trim() || config.accessToken?.trim();
109
- return token && token.length > 0 ? token : undefined;
110
- }
111
-
112
- function fingerprint(value: string): string {
113
- let hash = 2166136261;
114
- for (let i = 0; i < value.length; i += 1) {
115
- hash ^= value.charCodeAt(i);
116
- hash +=
117
- (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
118
- }
119
- return (hash >>> 0).toString(16);
120
- }
121
-
122
- function resolvePrivateCacheKey(
123
- providerId: string,
124
- config: ProviderConfig,
125
- ): string {
126
- return `${providerId}:${normalizeBaseUrl(config.baseUrl)}:${fingerprint(resolveAuthToken(config) ?? "")}`;
127
- }
128
-
129
- function includeCapability(
130
- capabilities: NonNullable<ModelInfo["capabilities"]>,
131
- capability: NonNullable<ModelInfo["capabilities"]>[number],
132
- when: boolean,
133
- ): void {
134
- if (when && !capabilities.includes(capability)) {
135
- capabilities.push(capability);
136
- }
137
- }
138
-
139
- function buildModelFromPrivateSource(
140
- id: string,
141
- input: {
142
- name?: string;
143
- contextWindow?: number;
144
- maxTokens?: number;
145
- supportsImages?: boolean;
146
- supportsPromptCache?: boolean;
147
- supportsReasoning?: boolean;
148
- releaseDate?: string;
149
- },
150
- ): ModelInfo {
151
- const capabilities: NonNullable<ModelInfo["capabilities"]> = [
152
- "streaming",
153
- "tools",
154
- ];
155
- includeCapability(capabilities, "images", Boolean(input.supportsImages));
156
- includeCapability(
157
- capabilities,
158
- "prompt-cache",
159
- Boolean(input.supportsPromptCache),
160
- );
161
- includeCapability(
162
- capabilities,
163
- "reasoning",
164
- Boolean(input.supportsReasoning),
165
- );
166
- return {
167
- id,
168
- name: input.name ?? id,
169
- contextWindow: input.contextWindow,
170
- maxTokens: input.maxTokens,
171
- capabilities,
172
- releaseDate: input.releaseDate,
173
- status: "active",
174
- };
175
- }
176
-
177
- interface BasetenModelResponse {
178
- id?: string;
179
- object?: string;
180
- supported_features?: string[];
181
- context_length?: number;
182
- max_completion_tokens?: number;
183
- }
184
-
185
- async function fetchBasetenPrivateModels(
186
- _config: ProviderConfig,
187
- token: string,
188
- ): Promise<Record<string, ModelInfo>> {
189
- const response = await fetch("https://inference.baseten.co/v1/models", {
190
- method: "GET",
191
- headers: {
192
- Authorization: `Bearer ${token}`,
193
- "Content-Type": "application/json",
194
- },
195
- });
196
- if (!response.ok) {
197
- throw new Error(`Baseten model refresh failed: HTTP ${response.status}`);
198
- }
199
-
200
- const payload = (await response.json()) as { data?: BasetenModelResponse[] };
201
- const entries = payload?.data ?? [];
202
- const models: Record<string, ModelInfo> = {};
203
- for (const model of entries) {
204
- const id = model.id?.trim();
205
- if (!id) {
206
- continue;
207
- }
208
- if (
209
- id.includes("whisper") ||
210
- id.includes("tts") ||
211
- id.includes("embedding")
212
- ) {
213
- continue;
214
- }
215
- const features = model.supported_features ?? [];
216
- models[id] = buildModelFromPrivateSource(id, {
217
- name: id,
218
- contextWindow: model.context_length,
219
- maxTokens: model.max_completion_tokens,
220
- supportsReasoning:
221
- features.includes("reasoning") || features.includes("reasoning_effort"),
222
- supportsImages: false,
223
- });
224
- }
225
- return models;
226
- }
227
-
228
- interface HicapModelResponse {
229
- id?: string;
230
- }
231
-
232
- async function fetchHicapPrivateModels(
233
- _config: ProviderConfig,
234
- token: string,
235
- ): Promise<Record<string, ModelInfo>> {
236
- const response = await fetch("https://api.hicap.ai/v2/openai/models", {
237
- method: "GET",
238
- headers: {
239
- "api-key": token,
240
- },
241
- });
242
- if (!response.ok) {
243
- throw new Error(`Hicap model refresh failed: HTTP ${response.status}`);
244
- }
245
-
246
- const payload = (await response.json()) as { data?: HicapModelResponse[] };
247
- const entries = payload?.data ?? [];
248
- const models: Record<string, ModelInfo> = {};
249
- for (const model of entries) {
250
- const id = model.id?.trim();
251
- if (!id) {
252
- continue;
253
- }
254
- models[id] = buildModelFromPrivateSource(id, {
255
- name: id,
256
- contextWindow: 128_000,
257
- supportsImages: true,
258
- supportsPromptCache: true,
259
- });
260
- }
261
- return models;
262
- }
263
-
264
- interface LiteLlmModelInfoResponse {
265
- model_name?: string;
266
- litellm_params?: {
267
- model?: string;
268
- };
269
- model_info?: {
270
- max_output_tokens?: number;
271
- max_tokens?: number;
272
- max_input_tokens?: number;
273
- supports_vision?: boolean;
274
- supports_prompt_caching?: boolean;
275
- supports_reasoning?: boolean;
276
- };
277
- }
278
-
279
- function normalizeLiteLlmBaseUrl(baseUrl: string | undefined): string {
280
- const normalized = normalizeBaseUrl(baseUrl);
281
- if (!normalized) {
282
- return "http://localhost:4000";
283
- }
284
- return normalized.endsWith("/v1") ? normalized.slice(0, -3) : normalized;
285
- }
286
-
287
- async function fetchLiteLlmPrivateModels(
288
- config: ProviderConfig,
289
- token: string,
290
- ): Promise<Record<string, ModelInfo>> {
291
- const baseUrl = normalizeLiteLlmBaseUrl(config.baseUrl);
292
- const endpoint = `${baseUrl}/v1/model/info`;
293
-
294
- const fetchWithHeaders = async (
295
- headers: Record<string, string>,
296
- ): Promise<Response> =>
297
- fetch(endpoint, {
298
- method: "GET",
299
- headers: {
300
- accept: "application/json",
301
- ...headers,
302
- },
303
- });
304
-
305
- let response = await fetchWithHeaders({ "x-litellm-api-key": token });
306
- if (!response.ok) {
307
- response = await fetchWithHeaders({ Authorization: `Bearer ${token}` });
308
- }
309
- if (!response.ok) {
310
- throw new Error(`LiteLLM model refresh failed: HTTP ${response.status}`);
311
- }
312
-
313
- const payload = (await response.json()) as {
314
- data?: LiteLlmModelInfoResponse[];
315
- };
316
- const entries = payload?.data ?? [];
317
- const models: Record<string, ModelInfo> = {};
318
- for (const model of entries) {
319
- const displayName = model.model_name?.trim();
320
- const actualModelId = model.litellm_params?.model?.trim();
321
- const modelId = actualModelId || displayName;
322
- if (!modelId) {
323
- continue;
324
- }
325
- const info = model.model_info;
326
- const converted = buildModelFromPrivateSource(modelId, {
327
- name: displayName ?? modelId,
328
- maxTokens: info?.max_output_tokens ?? info?.max_tokens,
329
- contextWindow: info?.max_input_tokens ?? info?.max_tokens,
330
- supportsImages: info?.supports_vision,
331
- supportsPromptCache: info?.supports_prompt_caching,
332
- supportsReasoning: info?.supports_reasoning,
333
- });
334
- models[modelId] = converted;
335
- if (displayName) {
336
- models[displayName] = {
337
- ...converted,
338
- id: displayName,
339
- name: displayName,
340
- };
341
- }
342
- }
343
- return models;
344
- }
345
-
346
- async function fetchPrivateProviderModels(
347
- providerId: string,
348
- config: ProviderConfig,
349
- ): Promise<Record<string, ModelInfo>> {
350
- const token = resolveAuthToken(config);
351
- if (!token) {
352
- return {};
353
- }
354
-
355
- const fetcher = PRIVATE_PROVIDER_MODEL_FETCHERS[providerId];
356
- if (!fetcher) {
357
- return {};
358
- }
359
- return fetcher(config, token);
360
- }
361
-
362
- type PrivateProviderModelFetcher = (
363
- config: ProviderConfig,
364
- token: string,
365
- ) => Promise<Record<string, ModelInfo>>;
366
-
367
- const PRIVATE_PROVIDER_MODEL_FETCHERS: Record<
368
- string,
369
- PrivateProviderModelFetcher
370
- > = {
371
- baseten: fetchBasetenPrivateModels,
372
- hicap: fetchHicapPrivateModels,
373
- litellm: fetchLiteLlmPrivateModels,
374
- };
375
-
376
- function shouldLoadPrivateModels(
377
- providerId: string,
378
- modelCatalog: ModelCatalogConfig | undefined,
379
- config: ProviderConfig | undefined,
380
- ): boolean {
381
- if (!config) {
382
- return false;
383
- }
384
- if (!PRIVATE_PROVIDER_MODEL_FETCHERS[providerId]) {
385
- return false;
386
- }
387
- if (modelCatalog?.loadPrivateOnAuth === false) {
388
- return false;
389
- }
390
- return Boolean(resolveAuthToken(config));
391
- }
392
-
393
- async function getPrivateProviderModels(
394
- providerId: string,
395
- modelCatalog: ModelCatalogConfig | undefined,
396
- config: ProviderConfig,
397
- ): Promise<Record<string, ModelInfo>> {
398
- const cacheTtlMs =
399
- modelCatalog?.cacheTtlMs ?? DEFAULT_PRIVATE_MODELS_CACHE_TTL_MS;
400
- const cacheKey = resolvePrivateCacheKey(providerId, config);
401
- const now = Date.now();
402
-
403
- const cached = PRIVATE_MODELS_CACHE.get(cacheKey);
404
- if (cached && cached.expiresAt > now) {
405
- return cached.data;
406
- }
407
-
408
- const inFlight = PRIVATE_MODELS_IN_FLIGHT.get(cacheKey);
409
- if (inFlight) {
410
- return inFlight;
411
- }
412
-
413
- const request = fetchPrivateProviderModels(providerId, config)
414
- .then((data) => {
415
- PRIVATE_MODELS_CACHE.set(cacheKey, {
416
- data,
417
- expiresAt: now + cacheTtlMs,
418
- });
419
- return data;
420
- })
421
- .finally(() => {
422
- PRIVATE_MODELS_IN_FLIGHT.delete(cacheKey);
423
- });
424
-
425
- PRIVATE_MODELS_IN_FLIGHT.set(cacheKey, request);
426
- return request;
427
- }
428
-
429
- async function fetchLiveModelsCatalog(
430
- url: string,
431
- ): Promise<Record<string, Record<string, ModelInfo>>> {
432
- return fetchModelsDevProviderModels(url, MODELS_DEV_PROVIDER_KEY_MAP);
433
- }
434
-
435
- export async function getLiveModelsCatalog(
436
- options: Pick<ModelCatalogConfig, "url" | "cacheTtlMs"> = {},
437
- ): Promise<Record<string, Record<string, ModelInfo>>> {
438
- const url = options.url ?? DEFAULT_MODELS_CATALOG_URL;
439
- const cacheTtlMs = options.cacheTtlMs ?? DEFAULT_MODELS_CATALOG_CACHE_TTL_MS;
440
- const now = Date.now();
441
-
442
- const cached = MODELS_CATALOG_CACHE.get(url);
443
- if (cached && cached.expiresAt > now) {
444
- return cached.data;
445
- }
446
-
447
- const inFlight = MODELS_CATALOG_IN_FLIGHT.get(url);
448
- if (inFlight) {
449
- return inFlight;
450
- }
451
-
452
- const request = fetchLiveModelsCatalog(url)
453
- .then((data) => {
454
- MODELS_CATALOG_CACHE.set(url, { data, expiresAt: now + cacheTtlMs });
455
- return data;
456
- })
457
- .finally(() => {
458
- MODELS_CATALOG_IN_FLIGHT.delete(url);
459
- });
460
-
461
- MODELS_CATALOG_IN_FLIGHT.set(url, request);
462
- return request;
463
- }
464
-
465
- export function clearLiveModelsCatalogCache(url?: string): void {
466
- if (url) {
467
- MODELS_CATALOG_CACHE.delete(url);
468
- MODELS_CATALOG_IN_FLIGHT.delete(url);
469
- return;
470
- }
471
-
472
- MODELS_CATALOG_CACHE.clear();
473
- MODELS_CATALOG_IN_FLIGHT.clear();
474
- }
475
-
476
- export function clearPrivateModelsCatalogCache(): void {
477
- PRIVATE_MODELS_CACHE.clear();
478
- PRIVATE_MODELS_IN_FLIGHT.clear();
479
- }
480
-
481
- function toRuntimeProviderDefaults(
482
- defaults: Record<string, OpenAICompatibleProviderDefaults>,
483
- ): Record<string, ProviderDefaults> {
484
- return Object.fromEntries(
485
- Object.entries(defaults).map(([providerId, providerDefaults]) => [
486
- providerId,
487
- {
488
- baseUrl: providerDefaults.baseUrl,
489
- modelId: providerDefaults.modelId,
490
- knownModels: providerDefaults.knownModels,
491
- capabilities: providerDefaults.capabilities as
492
- | ProviderCapability[]
493
- | undefined,
494
- },
495
- ]),
496
- );
497
- }
498
-
499
- /**
500
- * All OpenAI-compatible provider configurations
501
- *
502
- * Model data is sourced from @clinebot/models to maintain a single source of truth.
503
- */
504
- export const OPENAI_COMPATIBLE_PROVIDERS: Record<string, ProviderDefaults> =
505
- toRuntimeProviderDefaults(buildOpenAICompatibleProviderDefaults());
506
-
507
- /**
508
- * Get provider configuration by ID
509
- */
510
- export function getProviderConfig(
511
- providerId: string,
512
- ): ProviderDefaults | undefined {
513
- return OPENAI_COMPATIBLE_PROVIDERS[providerId];
514
- }
515
-
516
- /**
517
- * Resolve provider configuration and optionally merge live catalog metadata
518
- */
519
- export async function resolveProviderConfig(
520
- providerId: string,
521
- modelCatalog?: ModelCatalogConfig,
522
- config?: ProviderConfig,
523
- ): Promise<ProviderDefaults | undefined> {
524
- const defaults = getProviderConfig(providerId);
525
- if (!defaults) {
526
- return undefined;
527
- }
528
-
529
- try {
530
- const liveCatalog = modelCatalog?.loadLatestOnInit
531
- ? await getLiveModelsCatalog(modelCatalog)
532
- : undefined;
533
- const liveModels = liveCatalog?.[providerId] ?? {};
534
- const privateModels =
535
- config && shouldLoadPrivateModels(providerId, modelCatalog, config)
536
- ? await getPrivateProviderModels(providerId, modelCatalog, config)
537
- : {};
538
- const knownModels = await mergeKnownModels(
539
- providerId,
540
- defaults.knownModels,
541
- liveModels,
542
- privateModels,
543
- config?.knownModels,
544
- );
545
-
546
- return {
547
- ...defaults,
548
- knownModels,
549
- };
550
- } catch (error) {
551
- if (modelCatalog?.failOnError) {
552
- throw error;
553
- }
554
- return defaults;
555
- }
556
- }
557
-
558
- /**
559
- * Check if a provider is OpenAI-compatible
560
- */
561
- export function isOpenAICompatibleProvider(providerId: string): boolean {
562
- return providerId in OPENAI_COMPATIBLE_PROVIDERS;
563
- }