@adecore/agents 0.40.5 → 0.41.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/dist/providers/antigravity-models.json +12 -0
- package/dist/providers/catalog.d.ts +10 -6
- package/dist/providers/catalog.js +56 -31
- package/dist/providers/claude-models.json +1 -1
- package/dist/providers/codex-models.json +1 -1
- package/dist/providers/copilot-models.json +15 -0
- package/dist/providers/grok-models.json +15 -0
- package/package.json +15 -3
- package/src/providers/antigravity-models.json +12 -0
- package/src/providers/catalog.ts +77 -41
- package/src/providers/claude-models.json +1 -1
- package/src/providers/codex-models.json +1 -1
- package/src/providers/copilot-models.json +15 -0
- package/src/providers/grok-models.json +15 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-10-27T14:38:18.971Z",
|
|
3
|
+
"defaultModel": "default",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"agent": { "options": [], "contextWindowTokens": {} }
|
|
6
|
+
},
|
|
7
|
+
"models": [
|
|
8
|
+
{ "slug": "default", "name": "Default", "profile": "agent" },
|
|
9
|
+
{ "slug": "gemini-4-argon", "name": "Gemini 4 Argon", "profile": "agent" },
|
|
10
|
+
{ "slug": "gemini-3.8-flash", "name": "Gemini 3.8 Flash", "profile": "agent" }
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -2,22 +2,26 @@ import type { ModelCatalogData, ModelInfo, ModelOptionDescriptor, ModelSelection
|
|
|
2
2
|
export type ModelCatalogInput = Omit<ModelCatalogData, 'updatedAt'> & {
|
|
3
3
|
updatedAt?: string;
|
|
4
4
|
};
|
|
5
|
+
type AdoptedModel = {
|
|
6
|
+
slug: string;
|
|
7
|
+
name: string;
|
|
8
|
+
contextWindow?: number;
|
|
9
|
+
};
|
|
5
10
|
export declare class ModelCatalog {
|
|
6
11
|
private readonly shippedAt;
|
|
12
|
+
private base;
|
|
13
|
+
private adopted;
|
|
7
14
|
private data;
|
|
8
|
-
private hostWindows;
|
|
9
15
|
constructor(data?: ModelCatalogInput);
|
|
10
16
|
get defaultModel(): string;
|
|
11
17
|
replace(data: ModelCatalogData): boolean;
|
|
12
|
-
adopt(models:
|
|
13
|
-
slug: string;
|
|
14
|
-
name: string;
|
|
15
|
-
contextWindow?: number;
|
|
16
|
-
}>, defaultModel: string, options?: readonly ModelOptionDescriptor[]): boolean;
|
|
18
|
+
adopt(models: readonly AdoptedModel[], defaultModel: string, options?: readonly ModelOptionDescriptor[]): boolean;
|
|
17
19
|
list(): ModelInfo[];
|
|
18
20
|
nameOf(slug: string): string;
|
|
19
21
|
resolveModel(name: string): string | null;
|
|
20
22
|
normalize(selection: Partial<ModelSelection> | undefined): ModelSelection;
|
|
21
23
|
contextWindowFor(selection: ModelSelection): number | null;
|
|
22
24
|
private profileOf;
|
|
25
|
+
private settle;
|
|
23
26
|
}
|
|
27
|
+
export {};
|
|
@@ -3,18 +3,58 @@ const ADOPTED_PROFILE = 'agent';
|
|
|
3
3
|
function timeOf(data) {
|
|
4
4
|
return data.updatedAt === undefined ? 0 : Date.parse(data.updatedAt);
|
|
5
5
|
}
|
|
6
|
+
function profileIn(data, slug) {
|
|
7
|
+
const model = data.models.find((entry) => entry.slug === slug);
|
|
8
|
+
return model ? data.profiles[model.profile] : undefined;
|
|
9
|
+
}
|
|
10
|
+
/*
|
|
11
|
+
* The agent's models in the agent's order, with the agent's default. A model the base knows keeps how the base names
|
|
12
|
+
* it and its profile, with the size it reported where that profile names none; every other one gets the profile of the base's default, with the context window it reported as
|
|
13
|
+
* its only size. The options an agent reports replace the profile's options of the same id either way.
|
|
14
|
+
*/
|
|
15
|
+
function compose(base, adopted) {
|
|
16
|
+
const replaced = new Set(adopted.options.map((option) => option.id));
|
|
17
|
+
const withOptions = (profile) => ({
|
|
18
|
+
...profile,
|
|
19
|
+
options: [...profile.options.filter((option) => !replaced.has(option.id)), ...adopted.options]
|
|
20
|
+
});
|
|
21
|
+
const fallback = profileIn(base, base.defaultModel) ?? { options: [], contextWindowTokens: {} };
|
|
22
|
+
const profiles = {};
|
|
23
|
+
const models = adopted.models.map((model) => {
|
|
24
|
+
const known = base.models.find((entry) => entry.slug === model.slug);
|
|
25
|
+
const knownProfile = known === undefined ? undefined : base.profiles[known.profile];
|
|
26
|
+
if (known !== undefined && knownProfile !== undefined) {
|
|
27
|
+
// A base that names no size leaves the one the agent reported.
|
|
28
|
+
const reported = Object.keys(knownProfile.contextWindowTokens).length === 0 ? model.contextWindow : undefined;
|
|
29
|
+
const name = reported === undefined ? `${ADOPTED_PROFILE}:${known.profile}` : `${ADOPTED_PROFILE}:${known.profile}-${reported}`;
|
|
30
|
+
profiles[name] = withOptions(reported === undefined ? knownProfile : { ...knownProfile, contextWindowTokens: { '*': reported } });
|
|
31
|
+
return { ...known, profile: name };
|
|
32
|
+
}
|
|
33
|
+
const name = model.contextWindow === undefined ? ADOPTED_PROFILE : `${ADOPTED_PROFILE}-${model.contextWindow}`;
|
|
34
|
+
profiles[name] = withOptions(model.contextWindow === undefined ? fallback : { ...fallback, contextWindowTokens: { '*': model.contextWindow } });
|
|
35
|
+
return { slug: model.slug, name: model.name, profile: name };
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
...(base.updatedAt === undefined ? {} : { updatedAt: base.updatedAt }),
|
|
39
|
+
defaultModel: adopted.defaultModel,
|
|
40
|
+
profiles,
|
|
41
|
+
models
|
|
42
|
+
};
|
|
43
|
+
}
|
|
6
44
|
/*
|
|
7
45
|
* The models a provider offers and what each one can be asked for. Bundled as JSON so a new
|
|
8
46
|
* model is a data change; a profile is only needed for a new combination of options. A host may
|
|
9
|
-
* swap in a newer copy while it runs, never one older than the copy it was built with.
|
|
47
|
+
* swap in a newer copy while it runs, never one older than the copy it was built with. What an
|
|
48
|
+
* agent reported for itself lies over that copy and survives a newer one.
|
|
10
49
|
*/
|
|
11
50
|
export class ModelCatalog {
|
|
12
51
|
shippedAt;
|
|
52
|
+
base;
|
|
53
|
+
adopted = null;
|
|
13
54
|
data;
|
|
14
|
-
// The sizes the host's own default had before an agent's models replaced it, for an adopted model that names none.
|
|
15
|
-
hostWindows;
|
|
16
55
|
constructor(data = manifest) {
|
|
17
56
|
this.shippedAt = timeOf(data);
|
|
57
|
+
this.base = data;
|
|
18
58
|
this.data = data;
|
|
19
59
|
}
|
|
20
60
|
get defaultModel() {
|
|
@@ -25,40 +65,20 @@ export class ModelCatalog {
|
|
|
25
65
|
if (timeOf(data) < this.shippedAt) {
|
|
26
66
|
return false;
|
|
27
67
|
}
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
this.hostWindows = undefined;
|
|
31
|
-
return changed;
|
|
68
|
+
this.base = data;
|
|
69
|
+
return this.settle();
|
|
32
70
|
}
|
|
33
71
|
/*
|
|
34
72
|
* Takes the models an agent reported for itself in place of the list, the agent's current model as the
|
|
35
|
-
* default and its order kept; answers whether the models changed.
|
|
36
|
-
*
|
|
37
|
-
* in place of the profile's options of the same id, and the context window in tokens a model names as its only size.
|
|
73
|
+
* default and its order kept; answers whether the models changed. An agent names its models but not what
|
|
74
|
+
* each can be asked for, so that comes from the base where it knows the model (see `compose`).
|
|
38
75
|
*/
|
|
39
76
|
adopt(models, defaultModel, options = []) {
|
|
40
77
|
if (models.length === 0 || !models.some((model) => model.slug === defaultModel)) {
|
|
41
78
|
return false;
|
|
42
79
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.hostWindows ??= base.contextWindowTokens;
|
|
46
|
-
const profile = { ...base, contextWindowTokens: this.hostWindows, options: [...base.options.filter((option) => !replaced.has(option.id)), ...options] };
|
|
47
|
-
const profileName = (window) => (window === undefined ? ADOPTED_PROFILE : `${ADOPTED_PROFILE}-${window}`);
|
|
48
|
-
const profiles = {};
|
|
49
|
-
for (const model of models) {
|
|
50
|
-
profiles[profileName(model.contextWindow)] =
|
|
51
|
-
model.contextWindow === undefined ? profile : { ...profile, contextWindowTokens: { '*': model.contextWindow } };
|
|
52
|
-
}
|
|
53
|
-
const data = {
|
|
54
|
-
...(this.data.updatedAt === undefined ? {} : { updatedAt: this.data.updatedAt }),
|
|
55
|
-
defaultModel,
|
|
56
|
-
profiles,
|
|
57
|
-
models: models.map((model) => ({ slug: model.slug, name: model.name, profile: profileName(model.contextWindow) }))
|
|
58
|
-
};
|
|
59
|
-
const changed = JSON.stringify(data) !== JSON.stringify(this.data);
|
|
60
|
-
this.data = data;
|
|
61
|
-
return changed;
|
|
80
|
+
this.adopted = { models: [...models], defaultModel, options: [...options] };
|
|
81
|
+
return this.settle();
|
|
62
82
|
}
|
|
63
83
|
list() {
|
|
64
84
|
return this.data.models.map((model) => ({
|
|
@@ -107,7 +127,12 @@ export class ModelCatalog {
|
|
|
107
127
|
return (typeof chosen === 'string' ? profile.contextWindowTokens[chosen] : undefined) ?? profile.contextWindowTokens['*'] ?? null;
|
|
108
128
|
}
|
|
109
129
|
profileOf(slug) {
|
|
110
|
-
|
|
111
|
-
|
|
130
|
+
return profileIn(this.data, slug);
|
|
131
|
+
}
|
|
132
|
+
settle() {
|
|
133
|
+
const data = this.adopted === null ? this.base : compose(this.base, this.adopted);
|
|
134
|
+
const changed = JSON.stringify(data) !== JSON.stringify(this.data);
|
|
135
|
+
this.data = data;
|
|
136
|
+
return changed;
|
|
112
137
|
}
|
|
113
138
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-10-27T14:38:17.374Z",
|
|
3
|
+
"defaultModel": "default",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"agent": { "options": [], "contextWindowTokens": {} }
|
|
6
|
+
},
|
|
7
|
+
"models": [
|
|
8
|
+
{ "slug": "default", "name": "Default", "profile": "agent" },
|
|
9
|
+
{ "slug": "auto", "name": "Auto", "profile": "agent" },
|
|
10
|
+
{ "slug": "claude-sonnet-4.6", "name": "Claude Sonnet 4.6", "profile": "agent" },
|
|
11
|
+
{ "slug": "claude-haiku-4.5", "name": "Claude Haiku 4.5", "profile": "agent" },
|
|
12
|
+
{ "slug": "gpt-5.3-codex", "name": "GPT-5.3-Codex", "profile": "agent" },
|
|
13
|
+
{ "slug": "mai-code-1.1-flash", "name": "MAI-Code-1.1-Flash", "profile": "agent" }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-10-27T14:38:15.597Z",
|
|
3
|
+
"defaultModel": "default",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"agent": { "options": [], "contextWindowTokens": {} },
|
|
6
|
+
"agent-256k": { "options": [], "contextWindowTokens": { "*": 256000 } }
|
|
7
|
+
},
|
|
8
|
+
"models": [
|
|
9
|
+
{ "slug": "default", "name": "Default", "profile": "agent" },
|
|
10
|
+
{ "slug": "grok-4.7", "name": "Grok 4.7", "profile": "agent" },
|
|
11
|
+
{ "slug": "grok-4.7-build-fast", "name": "Grok 4.7 Build Fast", "profile": "agent" },
|
|
12
|
+
{ "slug": "grok-4.6", "name": "Grok 4.6", "profile": "agent-256k", "legacy": true },
|
|
13
|
+
{ "slug": "grok-4.5", "name": "Grok 4.5", "profile": "agent-256k", "legacy": true }
|
|
14
|
+
]
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.1",
|
|
4
4
|
"description": "Node-compatible agent chat hosts, providers, accounts, usage and durable task coordination.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -62,6 +62,18 @@
|
|
|
62
62
|
"source": "./src/providers/codex-models.json",
|
|
63
63
|
"default": "./dist/providers/codex-models.json"
|
|
64
64
|
},
|
|
65
|
+
"./providers/grok-models.json": {
|
|
66
|
+
"source": "./src/providers/grok-models.json",
|
|
67
|
+
"default": "./dist/providers/grok-models.json"
|
|
68
|
+
},
|
|
69
|
+
"./providers/copilot-models.json": {
|
|
70
|
+
"source": "./src/providers/copilot-models.json",
|
|
71
|
+
"default": "./dist/providers/copilot-models.json"
|
|
72
|
+
},
|
|
73
|
+
"./providers/antigravity-models.json": {
|
|
74
|
+
"source": "./src/providers/antigravity-models.json",
|
|
75
|
+
"default": "./dist/providers/antigravity-models.json"
|
|
76
|
+
},
|
|
65
77
|
"./usage/prices-snapshot.json": {
|
|
66
78
|
"source": "./src/usage/prices-snapshot.json",
|
|
67
79
|
"default": "./dist/usage/prices-snapshot.json"
|
|
@@ -81,8 +93,8 @@
|
|
|
81
93
|
"test": "bun --conditions=source test"
|
|
82
94
|
},
|
|
83
95
|
"dependencies": {
|
|
84
|
-
"@adecore/agent-contracts": "0.
|
|
85
|
-
"@adecore/intelligent-ui": "0.
|
|
96
|
+
"@adecore/agent-contracts": "0.41.1",
|
|
97
|
+
"@adecore/intelligent-ui": "0.41.1",
|
|
86
98
|
"zod": "^4.6.7"
|
|
87
99
|
},
|
|
88
100
|
"devDependencies": {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-10-27T14:38:18.971Z",
|
|
3
|
+
"defaultModel": "default",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"agent": { "options": [], "contextWindowTokens": {} }
|
|
6
|
+
},
|
|
7
|
+
"models": [
|
|
8
|
+
{ "slug": "default", "name": "Default", "profile": "agent" },
|
|
9
|
+
{ "slug": "gemini-4-argon", "name": "Gemini 4 Argon", "profile": "agent" },
|
|
10
|
+
{ "slug": "gemini-3.8-flash", "name": "Gemini 3.8 Flash", "profile": "agent" }
|
|
11
|
+
]
|
|
12
|
+
}
|
package/src/providers/catalog.ts
CHANGED
|
@@ -6,23 +6,82 @@ export type ModelCatalogInput = Omit<ModelCatalogData, 'updatedAt'> & { updatedA
|
|
|
6
6
|
|
|
7
7
|
const ADOPTED_PROFILE = 'agent';
|
|
8
8
|
|
|
9
|
+
type AdoptedModel = { slug: string; name: string; contextWindow?: number };
|
|
10
|
+
|
|
11
|
+
interface Adopted {
|
|
12
|
+
readonly models: readonly AdoptedModel[];
|
|
13
|
+
readonly defaultModel: string;
|
|
14
|
+
readonly options: readonly ModelOptionDescriptor[];
|
|
15
|
+
}
|
|
16
|
+
|
|
9
17
|
function timeOf(data: ModelCatalogInput): number {
|
|
10
18
|
return data.updatedAt === undefined ? 0 : Date.parse(data.updatedAt);
|
|
11
19
|
}
|
|
12
20
|
|
|
21
|
+
function profileIn(data: ModelCatalogInput, slug: string): ModelCatalogProfile | undefined {
|
|
22
|
+
const model = data.models.find((entry) => entry.slug === slug);
|
|
23
|
+
|
|
24
|
+
return model ? data.profiles[model.profile] : undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/*
|
|
28
|
+
* The agent's models in the agent's order, with the agent's default. A model the base knows keeps how the base names
|
|
29
|
+
* it and its profile, with the size it reported where that profile names none; every other one gets the profile of the base's default, with the context window it reported as
|
|
30
|
+
* its only size. The options an agent reports replace the profile's options of the same id either way.
|
|
31
|
+
*/
|
|
32
|
+
function compose(base: ModelCatalogInput, adopted: Adopted): ModelCatalogInput {
|
|
33
|
+
const replaced = new Set(adopted.options.map((option) => option.id));
|
|
34
|
+
|
|
35
|
+
const withOptions = (profile: ModelCatalogProfile): ModelCatalogProfile => ({
|
|
36
|
+
...profile,
|
|
37
|
+
options: [...profile.options.filter((option) => !replaced.has(option.id)), ...adopted.options]
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const fallback = profileIn(base, base.defaultModel) ?? { options: [], contextWindowTokens: {} };
|
|
41
|
+
const profiles: Record<string, ModelCatalogProfile> = {};
|
|
42
|
+
|
|
43
|
+
const models = adopted.models.map((model) => {
|
|
44
|
+
const known = base.models.find((entry) => entry.slug === model.slug);
|
|
45
|
+
const knownProfile = known === undefined ? undefined : base.profiles[known.profile];
|
|
46
|
+
|
|
47
|
+
if (known !== undefined && knownProfile !== undefined) {
|
|
48
|
+
// A base that names no size leaves the one the agent reported.
|
|
49
|
+
const reported = Object.keys(knownProfile.contextWindowTokens).length === 0 ? model.contextWindow : undefined;
|
|
50
|
+
const name = reported === undefined ? `${ADOPTED_PROFILE}:${known.profile}` : `${ADOPTED_PROFILE}:${known.profile}-${reported}`;
|
|
51
|
+
profiles[name] = withOptions(reported === undefined ? knownProfile : { ...knownProfile, contextWindowTokens: { '*': reported } });
|
|
52
|
+
|
|
53
|
+
return { ...known, profile: name };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const name = model.contextWindow === undefined ? ADOPTED_PROFILE : `${ADOPTED_PROFILE}-${model.contextWindow}`;
|
|
57
|
+
profiles[name] = withOptions(model.contextWindow === undefined ? fallback : { ...fallback, contextWindowTokens: { '*': model.contextWindow } });
|
|
58
|
+
|
|
59
|
+
return { slug: model.slug, name: model.name, profile: name };
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
...(base.updatedAt === undefined ? {} : { updatedAt: base.updatedAt }),
|
|
64
|
+
defaultModel: adopted.defaultModel,
|
|
65
|
+
profiles,
|
|
66
|
+
models
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
13
70
|
/*
|
|
14
71
|
* The models a provider offers and what each one can be asked for. Bundled as JSON so a new
|
|
15
72
|
* model is a data change; a profile is only needed for a new combination of options. A host may
|
|
16
|
-
* swap in a newer copy while it runs, never one older than the copy it was built with.
|
|
73
|
+
* swap in a newer copy while it runs, never one older than the copy it was built with. What an
|
|
74
|
+
* agent reported for itself lies over that copy and survives a newer one.
|
|
17
75
|
*/
|
|
18
76
|
export class ModelCatalog {
|
|
19
77
|
private readonly shippedAt: number;
|
|
78
|
+
private base: ModelCatalogInput;
|
|
79
|
+
private adopted: Adopted | null = null;
|
|
20
80
|
private data: ModelCatalogInput;
|
|
21
|
-
// The sizes the host's own default had before an agent's models replaced it, for an adopted model that names none.
|
|
22
|
-
private hostWindows: ModelCatalogProfile['contextWindowTokens'] | undefined;
|
|
23
81
|
|
|
24
82
|
constructor(data: ModelCatalogInput = manifest as never) {
|
|
25
83
|
this.shippedAt = timeOf(data);
|
|
84
|
+
this.base = data;
|
|
26
85
|
this.data = data;
|
|
27
86
|
}
|
|
28
87
|
|
|
@@ -36,53 +95,24 @@ export class ModelCatalog {
|
|
|
36
95
|
return false;
|
|
37
96
|
}
|
|
38
97
|
|
|
39
|
-
|
|
40
|
-
this.data = data;
|
|
41
|
-
this.hostWindows = undefined;
|
|
98
|
+
this.base = data;
|
|
42
99
|
|
|
43
|
-
return
|
|
100
|
+
return this.settle();
|
|
44
101
|
}
|
|
45
102
|
|
|
46
103
|
/*
|
|
47
104
|
* Takes the models an agent reported for itself in place of the list, the agent's current model as the
|
|
48
|
-
* default and its order kept; answers whether the models changed.
|
|
49
|
-
*
|
|
50
|
-
* in place of the profile's options of the same id, and the context window in tokens a model names as its only size.
|
|
105
|
+
* default and its order kept; answers whether the models changed. An agent names its models but not what
|
|
106
|
+
* each can be asked for, so that comes from the base where it knows the model (see `compose`).
|
|
51
107
|
*/
|
|
52
|
-
adopt(
|
|
53
|
-
models: ReadonlyArray<{ slug: string; name: string; contextWindow?: number }>,
|
|
54
|
-
defaultModel: string,
|
|
55
|
-
options: readonly ModelOptionDescriptor[] = []
|
|
56
|
-
): boolean {
|
|
108
|
+
adopt(models: readonly AdoptedModel[], defaultModel: string, options: readonly ModelOptionDescriptor[] = []): boolean {
|
|
57
109
|
if (models.length === 0 || !models.some((model) => model.slug === defaultModel)) {
|
|
58
110
|
return false;
|
|
59
111
|
}
|
|
60
112
|
|
|
61
|
-
|
|
62
|
-
const replaced = new Set(options.map((option) => option.id));
|
|
63
|
-
this.hostWindows ??= base.contextWindowTokens;
|
|
64
|
-
const profile = { ...base, contextWindowTokens: this.hostWindows, options: [...base.options.filter((option) => !replaced.has(option.id)), ...options] };
|
|
65
|
-
|
|
66
|
-
const profileName = (window: number | undefined): string => (window === undefined ? ADOPTED_PROFILE : `${ADOPTED_PROFILE}-${window}`);
|
|
67
|
-
|
|
68
|
-
const profiles: Record<string, ModelCatalogProfile> = {};
|
|
69
|
-
|
|
70
|
-
for (const model of models) {
|
|
71
|
-
profiles[profileName(model.contextWindow)] =
|
|
72
|
-
model.contextWindow === undefined ? profile : { ...profile, contextWindowTokens: { '*': model.contextWindow } };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const data: ModelCatalogInput = {
|
|
76
|
-
...(this.data.updatedAt === undefined ? {} : { updatedAt: this.data.updatedAt }),
|
|
77
|
-
defaultModel,
|
|
78
|
-
profiles,
|
|
79
|
-
models: models.map((model) => ({ slug: model.slug, name: model.name, profile: profileName(model.contextWindow) }))
|
|
80
|
-
};
|
|
113
|
+
this.adopted = { models: [...models], defaultModel, options: [...options] };
|
|
81
114
|
|
|
82
|
-
|
|
83
|
-
this.data = data;
|
|
84
|
-
|
|
85
|
-
return changed;
|
|
115
|
+
return this.settle();
|
|
86
116
|
}
|
|
87
117
|
|
|
88
118
|
list(): ModelInfo[] {
|
|
@@ -143,8 +173,14 @@ export class ModelCatalog {
|
|
|
143
173
|
}
|
|
144
174
|
|
|
145
175
|
private profileOf(slug: string): ModelCatalogProfile | undefined {
|
|
146
|
-
|
|
176
|
+
return profileIn(this.data, slug);
|
|
177
|
+
}
|
|
147
178
|
|
|
148
|
-
|
|
179
|
+
private settle(): boolean {
|
|
180
|
+
const data = this.adopted === null ? this.base : compose(this.base, this.adopted);
|
|
181
|
+
const changed = JSON.stringify(data) !== JSON.stringify(this.data);
|
|
182
|
+
this.data = data;
|
|
183
|
+
|
|
184
|
+
return changed;
|
|
149
185
|
}
|
|
150
186
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-10-27T14:38:17.374Z",
|
|
3
|
+
"defaultModel": "default",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"agent": { "options": [], "contextWindowTokens": {} }
|
|
6
|
+
},
|
|
7
|
+
"models": [
|
|
8
|
+
{ "slug": "default", "name": "Default", "profile": "agent" },
|
|
9
|
+
{ "slug": "auto", "name": "Auto", "profile": "agent" },
|
|
10
|
+
{ "slug": "claude-sonnet-4.6", "name": "Claude Sonnet 4.6", "profile": "agent" },
|
|
11
|
+
{ "slug": "claude-haiku-4.5", "name": "Claude Haiku 4.5", "profile": "agent" },
|
|
12
|
+
{ "slug": "gpt-5.3-codex", "name": "GPT-5.3-Codex", "profile": "agent" },
|
|
13
|
+
{ "slug": "mai-code-1.1-flash", "name": "MAI-Code-1.1-Flash", "profile": "agent" }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-10-27T14:38:15.597Z",
|
|
3
|
+
"defaultModel": "default",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"agent": { "options": [], "contextWindowTokens": {} },
|
|
6
|
+
"agent-256k": { "options": [], "contextWindowTokens": { "*": 256000 } }
|
|
7
|
+
},
|
|
8
|
+
"models": [
|
|
9
|
+
{ "slug": "default", "name": "Default", "profile": "agent" },
|
|
10
|
+
{ "slug": "grok-4.7", "name": "Grok 4.7", "profile": "agent" },
|
|
11
|
+
{ "slug": "grok-4.7-build-fast", "name": "Grok 4.7 Build Fast", "profile": "agent" },
|
|
12
|
+
{ "slug": "grok-4.6", "name": "Grok 4.6", "profile": "agent-256k", "legacy": true },
|
|
13
|
+
{ "slug": "grok-4.5", "name": "Grok 4.5", "profile": "agent-256k", "legacy": true }
|
|
14
|
+
]
|
|
15
|
+
}
|