@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.
- package/README.md +198 -0
- package/dist/config-browser.d.ts +3 -0
- package/dist/config.d.ts +3 -0
- package/dist/index.browser.d.ts +4 -0
- package/dist/index.browser.js +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +7 -0
- package/dist/models/generated-access.d.ts +4 -0
- package/dist/models/generated-provider-loaders.d.ts +13 -0
- package/dist/models/generated.d.ts +14 -0
- package/dist/models/index.d.ts +43 -0
- package/dist/models/models-dev-catalog.d.ts +32 -0
- package/dist/models/providers/aihubmix.d.ts +5 -0
- package/dist/models/providers/anthropic.d.ts +53 -0
- package/dist/models/providers/asksage.d.ts +5 -0
- package/dist/models/providers/baseten.d.ts +5 -0
- package/dist/models/providers/bedrock.d.ts +7 -0
- package/dist/models/providers/cerebras.d.ts +7 -0
- package/dist/models/providers/claude-code.d.ts +4 -0
- package/dist/models/providers/cline.d.ts +34 -0
- package/dist/models/providers/deepseek.d.ts +8 -0
- package/dist/models/providers/dify.d.ts +5 -0
- package/dist/models/providers/doubao.d.ts +7 -0
- package/dist/models/providers/fireworks.d.ts +8 -0
- package/dist/models/providers/gemini.d.ts +9 -0
- package/dist/models/providers/groq.d.ts +8 -0
- package/dist/models/providers/hicap.d.ts +5 -0
- package/dist/models/providers/huawei-cloud-maas.d.ts +5 -0
- package/dist/models/providers/huggingface.d.ts +6 -0
- package/dist/models/providers/index.d.ts +45 -0
- package/dist/models/providers/litellm.d.ts +5 -0
- package/dist/models/providers/lmstudio.d.ts +5 -0
- package/dist/models/providers/minimax.d.ts +7 -0
- package/dist/models/providers/mistral.d.ts +5 -0
- package/dist/models/providers/moonshot.d.ts +7 -0
- package/dist/models/providers/nebius.d.ts +7 -0
- package/dist/models/providers/nous-research.d.ts +7 -0
- package/dist/models/providers/oca.d.ts +9 -0
- package/dist/models/providers/ollama.d.ts +5 -0
- package/dist/models/providers/openai-codex.d.ts +10 -0
- package/dist/models/providers/openai.d.ts +9 -0
- package/dist/models/providers/opencode.d.ts +10 -0
- package/dist/models/providers/openrouter.d.ts +7 -0
- package/dist/models/providers/qwen-code.d.ts +7 -0
- package/dist/models/providers/qwen.d.ts +7 -0
- package/dist/models/providers/requesty.d.ts +6 -0
- package/dist/models/providers/sambanova.d.ts +7 -0
- package/dist/models/providers/sapaicore.d.ts +7 -0
- package/dist/models/providers/together.d.ts +8 -0
- package/dist/models/providers/vercel-ai-gateway.d.ts +5 -0
- package/dist/models/providers/vertex.d.ts +7 -0
- package/dist/models/providers/xai.d.ts +8 -0
- package/dist/models/providers/zai.d.ts +7 -0
- package/dist/models/query.d.ts +181 -0
- package/dist/models/registry.d.ts +123 -0
- package/dist/models/schemas/index.d.ts +7 -0
- package/dist/models/schemas/model.d.ts +340 -0
- package/dist/models/schemas/query.d.ts +191 -0
- package/dist/providers/handlers/ai-sdk-community.d.ts +46 -0
- package/dist/providers/handlers/ai-sdk-provider-base.d.ts +32 -0
- package/dist/providers/handlers/anthropic-base.d.ts +26 -0
- package/dist/providers/handlers/asksage.d.ts +12 -0
- package/dist/providers/handlers/auth.d.ts +5 -0
- package/dist/providers/handlers/base.d.ts +55 -0
- package/dist/providers/handlers/bedrock-base.d.ts +23 -0
- package/dist/providers/handlers/bedrock-client.d.ts +4 -0
- package/dist/providers/handlers/community-sdk.d.ts +97 -0
- package/dist/providers/handlers/fetch-base.d.ts +18 -0
- package/dist/providers/handlers/gemini-base.d.ts +25 -0
- package/dist/providers/handlers/index.d.ts +19 -0
- package/dist/providers/handlers/openai-base.d.ts +54 -0
- package/dist/providers/handlers/openai-responses.d.ts +64 -0
- package/dist/providers/handlers/providers.d.ts +43 -0
- package/dist/providers/handlers/r1-base.d.ts +62 -0
- package/dist/providers/handlers/registry.d.ts +106 -0
- package/dist/providers/handlers/vertex.d.ts +32 -0
- package/dist/providers/index.d.ts +100 -0
- package/dist/providers/public.browser.d.ts +2 -0
- package/dist/providers/public.d.ts +3 -0
- package/dist/providers/shared/openai-compatible.d.ts +10 -0
- package/dist/providers/transform/ai-sdk-community-format.d.ts +9 -0
- package/dist/providers/transform/anthropic-format.d.ts +24 -0
- package/dist/providers/transform/content-format.d.ts +3 -0
- package/dist/providers/transform/gemini-format.d.ts +19 -0
- package/dist/providers/transform/index.d.ts +10 -0
- package/dist/providers/transform/openai-format.d.ts +36 -0
- package/dist/providers/transform/r1-format.d.ts +26 -0
- package/dist/providers/types/config.d.ts +261 -0
- package/dist/providers/types/handler.d.ts +71 -0
- package/dist/providers/types/index.d.ts +11 -0
- package/dist/providers/types/messages.d.ts +139 -0
- package/dist/providers/types/model-info.d.ts +32 -0
- package/dist/providers/types/provider-ids.d.ts +63 -0
- package/dist/providers/types/settings.d.ts +308 -0
- package/dist/providers/types/stream.d.ts +106 -0
- package/dist/providers/utils/index.d.ts +7 -0
- package/dist/providers/utils/retry.d.ts +38 -0
- package/dist/providers/utils/stream-processor.d.ts +110 -0
- package/dist/providers/utils/tool-processor.d.ts +34 -0
- package/dist/sdk.d.ts +18 -0
- package/dist/types.d.ts +60 -0
- package/package.json +66 -0
- package/src/catalog.ts +20 -0
- package/src/config-browser.ts +11 -0
- package/src/config.ts +49 -0
- package/src/index.browser.ts +9 -0
- package/src/index.ts +10 -0
- package/src/live-providers.test.ts +137 -0
- package/src/models/generated-access.ts +41 -0
- package/src/models/generated-provider-loaders.ts +166 -0
- package/src/models/generated.ts +11997 -0
- package/src/models/index.ts +271 -0
- package/src/models/models-dev-catalog.test.ts +161 -0
- package/src/models/models-dev-catalog.ts +161 -0
- package/src/models/providers/aihubmix.ts +19 -0
- package/src/models/providers/anthropic.ts +60 -0
- package/src/models/providers/asksage.ts +19 -0
- package/src/models/providers/baseten.ts +21 -0
- package/src/models/providers/bedrock.ts +30 -0
- package/src/models/providers/cerebras.ts +24 -0
- package/src/models/providers/claude-code.ts +51 -0
- package/src/models/providers/cline.ts +25 -0
- package/src/models/providers/deepseek.ts +33 -0
- package/src/models/providers/dify.ts +17 -0
- package/src/models/providers/doubao.ts +33 -0
- package/src/models/providers/fireworks.ts +34 -0
- package/src/models/providers/gemini.ts +43 -0
- package/src/models/providers/groq.ts +33 -0
- package/src/models/providers/hicap.ts +18 -0
- package/src/models/providers/huawei-cloud-maas.ts +18 -0
- package/src/models/providers/huggingface.ts +22 -0
- package/src/models/providers/index.ts +162 -0
- package/src/models/providers/litellm.ts +19 -0
- package/src/models/providers/lmstudio.ts +22 -0
- package/src/models/providers/minimax.ts +34 -0
- package/src/models/providers/mistral.ts +19 -0
- package/src/models/providers/moonshot.ts +34 -0
- package/src/models/providers/nebius.ts +24 -0
- package/src/models/providers/nous-research.ts +21 -0
- package/src/models/providers/oca.ts +30 -0
- package/src/models/providers/ollama.ts +18 -0
- package/src/models/providers/openai-codex.ts +30 -0
- package/src/models/providers/openai.ts +43 -0
- package/src/models/providers/opencode.ts +28 -0
- package/src/models/providers/openrouter.ts +24 -0
- package/src/models/providers/qwen-code.ts +33 -0
- package/src/models/providers/qwen.ts +34 -0
- package/src/models/providers/requesty.ts +23 -0
- package/src/models/providers/sambanova.ts +23 -0
- package/src/models/providers/sapaicore.ts +34 -0
- package/src/models/providers/together.ts +35 -0
- package/src/models/providers/vercel-ai-gateway.ts +23 -0
- package/src/models/providers/vertex.ts +36 -0
- package/src/models/providers/xai.ts +34 -0
- package/src/models/providers/zai.ts +25 -0
- package/src/models/query.ts +407 -0
- package/src/models/registry.ts +511 -0
- package/src/models/schemas/index.ts +62 -0
- package/src/models/schemas/model.ts +308 -0
- package/src/models/schemas/query.ts +336 -0
- package/src/providers/browser.ts +4 -0
- package/src/providers/handlers/ai-sdk-community.ts +226 -0
- package/src/providers/handlers/ai-sdk-provider-base.ts +193 -0
- package/src/providers/handlers/anthropic-base.ts +372 -0
- package/src/providers/handlers/asksage.test.ts +103 -0
- package/src/providers/handlers/asksage.ts +138 -0
- package/src/providers/handlers/auth.test.ts +19 -0
- package/src/providers/handlers/auth.ts +121 -0
- package/src/providers/handlers/base.test.ts +46 -0
- package/src/providers/handlers/base.ts +160 -0
- package/src/providers/handlers/bedrock-base.ts +390 -0
- package/src/providers/handlers/bedrock-client.ts +100 -0
- package/src/providers/handlers/codex.test.ts +123 -0
- package/src/providers/handlers/community-sdk.test.ts +288 -0
- package/src/providers/handlers/community-sdk.ts +392 -0
- package/src/providers/handlers/fetch-base.ts +68 -0
- package/src/providers/handlers/gemini-base.ts +302 -0
- package/src/providers/handlers/index.ts +67 -0
- package/src/providers/handlers/openai-base.ts +277 -0
- package/src/providers/handlers/openai-responses.ts +598 -0
- package/src/providers/handlers/providers.test.ts +120 -0
- package/src/providers/handlers/providers.ts +563 -0
- package/src/providers/handlers/r1-base.ts +280 -0
- package/src/providers/handlers/registry.ts +185 -0
- package/src/providers/handlers/vertex.test.ts +124 -0
- package/src/providers/handlers/vertex.ts +292 -0
- package/src/providers/index.ts +534 -0
- package/src/providers/public.browser.ts +20 -0
- package/src/providers/public.ts +51 -0
- package/src/providers/shared/openai-compatible.ts +63 -0
- package/src/providers/transform/ai-sdk-community-format.test.ts +73 -0
- package/src/providers/transform/ai-sdk-community-format.ts +115 -0
- package/src/providers/transform/anthropic-format.ts +218 -0
- package/src/providers/transform/content-format.ts +34 -0
- package/src/providers/transform/format-conversion.test.ts +310 -0
- package/src/providers/transform/gemini-format.ts +167 -0
- package/src/providers/transform/index.ts +22 -0
- package/src/providers/transform/openai-format.ts +247 -0
- package/src/providers/transform/r1-format.ts +287 -0
- package/src/providers/types/config.ts +388 -0
- package/src/providers/types/handler.ts +87 -0
- package/src/providers/types/index.ts +120 -0
- package/src/providers/types/messages.ts +158 -0
- package/src/providers/types/model-info.test.ts +57 -0
- package/src/providers/types/model-info.ts +65 -0
- package/src/providers/types/provider-ids.test.ts +12 -0
- package/src/providers/types/provider-ids.ts +89 -0
- package/src/providers/types/settings.test.ts +49 -0
- package/src/providers/types/settings.ts +533 -0
- package/src/providers/types/stream.ts +117 -0
- package/src/providers/utils/index.ts +27 -0
- package/src/providers/utils/retry.test.ts +140 -0
- package/src/providers/utils/retry.ts +188 -0
- package/src/providers/utils/stream-processor.test.ts +232 -0
- package/src/providers/utils/stream-processor.ts +472 -0
- package/src/providers/utils/tool-processor.test.ts +34 -0
- package/src/providers/utils/tool-processor.ts +111 -0
- package/src/sdk.ts +264 -0
- 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
|
+
}
|