@funkai/models 0.1.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/.generated/entries.json +23 -0
- package/.generated/req.txt +1 -0
- package/.turbo/turbo-build.log +145 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +23 -0
- package/README.md +95 -0
- package/dist/alibaba-B6q4Ng1R.mjs +957 -0
- package/dist/alibaba-B6q4Ng1R.mjs.map +1 -0
- package/dist/amazon-bedrock-Cv9AHQBH.mjs +2070 -0
- package/dist/amazon-bedrock-Cv9AHQBH.mjs.map +1 -0
- package/dist/anthropic-yB7ST97_.mjs +651 -0
- package/dist/anthropic-yB7ST97_.mjs.map +1 -0
- package/dist/cerebras-COfl7XM-.mjs +95 -0
- package/dist/cerebras-COfl7XM-.mjs.map +1 -0
- package/dist/cohere-B7TgO0hT.mjs +271 -0
- package/dist/cohere-B7TgO0hT.mjs.map +1 -0
- package/dist/deepinfra-B0GxUwCG.mjs +636 -0
- package/dist/deepinfra-B0GxUwCG.mjs.map +1 -0
- package/dist/deepseek-D64ZEsvS.mjs +50 -0
- package/dist/deepseek-D64ZEsvS.mjs.map +1 -0
- package/dist/fireworks-ai-DJYvdAi_.mjs +304 -0
- package/dist/fireworks-ai-DJYvdAi_.mjs.map +1 -0
- package/dist/google-BypRl349.mjs +833 -0
- package/dist/google-BypRl349.mjs.map +1 -0
- package/dist/google-vertex-DbS-zTGD.mjs +730 -0
- package/dist/google-vertex-DbS-zTGD.mjs.map +1 -0
- package/dist/groq-ei_PerYi.mjs +381 -0
- package/dist/groq-ei_PerYi.mjs.map +1 -0
- package/dist/huggingface-DaM1EeLP.mjs +456 -0
- package/dist/huggingface-DaM1EeLP.mjs.map +1 -0
- package/dist/inception-CspEzqNV.mjs +101 -0
- package/dist/inception-CspEzqNV.mjs.map +1 -0
- package/dist/index.d.mts +30314 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +271 -0
- package/dist/index.mjs.map +1 -0
- package/dist/llama-Cf3-koap.mjs +161 -0
- package/dist/llama-Cf3-koap.mjs.map +1 -0
- package/dist/mistral-BI9MdAO4.mjs +579 -0
- package/dist/mistral-BI9MdAO4.mjs.map +1 -0
- package/dist/nvidia-COHacuoa.mjs +1625 -0
- package/dist/nvidia-COHacuoa.mjs.map +1 -0
- package/dist/openai-C0nCfZUq.mjs +1023 -0
- package/dist/openai-C0nCfZUq.mjs.map +1 -0
- package/dist/openrouter-DSFzxKQb.mjs +4608 -0
- package/dist/openrouter-DSFzxKQb.mjs.map +1 -0
- package/dist/perplexity-zeZ2WlBU.mjs +96 -0
- package/dist/perplexity-zeZ2WlBU.mjs.map +1 -0
- package/dist/providers/alibaba.d.mts +1795 -0
- package/dist/providers/alibaba.d.mts.map +1 -0
- package/dist/providers/alibaba.mjs +39 -0
- package/dist/providers/alibaba.mjs.map +1 -0
- package/dist/providers/amazon-bedrock.d.mts +3713 -0
- package/dist/providers/amazon-bedrock.d.mts.map +1 -0
- package/dist/providers/amazon-bedrock.mjs +39 -0
- package/dist/providers/amazon-bedrock.mjs.map +1 -0
- package/dist/providers/anthropic.d.mts +1109 -0
- package/dist/providers/anthropic.d.mts.map +1 -0
- package/dist/providers/anthropic.mjs +39 -0
- package/dist/providers/anthropic.mjs.map +1 -0
- package/dist/providers/cerebras.d.mts +219 -0
- package/dist/providers/cerebras.d.mts.map +1 -0
- package/dist/providers/cerebras.mjs +39 -0
- package/dist/providers/cerebras.mjs.map +1 -0
- package/dist/providers/cohere.d.mts +555 -0
- package/dist/providers/cohere.d.mts.map +1 -0
- package/dist/providers/cohere.mjs +39 -0
- package/dist/providers/cohere.mjs.map +1 -0
- package/dist/providers/deepinfra.d.mts +1245 -0
- package/dist/providers/deepinfra.d.mts.map +1 -0
- package/dist/providers/deepinfra.mjs +39 -0
- package/dist/providers/deepinfra.mjs.map +1 -0
- package/dist/providers/deepseek.d.mts +139 -0
- package/dist/providers/deepseek.d.mts.map +1 -0
- package/dist/providers/deepseek.mjs +39 -0
- package/dist/providers/deepseek.mjs.map +1 -0
- package/dist/providers/fireworks-ai.d.mts +611 -0
- package/dist/providers/fireworks-ai.d.mts.map +1 -0
- package/dist/providers/fireworks-ai.mjs +39 -0
- package/dist/providers/fireworks-ai.mjs.map +1 -0
- package/dist/providers/google-vertex.d.mts +1227 -0
- package/dist/providers/google-vertex.d.mts.map +1 -0
- package/dist/providers/google-vertex.mjs +39 -0
- package/dist/providers/google-vertex.mjs.map +1 -0
- package/dist/providers/google.d.mts +1359 -0
- package/dist/providers/google.d.mts.map +1 -0
- package/dist/providers/google.mjs +39 -0
- package/dist/providers/google.mjs.map +1 -0
- package/dist/providers/groq.d.mts +765 -0
- package/dist/providers/groq.d.mts.map +1 -0
- package/dist/providers/groq.mjs +39 -0
- package/dist/providers/groq.mjs.map +1 -0
- package/dist/providers/huggingface.d.mts +901 -0
- package/dist/providers/huggingface.d.mts.map +1 -0
- package/dist/providers/huggingface.mjs +39 -0
- package/dist/providers/huggingface.mjs.map +1 -0
- package/dist/providers/inception.d.mts +231 -0
- package/dist/providers/inception.d.mts.map +1 -0
- package/dist/providers/inception.mjs +39 -0
- package/dist/providers/inception.mjs.map +1 -0
- package/dist/providers/llama.d.mts +345 -0
- package/dist/providers/llama.d.mts.map +1 -0
- package/dist/providers/llama.mjs +39 -0
- package/dist/providers/llama.mjs.map +1 -0
- package/dist/providers/mistral.d.mts +1143 -0
- package/dist/providers/mistral.d.mts.map +1 -0
- package/dist/providers/mistral.mjs +39 -0
- package/dist/providers/mistral.mjs.map +1 -0
- package/dist/providers/nvidia.d.mts +3117 -0
- package/dist/providers/nvidia.d.mts.map +1 -0
- package/dist/providers/nvidia.mjs +39 -0
- package/dist/providers/nvidia.mjs.map +1 -0
- package/dist/providers/openai.d.mts +1963 -0
- package/dist/providers/openai.d.mts.map +1 -0
- package/dist/providers/openai.mjs +39 -0
- package/dist/providers/openai.mjs.map +1 -0
- package/dist/providers/openrouter.d.mts +8531 -0
- package/dist/providers/openrouter.d.mts.map +1 -0
- package/dist/providers/openrouter.mjs +39 -0
- package/dist/providers/openrouter.mjs.map +1 -0
- package/dist/providers/perplexity.d.mts +221 -0
- package/dist/providers/perplexity.d.mts.map +1 -0
- package/dist/providers/perplexity.mjs +39 -0
- package/dist/providers/perplexity.mjs.map +1 -0
- package/dist/providers/togetherai.d.mts +767 -0
- package/dist/providers/togetherai.d.mts.map +1 -0
- package/dist/providers/togetherai.mjs +39 -0
- package/dist/providers/togetherai.mjs.map +1 -0
- package/dist/providers/xai.d.mts +1161 -0
- package/dist/providers/xai.d.mts.map +1 -0
- package/dist/providers/xai.mjs +39 -0
- package/dist/providers/xai.mjs.map +1 -0
- package/dist/togetherai-BvcxUfPE.mjs +382 -0
- package/dist/togetherai-BvcxUfPE.mjs.map +1 -0
- package/dist/types-DjdaZckF.d.mts +71 -0
- package/dist/types-DjdaZckF.d.mts.map +1 -0
- package/dist/xai-fSuAkQJo.mjs +587 -0
- package/dist/xai-fSuAkQJo.mjs.map +1 -0
- package/docs/catalog/filtering.md +102 -0
- package/docs/catalog/overview.md +168 -0
- package/docs/catalog/providers.md +73 -0
- package/docs/cost/overview.md +125 -0
- package/docs/guides/filter-models.md +113 -0
- package/docs/guides/setup-resolver.md +106 -0
- package/docs/guides/track-costs.md +133 -0
- package/docs/overview.md +139 -0
- package/docs/provider/configuration.md +100 -0
- package/docs/provider/openrouter.md +105 -0
- package/docs/provider/overview.md +131 -0
- package/docs/troubleshooting.md +100 -0
- package/package.json +142 -0
- package/providers.json +39 -0
- package/scripts/generate-models.ts +392 -0
- package/src/catalog/index.test.ts +124 -0
- package/src/catalog/index.ts +65 -0
- package/src/catalog/providers/alibaba.ts +468 -0
- package/src/catalog/providers/amazon-bedrock.ts +941 -0
- package/src/catalog/providers/anthropic.ts +270 -0
- package/src/catalog/providers/cerebras.ts +61 -0
- package/src/catalog/providers/cohere.ts +149 -0
- package/src/catalog/providers/deepinfra.ts +325 -0
- package/src/catalog/providers/deepseek.ts +39 -0
- package/src/catalog/providers/fireworks-ai.ts +160 -0
- package/src/catalog/providers/google-vertex.ts +314 -0
- package/src/catalog/providers/google.ts +347 -0
- package/src/catalog/providers/groq.ts +204 -0
- package/src/catalog/providers/huggingface.ts +237 -0
- package/src/catalog/providers/inception.ts +61 -0
- package/src/catalog/providers/index.ts +59 -0
- package/src/catalog/providers/llama.ts +94 -0
- package/src/catalog/providers/mistral.ts +303 -0
- package/src/catalog/providers/nvidia.ts +820 -0
- package/src/catalog/providers/openai.ts +501 -0
- package/src/catalog/providers/openrouter.ts +2201 -0
- package/src/catalog/providers/perplexity.ts +61 -0
- package/src/catalog/providers/togetherai.ts +204 -0
- package/src/catalog/providers/xai.ts +292 -0
- package/src/catalog/types.ts +86 -0
- package/src/cost/calculate.test.ts +157 -0
- package/src/cost/calculate.ts +43 -0
- package/src/cost/index.ts +2 -0
- package/src/cost/types.ts +25 -0
- package/src/index.ts +25 -0
- package/src/provider/index.ts +9 -0
- package/src/provider/openrouter.test.ts +125 -0
- package/src/provider/openrouter.ts +110 -0
- package/src/provider/resolver.test.ts +138 -0
- package/src/provider/resolver.ts +125 -0
- package/src/provider/types.ts +39 -0
- package/src/providers/alibaba.ts +65 -0
- package/src/providers/amazon-bedrock.ts +67 -0
- package/src/providers/anthropic.ts +65 -0
- package/src/providers/cerebras.ts +65 -0
- package/src/providers/cohere.ts +65 -0
- package/src/providers/deepinfra.ts +65 -0
- package/src/providers/deepseek.ts +65 -0
- package/src/providers/fireworks-ai.ts +65 -0
- package/src/providers/google-vertex.ts +67 -0
- package/src/providers/google.ts +65 -0
- package/src/providers/groq.ts +65 -0
- package/src/providers/huggingface.ts +67 -0
- package/src/providers/inception.ts +65 -0
- package/src/providers/llama.ts +65 -0
- package/src/providers/mistral.ts +65 -0
- package/src/providers/nvidia.ts +65 -0
- package/src/providers/openai.ts +65 -0
- package/src/providers/openrouter.ts +67 -0
- package/src/providers/perplexity.ts +67 -0
- package/src/providers/togetherai.ts +65 -0
- package/src/providers/xai.ts +65 -0
- package/tsconfig.json +25 -0
- package/tsdown.config.ts +23 -0
- package/vitest.config.ts +29 -0
package/package.json
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@funkai/models",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Model catalog, provider resolution, and cost calculations for the funkai AI SDK",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"ai",
|
|
8
|
+
"ai-sdk",
|
|
9
|
+
"models",
|
|
10
|
+
"openrouter",
|
|
11
|
+
"pricing",
|
|
12
|
+
"providers",
|
|
13
|
+
"typescript"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/joggrdocs/funkai/tree/main/packages/models#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/joggrdocs/funkai/issues"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/joggrdocs/funkai.git",
|
|
23
|
+
"directory": "packages/models"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.mts",
|
|
29
|
+
"import": "./dist/index.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./openai": {
|
|
32
|
+
"types": "./dist/providers/openai.d.mts",
|
|
33
|
+
"import": "./dist/providers/openai.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./anthropic": {
|
|
36
|
+
"types": "./dist/providers/anthropic.d.mts",
|
|
37
|
+
"import": "./dist/providers/anthropic.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./google": {
|
|
40
|
+
"types": "./dist/providers/google.d.mts",
|
|
41
|
+
"import": "./dist/providers/google.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./google-vertex": {
|
|
44
|
+
"types": "./dist/providers/google-vertex.d.mts",
|
|
45
|
+
"import": "./dist/providers/google-vertex.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./mistral": {
|
|
48
|
+
"types": "./dist/providers/mistral.d.mts",
|
|
49
|
+
"import": "./dist/providers/mistral.mjs"
|
|
50
|
+
},
|
|
51
|
+
"./amazon-bedrock": {
|
|
52
|
+
"types": "./dist/providers/amazon-bedrock.d.mts",
|
|
53
|
+
"import": "./dist/providers/amazon-bedrock.mjs"
|
|
54
|
+
},
|
|
55
|
+
"./groq": {
|
|
56
|
+
"types": "./dist/providers/groq.d.mts",
|
|
57
|
+
"import": "./dist/providers/groq.mjs"
|
|
58
|
+
},
|
|
59
|
+
"./deepseek": {
|
|
60
|
+
"types": "./dist/providers/deepseek.d.mts",
|
|
61
|
+
"import": "./dist/providers/deepseek.mjs"
|
|
62
|
+
},
|
|
63
|
+
"./xai": {
|
|
64
|
+
"types": "./dist/providers/xai.d.mts",
|
|
65
|
+
"import": "./dist/providers/xai.mjs"
|
|
66
|
+
},
|
|
67
|
+
"./cohere": {
|
|
68
|
+
"types": "./dist/providers/cohere.d.mts",
|
|
69
|
+
"import": "./dist/providers/cohere.mjs"
|
|
70
|
+
},
|
|
71
|
+
"./fireworks-ai": {
|
|
72
|
+
"types": "./dist/providers/fireworks-ai.d.mts",
|
|
73
|
+
"import": "./dist/providers/fireworks-ai.mjs"
|
|
74
|
+
},
|
|
75
|
+
"./togetherai": {
|
|
76
|
+
"types": "./dist/providers/togetherai.d.mts",
|
|
77
|
+
"import": "./dist/providers/togetherai.mjs"
|
|
78
|
+
},
|
|
79
|
+
"./deepinfra": {
|
|
80
|
+
"types": "./dist/providers/deepinfra.d.mts",
|
|
81
|
+
"import": "./dist/providers/deepinfra.mjs"
|
|
82
|
+
},
|
|
83
|
+
"./cerebras": {
|
|
84
|
+
"types": "./dist/providers/cerebras.d.mts",
|
|
85
|
+
"import": "./dist/providers/cerebras.mjs"
|
|
86
|
+
},
|
|
87
|
+
"./perplexity": {
|
|
88
|
+
"types": "./dist/providers/perplexity.d.mts",
|
|
89
|
+
"import": "./dist/providers/perplexity.mjs"
|
|
90
|
+
},
|
|
91
|
+
"./openrouter": {
|
|
92
|
+
"types": "./dist/providers/openrouter.d.mts",
|
|
93
|
+
"import": "./dist/providers/openrouter.mjs"
|
|
94
|
+
},
|
|
95
|
+
"./llama": {
|
|
96
|
+
"types": "./dist/providers/llama.d.mts",
|
|
97
|
+
"import": "./dist/providers/llama.mjs"
|
|
98
|
+
},
|
|
99
|
+
"./alibaba": {
|
|
100
|
+
"types": "./dist/providers/alibaba.d.mts",
|
|
101
|
+
"import": "./dist/providers/alibaba.mjs"
|
|
102
|
+
},
|
|
103
|
+
"./nvidia": {
|
|
104
|
+
"types": "./dist/providers/nvidia.d.mts",
|
|
105
|
+
"import": "./dist/providers/nvidia.mjs"
|
|
106
|
+
},
|
|
107
|
+
"./huggingface": {
|
|
108
|
+
"types": "./dist/providers/huggingface.d.mts",
|
|
109
|
+
"import": "./dist/providers/huggingface.mjs"
|
|
110
|
+
},
|
|
111
|
+
"./inception": {
|
|
112
|
+
"types": "./dist/providers/inception.d.mts",
|
|
113
|
+
"import": "./dist/providers/inception.mjs"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"scripts": {
|
|
117
|
+
"generate:models": "lauf run @funkai/models/generate-models",
|
|
118
|
+
"build": "tsdown",
|
|
119
|
+
"typecheck": "tsc --noEmit",
|
|
120
|
+
"test": "vitest run --typecheck",
|
|
121
|
+
"test:coverage": "vitest run --coverage"
|
|
122
|
+
},
|
|
123
|
+
"dependencies": {
|
|
124
|
+
"@openrouter/ai-sdk-provider": "^2.3.1",
|
|
125
|
+
"ai": "^6.0.116",
|
|
126
|
+
"type-fest": "^5.4.4"
|
|
127
|
+
},
|
|
128
|
+
"devDependencies": {
|
|
129
|
+
"@types/node": "catalog:",
|
|
130
|
+
"@vitest/coverage-v8": "catalog:",
|
|
131
|
+
"tsdown": "catalog:",
|
|
132
|
+
"tsx": "catalog:",
|
|
133
|
+
"typescript": "catalog:",
|
|
134
|
+
"vitest": "catalog:"
|
|
135
|
+
},
|
|
136
|
+
"publishConfig": {
|
|
137
|
+
"access": "public"
|
|
138
|
+
},
|
|
139
|
+
"engines": {
|
|
140
|
+
"node": ">=24.0.0"
|
|
141
|
+
}
|
|
142
|
+
}
|
package/providers.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openai": { "name": "OpenAI", "prefix": "OpenAI", "sdk": "@ai-sdk/openai" },
|
|
3
|
+
"anthropic": { "name": "Anthropic", "prefix": "Anthropic", "sdk": "@ai-sdk/anthropic" },
|
|
4
|
+
"google": { "name": "Google", "prefix": "Google", "sdk": "@ai-sdk/google" },
|
|
5
|
+
"google-vertex": {
|
|
6
|
+
"name": "Google Vertex AI",
|
|
7
|
+
"prefix": "GoogleVertex",
|
|
8
|
+
"sdk": "@ai-sdk/google-vertex"
|
|
9
|
+
},
|
|
10
|
+
"mistral": { "name": "Mistral", "prefix": "Mistral", "sdk": "@ai-sdk/mistral" },
|
|
11
|
+
"amazon-bedrock": {
|
|
12
|
+
"name": "Amazon Bedrock",
|
|
13
|
+
"prefix": "AmazonBedrock",
|
|
14
|
+
"sdk": "@ai-sdk/amazon-bedrock"
|
|
15
|
+
},
|
|
16
|
+
"groq": { "name": "Groq", "prefix": "Groq", "sdk": "@ai-sdk/groq" },
|
|
17
|
+
"deepseek": { "name": "DeepSeek", "prefix": "DeepSeek", "sdk": "@ai-sdk/deepseek" },
|
|
18
|
+
"xai": { "name": "xAI", "prefix": "XAI", "sdk": "@ai-sdk/xai" },
|
|
19
|
+
"cohere": { "name": "Cohere", "prefix": "Cohere", "sdk": "@ai-sdk/cohere" },
|
|
20
|
+
"fireworks-ai": { "name": "Fireworks AI", "prefix": "Fireworks", "sdk": "@ai-sdk/fireworks" },
|
|
21
|
+
"togetherai": { "name": "Together AI", "prefix": "Together", "sdk": "@ai-sdk/togetherai" },
|
|
22
|
+
"deepinfra": { "name": "DeepInfra", "prefix": "DeepInfra", "sdk": "@ai-sdk/deepinfra" },
|
|
23
|
+
"cerebras": { "name": "Cerebras", "prefix": "Cerebras", "sdk": "@ai-sdk/cerebras" },
|
|
24
|
+
"perplexity": { "name": "Perplexity", "prefix": "Perplexity", "sdk": "@ai-sdk/perplexity" },
|
|
25
|
+
"openrouter": {
|
|
26
|
+
"name": "OpenRouter",
|
|
27
|
+
"prefix": "OpenRouter",
|
|
28
|
+
"sdk": "@openrouter/ai-sdk-provider"
|
|
29
|
+
},
|
|
30
|
+
"llama": { "name": "Meta Llama", "prefix": "Llama", "sdk": "@ai-sdk/openai-compatible" },
|
|
31
|
+
"alibaba": { "name": "Alibaba (Qwen)", "prefix": "Alibaba", "sdk": "@ai-sdk/alibaba" },
|
|
32
|
+
"nvidia": { "name": "NVIDIA NIM", "prefix": "Nvidia", "sdk": "@ai-sdk/openai-compatible" },
|
|
33
|
+
"huggingface": { "name": "Hugging Face", "prefix": "HuggingFace", "sdk": "@ai-sdk/huggingface" },
|
|
34
|
+
"inception": {
|
|
35
|
+
"name": "Inception (Mercury)",
|
|
36
|
+
"prefix": "Inception",
|
|
37
|
+
"sdk": "@ai-sdk/openai-compatible"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { lauf, z } from "laufen";
|
|
5
|
+
|
|
6
|
+
const API_URL = "https://models.dev/api.json";
|
|
7
|
+
const STALE_MS = 24 * 60 * 60 * 1000;
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Banner
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
const BANNER = `// ──────────────────────────────────────────────────────────────
|
|
14
|
+
// ███████╗██╗ ██╗███╗ ██╗██╗ ██╗ █████╗ ██╗
|
|
15
|
+
// ██╔════╝██║ ██║████╗ ██║██║ ██╔╝██╔══██╗██║
|
|
16
|
+
// █████╗ ██║ ██║██╔██╗ ██║█████╔╝ ███████║██║
|
|
17
|
+
// ██╔══╝ ██║ ██║██║╚██╗██║██╔═██╗ ██╔══██║██║
|
|
18
|
+
// ██║ ╚██████╔╝██║ ╚████║██║ ██╗██║ ██║██║
|
|
19
|
+
// ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝
|
|
20
|
+
//
|
|
21
|
+
// AUTO-GENERATED — DO NOT EDIT
|
|
22
|
+
// Source: https://models.dev
|
|
23
|
+
// Update: pnpm --filter=@funkai/models generate:models
|
|
24
|
+
// ──────────────────────────────────────────────────────────────`;
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Types
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
interface ProviderEntry {
|
|
31
|
+
name: string;
|
|
32
|
+
prefix: string;
|
|
33
|
+
sdk: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ApiModel {
|
|
37
|
+
id: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
family?: string;
|
|
40
|
+
reasoning?: boolean;
|
|
41
|
+
tool_call?: boolean;
|
|
42
|
+
attachment?: boolean;
|
|
43
|
+
structured_output?: boolean;
|
|
44
|
+
modalities?: { input?: string[]; output?: string[] };
|
|
45
|
+
cost?: {
|
|
46
|
+
input?: number;
|
|
47
|
+
output?: number;
|
|
48
|
+
cache_read?: number;
|
|
49
|
+
cache_write?: number;
|
|
50
|
+
reasoning?: number;
|
|
51
|
+
};
|
|
52
|
+
limit?: { context?: number; output?: number };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface ApiProvider {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
models: Record<string, ApiModel>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Helpers
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Convert a provider key to a TypeScript constant name.
|
|
67
|
+
* e.g. "openai" → "OPENAI_MODELS", "meta-llama" → "META_LLAMA_MODELS"
|
|
68
|
+
*/
|
|
69
|
+
function toConstName(provider: string): string {
|
|
70
|
+
return `${provider.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_MODELS`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Lowercase the first character of a string, preserving the rest as-is.
|
|
75
|
+
* e.g. "OpenAI" → "openAI", "GoogleVertex" → "googleVertex", "XAI" → "xAI"
|
|
76
|
+
*/
|
|
77
|
+
function lowerFirst(s: string): string {
|
|
78
|
+
return s.length === 0 ? s : s[0]!.toLowerCase() + s.slice(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Return the correct indefinite article ("a" or "an") for a word.
|
|
83
|
+
*/
|
|
84
|
+
function article(word: string): string {
|
|
85
|
+
return /^[aeiou]/i.test(word) ? "an" : "a";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Convert per-million-token rate to per-token rate, rounding to
|
|
90
|
+
* eliminate floating-point noise (e.g. `8.000000000000001e-7`).
|
|
91
|
+
*/
|
|
92
|
+
function toPerToken(perMillion: number): number {
|
|
93
|
+
return parseFloat((perMillion / 1_000_000).toPrecision(6));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Format a number for codegen output, using scientific notation for
|
|
98
|
+
* very small values.
|
|
99
|
+
*/
|
|
100
|
+
function fmtNum(n: number): string {
|
|
101
|
+
if (n === 0) return "0";
|
|
102
|
+
if (n < 0.0000001) return n.toExponential();
|
|
103
|
+
return String(n);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Build the pricing object literal string for a model.
|
|
108
|
+
*/
|
|
109
|
+
function buildPricing(cost: ApiModel["cost"]): string {
|
|
110
|
+
const input = toPerToken(cost?.input ?? 0);
|
|
111
|
+
const output = toPerToken(cost?.output ?? 0);
|
|
112
|
+
const parts: string[] = [`input: ${fmtNum(input)}`, `output: ${fmtNum(output)}`];
|
|
113
|
+
|
|
114
|
+
if (cost?.cache_read != null && cost.cache_read > 0) {
|
|
115
|
+
parts.push(`cacheRead: ${fmtNum(toPerToken(cost.cache_read))}`);
|
|
116
|
+
}
|
|
117
|
+
if (cost?.cache_write != null && cost.cache_write > 0) {
|
|
118
|
+
parts.push(`cacheWrite: ${fmtNum(toPerToken(cost.cache_write))}`);
|
|
119
|
+
}
|
|
120
|
+
if (cost?.reasoning != null && cost.reasoning > 0) {
|
|
121
|
+
parts.push(`reasoning: ${fmtNum(toPerToken(cost.reasoning))}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return `{ ${parts.join(", ")} }`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Build the modalities object literal string.
|
|
129
|
+
*/
|
|
130
|
+
function buildModalities(modalities: ApiModel["modalities"]): string {
|
|
131
|
+
const input = JSON.stringify(modalities?.input ?? ["text"]);
|
|
132
|
+
const output = JSON.stringify(modalities?.output ?? ["text"]);
|
|
133
|
+
return `{ input: ${input}, output: ${output} }`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Build the capabilities object literal string.
|
|
138
|
+
*/
|
|
139
|
+
function buildCapabilities(m: ApiModel): string {
|
|
140
|
+
return [
|
|
141
|
+
`reasoning: ${Boolean(m.reasoning)}`,
|
|
142
|
+
`toolCall: ${Boolean(m.tool_call)}`,
|
|
143
|
+
`attachment: ${Boolean(m.attachment)}`,
|
|
144
|
+
`structuredOutput: ${Boolean(m.structured_output)}`,
|
|
145
|
+
].join(", ");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Escape a string for use in a TypeScript single-quoted string literal.
|
|
150
|
+
*/
|
|
151
|
+
function escapeStr(s: string): string {
|
|
152
|
+
return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Staleness check
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
function isFresh(reqPath: string): boolean {
|
|
160
|
+
if (!existsSync(reqPath)) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const timestamp = readFileSync(reqPath, "utf-8").trim();
|
|
165
|
+
const lastRun = new Date(timestamp).getTime();
|
|
166
|
+
return Date.now() - lastRun < STALE_MS;
|
|
167
|
+
} catch {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
// Script
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
export default lauf({
|
|
177
|
+
description: "Fetch model data from models.dev and generate TypeScript catalog files",
|
|
178
|
+
args: {
|
|
179
|
+
force: z.boolean().default(false).describe("Force-fetch ignoring staleness cache"),
|
|
180
|
+
},
|
|
181
|
+
async run(ctx) {
|
|
182
|
+
const PACKAGE_ROOT = ctx.dir.package;
|
|
183
|
+
const PROVIDERS_PATH = join(PACKAGE_ROOT, "providers.json");
|
|
184
|
+
const CATALOG_DIR = join(PACKAGE_ROOT, "src", "catalog", "providers");
|
|
185
|
+
const ENTRY_DIR = join(PACKAGE_ROOT, "src", "providers");
|
|
186
|
+
const GENERATED_DIR = join(PACKAGE_ROOT, ".generated");
|
|
187
|
+
const REQ_PATH = join(GENERATED_DIR, "req.txt");
|
|
188
|
+
const ENTRIES_PATH = join(GENERATED_DIR, "entries.json");
|
|
189
|
+
const PACKAGE_JSON_PATH = join(PACKAGE_ROOT, "package.json");
|
|
190
|
+
|
|
191
|
+
if (!ctx.args.force && isFresh(REQ_PATH)) {
|
|
192
|
+
ctx.logger.info("skipping — last fetch was less than 24h ago");
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Read provider config
|
|
197
|
+
const providers: Record<string, ProviderEntry> = JSON.parse(
|
|
198
|
+
readFileSync(PROVIDERS_PATH, "utf-8"),
|
|
199
|
+
);
|
|
200
|
+
const providerKeys = Object.keys(providers);
|
|
201
|
+
|
|
202
|
+
if (providerKeys.length === 0) {
|
|
203
|
+
throw new Error("providers.json has no providers");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Fetch models.dev API
|
|
207
|
+
ctx.spinner.start("Fetching models from models.dev");
|
|
208
|
+
const response = await fetch(API_URL, { signal: AbortSignal.timeout(30_000) });
|
|
209
|
+
if (!response.ok) {
|
|
210
|
+
throw new Error(`Failed to fetch ${API_URL}: ${response.status} ${response.statusText}`);
|
|
211
|
+
}
|
|
212
|
+
const apiData: Record<string, ApiProvider> = await response.json();
|
|
213
|
+
ctx.spinner.stop(`${Object.keys(apiData).length} providers from API`);
|
|
214
|
+
|
|
215
|
+
// Fail fast if any configured provider is missing from the API
|
|
216
|
+
const missingProviders = providerKeys.filter((key) => !apiData[key]);
|
|
217
|
+
if (missingProviders.length > 0) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`models.dev API is missing configured providers: ${missingProviders.join(", ")}`,
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
mkdirSync(GENERATED_DIR, { recursive: true });
|
|
224
|
+
|
|
225
|
+
// Clean and recreate catalog providers dir
|
|
226
|
+
rmSync(CATALOG_DIR, { recursive: true, force: true });
|
|
227
|
+
mkdirSync(CATALOG_DIR, { recursive: true });
|
|
228
|
+
|
|
229
|
+
// Clean and recreate entry points dir
|
|
230
|
+
rmSync(ENTRY_DIR, { recursive: true, force: true });
|
|
231
|
+
mkdirSync(ENTRY_DIR, { recursive: true });
|
|
232
|
+
|
|
233
|
+
const providerFiles: { provider: string; constName: string; count: number }[] = [];
|
|
234
|
+
|
|
235
|
+
for (const providerKey of providerKeys) {
|
|
236
|
+
const apiProvider = apiData[providerKey]!;
|
|
237
|
+
const apiModels = apiProvider.models ?? {};
|
|
238
|
+
const constName = toConstName(providerKey);
|
|
239
|
+
const lines: string[] = [];
|
|
240
|
+
|
|
241
|
+
for (const [, m] of Object.entries(apiModels)) {
|
|
242
|
+
const id = escapeStr(m.id);
|
|
243
|
+
const name = escapeStr(m.name ?? m.id);
|
|
244
|
+
const family = escapeStr(m.family ?? "");
|
|
245
|
+
const pricing = buildPricing(m.cost);
|
|
246
|
+
const contextWindow = m.limit?.context ?? 0;
|
|
247
|
+
const maxOutput = m.limit?.output ?? 0;
|
|
248
|
+
const modalities = buildModalities(m.modalities);
|
|
249
|
+
const capabilities = buildCapabilities(m);
|
|
250
|
+
|
|
251
|
+
lines.push(
|
|
252
|
+
` { id: '${id}', name: '${name}', provider: '${providerKey}', family: '${family}', ` +
|
|
253
|
+
`pricing: ${pricing}, contextWindow: ${contextWindow}, maxOutput: ${maxOutput}, ` +
|
|
254
|
+
`modalities: ${modalities}, capabilities: { ${capabilities} } },`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Write catalog provider file
|
|
259
|
+
const catalogContent = `${BANNER}
|
|
260
|
+
|
|
261
|
+
import type { ModelDefinition } from '../types.js'
|
|
262
|
+
|
|
263
|
+
export const ${constName} = [
|
|
264
|
+
${lines.join("\n")}
|
|
265
|
+
] as const satisfies readonly ModelDefinition[]
|
|
266
|
+
`;
|
|
267
|
+
|
|
268
|
+
const catalogPath = join(CATALOG_DIR, `${providerKey}.ts`);
|
|
269
|
+
writeFileSync(catalogPath, catalogContent, "utf-8");
|
|
270
|
+
|
|
271
|
+
// Write per-provider entry point
|
|
272
|
+
const prefix = providers[providerKey]!.prefix;
|
|
273
|
+
const camel = lowerFirst(prefix);
|
|
274
|
+
const exampleId = escapeStr(Object.values(apiModels)[0]?.id ?? "example-id");
|
|
275
|
+
const providerName = escapeStr(providers[providerKey]!.name);
|
|
276
|
+
const art = article(providers[providerKey]!.name);
|
|
277
|
+
const entryContent = `${BANNER}
|
|
278
|
+
|
|
279
|
+
import type { LiteralUnion } from 'type-fest'
|
|
280
|
+
import type { ModelDefinition } from '../catalog/types.js'
|
|
281
|
+
import { ${constName} } from '../catalog/providers/${providerKey}.js'
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Known model identifiers for ${providerName}.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* \`\`\`typescript
|
|
288
|
+
* import type { ${prefix}ModelId } from '@funkai/models/${providerKey}'
|
|
289
|
+
*
|
|
290
|
+
* const id: ${prefix}ModelId = '${exampleId}'
|
|
291
|
+
* \`\`\`
|
|
292
|
+
*/
|
|
293
|
+
export type ${prefix}ModelId = (typeof ${constName})[number]['id']
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* All ${providerName} models in the catalog.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* \`\`\`typescript
|
|
300
|
+
* import { ${camel}Models } from '@funkai/models/${providerKey}'
|
|
301
|
+
*
|
|
302
|
+
* for (const m of ${camel}Models) {
|
|
303
|
+
* console.log(m.id, m.pricing.input)
|
|
304
|
+
* }
|
|
305
|
+
* \`\`\`
|
|
306
|
+
*/
|
|
307
|
+
export const ${camel}Models = ${constName}
|
|
308
|
+
|
|
309
|
+
const MODEL_INDEX = new Map<string, ModelDefinition>(${constName}.map((m) => [m.id, m]))
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Look up ${art} ${providerName} model by ID.
|
|
313
|
+
*
|
|
314
|
+
* @param id - The provider-native model identifier.
|
|
315
|
+
* @returns The matching model definition, or \`null\`.
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* \`\`\`typescript
|
|
319
|
+
* import { ${camel}Model } from '@funkai/models/${providerKey}'
|
|
320
|
+
*
|
|
321
|
+
* const m = ${camel}Model('${exampleId}')
|
|
322
|
+
* if (m) {
|
|
323
|
+
* console.log(m.pricing.input)
|
|
324
|
+
* }
|
|
325
|
+
* \`\`\`
|
|
326
|
+
*/
|
|
327
|
+
export function ${camel}Model(id: LiteralUnion<${prefix}ModelId, string>): ModelDefinition | null {
|
|
328
|
+
return MODEL_INDEX.get(id) ?? null
|
|
329
|
+
}
|
|
330
|
+
`;
|
|
331
|
+
|
|
332
|
+
const entryPath = join(ENTRY_DIR, `${providerKey}.ts`);
|
|
333
|
+
writeFileSync(entryPath, entryContent, "utf-8");
|
|
334
|
+
|
|
335
|
+
ctx.logger.success(`${providerKey} (${lines.length} models)`);
|
|
336
|
+
providerFiles.push({ provider: providerKey, constName, count: lines.length });
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Catalog barrel
|
|
340
|
+
const imports = providerFiles
|
|
341
|
+
.map((p) => `import { ${p.constName} } from './${p.provider}.js'`)
|
|
342
|
+
.join("\n");
|
|
343
|
+
|
|
344
|
+
const spreads = providerFiles.map((p) => ` ...${p.constName},`).join("\n");
|
|
345
|
+
|
|
346
|
+
const catalogBarrel = `${BANNER}
|
|
347
|
+
|
|
348
|
+
import type { ModelDefinition } from '../types.js'
|
|
349
|
+
${imports}
|
|
350
|
+
|
|
351
|
+
export const MODELS = [
|
|
352
|
+
${spreads}
|
|
353
|
+
] as const satisfies readonly ModelDefinition[]
|
|
354
|
+
`;
|
|
355
|
+
|
|
356
|
+
writeFileSync(join(CATALOG_DIR, "index.ts"), catalogBarrel, "utf-8");
|
|
357
|
+
ctx.logger.success("catalog/providers/index.ts (barrel)");
|
|
358
|
+
|
|
359
|
+
// Write generated entries list for tsdown config
|
|
360
|
+
const entryPoints = providerFiles.map((p) => `src/providers/${p.provider}.ts`);
|
|
361
|
+
writeFileSync(ENTRIES_PATH, JSON.stringify(entryPoints, null, 2), "utf-8");
|
|
362
|
+
ctx.logger.success(".generated/entries.json");
|
|
363
|
+
|
|
364
|
+
// Update package.json exports map
|
|
365
|
+
const pkgRaw = readFileSync(PACKAGE_JSON_PATH, "utf-8");
|
|
366
|
+
const pkg = JSON.parse(pkgRaw);
|
|
367
|
+
|
|
368
|
+
const exportsMap: Record<string, { types: string; import: string }> = {
|
|
369
|
+
".": {
|
|
370
|
+
types: "./dist/index.d.mts",
|
|
371
|
+
import: "./dist/index.mjs",
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
for (const p of providerFiles) {
|
|
376
|
+
exportsMap[`./${p.provider}`] = {
|
|
377
|
+
types: `./dist/providers/${p.provider}.d.mts`,
|
|
378
|
+
import: `./dist/providers/${p.provider}.mjs`,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
pkg.exports = exportsMap;
|
|
383
|
+
writeFileSync(PACKAGE_JSON_PATH, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
384
|
+
ctx.logger.success("package.json exports map updated");
|
|
385
|
+
|
|
386
|
+
// Staleness timestamp
|
|
387
|
+
writeFileSync(REQ_PATH, new Date().toISOString(), "utf-8");
|
|
388
|
+
|
|
389
|
+
const totalModels = providerFiles.reduce((sum, p) => sum + p.count, 0);
|
|
390
|
+
ctx.logger.info(`done (${providerFiles.length} providers, ${totalModels} models)`);
|
|
391
|
+
},
|
|
392
|
+
});
|