@agentproto/model-catalog 0.13.1 → 0.14.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.
Files changed (47) hide show
  1. package/dist/access/index.d.ts +4 -3
  2. package/dist/access/index.mjs +5 -4
  3. package/dist/{catalog-DRGEICKV.d.ts → catalog-BB0uDJh-.d.ts} +25 -37
  4. package/dist/{chunk-ALUIW3QO.mjs → chunk-BXTZ2EDE.mjs} +217 -482
  5. package/dist/chunk-BXTZ2EDE.mjs.map +1 -0
  6. package/dist/{chunk-6TZ6WIM3.mjs → chunk-DTE62ERL.mjs} +4 -4
  7. package/dist/{chunk-6TZ6WIM3.mjs.map → chunk-DTE62ERL.mjs.map} +1 -1
  8. package/dist/{chunk-XJUZ5X3W.mjs → chunk-ETI76MOK.mjs} +5 -5
  9. package/dist/{chunk-XJUZ5X3W.mjs.map → chunk-ETI76MOK.mjs.map} +1 -1
  10. package/dist/chunk-HFPX2DNR.mjs +3 -0
  11. package/dist/chunk-HFPX2DNR.mjs.map +1 -0
  12. package/dist/{chunk-UOOTUH6N.mjs → chunk-IHU6XTXS.mjs} +3 -3
  13. package/dist/{chunk-UOOTUH6N.mjs.map → chunk-IHU6XTXS.mjs.map} +1 -1
  14. package/dist/{chunk-TVXNRUJM.mjs → chunk-MZ23K5W6.mjs} +186 -204
  15. package/dist/chunk-MZ23K5W6.mjs.map +1 -0
  16. package/dist/{chunk-TZ5LNR5F.mjs → chunk-PVE3WQRH.mjs} +8 -6
  17. package/dist/chunk-PVE3WQRH.mjs.map +1 -0
  18. package/dist/{chunk-5EX3V7QZ.mjs → chunk-W7K6DGOK.mjs} +4 -4
  19. package/dist/{chunk-5EX3V7QZ.mjs.map → chunk-W7K6DGOK.mjs.map} +1 -1
  20. package/dist/{chunk-NNV3NYUE.mjs → chunk-YSEQMLV2.mjs} +14 -5
  21. package/dist/chunk-YSEQMLV2.mjs.map +1 -0
  22. package/dist/cost/index.mjs +6 -6
  23. package/dist/curation/index.d.ts +2 -2
  24. package/dist/curation/index.mjs +6 -6
  25. package/dist/evaluate-BjSlZsJf.d.ts +49 -0
  26. package/dist/{index-VuUTv1ft.d.ts → index-D8FWHlom.d.ts} +1 -1
  27. package/dist/index-DetGJJ-F.d.ts +78 -0
  28. package/dist/index.d.ts +7 -5
  29. package/dist/index.mjs +11 -10
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/lists/index.d.ts +70 -0
  32. package/dist/lists/index.mjs +290 -0
  33. package/dist/lists/index.mjs.map +1 -0
  34. package/dist/llm/index.d.ts +1 -1
  35. package/dist/llm/index.mjs +2 -2
  36. package/dist/overlay/index.d.ts +1 -1
  37. package/dist/picker/index.d.ts +112 -5
  38. package/dist/route-identity/index.d.ts +1 -1
  39. package/dist/route-identity/index.mjs +2 -2
  40. package/dist/types-DMzMWJeJ.d.ts +50 -0
  41. package/package.json +8 -3
  42. package/dist/chunk-ALUIW3QO.mjs.map +0 -1
  43. package/dist/chunk-NNV3NYUE.mjs.map +0 -1
  44. package/dist/chunk-TVXNRUJM.mjs.map +0 -1
  45. package/dist/chunk-TZ5LNR5F.mjs.map +0 -1
  46. package/dist/evaluate-B-irutMW.d.ts +0 -84
  47. package/dist/index-kbLggJk1.d.ts +0 -171
