@x12i/ai-tools 1.0.2
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/README.md +214 -0
- package/dist/AiModelsCatalogClient-4RF5BCDL.cjs +9 -0
- package/dist/AiModelsCatalogClient-4RF5BCDL.cjs.map +1 -0
- package/dist/AiModelsCatalogClient-B-dNLXX0.d.ts +29 -0
- package/dist/AiModelsCatalogClient-CSVlKql5.d.cts +29 -0
- package/dist/AiModelsCatalogClient-NUF3CBLW.js +9 -0
- package/dist/AiModelsCatalogClient-NUF3CBLW.js.map +1 -0
- package/dist/aliases/index.cjs +11 -0
- package/dist/aliases/index.cjs.map +1 -0
- package/dist/aliases/index.d.cts +21 -0
- package/dist/aliases/index.d.ts +21 -0
- package/dist/aliases/index.js +11 -0
- package/dist/aliases/index.js.map +1 -0
- package/dist/catalox/index.cjs +21 -0
- package/dist/catalox/index.cjs.map +1 -0
- package/dist/catalox/index.d.cts +23 -0
- package/dist/catalox/index.d.ts +23 -0
- package/dist/catalox/index.js +21 -0
- package/dist/catalox/index.js.map +1 -0
- package/dist/chunk-2PYACSZ5.cjs +1 -0
- package/dist/chunk-2PYACSZ5.cjs.map +1 -0
- package/dist/chunk-3E67S427.cjs +1 -0
- package/dist/chunk-3E67S427.cjs.map +1 -0
- package/dist/chunk-4NAY6HRP.js +137 -0
- package/dist/chunk-4NAY6HRP.js.map +1 -0
- package/dist/chunk-5HNFAYTO.cjs +254 -0
- package/dist/chunk-5HNFAYTO.cjs.map +1 -0
- package/dist/chunk-6QGDZTGH.js +127 -0
- package/dist/chunk-6QGDZTGH.js.map +1 -0
- package/dist/chunk-7Q742NI3.cjs +106 -0
- package/dist/chunk-7Q742NI3.cjs.map +1 -0
- package/dist/chunk-AJEKEWWB.js +106 -0
- package/dist/chunk-AJEKEWWB.js.map +1 -0
- package/dist/chunk-AV6OE2YQ.cjs +127 -0
- package/dist/chunk-AV6OE2YQ.cjs.map +1 -0
- package/dist/chunk-COK34C6P.js +1 -0
- package/dist/chunk-COK34C6P.js.map +1 -0
- package/dist/chunk-DJ5SWJDY.js +729 -0
- package/dist/chunk-DJ5SWJDY.js.map +1 -0
- package/dist/chunk-F2F4UEFD.cjs +75 -0
- package/dist/chunk-F2F4UEFD.cjs.map +1 -0
- package/dist/chunk-G2G4KSC5.js +30 -0
- package/dist/chunk-G2G4KSC5.js.map +1 -0
- package/dist/chunk-HHNHWYTP.cjs +105 -0
- package/dist/chunk-HHNHWYTP.cjs.map +1 -0
- package/dist/chunk-HN6UAQAE.cjs +83 -0
- package/dist/chunk-HN6UAQAE.cjs.map +1 -0
- package/dist/chunk-KHODXGPV.js +1 -0
- package/dist/chunk-KHODXGPV.js.map +1 -0
- package/dist/chunk-KQOALKKX.js +75 -0
- package/dist/chunk-KQOALKKX.js.map +1 -0
- package/dist/chunk-LYOU7CA2.cjs +30 -0
- package/dist/chunk-LYOU7CA2.cjs.map +1 -0
- package/dist/chunk-ML2FRR4L.js +105 -0
- package/dist/chunk-ML2FRR4L.js.map +1 -0
- package/dist/chunk-MLRHYOCD.js +160 -0
- package/dist/chunk-MLRHYOCD.js.map +1 -0
- package/dist/chunk-O2A6OVEH.js +240 -0
- package/dist/chunk-O2A6OVEH.js.map +1 -0
- package/dist/chunk-ONA73BU6.cjs +160 -0
- package/dist/chunk-ONA73BU6.cjs.map +1 -0
- package/dist/chunk-QCRLKVB3.cjs +137 -0
- package/dist/chunk-QCRLKVB3.cjs.map +1 -0
- package/dist/chunk-QWAX7VQO.cjs +240 -0
- package/dist/chunk-QWAX7VQO.cjs.map +1 -0
- package/dist/chunk-TF4L2NEC.cjs +729 -0
- package/dist/chunk-TF4L2NEC.cjs.map +1 -0
- package/dist/chunk-XRBZQQQU.js +254 -0
- package/dist/chunk-XRBZQQQU.js.map +1 -0
- package/dist/chunk-YHO57D2V.js +83 -0
- package/dist/chunk-YHO57D2V.js.map +1 -0
- package/dist/cli/index.cjs +403 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +403 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cost/index.cjs +7 -0
- package/dist/cost/index.cjs.map +1 -0
- package/dist/cost/index.d.cts +52 -0
- package/dist/cost/index.d.ts +52 -0
- package/dist/cost/index.js +7 -0
- package/dist/cost/index.js.map +1 -0
- package/dist/index.cjs +104 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/modelNameResolver-Bn8QnkSj.d.ts +80 -0
- package/dist/modelNameResolver-bZD-eBSJ.d.cts +80 -0
- package/dist/models/index.cjs +33 -0
- package/dist/models/index.cjs.map +1 -0
- package/dist/models/index.d.cts +75 -0
- package/dist/models/index.d.ts +75 -0
- package/dist/models/index.js +33 -0
- package/dist/models/index.js.map +1 -0
- package/dist/sync/index.cjs +38 -0
- package/dist/sync/index.cjs.map +1 -0
- package/dist/sync/index.d.cts +12 -0
- package/dist/sync/index.d.ts +12 -0
- package/dist/sync/index.js +38 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/toolbox/index.cjs +7 -0
- package/dist/toolbox/index.cjs.map +1 -0
- package/dist/toolbox/index.d.cts +72 -0
- package/dist/toolbox/index.d.ts +72 -0
- package/dist/toolbox/index.js +7 -0
- package/dist/toolbox/index.js.map +1 -0
- package/dist/types-DdGB3YaA.d.cts +278 -0
- package/dist/types-DdGB3YaA.d.ts +278 -0
- package/package.json +115 -0
- package/schemas/aliases.json +28 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunkHHNHWYTPcjs = require('./chunk-HHNHWYTP.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunkAV6OE2YQcjs = require('./chunk-AV6OE2YQ.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _chunkTF4L2NECcjs = require('./chunk-TF4L2NEC.cjs');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var _chunk7Q742NI3cjs = require('./chunk-7Q742NI3.cjs');
|
|
17
|
+
|
|
18
|
+
// src/catalog/ensureAiModelsCatalog.ts
|
|
19
|
+
async function ensureAiModelsCatalog(catalox, options = {}) {
|
|
20
|
+
const appId = _nullishCoalesce(options.appId, () => ( _chunkTF4L2NECcjs.AI_TOOLS_APP_ID));
|
|
21
|
+
const catalogId = _nullishCoalesce(options.catalogId, () => ( _chunkTF4L2NECcjs.AI_MODELS_CATALOG_ID));
|
|
22
|
+
const ctx = { appId, superAdmin: true };
|
|
23
|
+
try {
|
|
24
|
+
await catalox.ensureCatalog(ctx, {
|
|
25
|
+
catalogId,
|
|
26
|
+
name: _chunkTF4L2NECcjs.AI_MODELS_DESCRIPTOR.label,
|
|
27
|
+
status: "active"
|
|
28
|
+
});
|
|
29
|
+
await catalox.bindCatalogToApp(ctx, {
|
|
30
|
+
appId,
|
|
31
|
+
catalogId,
|
|
32
|
+
access: { canRead: true, canWrite: true, canAdmin: true }
|
|
33
|
+
});
|
|
34
|
+
await catalox.upsertCatalogDescriptor(ctx, catalogId, {
|
|
35
|
+
descriptorVersion: "1.0.0",
|
|
36
|
+
descriptor: _chunkTF4L2NECcjs.AI_MODELS_DESCRIPTOR
|
|
37
|
+
});
|
|
38
|
+
} catch (cause) {
|
|
39
|
+
throw new (0, _chunk7Q742NI3cjs.AiToolsError)(
|
|
40
|
+
"CATALOG_BOOTSTRAP_FAILED",
|
|
41
|
+
`Failed to bootstrap catalog "${catalogId}" for app "${appId}".`,
|
|
42
|
+
cause
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/sync/OpenRouterSyncProvider.ts
|
|
48
|
+
function buildFetchHeaders(apiKey) {
|
|
49
|
+
const headers = { Accept: "application/json" };
|
|
50
|
+
if (_optionalChain([apiKey, 'optionalAccess', _ => _.trim, 'call', _2 => _2()])) headers.Authorization = `Bearer ${apiKey.trim()}`;
|
|
51
|
+
return headers;
|
|
52
|
+
}
|
|
53
|
+
function buildModelsUrl(baseUrl, query) {
|
|
54
|
+
const url = new URL(`${baseUrl.replace(/\/$/, "")}/models`);
|
|
55
|
+
const q = { output_modalities: "all", ...query };
|
|
56
|
+
for (const [key, value] of Object.entries(q)) {
|
|
57
|
+
if (value !== void 0 && value !== "") url.searchParams.set(key, value);
|
|
58
|
+
}
|
|
59
|
+
return url.toString();
|
|
60
|
+
}
|
|
61
|
+
var OpenRouterSyncProvider = class {
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
constructor(options = {}) {
|
|
66
|
+
this.apiKey = options.apiKey;
|
|
67
|
+
this.baseUrl = _nullishCoalesce(options.baseUrl, () => ( "https://openrouter.ai/api/v1"));
|
|
68
|
+
this.query = _nullishCoalesce(options.query, () => ( { output_modalities: "all" }));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fetches the full OpenRouter model catalog (public, no API key required).
|
|
72
|
+
* @see https://openrouter.ai/api/v1/models
|
|
73
|
+
*/
|
|
74
|
+
async fetchModels() {
|
|
75
|
+
const url = buildModelsUrl(this.baseUrl, this.query);
|
|
76
|
+
let response;
|
|
77
|
+
try {
|
|
78
|
+
response = await fetch(url, { headers: buildFetchHeaders(this.apiKey) });
|
|
79
|
+
} catch (cause) {
|
|
80
|
+
throw new (0, _chunk7Q742NI3cjs.SyncError)("OPENROUTER_MODELS_FETCH_FAILED", `Failed to fetch OpenRouter models from ${url}`, cause);
|
|
81
|
+
}
|
|
82
|
+
if (response.status === 401 || response.status === 403) {
|
|
83
|
+
throw new (0, _chunk7Q742NI3cjs.SyncError)(
|
|
84
|
+
"OPENROUTER_AUTH_FAILED",
|
|
85
|
+
this.apiKey ? "OpenRouter API key is invalid or unauthorized." : "OpenRouter returned unauthorized \u2014 remove OPENROUTER_API_KEY to use the public models endpoint."
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
const body = await response.text().catch(() => "");
|
|
90
|
+
throw new (0, _chunk7Q742NI3cjs.SyncError)(
|
|
91
|
+
"OPENROUTER_MODELS_FETCH_FAILED",
|
|
92
|
+
`OpenRouter models fetch failed (${response.status}): ${body.slice(0, 200)}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const json = await response.json();
|
|
96
|
+
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
97
|
+
return (_nullishCoalesce(json.data, () => ( []))).map((row) => _chunkAV6OE2YQcjs.normalizeOpenRouterModel.call(void 0, row, syncedAt));
|
|
98
|
+
}
|
|
99
|
+
/** Build the URL used for the last fetch pattern (for debugging). */
|
|
100
|
+
getModelsUrl() {
|
|
101
|
+
return buildModelsUrl(this.baseUrl, this.query);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// src/sync/syncAiModelsCatalog.ts
|
|
106
|
+
async function syncAiModelsCatalog(options) {
|
|
107
|
+
const start = Date.now();
|
|
108
|
+
const appId = _nullishCoalesce(options.appId, () => ( _chunkTF4L2NECcjs.AI_TOOLS_APP_ID));
|
|
109
|
+
const catalogId = _nullishCoalesce(options.catalogId, () => ( _chunkTF4L2NECcjs.AI_MODELS_CATALOG_ID));
|
|
110
|
+
const ctx = { appId, superAdmin: true };
|
|
111
|
+
if (options.forceCache) {
|
|
112
|
+
_chunkTF4L2NECcjs.invalidateModelsCache.call(void 0, appId);
|
|
113
|
+
}
|
|
114
|
+
await ensureAiModelsCatalog(options.catalox, { appId, catalogId });
|
|
115
|
+
const provider = new OpenRouterSyncProvider({
|
|
116
|
+
apiKey: options.openRouterApiKey,
|
|
117
|
+
query: _nullishCoalesce(options.openRouterQuery, () => ( { output_modalities: "all" }))
|
|
118
|
+
});
|
|
119
|
+
let models;
|
|
120
|
+
try {
|
|
121
|
+
models = await provider.fetchModels();
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof _chunk7Q742NI3cjs.SyncError) throw error;
|
|
124
|
+
throw new (0, _chunk7Q742NI3cjs.SyncError)("SYNC_FETCH_FAILED", "Failed to fetch models from OpenRouter.", error);
|
|
125
|
+
}
|
|
126
|
+
if (options.verbose) {
|
|
127
|
+
console.log(`[sync] fetched ${models.length} models from ${provider.getModelsUrl()}`);
|
|
128
|
+
}
|
|
129
|
+
if (options.dryRun) {
|
|
130
|
+
return {
|
|
131
|
+
fetched: models.length,
|
|
132
|
+
upserted: 0,
|
|
133
|
+
skipped: models.length,
|
|
134
|
+
errors: [],
|
|
135
|
+
durationMs: Date.now() - start
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const errors = [];
|
|
139
|
+
try {
|
|
140
|
+
await _chunkHHNHWYTPcjs.batchUpsertAiModelRecords.call(void 0, options.firestore, catalogId, ctx, models);
|
|
141
|
+
} catch (cause) {
|
|
142
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
143
|
+
throw new (0, _chunk7Q742NI3cjs.SyncError)("SYNC_UPSERT_FAILED", `Batch upsert failed: ${message}`, cause);
|
|
144
|
+
}
|
|
145
|
+
_chunkTF4L2NECcjs.invalidateModelsCache.call(void 0, appId);
|
|
146
|
+
return {
|
|
147
|
+
fetched: models.length,
|
|
148
|
+
upserted: models.length,
|
|
149
|
+
skipped: 0,
|
|
150
|
+
errors,
|
|
151
|
+
durationMs: Date.now() - start
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
exports.ensureAiModelsCatalog = ensureAiModelsCatalog; exports.OpenRouterSyncProvider = OpenRouterSyncProvider; exports.syncAiModelsCatalog = syncAiModelsCatalog;
|
|
160
|
+
//# sourceMappingURL=chunk-ONA73BU6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-ONA73BU6.cjs","../src/catalog/ensureAiModelsCatalog.ts","../src/sync/OpenRouterSyncProvider.ts","../src/sync/syncAiModelsCatalog.ts"],"names":[],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-ONA73BU6.cjs","sourcesContent":[null,"import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport { AiToolsError } from \"../errors.js\";\nimport {\n AI_MODELS_CATALOG_ID,\n AI_MODELS_DESCRIPTOR,\n AI_TOOLS_APP_ID,\n} from \"./aiModelsCatalogDescriptor.js\";\n\nexport type EnsureAiModelsCatalogOptions = {\n appId?: string;\n catalogId?: string;\n};\n\nexport async function ensureAiModelsCatalog(\n catalox: Catalox,\n options: EnsureAiModelsCatalogOptions = {},\n): Promise<void> {\n const appId = options.appId ?? AI_TOOLS_APP_ID;\n const catalogId = options.catalogId ?? AI_MODELS_CATALOG_ID;\n\n const ctx: CataloxContext = { appId, superAdmin: true };\n\n try {\n await catalox.ensureCatalog(ctx, {\n catalogId,\n name: AI_MODELS_DESCRIPTOR.label,\n status: \"active\",\n });\n\n await catalox.bindCatalogToApp(ctx, {\n appId,\n catalogId,\n access: { canRead: true, canWrite: true, canAdmin: true },\n });\n\n await catalox.upsertCatalogDescriptor(ctx, catalogId, {\n descriptorVersion: \"1.0.0\",\n descriptor: AI_MODELS_DESCRIPTOR,\n });\n } catch (cause) {\n throw new AiToolsError(\n \"CATALOG_BOOTSTRAP_FAILED\",\n `Failed to bootstrap catalog \"${catalogId}\" for app \"${appId}\".`,\n cause,\n );\n }\n}\n","import { SyncError } from \"../errors.js\";\nimport { normalizeOpenRouterModel } from \"../models/normalizeOpenRouterModel.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport type {\n OpenRouterModelsQuery,\n OpenRouterModelsResponse,\n} from \"../models/openrouter.types.js\";\n\nexport type OpenRouterSyncProviderOptions = {\n /** Optional — public GET /models needs no key. */\n apiKey?: string;\n baseUrl?: string;\n /** Query params passed to OpenRouter (default: all modalities). */\n query?: OpenRouterModelsQuery;\n};\n\nfunction buildFetchHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (apiKey?.trim()) headers.Authorization = `Bearer ${apiKey.trim()}`;\n return headers;\n}\n\nfunction buildModelsUrl(baseUrl: string, query?: OpenRouterModelsQuery): string {\n const url = new URL(`${baseUrl.replace(/\\/$/, \"\")}/models`);\n const q = { output_modalities: \"all\", ...query };\n for (const [key, value] of Object.entries(q)) {\n if (value !== undefined && value !== \"\") url.searchParams.set(key, value);\n }\n return url.toString();\n}\n\nexport class OpenRouterSyncProvider {\n private readonly apiKey?: string;\n private readonly baseUrl: string;\n private readonly query?: OpenRouterModelsQuery;\n\n constructor(options: OpenRouterSyncProviderOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://openrouter.ai/api/v1\";\n this.query = options.query ?? { output_modalities: \"all\" };\n }\n\n /**\n * Fetches the full OpenRouter model catalog (public, no API key required).\n * @see https://openrouter.ai/api/v1/models\n */\n async fetchModels(): Promise<AiModelRecord[]> {\n const url = buildModelsUrl(this.baseUrl, this.query);\n let response: Response;\n\n try {\n response = await fetch(url, { headers: buildFetchHeaders(this.apiKey) });\n } catch (cause) {\n throw new SyncError(\"OPENROUTER_MODELS_FETCH_FAILED\", `Failed to fetch OpenRouter models from ${url}`, cause);\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SyncError(\n \"OPENROUTER_AUTH_FAILED\",\n this.apiKey\n ? \"OpenRouter API key is invalid or unauthorized.\"\n : \"OpenRouter returned unauthorized — remove OPENROUTER_API_KEY to use the public models endpoint.\",\n );\n }\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new SyncError(\n \"OPENROUTER_MODELS_FETCH_FAILED\",\n `OpenRouter models fetch failed (${response.status}): ${body.slice(0, 200)}`,\n );\n }\n\n const json = (await response.json()) as OpenRouterModelsResponse;\n const syncedAt = new Date().toISOString();\n return (json.data ?? []).map((row) => normalizeOpenRouterModel(row, syncedAt));\n }\n\n /** Build the URL used for the last fetch pattern (for debugging). */\n getModelsUrl(): string {\n return buildModelsUrl(this.baseUrl, this.query);\n }\n}\n","import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport type { Firestore } from \"firebase-admin/firestore\";\nimport { ensureAiModelsCatalog } from \"../catalog/ensureAiModelsCatalog.js\";\nimport { AI_MODELS_CATALOG_ID, AI_TOOLS_APP_ID } from \"../catalog/aiModelsCatalogDescriptor.js\";\nimport { invalidateModelsCache } from \"../cache/modelCache.js\";\nimport { batchUpsertAiModelRecords } from \"../catalox/upsertAiModelRecord.js\";\nimport { SyncError } from \"../errors.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport type { OpenRouterModelsQuery } from \"../models/openrouter.types.js\";\nimport { OpenRouterSyncProvider } from \"./OpenRouterSyncProvider.js\";\n\nexport type SyncOptions = {\n catalox: Catalox;\n firestore: Firestore;\n openRouterApiKey?: string;\n openRouterQuery?: OpenRouterModelsQuery;\n appId?: string;\n catalogId?: string;\n dryRun?: boolean;\n verbose?: boolean;\n forceCache?: boolean;\n};\n\nexport type SyncResult = {\n fetched: number;\n upserted: number;\n skipped: number;\n errors: Array<{ modelId: string; error: string }>;\n durationMs: number;\n};\n\nexport async function syncAiModelsCatalog(options: SyncOptions): Promise<SyncResult> {\n const start = Date.now();\n const appId = options.appId ?? AI_TOOLS_APP_ID;\n const catalogId = options.catalogId ?? AI_MODELS_CATALOG_ID;\n const ctx: CataloxContext = { appId, superAdmin: true };\n\n if (options.forceCache) {\n invalidateModelsCache(appId);\n }\n\n await ensureAiModelsCatalog(options.catalox, { appId, catalogId });\n\n const provider = new OpenRouterSyncProvider({\n apiKey: options.openRouterApiKey,\n query: options.openRouterQuery ?? { output_modalities: \"all\" },\n });\n\n let models: AiModelRecord[];\n try {\n models = await provider.fetchModels();\n } catch (error) {\n if (error instanceof SyncError) throw error;\n throw new SyncError(\"SYNC_FETCH_FAILED\", \"Failed to fetch models from OpenRouter.\", error);\n }\n\n if (options.verbose) {\n console.log(`[sync] fetched ${models.length} models from ${provider.getModelsUrl()}`);\n }\n\n if (options.dryRun) {\n return {\n fetched: models.length,\n upserted: 0,\n skipped: models.length,\n errors: [],\n durationMs: Date.now() - start,\n };\n }\n\n const errors: SyncResult[\"errors\"] = [];\n try {\n await batchUpsertAiModelRecords(options.firestore, catalogId, ctx, models);\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n throw new SyncError(\"SYNC_UPSERT_FAILED\", `Batch upsert failed: ${message}`, cause);\n }\n\n invalidateModelsCache(appId);\n\n return {\n fetched: models.length,\n upserted: models.length,\n skipped: 0,\n errors,\n durationMs: Date.now() - start,\n };\n}\n"]}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunkF2F4UEFDcjs = require('./chunk-F2F4UEFD.cjs');
|
|
4
|
+
|
|
5
|
+
// src/models/filterModels.ts
|
|
6
|
+
function matchesSearch(record, search) {
|
|
7
|
+
const q = search.toLowerCase();
|
|
8
|
+
return record.modelId.toLowerCase().includes(q) || record.name.toLowerCase().includes(q) || record.description.toLowerCase().includes(q) || record.canonicalSlug.toLowerCase().includes(q) || record.aliases.some((a) => a.toLowerCase().includes(q));
|
|
9
|
+
}
|
|
10
|
+
function filterModels(models, filters = {}) {
|
|
11
|
+
let list = [...models];
|
|
12
|
+
if (filters.providerId) {
|
|
13
|
+
list = list.filter((m) => m.providerId === filters.providerId);
|
|
14
|
+
}
|
|
15
|
+
if (filters.status) {
|
|
16
|
+
list = list.filter((m) => m.status === filters.status);
|
|
17
|
+
}
|
|
18
|
+
if (filters.outputModality) {
|
|
19
|
+
list = list.filter((m) => m.outputModalities.includes(filters.outputModality));
|
|
20
|
+
}
|
|
21
|
+
if (filters.inputModality) {
|
|
22
|
+
list = list.filter((m) => m.inputModalities.includes(filters.inputModality));
|
|
23
|
+
}
|
|
24
|
+
if (filters.supportedParameter) {
|
|
25
|
+
list = list.filter((m) => m.supportedParameters.includes(filters.supportedParameter));
|
|
26
|
+
}
|
|
27
|
+
if (filters.supportsTools !== void 0) {
|
|
28
|
+
list = list.filter((m) => m.supportsTools === filters.supportsTools);
|
|
29
|
+
}
|
|
30
|
+
if (filters.supportsReasoning !== void 0) {
|
|
31
|
+
list = list.filter((m) => m.supportsReasoning === filters.supportsReasoning);
|
|
32
|
+
}
|
|
33
|
+
if (filters.search) {
|
|
34
|
+
list = list.filter((m) => matchesSearch(m, filters.search));
|
|
35
|
+
}
|
|
36
|
+
list.sort((a, b) => a.name.localeCompare(b.name));
|
|
37
|
+
const offset = _nullishCoalesce(filters.offset, () => ( 0));
|
|
38
|
+
const limit = _nullishCoalesce(filters.limit, () => ( list.length));
|
|
39
|
+
return list.slice(offset, offset + limit);
|
|
40
|
+
}
|
|
41
|
+
function countModels(models, filters = {}) {
|
|
42
|
+
return filterModels(models, { ...filters, limit: Number.MAX_SAFE_INTEGER, offset: 0 }).length;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/models/AiModelsService.ts
|
|
46
|
+
var AiModelsService = class {
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.catalox = options.catalox;
|
|
53
|
+
this.client = new (0, _chunkF2F4UEFDcjs.AiModelsCatalogClient)(options);
|
|
54
|
+
this.appId = _nullishCoalesce(options.appId, () => ( "ai-tools"));
|
|
55
|
+
this.catalogId = _nullishCoalesce(options.catalogId, () => ( "ai-models"));
|
|
56
|
+
}
|
|
57
|
+
context() {
|
|
58
|
+
return { appId: this.appId, superAdmin: true };
|
|
59
|
+
}
|
|
60
|
+
/** Load all models (cached). */
|
|
61
|
+
async getAllModels() {
|
|
62
|
+
return this.client.getAllModels();
|
|
63
|
+
}
|
|
64
|
+
/** List models with in-memory filters (fast after cache warm). */
|
|
65
|
+
async listModels(filters = {}) {
|
|
66
|
+
const all = await this.getAllModels();
|
|
67
|
+
const total = countModels(all.values(), filters);
|
|
68
|
+
const limit = _nullishCoalesce(filters.limit, () => ( 50));
|
|
69
|
+
const offset = _nullishCoalesce(filters.offset, () => ( 0));
|
|
70
|
+
const models = filterModels(all.values(), { ...filters, limit, offset });
|
|
71
|
+
return { models, total, limit, offset };
|
|
72
|
+
}
|
|
73
|
+
/** Count models matching filters. */
|
|
74
|
+
async countModels(filters = {}) {
|
|
75
|
+
const all = await this.getAllModels();
|
|
76
|
+
return countModels(all.values(), filters);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Full model record by id or alias (same resolution as cost calculator).
|
|
80
|
+
*/
|
|
81
|
+
async getModelInfo(modelIdOrAlias) {
|
|
82
|
+
return this.client.getModel(modelIdOrAlias);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Query via Catalox indexed fields (provider, status, output modality, tools).
|
|
86
|
+
* Falls back to in-memory filter when Catalox returns partial pages.
|
|
87
|
+
*/
|
|
88
|
+
async listModelsFromCatalog(filters = {}, options) {
|
|
89
|
+
const filter = {};
|
|
90
|
+
if (filters.providerId) filter.providerId = filters.providerId;
|
|
91
|
+
if (filters.status) filter.status = filters.status;
|
|
92
|
+
if (filters.outputModality) filter.primaryOutputModality = filters.outputModality;
|
|
93
|
+
if (filters.supportsTools !== void 0) filter.supportsTools = filters.supportsTools;
|
|
94
|
+
if (filters.supportsReasoning !== void 0) {
|
|
95
|
+
filter.supportsReasoning = filters.supportsReasoning;
|
|
96
|
+
}
|
|
97
|
+
const limit = _nullishCoalesce(filters.limit, () => ( 50));
|
|
98
|
+
const result = await this.catalox.listCatalogItems(this.context(), this.catalogId, {
|
|
99
|
+
limit: Math.min(limit, 1e4),
|
|
100
|
+
filter,
|
|
101
|
+
...options
|
|
102
|
+
});
|
|
103
|
+
let models = result.items.map((item) => item.data);
|
|
104
|
+
if (filters.supportedParameter) {
|
|
105
|
+
models = models.filter((m) => _optionalChain([m, 'access', _ => _.supportedParameters, 'optionalAccess', _2 => _2.includes, 'call', _3 => _3(filters.supportedParameter)]));
|
|
106
|
+
}
|
|
107
|
+
if (filters.inputModality) {
|
|
108
|
+
models = models.filter((m) => _optionalChain([m, 'access', _4 => _4.inputModalities, 'optionalAccess', _5 => _5.includes, 'call', _6 => _6(filters.inputModality)]));
|
|
109
|
+
}
|
|
110
|
+
if (filters.search) {
|
|
111
|
+
models = filterModels(models, { search: filters.search });
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
models,
|
|
115
|
+
total: models.length,
|
|
116
|
+
limit,
|
|
117
|
+
offset: _nullishCoalesce(filters.offset, () => ( 0))
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
async resolve(modelIdOrAlias, provider) {
|
|
121
|
+
return this.client.resolveModel({ model: modelIdOrAlias, provider });
|
|
122
|
+
}
|
|
123
|
+
async refresh() {
|
|
124
|
+
await this.client.refresh();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
async function getModelInfo(service, modelIdOrAlias) {
|
|
128
|
+
return service.getModelInfo(modelIdOrAlias);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
exports.filterModels = filterModels; exports.countModels = countModels; exports.AiModelsService = AiModelsService; exports.getModelInfo = getModelInfo;
|
|
137
|
+
//# sourceMappingURL=chunk-QCRLKVB3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-QCRLKVB3.cjs","../src/models/filterModels.ts","../src/models/AiModelsService.ts"],"names":[],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-QCRLKVB3.cjs","sourcesContent":[null,"import type { AiModelRecord, ModelListFilters } from \"./types.js\";\n\nfunction matchesSearch(record: AiModelRecord, search: string): boolean {\n const q = search.toLowerCase();\n return (\n record.modelId.toLowerCase().includes(q) ||\n record.name.toLowerCase().includes(q) ||\n record.description.toLowerCase().includes(q) ||\n record.canonicalSlug.toLowerCase().includes(q) ||\n record.aliases.some((a) => a.toLowerCase().includes(q))\n );\n}\n\nexport function filterModels(\n models: Iterable<AiModelRecord>,\n filters: ModelListFilters = {},\n): AiModelRecord[] {\n let list = [...models];\n\n if (filters.providerId) {\n list = list.filter((m) => m.providerId === filters.providerId);\n }\n if (filters.status) {\n list = list.filter((m) => m.status === filters.status);\n }\n if (filters.outputModality) {\n list = list.filter((m) => m.outputModalities.includes(filters.outputModality!));\n }\n if (filters.inputModality) {\n list = list.filter((m) => m.inputModalities.includes(filters.inputModality!));\n }\n if (filters.supportedParameter) {\n list = list.filter((m) => m.supportedParameters.includes(filters.supportedParameter!));\n }\n if (filters.supportsTools !== undefined) {\n list = list.filter((m) => m.supportsTools === filters.supportsTools);\n }\n if (filters.supportsReasoning !== undefined) {\n list = list.filter((m) => m.supportsReasoning === filters.supportsReasoning);\n }\n if (filters.search) {\n list = list.filter((m) => matchesSearch(m, filters.search!));\n }\n\n list.sort((a, b) => a.name.localeCompare(b.name));\n\n const offset = filters.offset ?? 0;\n const limit = filters.limit ?? list.length;\n return list.slice(offset, offset + limit);\n}\n\nexport function countModels(\n models: Iterable<AiModelRecord>,\n filters: Omit<ModelListFilters, \"limit\" | \"offset\"> = {},\n): number {\n return filterModels(models, { ...filters, limit: Number.MAX_SAFE_INTEGER, offset: 0 }).length;\n}\n","import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport type { CatalogQueryOptions } from \"@x12i/catalox\";\nimport { AiModelsCatalogClient } from \"../catalox/AiModelsCatalogClient.js\";\nimport { countModels, filterModels } from \"./filterModels.js\";\nimport type { AiModelRecord, ModelListFilters, ModelListResult } from \"./types.js\";\n\nexport type AiModelsServiceOptions = {\n catalox: Catalox;\n appId?: string;\n catalogId?: string;\n cacheTtlMs?: number;\n};\n\n/**\n * High-level model catalog API — list, filter, count, and get full model info.\n */\nexport class AiModelsService {\n private readonly client: AiModelsCatalogClient;\n private readonly catalox: Catalox;\n private readonly appId: string;\n private readonly catalogId: string;\n\n constructor(options: AiModelsServiceOptions) {\n this.catalox = options.catalox;\n this.client = new AiModelsCatalogClient(options);\n this.appId = options.appId ?? \"ai-tools\";\n this.catalogId = options.catalogId ?? \"ai-models\";\n }\n\n private context(): CataloxContext {\n return { appId: this.appId, superAdmin: true };\n }\n\n /** Load all models (cached). */\n async getAllModels(): Promise<Map<string, AiModelRecord>> {\n return this.client.getAllModels();\n }\n\n /** List models with in-memory filters (fast after cache warm). */\n async listModels(filters: ModelListFilters = {}): Promise<ModelListResult> {\n const all = await this.getAllModels();\n const total = countModels(all.values(), filters);\n const limit = filters.limit ?? 50;\n const offset = filters.offset ?? 0;\n const models = filterModels(all.values(), { ...filters, limit, offset });\n return { models, total, limit, offset };\n }\n\n /** Count models matching filters. */\n async countModels(filters: Omit<ModelListFilters, \"limit\" | \"offset\"> = {}): Promise<number> {\n const all = await this.getAllModels();\n return countModels(all.values(), filters);\n }\n\n /**\n * Full model record by id or alias (same resolution as cost calculator).\n */\n async getModelInfo(modelIdOrAlias: string): Promise<AiModelRecord | null> {\n return this.client.getModel(modelIdOrAlias);\n }\n\n /**\n * Query via Catalox indexed fields (provider, status, output modality, tools).\n * Falls back to in-memory filter when Catalox returns partial pages.\n */\n async listModelsFromCatalog(\n filters: ModelListFilters = {},\n options?: CatalogQueryOptions,\n ): Promise<ModelListResult> {\n const filter: Record<string, unknown> = {};\n if (filters.providerId) filter.providerId = filters.providerId;\n if (filters.status) filter.status = filters.status;\n if (filters.outputModality) filter.primaryOutputModality = filters.outputModality;\n if (filters.supportsTools !== undefined) filter.supportsTools = filters.supportsTools;\n if (filters.supportsReasoning !== undefined) {\n filter.supportsReasoning = filters.supportsReasoning;\n }\n\n const limit = filters.limit ?? 50;\n const result = await this.catalox.listCatalogItems(this.context(), this.catalogId, {\n limit: Math.min(limit, 10_000),\n filter,\n ...options,\n });\n\n let models = result.items.map((item) => item.data as unknown as AiModelRecord);\n\n if (filters.supportedParameter) {\n models = models.filter((m) => m.supportedParameters?.includes(filters.supportedParameter!));\n }\n if (filters.inputModality) {\n models = models.filter((m) => m.inputModalities?.includes(filters.inputModality!));\n }\n if (filters.search) {\n models = filterModels(models, { search: filters.search });\n }\n\n return {\n models,\n total: models.length,\n limit,\n offset: filters.offset ?? 0,\n };\n }\n\n async resolve(\n modelIdOrAlias: string,\n provider?: string,\n ): Promise<import(\"../sync/modelNameResolver/types.js\").ModelResolutionResult> {\n return this.client.resolveModel({ model: modelIdOrAlias, provider });\n }\n\n async refresh(): Promise<void> {\n await this.client.refresh();\n }\n}\n\n/** Convenience: getModelInfo */\nexport async function getModelInfo(\n service: AiModelsService,\n modelIdOrAlias: string,\n): Promise<AiModelRecord | null> {\n return service.getModelInfo(modelIdOrAlias);\n}\n"]}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunk7Q742NI3cjs = require('./chunk-7Q742NI3.cjs');
|
|
8
|
+
|
|
9
|
+
// src/aliases/AliasRegistry.ts
|
|
10
|
+
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
11
|
+
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
12
|
+
var _zod = require('zod');
|
|
13
|
+
var ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
14
|
+
var aliasEntrySchema = _zod.z.object({
|
|
15
|
+
modelId: _zod.z.string().min(1),
|
|
16
|
+
provider: _zod.z.string().min(1),
|
|
17
|
+
description: _zod.z.string().optional(),
|
|
18
|
+
tags: _zod.z.array(_zod.z.string()).optional(),
|
|
19
|
+
addedAt: _zod.z.string(),
|
|
20
|
+
updatedAt: _zod.z.string()
|
|
21
|
+
});
|
|
22
|
+
var aliasFileSchema = _zod.z.object({
|
|
23
|
+
$schema: _zod.z.string().optional(),
|
|
24
|
+
version: _zod.z.literal(1),
|
|
25
|
+
updatedAt: _zod.z.string(),
|
|
26
|
+
aliases: _zod.z.record(aliasEntrySchema)
|
|
27
|
+
});
|
|
28
|
+
function defaultAliasesPath() {
|
|
29
|
+
if (process.env.AI_TOOLS_ALIASES_PATH) {
|
|
30
|
+
return _path2.default.resolve(process.env.AI_TOOLS_ALIASES_PATH);
|
|
31
|
+
}
|
|
32
|
+
return _path2.default.resolve(process.cwd(), "ai-tools/aliases.json");
|
|
33
|
+
}
|
|
34
|
+
function emptySchema() {
|
|
35
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36
|
+
return {
|
|
37
|
+
$schema: "https://unpkg.com/@x12i/ai-tools/schemas/aliases.json",
|
|
38
|
+
version: 1,
|
|
39
|
+
updatedAt: now,
|
|
40
|
+
aliases: {}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
var AliasRegistry = class {
|
|
44
|
+
|
|
45
|
+
constructor(options = {}) {
|
|
46
|
+
this.aliasesPath = _nullishCoalesce(options.aliasesPath, () => ( defaultAliasesPath()));
|
|
47
|
+
}
|
|
48
|
+
get path() {
|
|
49
|
+
return this.aliasesPath;
|
|
50
|
+
}
|
|
51
|
+
exists() {
|
|
52
|
+
return _fs2.default.existsSync(this.aliasesPath);
|
|
53
|
+
}
|
|
54
|
+
init() {
|
|
55
|
+
if (this.exists()) return;
|
|
56
|
+
_fs2.default.mkdirSync(_path2.default.dirname(this.aliasesPath), { recursive: true });
|
|
57
|
+
this.writeFile(emptySchema());
|
|
58
|
+
}
|
|
59
|
+
load() {
|
|
60
|
+
if (!this.exists()) return emptySchema();
|
|
61
|
+
let raw;
|
|
62
|
+
try {
|
|
63
|
+
raw = _fs2.default.readFileSync(this.aliasesPath, "utf8");
|
|
64
|
+
} catch (cause) {
|
|
65
|
+
throw new (0, _chunk7Q742NI3cjs.AliasFileParseError)(this.aliasesPath, cause);
|
|
66
|
+
}
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(raw);
|
|
70
|
+
} catch (cause) {
|
|
71
|
+
throw new (0, _chunk7Q742NI3cjs.AliasFileParseError)(this.aliasesPath, cause);
|
|
72
|
+
}
|
|
73
|
+
const result = aliasFileSchema.safeParse(parsed);
|
|
74
|
+
if (!result.success) {
|
|
75
|
+
throw new (0, _chunk7Q742NI3cjs.AliasFileParseError)(this.aliasesPath, result.error);
|
|
76
|
+
}
|
|
77
|
+
return result.data;
|
|
78
|
+
}
|
|
79
|
+
get(aliasName) {
|
|
80
|
+
const schema = this.load();
|
|
81
|
+
return _nullishCoalesce(schema.aliases[aliasName], () => ( null));
|
|
82
|
+
}
|
|
83
|
+
list(filter) {
|
|
84
|
+
const schema = this.load();
|
|
85
|
+
return Object.entries(schema.aliases).filter(([, entry]) => !_optionalChain([filter, 'optionalAccess', _ => _.tag]) || (_nullishCoalesce(entry.tags, () => ( []))).includes(filter.tag)).map(([name, entry]) => ({ name, ...entry }));
|
|
86
|
+
}
|
|
87
|
+
set(aliasName, entry) {
|
|
88
|
+
if (!ALIAS_NAME_RE.test(aliasName)) {
|
|
89
|
+
throw new (0, _chunk7Q742NI3cjs.AliasInvalidNameError)(aliasName);
|
|
90
|
+
}
|
|
91
|
+
if (!this.exists()) this.init();
|
|
92
|
+
const schema = this.load();
|
|
93
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
94
|
+
const existing = schema.aliases[aliasName];
|
|
95
|
+
const full = {
|
|
96
|
+
...entry,
|
|
97
|
+
addedAt: _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _2 => _2.addedAt]), () => ( now)),
|
|
98
|
+
updatedAt: now
|
|
99
|
+
};
|
|
100
|
+
schema.aliases[aliasName] = full;
|
|
101
|
+
schema.updatedAt = now;
|
|
102
|
+
this.writeFile(schema);
|
|
103
|
+
return full;
|
|
104
|
+
}
|
|
105
|
+
remove(aliasName) {
|
|
106
|
+
if (!this.exists()) return false;
|
|
107
|
+
const schema = this.load();
|
|
108
|
+
if (!schema.aliases[aliasName]) return false;
|
|
109
|
+
delete schema.aliases[aliasName];
|
|
110
|
+
schema.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
111
|
+
this.writeFile(schema);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
rename(from, to, options) {
|
|
115
|
+
if (!ALIAS_NAME_RE.test(to)) {
|
|
116
|
+
throw new (0, _chunk7Q742NI3cjs.AliasInvalidNameError)(to);
|
|
117
|
+
}
|
|
118
|
+
const schema = this.load();
|
|
119
|
+
const entry = schema.aliases[from];
|
|
120
|
+
if (!entry) {
|
|
121
|
+
throw new (0, _chunk7Q742NI3cjs.AliasNotFoundError)(from);
|
|
122
|
+
}
|
|
123
|
+
if (schema.aliases[to] && !_optionalChain([options, 'optionalAccess', _3 => _3.force])) {
|
|
124
|
+
throw new (0, _chunk7Q742NI3cjs.AliasConflictError)(to);
|
|
125
|
+
}
|
|
126
|
+
delete schema.aliases[from];
|
|
127
|
+
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
128
|
+
schema.aliases[to] = entry;
|
|
129
|
+
schema.updatedAt = entry.updatedAt;
|
|
130
|
+
this.writeFile(schema);
|
|
131
|
+
}
|
|
132
|
+
writeFile(schema) {
|
|
133
|
+
const tmp = `${this.aliasesPath}.tmp`;
|
|
134
|
+
try {
|
|
135
|
+
_fs2.default.mkdirSync(_path2.default.dirname(this.aliasesPath), { recursive: true });
|
|
136
|
+
_fs2.default.writeFileSync(tmp, JSON.stringify(schema, null, 2), "utf8");
|
|
137
|
+
_fs2.default.renameSync(tmp, this.aliasesPath);
|
|
138
|
+
} catch (cause) {
|
|
139
|
+
throw new (0, _chunk7Q742NI3cjs.AliasFileWriteError)(this.aliasesPath, cause);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/aliases/AliasResolver.ts
|
|
145
|
+
var ALIAS_NAME_RE2 = /^[a-z0-9][a-z0-9-]*$/;
|
|
146
|
+
var AliasResolver = class {
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
constructor(options) {
|
|
150
|
+
this.registry = options.registry;
|
|
151
|
+
this.catalogClient = options.catalogClient;
|
|
152
|
+
}
|
|
153
|
+
async getModel(aliasName) {
|
|
154
|
+
const entry = this.registry.get(aliasName);
|
|
155
|
+
if (!entry) {
|
|
156
|
+
throw new (0, _chunk7Q742NI3cjs.AliasNotFoundError)(aliasName);
|
|
157
|
+
}
|
|
158
|
+
return this.resolveEntry(aliasName, entry);
|
|
159
|
+
}
|
|
160
|
+
async getModels(aliasNames) {
|
|
161
|
+
const results = [];
|
|
162
|
+
for (const name of aliasNames) {
|
|
163
|
+
const entry = this.registry.get(name);
|
|
164
|
+
if (!entry) {
|
|
165
|
+
console.warn(`[ai-tools] Unknown alias "${name}" \u2014 skipped.`);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
results.push(await this.resolveEntry(name, entry));
|
|
169
|
+
}
|
|
170
|
+
return results;
|
|
171
|
+
}
|
|
172
|
+
async getAllResolved() {
|
|
173
|
+
const list = this.registry.list();
|
|
174
|
+
return Promise.all(list.map(({ name, ...entry }) => this.resolveEntry(name, entry)));
|
|
175
|
+
}
|
|
176
|
+
async validate() {
|
|
177
|
+
const list = this.registry.list();
|
|
178
|
+
const entries = [];
|
|
179
|
+
let ok = 0;
|
|
180
|
+
let unknown = 0;
|
|
181
|
+
let broken = 0;
|
|
182
|
+
for (const { name, modelId } of list) {
|
|
183
|
+
if (!ALIAS_NAME_RE2.test(name) || !modelId) {
|
|
184
|
+
broken++;
|
|
185
|
+
entries.push({
|
|
186
|
+
name,
|
|
187
|
+
status: "broken",
|
|
188
|
+
modelId: _nullishCoalesce(modelId, () => ( "")),
|
|
189
|
+
issue: "Invalid alias name or empty modelId"
|
|
190
|
+
});
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const ref = await this.resolveEntry(name, this.registry.get(name));
|
|
194
|
+
if (ref.modelRecord) {
|
|
195
|
+
ok++;
|
|
196
|
+
entries.push({
|
|
197
|
+
name,
|
|
198
|
+
status: "ok",
|
|
199
|
+
modelId: ref.modelId,
|
|
200
|
+
resolvedName: ref.name
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
unknown++;
|
|
204
|
+
entries.push({
|
|
205
|
+
name,
|
|
206
|
+
status: "unknown",
|
|
207
|
+
modelId: ref.modelId,
|
|
208
|
+
issue: "Model not found in catalog"
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
total: list.length,
|
|
214
|
+
ok,
|
|
215
|
+
unknown,
|
|
216
|
+
broken,
|
|
217
|
+
entries
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
async resolveEntry(alias, entry) {
|
|
221
|
+
const result = await this.catalogClient.resolveModel({
|
|
222
|
+
model: entry.modelId,
|
|
223
|
+
provider: entry.provider
|
|
224
|
+
});
|
|
225
|
+
return {
|
|
226
|
+
alias,
|
|
227
|
+
entry,
|
|
228
|
+
modelRecord: result.found ? result.record : null,
|
|
229
|
+
modelId: result.found ? result.modelId : entry.modelId,
|
|
230
|
+
provider: entry.provider,
|
|
231
|
+
name: _nullishCoalesce(_optionalChain([result, 'access', _4 => _4.record, 'optionalAccess', _5 => _5.name]), () => ( entry.modelId))
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
exports.AliasRegistry = AliasRegistry; exports.AliasResolver = AliasResolver;
|
|
240
|
+
//# sourceMappingURL=chunk-QWAX7VQO.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-QWAX7VQO.cjs","../src/aliases/AliasRegistry.ts","../src/aliases/AliasResolver.ts"],"names":["ALIAS_NAME_RE"],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-QWAX7VQO.cjs","sourcesContent":[null,"import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport {\n AliasConflictError,\n AliasFileParseError,\n AliasFileWriteError,\n AliasInvalidNameError,\n AliasNotFoundError,\n} from \"../errors.js\";\nimport type { AliasEntry, AliasFileSchema } from \"./types.js\";\n\nconst ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\nconst aliasEntrySchema = z.object({\n modelId: z.string().min(1),\n provider: z.string().min(1),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n addedAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst aliasFileSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n updatedAt: z.string(),\n aliases: z.record(aliasEntrySchema),\n});\n\nexport type AliasRegistryOptions = {\n aliasesPath?: string;\n};\n\nfunction defaultAliasesPath(): string {\n if (process.env.AI_TOOLS_ALIASES_PATH) {\n return path.resolve(process.env.AI_TOOLS_ALIASES_PATH);\n }\n return path.resolve(process.cwd(), \"ai-tools/aliases.json\");\n}\n\nfunction emptySchema(): AliasFileSchema {\n const now = new Date().toISOString();\n return {\n $schema: \"https://unpkg.com/@x12i/ai-tools/schemas/aliases.json\",\n version: 1,\n updatedAt: now,\n aliases: {},\n };\n}\n\nexport class AliasRegistry {\n private readonly aliasesPath: string;\n\n constructor(options: AliasRegistryOptions = {}) {\n this.aliasesPath = options.aliasesPath ?? defaultAliasesPath();\n }\n\n get path(): string {\n return this.aliasesPath;\n }\n\n exists(): boolean {\n return fs.existsSync(this.aliasesPath);\n }\n\n init(): void {\n if (this.exists()) return;\n fs.mkdirSync(path.dirname(this.aliasesPath), { recursive: true });\n this.writeFile(emptySchema());\n }\n\n load(): AliasFileSchema {\n if (!this.exists()) return emptySchema();\n\n let raw: string;\n try {\n raw = fs.readFileSync(this.aliasesPath, \"utf8\");\n } catch (cause) {\n throw new AliasFileParseError(this.aliasesPath, cause);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new AliasFileParseError(this.aliasesPath, cause);\n }\n\n const result = aliasFileSchema.safeParse(parsed);\n if (!result.success) {\n throw new AliasFileParseError(this.aliasesPath, result.error);\n }\n\n return result.data;\n }\n\n get(aliasName: string): AliasEntry | null {\n const schema = this.load();\n return schema.aliases[aliasName] ?? null;\n }\n\n list(filter?: { tag?: string }): Array<{ name: string } & AliasEntry> {\n const schema = this.load();\n return Object.entries(schema.aliases)\n .filter(([, entry]) => !filter?.tag || (entry.tags ?? []).includes(filter.tag))\n .map(([name, entry]) => ({ name, ...entry }));\n }\n\n set(\n aliasName: string,\n entry: Omit<AliasEntry, \"addedAt\" | \"updatedAt\">,\n ): AliasEntry {\n if (!ALIAS_NAME_RE.test(aliasName)) {\n throw new AliasInvalidNameError(aliasName);\n }\n\n if (!this.exists()) this.init();\n\n const schema = this.load();\n const now = new Date().toISOString();\n const existing = schema.aliases[aliasName];\n\n const full: AliasEntry = {\n ...entry,\n addedAt: existing?.addedAt ?? now,\n updatedAt: now,\n };\n\n schema.aliases[aliasName] = full;\n schema.updatedAt = now;\n this.writeFile(schema);\n return full;\n }\n\n remove(aliasName: string): boolean {\n if (!this.exists()) return false;\n const schema = this.load();\n if (!schema.aliases[aliasName]) return false;\n delete schema.aliases[aliasName];\n schema.updatedAt = new Date().toISOString();\n this.writeFile(schema);\n return true;\n }\n\n rename(from: string, to: string, options?: { force?: boolean }): void {\n if (!ALIAS_NAME_RE.test(to)) {\n throw new AliasInvalidNameError(to);\n }\n\n const schema = this.load();\n const entry = schema.aliases[from];\n if (!entry) {\n throw new AliasNotFoundError(from);\n }\n if (schema.aliases[to] && !options?.force) {\n throw new AliasConflictError(to);\n }\n\n delete schema.aliases[from];\n entry.updatedAt = new Date().toISOString();\n schema.aliases[to] = entry;\n schema.updatedAt = entry.updatedAt;\n this.writeFile(schema);\n }\n\n private writeFile(schema: AliasFileSchema): void {\n const tmp = `${this.aliasesPath}.tmp`;\n try {\n fs.mkdirSync(path.dirname(this.aliasesPath), { recursive: true });\n fs.writeFileSync(tmp, JSON.stringify(schema, null, 2), \"utf8\");\n fs.renameSync(tmp, this.aliasesPath);\n } catch (cause) {\n throw new AliasFileWriteError(this.aliasesPath, cause);\n }\n }\n}\n","import { AliasNotFoundError } from \"../errors.js\";\nimport type { AiModelsCatalogClient } from \"../catalox/AiModelsCatalogClient.js\";\nimport type { AliasRegistry } from \"./AliasRegistry.js\";\nimport type { AliasValidationReport, ResolvedModelRef } from \"./types.js\";\n\nconst ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\nexport type AliasResolverOptions = {\n registry: AliasRegistry;\n catalogClient: AiModelsCatalogClient;\n};\n\nexport class AliasResolver {\n private readonly registry: AliasRegistry;\n private readonly catalogClient: AiModelsCatalogClient;\n\n constructor(options: AliasResolverOptions) {\n this.registry = options.registry;\n this.catalogClient = options.catalogClient;\n }\n\n async getModel(aliasName: string): Promise<ResolvedModelRef> {\n const entry = this.registry.get(aliasName);\n if (!entry) {\n throw new AliasNotFoundError(aliasName);\n }\n return this.resolveEntry(aliasName, entry);\n }\n\n async getModels(aliasNames: string[]): Promise<ResolvedModelRef[]> {\n const results: ResolvedModelRef[] = [];\n for (const name of aliasNames) {\n const entry = this.registry.get(name);\n if (!entry) {\n console.warn(`[ai-tools] Unknown alias \"${name}\" — skipped.`);\n continue;\n }\n results.push(await this.resolveEntry(name, entry));\n }\n return results;\n }\n\n async getAllResolved(): Promise<ResolvedModelRef[]> {\n const list = this.registry.list();\n return Promise.all(list.map(({ name, ...entry }) => this.resolveEntry(name, entry)));\n }\n\n async validate(): Promise<AliasValidationReport> {\n const list = this.registry.list();\n const entries: AliasValidationReport[\"entries\"] = [];\n let ok = 0;\n let unknown = 0;\n let broken = 0;\n\n for (const { name, modelId } of list) {\n if (!ALIAS_NAME_RE.test(name) || !modelId) {\n broken++;\n entries.push({\n name,\n status: \"broken\",\n modelId: modelId ?? \"\",\n issue: \"Invalid alias name or empty modelId\",\n });\n continue;\n }\n\n const ref = await this.resolveEntry(name, this.registry.get(name)!);\n if (ref.modelRecord) {\n ok++;\n entries.push({\n name,\n status: \"ok\",\n modelId: ref.modelId,\n resolvedName: ref.name,\n });\n } else {\n unknown++;\n entries.push({\n name,\n status: \"unknown\",\n modelId: ref.modelId,\n issue: \"Model not found in catalog\",\n });\n }\n }\n\n return {\n total: list.length,\n ok,\n unknown,\n broken,\n entries,\n };\n }\n\n private async resolveEntry(\n alias: string,\n entry: import(\"./types.js\").AliasEntry,\n ): Promise<ResolvedModelRef> {\n const result = await this.catalogClient.resolveModel({\n model: entry.modelId,\n provider: entry.provider,\n });\n\n return {\n alias,\n entry,\n modelRecord: result.found ? result.record : null,\n modelId: result.found ? result.modelId : entry.modelId,\n provider: entry.provider,\n name: result.record?.name ?? entry.modelId,\n };\n }\n}\n"]}
|