language-models 0.1.0 → 0.2.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/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-test.log +18 -0
- package/README.md +56 -142
- package/data/models.json +18805 -0
- package/dist/aliases.d.ts +5 -1
- package/dist/aliases.d.ts.map +1 -0
- package/dist/aliases.js +40 -4
- package/dist/aliases.js.map +1 -0
- package/dist/data/models.json +18805 -0
- package/dist/index.d.ts +10 -7
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +94 -167
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +109 -69803
- package/dist/models.js.map +1 -0
- package/package.json +25 -23
- package/scripts/fetch-models.ts +115 -0
- package/src/aliases.test.ts +319 -0
- package/src/aliases.ts +48 -4
- package/src/index.test.ts +400 -0
- package/src/index.ts +20 -9
- package/src/models.test.ts +392 -0
- package/src/models.ts +174 -0
- package/tsconfig.json +5 -15
- package/vitest.config.ts +4 -14
- package/.editorconfig +0 -10
- package/.gitattributes +0 -4
- package/.releaserc.js +0 -129
- package/LICENSE +0 -21
- package/dist/parser.d.ts +0 -86
- package/dist/parser.js +0 -390
- package/dist/providers.d.ts +0 -1
- package/dist/providers.js +0 -76
- package/dist/types.d.ts +0 -127
- package/dist/types.js +0 -1
- package/eslint.config.js +0 -3
- package/generate/build-models.ts +0 -150
- package/generate/overwrites.ts +0 -12
- package/publish.js +0 -32
- package/roadmap.md +0 -54
- package/src/models.d.ts +0 -170
- package/src/models.js +0 -70434
- package/src/parser.ts +0 -485
- package/src/providers.ts +0 -79
- package/src/types.ts +0 -135
- package/tests/parser.test.ts +0 -11
- package/tests/regex.test.ts +0 -42
- package/tests/selector.test.ts +0 -53
- package/tests/setup.ts +0 -0
package/.releaserc.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export default {
|
|
3
|
-
branches: [
|
|
4
|
-
{name: 'next', prerelease: 'next', channel: 'next'}
|
|
5
|
-
],
|
|
6
|
-
repositoryUrl: 'https://github.com/drivly/ai.git',
|
|
7
|
-
tagFormat: '${name}@${version}',
|
|
8
|
-
initialVersion: '0.1.0',
|
|
9
|
-
npmPublish: true,
|
|
10
|
-
pkgRoot: '.',
|
|
11
|
-
plugins: [
|
|
12
|
-
{
|
|
13
|
-
verifyConditions: (pluginConfig, context) => {
|
|
14
|
-
console.log('Verifying conditions for semantic-release...');
|
|
15
|
-
|
|
16
|
-
if (context.nextRelease && context.nextRelease.version) {
|
|
17
|
-
if (!context.nextRelease.version.startsWith('0.')) {
|
|
18
|
-
console.log(`Forcing version to start with 0: ${context.nextRelease.version} -> 0.${context.nextRelease.version}`);
|
|
19
|
-
context.nextRelease.version = '0.' + context.nextRelease.version;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
24
|
-
if (fs.existsSync(pkgPath)) {
|
|
25
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
26
|
-
if (!pkg.version.startsWith('0.')) {
|
|
27
|
-
console.log(`Fixing package.json version: ${pkg.version} -> 0.1.0`);
|
|
28
|
-
pkg.version = '0.1.0';
|
|
29
|
-
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
analyzeCommits: (pluginConfig, context) => {
|
|
34
|
-
if (!context.lastRelease.version) {
|
|
35
|
-
console.log('No previous version found, starting at 0.1.0-next.1');
|
|
36
|
-
return '0.1.0-next.1'; // Start new packages at 0.1.0-next.1
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
console.log('Forcing patch release regardless of commit types');
|
|
40
|
-
return 'patch';
|
|
41
|
-
},
|
|
42
|
-
prepare: (pluginConfig, context) => {
|
|
43
|
-
console.log('Preparing for release...');
|
|
44
|
-
|
|
45
|
-
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
46
|
-
if (fs.existsSync(pkgPath)) {
|
|
47
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
48
|
-
let modified = false;
|
|
49
|
-
|
|
50
|
-
const packageVersions = {};
|
|
51
|
-
for (const pkgDir of ["/home/runner/work/ai/ai/sdks/actions.do","/home/runner/work/ai/ai/sdks/agents.do","/home/runner/work/ai/ai/sdks/analytics.do","/home/runner/work/ai/ai/sdks/apis.do","/home/runner/work/ai/ai/sdks/database.do","/home/runner/work/ai/ai/sdks/evals.do","/home/runner/work/ai/ai/sdks/experiments.do","/home/runner/work/ai/ai/sdks/functions.do","/home/runner/work/ai/ai/sdks/goals.do","/home/runner/work/ai/ai/sdks/gpt.do","/home/runner/work/ai/ai/sdks/integrations.do","/home/runner/work/ai/ai/sdks/llm.do","/home/runner/work/ai/ai/sdks/mcp.do","/home/runner/work/ai/ai/sdks/models.do","/home/runner/work/ai/ai/sdks/plans.do","/home/runner/work/ai/ai/sdks/projects.do","/home/runner/work/ai/ai/sdks/sdk.do","/home/runner/work/ai/ai/sdks/searches.do","/home/runner/work/ai/ai/sdks/tasks.do","/home/runner/work/ai/ai/sdks/triggers.do","/home/runner/work/ai/ai/sdks/workflows.do","/home/runner/work/ai/ai/pkgs/ai-business","/home/runner/work/ai/ai/pkgs/ai-database","/home/runner/work/ai/ai/pkgs/ai-functions","/home/runner/work/ai/ai/pkgs/ai-models","/home/runner/work/ai/ai/pkgs/ai-providers","/home/runner/work/ai/ai/pkgs/ai-workflows","/home/runner/work/ai/ai/pkgs/apis-do-searches","/home/runner/work/ai/ai/pkgs/apis-do-zapier","/home/runner/work/ai/ai/pkgs/business-as-code","/home/runner/work/ai/ai/pkgs/clickable-apis","/home/runner/work/ai/ai/pkgs/deploy-worker","/home/runner/work/ai/ai/pkgs/durable-objects-cron","/home/runner/work/ai/ai/pkgs/durable-objects-nosql","/home/runner/work/ai/ai/pkgs/eslint-config","/home/runner/work/ai/ai/pkgs/exec-symbols","/home/runner/work/ai/ai/pkgs/language-models","/home/runner/work/ai/ai/pkgs/mdxdb","/home/runner/work/ai/ai/pkgs/mdxld","/home/runner/work/ai/ai/pkgs/motion.md","/home/runner/work/ai/ai/pkgs/payload-agent","/home/runner/work/ai/ai/pkgs/payload-commandbar","/home/runner/work/ai/ai/pkgs/payload-hooks-queue","/home/runner/work/ai/ai/pkgs/payload-theme","/home/runner/work/ai/ai/pkgs/payload-utils","/home/runner/work/ai/ai/pkgs/payload-vscode","/home/runner/work/ai/ai/pkgs/payload-workos","/home/runner/work/ai/ai/pkgs/payload-zapier-apps","/home/runner/work/ai/ai/pkgs/services-as-software","/home/runner/work/ai/ai/pkgs/simple-payload","/home/runner/work/ai/ai/pkgs/tsconfig","/home/runner/work/ai/ai/pkgs/zapier-apis-do"]) {
|
|
52
|
-
const pkgJsonPath = path.join(pkgDir, 'package.json');
|
|
53
|
-
if (fs.existsSync(pkgJsonPath)) {
|
|
54
|
-
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
55
|
-
packageVersions[pkgJson.name] = pkgJson.version || '0.1.0';
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (pkg.dependencies) {
|
|
60
|
-
for (const [dep, version] of Object.entries(pkg.dependencies)) {
|
|
61
|
-
if (version.startsWith('workspace:')) {
|
|
62
|
-
if (packageVersions[dep]) {
|
|
63
|
-
console.log(`Converting workspace dependency ${dep} from ${version} to ${packageVersions[dep]}`);
|
|
64
|
-
pkg.dependencies[dep] = packageVersions[dep];
|
|
65
|
-
modified = true;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (pkg.devDependencies) {
|
|
72
|
-
for (const [dep, version] of Object.entries(pkg.devDependencies)) {
|
|
73
|
-
if (version.startsWith('workspace:')) {
|
|
74
|
-
if (packageVersions[dep]) {
|
|
75
|
-
console.log(`Converting workspace devDependency ${dep} from ${version} to ${packageVersions[dep]}`);
|
|
76
|
-
pkg.devDependencies[dep] = packageVersions[dep];
|
|
77
|
-
modified = true;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (pkg.peerDependencies) {
|
|
84
|
-
for (const [dep, version] of Object.entries(pkg.peerDependencies)) {
|
|
85
|
-
if (version.startsWith('workspace:')) {
|
|
86
|
-
if (packageVersions[dep]) {
|
|
87
|
-
console.log(`Converting workspace peerDependency ${dep} from ${version} to ${packageVersions[dep]}`);
|
|
88
|
-
pkg.peerDependencies[dep] = packageVersions[dep];
|
|
89
|
-
modified = true;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (modified) {
|
|
96
|
-
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
97
|
-
console.log('Updated package.json with converted workspace dependencies before publishing');
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
['@semantic-release/commit-analyzer', {
|
|
103
|
-
preset: 'angular',
|
|
104
|
-
releaseRules: [
|
|
105
|
-
{type: 'feat', release: 'patch'},
|
|
106
|
-
{type: 'fix', release: 'patch'},
|
|
107
|
-
{type: 'docs', release: 'patch'},
|
|
108
|
-
{type: 'style', release: 'patch'},
|
|
109
|
-
{type: 'refactor', release: 'patch'},
|
|
110
|
-
{type: 'perf', release: 'patch'},
|
|
111
|
-
{type: 'test', release: 'patch'},
|
|
112
|
-
{type: 'build', release: 'patch'},
|
|
113
|
-
{type: 'ci', release: 'patch'},
|
|
114
|
-
{type: 'chore', release: 'patch'}
|
|
115
|
-
]
|
|
116
|
-
}],
|
|
117
|
-
['@semantic-release/release-notes-generator', {
|
|
118
|
-
writerOpts: {
|
|
119
|
-
commitLimit: 100,
|
|
120
|
-
}
|
|
121
|
-
}],
|
|
122
|
-
['@semantic-release/npm', {
|
|
123
|
-
npmPublish: true,
|
|
124
|
-
pkgRoot: '.',
|
|
125
|
-
npmTag: 'next'
|
|
126
|
-
}],
|
|
127
|
-
'@semantic-release/github'
|
|
128
|
-
]
|
|
129
|
-
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Driv.ly
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/dist/parser.d.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { Model, Provider } from './types';
|
|
2
|
-
type InternalModel = Model;
|
|
3
|
-
type ParsedModelIdentifier = {
|
|
4
|
-
provider?: string;
|
|
5
|
-
author?: string;
|
|
6
|
-
model?: string;
|
|
7
|
-
systemConfig?: Record<string, string | number>;
|
|
8
|
-
alias?: string;
|
|
9
|
-
priorities?: string[];
|
|
10
|
-
providerConstraints?: {
|
|
11
|
-
field: string;
|
|
12
|
-
value: string;
|
|
13
|
-
type: 'gt' | 'lt' | 'eq';
|
|
14
|
-
}[];
|
|
15
|
-
tools?: Record<string, string | number | boolean | Record<string, unknown>>;
|
|
16
|
-
capabilities?: Record<string, string | number | boolean>;
|
|
17
|
-
outputFormat?: string;
|
|
18
|
-
outputSchema?: string;
|
|
19
|
-
unasignedParameters?: Record<string, string | number | boolean>;
|
|
20
|
-
};
|
|
21
|
-
export declare function parse(modelIdentifier: string): ParsedModelIdentifier;
|
|
22
|
-
export declare function constructModelIdentifier(parsed: ParsedModelIdentifier): string;
|
|
23
|
-
export declare function modelToIdentifier(model: Model): string;
|
|
24
|
-
type ResolvedModel = Model & {
|
|
25
|
-
provider: Provider;
|
|
26
|
-
};
|
|
27
|
-
export declare function filterModels(modelIdentifier: string, modelsToFilter?: InternalModel[]): {
|
|
28
|
-
models: ResolvedModel[];
|
|
29
|
-
parsed: ParsedModelIdentifier;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Helper function to get the first model that matches a model identifier
|
|
33
|
-
* @param modelIdentifier
|
|
34
|
-
* @returns ResolvedModel
|
|
35
|
-
*/
|
|
36
|
-
export declare function getModel(modelIdentifier: string, augments?: Record<string, string | number | boolean | string[]>): {
|
|
37
|
-
parsed: {
|
|
38
|
-
provider?: string;
|
|
39
|
-
author?: string;
|
|
40
|
-
model?: string;
|
|
41
|
-
systemConfig?: Record<string, string | number>;
|
|
42
|
-
alias?: string;
|
|
43
|
-
priorities?: string[];
|
|
44
|
-
providerConstraints?: {
|
|
45
|
-
field: string;
|
|
46
|
-
value: string;
|
|
47
|
-
type: "gt" | "lt" | "eq";
|
|
48
|
-
}[];
|
|
49
|
-
tools?: Record<string, string | number | boolean | Record<string, unknown>>;
|
|
50
|
-
capabilities?: Record<string, string | number | boolean>;
|
|
51
|
-
outputFormat?: string;
|
|
52
|
-
outputSchema?: string;
|
|
53
|
-
unasignedParameters?: Record<string, string | number | boolean>;
|
|
54
|
-
};
|
|
55
|
-
slug: string;
|
|
56
|
-
hfSlug?: string | null;
|
|
57
|
-
updatedAt: string;
|
|
58
|
-
createdAt: string;
|
|
59
|
-
hfUpdatedAt: null;
|
|
60
|
-
name: string;
|
|
61
|
-
shortName: string;
|
|
62
|
-
author: string;
|
|
63
|
-
description: string;
|
|
64
|
-
modelVersionGroupId: string;
|
|
65
|
-
contextLength: number;
|
|
66
|
-
inputModalities: string[];
|
|
67
|
-
outputModalities: string[];
|
|
68
|
-
hasTextOutput: boolean;
|
|
69
|
-
group: string;
|
|
70
|
-
instructType: null;
|
|
71
|
-
defaultSystem: null;
|
|
72
|
-
defaultStops: any[];
|
|
73
|
-
hidden: boolean;
|
|
74
|
-
router: null;
|
|
75
|
-
warningMessage: null;
|
|
76
|
-
permaslug: string;
|
|
77
|
-
reasoningConfig: null;
|
|
78
|
-
endpoint?: import("./types").Endpoint | Provider;
|
|
79
|
-
sorting?: import("./types").Sorting;
|
|
80
|
-
providers?: Provider[];
|
|
81
|
-
provider: Provider;
|
|
82
|
-
};
|
|
83
|
-
export declare function getModels(modelIdentifier: string): (Model & {
|
|
84
|
-
parsed: ParsedModelIdentifier;
|
|
85
|
-
})[];
|
|
86
|
-
export {};
|
package/dist/parser.js
DELETED
|
@@ -1,390 +0,0 @@
|
|
|
1
|
-
import camelCase from 'camelcase';
|
|
2
|
-
import { aliases } from './aliases';
|
|
3
|
-
import rawModels from './models';
|
|
4
|
-
const allModels = rawModels;
|
|
5
|
-
// Priorities may be on its own, which indicates to just find the best value for that priority
|
|
6
|
-
// or it may be in one of the following formats:
|
|
7
|
-
// cost:<1 -> A model that has a cost of less than $1 per million tokens
|
|
8
|
-
// latency:<50 -> A model with a latency of less than 50ms
|
|
9
|
-
// throughput:>250 -> A model with a throughput higher than 250 tokens per second
|
|
10
|
-
// Additional notes: if just cost is specified, then it will be treated as outputCost
|
|
11
|
-
const priorities = ['cost', 'latency', 'throughput', 'inputCost', 'outputCost'];
|
|
12
|
-
const capabilities = ['reasoning', 'thinking', 'tools', 'structuredOutput', 'responseFormat', 'pdf'];
|
|
13
|
-
const defaultTools = ['exec', 'online'];
|
|
14
|
-
const systemConfiguration = ['seed', 'thread', 'temperature', 'topP', 'topK'];
|
|
15
|
-
// Any of the following is an output format, anything else that starts with a capital letter is an output *schema*
|
|
16
|
-
const outputFormats = ['Object', 'ObjectArray', 'Text', 'TextArray', 'Markdown', 'Code'];
|
|
17
|
-
export function parse(modelIdentifier) {
|
|
18
|
-
const output = {
|
|
19
|
-
model: '',
|
|
20
|
-
};
|
|
21
|
-
// Locate all paratheses, even nested ones
|
|
22
|
-
const parentheses = modelIdentifier.match(/\(([^)]+)\)/g);
|
|
23
|
-
output.model = modelIdentifier.split('(')[0];
|
|
24
|
-
const modelName = output.model.includes('/') ? output.model.split('/')[1] : output.model;
|
|
25
|
-
if (aliases[modelName]) {
|
|
26
|
-
output.model = aliases[modelName];
|
|
27
|
-
}
|
|
28
|
-
if (output.model.includes('/')) {
|
|
29
|
-
const [author, model] = output.model.split('/');
|
|
30
|
-
output.author = author;
|
|
31
|
-
output.model = model;
|
|
32
|
-
}
|
|
33
|
-
if (output.model.includes('@')) {
|
|
34
|
-
// @ indicates a specific provider
|
|
35
|
-
const [model, provider] = output.model.split('@');
|
|
36
|
-
output.model = model;
|
|
37
|
-
output.provider = provider;
|
|
38
|
-
}
|
|
39
|
-
// If there are no parentheses, then we can just return the model identifier
|
|
40
|
-
if (!parentheses) {
|
|
41
|
-
return output;
|
|
42
|
-
}
|
|
43
|
-
// Defaults storage allows us to set defaults for settings if they are missing from the input
|
|
44
|
-
// The main use case is for output formats, where we want to set the format based on the schema
|
|
45
|
-
// but only if the format isnt already set. Since we only have access to a single expression at once,
|
|
46
|
-
// we need to store the defaults and apply them later.
|
|
47
|
-
const defaultStorage = {};
|
|
48
|
-
// Split by comma, each part is a new parameter that needs to be stored in the right
|
|
49
|
-
// place in the output object
|
|
50
|
-
// For each parathesis, we need to parse the contents
|
|
51
|
-
for (const parenthesis of parentheses) {
|
|
52
|
-
const contents = parenthesis.slice(1, -1);
|
|
53
|
-
const parts = contents.split(',');
|
|
54
|
-
for (const part of parts) {
|
|
55
|
-
// Not all parts will have a colon, if not, treat it as a boolean with a value of true.
|
|
56
|
-
const [key, value] = part
|
|
57
|
-
// Cheat we can do to make the parsing easier
|
|
58
|
-
.replace('<', ':<')
|
|
59
|
-
.replace('>', ':>')
|
|
60
|
-
.split(':');
|
|
61
|
-
if (!key) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
let notAKnownParameter = false;
|
|
65
|
-
switch (true) {
|
|
66
|
-
case defaultTools.includes(key):
|
|
67
|
-
output.tools = output.tools || {};
|
|
68
|
-
output.tools[key] = value || true;
|
|
69
|
-
break;
|
|
70
|
-
case systemConfiguration.includes(key):
|
|
71
|
-
output.systemConfig = {
|
|
72
|
-
...output.systemConfig,
|
|
73
|
-
[key]: value,
|
|
74
|
-
};
|
|
75
|
-
break;
|
|
76
|
-
case priorities.includes(key):
|
|
77
|
-
if (value) {
|
|
78
|
-
output.providerConstraints = output.providerConstraints || [];
|
|
79
|
-
output.providerConstraints.push({
|
|
80
|
-
field: key,
|
|
81
|
-
value: value.replace('>', '').replace('<', ''),
|
|
82
|
-
type: value.startsWith('>') ? 'gt' : value.startsWith('<') ? 'lt' : 'eq',
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
output.priorities = [...(output.priorities || []), key];
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
case capabilities.includes(key):
|
|
90
|
-
output.capabilities = {
|
|
91
|
-
...output.capabilities,
|
|
92
|
-
[key]: value || true,
|
|
93
|
-
};
|
|
94
|
-
break;
|
|
95
|
-
case outputFormats.includes(key):
|
|
96
|
-
output.outputFormat = key == 'Code' && !!value ? `Code:${value}` : key;
|
|
97
|
-
break;
|
|
98
|
-
default:
|
|
99
|
-
notAKnownParameter = true;
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
if (!notAKnownParameter) {
|
|
103
|
-
// No need to process any further
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
// If it starts with a capital letter, then it is a Schema
|
|
107
|
-
if (key[0] === key[0].toUpperCase()) {
|
|
108
|
-
const schema = key;
|
|
109
|
-
if (schema.includes('[]')) {
|
|
110
|
-
defaultStorage.outputFormat = 'ObjectArray';
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
defaultStorage.outputFormat = 'Object';
|
|
114
|
-
}
|
|
115
|
-
output.outputSchema = schema.replace('[]', '');
|
|
116
|
-
}
|
|
117
|
-
else if (value?.includes('>') || value?.includes('<')) {
|
|
118
|
-
// This is most likely a benchmark constraint
|
|
119
|
-
output.providerConstraints = output.providerConstraints || [];
|
|
120
|
-
output.providerConstraints.push({
|
|
121
|
-
field: key,
|
|
122
|
-
value: value.replace('>', '').replace('<', ''),
|
|
123
|
-
type: value.startsWith('>') ? 'gt' : 'lt',
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
output.tools = output.tools || {};
|
|
128
|
-
output.tools = {
|
|
129
|
-
...output.tools,
|
|
130
|
-
[key]: value || true,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Custom rules / requirements
|
|
136
|
-
// If someone has tools, they need to have the tools capability
|
|
137
|
-
if (Object.values(output.tools || {}).length > 0) {
|
|
138
|
-
if (!output.capabilities?.tools) {
|
|
139
|
-
output.capabilities = {
|
|
140
|
-
...output.capabilities,
|
|
141
|
-
tools: true,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// Finally, apply the defaults
|
|
146
|
-
Object.entries(defaultStorage).forEach(([key, value]) => {
|
|
147
|
-
const keyToCheck = key;
|
|
148
|
-
if (output[keyToCheck] === undefined) {
|
|
149
|
-
// @ts-expect-error - We know these assignments are safe based on our defaultStorage logic
|
|
150
|
-
output[keyToCheck] = value;
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
return output;
|
|
154
|
-
}
|
|
155
|
-
export function constructModelIdentifier(parsed) {
|
|
156
|
-
const modelAlias = aliases[parsed.model || ''] || parsed.model || '';
|
|
157
|
-
let identifier = `${modelAlias}`;
|
|
158
|
-
if (parsed.provider) {
|
|
159
|
-
identifier += `@${parsed.provider}`;
|
|
160
|
-
}
|
|
161
|
-
const args = [];
|
|
162
|
-
const formatArgument = (key, value) => {
|
|
163
|
-
// If the value is a boolean, then we can just return the key
|
|
164
|
-
if (typeof value === 'boolean') {
|
|
165
|
-
return value ? key : '';
|
|
166
|
-
}
|
|
167
|
-
console.log(key, value);
|
|
168
|
-
// Otherwise, we need to format the value
|
|
169
|
-
return `${key}:${value}`;
|
|
170
|
-
};
|
|
171
|
-
const keysToFormat = ['capabilities', 'tools', 'systemConfig'];
|
|
172
|
-
keysToFormat.forEach((key) => {
|
|
173
|
-
if (parsed[key]) {
|
|
174
|
-
Object.entries(parsed[key]).forEach(([key, value]) => {
|
|
175
|
-
args.push(formatArgument(key, value));
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
if (parsed.priorities) {
|
|
180
|
-
parsed.priorities.forEach((priority) => {
|
|
181
|
-
args.push(priority);
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
// Provider constraints are a bit more complex as they are stored as { field: string, value: string }[]
|
|
185
|
-
if (parsed.providerConstraints) {
|
|
186
|
-
parsed.providerConstraints.forEach((constraint) => {
|
|
187
|
-
args.push(`${constraint.field}${constraint.type === 'gt' ? '>' : constraint.type === 'lt' ? '<' : ':'}${constraint.value}`);
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
if (args.length) {
|
|
191
|
-
identifier += `(${args.join(',')})`;
|
|
192
|
-
}
|
|
193
|
-
return identifier;
|
|
194
|
-
}
|
|
195
|
-
export function modelToIdentifier(model) {
|
|
196
|
-
return constructModelIdentifier({
|
|
197
|
-
model: model.slug.split('/')[1],
|
|
198
|
-
provider: model.slug.split('/')[0],
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
export function filterModels(modelIdentifier, modelsToFilter) {
|
|
202
|
-
const parsed = parse(modelIdentifier);
|
|
203
|
-
const modelAndProviders = [];
|
|
204
|
-
let modelsToFilterMixin = modelsToFilter;
|
|
205
|
-
if (metaModels.find((m) => m.name === parsed.model) && !modelsToFilter?.length) {
|
|
206
|
-
const metaModelChildren = metaModels.find((m) => m.name === parsed.model)?.models;
|
|
207
|
-
modelsToFilterMixin = allModels.models.filter((m) => metaModelChildren?.includes(m.slug.split('/')[1]));
|
|
208
|
-
// Because the parser has no model knowledge, it thinks the meta model name is the model name
|
|
209
|
-
// Which will always return false.
|
|
210
|
-
delete parsed.model;
|
|
211
|
-
}
|
|
212
|
-
else if (modelsToFilter?.length) {
|
|
213
|
-
modelsToFilterMixin = modelsToFilter;
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
modelsToFilterMixin = allModels.models;
|
|
217
|
-
}
|
|
218
|
-
const filterChain = [];
|
|
219
|
-
if (parsed.model) {
|
|
220
|
-
filterChain.push(function modelFilter(model) {
|
|
221
|
-
// Wildcard search for any model that matches everything else.
|
|
222
|
-
if (parsed.model == '*') {
|
|
223
|
-
return true;
|
|
224
|
-
}
|
|
225
|
-
// Return true if we're looking for claude-3.7-sonnet
|
|
226
|
-
// Fixes the issue where we need :thinking to be supported
|
|
227
|
-
if (parsed.model === 'claude-3.7-sonnet' && model.slug.includes('claude-3.7-sonnet') && !model.slug.includes('beta')) {
|
|
228
|
-
return true;
|
|
229
|
-
}
|
|
230
|
-
return model.slug.split('/')[1] === parsed.model;
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
// We're using named functions here so we can console.log the filter chain
|
|
234
|
-
// and see what filter is being applied and when
|
|
235
|
-
if (parsed.provider) {
|
|
236
|
-
filterChain.push(function providerFilter(model, provider) {
|
|
237
|
-
return provider?.slug === parsed.provider;
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
if (parsed?.providerConstraints?.length) {
|
|
241
|
-
// Since the provider isnt defined, we need to filter based on the provider constraints
|
|
242
|
-
filterChain.push(function providerConstraintFilter(model, provider) {
|
|
243
|
-
return (parsed?.providerConstraints?.every((constraint) => {
|
|
244
|
-
if (!provider) {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
let fieldToCheck = constraint.field;
|
|
248
|
-
if (constraint.field === 'cost') {
|
|
249
|
-
fieldToCheck = 'outputCost';
|
|
250
|
-
}
|
|
251
|
-
switch (constraint.type) {
|
|
252
|
-
case 'gt':
|
|
253
|
-
return Number(provider[fieldToCheck]) > parseFloat(constraint.value);
|
|
254
|
-
case 'lt':
|
|
255
|
-
return Number(provider[fieldToCheck]) < parseFloat(constraint.value);
|
|
256
|
-
case 'eq':
|
|
257
|
-
return Number(provider[fieldToCheck]) === parseFloat(constraint.value);
|
|
258
|
-
default:
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
}) || false);
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
if (parsed.capabilities) {
|
|
265
|
-
filterChain.push(function capabilitiesFilter(model, provider) {
|
|
266
|
-
return Object.entries(parsed?.capabilities || {}).every(([key, value]) => {
|
|
267
|
-
return provider?.supportedParameters?.includes(camelCase(key));
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
for (const model of modelsToFilterMixin) {
|
|
272
|
-
for (const provider of model.providers || []) {
|
|
273
|
-
if (filterChain.every((f) => f(model, provider))) {
|
|
274
|
-
modelAndProviders.push({
|
|
275
|
-
model,
|
|
276
|
-
provider: provider,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
const orderBy = (fields) => (a, b) => fields
|
|
282
|
-
.map((o) => {
|
|
283
|
-
let dir = 1;
|
|
284
|
-
if (o[0] === '-') {
|
|
285
|
-
dir = -1;
|
|
286
|
-
o = o.substring(1);
|
|
287
|
-
}
|
|
288
|
-
// Support for dot notation to access nested properties
|
|
289
|
-
const getNestedValue = (obj, path) => {
|
|
290
|
-
return path.split('.').reduce((prev, curr) => (prev && prev[curr] !== undefined ? prev[curr] : undefined), obj);
|
|
291
|
-
};
|
|
292
|
-
const aVal = getNestedValue(a, o);
|
|
293
|
-
const bVal = getNestedValue(b, o);
|
|
294
|
-
return aVal > bVal ? dir : aVal < bVal ? -dir : 0;
|
|
295
|
-
})
|
|
296
|
-
.reduce((p, n) => (p ? p : n), 0);
|
|
297
|
-
let sortingStrategy = orderBy(parsed?.priorities?.map((f) => `provider.${f}`) || []);
|
|
298
|
-
// Re-join back on model, replacing the providers with the filtered providers
|
|
299
|
-
return {
|
|
300
|
-
models: modelAndProviders
|
|
301
|
-
.map((x) => ({
|
|
302
|
-
...x.model,
|
|
303
|
-
provider: x.provider,
|
|
304
|
-
}))
|
|
305
|
-
.map((x) => {
|
|
306
|
-
delete x.providers;
|
|
307
|
-
delete x.endpoint;
|
|
308
|
-
return x;
|
|
309
|
-
})
|
|
310
|
-
.sort(sortingStrategy),
|
|
311
|
-
parsed,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Helper function to get the first model that matches a model identifier
|
|
316
|
-
* @param modelIdentifier
|
|
317
|
-
* @returns ResolvedModel
|
|
318
|
-
*/
|
|
319
|
-
export function getModel(modelIdentifier, augments = {}) {
|
|
320
|
-
// Inject the augments into the model string inside the parentheses
|
|
321
|
-
// Keeping the content of the parentheses intact
|
|
322
|
-
const parentheses = modelIdentifier.match(/\(([^)]+)\)/);
|
|
323
|
-
const augmentsString = [];
|
|
324
|
-
Object.entries(augments).forEach(([key, value]) => {
|
|
325
|
-
if (key == 'seed')
|
|
326
|
-
augmentsString.push(`seed:${value}`);
|
|
327
|
-
else if (key == 'temperature')
|
|
328
|
-
augmentsString.push(`temperature:${value}`);
|
|
329
|
-
else if (key == 'topP')
|
|
330
|
-
augmentsString.push(`topP:${value}`);
|
|
331
|
-
else if (key == 'topK')
|
|
332
|
-
augmentsString.push(`topK:${value}`);
|
|
333
|
-
else if (key == 'thread')
|
|
334
|
-
augmentsString.push(`thread:${value}`);
|
|
335
|
-
else if (key == 'requiredCapabilities') {
|
|
336
|
-
for (const capability of value) {
|
|
337
|
-
augmentsString.push(capability);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
else
|
|
341
|
-
augmentsString.push(`${key}:${value}`);
|
|
342
|
-
});
|
|
343
|
-
if (parentheses) {
|
|
344
|
-
modelIdentifier = modelIdentifier.replace(parentheses[0], `(${parentheses[1]},${augmentsString.filter(Boolean).join(',')})`);
|
|
345
|
-
}
|
|
346
|
-
else {
|
|
347
|
-
if (augmentsString.length) {
|
|
348
|
-
modelIdentifier += `(${augmentsString.join(',')})`;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
const parsed = parse(modelIdentifier);
|
|
352
|
-
const { models } = filterModels(modelIdentifier);
|
|
353
|
-
return {
|
|
354
|
-
...models[0],
|
|
355
|
-
parsed: {
|
|
356
|
-
...parsed,
|
|
357
|
-
...augments,
|
|
358
|
-
},
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
export function getModels(modelIdentifier) {
|
|
362
|
-
// Split the modelIdentifier by comma, ignoring commas inside parentheses
|
|
363
|
-
let result = [];
|
|
364
|
-
let segment = '';
|
|
365
|
-
let depth = 0;
|
|
366
|
-
for (const char of modelIdentifier) {
|
|
367
|
-
if (char === '(')
|
|
368
|
-
depth++;
|
|
369
|
-
else if (char === ')')
|
|
370
|
-
depth--;
|
|
371
|
-
else if (char === ',' && depth === 0) {
|
|
372
|
-
result.push(segment.trim());
|
|
373
|
-
segment = '';
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
segment += char;
|
|
377
|
-
}
|
|
378
|
-
if (segment.trim())
|
|
379
|
-
result.push(segment.trim());
|
|
380
|
-
// Resolve each segment
|
|
381
|
-
return result.map((r) => getModel(r));
|
|
382
|
-
}
|
|
383
|
-
// TODO: Move this to a database or another source of truth
|
|
384
|
-
// This isnt a good place for this data.
|
|
385
|
-
const metaModels = [
|
|
386
|
-
{
|
|
387
|
-
name: 'frontier',
|
|
388
|
-
models: ['gemini-2.0-flash-001', 'deepseek-r1'],
|
|
389
|
-
},
|
|
390
|
-
];
|
package/dist/providers.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const getProviderName: (provider: string) => string | undefined;
|