@@ -0,0 +1,70 @@
1
+ import { A as AccessTarget } from '../types-DMzMWJeJ.js';
2
+ export { i as isZeroPriced } from '../index-DetGJJ-F.js';
3
+ import '../base-BaiI72Da.js';
4
+ import 'zod';
5
+ import '../index-D8FWHlom.js';
6
+ import '../catalog-BB0uDJh-.js';
7
+ import '../image/index.js';
8
+ import '../video/index.js';
9
+ import '../audio/index.js';
10
+ import '../audio-Do2j3wDC.js';
11
+ import '../schema/voice.js';
12
+
13
+ /**
14
+ * Model lists — named, user-editable selections over the model catalog.
15
+ *
16
+ * A list is data: a set of include selectors (OR), optional exclusions that
17
+ * always win, explicit id pins, and an ordering mode. The selector vocabulary
18
+ * is the existing `AccessTarget` matcher plus the catalog dimensions that have
19
+ * no access-rule target (price, context window, route variant) and list
20
+ * composition.
21
+ *
22
+ * `zero-cost` (the seed list) is the one way "free" is expressed in code now:
23
+ * `{ include: [{ kind: "tag", value: "price:zero" }] }`.
24
+ */
25
+
26
+ type ModelSelector = AccessTarget | {
27
+ kind: "price";
28
+ maxInPer1M?: number;
29
+ maxOutPer1M?: number;
30
+ } | {
31
+ kind: "context";
32
+ min: number;
33
+ } | {
34
+ kind: "variant";
35
+ value: string;
36
+ } | {
37
+ kind: "list";
38
+ id: string;
39
+ };
40
+ /** A named selection over the model catalog. An uncataloged `ids` pin is only
41
+ * removed by a `{ kind: "model" }` exclude; no other selector can match an id
42
+ * the catalog does not know. */
43
+ interface ModelList {
44
+ id: string;
45
+ label?: string;
46
+ include?: ModelSelector[];
47
+ exclude?: ModelSelector[];
48
+ ids?: string[];
49
+ order?: "listed" | "cheapest" | "largest-context" | "newest";
50
+ rotation?: "priority" | "round-robin" | "least-recently-limited";
51
+ }
52
+ interface ModelListSource {
53
+ get(id: string): ModelList | undefined;
54
+ }
55
+ declare class ModelListError extends Error {
56
+ readonly name = "ModelListError";
57
+ }
58
+ /** Test/consumer helper after an overlay or route registration changes. */
59
+ declare function clearModelListCache(): void;
60
+ /** Membership without full expansion; uncataloged ids match only via `ids`. */
61
+ declare function inModelList(model: string, id: string, src: ModelListSource): boolean;
62
+ /** Ordered, de-duplicated model ids. Throws ModelListError on unknown id or cycle. */
63
+ declare function resolveModelList(id: string, src: ModelListSource): string[];
64
+ /** Explain: per model, which selector or pin included it. */
65
+ declare function explainModelList(id: string, src: ModelListSource): Array<{
66
+ model: string;
67
+ via: string;
68
+ }>;
69
+
70
+ export { type ModelList, ModelListError, type ModelListSource, type ModelSelector, clearModelListCache, explainModelList, inModelList, resolveModelList };
@@ -0,0 +1,290 @@
1
+ import { getModel, resolveAlias, listModels } from '../chunk-ETI76MOK.mjs';
2
+ import '../chunk-H6JUTF3U.mjs';
3
+ import { stripRouteSuffix, resolveLlmModelRoute, formatModelRef, listRouterLlmRoutes, tryParseModelRef } from '../chunk-BXTZ2EDE.mjs';
4
+ import { modelMatchesTarget } from '../chunk-PVE3WQRH.mjs';
5
+ export { isZeroPriced } from '../chunk-YSEQMLV2.mjs';
6
+ import '../chunk-WG4F6IRS.mjs';
7
+ import '../chunk-IHU6XTXS.mjs';
8
+ import { resolveContextWindow } from '../chunk-MZ23K5W6.mjs';
9
+ import '../chunk-QHELXPSL.mjs';
10
+ import '../chunk-2LWYZOWB.mjs';
11
+ import '../chunk-IJZ4XPO2.mjs';
12
+ import '../chunk-WRUWNKDB.mjs';
13
+ import '../chunk-SGJR6ZQH.mjs';
14
+ import '../chunk-HEDDSOZF.mjs';
15
+
16
+ /**
17
+ * @agentproto/model-catalog v0.1.0
18
+ * Unified model catalog: LLM, image, video, audio entries + cost dispatcher + picker.
19
+ * Zod-only OSS core; @agstudio/model-catalog layers billing/access/BYOK on top.
20
+ */
21
+
22
+ // src/lists/index.ts
23
+ var ModelListError = class extends Error {
24
+ name = "ModelListError";
25
+ };
26
+ var ROUTERS = [
27
+ "openrouter",
28
+ "requesty",
29
+ "huggingface",
30
+ "opencode",
31
+ "opencode-go"
32
+ ];
33
+ var candidateCache;
34
+ var candidateIndexCache;
35
+ var subjectIdsCache = /* @__PURE__ */ new Map();
36
+ function candidates() {
37
+ if (candidateCache) return candidateCache;
38
+ const out = listModels({ kind: "llm" });
39
+ const seen = new Set(out.map((model) => model.id));
40
+ for (const router of ROUTERS) {
41
+ for (const route of listRouterLlmRoutes(router)) {
42
+ const id = formatModelRef(route.ref);
43
+ if (seen.has(id)) continue;
44
+ seen.add(id);
45
+ out.push({
46
+ kind: "llm",
47
+ id,
48
+ canonicalId: route.canonicalProductId,
49
+ pricing: route.pricing,
50
+ provider: route.pricing.provider
51
+ });
52
+ }
53
+ }
54
+ candidateCache = out;
55
+ return out;
56
+ }
57
+ function clearModelListCache() {
58
+ candidateCache = void 0;
59
+ candidateIndexCache = void 0;
60
+ subjectIdsCache.clear();
61
+ }
62
+ function selectorLabel(selector) {
63
+ switch (selector.kind) {
64
+ case "model":
65
+ return `model:${selector.id}`;
66
+ case "price":
67
+ return `price:${selector.maxInPer1M ?? "*"}/${selector.maxOutPer1M ?? "*"}`;
68
+ case "context":
69
+ return `context:>=${selector.min}`;
70
+ case "variant":
71
+ return `variant:${selector.value}`;
72
+ case "list":
73
+ return `list:${selector.id}`;
74
+ default:
75
+ return `${selector.kind}:${selector.value}`;
76
+ }
77
+ }
78
+ function isListSelector(selector) {
79
+ return selector.kind === "list";
80
+ }
81
+ function contextWindowOf(model) {
82
+ if (model.kind !== "llm") return void 0;
83
+ return resolveContextWindow(model.id)?.contextWindow ?? resolveContextWindow(model.canonicalId)?.contextWindow;
84
+ }
85
+ function variantOf(id) {
86
+ const ref = tryParseModelRef(id);
87
+ return ref?.variant;
88
+ }
89
+ function selectorMatches(selector, model, rawId, src, stack) {
90
+ if (isListSelector(selector)) {
91
+ return inList(selector.id, rawId, src, stack);
92
+ }
93
+ switch (selector.kind) {
94
+ case "variant":
95
+ return variantOf(rawId) === selector.value || model !== void 0 && variantOf(model.id) === selector.value;
96
+ case "price": {
97
+ const pricing = model?.kind === "llm" ? model.pricing : void 0;
98
+ if (!pricing) return false;
99
+ if (selector.maxInPer1M !== void 0 && pricing.inputPer1M > selector.maxInPer1M) {
100
+ return false;
101
+ }
102
+ if (selector.maxOutPer1M !== void 0 && pricing.outputPer1M > selector.maxOutPer1M) {
103
+ return false;
104
+ }
105
+ return true;
106
+ }
107
+ case "context": {
108
+ if (!model) return false;
109
+ const window = contextWindowOf(model);
110
+ return window !== void 0 && window >= selector.min;
111
+ }
112
+ default:
113
+ return model !== void 0 && modelMatchesTarget(selector, model);
114
+ }
115
+ }
116
+ function excludeMatches(selector, model, rawId, src, stack) {
117
+ if (selector.kind === "model" && pinsMatch(selector.id, rawId)) {
118
+ return true;
119
+ }
120
+ return selectorMatches(selector, model, rawId, src, stack);
121
+ }
122
+ function candidateIndex() {
123
+ if (candidateIndexCache) return candidateIndexCache;
124
+ const index = /* @__PURE__ */ new Map();
125
+ for (const model of candidates()) index.set(model.id, model);
126
+ candidateIndexCache = index;
127
+ return index;
128
+ }
129
+ function subjectIds(raw) {
130
+ const cached = subjectIdsCache.get(raw);
131
+ if (cached) return cached;
132
+ const stripped = stripRouteSuffix(raw);
133
+ const out = /* @__PURE__ */ new Set([raw, stripped]);
134
+ const consider = (id) => {
135
+ out.add(id);
136
+ const model = getModel(id);
137
+ if (model) {
138
+ out.add(model.id);
139
+ if (model.kind === "llm") out.add(model.canonicalId);
140
+ }
141
+ out.add(resolveAlias(id));
142
+ try {
143
+ const route = resolveLlmModelRoute(id);
144
+ if (route) {
145
+ out.add(formatModelRef(route.ref));
146
+ out.add(`${route.vendor}/${route.product}`);
147
+ }
148
+ } catch {
149
+ }
150
+ };
151
+ consider(stripped);
152
+ if (!stripped.includes("/")) {
153
+ const bare = stripped.split(":")[0] ?? stripped;
154
+ for (const model of candidates()) {
155
+ const segment = model.id.split("/").pop()?.split(":")[0];
156
+ if (segment === bare) out.add(model.id);
157
+ }
158
+ }
159
+ const result = [...out];
160
+ subjectIdsCache.set(raw, result);
161
+ return result;
162
+ }
163
+ function pinsMatch(pin, id) {
164
+ if (pin === id) return true;
165
+ const pinStripped = stripRouteSuffix(pin);
166
+ const idStripped = stripRouteSuffix(id);
167
+ return pin === idStripped || pinStripped === id || pinStripped === idStripped;
168
+ }
169
+ function listContains(list, rawId, src, stack) {
170
+ const index = candidateIndex();
171
+ const model = index.get(rawId) ?? index.get(stripRouteSuffix(rawId));
172
+ for (const selector of list.exclude ?? []) {
173
+ if (excludeMatches(selector, model, rawId, src, stack)) return false;
174
+ }
175
+ if ((list.ids ?? []).some((pin) => pinsMatch(pin, rawId))) return true;
176
+ return (list.include ?? []).some(
177
+ (selector) => selectorMatches(selector, model, rawId, src, stack)
178
+ );
179
+ }
180
+ function inList(listId, rawId, src, stack) {
181
+ const list = src.get(listId);
182
+ if (!list) throw new ModelListError(`unknown model list "${listId}"`);
183
+ if (stack.includes(listId)) {
184
+ throw new ModelListError(
185
+ `model list cycle: ${[...stack, listId].join(" -> ")}`
186
+ );
187
+ }
188
+ return listContains(list, rawId, src, [...stack, listId]);
189
+ }
190
+ function inModelList(model, id, src) {
191
+ return subjectIds(model).some(
192
+ (candidate) => inList(id, candidate, src, [])
193
+ );
194
+ }
195
+ function insert(entries, model, via) {
196
+ if (!entries.has(model)) entries.set(model, { model, via });
197
+ }
198
+ function resolveEntries(id, src, stack) {
199
+ const list = src.get(id);
200
+ if (!list) throw new ModelListError(`unknown model list "${id}"`);
201
+ if (stack.includes(id)) {
202
+ throw new ModelListError(`model list cycle: ${[...stack, id].join(" -> ")}`);
203
+ }
204
+ const nextStack = [...stack, id];
205
+ const entries = /* @__PURE__ */ new Map();
206
+ const index = candidateIndex();
207
+ const all = candidates();
208
+ for (const selector of list.include ?? []) {
209
+ if (isListSelector(selector)) {
210
+ for (const entry of resolveEntries(selector.id, src, nextStack)) {
211
+ insert(entries, entry.model, `list:${selector.id}`);
212
+ }
213
+ continue;
214
+ }
215
+ for (const model of all) {
216
+ if (selectorMatches(selector, model, model.id, src, nextStack)) {
217
+ insert(entries, model.id, selectorLabel(selector));
218
+ }
219
+ }
220
+ }
221
+ for (const pin of list.ids ?? []) insert(entries, pin, "ids");
222
+ for (const selector of list.exclude ?? []) {
223
+ if (isListSelector(selector)) {
224
+ for (const entry of resolveEntries(selector.id, src, nextStack)) {
225
+ entries.delete(entry.model);
226
+ }
227
+ continue;
228
+ }
229
+ for (const model of all) {
230
+ if (selectorMatches(selector, model, model.id, src, nextStack)) {
231
+ entries.delete(model.id);
232
+ }
233
+ }
234
+ for (const key of [...entries.keys()]) {
235
+ if (excludeMatches(selector, index.get(key), key, src, nextStack)) {
236
+ entries.delete(key);
237
+ }
238
+ }
239
+ }
240
+ return [...entries.values()];
241
+ }
242
+ function applyOrder(entries, order, index) {
243
+ if (!order || order === "listed" || entries.length === 0) return entries;
244
+ const pricingOf = (entry) => {
245
+ const model = index.get(entry.model);
246
+ return model?.kind === "llm" ? model.pricing : void 0;
247
+ };
248
+ const sorted = [...entries];
249
+ sorted.sort((a, b) => {
250
+ const pa = pricingOf(a);
251
+ const pb = pricingOf(b);
252
+ if (order === "cheapest") {
253
+ const ca = pa ? pa.inputPer1M + pa.outputPer1M : Number.POSITIVE_INFINITY;
254
+ const cb = pb ? pb.inputPer1M + pb.outputPer1M : Number.POSITIVE_INFINITY;
255
+ return ca - cb;
256
+ }
257
+ if (order === "largest-context") {
258
+ const ma = index.get(a.model);
259
+ const mb = index.get(b.model);
260
+ const ca = ma ? contextWindowOf(ma) ?? Number.NEGATIVE_INFINITY : Number.NEGATIVE_INFINITY;
261
+ const cb = mb ? contextWindowOf(mb) ?? Number.NEGATIVE_INFINITY : Number.NEGATIVE_INFINITY;
262
+ return cb - ca;
263
+ }
264
+ const aa = pa?.addedAt ?? "";
265
+ const ab = pb?.addedAt ?? "";
266
+ return aa === ab ? 0 : aa < ab ? 1 : -1;
267
+ });
268
+ return sorted;
269
+ }
270
+ function resolveModelList(id, src) {
271
+ const list = src.get(id);
272
+ if (!list) throw new ModelListError(`unknown model list "${id}"`);
273
+ const entries = resolveEntries(id, src, []);
274
+ return applyOrder(entries, list.order, candidateIndex()).map(
275
+ (entry) => entry.model
276
+ );
277
+ }
278
+ function explainModelList(id, src) {
279
+ const list = src.get(id);
280
+ if (!list) throw new ModelListError(`unknown model list "${id}"`);
281
+ const entries = resolveEntries(id, src, []);
282
+ return applyOrder(entries, list.order, candidateIndex()).map((entry) => ({
283
+ model: entry.model,
284
+ via: entry.via
285
+ }));
286
+ }
287
+
288
+ export { ModelListError, clearModelListCache, explainModelList, inModelList, resolveModelList };
289
+ //# sourceMappingURL=index.mjs.map
290
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lists/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Model lists — named, user-editable selections over the model catalog.\n *\n * A list is data: a set of include selectors (OR), optional exclusions that\n * always win, explicit id pins, and an ordering mode. The selector vocabulary\n * is the existing `AccessTarget` matcher plus the catalog dimensions that have\n * no access-rule target (price, context window, route variant) and list\n * composition.\n *\n * `zero-cost` (the seed list) is the one way \"free\" is expressed in code now:\n * `{ include: [{ kind: \"tag\", value: \"price:zero\" }] }`.\n */\n\nimport type { AccessTarget } from \"../access/types.js\"\nimport { modelMatchesTarget } from \"../access/evaluate.js\"\nimport { isZeroPriced } from \"../enrichment/index.js\"\nimport { resolveContextWindow } from \"../llm/index.js\"\nimport type { ResolvedModel } from \"../registry/index.js\"\nimport { getModel, listModels, resolveAlias } from \"../registry/index.js\"\nimport {\n formatModelRef,\n listRouterLlmRoutes,\n resolveLlmModelRoute,\n stripRouteSuffix,\n tryParseModelRef,\n} from \"../route-identity/index.js\"\n\nexport type ModelSelector =\n | AccessTarget\n | { kind: \"price\"; maxInPer1M?: number; maxOutPer1M?: number }\n | { kind: \"context\"; min: number }\n | { kind: \"variant\"; value: string }\n | { kind: \"list\"; id: string }\n\n/** A named selection over the model catalog. An uncataloged `ids` pin is only\n * removed by a `{ kind: \"model\" }` exclude; no other selector can match an id\n * the catalog does not know. */\nexport interface ModelList {\n id: string\n label?: string\n include?: ModelSelector[]\n exclude?: ModelSelector[]\n ids?: string[]\n order?: \"listed\" | \"cheapest\" | \"largest-context\" | \"newest\"\n rotation?: \"priority\" | \"round-robin\" | \"least-recently-limited\"\n}\n\nexport interface ModelListSource {\n get(id: string): ModelList | undefined\n}\n\nexport class ModelListError extends Error {\n readonly name = \"ModelListError\"\n}\n\n/** Routers whose generated route tables are part of the catalog surface. */\nconst ROUTERS = [\n \"openrouter\",\n \"requesty\",\n \"huggingface\",\n \"opencode\",\n \"opencode-go\",\n] as const\n\n/**\n * Every LLM candidate selectors can match: the registry's own `listModels`\n * view plus each router's generated route table (whose ids, e.g.\n * `opencode/big-pickle`, the bare-id registry deliberately does not carry).\n */\nlet candidateCache: ResolvedModel[] | undefined\nlet candidateIndexCache: Map<string, ResolvedModel> | undefined\nconst subjectIdsCache = new Map<string, string[]>()\n\nfunction candidates(): ResolvedModel[] {\n if (candidateCache) return candidateCache\n const out = listModels({ kind: \"llm\" })\n const seen = new Set(out.map(model => model.id))\n for (const router of ROUTERS) {\n for (const route of listRouterLlmRoutes(router)) {\n const id = formatModelRef(route.ref)\n if (seen.has(id)) continue\n seen.add(id)\n out.push({\n kind: \"llm\",\n id,\n canonicalId: route.canonicalProductId,\n pricing: route.pricing,\n provider: route.pricing.provider,\n })\n }\n }\n candidateCache = out\n return out\n}\n\n/** Test/consumer helper after an overlay or route registration changes. */\nexport function clearModelListCache(): void {\n candidateCache = undefined\n candidateIndexCache = undefined\n subjectIdsCache.clear()\n}\n\nfunction selectorLabel(selector: ModelSelector): string {\n switch (selector.kind) {\n case \"model\":\n return `model:${selector.id}`\n case \"price\":\n return `price:${selector.maxInPer1M ?? \"*\"}/${selector.maxOutPer1M ?? \"*\"}`\n case \"context\":\n return `context:>=${selector.min}`\n case \"variant\":\n return `variant:${selector.value}`\n case \"list\":\n return `list:${selector.id}`\n default:\n return `${selector.kind}:${selector.value}`\n }\n}\n\nfunction isListSelector(\n selector: ModelSelector,\n): selector is Extract<ModelSelector, { kind: \"list\" }> {\n return selector.kind === \"list\"\n}\n\nfunction contextWindowOf(model: ResolvedModel): number | undefined {\n if (model.kind !== \"llm\") return undefined\n return (\n resolveContextWindow(model.id)?.contextWindow ??\n resolveContextWindow(model.canonicalId)?.contextWindow\n )\n}\n\nfunction variantOf(id: string): string | undefined {\n const ref = tryParseModelRef(id)\n return ref?.variant\n}\n\n/**\n * Does a selector match one model? `model` is the catalog candidate when one\n * exists; `rawId` is the id being tested (a route-suffixed or bare spelling\n * may differ from the catalog key). Uncataloged ids only match through an\n * explicit `ids` pin, handled by the caller.\n */\nfunction selectorMatches(\n selector: ModelSelector,\n model: ResolvedModel | undefined,\n rawId: string,\n src: ModelListSource,\n stack: string[],\n): boolean {\n if (isListSelector(selector)) {\n return inList(selector.id, rawId, src, stack)\n }\n switch (selector.kind) {\n case \"variant\":\n return variantOf(rawId) === selector.value ||\n (model !== undefined && variantOf(model.id) === selector.value)\n case \"price\": {\n const pricing = model?.kind === \"llm\" ? model.pricing : undefined\n if (!pricing) return false\n if (\n selector.maxInPer1M !== undefined &&\n pricing.inputPer1M > selector.maxInPer1M\n ) {\n return false\n }\n if (\n selector.maxOutPer1M !== undefined &&\n pricing.outputPer1M > selector.maxOutPer1M\n ) {\n return false\n }\n return true\n }\n case \"context\": {\n if (!model) return false\n const window = contextWindowOf(model)\n return window !== undefined && window >= selector.min\n }\n default:\n return model !== undefined && modelMatchesTarget(selector, model)\n }\n}\n\n/** Exclusion is a negation: an explicit `model` target must also be able to\n * remove an uncataloged `ids` pin, which no include selector can match. */\nfunction excludeMatches(\n selector: ModelSelector,\n model: ResolvedModel | undefined,\n rawId: string,\n src: ModelListSource,\n stack: string[],\n): boolean {\n if (\n selector.kind === \"model\" &&\n pinsMatch(selector.id, rawId)\n ) {\n return true\n }\n return selectorMatches(selector, model, rawId, src, stack)\n}\n\nfunction candidateIndex(): Map<string, ResolvedModel> {\n if (candidateIndexCache) return candidateIndexCache\n const index = new Map<string, ResolvedModel>()\n for (const model of candidates()) index.set(model.id, model)\n candidateIndexCache = index\n return index\n}\n\n/**\n * Normalize a model id to the catalog spellings it may match. A trailing\n * `@<route>` is stripped; the registry and the route resolver get a chance;\n * and a bare id (`big-pickle`) also matches catalog ids whose last `/`\n * segment equals it (`opencode/big-pickle`).\n */\nfunction subjectIds(raw: string): string[] {\n const cached = subjectIdsCache.get(raw)\n if (cached) return cached\n const stripped = stripRouteSuffix(raw)\n const out = new Set<string>([raw, stripped])\n const consider = (id: string): void => {\n out.add(id)\n const model = getModel(id)\n if (model) {\n out.add(model.id)\n if (model.kind === \"llm\") out.add(model.canonicalId)\n }\n out.add(resolveAlias(id))\n try {\n const route = resolveLlmModelRoute(id)\n if (route) {\n out.add(formatModelRef(route.ref))\n out.add(`${route.vendor}/${route.product}`)\n }\n } catch {\n // Not a canonical `vendor/product` ref (e.g. an internal `~vendor/...`\n // spelling). It can still match through `ids` or a bare-id key.\n }\n }\n consider(stripped)\n if (!stripped.includes(\"/\")) {\n const bare = stripped.split(\":\")[0] ?? stripped\n for (const model of candidates()) {\n const segment = model.id.split(\"/\").pop()?.split(\":\")[0]\n if (segment === bare) out.add(model.id)\n }\n }\n const result = [...out]\n subjectIdsCache.set(raw, result)\n return result\n}\n\nfunction pinsMatch(pin: string, id: string): boolean {\n if (pin === id) return true\n const pinStripped = stripRouteSuffix(pin)\n const idStripped = stripRouteSuffix(id)\n return pin === idStripped || pinStripped === id || pinStripped === idStripped\n}\n\nfunction listContains(\n list: ModelList,\n rawId: string,\n src: ModelListSource,\n stack: string[],\n): boolean {\n const index = candidateIndex()\n const model = index.get(rawId) ?? index.get(stripRouteSuffix(rawId))\n for (const selector of list.exclude ?? []) {\n if (excludeMatches(selector, model, rawId, src, stack)) return false\n }\n if ((list.ids ?? []).some(pin => pinsMatch(pin, rawId))) return true\n return (list.include ?? []).some(selector =>\n selectorMatches(selector, model, rawId, src, stack),\n )\n}\n\n/** Membership of ONE normalized id in a list (no subject expansion). */\nfunction inList(\n listId: string,\n rawId: string,\n src: ModelListSource,\n stack: string[],\n): boolean {\n const list = src.get(listId)\n if (!list) throw new ModelListError(`unknown model list \"${listId}\"`)\n if (stack.includes(listId)) {\n throw new ModelListError(\n `model list cycle: ${[...stack, listId].join(\" -> \")}`,\n )\n }\n return listContains(list, rawId, src, [...stack, listId])\n}\n\n/** Membership without full expansion; uncataloged ids match only via `ids`. */\nexport function inModelList(\n model: string,\n id: string,\n src: ModelListSource,\n): boolean {\n return subjectIds(model).some(candidate =>\n inList(id, candidate, src, []),\n )\n}\n\ninterface ResolvedEntry {\n model: string\n via: string\n}\n\nfunction insert(\n entries: Map<string, ResolvedEntry>,\n model: string,\n via: string,\n): void {\n if (!entries.has(model)) entries.set(model, { model, via })\n}\n\nfunction resolveEntries(\n id: string,\n src: ModelListSource,\n stack: string[],\n): ResolvedEntry[] {\n const list = src.get(id)\n if (!list) throw new ModelListError(`unknown model list \"${id}\"`)\n if (stack.includes(id)) {\n throw new ModelListError(`model list cycle: ${[...stack, id].join(\" -> \")}`)\n }\n const nextStack = [...stack, id]\n const entries = new Map<string, ResolvedEntry>()\n const index = candidateIndex()\n const all = candidates()\n\n for (const selector of list.include ?? []) {\n if (isListSelector(selector)) {\n for (const entry of resolveEntries(selector.id, src, nextStack)) {\n insert(entries, entry.model, `list:${selector.id}`)\n }\n continue\n }\n for (const model of all) {\n if (selectorMatches(selector, model, model.id, src, nextStack)) {\n insert(entries, model.id, selectorLabel(selector))\n }\n }\n }\n for (const pin of list.ids ?? []) insert(entries, pin, \"ids\")\n\n for (const selector of list.exclude ?? []) {\n if (isListSelector(selector)) {\n for (const entry of resolveEntries(selector.id, src, nextStack)) {\n entries.delete(entry.model)\n }\n continue\n }\n for (const model of all) {\n if (selectorMatches(selector, model, model.id, src, nextStack)) {\n entries.delete(model.id)\n }\n }\n for (const key of [...entries.keys()]) {\n if (excludeMatches(selector, index.get(key), key, src, nextStack)) {\n entries.delete(key)\n }\n }\n }\n\n return [...entries.values()]\n}\n\nfunction applyOrder(\n entries: ResolvedEntry[],\n order: ModelList[\"order\"],\n index: Map<string, ResolvedModel>,\n): ResolvedEntry[] {\n if (!order || order === \"listed\" || entries.length === 0) return entries\n const pricingOf = (entry: ResolvedEntry) => {\n const model = index.get(entry.model)\n return model?.kind === \"llm\" ? model.pricing : undefined\n }\n const sorted = [...entries]\n sorted.sort((a, b) => {\n const pa = pricingOf(a)\n const pb = pricingOf(b)\n if (order === \"cheapest\") {\n const ca = pa ? pa.inputPer1M + pa.outputPer1M : Number.POSITIVE_INFINITY\n const cb = pb ? pb.inputPer1M + pb.outputPer1M : Number.POSITIVE_INFINITY\n return ca - cb\n }\n if (order === \"largest-context\") {\n const ma = index.get(a.model)\n const mb = index.get(b.model)\n const ca = ma ? contextWindowOf(ma) ?? Number.NEGATIVE_INFINITY : Number.NEGATIVE_INFINITY\n const cb = mb ? contextWindowOf(mb) ?? Number.NEGATIVE_INFINITY : Number.NEGATIVE_INFINITY\n return cb - ca\n }\n // newest — a missing `addedAt` sorts last.\n const aa = pa?.addedAt ?? \"\"\n const ab = pb?.addedAt ?? \"\"\n return aa === ab ? 0 : aa < ab ? 1 : -1\n })\n return sorted\n}\n\n/** Ordered, de-duplicated model ids. Throws ModelListError on unknown id or cycle. */\nexport function resolveModelList(id: string, src: ModelListSource): string[] {\n const list = src.get(id)\n if (!list) throw new ModelListError(`unknown model list \"${id}\"`)\n const entries = resolveEntries(id, src, [])\n return applyOrder(entries, list.order, candidateIndex()).map(\n entry => entry.model,\n )\n}\n\n/** Explain: per model, which selector or pin included it. */\nexport function explainModelList(\n id: string,\n src: ModelListSource,\n): Array<{ model: string; via: string }> {\n const list = src.get(id)\n if (!list) throw new ModelListError(`unknown model list \"${id}\"`)\n const entries = resolveEntries(id, src, [])\n return applyOrder(entries, list.order, candidateIndex()).map(entry => ({\n model: entry.model,\n via: entry.via,\n }))\n}\n\n/** True iff the model is in a zero-priced list entry; re-exported for convenience. */\nexport { isZeroPriced }\n"]}
@@ -1,4 +1,4 @@
1
- export { C as CacheStats, f as CalculateLLMCreditCostOptions, g as ContextWindowEntry, D as DEFAULT_PRICING, K as KnownLlmId, a as LLMCreditCostResult, L as LLMPricing, b as LLMPricingTier, c as LLMUsageBreakdown, d as LLM_PRICING_CATALOG, h as LlmModelAlias, i as LlmModelId, M as MODEL_ALIASES, j as ModelRoute, e as calculateLLMCreditCost, k as getCacheStats, l as getModelProvider, m as isKnownLlmId, n as listNativeModelIds, o as listUnpricedKnownLlmIds, p as resolveAlias, q as resolveContextWindow, t as resolveModelRoute, r as resolvePricing, u as resolvePricingExact, s as selectPricingTier, v as splitContextWindowHint } from '../catalog-DRGEICKV.js';
1
+ export { C as CacheStats, f as CalculateLLMCreditCostOptions, g as ContextWindowEntry, D as DEFAULT_PRICING, K as KnownLlmId, a as LLMCreditCostResult, L as LLMPricing, b as LLMPricingTier, c as LLMUsageBreakdown, d as LLM_PRICING_CATALOG, h as LlmModelAlias, i as LlmModelId, M as MODEL_ALIASES, j as ModelRoute, e as calculateLLMCreditCost, k as getCacheStats, l as getModelProvider, m as isKnownLlmId, n as listNativeModelIds, o as listUnpricedKnownLlmIds, p as resolveAlias, q as resolveContextWindow, t as resolveModelRoute, r as resolvePricing, u as resolvePricingExact, s as selectPricingTier, v as splitContextWindowHint } from '../catalog-BB0uDJh-.js';
2
2
  export { D as DEFAULT_ANTHROPIC_MODEL, L as LLM_TIERS, a as LlmTierName, O as OPERATOR_AGENT_MODELS, b as OPERATOR_DEFAULT_GEMINI, c as OPERATOR_DEFAULT_PREMIUM, d as OPERATOR_DEFAULT_STANDARD, e as OperatorAgentModel, W as WORKFLOW_FAST_MODEL, f as WORKFLOW_PREMIUM_MODEL, g as WORKFLOW_TINY_MODEL } from '../defaults-BDkNRPK8.js';
