@codelia/model-metadata 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ModelMetadataServiceImpl: () => ModelMetadataServiceImpl
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/sources/modeldev.ts
38
+ var import_promises = require("fs/promises");
39
+ var import_node_path = __toESM(require("path"), 1);
40
+ var import_storage = require("@codelia/storage");
41
+ var import_zod = require("zod");
42
+ var modelResourceUrl = "https://models.dev/api.json";
43
+ var CACHE_FILENAME = "models.dev.json";
44
+ var CACHE_VERSION = 1;
45
+ var DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
46
+ var wireModelDevModelSchema = import_zod.z.object({
47
+ id: import_zod.z.string(),
48
+ name: import_zod.z.string(),
49
+ family: import_zod.z.string().optional(),
50
+ attachment: import_zod.z.boolean().optional(),
51
+ reasoning: import_zod.z.boolean().optional(),
52
+ tool_call: import_zod.z.boolean().optional(),
53
+ structured_output: import_zod.z.boolean().optional(),
54
+ temperature: import_zod.z.boolean().optional(),
55
+ knowledge: import_zod.z.string().optional(),
56
+ release_date: import_zod.z.string().optional(),
57
+ last_updated: import_zod.z.string().optional(),
58
+ open_weights: import_zod.z.boolean().optional(),
59
+ cost: import_zod.z.object({
60
+ input: import_zod.z.number().optional(),
61
+ output: import_zod.z.number().optional(),
62
+ reasoning: import_zod.z.number().optional(),
63
+ cache_read: import_zod.z.number().optional(),
64
+ cache_write: import_zod.z.number().optional(),
65
+ input_audio: import_zod.z.number().optional(),
66
+ output_audio: import_zod.z.number().optional()
67
+ }).loose().optional(),
68
+ limit: import_zod.z.object({
69
+ context: import_zod.z.number().optional(),
70
+ input: import_zod.z.number().optional(),
71
+ output: import_zod.z.number().optional()
72
+ }).loose().optional(),
73
+ modalities: import_zod.z.object({
74
+ input: import_zod.z.array(import_zod.z.string()).optional(),
75
+ output: import_zod.z.array(import_zod.z.string()).optional()
76
+ }).loose().optional(),
77
+ interleaved: import_zod.z.union([
78
+ import_zod.z.boolean(),
79
+ import_zod.z.object({
80
+ field: import_zod.z.string().optional()
81
+ }).loose()
82
+ ]).optional()
83
+ }).loose();
84
+ var wireModelDevModelsSchema = import_zod.z.union([
85
+ import_zod.z.array(wireModelDevModelSchema),
86
+ import_zod.z.record(import_zod.z.string(), wireModelDevModelSchema)
87
+ ]);
88
+ var wireModelDevProviderSchema = import_zod.z.object({
89
+ id: import_zod.z.string().optional(),
90
+ name: import_zod.z.string().optional(),
91
+ api: import_zod.z.string().optional(),
92
+ doc: import_zod.z.string().optional(),
93
+ env: import_zod.z.array(import_zod.z.string()).optional(),
94
+ npm: import_zod.z.string().optional(),
95
+ models: import_zod.z.record(import_zod.z.string(), wireModelDevModelSchema).optional()
96
+ }).loose();
97
+ var wireModelDevProvidersSchema = import_zod.z.record(
98
+ import_zod.z.string(),
99
+ wireModelDevProviderSchema
100
+ );
101
+ var ModelDevSource = class {
102
+ loaded = false;
103
+ models = {};
104
+ cacheTtlMs;
105
+ cachePath;
106
+ constructor(options = {}) {
107
+ this.cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
108
+ const storagePaths = options.storagePathService ? options.storagePathService.resolvePaths({
109
+ rootOverride: options.storageRoot
110
+ }) : (0, import_storage.resolveStoragePaths)({ rootOverride: options.storageRoot });
111
+ this.cachePath = options.cachePath ?? import_node_path.default.join(storagePaths.cacheDir, CACHE_FILENAME);
112
+ }
113
+ async loadModelMetadata(options = {}) {
114
+ this.loaded = false;
115
+ this.models = {};
116
+ if (!options.forceRefresh) {
117
+ const cached = await readCacheFile(this.cachePath);
118
+ if (cached && !isCacheExpired(cached.expiresAt)) {
119
+ this.models = cached.entries;
120
+ this.loaded = true;
121
+ return;
122
+ }
123
+ }
124
+ const response = await fetch(modelResourceUrl);
125
+ const data = await response.json();
126
+ const providersResult = wireModelDevProvidersSchema.safeParse(data);
127
+ if (providersResult.success) {
128
+ this.models = buildEntriesFromProviders(providersResult.data);
129
+ }
130
+ let hasEntries = Object.keys(this.models).length > 0;
131
+ if (!hasEntries) {
132
+ this.models = buildEntriesFromLegacyPayload(data);
133
+ }
134
+ hasEntries = Object.keys(this.models).length > 0;
135
+ if (!hasEntries) {
136
+ throw new Error("ModelDevSource: empty metadata payload");
137
+ }
138
+ await writeCacheFile(this.cachePath, {
139
+ version: CACHE_VERSION,
140
+ cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
141
+ expiresAt: new Date(Date.now() + this.cacheTtlMs).toISOString(),
142
+ entries: this.models
143
+ }).catch(() => void 0);
144
+ this.loaded = true;
145
+ }
146
+ async getModelEntry(provider, model) {
147
+ if (!this.loaded) {
148
+ await this.loadModelMetadata();
149
+ }
150
+ return this.models[provider]?.[model] || null;
151
+ }
152
+ async getModelEntries(provider) {
153
+ if (!this.loaded) {
154
+ await this.loadModelMetadata();
155
+ }
156
+ return this.models[provider] ? Object.values(this.models[provider]) : null;
157
+ }
158
+ async getAllModelEntries() {
159
+ if (!this.loaded) {
160
+ await this.loadModelMetadata();
161
+ }
162
+ return this.models;
163
+ }
164
+ };
165
+ function buildEntriesFromProviders(providers) {
166
+ const entries = {};
167
+ for (const [providerId, provider] of Object.entries(providers)) {
168
+ const models = provider.models ? Object.values(provider.models) : [];
169
+ if (models.length === 0) continue;
170
+ entries[providerId] = buildEntriesForProvider(providerId, models);
171
+ }
172
+ return entries;
173
+ }
174
+ function buildEntriesFromLegacyPayload(data) {
175
+ let provider = "unknown";
176
+ if (data.provider && typeof data.provider === "object") {
177
+ const name = data.provider.name;
178
+ if (name) provider = name;
179
+ }
180
+ const modelsResult = wireModelDevModelsSchema.safeParse(
181
+ data.models
182
+ );
183
+ if (!modelsResult.success) return {};
184
+ const models = Array.isArray(modelsResult.data) ? modelsResult.data : Object.values(modelsResult.data);
185
+ if (models.length === 0) return {};
186
+ return { [provider]: buildEntriesForProvider(provider, models) };
187
+ }
188
+ function buildEntriesForProvider(provider, models) {
189
+ const entries = {};
190
+ for (const model of models) {
191
+ entries[model.id] = {
192
+ provider,
193
+ modelId: model.id,
194
+ cost: {
195
+ input: model.cost?.input,
196
+ output: model.cost?.output,
197
+ reasoning: model.cost?.reasoning,
198
+ cacheRead: model.cost?.cache_read,
199
+ cacheWrite: model.cost?.cache_write,
200
+ inputAudio: model.cost?.input_audio,
201
+ outputAudio: model.cost?.output_audio
202
+ },
203
+ limits: {
204
+ contextWindow: model.limit?.context,
205
+ inputTokens: model.limit?.input,
206
+ outputTokens: model.limit?.output
207
+ }
208
+ };
209
+ }
210
+ return entries;
211
+ }
212
+ async function readCacheFile(cachePath) {
213
+ const contents = await (0, import_promises.readFile)(cachePath, "utf8").catch(() => null);
214
+ if (!contents) return null;
215
+ const parsed = safeJsonParse(contents);
216
+ if (!parsed || !isCacheFile(parsed)) return null;
217
+ return parsed;
218
+ }
219
+ async function writeCacheFile(cachePath, cache) {
220
+ await ensureDir(import_node_path.default.dirname(cachePath));
221
+ await (0, import_promises.writeFile)(cachePath, JSON.stringify(cache), "utf8");
222
+ }
223
+ function isCacheExpired(expiresAt) {
224
+ const timestamp = Date.parse(expiresAt);
225
+ if (Number.isNaN(timestamp)) return true;
226
+ return timestamp <= Date.now();
227
+ }
228
+ function isCacheFile(value) {
229
+ if (!value || typeof value !== "object") return false;
230
+ const file = value;
231
+ if (file.version !== CACHE_VERSION) return false;
232
+ if (typeof file.cachedAt !== "string") return false;
233
+ if (typeof file.expiresAt !== "string") return false;
234
+ if (!file.entries || typeof file.entries !== "object") return false;
235
+ return true;
236
+ }
237
+ function safeJsonParse(value) {
238
+ try {
239
+ return JSON.parse(value);
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+ async function ensureDir(dir) {
245
+ await (0, import_promises.mkdir)(dir, { recursive: true });
246
+ }
247
+
248
+ // src/service.ts
249
+ var ModelMetadataServiceImpl = class {
250
+ modelDevSource;
251
+ sources;
252
+ constructor(options = {}) {
253
+ this.modelDevSource = new ModelDevSource(options);
254
+ this.sources = [this.modelDevSource];
255
+ }
256
+ async refreshAllModelEntries() {
257
+ await this.modelDevSource.loadModelMetadata({ forceRefresh: true });
258
+ return this.getAllModelEntries();
259
+ }
260
+ async getModelEntry(provider, model) {
261
+ for (const source of this.sources) {
262
+ const entry = await source.getModelEntry(provider, model);
263
+ if (entry) {
264
+ return entry;
265
+ }
266
+ }
267
+ return null;
268
+ }
269
+ async getModelEntries(provider) {
270
+ for (const source of this.sources) {
271
+ const entries = await source.getModelEntries(provider);
272
+ if (entries) {
273
+ return entries;
274
+ }
275
+ }
276
+ return null;
277
+ }
278
+ async getAllModelEntries() {
279
+ const entries = {};
280
+ for (const source of this.sources) {
281
+ const sourceEntries = await source.getAllModelEntries();
282
+ Object.assign(entries, sourceEntries);
283
+ }
284
+ return entries;
285
+ }
286
+ };
287
+ // Annotate the CommonJS export names for ESM import in node:
288
+ 0 && (module.exports = {
289
+ ModelMetadataServiceImpl
290
+ });
@@ -0,0 +1,27 @@
1
+ import { ModelEntry, StoragePathService, ModelMetadataService } from '@codelia/core';
2
+ export { ModelCost, ModelEntry, ModelLimits, ModelMetadataIndex } from '@codelia/core';
3
+
4
+ type ModelMetadataSource = {
5
+ getModelEntry(provider: string, modelId: string): Promise<ModelEntry | null>;
6
+ getModelEntries(provider: string): Promise<ModelEntry[] | null>;
7
+ getAllModelEntries(): Promise<Record<string, Record<string, ModelEntry>>>;
8
+ };
9
+
10
+ type ModelDevSourceOptions = {
11
+ cacheTtlMs?: number;
12
+ cachePath?: string;
13
+ storageRoot?: string;
14
+ storagePathService?: StoragePathService;
15
+ };
16
+
17
+ declare class ModelMetadataServiceImpl implements ModelMetadataService {
18
+ private readonly modelDevSource;
19
+ private readonly sources;
20
+ constructor(options?: ModelDevSourceOptions);
21
+ refreshAllModelEntries(): Promise<Record<string, Record<string, ModelEntry>>>;
22
+ getModelEntry(provider: string, model: string): Promise<ModelEntry | null>;
23
+ getModelEntries(provider: string): Promise<ModelEntry[] | null>;
24
+ getAllModelEntries(): Promise<Record<string, Record<string, ModelEntry>>>;
25
+ }
26
+
27
+ export { type ModelDevSourceOptions, ModelMetadataServiceImpl, type ModelMetadataSource };
@@ -0,0 +1,27 @@
1
+ import { ModelEntry, StoragePathService, ModelMetadataService } from '@codelia/core';
2
+ export { ModelCost, ModelEntry, ModelLimits, ModelMetadataIndex } from '@codelia/core';
3
+
4
+ type ModelMetadataSource = {
5
+ getModelEntry(provider: string, modelId: string): Promise<ModelEntry | null>;
6
+ getModelEntries(provider: string): Promise<ModelEntry[] | null>;
7
+ getAllModelEntries(): Promise<Record<string, Record<string, ModelEntry>>>;
8
+ };
9
+
10
+ type ModelDevSourceOptions = {
11
+ cacheTtlMs?: number;
12
+ cachePath?: string;
13
+ storageRoot?: string;
14
+ storagePathService?: StoragePathService;
15
+ };
16
+
17
+ declare class ModelMetadataServiceImpl implements ModelMetadataService {
18
+ private readonly modelDevSource;
19
+ private readonly sources;
20
+ constructor(options?: ModelDevSourceOptions);
21
+ refreshAllModelEntries(): Promise<Record<string, Record<string, ModelEntry>>>;
22
+ getModelEntry(provider: string, model: string): Promise<ModelEntry | null>;
23
+ getModelEntries(provider: string): Promise<ModelEntry[] | null>;
24
+ getAllModelEntries(): Promise<Record<string, Record<string, ModelEntry>>>;
25
+ }
26
+
27
+ export { type ModelDevSourceOptions, ModelMetadataServiceImpl, type ModelMetadataSource };
package/dist/index.js ADDED
@@ -0,0 +1,253 @@
1
+ // src/sources/modeldev.ts
2
+ import { mkdir, readFile, writeFile } from "fs/promises";
3
+ import path from "path";
4
+ import { resolveStoragePaths } from "@codelia/storage";
5
+ import { z } from "zod";
6
+ var modelResourceUrl = "https://models.dev/api.json";
7
+ var CACHE_FILENAME = "models.dev.json";
8
+ var CACHE_VERSION = 1;
9
+ var DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
10
+ var wireModelDevModelSchema = z.object({
11
+ id: z.string(),
12
+ name: z.string(),
13
+ family: z.string().optional(),
14
+ attachment: z.boolean().optional(),
15
+ reasoning: z.boolean().optional(),
16
+ tool_call: z.boolean().optional(),
17
+ structured_output: z.boolean().optional(),
18
+ temperature: z.boolean().optional(),
19
+ knowledge: z.string().optional(),
20
+ release_date: z.string().optional(),
21
+ last_updated: z.string().optional(),
22
+ open_weights: z.boolean().optional(),
23
+ cost: z.object({
24
+ input: z.number().optional(),
25
+ output: z.number().optional(),
26
+ reasoning: z.number().optional(),
27
+ cache_read: z.number().optional(),
28
+ cache_write: z.number().optional(),
29
+ input_audio: z.number().optional(),
30
+ output_audio: z.number().optional()
31
+ }).loose().optional(),
32
+ limit: z.object({
33
+ context: z.number().optional(),
34
+ input: z.number().optional(),
35
+ output: z.number().optional()
36
+ }).loose().optional(),
37
+ modalities: z.object({
38
+ input: z.array(z.string()).optional(),
39
+ output: z.array(z.string()).optional()
40
+ }).loose().optional(),
41
+ interleaved: z.union([
42
+ z.boolean(),
43
+ z.object({
44
+ field: z.string().optional()
45
+ }).loose()
46
+ ]).optional()
47
+ }).loose();
48
+ var wireModelDevModelsSchema = z.union([
49
+ z.array(wireModelDevModelSchema),
50
+ z.record(z.string(), wireModelDevModelSchema)
51
+ ]);
52
+ var wireModelDevProviderSchema = z.object({
53
+ id: z.string().optional(),
54
+ name: z.string().optional(),
55
+ api: z.string().optional(),
56
+ doc: z.string().optional(),
57
+ env: z.array(z.string()).optional(),
58
+ npm: z.string().optional(),
59
+ models: z.record(z.string(), wireModelDevModelSchema).optional()
60
+ }).loose();
61
+ var wireModelDevProvidersSchema = z.record(
62
+ z.string(),
63
+ wireModelDevProviderSchema
64
+ );
65
+ var ModelDevSource = class {
66
+ loaded = false;
67
+ models = {};
68
+ cacheTtlMs;
69
+ cachePath;
70
+ constructor(options = {}) {
71
+ this.cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
72
+ const storagePaths = options.storagePathService ? options.storagePathService.resolvePaths({
73
+ rootOverride: options.storageRoot
74
+ }) : resolveStoragePaths({ rootOverride: options.storageRoot });
75
+ this.cachePath = options.cachePath ?? path.join(storagePaths.cacheDir, CACHE_FILENAME);
76
+ }
77
+ async loadModelMetadata(options = {}) {
78
+ this.loaded = false;
79
+ this.models = {};
80
+ if (!options.forceRefresh) {
81
+ const cached = await readCacheFile(this.cachePath);
82
+ if (cached && !isCacheExpired(cached.expiresAt)) {
83
+ this.models = cached.entries;
84
+ this.loaded = true;
85
+ return;
86
+ }
87
+ }
88
+ const response = await fetch(modelResourceUrl);
89
+ const data = await response.json();
90
+ const providersResult = wireModelDevProvidersSchema.safeParse(data);
91
+ if (providersResult.success) {
92
+ this.models = buildEntriesFromProviders(providersResult.data);
93
+ }
94
+ let hasEntries = Object.keys(this.models).length > 0;
95
+ if (!hasEntries) {
96
+ this.models = buildEntriesFromLegacyPayload(data);
97
+ }
98
+ hasEntries = Object.keys(this.models).length > 0;
99
+ if (!hasEntries) {
100
+ throw new Error("ModelDevSource: empty metadata payload");
101
+ }
102
+ await writeCacheFile(this.cachePath, {
103
+ version: CACHE_VERSION,
104
+ cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
105
+ expiresAt: new Date(Date.now() + this.cacheTtlMs).toISOString(),
106
+ entries: this.models
107
+ }).catch(() => void 0);
108
+ this.loaded = true;
109
+ }
110
+ async getModelEntry(provider, model) {
111
+ if (!this.loaded) {
112
+ await this.loadModelMetadata();
113
+ }
114
+ return this.models[provider]?.[model] || null;
115
+ }
116
+ async getModelEntries(provider) {
117
+ if (!this.loaded) {
118
+ await this.loadModelMetadata();
119
+ }
120
+ return this.models[provider] ? Object.values(this.models[provider]) : null;
121
+ }
122
+ async getAllModelEntries() {
123
+ if (!this.loaded) {
124
+ await this.loadModelMetadata();
125
+ }
126
+ return this.models;
127
+ }
128
+ };
129
+ function buildEntriesFromProviders(providers) {
130
+ const entries = {};
131
+ for (const [providerId, provider] of Object.entries(providers)) {
132
+ const models = provider.models ? Object.values(provider.models) : [];
133
+ if (models.length === 0) continue;
134
+ entries[providerId] = buildEntriesForProvider(providerId, models);
135
+ }
136
+ return entries;
137
+ }
138
+ function buildEntriesFromLegacyPayload(data) {
139
+ let provider = "unknown";
140
+ if (data.provider && typeof data.provider === "object") {
141
+ const name = data.provider.name;
142
+ if (name) provider = name;
143
+ }
144
+ const modelsResult = wireModelDevModelsSchema.safeParse(
145
+ data.models
146
+ );
147
+ if (!modelsResult.success) return {};
148
+ const models = Array.isArray(modelsResult.data) ? modelsResult.data : Object.values(modelsResult.data);
149
+ if (models.length === 0) return {};
150
+ return { [provider]: buildEntriesForProvider(provider, models) };
151
+ }
152
+ function buildEntriesForProvider(provider, models) {
153
+ const entries = {};
154
+ for (const model of models) {
155
+ entries[model.id] = {
156
+ provider,
157
+ modelId: model.id,
158
+ cost: {
159
+ input: model.cost?.input,
160
+ output: model.cost?.output,
161
+ reasoning: model.cost?.reasoning,
162
+ cacheRead: model.cost?.cache_read,
163
+ cacheWrite: model.cost?.cache_write,
164
+ inputAudio: model.cost?.input_audio,
165
+ outputAudio: model.cost?.output_audio
166
+ },
167
+ limits: {
168
+ contextWindow: model.limit?.context,
169
+ inputTokens: model.limit?.input,
170
+ outputTokens: model.limit?.output
171
+ }
172
+ };
173
+ }
174
+ return entries;
175
+ }
176
+ async function readCacheFile(cachePath) {
177
+ const contents = await readFile(cachePath, "utf8").catch(() => null);
178
+ if (!contents) return null;
179
+ const parsed = safeJsonParse(contents);
180
+ if (!parsed || !isCacheFile(parsed)) return null;
181
+ return parsed;
182
+ }
183
+ async function writeCacheFile(cachePath, cache) {
184
+ await ensureDir(path.dirname(cachePath));
185
+ await writeFile(cachePath, JSON.stringify(cache), "utf8");
186
+ }
187
+ function isCacheExpired(expiresAt) {
188
+ const timestamp = Date.parse(expiresAt);
189
+ if (Number.isNaN(timestamp)) return true;
190
+ return timestamp <= Date.now();
191
+ }
192
+ function isCacheFile(value) {
193
+ if (!value || typeof value !== "object") return false;
194
+ const file = value;
195
+ if (file.version !== CACHE_VERSION) return false;
196
+ if (typeof file.cachedAt !== "string") return false;
197
+ if (typeof file.expiresAt !== "string") return false;
198
+ if (!file.entries || typeof file.entries !== "object") return false;
199
+ return true;
200
+ }
201
+ function safeJsonParse(value) {
202
+ try {
203
+ return JSON.parse(value);
204
+ } catch {
205
+ return null;
206
+ }
207
+ }
208
+ async function ensureDir(dir) {
209
+ await mkdir(dir, { recursive: true });
210
+ }
211
+
212
+ // src/service.ts
213
+ var ModelMetadataServiceImpl = class {
214
+ modelDevSource;
215
+ sources;
216
+ constructor(options = {}) {
217
+ this.modelDevSource = new ModelDevSource(options);
218
+ this.sources = [this.modelDevSource];
219
+ }
220
+ async refreshAllModelEntries() {
221
+ await this.modelDevSource.loadModelMetadata({ forceRefresh: true });
222
+ return this.getAllModelEntries();
223
+ }
224
+ async getModelEntry(provider, model) {
225
+ for (const source of this.sources) {
226
+ const entry = await source.getModelEntry(provider, model);
227
+ if (entry) {
228
+ return entry;
229
+ }
230
+ }
231
+ return null;
232
+ }
233
+ async getModelEntries(provider) {
234
+ for (const source of this.sources) {
235
+ const entries = await source.getModelEntries(provider);
236
+ if (entries) {
237
+ return entries;
238
+ }
239
+ }
240
+ return null;
241
+ }
242
+ async getAllModelEntries() {
243
+ const entries = {};
244
+ for (const source of this.sources) {
245
+ const sourceEntries = await source.getAllModelEntries();
246
+ Object.assign(entries, sourceEntries);
247
+ }
248
+ return entries;
249
+ }
250
+ };
251
+ export {
252
+ ModelMetadataServiceImpl
253
+ };
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@codelia/model-metadata",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "dependencies": {
23
+ "@codelia/core": "0.1.0",
24
+ "@codelia/storage": "0.1.0",
25
+ "zod": "^4.3.5"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ }
30
+ }