language-models 0.0.1
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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test.log +18 -0
- package/README.md +79 -0
- package/data/models.json +18805 -0
- package/dist/aliases.d.ts +5 -0
- package/dist/aliases.d.ts.map +1 -0
- package/dist/aliases.js +41 -0
- package/dist/aliases.js.map +1 -0
- package/dist/data/models.json +18805 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +97 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +109 -0
- package/dist/models.js.map +1 -0
- package/package.json +34 -0
- package/scripts/fetch-models.ts +115 -0
- package/src/aliases.test.ts +319 -0
- package/src/aliases.ts +49 -0
- package/src/index.test.ts +400 -0
- package/src/index.ts +21 -0
- package/src/models.test.ts +392 -0
- package/src/models.ts +174 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +11 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* language-models - Model listing and resolution
|
|
3
|
+
*
|
|
4
|
+
* Lists all available models and resolves aliases to full model IDs.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { resolve, resolveWithProvider, list, get, search, DIRECT_PROVIDERS, type ModelInfo, type ProviderEndpoint, type ResolvedModel, type DirectProvider } from './models.js';
|
|
9
|
+
export { ALIASES } from './aliases.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,IAAI,EACJ,GAAG,EACH,MAAM,EACN,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* language-models - Model listing and resolution
|
|
3
|
+
*
|
|
4
|
+
* Lists all available models and resolves aliases to full model IDs.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { resolve, resolveWithProvider, list, get, search, DIRECT_PROVIDERS } from './models.js';
|
|
9
|
+
export { ALIASES } from './aliases.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,IAAI,EACJ,GAAG,EACH,MAAM,EACN,gBAAgB,EAKjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/models.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model listing and resolution
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Provider endpoint information for direct API access
|
|
6
|
+
*/
|
|
7
|
+
export interface ProviderEndpoint {
|
|
8
|
+
/** Provider's API base URL (e.g., https://api.anthropic.com/v1) */
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
/** Provider's model ID (e.g., claude-opus-4-5-20251101) */
|
|
11
|
+
modelId: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ModelInfo {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
context_length: number;
|
|
18
|
+
pricing: {
|
|
19
|
+
prompt: string;
|
|
20
|
+
completion: string;
|
|
21
|
+
};
|
|
22
|
+
architecture?: {
|
|
23
|
+
modality: string;
|
|
24
|
+
input_modalities: string[];
|
|
25
|
+
output_modalities: string[];
|
|
26
|
+
};
|
|
27
|
+
/** Provider slug (e.g., 'anthropic', 'openai', 'google') */
|
|
28
|
+
provider?: string;
|
|
29
|
+
/** Provider's native model ID for direct API calls */
|
|
30
|
+
provider_model_id?: string;
|
|
31
|
+
/** Provider endpoint info for direct routing */
|
|
32
|
+
endpoint?: ProviderEndpoint;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* List all available models
|
|
36
|
+
*/
|
|
37
|
+
export declare function list(): ModelInfo[];
|
|
38
|
+
/**
|
|
39
|
+
* Get a model by exact ID
|
|
40
|
+
*/
|
|
41
|
+
export declare function get(id: string): ModelInfo | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Search models by query string
|
|
44
|
+
* Searches in id and name fields
|
|
45
|
+
*/
|
|
46
|
+
export declare function search(query: string): ModelInfo[];
|
|
47
|
+
/**
|
|
48
|
+
* Resolve a model alias or partial name to a full model ID
|
|
49
|
+
*
|
|
50
|
+
* Resolution order:
|
|
51
|
+
* 1. Check aliases (e.g., 'opus' -> 'anthropic/claude-opus-4.5')
|
|
52
|
+
* 2. Check if it's already a full ID (contains '/')
|
|
53
|
+
* 3. Search for first matching model
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* resolve('opus') // 'anthropic/claude-opus-4.5'
|
|
57
|
+
* resolve('gpt-4o') // 'openai/gpt-4o'
|
|
58
|
+
* resolve('claude-sonnet') // 'anthropic/claude-sonnet-4.5'
|
|
59
|
+
* resolve('llama-70b') // 'meta-llama/llama-3.3-70b-instruct'
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolve(input: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Providers that support direct SDK access (not via OpenRouter)
|
|
64
|
+
* These providers have special capabilities like MCP, extended thinking, etc.
|
|
65
|
+
*/
|
|
66
|
+
export declare const DIRECT_PROVIDERS: readonly ["openai", "anthropic", "google"];
|
|
67
|
+
export type DirectProvider = typeof DIRECT_PROVIDERS[number];
|
|
68
|
+
/**
|
|
69
|
+
* Result of resolving a model with provider routing info
|
|
70
|
+
*/
|
|
71
|
+
export interface ResolvedModel {
|
|
72
|
+
/** OpenRouter-style model ID (e.g., 'anthropic/claude-opus-4.5') */
|
|
73
|
+
id: string;
|
|
74
|
+
/** Provider slug (e.g., 'anthropic', 'openai', 'google') */
|
|
75
|
+
provider: string;
|
|
76
|
+
/** Provider's native model ID (e.g., 'claude-opus-4-5-20251101') */
|
|
77
|
+
providerModelId?: string;
|
|
78
|
+
/** Whether this provider supports direct SDK routing */
|
|
79
|
+
supportsDirectRouting: boolean;
|
|
80
|
+
/** Full model info if available */
|
|
81
|
+
model?: ModelInfo;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Resolve a model alias and get full routing information
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const info = resolveWithProvider('opus')
|
|
88
|
+
* // {
|
|
89
|
+
* // id: 'anthropic/claude-opus-4.5',
|
|
90
|
+
* // provider: 'anthropic',
|
|
91
|
+
* // providerModelId: 'claude-opus-4-5-20251101',
|
|
92
|
+
* // supportsDirectRouting: true,
|
|
93
|
+
* // model: { ... }
|
|
94
|
+
* // }
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolveWithProvider(input: string): ResolvedModel;
|
|
97
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAA;IACf,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAA;QACd,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAA;QAChB,gBAAgB,EAAE,MAAM,EAAE,CAAA;QAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;KAC5B,CAAA;IACD,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAC5B;AAeD;;GAEG;AACH,wBAAgB,IAAI,IAAI,SAAS,EAAE,CAElC;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAErD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,CAMjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwB7C;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,4CAA6C,CAAA;AAC1E,MAAM,MAAM,cAAc,GAAG,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;AAE5D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAA;IACV,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,qBAAqB,EAAE,OAAO,CAAA;IAC9B,mCAAmC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAiBhE"}
|
package/dist/models.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model listing and resolution
|
|
3
|
+
*/
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { ALIASES } from './aliases.js';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
// Load models from JSON
|
|
8
|
+
let modelsCache = null;
|
|
9
|
+
function loadModels() {
|
|
10
|
+
if (modelsCache)
|
|
11
|
+
return modelsCache;
|
|
12
|
+
try {
|
|
13
|
+
modelsCache = require('../data/models.json');
|
|
14
|
+
return modelsCache;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* List all available models
|
|
22
|
+
*/
|
|
23
|
+
export function list() {
|
|
24
|
+
return loadModels();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get a model by exact ID
|
|
28
|
+
*/
|
|
29
|
+
export function get(id) {
|
|
30
|
+
return loadModels().find(m => m.id === id);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Search models by query string
|
|
34
|
+
* Searches in id and name fields
|
|
35
|
+
*/
|
|
36
|
+
export function search(query) {
|
|
37
|
+
const q = query.toLowerCase();
|
|
38
|
+
return loadModels().filter(m => m.id.toLowerCase().includes(q) ||
|
|
39
|
+
m.name.toLowerCase().includes(q));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a model alias or partial name to a full model ID
|
|
43
|
+
*
|
|
44
|
+
* Resolution order:
|
|
45
|
+
* 1. Check aliases (e.g., 'opus' -> 'anthropic/claude-opus-4.5')
|
|
46
|
+
* 2. Check if it's already a full ID (contains '/')
|
|
47
|
+
* 3. Search for first matching model
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* resolve('opus') // 'anthropic/claude-opus-4.5'
|
|
51
|
+
* resolve('gpt-4o') // 'openai/gpt-4o'
|
|
52
|
+
* resolve('claude-sonnet') // 'anthropic/claude-sonnet-4.5'
|
|
53
|
+
* resolve('llama-70b') // 'meta-llama/llama-3.3-70b-instruct'
|
|
54
|
+
*/
|
|
55
|
+
export function resolve(input) {
|
|
56
|
+
const normalized = input.toLowerCase().trim();
|
|
57
|
+
// Check aliases first
|
|
58
|
+
if (ALIASES[normalized]) {
|
|
59
|
+
return ALIASES[normalized];
|
|
60
|
+
}
|
|
61
|
+
// Already a full ID with provider prefix
|
|
62
|
+
if (input.includes('/')) {
|
|
63
|
+
// Verify it exists or return as-is
|
|
64
|
+
const model = get(input);
|
|
65
|
+
return model?.id || input;
|
|
66
|
+
}
|
|
67
|
+
// Search for matching model
|
|
68
|
+
const matches = search(normalized);
|
|
69
|
+
const firstMatch = matches[0];
|
|
70
|
+
if (firstMatch) {
|
|
71
|
+
return firstMatch.id;
|
|
72
|
+
}
|
|
73
|
+
// Return as-is if nothing found
|
|
74
|
+
return input;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Providers that support direct SDK access (not via OpenRouter)
|
|
78
|
+
* These providers have special capabilities like MCP, extended thinking, etc.
|
|
79
|
+
*/
|
|
80
|
+
export const DIRECT_PROVIDERS = ['openai', 'anthropic', 'google'];
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a model alias and get full routing information
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* const info = resolveWithProvider('opus')
|
|
86
|
+
* // {
|
|
87
|
+
* // id: 'anthropic/claude-opus-4.5',
|
|
88
|
+
* // provider: 'anthropic',
|
|
89
|
+
* // providerModelId: 'claude-opus-4-5-20251101',
|
|
90
|
+
* // supportsDirectRouting: true,
|
|
91
|
+
* // model: { ... }
|
|
92
|
+
* // }
|
|
93
|
+
*/
|
|
94
|
+
export function resolveWithProvider(input) {
|
|
95
|
+
const id = resolve(input);
|
|
96
|
+
const model = get(id);
|
|
97
|
+
// Extract provider from ID (e.g., 'anthropic' from 'anthropic/claude-opus-4.5')
|
|
98
|
+
const slashIndex = id.indexOf('/');
|
|
99
|
+
const provider = slashIndex > 0 ? id.substring(0, slashIndex) : 'unknown';
|
|
100
|
+
const supportsDirectRouting = DIRECT_PROVIDERS.includes(provider);
|
|
101
|
+
return {
|
|
102
|
+
id,
|
|
103
|
+
provider,
|
|
104
|
+
providerModelId: model?.provider_model_id,
|
|
105
|
+
supportsDirectRouting,
|
|
106
|
+
model
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAkC9C,wBAAwB;AACxB,IAAI,WAAW,GAAuB,IAAI,CAAA;AAE1C,SAAS,UAAU;IACjB,IAAI,WAAW;QAAE,OAAO,WAAW,CAAA;IACnC,IAAI,CAAC;QACH,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;QAC5C,OAAO,WAAY,CAAA;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,IAAI;IAClB,OAAO,UAAU,EAAE,CAAA;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAC,EAAU;IAC5B,OAAO,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;IAC7B,OAAO,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7B,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CACjC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAE7C,sBAAsB;IACtB,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,UAAU,CAAC,CAAA;IAC5B,CAAC;IAED,yCAAyC;IACzC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,mCAAmC;QACnC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;QACxB,OAAO,KAAK,EAAE,EAAE,IAAI,KAAK,CAAA;IAC3B,CAAC;IAED,4BAA4B;IAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7B,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,EAAE,CAAA;IACtB,CAAC;IAED,gCAAgC;IAChC,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAA;AAmB1E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IACzB,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC,CAAA;IAErB,gFAAgF;IAChF,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEzE,MAAM,qBAAqB,GAAI,gBAAsC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAExF,OAAO;QACL,EAAE;QACF,QAAQ;QACR,eAAe,EAAE,KAAK,EAAE,iBAAiB;QACzC,qBAAqB;QACrB,KAAK;KACN,CAAA;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "language-models",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Model listing and resolution for LLM providers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p tsconfig.json && cp -r data dist/",
|
|
16
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
17
|
+
"test": "vitest",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"lint": "eslint .",
|
|
20
|
+
"clean": "rm -rf dist",
|
|
21
|
+
"fetch-models": "npx tsx scripts/fetch-models.ts"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"ai",
|
|
25
|
+
"llm",
|
|
26
|
+
"language-models",
|
|
27
|
+
"openrouter",
|
|
28
|
+
"primitives"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"rpc.do": "^0.1.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Fetch models from OpenRouter API and save to data/models.json
|
|
4
|
+
*
|
|
5
|
+
* Fetches from both:
|
|
6
|
+
* - /api/v1/models - Basic model info
|
|
7
|
+
* - /api/frontend/models - Provider routing info (provider_model_id, endpoint)
|
|
8
|
+
*
|
|
9
|
+
* Usage: npx tsx scripts/fetch-models.ts
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { writeFileSync } from 'fs'
|
|
13
|
+
import { dirname, join } from 'path'
|
|
14
|
+
import { fileURLToPath } from 'url'
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
17
|
+
const OUTPUT_PATH = join(__dirname, '..', 'data', 'models.json')
|
|
18
|
+
|
|
19
|
+
interface FrontendModel {
|
|
20
|
+
slug: string
|
|
21
|
+
endpoint?: {
|
|
22
|
+
provider_model_id?: string
|
|
23
|
+
provider_slug?: string
|
|
24
|
+
provider_info?: {
|
|
25
|
+
baseUrl?: string
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function fetchModels() {
|
|
31
|
+
console.log('Fetching models from OpenRouter API...')
|
|
32
|
+
|
|
33
|
+
// Fetch basic model info
|
|
34
|
+
const modelsResponse = await fetch('https://openrouter.ai/api/v1/models')
|
|
35
|
+
if (!modelsResponse.ok) {
|
|
36
|
+
throw new Error(`Failed to fetch models: ${modelsResponse.status} ${modelsResponse.statusText}`)
|
|
37
|
+
}
|
|
38
|
+
const modelsData = await modelsResponse.json()
|
|
39
|
+
const models = modelsData.data || modelsData
|
|
40
|
+
|
|
41
|
+
console.log(`Found ${models.length} models from v1 API`)
|
|
42
|
+
|
|
43
|
+
// Fetch frontend models for provider routing info
|
|
44
|
+
console.log('Fetching provider routing info from frontend API...')
|
|
45
|
+
let frontendModels: FrontendModel[] = []
|
|
46
|
+
try {
|
|
47
|
+
const frontendResponse = await fetch('https://openrouter.ai/api/frontend/models')
|
|
48
|
+
if (frontendResponse.ok) {
|
|
49
|
+
const frontendData = await frontendResponse.json()
|
|
50
|
+
frontendModels = Array.isArray(frontendData) ? frontendData : (frontendData.data || [])
|
|
51
|
+
console.log(`Found ${frontendModels.length} models from frontend API`)
|
|
52
|
+
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.warn('Could not fetch frontend models, continuing without provider routing info')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Create a map of frontend models by slug for quick lookup
|
|
58
|
+
const frontendMap = new Map<string, FrontendModel>()
|
|
59
|
+
for (const fm of frontendModels) {
|
|
60
|
+
if (fm.slug) {
|
|
61
|
+
frontendMap.set(fm.slug, fm)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Merge frontend data into models
|
|
66
|
+
let enrichedCount = 0
|
|
67
|
+
for (const model of models) {
|
|
68
|
+
const frontend = frontendMap.get(model.id)
|
|
69
|
+
if (frontend?.endpoint) {
|
|
70
|
+
// Add provider routing info from nested endpoint
|
|
71
|
+
if (frontend.endpoint.provider_model_id) {
|
|
72
|
+
model.provider_model_id = frontend.endpoint.provider_model_id
|
|
73
|
+
}
|
|
74
|
+
if (frontend.endpoint.provider_slug) {
|
|
75
|
+
model.provider = frontend.endpoint.provider_slug
|
|
76
|
+
}
|
|
77
|
+
if (frontend.endpoint.provider_info?.baseUrl) {
|
|
78
|
+
model.endpoint = {
|
|
79
|
+
baseUrl: frontend.endpoint.provider_info.baseUrl,
|
|
80
|
+
modelId: frontend.endpoint.provider_model_id || model.id.split('/')[1]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
enrichedCount++
|
|
84
|
+
} else {
|
|
85
|
+
// Extract provider from ID as fallback
|
|
86
|
+
const slashIndex = model.id.indexOf('/')
|
|
87
|
+
if (slashIndex > 0) {
|
|
88
|
+
model.provider = model.id.substring(0, slashIndex)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log(`Enriched ${enrichedCount} models with provider routing info`)
|
|
94
|
+
|
|
95
|
+
// Sort by created date (newest first)
|
|
96
|
+
models.sort((a: any, b: any) => (b.created || 0) - (a.created || 0))
|
|
97
|
+
|
|
98
|
+
writeFileSync(OUTPUT_PATH, JSON.stringify(models, null, 2))
|
|
99
|
+
console.log(`Saved to ${OUTPUT_PATH}`)
|
|
100
|
+
|
|
101
|
+
// Print some stats
|
|
102
|
+
const providers = new Set(models.map((m: any) => m.id.split('/')[0]))
|
|
103
|
+
console.log(`\nProviders: ${[...providers].join(', ')}`)
|
|
104
|
+
|
|
105
|
+
// Show which direct providers have routing info
|
|
106
|
+
const directProviders = ['openai', 'anthropic', 'google']
|
|
107
|
+
for (const provider of directProviders) {
|
|
108
|
+
const withRouting = models.filter((m: any) =>
|
|
109
|
+
m.id.startsWith(`${provider}/`) && m.provider_model_id
|
|
110
|
+
)
|
|
111
|
+
console.log(`${provider}: ${withRouting.length} models with provider_model_id`)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
fetchModels().catch(console.error)
|