3
3
  import '../base-BaiI72Da.js';
4
4
  import 'zod';
@@ -1,5 +1,5 @@
1
- export { DEFAULT_ANTHROPIC_MODEL, LLM_TIERS, OPERATOR_AGENT_MODELS, OPERATOR_DEFAULT_GEMINI, OPERATOR_DEFAULT_PREMIUM, OPERATOR_DEFAULT_STANDARD, WORKFLOW_FAST_MODEL, WORKFLOW_PREMIUM_MODEL, WORKFLOW_TINY_MODEL, formatTokens, listOpencodeAnthropicModelRefs, listOpencodeModelRefs } from '../chunk-UOOTUH6N.mjs';
2
- export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, getCacheStats, getModelProvider, isKnownLlmId, listNativeModelIds, listUnpricedKnownLlmIds, resolveAlias, resolveContextWindow, resolveModelRoute, resolvePricing, resolvePricingExact, selectPricingTier, splitContextWindowHint } from '../chunk-TVXNRUJM.mjs';
1
+ export { DEFAULT_ANTHROPIC_MODEL, LLM_TIERS, OPERATOR_AGENT_MODELS, OPERATOR_DEFAULT_GEMINI, OPERATOR_DEFAULT_PREMIUM, OPERATOR_DEFAULT_STANDARD, WORKFLOW_FAST_MODEL, WORKFLOW_PREMIUM_MODEL, WORKFLOW_TINY_MODEL, formatTokens, listOpencodeAnthropicModelRefs, listOpencodeModelRefs } from '../chunk-IHU6XTXS.mjs';
2
+ export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, getCacheStats, getModelProvider, isKnownLlmId, listNativeModelIds, listUnpricedKnownLlmIds, resolveAlias, resolveContextWindow, resolveModelRoute, resolvePricing, resolvePricingExact, selectPricingTier, splitContextWindowHint } from '../chunk-MZ23K5W6.mjs';
3
3
  import '../chunk-QHELXPSL.mjs';
