@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.
@@ -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: ReadonlyArray<{
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
- const changed = JSON.stringify(data) !== JSON.stringify(this.data);
29
- this.data = data;
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. Every model gets the profile the
36
- * default has now, as an agent names its models but not what each can be asked for, with `options`
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
- const base = this.profileOf(this.data.defaultModel) ?? { options: [], contextWindowTokens: {} };
44
- const replaced = new Set(options.map((option) => option.id));
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
- const model = this.data.models.find((entry) => entry.slug === slug);
111
- return model ? this.data.profiles[model.profile] : undefined;
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
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "updatedAt": "2026-10-07T19:30:00Z",
2
+ "updatedAt": "2026-10-27T14:14:12.072Z",
3
3
  "defaultModel": "claude-sonnet-5-5",
4
4
  "profiles": {
5
5
  "frontier": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "updatedAt": "2026-10-26T22:10:00Z",
2
+ "updatedAt": "2026-10-27T14:14:13.686Z",
3
3
  "defaultModel": "gpt-6-astra",
4
4
  "profiles": {
5
5
  "ultra": {
@@ -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.40.5",
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.40.5",
85
- "@adecore/intelligent-ui": "0.40.5",
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
+ }
@@ -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
- const changed = JSON.stringify(data) !== JSON.stringify(this.data);
40
- this.data = data;
41
- this.hostWindows = undefined;
98
+ this.base = data;
42
99
 
43
- return changed;
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. Every model gets the profile the
49
- * default has now, as an agent names its models but not what each can be asked for, with `options`
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
- const base = this.profileOf(this.data.defaultModel) ?? { options: [], contextWindowTokens: {} };
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
- const changed = JSON.stringify(data) !== JSON.stringify(this.data);
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
- const model = this.data.models.find((entry) => entry.slug === slug);
176
+ return profileIn(this.data, slug);
177
+ }
147
178
 
148
- return model ? this.data.profiles[model.profile] : undefined;
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
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "updatedAt": "2026-10-07T19:30:00Z",
2
+ "updatedAt": "2026-10-27T14:14:12.072Z",
3
3
  "defaultModel": "claude-sonnet-5-5",
4
4
  "profiles": {
5
5
  "frontier": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "updatedAt": "2026-10-26T22:10:00Z",
2
+ "updatedAt": "2026-10-27T14:14:13.686Z",
3
3
  "defaultModel": "gpt-6-astra",
4
4
  "profiles": {
5
5
  "ultra": {
@@ -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
+ }