@clinebot/llms 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/README.md +198 -0
  2. package/dist/config-browser.d.ts +3 -0
  3. package/dist/config.d.ts +3 -0
  4. package/dist/index.browser.d.ts +4 -0
  5. package/dist/index.browser.js +1 -0
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.js +7 -0
  8. package/dist/models/generated-access.d.ts +4 -0
  9. package/dist/models/generated-provider-loaders.d.ts +13 -0
  10. package/dist/models/generated.d.ts +14 -0
  11. package/dist/models/index.d.ts +43 -0
  12. package/dist/models/models-dev-catalog.d.ts +32 -0
  13. package/dist/models/providers/aihubmix.d.ts +5 -0
  14. package/dist/models/providers/anthropic.d.ts +53 -0
  15. package/dist/models/providers/asksage.d.ts +5 -0
  16. package/dist/models/providers/baseten.d.ts +5 -0
  17. package/dist/models/providers/bedrock.d.ts +7 -0
  18. package/dist/models/providers/cerebras.d.ts +7 -0
  19. package/dist/models/providers/claude-code.d.ts +4 -0
  20. package/dist/models/providers/cline.d.ts +34 -0
  21. package/dist/models/providers/deepseek.d.ts +8 -0
  22. package/dist/models/providers/dify.d.ts +5 -0
  23. package/dist/models/providers/doubao.d.ts +7 -0
  24. package/dist/models/providers/fireworks.d.ts +8 -0
  25. package/dist/models/providers/gemini.d.ts +9 -0
  26. package/dist/models/providers/groq.d.ts +8 -0
  27. package/dist/models/providers/hicap.d.ts +5 -0
  28. package/dist/models/providers/huawei-cloud-maas.d.ts +5 -0
  29. package/dist/models/providers/huggingface.d.ts +6 -0
  30. package/dist/models/providers/index.d.ts +45 -0
  31. package/dist/models/providers/litellm.d.ts +5 -0
  32. package/dist/models/providers/lmstudio.d.ts +5 -0
  33. package/dist/models/providers/minimax.d.ts +7 -0
  34. package/dist/models/providers/mistral.d.ts +5 -0
  35. package/dist/models/providers/moonshot.d.ts +7 -0
  36. package/dist/models/providers/nebius.d.ts +7 -0
  37. package/dist/models/providers/nous-research.d.ts +7 -0
  38. package/dist/models/providers/oca.d.ts +9 -0
  39. package/dist/models/providers/ollama.d.ts +5 -0
  40. package/dist/models/providers/openai-codex.d.ts +10 -0
  41. package/dist/models/providers/openai.d.ts +9 -0
  42. package/dist/models/providers/opencode.d.ts +10 -0
  43. package/dist/models/providers/openrouter.d.ts +7 -0
  44. package/dist/models/providers/qwen-code.d.ts +7 -0
  45. package/dist/models/providers/qwen.d.ts +7 -0
  46. package/dist/models/providers/requesty.d.ts +6 -0
  47. package/dist/models/providers/sambanova.d.ts +7 -0
  48. package/dist/models/providers/sapaicore.d.ts +7 -0
  49. package/dist/models/providers/together.d.ts +8 -0
  50. package/dist/models/providers/vercel-ai-gateway.d.ts +5 -0
  51. package/dist/models/providers/vertex.d.ts +7 -0
  52. package/dist/models/providers/xai.d.ts +8 -0
  53. package/dist/models/providers/zai.d.ts +7 -0
  54. package/dist/models/query.d.ts +181 -0
  55. package/dist/models/registry.d.ts +123 -0
  56. package/dist/models/schemas/index.d.ts +7 -0
  57. package/dist/models/schemas/model.d.ts +340 -0
  58. package/dist/models/schemas/query.d.ts +191 -0
  59. package/dist/providers/handlers/ai-sdk-community.d.ts +46 -0
  60. package/dist/providers/handlers/ai-sdk-provider-base.d.ts +32 -0
  61. package/dist/providers/handlers/anthropic-base.d.ts +26 -0
  62. package/dist/providers/handlers/asksage.d.ts +12 -0
  63. package/dist/providers/handlers/auth.d.ts +5 -0
  64. package/dist/providers/handlers/base.d.ts +55 -0
  65. package/dist/providers/handlers/bedrock-base.d.ts +23 -0
  66. package/dist/providers/handlers/bedrock-client.d.ts +4 -0
  67. package/dist/providers/handlers/community-sdk.d.ts +97 -0
  68. package/dist/providers/handlers/fetch-base.d.ts +18 -0
  69. package/dist/providers/handlers/gemini-base.d.ts +25 -0
  70. package/dist/providers/handlers/index.d.ts +19 -0
  71. package/dist/providers/handlers/openai-base.d.ts +54 -0
  72. package/dist/providers/handlers/openai-responses.d.ts +64 -0
  73. package/dist/providers/handlers/providers.d.ts +43 -0
  74. package/dist/providers/handlers/r1-base.d.ts +62 -0
  75. package/dist/providers/handlers/registry.d.ts +106 -0
  76. package/dist/providers/handlers/vertex.d.ts +32 -0
  77. package/dist/providers/index.d.ts +100 -0
  78. package/dist/providers/public.browser.d.ts +2 -0
  79. package/dist/providers/public.d.ts +3 -0
  80. package/dist/providers/shared/openai-compatible.d.ts +10 -0
  81. package/dist/providers/transform/ai-sdk-community-format.d.ts +9 -0
  82. package/dist/providers/transform/anthropic-format.d.ts +24 -0
  83. package/dist/providers/transform/content-format.d.ts +3 -0
  84. package/dist/providers/transform/gemini-format.d.ts +19 -0
  85. package/dist/providers/transform/index.d.ts +10 -0
  86. package/dist/providers/transform/openai-format.d.ts +36 -0
  87. package/dist/providers/transform/r1-format.d.ts +26 -0
  88. package/dist/providers/types/config.d.ts +261 -0
  89. package/dist/providers/types/handler.d.ts +71 -0
  90. package/dist/providers/types/index.d.ts +11 -0
  91. package/dist/providers/types/messages.d.ts +139 -0
  92. package/dist/providers/types/model-info.d.ts +32 -0
  93. package/dist/providers/types/provider-ids.d.ts +63 -0
  94. package/dist/providers/types/settings.d.ts +308 -0
  95. package/dist/providers/types/stream.d.ts +106 -0
  96. package/dist/providers/utils/index.d.ts +7 -0
  97. package/dist/providers/utils/retry.d.ts +38 -0
  98. package/dist/providers/utils/stream-processor.d.ts +110 -0
  99. package/dist/providers/utils/tool-processor.d.ts +34 -0
  100. package/dist/sdk.d.ts +18 -0
  101. package/dist/types.d.ts +60 -0
  102. package/package.json +66 -0
  103. package/src/catalog.ts +20 -0
  104. package/src/config-browser.ts +11 -0
  105. package/src/config.ts +49 -0
  106. package/src/index.browser.ts +9 -0
  107. package/src/index.ts +10 -0
  108. package/src/live-providers.test.ts +137 -0
  109. package/src/models/generated-access.ts +41 -0
  110. package/src/models/generated-provider-loaders.ts +166 -0
  111. package/src/models/generated.ts +11997 -0
  112. package/src/models/index.ts +271 -0
  113. package/src/models/models-dev-catalog.test.ts +161 -0
  114. package/src/models/models-dev-catalog.ts +161 -0
  115. package/src/models/providers/aihubmix.ts +19 -0
  116. package/src/models/providers/anthropic.ts +60 -0
  117. package/src/models/providers/asksage.ts +19 -0
  118. package/src/models/providers/baseten.ts +21 -0
  119. package/src/models/providers/bedrock.ts +30 -0
  120. package/src/models/providers/cerebras.ts +24 -0
  121. package/src/models/providers/claude-code.ts +51 -0
  122. package/src/models/providers/cline.ts +25 -0
  123. package/src/models/providers/deepseek.ts +33 -0
  124. package/src/models/providers/dify.ts +17 -0
  125. package/src/models/providers/doubao.ts +33 -0
  126. package/src/models/providers/fireworks.ts +34 -0
  127. package/src/models/providers/gemini.ts +43 -0
  128. package/src/models/providers/groq.ts +33 -0
  129. package/src/models/providers/hicap.ts +18 -0
  130. package/src/models/providers/huawei-cloud-maas.ts +18 -0
  131. package/src/models/providers/huggingface.ts +22 -0
  132. package/src/models/providers/index.ts +162 -0
  133. package/src/models/providers/litellm.ts +19 -0
  134. package/src/models/providers/lmstudio.ts +22 -0
  135. package/src/models/providers/minimax.ts +34 -0
  136. package/src/models/providers/mistral.ts +19 -0
  137. package/src/models/providers/moonshot.ts +34 -0
  138. package/src/models/providers/nebius.ts +24 -0
  139. package/src/models/providers/nous-research.ts +21 -0
  140. package/src/models/providers/oca.ts +30 -0
  141. package/src/models/providers/ollama.ts +18 -0
  142. package/src/models/providers/openai-codex.ts +30 -0
  143. package/src/models/providers/openai.ts +43 -0
  144. package/src/models/providers/opencode.ts +28 -0
  145. package/src/models/providers/openrouter.ts +24 -0
  146. package/src/models/providers/qwen-code.ts +33 -0
  147. package/src/models/providers/qwen.ts +34 -0
  148. package/src/models/providers/requesty.ts +23 -0
  149. package/src/models/providers/sambanova.ts +23 -0
  150. package/src/models/providers/sapaicore.ts +34 -0
  151. package/src/models/providers/together.ts +35 -0
  152. package/src/models/providers/vercel-ai-gateway.ts +23 -0
  153. package/src/models/providers/vertex.ts +36 -0
  154. package/src/models/providers/xai.ts +34 -0
  155. package/src/models/providers/zai.ts +25 -0
  156. package/src/models/query.ts +407 -0
  157. package/src/models/registry.ts +511 -0
  158. package/src/models/schemas/index.ts +62 -0
  159. package/src/models/schemas/model.ts +308 -0
  160. package/src/models/schemas/query.ts +336 -0
  161. package/src/providers/browser.ts +4 -0
  162. package/src/providers/handlers/ai-sdk-community.ts +226 -0
  163. package/src/providers/handlers/ai-sdk-provider-base.ts +193 -0
  164. package/src/providers/handlers/anthropic-base.ts +372 -0
  165. package/src/providers/handlers/asksage.test.ts +103 -0
  166. package/src/providers/handlers/asksage.ts +138 -0
  167. package/src/providers/handlers/auth.test.ts +19 -0
  168. package/src/providers/handlers/auth.ts +121 -0
  169. package/src/providers/handlers/base.test.ts +46 -0
  170. package/src/providers/handlers/base.ts +160 -0
  171. package/src/providers/handlers/bedrock-base.ts +390 -0
  172. package/src/providers/handlers/bedrock-client.ts +100 -0
  173. package/src/providers/handlers/codex.test.ts +123 -0
  174. package/src/providers/handlers/community-sdk.test.ts +288 -0
  175. package/src/providers/handlers/community-sdk.ts +392 -0
  176. package/src/providers/handlers/fetch-base.ts +68 -0
  177. package/src/providers/handlers/gemini-base.ts +302 -0
  178. package/src/providers/handlers/index.ts +67 -0
  179. package/src/providers/handlers/openai-base.ts +277 -0
  180. package/src/providers/handlers/openai-responses.ts +598 -0
  181. package/src/providers/handlers/providers.test.ts +120 -0
  182. package/src/providers/handlers/providers.ts +563 -0
  183. package/src/providers/handlers/r1-base.ts +280 -0
  184. package/src/providers/handlers/registry.ts +185 -0
  185. package/src/providers/handlers/vertex.test.ts +124 -0
  186. package/src/providers/handlers/vertex.ts +292 -0
  187. package/src/providers/index.ts +534 -0
  188. package/src/providers/public.browser.ts +20 -0
  189. package/src/providers/public.ts +51 -0
  190. package/src/providers/shared/openai-compatible.ts +63 -0
  191. package/src/providers/transform/ai-sdk-community-format.test.ts +73 -0
  192. package/src/providers/transform/ai-sdk-community-format.ts +115 -0
  193. package/src/providers/transform/anthropic-format.ts +218 -0
  194. package/src/providers/transform/content-format.ts +34 -0
  195. package/src/providers/transform/format-conversion.test.ts +310 -0
  196. package/src/providers/transform/gemini-format.ts +167 -0
  197. package/src/providers/transform/index.ts +22 -0
  198. package/src/providers/transform/openai-format.ts +247 -0
  199. package/src/providers/transform/r1-format.ts +287 -0
  200. package/src/providers/types/config.ts +388 -0
  201. package/src/providers/types/handler.ts +87 -0
  202. package/src/providers/types/index.ts +120 -0
  203. package/src/providers/types/messages.ts +158 -0
  204. package/src/providers/types/model-info.test.ts +57 -0
  205. package/src/providers/types/model-info.ts +65 -0
  206. package/src/providers/types/provider-ids.test.ts +12 -0
  207. package/src/providers/types/provider-ids.ts +89 -0
  208. package/src/providers/types/settings.test.ts +49 -0
  209. package/src/providers/types/settings.ts +533 -0
  210. package/src/providers/types/stream.ts +117 -0
  211. package/src/providers/utils/index.ts +27 -0
  212. package/src/providers/utils/retry.test.ts +140 -0
  213. package/src/providers/utils/retry.ts +188 -0
  214. package/src/providers/utils/stream-processor.test.ts +232 -0
  215. package/src/providers/utils/stream-processor.ts +472 -0
  216. package/src/providers/utils/tool-processor.test.ts +34 -0
  217. package/src/providers/utils/tool-processor.ts +111 -0
  218. package/src/sdk.ts +264 -0
  219. package/src/types.ts +79 -0
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Model Schema Definitions
3
+ *
4
+ * Zod schemas for validating model information, capabilities, and pricing.
5
+ * These schemas are the source of truth for all model type definitions.
6
+ */
7
+
8
+ import { z } from "zod";
9
+
10
+ // =============================================================================
11
+ // API Format
12
+ // =============================================================================
13
+
14
+ /**
15
+ * API format variants for different provider protocols
16
+ */
17
+ export const ApiFormatSchema = z.enum(["default", "openai-responses", "r1"]);
18
+
19
+ export type ApiFormat = z.infer<typeof ApiFormatSchema>;
20
+
21
+ export const ApiFormat = {
22
+ DEFAULT: "default" as const,
23
+ OPENAI_RESPONSES: "openai-responses" as const,
24
+ R1: "r1" as const,
25
+ } as const;
26
+
27
+ // =============================================================================
28
+ // Model Capabilities
29
+ // =============================================================================
30
+
31
+ /**
32
+ * Capabilities a model may support
33
+ */
34
+ export const ModelCapabilitySchema = z.enum([
35
+ "images", // Image/vision inputs
36
+ "tools", // Tool/function calling
37
+ "streaming", // Streaming responses
38
+ "prompt-cache", // Prompt caching
39
+ "reasoning", // Extended thinking/reasoning
40
+ "reasoning-effort", // Reasoning effort parameter
41
+ "computer-use", // Computer use tools
42
+ "global-endpoint", // Global endpoint (Vertex AI)
43
+ "structured_output", // Structured output formats
44
+ "temperature", // Supports temperature parameter
45
+ "files", // File inputs (e.g. PDFs)
46
+ ]);
47
+
48
+ export type ModelCapability = z.infer<typeof ModelCapabilitySchema>;
49
+
50
+ // =============================================================================
51
+ // Model Status
52
+ // =============================================================================
53
+
54
+ /**
55
+ * Model lifecycle status
56
+ */
57
+ export const ModelStatusSchema = z.enum([
58
+ "active", // Currently available and supported
59
+ "preview", // Available but may change
60
+ "deprecated", // Will be removed, use alternative
61
+ "legacy", // Still works but not recommended
62
+ ]);
63
+
64
+ export type ModelStatus = z.infer<typeof ModelStatusSchema>;
65
+
66
+ // =============================================================================
67
+ // Pricing
68
+ // =============================================================================
69
+
70
+ /**
71
+ * Token pricing configuration (per million tokens)
72
+ */
73
+ export const ModelPricingSchema = z.object({
74
+ /** Input price per million tokens */
75
+ input: z.number().optional(),
76
+ /** Output price per million tokens */
77
+ output: z.number().optional(),
78
+ /** Cache write price per million tokens */
79
+ cacheWrite: z.number().optional(),
80
+ /** Cache read price per million tokens */
81
+ cacheRead: z.number().optional(),
82
+ });
83
+
84
+ export type ModelPricing = z.infer<typeof ModelPricingSchema>;
85
+
86
+ // =============================================================================
87
+ // Thinking/Reasoning Config
88
+ // =============================================================================
89
+
90
+ /**
91
+ * Configuration for models with thinking/reasoning capabilities
92
+ */
93
+ export const ThinkingConfigSchema = z.object({
94
+ /** Maximum thinking budget in tokens */
95
+ maxBudget: z.number().optional(),
96
+ /** Output price when thinking is enabled (per million tokens) */
97
+ outputPrice: z.number().optional(),
98
+ /** Gemini-specific thinking level */
99
+ thinkingLevel: z.enum(["low", "high"]).optional(),
100
+ });
101
+
102
+ export type ThinkingConfig = z.infer<typeof ThinkingConfigSchema>;
103
+
104
+ // =============================================================================
105
+ // Model Info
106
+ // =============================================================================
107
+
108
+ /**
109
+ * Complete model information schema
110
+ */
111
+ export const ModelInfoSchema = z.object({
112
+ /** Model identifier (e.g., "claude-sonnet-4-20250514") */
113
+ id: z.string(),
114
+
115
+ /** Human-readable model name */
116
+ name: z.string().optional(),
117
+
118
+ /** Model description */
119
+ description: z.string().optional(),
120
+
121
+ // === Token Limits ===
122
+
123
+ /** Maximum output tokens */
124
+ maxTokens: z.number().optional(),
125
+
126
+ /** Context window size in tokens */
127
+ contextWindow: z.number().optional(),
128
+
129
+ // === Capabilities ===
130
+
131
+ /** Model capabilities (images, tools, streaming, prompt-cache, reasoning, etc.) */
132
+ capabilities: z.array(ModelCapabilitySchema).optional(),
133
+
134
+ // === API Configuration ===
135
+
136
+ /** API format required by this model */
137
+ apiFormat: ApiFormatSchema.optional(),
138
+
139
+ /** System message role override (for OpenAI-compatible) */
140
+ systemRole: z.enum(["system", "developer"]).optional(),
141
+
142
+ /** Default temperature for this model */
143
+ temperature: z.number().optional(),
144
+
145
+ // === Pricing ===
146
+
147
+ /** Token pricing (per million tokens) */
148
+ pricing: ModelPricingSchema.optional(),
149
+
150
+ // === Thinking/Reasoning ===
151
+
152
+ /** Thinking/reasoning configuration */
153
+ thinkingConfig: ThinkingConfigSchema.optional(),
154
+
155
+ // === Lifecycle ===
156
+
157
+ /** Model status (active, preview, deprecated, legacy) */
158
+ status: ModelStatusSchema.optional(),
159
+
160
+ /** Deprecation notice if status is deprecated */
161
+ deprecationNotice: z.string().optional(),
162
+
163
+ /** Suggested replacement model ID if deprecated */
164
+ replacedBy: z.string().optional(),
165
+
166
+ /** Date when model was released (ISO 8601) */
167
+ releaseDate: z.string().optional(),
168
+
169
+ /** Date when model will be/was deprecated (ISO 8601) */
170
+ deprecationDate: z.string().optional(),
171
+ });
172
+
173
+ export type ModelInfo = z.infer<typeof ModelInfoSchema>;
174
+
175
+ // =============================================================================
176
+ // Model Entry (with ID)
177
+ // =============================================================================
178
+
179
+ /**
180
+ * A model entry with its ID and info
181
+ */
182
+ export const ModelEntrySchema = z.object({
183
+ /** Model identifier (e.g., "claude-sonnet-4-20250514") */
184
+ id: z.string(),
185
+ /** Model information */
186
+ info: ModelInfoSchema,
187
+ });
188
+
189
+ export type ModelEntry = z.infer<typeof ModelEntrySchema>;
190
+
191
+ // =============================================================================
192
+ // Provider Info
193
+ // =============================================================================
194
+
195
+ /**
196
+ * Provider capability (applies to all models from this provider)
197
+ */
198
+ export const ProviderCapabilitySchema = z.enum([
199
+ "reasoning",
200
+ "prompt-cache",
201
+ "tools",
202
+ "oauth",
203
+ ]);
204
+
205
+ export type ProviderCapability = z.infer<typeof ProviderCapabilitySchema>;
206
+
207
+ /**
208
+ * Provider protocol/transport family
209
+ */
210
+ export const ProviderProtocolSchema = z.enum([
211
+ "anthropic",
212
+ "gemini",
213
+ "openai-chat",
214
+ "openai-responses",
215
+ "openai-r1",
216
+ ]);
217
+
218
+ export type ProviderProtocol = z.infer<typeof ProviderProtocolSchema>;
219
+
220
+ /**
221
+ * Provider configuration
222
+ */
223
+ export const ProviderInfoSchema = z.object({
224
+ /** Provider ID (e.g., "anthropic", "openai") */
225
+ id: z.string(),
226
+ /** Human-readable name */
227
+ name: z.string(),
228
+ /** Provider description */
229
+ description: z.string().optional(),
230
+ /** Provider protocol family used for handler routing */
231
+ protocol: ProviderProtocolSchema.optional(),
232
+ /** Base URL for API */
233
+ baseUrl: z.string().optional(),
234
+ /** Default model ID */
235
+ defaultModelId: z.string(),
236
+ /** Provider-level capabilities */
237
+ capabilities: z.array(ProviderCapabilitySchema).optional(),
238
+ /** Environment variables associated with this provider */
239
+ env: z.array(z.string()).optional(),
240
+ });
241
+
242
+ export type ProviderInfo = z.infer<typeof ProviderInfoSchema>;
243
+
244
+ // =============================================================================
245
+ // Model Collection
246
+ // =============================================================================
247
+
248
+ /**
249
+ * A collection of models from a provider
250
+ */
251
+ export const ModelCollectionSchema = z.object({
252
+ /** Provider information */
253
+ provider: ProviderInfoSchema,
254
+ /** Models keyed by ID */
255
+ models: z.record(z.string(), ModelInfoSchema),
256
+ });
257
+
258
+ export type ModelCollection = z.infer<typeof ModelCollectionSchema>;
259
+
260
+ // =============================================================================
261
+ // Helper Functions
262
+ // =============================================================================
263
+
264
+ /**
265
+ * Check if a model has a specific capability
266
+ */
267
+ export function hasCapability(
268
+ info: ModelInfo,
269
+ capability: ModelCapability,
270
+ ): boolean {
271
+ return info.capabilities?.includes(capability) ?? false;
272
+ }
273
+
274
+ /**
275
+ * Check if a model is deprecated
276
+ */
277
+ export function isDeprecated(info: ModelInfo): boolean {
278
+ return info.status === "deprecated";
279
+ }
280
+
281
+ /**
282
+ * Check if a model is active (not deprecated or legacy)
283
+ */
284
+ export function isActive(info: ModelInfo): boolean {
285
+ return !info.status || info.status === "active" || info.status === "preview";
286
+ }
287
+
288
+ /**
289
+ * Get pricing for a model
290
+ */
291
+ export function getPricing(info: ModelInfo): ModelPricing {
292
+ return info.pricing ?? {};
293
+ }
294
+
295
+ /**
296
+ * Validate model info against schema
297
+ */
298
+ export function validateModelInfo(data: unknown): ModelInfo {
299
+ return ModelInfoSchema.parse(data);
300
+ }
301
+
302
+ /**
303
+ * Safely validate model info (returns undefined on failure)
304
+ */
305
+ export function safeValidateModelInfo(data: unknown): ModelInfo | undefined {
306
+ const result = ModelInfoSchema.safeParse(data);
307
+ return result.success ? result.data : undefined;
308
+ }
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Model Query Schema Definitions
3
+ *
4
+ * Zod schemas for configuring model queries and filters.
5
+ * Users can use these to find models matching specific criteria.
6
+ */
7
+
8
+ import { z } from "zod";
9
+ import {
10
+ ApiFormatSchema,
11
+ hasCapability,
12
+ isDeprecated,
13
+ ModelCapabilitySchema,
14
+ type ModelInfo,
15
+ ModelStatusSchema,
16
+ } from "./model";
17
+
18
+ // =============================================================================
19
+ // Query Configuration
20
+ // =============================================================================
21
+
22
+ /**
23
+ * Configuration for querying models
24
+ */
25
+ export const ModelQueryConfigSchema = z.object({
26
+ /**
27
+ * Filter by provider IDs
28
+ * If not specified, returns models from all providers
29
+ */
30
+ providers: z.array(z.string()).optional(),
31
+
32
+ /**
33
+ * Filter by required capabilities
34
+ * Models must have ALL specified capabilities
35
+ */
36
+ capabilities: z.array(ModelCapabilitySchema).optional(),
37
+
38
+ /**
39
+ * Filter by any of these capabilities
40
+ * Models must have AT LEAST ONE of the specified capabilities
41
+ */
42
+ anyCapabilities: z.array(ModelCapabilitySchema).optional(),
43
+
44
+ /**
45
+ * Exclude models with these capabilities
46
+ */
47
+ excludeCapabilities: z.array(ModelCapabilitySchema).optional(),
48
+
49
+ /**
50
+ * Filter by model status
51
+ * If not specified, includes all statuses
52
+ */
53
+ status: z.array(ModelStatusSchema).optional(),
54
+
55
+ /**
56
+ * Include deprecated models
57
+ * @default false
58
+ */
59
+ includeDeprecated: z.boolean().optional(),
60
+
61
+ /**
62
+ * Filter by API format
63
+ */
64
+ apiFormat: ApiFormatSchema.optional(),
65
+
66
+ /**
67
+ * Filter by minimum context window size
68
+ */
69
+ minContextWindow: z.number().optional(),
70
+
71
+ /**
72
+ * Filter by maximum context window size
73
+ */
74
+ maxContextWindow: z.number().optional(),
75
+
76
+ /**
77
+ * Filter by minimum output tokens
78
+ */
79
+ minMaxTokens: z.number().optional(),
80
+
81
+ /**
82
+ * Filter by maximum price per million input tokens
83
+ */
84
+ maxInputPrice: z.number().optional(),
85
+
86
+ /**
87
+ * Filter by maximum price per million output tokens
88
+ */
89
+ maxOutputPrice: z.number().optional(),
90
+
91
+ /**
92
+ * Search by model name or ID (case-insensitive partial match)
93
+ */
94
+ search: z.string().optional(),
95
+
96
+ /**
97
+ * Only return models with thinking/reasoning support
98
+ */
99
+ hasThinking: z.boolean().optional(),
100
+
101
+ /**
102
+ * Sort results by field
103
+ */
104
+ sortBy: z
105
+ .enum(["name", "contextWindow", "maxTokens", "inputPrice", "outputPrice"])
106
+ .optional(),
107
+
108
+ /**
109
+ * Sort direction
110
+ * @default "asc"
111
+ */
112
+ sortDirection: z.enum(["asc", "desc"]).optional(),
113
+
114
+ /**
115
+ * Limit number of results
116
+ */
117
+ limit: z.number().optional(),
118
+ });
119
+
120
+ export type ModelQueryConfig = z.infer<typeof ModelQueryConfigSchema>;
121
+
122
+ // =============================================================================
123
+ // Query Result
124
+ // =============================================================================
125
+
126
+ /**
127
+ * Result of a model query
128
+ */
129
+ export const ModelQueryResultSchema = z.object({
130
+ /** Matching models with their provider */
131
+ models: z.array(
132
+ z.object({
133
+ providerId: z.string(),
134
+ modelId: z.string(),
135
+ info: z.any(), // ModelInfoSchema but avoiding circular ref
136
+ }),
137
+ ),
138
+ /** Total count before limit */
139
+ total: z.number(),
140
+ /** Query config used */
141
+ config: ModelQueryConfigSchema,
142
+ });
143
+
144
+ export type ModelQueryResult = z.infer<typeof ModelQueryResultSchema>;
145
+
146
+ // =============================================================================
147
+ // Model Match Result
148
+ // =============================================================================
149
+
150
+ export interface ModelMatch {
151
+ providerId: string;
152
+ modelId: string;
153
+ info: ModelInfo;
154
+ }
155
+
156
+ // =============================================================================
157
+ // Query Functions
158
+ // =============================================================================
159
+
160
+ /**
161
+ * Check if a model matches the query config
162
+ */
163
+ export function matchesQuery(
164
+ modelId: string,
165
+ info: ModelInfo,
166
+ config: ModelQueryConfig,
167
+ ): boolean {
168
+ // Check deprecated filter
169
+ if (!config.includeDeprecated && isDeprecated(info)) {
170
+ return false;
171
+ }
172
+
173
+ // Check status filter
174
+ if (config.status && config.status.length > 0) {
175
+ const modelStatus = info.status ?? "active";
176
+ if (!config.status.includes(modelStatus)) {
177
+ return false;
178
+ }
179
+ }
180
+
181
+ // Check required capabilities (ALL must be present)
182
+ if (config.capabilities && config.capabilities.length > 0) {
183
+ const hasAll = config.capabilities.every((cap) => hasCapability(info, cap));
184
+ if (!hasAll) {
185
+ return false;
186
+ }
187
+ }
188
+
189
+ // Check any capabilities (AT LEAST ONE must be present)
190
+ if (config.anyCapabilities && config.anyCapabilities.length > 0) {
191
+ const hasAny = config.anyCapabilities.some((cap) =>
192
+ hasCapability(info, cap),
193
+ );
194
+ if (!hasAny) {
195
+ return false;
196
+ }
197
+ }
198
+
199
+ // Check excluded capabilities (NONE must be present)
200
+ if (config.excludeCapabilities && config.excludeCapabilities.length > 0) {
201
+ const hasExcluded = config.excludeCapabilities.some((cap) =>
202
+ hasCapability(info, cap),
203
+ );
204
+ if (hasExcluded) {
205
+ return false;
206
+ }
207
+ }
208
+
209
+ // Check API format
210
+ if (config.apiFormat && info.apiFormat !== config.apiFormat) {
211
+ return false;
212
+ }
213
+
214
+ // Check context window bounds
215
+ if (
216
+ config.minContextWindow &&
217
+ (info.contextWindow ?? 0) < config.minContextWindow
218
+ ) {
219
+ return false;
220
+ }
221
+ if (
222
+ config.maxContextWindow &&
223
+ (info.contextWindow ?? Number.POSITIVE_INFINITY) > config.maxContextWindow
224
+ ) {
225
+ return false;
226
+ }
227
+
228
+ // Check max tokens
229
+ if (config.minMaxTokens && (info.maxTokens ?? 0) < config.minMaxTokens) {
230
+ return false;
231
+ }
232
+
233
+ // Check pricing bounds
234
+ if (
235
+ config.maxInputPrice &&
236
+ (info.pricing?.input ?? Number.POSITIVE_INFINITY) > config.maxInputPrice
237
+ ) {
238
+ return false;
239
+ }
240
+ if (
241
+ config.maxOutputPrice &&
242
+ (info.pricing?.output ?? Number.POSITIVE_INFINITY) > config.maxOutputPrice
243
+ ) {
244
+ return false;
245
+ }
246
+
247
+ // Check search term
248
+ if (config.search) {
249
+ const searchLower = config.search.toLowerCase();
250
+ const nameMatch = info.name?.toLowerCase().includes(searchLower) ?? false;
251
+ const idMatch = modelId.toLowerCase().includes(searchLower);
252
+ const descMatch =
253
+ info.description?.toLowerCase().includes(searchLower) ?? false;
254
+ if (!nameMatch && !idMatch && !descMatch) {
255
+ return false;
256
+ }
257
+ }
258
+
259
+ // Check thinking support
260
+ if (config.hasThinking === true && !info.thinkingConfig) {
261
+ return false;
262
+ }
263
+ if (config.hasThinking === false && info.thinkingConfig) {
264
+ return false;
265
+ }
266
+
267
+ return true;
268
+ }
269
+
270
+ /**
271
+ * Sort model results
272
+ */
273
+ export function sortModels(
274
+ models: ModelMatch[],
275
+ sortBy: ModelQueryConfig["sortBy"],
276
+ direction: "asc" | "desc" = "asc",
277
+ ): ModelMatch[] {
278
+ if (!sortBy) {
279
+ return models;
280
+ }
281
+
282
+ const sorted = [...models].sort((a, b) => {
283
+ let aVal: number | string;
284
+ let bVal: number | string;
285
+
286
+ switch (sortBy) {
287
+ case "name":
288
+ aVal = a.info.name ?? a.modelId;
289
+ bVal = b.info.name ?? b.modelId;
290
+ break;
291
+ case "contextWindow":
292
+ aVal = a.info.contextWindow ?? 0;
293
+ bVal = b.info.contextWindow ?? 0;
294
+ break;
295
+ case "maxTokens":
296
+ aVal = a.info.maxTokens ?? 0;
297
+ bVal = b.info.maxTokens ?? 0;
298
+ break;
299
+ case "inputPrice":
300
+ aVal = a.info.pricing?.input ?? Number.POSITIVE_INFINITY;
301
+ bVal = b.info.pricing?.input ?? Number.POSITIVE_INFINITY;
302
+ break;
303
+ case "outputPrice":
304
+ aVal = a.info.pricing?.output ?? Number.POSITIVE_INFINITY;
305
+ bVal = b.info.pricing?.output ?? Number.POSITIVE_INFINITY;
306
+ break;
307
+ default:
308
+ return 0;
309
+ }
310
+
311
+ if (typeof aVal === "string" && typeof bVal === "string") {
312
+ return aVal.localeCompare(bVal);
313
+ }
314
+
315
+ return (aVal as number) - (bVal as number);
316
+ });
317
+
318
+ return direction === "desc" ? sorted.reverse() : sorted;
319
+ }
320
+
321
+ /**
322
+ * Validate query config
323
+ */
324
+ export function validateQueryConfig(data: unknown): ModelQueryConfig {
325
+ return ModelQueryConfigSchema.parse(data);
326
+ }
327
+
328
+ /**
329
+ * Safely validate query config (returns undefined on failure)
330
+ */
331
+ export function safeValidateQueryConfig(
332
+ data: unknown,
333
+ ): ModelQueryConfig | undefined {
334
+ const result = ModelQueryConfigSchema.safeParse(data);
335
+ return result.success ? result.data : undefined;
336
+ }
@@ -0,0 +1,4 @@
1
+ export {
2
+ OPENAI_COMPATIBLE_PROVIDERS,
3
+ type ProviderDefaults,
4
+ } from "./handlers/providers";