4
4
  //# sourceMappingURL=index.mjs.map
5
5
  //# sourceMappingURL=index.mjs.map
@@ -1,4 +1,4 @@
1
- import { L as LLMPricing } from '../catalog-DRGEICKV.js';
1
+ import { L as LLMPricing } from '../catalog-BB0uDJh-.js';
2
2
  import { ImageModelDefinition } from '../image/index.js';
3
3
  import { VideoModelDefinition } from '../video/index.js';
4
4
  import { AudioModelDefinition } from '../audio/index.js';
@@ -1,11 +1,118 @@
1
- import '../evaluate-B-irutMW.js';
2
- import '../base-BaiI72Da.js';
3
- export { A as AvailableConnector, a as AvailableModel, b as AvailableModelCapabilities, c as AvailableModelsActor, d as AvailableModelsResponse, L as ListAvailableModelsParams, P as PRICE_TIER_NAMES, j as PRICE_TIER_SLOTS, k as priceTierBar, l as priceTierName } from '../index-kbLggJk1.js';
4
- import '../index-VuUTv1ft.js';
5
- import '../catalog-DRGEICKV.js';
1
+ import { A as AccessDecision } from '../evaluate-BjSlZsJf.js';
2
+ import { M as ModelKind } from '../base-BaiI72Da.js';
3
+ import { M as ModelEnrichment } from '../index-DetGJJ-F.js';
4
+ import '../index-D8FWHlom.js';
5
+ import '../catalog-BB0uDJh-.js';
6
6
  import '../image/index.js';
7
7
  import '../video/index.js';
8
8
  import '../audio/index.js';
9
9
  import '../audio-Do2j3wDC.js';
10
10
  import 'zod';
11
11
  import '../schema/voice.js';
12
+ import '../types-DMzMWJeJ.js';
13
+
14
+ /**
15
+ * Picker subpath — wire shapes returned by the per-app
16
+ * `GET /models/available` route. Single source of truth shared by:
17
+ * - the server-side helper (an app-side model-access helper)
18
+ * - the per-app SDK clients (e.g. an app SDK client)
19
+ * - the cross-app picker hook (an app picker hook)
20
+ *
21
+ * Without this single source the hook + SDK previously drifted from
22
+ * the API contract and a fetcher in the app silently kept calling
23
+ * with a stale auth pattern after the cookie-auth migration.
24
+ */
25
+
26
+ interface AvailableModelCapabilities {
27
+ generate?: boolean;
28
+ edit?: boolean;
29
+ upscale?: boolean;
30
+ textToVideo?: boolean;
31
+ imageToVideo?: boolean;
32
+ audio?: boolean;
33
+ subjectReference?: boolean;
34
+ tts?: boolean;
35
+ stt?: boolean;
36
+ s2s?: boolean;
37
+ }
38
+ interface AvailableModel {
39
+ id: string;
40
+ /** Canonical model id (LLM aliases collapse here). */
41
+ canonicalId: string;
42
+ /**
43
+ * Priced model kind. Typed `ModelKind` (not `CatalogKind`) on purpose: the
44
+ * picker never surfaces `voice` rows as `AvailableModel` — voices reach the
45
+ * UI through a separate path — so `voice` is intentionally out of range here.
46
+ */
47
+ kind: ModelKind;
48
+ displayName: string;
49
+ description: string;
50
+ enrichment: ModelEnrichment;
51
+ decision: AccessDecision;
52
+ capabilities: AvailableModelCapabilities;
53
+ /** Recommended pricing display (per provider unit). */
54
+ pricingHint?: string;
55
+ /**
56
+ * Audio models only: cost normalized to **per minute of speech**, the
57
+ * intuitive unit for the voice picker. TTS (billed per 1k chars) is
58
+ * converted via an assumed speaking rate; per-minute models pass through.
59
+ */
60
+ voiceHint?: string;
61
+ /**
62
+ * Relative price gauge level (1..{@link PRICE_TIER_SLOTS}) from
63
+ * `priceTierForModel` — the visual "price mostly" indicator the picker
64
+ * renders as a segmented bar instead of a raw number. 0 when unknown.
65
+ */
66
+ priceTier?: number;
67
+ /** Localized-agnostic tier name for `priceTier` (e.g. `"High"`). */
68
+ priceTierName?: string;
69
+ }
70
+ interface AvailableConnector {
71
+ id: string;
72
+ name: string;
73
+ /** Whether the actor's guild/workspace has a connected credential for this provider. */
74
+ byokAvailable: boolean;
75
+ models: AvailableModel[];
76
+ }
77
+ /** Number of segments in the price gauge. */
78
+ declare const PRICE_TIER_SLOTS = 5;
79
+ /**
80
+ * Display names for levels 1..{@link PRICE_TIER_SLOTS}, ascending price. Kept
81
+ * as brand tokens (not localized) so the gauge reads the same everywhere.
82
+ */
83
+ declare const PRICE_TIER_NAMES: readonly ["Low", "Medium", "High", "Max", "Ultra"];
84
+ /** Name for a gauge level (1-based); empty string when out of range. */
85
+ declare function priceTierName(level: number): string;
86
+ /**
87
+ * Unicode price gauge (e.g. `▰▰▱▱▱`) for text-only surfaces (WhatsApp, logs).
88
+ * Rich UIs read {@link AvailableModel.priceTier} and render styled segments.
89
+ */
90
+ declare function priceTierBar(level: number, slots?: number): string;
91
+ interface AvailableModelsActor {
92
+ appId: string;
93
+ userId: string;
94
+ tier?: string;
95
+ guildId?: string;
96
+ }
97
+ interface AvailableModelsResponse {
98
+ success: true;
99
+ actor: AvailableModelsActor;
100
+ connectors: AvailableConnector[];
101
+ }
102
+ interface ListAvailableModelsParams {
103
+ /** Restrict to one or more kinds. Empty = all kinds. */
104
+ kind?: ModelKind | ModelKind[];
105
+ /** Guild scope — joins guild-level connectors for BYOK badges. */
106
+ guildId?: string;
107
+ /** Include rules-blocked models (decision.allowed=false). Default true. */
108
+ includeBlocked?: boolean;
109
+ /** Include catalog entries with agentVisible=false. Default false. */
110
+ includeHidden?: boolean;
111
+ /**
112
+ * Curation surface-profile id (`voice-s2s`, `images`, …) the app exposes.
113
+ * Resolved server-side via `getSurfaceProfile`. Omitted = full catalog.
114
+ */
115
+ surface?: string;
116
+ }
117
+
118
+ export { type AvailableConnector, type AvailableModel, type AvailableModelCapabilities, type AvailableModelsActor, type AvailableModelsResponse, type ListAvailableModelsParams, PRICE_TIER_NAMES, PRICE_TIER_SLOTS, priceTierBar, priceTierName };
@@ -1,4 +1,4 @@
1
- import { L as LLMPricing } from '../catalog-DRGEICKV.js';
1
+ import { L as LLMPricing } from '../catalog-BB0uDJh-.js';
2
2
  import '../base-BaiI72Da.js';
3
3
  import 'zod';
4
4
 
@@ -1,6 +1,6 @@
1
- export { InvalidModelRefError, OPENROUTER_VARIANTS, clearCustomRoutes, diagnoseModelRef, formatModelRef, isModelRefString, listRouterLlmRoutes, parseModelRef, registerCustomRoute, resolveCustomRoute, resolveLlmModelRoute, stripAnthropicNativeVendor, stripFixedNativeVendor, stripRouteSuffix, tryParseModelRef } from '../chunk-ALUIW3QO.mjs';
1
+ export { InvalidModelRefError, OPENROUTER_VARIANTS, clearCustomRoutes, diagnoseModelRef, formatModelRef, isModelRefString, listRouterLlmRoutes, parseModelRef, registerCustomRoute, resolveCustomRoute, resolveLlmModelRoute, stripAnthropicNativeVendor, stripFixedNativeVendor, stripRouteSuffix, tryParseModelRef } from '../chunk-BXTZ2EDE.mjs';
2
2
  import '../chunk-WG4F6IRS.mjs';
3
- import '../chunk-TVXNRUJM.mjs';
3
+ import '../chunk-MZ23K5W6.mjs';
4
4
  import '../chunk-QHELXPSL.mjs';
5
5
  //# sourceMappingURL=index.mjs.map
6
6
  //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,50 @@
1
+ import { M as ModelKind } from './base-BaiI72Da.js';
2
+
3
+ /**
4
+ * Access control types — workspace-override rules + app scope.
5
+ *
6
+ * v1 ships the evaluator + types; the DB-backed `model_access_rules`
7
+ * table follows in v2 (the MCP gen layer reads rows and threads them
8
+ * through `evaluateAccess` per workspace).
9
+ */
10
+
11
+ type AccessEffect = "allow" | "block";
12
+ type AccessTarget = {
13
+ kind: "model";
14
+ id: string;
15
+ } | {
16
+ kind: "tag";
17
+ value: string;
18
+ } | {
19
+ kind: "provider";
20
+ value: string;
21
+ }
22
+ /**
23
+ * `kind: "priceTier"` is the persisted DB discriminator string for
24
+ * catalog-price-tier targets (`low | mid | high | premium`). The
25
+ * conceptual name is `catalogPriceTier`; the literal stays `priceTier`
26
+ * to avoid breaking existing rows in `*_model_access_rules` tables.
27
+ */
28
+ | {
29
+ kind: "priceTier";
30
+ value: "low" | "mid" | "high" | "premium";
31
+ } | {
32
+ kind: "kind";
33
+ value: ModelKind;
34
+ };
35
+ interface AccessRule {
36
+ effect: AccessEffect;
37
+ target: AccessTarget;
38
+ /** Audit reason; surfaced in decision.reason. */
39
+ reason?: string;
40
+ }
41
+ /**
42
+ * Per-product opt-in: the app declares which kinds it surfaces. Lets
43
+ * one app hide LLMs, another hide video, etc. Empty `kinds` means the app
44
+ * does not constrain by kind (admin / catalog-browser scope).
45
+ */
46
+ interface AppScope {
47
+ kinds: ModelKind[];
48
+ }
49
+
50
+ export type { AccessTarget as A, AppScope as a, AccessRule as b, AccessEffect as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/model-catalog",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "description": "Unified, dependency-light model catalog: LLM, image, video, audio entries + cost dispatcher + picker. Zod-only; the OSS core that @agstudio/model-catalog layers billing/access/BYOK on top of.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -102,6 +102,11 @@
102
102
  "import": "./dist/access/index.mjs",
103
103
  "default": "./dist/access/index.mjs"
104
104
  },
105
+ "./lists": {
106
+ "types": "./dist/lists/index.d.ts",
107
+ "import": "./dist/lists/index.mjs",
108
+ "default": "./dist/lists/index.mjs"
109
+ },
105
110
  "./picker": {
106
111
  "types": "./dist/picker/index.d.ts",
107
112
  "import": "./dist/picker/index.mjs",
@@ -126,8 +131,8 @@
126
131
  "tsup": "^8.5.1",
127
132
  "typescript": "^5.9.3",
128
133
  "vitest": "^3.2.7",
129
- "@agentproto/provider-presets": "0.7.1",
130
- "@agentproto/tooling": "0.1.0"
134
+ "@agentproto/tooling": "0.1.0",
135
+ "@agentproto/provider-presets": "0.7.2"
131
136
  },
132
137
  "engines": {
133
138
  "node": ">=20.9.0"