@ai-matrx/agents 0.59.187 → 0.59.188
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/CHANGELOG.md +11 -1
- package/dist/content-transfer/index.cjs +1 -1
- package/dist/content-transfer/index.js +1 -1
- package/dist/content-transfer/react/index.cjs +1 -1
- package/dist/content-transfer/react/index.js +1 -1
- package/dist/mandates/index.cjs +4 -4
- package/dist/mandates/index.d.cts +6 -6
- package/dist/mandates/index.d.ts +6 -6
- package/dist/mandates/index.js +4 -4
- package/dist/models/index.cjs +366 -143
- package/dist/models/index.d.cts +128 -9
- package/dist/models/index.d.ts +128 -9
- package/dist/models/index.js +366 -143
- package/dist/models/react/index.d.cts +19 -0
- package/dist/models/react/index.d.ts +19 -0
- package/package.json +9 -9
package/dist/models/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(models_exports, {
|
|
|
24
24
|
CONTENT_TYPES: () => CONTENT_TYPES,
|
|
25
25
|
DEFAULT_CAPABILITIES: () => DEFAULT_CAPABILITIES,
|
|
26
26
|
EMPTY_MODEL_RECORDS: () => EMPTY_MODEL_RECORDS,
|
|
27
|
+
EXCLUDED_REVIEW_STATES: () => EXCLUDED_REVIEW_STATES,
|
|
27
28
|
FEATURE_BUCKETS: () => FEATURE_BUCKETS,
|
|
28
29
|
FEATURE_BUCKET_ORDER: () => FEATURE_BUCKET_ORDER,
|
|
29
30
|
FEATURE_KEYS: () => FEATURE_KEYS,
|
|
@@ -32,6 +33,7 @@ __export(models_exports, {
|
|
|
32
33
|
INPUT_MODALITIES: () => INPUT_MODALITIES,
|
|
33
34
|
INTERACTION_MODES: () => INTERACTION_MODES,
|
|
34
35
|
MAX_SUCCESSION_HOPS: () => MAX_SUCCESSION_HOPS,
|
|
36
|
+
MODEL_CATALOG_KINDS: () => MODEL_CATALOG_KINDS,
|
|
35
37
|
MODEL_FAVORITE_ENTITY_TYPE: () => MODEL_FAVORITE_ENTITY_TYPE,
|
|
36
38
|
OUTPUT_MODALITIES: () => OUTPUT_MODALITIES,
|
|
37
39
|
SERVICE_LABEL: () => SERVICE_LABEL,
|
|
@@ -41,7 +43,9 @@ __export(models_exports, {
|
|
|
41
43
|
acceptsTextInstructions: () => acceptsTextInstructions,
|
|
42
44
|
buildModelClassIndex: () => buildModelClassIndex,
|
|
43
45
|
buildSuccessionIndex: () => buildSuccessionIndex,
|
|
46
|
+
catalogFingerprint: () => catalogFingerprint,
|
|
44
47
|
catalogForApp: () => catalogForApp,
|
|
48
|
+
catalogKindOf: () => catalogKindOf,
|
|
45
49
|
classConfigKey: () => classConfigKey,
|
|
46
50
|
collapseTiersByClass: () => collapseTiersByClass,
|
|
47
51
|
costRatingTier: () => costRatingTier,
|
|
@@ -69,6 +73,7 @@ __export(models_exports, {
|
|
|
69
73
|
isFeatureKey: () => isFeatureKey,
|
|
70
74
|
isHelperGguf: () => isHelperGguf,
|
|
71
75
|
isInteractionMode: () => isInteractionMode,
|
|
76
|
+
isListedVariant: () => isListedVariant,
|
|
72
77
|
isLocalModelCatalog: () => isLocalModelCatalog,
|
|
73
78
|
isManagedAgentModelCapability: () => isManagedAgentModelCapability,
|
|
74
79
|
isProjectorName: () => isProjectorName,
|
|
@@ -94,7 +99,9 @@ __export(models_exports, {
|
|
|
94
99
|
priceTierRating: () => priceTierRating,
|
|
95
100
|
quantFromName: () => quantFromName,
|
|
96
101
|
rankVariants: () => rankVariants,
|
|
102
|
+
readCuratedRows: () => readCuratedRows,
|
|
97
103
|
readGgufHeader: () => readGgufHeader,
|
|
104
|
+
readModelCatalog: () => readModelCatalog,
|
|
98
105
|
reconcileModelFavoriteIds: () => reconcileModelFavoriteIds,
|
|
99
106
|
reportModelDiagnostic: () => reportModelDiagnostic,
|
|
100
107
|
requireCanonicalCapabilities: () => requireCanonicalCapabilities,
|
|
@@ -381,13 +388,13 @@ function setModelDiagnosticsSink(sink) {
|
|
|
381
388
|
}
|
|
382
389
|
function reportModelDiagnostic(dedupeKey, entry) {
|
|
383
390
|
try {
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
386
|
-
|
|
391
|
+
const s3 = state();
|
|
392
|
+
if (s3.reported.has(dedupeKey)) return;
|
|
393
|
+
s3.reported.add(dedupeKey);
|
|
387
394
|
console.warn(`[parseCapabilities] ${entry.message}`);
|
|
388
|
-
if (
|
|
389
|
-
else if (!
|
|
390
|
-
|
|
395
|
+
if (s3.sink) s3.sink(entry);
|
|
396
|
+
else if (!s3.announced) {
|
|
397
|
+
s3.announced = true;
|
|
391
398
|
console.error(
|
|
392
399
|
"[@ai-matrx/agents/models] No diagnostics sink is bound \u2014 capability-vocabulary drift reaches the console only. Call setModelDiagnosticsSink(...) with your error store."
|
|
393
400
|
);
|
|
@@ -1014,29 +1021,29 @@ function createModelRecords(config) {
|
|
|
1014
1021
|
loadOptions() {
|
|
1015
1022
|
if (state2.fetchScope === "active" || state2.fetchScope === "all") return Promise.resolve();
|
|
1016
1023
|
return once("options", async () => {
|
|
1017
|
-
update((
|
|
1024
|
+
update((s3) => ({ ...s3, isLoading: true, error: null }));
|
|
1018
1025
|
try {
|
|
1019
1026
|
const rows3 = await readOptions();
|
|
1020
|
-
update((
|
|
1021
|
-
const entities = { ...
|
|
1027
|
+
update((s3) => {
|
|
1028
|
+
const entities = { ...s3.entities };
|
|
1022
1029
|
for (const row of rows3) {
|
|
1023
1030
|
const existing = entities[row.id];
|
|
1024
1031
|
if (existing?._fetchType === "full") continue;
|
|
1025
1032
|
entities[row.id] = { ...emptyRecord(), ...existing, ...row, _fetchType: "options" };
|
|
1026
1033
|
}
|
|
1027
1034
|
return withIdLists({
|
|
1028
|
-
...
|
|
1035
|
+
...s3,
|
|
1029
1036
|
entities,
|
|
1030
1037
|
isLoading: false,
|
|
1031
1038
|
error: null,
|
|
1032
|
-
fetchScope:
|
|
1039
|
+
fetchScope: s3.fetchScope !== "all" && s3.fetchScope !== "deprecated" ? "active" : s3.fetchScope,
|
|
1033
1040
|
lastFetched: Date.now()
|
|
1034
1041
|
});
|
|
1035
1042
|
});
|
|
1036
1043
|
} catch (err) {
|
|
1037
1044
|
const message = messageOf(err);
|
|
1038
1045
|
errorSink({ code: "model-records-options-load-failed", message });
|
|
1039
|
-
update((
|
|
1046
|
+
update((s3) => ({ ...s3, isLoading: false, error: message }));
|
|
1040
1047
|
}
|
|
1041
1048
|
});
|
|
1042
1049
|
},
|
|
@@ -1046,10 +1053,10 @@ function createModelRecords(config) {
|
|
|
1046
1053
|
return inFlight.get(`model:${modelId}`) ?? Promise.resolve();
|
|
1047
1054
|
}
|
|
1048
1055
|
return once(`model:${modelId}`, async () => {
|
|
1049
|
-
update((
|
|
1050
|
-
const detailErrorById = { ...
|
|
1056
|
+
update((s3) => {
|
|
1057
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
1051
1058
|
delete detailErrorById[modelId];
|
|
1052
|
-
return { ...
|
|
1059
|
+
return { ...s3, detailStatusById: { ...s3.detailStatusById, [modelId]: "loading" }, detailErrorById };
|
|
1053
1060
|
});
|
|
1054
1061
|
try {
|
|
1055
1062
|
const relation = await isSignedIn() ? "model_config" : "model_public";
|
|
@@ -1066,16 +1073,16 @@ function createModelRecords(config) {
|
|
|
1066
1073
|
capabilities: requireCanonicalCapabilities(row.capabilities, { modelId: row.id, modelName: row.name })
|
|
1067
1074
|
};
|
|
1068
1075
|
const record = normalizeModel(read);
|
|
1069
|
-
update((
|
|
1070
|
-
const existing =
|
|
1071
|
-
const detailErrorById = { ...
|
|
1076
|
+
update((s3) => {
|
|
1077
|
+
const existing = s3.entities[record.id];
|
|
1078
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
1072
1079
|
delete detailErrorById[modelId];
|
|
1073
1080
|
return withIdLists({
|
|
1074
|
-
...
|
|
1075
|
-
detailStatusById: { ...
|
|
1081
|
+
...s3,
|
|
1082
|
+
detailStatusById: { ...s3.detailStatusById, [modelId]: "succeeded" },
|
|
1076
1083
|
detailErrorById,
|
|
1077
1084
|
entities: {
|
|
1078
|
-
...
|
|
1085
|
+
...s3.entities,
|
|
1079
1086
|
[record.id]: { ...emptyRecord(), ...existing, ...record, maker: record.maker ?? existing?.maker ?? null, _fetchType: "full" }
|
|
1080
1087
|
}
|
|
1081
1088
|
});
|
|
@@ -1083,21 +1090,21 @@ function createModelRecords(config) {
|
|
|
1083
1090
|
} catch (err) {
|
|
1084
1091
|
const message = `Model configuration ${modelId}: ${messageOf(err)}`;
|
|
1085
1092
|
errorSink({ code: "model-records-model-load-failed", message, context: { modelId } });
|
|
1086
|
-
update((
|
|
1087
|
-
...
|
|
1088
|
-
detailStatusById: { ...
|
|
1089
|
-
detailErrorById: { ...
|
|
1093
|
+
update((s3) => ({
|
|
1094
|
+
...s3,
|
|
1095
|
+
detailStatusById: { ...s3.detailStatusById, [modelId]: "failed" },
|
|
1096
|
+
detailErrorById: { ...s3.detailErrorById, [modelId]: message }
|
|
1090
1097
|
}));
|
|
1091
1098
|
}
|
|
1092
1099
|
});
|
|
1093
1100
|
},
|
|
1094
1101
|
retryModel(modelId) {
|
|
1095
|
-
update((
|
|
1096
|
-
const detailStatusById = { ...
|
|
1097
|
-
const detailErrorById = { ...
|
|
1102
|
+
update((s3) => {
|
|
1103
|
+
const detailStatusById = { ...s3.detailStatusById };
|
|
1104
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
1098
1105
|
delete detailStatusById[modelId];
|
|
1099
1106
|
delete detailErrorById[modelId];
|
|
1100
|
-
return { ...
|
|
1107
|
+
return { ...s3, detailStatusById, detailErrorById };
|
|
1101
1108
|
});
|
|
1102
1109
|
},
|
|
1103
1110
|
loadClassConfig(modelId, offeringId) {
|
|
@@ -1105,37 +1112,37 @@ function createModelRecords(config) {
|
|
|
1105
1112
|
const status = state2.classConfigStatusByOffering[key];
|
|
1106
1113
|
if (status === "loading" || status === "succeeded") return inFlight.get(`class:${key}`) ?? Promise.resolve();
|
|
1107
1114
|
return once(`class:${key}`, async () => {
|
|
1108
|
-
update((
|
|
1115
|
+
update((s3) => ({ ...s3, classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "loading" } }));
|
|
1109
1116
|
try {
|
|
1110
1117
|
const { data, error } = await ai().rpc("resolve_model_config", { p_model_id: modelId, p_offering_id: offeringId });
|
|
1111
1118
|
if (error) throw error;
|
|
1112
1119
|
const cfg = data && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
1113
|
-
update((
|
|
1114
|
-
...
|
|
1115
|
-
classConfigStatusByOffering: { ...
|
|
1120
|
+
update((s3) => ({
|
|
1121
|
+
...s3,
|
|
1122
|
+
classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "succeeded" },
|
|
1116
1123
|
classConfigByOffering: {
|
|
1117
|
-
...
|
|
1124
|
+
...s3.classConfigByOffering,
|
|
1118
1125
|
[key]: { modelId, controls: cfg?.controls ?? null, constraints: cfg?.constraints ?? null }
|
|
1119
1126
|
}
|
|
1120
1127
|
}));
|
|
1121
1128
|
} catch (err) {
|
|
1122
1129
|
errorSink({ code: "model-records-class-config-failed", message: `Model class configuration ${modelId} / ${offeringId}: ${messageOf(err)}` });
|
|
1123
|
-
update((
|
|
1130
|
+
update((s3) => ({ ...s3, classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "failed" } }));
|
|
1124
1131
|
}
|
|
1125
1132
|
});
|
|
1126
1133
|
},
|
|
1127
1134
|
loadClasses() {
|
|
1128
1135
|
if (state2.modelClassStatus === "loading" || state2.modelClassStatus === "succeeded") return inFlight.get("classes") ?? Promise.resolve();
|
|
1129
1136
|
return once("classes", async () => {
|
|
1130
|
-
update((
|
|
1137
|
+
update((s3) => ({ ...s3, modelClassStatus: "loading" }));
|
|
1131
1138
|
try {
|
|
1132
1139
|
const { data, error } = await ai().from("model_offering").select("model_id, offering_id, served_via, served_via_endpoint_id, priority");
|
|
1133
1140
|
if (error) throw error;
|
|
1134
1141
|
const index = buildModelClassIndex(data ?? []);
|
|
1135
|
-
update((
|
|
1142
|
+
update((s3) => ({ ...s3, modelClassStatus: "succeeded", modelClassIndex: index }));
|
|
1136
1143
|
} catch (err) {
|
|
1137
1144
|
errorSink({ code: "model-records-classes-failed", message: `Model classes: ${messageOf(err)}` });
|
|
1138
|
-
update((
|
|
1145
|
+
update((s3) => ({ ...s3, modelClassStatus: "failed" }));
|
|
1139
1146
|
}
|
|
1140
1147
|
});
|
|
1141
1148
|
},
|
|
@@ -1150,11 +1157,11 @@ function createModelRecords(config) {
|
|
|
1150
1157
|
if (error) throw error;
|
|
1151
1158
|
const slice = buildModelClassIndex(data ?? []);
|
|
1152
1159
|
classesReadFor.add(modelId);
|
|
1153
|
-
update((
|
|
1154
|
-
if (
|
|
1155
|
-
const base =
|
|
1160
|
+
update((s3) => {
|
|
1161
|
+
if (s3.modelClassStatus === "succeeded") return s3;
|
|
1162
|
+
const base = s3.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
|
|
1156
1163
|
return {
|
|
1157
|
-
...
|
|
1164
|
+
...s3,
|
|
1158
1165
|
modelClassIndex: {
|
|
1159
1166
|
classesByModelId: { ...base.classesByModelId, ...slice.classesByModelId },
|
|
1160
1167
|
classOfOffering: { ...base.classOfOffering, ...slice.classOfOffering }
|
|
@@ -1172,20 +1179,20 @@ function createModelRecords(config) {
|
|
|
1172
1179
|
return inFlight.get(`identity:${modelId}`) ?? Promise.resolve();
|
|
1173
1180
|
}
|
|
1174
1181
|
return once(`identity:${modelId}`, async () => {
|
|
1175
|
-
update((
|
|
1182
|
+
update((s3) => ({ ...s3, identityStatusById: { ...s3.identityStatusById, [modelId]: "loading" } }));
|
|
1176
1183
|
try {
|
|
1177
1184
|
const { data, error } = await ai().from("model_definition").select("id, name, common_name, is_deprecated").eq("id", modelId).maybeSingle();
|
|
1178
1185
|
if (error) throw error;
|
|
1179
1186
|
if (!data) throw new Error(`AI model ${modelId} is not available (ai.model_definition has no such row)`);
|
|
1180
1187
|
const row = data;
|
|
1181
|
-
update((
|
|
1182
|
-
...
|
|
1183
|
-
identityById: { ...
|
|
1184
|
-
identityStatusById: { ...
|
|
1188
|
+
update((s3) => ({
|
|
1189
|
+
...s3,
|
|
1190
|
+
identityById: { ...s3.identityById, [row.id]: row },
|
|
1191
|
+
identityStatusById: { ...s3.identityStatusById, [row.id]: "succeeded" }
|
|
1185
1192
|
}));
|
|
1186
1193
|
} catch (err) {
|
|
1187
1194
|
errorSink({ code: "model-records-identity-failed", message: messageOf(err), context: { modelId } });
|
|
1188
|
-
update((
|
|
1195
|
+
update((s3) => ({ ...s3, identityStatusById: { ...s3.identityStatusById, [modelId]: "failed" } }));
|
|
1189
1196
|
}
|
|
1190
1197
|
});
|
|
1191
1198
|
},
|
|
@@ -1194,11 +1201,11 @@ function createModelRecords(config) {
|
|
|
1194
1201
|
if (!classesReadFor.has(modelId) && state2.modelClassStatus !== "succeeded") {
|
|
1195
1202
|
const slice = buildModelClassIndex(offerings.filter((o) => o.model_id === modelId));
|
|
1196
1203
|
classesReadFor.add(modelId);
|
|
1197
|
-
update((
|
|
1198
|
-
if (
|
|
1199
|
-
const base =
|
|
1204
|
+
update((s3) => {
|
|
1205
|
+
if (s3.modelClassStatus === "succeeded") return s3;
|
|
1206
|
+
const base = s3.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
|
|
1200
1207
|
return {
|
|
1201
|
-
...
|
|
1208
|
+
...s3,
|
|
1202
1209
|
modelClassIndex: {
|
|
1203
1210
|
classesByModelId: { ...base.classesByModelId, ...slice.classesByModelId },
|
|
1204
1211
|
classOfOffering: { ...base.classOfOffering, ...slice.classOfOffering }
|
|
@@ -1217,16 +1224,16 @@ function createModelRecords(config) {
|
|
|
1217
1224
|
controls: row.controls ?? null,
|
|
1218
1225
|
capabilities: requireCanonicalCapabilities(row.capabilities, { modelId: row.id, modelName: row.name })
|
|
1219
1226
|
});
|
|
1220
|
-
update((
|
|
1221
|
-
const existing =
|
|
1222
|
-
const detailErrorById = { ...
|
|
1227
|
+
update((s3) => {
|
|
1228
|
+
const existing = s3.entities[record.id];
|
|
1229
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
1223
1230
|
delete detailErrorById[modelId];
|
|
1224
1231
|
return withIdLists({
|
|
1225
|
-
...
|
|
1226
|
-
detailStatusById: { ...
|
|
1232
|
+
...s3,
|
|
1233
|
+
detailStatusById: { ...s3.detailStatusById, [modelId]: "succeeded" },
|
|
1227
1234
|
detailErrorById,
|
|
1228
1235
|
entities: {
|
|
1229
|
-
...
|
|
1236
|
+
...s3.entities,
|
|
1230
1237
|
[record.id]: { ...emptyRecord(), ...existing, ...record, maker: record.maker ?? existing?.maker ?? null, _fetchType: "full" }
|
|
1231
1238
|
}
|
|
1232
1239
|
});
|
|
@@ -1236,14 +1243,14 @@ function createModelRecords(config) {
|
|
|
1236
1243
|
}
|
|
1237
1244
|
},
|
|
1238
1245
|
hydrate({ models, fetchType, fetchScope, lastFetched }) {
|
|
1239
|
-
update((
|
|
1240
|
-
const entities = { ...
|
|
1246
|
+
update((s3) => {
|
|
1247
|
+
const entities = { ...s3.entities };
|
|
1241
1248
|
for (const raw of models) {
|
|
1242
1249
|
const existing = entities[raw.id];
|
|
1243
1250
|
if (existing?._fetchType === "full" && fetchType === "options") continue;
|
|
1244
1251
|
entities[raw.id] = { ...emptyRecord(), ...normalizeModel({ ...raw, controls: raw.controls ?? null }), _fetchType: fetchType };
|
|
1245
1252
|
}
|
|
1246
|
-
return withIdLists({ ...
|
|
1253
|
+
return withIdLists({ ...s3, entities, fetchScope, lastFetched, isLoading: false, error: null });
|
|
1247
1254
|
});
|
|
1248
1255
|
}
|
|
1249
1256
|
};
|
|
@@ -1262,28 +1269,28 @@ function memo(fn) {
|
|
|
1262
1269
|
var UNSET = /* @__PURE__ */ Symbol("unset");
|
|
1263
1270
|
var activeKey = null;
|
|
1264
1271
|
var activeOut = [];
|
|
1265
|
-
function selectActiveModels(
|
|
1266
|
-
if (!activeKey || activeKey[0] !==
|
|
1267
|
-
activeKey = [
|
|
1268
|
-
activeOut =
|
|
1272
|
+
function selectActiveModels(s3) {
|
|
1273
|
+
if (!activeKey || activeKey[0] !== s3.entities || activeKey[1] !== s3.activeIds) {
|
|
1274
|
+
activeKey = [s3.entities, s3.activeIds];
|
|
1275
|
+
activeOut = s3.activeIds.map((id) => s3.entities[id]).filter((m) => !!m);
|
|
1269
1276
|
}
|
|
1270
1277
|
return activeOut;
|
|
1271
1278
|
}
|
|
1272
1279
|
var deprecatedKey = null;
|
|
1273
1280
|
var deprecatedOut = [];
|
|
1274
|
-
function selectDeprecatedModels(
|
|
1275
|
-
if (!deprecatedKey || deprecatedKey[0] !==
|
|
1276
|
-
deprecatedKey = [
|
|
1277
|
-
deprecatedOut =
|
|
1281
|
+
function selectDeprecatedModels(s3) {
|
|
1282
|
+
if (!deprecatedKey || deprecatedKey[0] !== s3.entities || deprecatedKey[1] !== s3.deprecatedIds) {
|
|
1283
|
+
deprecatedKey = [s3.entities, s3.deprecatedIds];
|
|
1284
|
+
deprecatedOut = s3.deprecatedIds.map((id) => s3.entities[id]).filter((m) => !!m);
|
|
1278
1285
|
}
|
|
1279
1286
|
return deprecatedOut;
|
|
1280
1287
|
}
|
|
1281
1288
|
var allOf = memo((entities) => Object.values(entities));
|
|
1282
|
-
var selectAllModels = (
|
|
1289
|
+
var selectAllModels = (s3) => allOf(s3.entities);
|
|
1283
1290
|
var optionsOf = memo(
|
|
1284
1291
|
(models) => models.map((m) => ({ value: m.id, label: m.common_name || m.name || m.id, maker: m.maker, costRating: m.cost_rating, speedRating: m.speed_rating }))
|
|
1285
1292
|
);
|
|
1286
|
-
var selectModelOptions = (
|
|
1293
|
+
var selectModelOptions = (s3) => optionsOf(selectActiveModels(s3));
|
|
1287
1294
|
var allOptionsOf = memo(
|
|
1288
1295
|
(entities) => Object.values(entities).map((m) => ({
|
|
1289
1296
|
value: m.id,
|
|
@@ -1294,30 +1301,30 @@ var allOptionsOf = memo(
|
|
|
1294
1301
|
successorId: m.successor_id ?? null
|
|
1295
1302
|
}))
|
|
1296
1303
|
);
|
|
1297
|
-
var selectAllModelOptions = (
|
|
1298
|
-
var selectModelById = (
|
|
1299
|
-
function selectModelLabelById(
|
|
1304
|
+
var selectAllModelOptions = (s3) => allOptionsOf(s3.entities);
|
|
1305
|
+
var selectModelById = (s3, modelId) => modelId ? s3.entities[modelId] : void 0;
|
|
1306
|
+
function selectModelLabelById(s3, modelId) {
|
|
1300
1307
|
if (!modelId) return void 0;
|
|
1301
|
-
const m =
|
|
1302
|
-
const identity =
|
|
1308
|
+
const m = s3.entities[modelId];
|
|
1309
|
+
const identity = s3.identityById[modelId];
|
|
1303
1310
|
return m?.common_name || m?.name || identity?.common_name || identity?.name || void 0;
|
|
1304
1311
|
}
|
|
1305
|
-
var selectModelNameById = (
|
|
1306
|
-
var selectModelClassName = (
|
|
1307
|
-
function selectModelLabelWithClass(
|
|
1308
|
-
const label = selectModelLabelById(
|
|
1309
|
-
return label ? withModelClass(label, selectModelClassName(
|
|
1310
|
-
}
|
|
1311
|
-
var selectModelControls = (
|
|
1312
|
-
var selectModelFetchType = (
|
|
1313
|
-
var selectModelFullyLoaded = (
|
|
1314
|
-
var selectModelDetailError = (
|
|
1315
|
-
var selectModelClassConfig = (
|
|
1316
|
-
var selectActiveModelsReady = (
|
|
1317
|
-
var selectDeprecatedModelsReady = (
|
|
1318
|
-
var selectAllModelsReady = (
|
|
1319
|
-
var selectModelIdentityById = (
|
|
1320
|
-
var selectModelIdentityLookupStatus = (
|
|
1312
|
+
var selectModelNameById = (s3, modelId) => modelId ? s3.entities[modelId]?.name : void 0;
|
|
1313
|
+
var selectModelClassName = (s3, modelId, offeringId) => modelClassName(s3.modelClassIndex, modelId, offeringId);
|
|
1314
|
+
function selectModelLabelWithClass(s3, modelId, offeringId) {
|
|
1315
|
+
const label = selectModelLabelById(s3, modelId);
|
|
1316
|
+
return label ? withModelClass(label, selectModelClassName(s3, modelId, offeringId)) : void 0;
|
|
1317
|
+
}
|
|
1318
|
+
var selectModelControls = (s3, modelId) => s3.entities[modelId]?.controls;
|
|
1319
|
+
var selectModelFetchType = (s3, modelId) => s3.entities[modelId]?._fetchType;
|
|
1320
|
+
var selectModelFullyLoaded = (s3, modelId) => !!modelId && s3.entities[modelId]?._fetchType === "full";
|
|
1321
|
+
var selectModelDetailError = (s3, modelId) => modelId && s3.detailErrorById[modelId] || null;
|
|
1322
|
+
var selectModelClassConfig = (s3, modelId, offeringId) => modelId && offeringId ? s3.classConfigByOffering[classConfigKey(modelId, offeringId)] : void 0;
|
|
1323
|
+
var selectActiveModelsReady = (s3) => (s3.fetchScope === "active" || s3.fetchScope === "all") && s3.activeIds.length > 0;
|
|
1324
|
+
var selectDeprecatedModelsReady = (s3) => (s3.fetchScope === "deprecated" || s3.fetchScope === "all") && s3.deprecatedIds.length > 0;
|
|
1325
|
+
var selectAllModelsReady = (s3) => s3.fetchScope === "all";
|
|
1326
|
+
var selectModelIdentityById = (s3, modelId) => s3.identityById[modelId];
|
|
1327
|
+
var selectModelIdentityLookupStatus = (s3, modelId) => s3.identityStatusById[modelId] ?? "idle";
|
|
1321
1328
|
|
|
1322
1329
|
// models/catalog/store.ts
|
|
1323
1330
|
var IDLE = { status: "idle", models: [], error: null, loadedAt: null };
|
|
@@ -1592,9 +1599,9 @@ function createModelCatalog(config) {
|
|
|
1592
1599
|
};
|
|
1593
1600
|
},
|
|
1594
1601
|
load(variant) {
|
|
1595
|
-
const
|
|
1596
|
-
if (
|
|
1597
|
-
if (
|
|
1602
|
+
const s3 = state2[variant];
|
|
1603
|
+
if (s3.status === "idle" || s3.status === "error") return run(variant);
|
|
1604
|
+
if (s3.status === "ready" && s3.loadedAt !== null && Date.now() - s3.loadedAt > staleAfterMs) return run(variant);
|
|
1598
1605
|
return inFlight[variant] ?? Promise.resolve();
|
|
1599
1606
|
},
|
|
1600
1607
|
reload: (variant) => run(variant)
|
|
@@ -1779,9 +1786,9 @@ function placement(v, runtimes, device) {
|
|
|
1779
1786
|
}
|
|
1780
1787
|
return "not_compatible";
|
|
1781
1788
|
}
|
|
1782
|
-
function formatMemoryBytes(
|
|
1783
|
-
const g =
|
|
1784
|
-
if (g < 1) return `${Math.max(1, Math.round(
|
|
1789
|
+
function formatMemoryBytes(n2) {
|
|
1790
|
+
const g = n2 / 2 ** 30;
|
|
1791
|
+
if (g < 1) return `${Math.max(1, Math.round(n2 / 2 ** 20))} MB`;
|
|
1785
1792
|
return `${g < 10 ? Math.round(g * 10) / 10 : Math.round(g)} GB`;
|
|
1786
1793
|
}
|
|
1787
1794
|
function describe(c, decided, runnerUp, device) {
|
|
@@ -2073,41 +2080,41 @@ var Cursor = class {
|
|
|
2073
2080
|
this.read = read;
|
|
2074
2081
|
this.size = size;
|
|
2075
2082
|
}
|
|
2076
|
-
async need(
|
|
2077
|
-
if (this.pos +
|
|
2078
|
-
if (this.pos +
|
|
2079
|
-
if (this.pos >= this.base && this.pos +
|
|
2080
|
-
const len = Math.min(Math.max(
|
|
2083
|
+
async need(n2) {
|
|
2084
|
+
if (this.pos + n2 > this.size) throw new GgufError("the file ends inside its header");
|
|
2085
|
+
if (this.pos + n2 > MAX_HEADER) throw new GgufError("its header is larger than any real model's");
|
|
2086
|
+
if (this.pos >= this.base && this.pos + n2 <= this.base + this.buf.length) return;
|
|
2087
|
+
const len = Math.min(Math.max(n2, CHUNK), this.size - this.pos);
|
|
2081
2088
|
this.buf = await this.read(this.pos, len);
|
|
2082
2089
|
this.base = this.pos;
|
|
2083
|
-
if (this.buf.length <
|
|
2090
|
+
if (this.buf.length < n2) throw new GgufError("the file ends inside its header");
|
|
2084
2091
|
}
|
|
2085
|
-
async view(
|
|
2086
|
-
await this.need(
|
|
2087
|
-
const v = new DataView(this.buf.buffer, this.buf.byteOffset + (this.pos - this.base),
|
|
2088
|
-
this.pos +=
|
|
2092
|
+
async view(n2) {
|
|
2093
|
+
await this.need(n2);
|
|
2094
|
+
const v = new DataView(this.buf.buffer, this.buf.byteOffset + (this.pos - this.base), n2);
|
|
2095
|
+
this.pos += n2;
|
|
2089
2096
|
return v;
|
|
2090
2097
|
}
|
|
2091
2098
|
async u32() {
|
|
2092
2099
|
return (await this.view(4)).getUint32(0, true);
|
|
2093
2100
|
}
|
|
2094
2101
|
async u64() {
|
|
2095
|
-
const
|
|
2096
|
-
if (
|
|
2097
|
-
return Number(
|
|
2102
|
+
const n2 = (await this.view(8)).getBigUint64(0, true);
|
|
2103
|
+
if (n2 > BigInt(Number.MAX_SAFE_INTEGER)) throw new GgufError("a size in its header is out of range");
|
|
2104
|
+
return Number(n2);
|
|
2098
2105
|
}
|
|
2099
2106
|
async str() {
|
|
2100
2107
|
const len = await this.u64();
|
|
2101
2108
|
if (len > MAX_STRING) throw new GgufError("a text value in its header is out of range");
|
|
2102
2109
|
await this.need(len);
|
|
2103
2110
|
const at = this.pos - this.base;
|
|
2104
|
-
const
|
|
2111
|
+
const s3 = new TextDecoder().decode(this.buf.subarray(at, at + len));
|
|
2105
2112
|
this.pos += len;
|
|
2106
|
-
return
|
|
2113
|
+
return s3;
|
|
2107
2114
|
}
|
|
2108
|
-
async skip(
|
|
2109
|
-
if (this.pos +
|
|
2110
|
-
this.pos +=
|
|
2115
|
+
async skip(n2) {
|
|
2116
|
+
if (this.pos + n2 > this.size) throw new GgufError("the file ends inside its header");
|
|
2117
|
+
this.pos += n2;
|
|
2111
2118
|
}
|
|
2112
2119
|
async scalar(type) {
|
|
2113
2120
|
switch (type) {
|
|
@@ -2159,11 +2166,11 @@ async function readGgufHeader(read, size) {
|
|
|
2159
2166
|
const type = await c.u32();
|
|
2160
2167
|
if (type === 9) {
|
|
2161
2168
|
const elem = await c.u32();
|
|
2162
|
-
const
|
|
2163
|
-
if (
|
|
2164
|
-
arrays[key] =
|
|
2165
|
-
if (elem === 8) for (let j = 0; j <
|
|
2166
|
-
else if (SCALAR_BYTES[elem] !== void 0) await c.skip(
|
|
2169
|
+
const n2 = await c.u64();
|
|
2170
|
+
if (n2 > 64 * MAX_COUNT) throw new GgufError("an array in its header is out of range");
|
|
2171
|
+
arrays[key] = n2;
|
|
2172
|
+
if (elem === 8) for (let j = 0; j < n2; j++) await c.str();
|
|
2173
|
+
else if (SCALAR_BYTES[elem] !== void 0) await c.skip(n2 * SCALAR_BYTES[elem]);
|
|
2167
2174
|
else throw new GgufError(`its header has an array of unknown type ${elem}`);
|
|
2168
2175
|
} else kv[key] = await c.scalar(type);
|
|
2169
2176
|
}
|
|
@@ -2193,20 +2200,20 @@ async function readGgufHeader(read, size) {
|
|
|
2193
2200
|
return { version, kv, array_lengths: arrays, tensors, data_offset: dataOffset, data_end: end };
|
|
2194
2201
|
}
|
|
2195
2202
|
function ggufFacts(h) {
|
|
2196
|
-
const
|
|
2197
|
-
const
|
|
2198
|
-
const arch =
|
|
2199
|
-
const ft =
|
|
2203
|
+
const s3 = (k) => typeof h.kv[k] === "string" ? h.kv[k] : null;
|
|
2204
|
+
const n2 = (k) => typeof h.kv[k] === "number" ? h.kv[k] : null;
|
|
2205
|
+
const arch = s3("general.architecture");
|
|
2206
|
+
const ft = n2("general.file_type");
|
|
2200
2207
|
const params = h.tensors.reduce((t, x) => t + x.dims.reduce((a, b) => a * b, 1), 0);
|
|
2201
2208
|
return {
|
|
2202
2209
|
architecture: arch,
|
|
2203
|
-
name:
|
|
2210
|
+
name: s3("general.name"),
|
|
2204
2211
|
quant: ft !== null ? FILE_TYPE_QUANT[ft] ?? `FTYPE_${ft}` : null,
|
|
2205
|
-
context_length: arch ?
|
|
2212
|
+
context_length: arch ? n2(`${arch}.context_length`) : null,
|
|
2206
2213
|
parameter_count: params > 0 ? params : null,
|
|
2207
|
-
split_count:
|
|
2208
|
-
split_index:
|
|
2209
|
-
type:
|
|
2214
|
+
split_count: n2("split.count") ?? 1,
|
|
2215
|
+
split_index: n2("split.no") ?? 0,
|
|
2216
|
+
type: s3("general.type"),
|
|
2210
2217
|
has_tokenizer: typeof h.kv["tokenizer.ggml.model"] === "string"
|
|
2211
2218
|
};
|
|
2212
2219
|
}
|
|
@@ -2247,16 +2254,16 @@ var isHelperGguf = (name) => HELPER_RE.test(name);
|
|
|
2247
2254
|
var isProjectorName = (name) => name.toLowerCase().includes("mmproj");
|
|
2248
2255
|
var quantFromName = (name) => QUANT_RE.exec(name.split("/").pop() ?? name)?.[1]?.toUpperCase() ?? null;
|
|
2249
2256
|
function splitSetProblems(names) {
|
|
2250
|
-
const shards = names.map(shardName).filter((
|
|
2257
|
+
const shards = names.map(shardName).filter((s3) => s3 !== null);
|
|
2251
2258
|
if (!shards.length) return [];
|
|
2252
|
-
const counts = [...new Set(shards.map((
|
|
2259
|
+
const counts = [...new Set(shards.map((s3) => s3.count))];
|
|
2253
2260
|
if (counts.length !== 1) return [`its parts disagree on how many parts there are (${counts.sort((a, b) => a - b).join(", ")})`];
|
|
2254
|
-
const
|
|
2255
|
-
const have = shards.map((
|
|
2256
|
-
const missing = Array.from({ length:
|
|
2261
|
+
const n2 = counts[0];
|
|
2262
|
+
const have = shards.map((s3) => s3.index);
|
|
2263
|
+
const missing = Array.from({ length: n2 }, (_, i) => i + 1).filter((i) => !have.includes(i));
|
|
2257
2264
|
const dupes = [...new Set(have.filter((i, k) => have.indexOf(i) !== k))].sort((a, b) => a - b);
|
|
2258
2265
|
const out = [];
|
|
2259
|
-
if (missing.length) out.push(`part${missing.length === 1 ? "" : "s"} ${missing.map((i) => `${i} of ${
|
|
2266
|
+
if (missing.length) out.push(`part${missing.length === 1 ? "" : "s"} ${missing.map((i) => `${i} of ${n2}`).join(", ")} ${missing.length === 1 ? "is" : "are"} missing`);
|
|
2260
2267
|
if (dupes.length) out.push(`part${dupes.length === 1 ? "" : "s"} ${dupes.join(", ")} appear${dupes.length === 1 ? "s" : ""} twice`);
|
|
2261
2268
|
return out;
|
|
2262
2269
|
}
|
|
@@ -2300,8 +2307,8 @@ async function validateModelSet(primary, siblings, env) {
|
|
|
2300
2307
|
let parts = [primary];
|
|
2301
2308
|
if (shard) {
|
|
2302
2309
|
if (shard.index !== 1) return { ok: false, reason: `This is part ${shard.index} of ${shard.count} of a split model; add its first part, ${shardFileName(shard.stem, 1, shard.count)}.` };
|
|
2303
|
-
const same = [primary, ...siblings.filter((
|
|
2304
|
-
const problems = splitSetProblems(same.map((
|
|
2310
|
+
const same = [primary, ...siblings.filter((s3) => s3 !== primary && shardName(s3.name)?.stem === shard.stem)];
|
|
2311
|
+
const problems = splitSetProblems(same.map((s3) => s3.name));
|
|
2305
2312
|
if (problems.length) return { ok: false, reason: `It is a model in ${shard.count} parts and ${problems.join("; ")} (every part has to be in the same folder).` };
|
|
2306
2313
|
parts = same.sort((a, b) => (shardName(a.name)?.index ?? 0) - (shardName(b.name)?.index ?? 0));
|
|
2307
2314
|
}
|
|
@@ -2334,7 +2341,7 @@ async function validateModelSet(primary, siblings, env) {
|
|
|
2334
2341
|
if (end !== null && p.size < end) return { ok: false, reason: `${parts.length > 1 ? `Part ${i + 1} of ${parts.length} is incomplete` : "The file is incomplete"}: it is ${formatMemoryBytes(p.size)} and its header says ${formatMemoryBytes(end)} (a download that stopped early?).` };
|
|
2335
2342
|
}
|
|
2336
2343
|
const quant = f.quant ?? quantFromName(primary.name) ?? "unknown";
|
|
2337
|
-
const projectorFiles = siblings.filter((
|
|
2344
|
+
const projectorFiles = siblings.filter((s3) => s3 !== primary && extOf(s3.name) === ".gguf" && isProjectorName(s3.name));
|
|
2338
2345
|
const pickedName = pickProjector(quant === "unknown" ? null : quant, projectorFiles.map((p) => p.name));
|
|
2339
2346
|
let projector = null;
|
|
2340
2347
|
const picked = projectorFiles.find((p) => p.name === pickedName);
|
|
@@ -2399,12 +2406,13 @@ async function rows2(client, table) {
|
|
|
2399
2406
|
if (error) throw new Error(`ai.${table}: ${error.message}`);
|
|
2400
2407
|
return (data ?? []).filter(live);
|
|
2401
2408
|
}
|
|
2409
|
+
var EXCLUDED_REVIEW_STATES = /* @__PURE__ */ new Set(["rejected", "withdrawn"]);
|
|
2410
|
+
var isListedVariant = (v) => live(v) && !EXCLUDED_REVIEW_STATES.has(s(v.review_state));
|
|
2402
2411
|
function shapeCuratedModels(input) {
|
|
2403
2412
|
const providerName = new Map(input.providers.map((p) => [s(p.id), sn(p.name)]));
|
|
2404
2413
|
const presentationOf = new Map(input.presentations.filter(live).map((p) => [s(p.model_id), p]));
|
|
2405
2414
|
const variantsOf = /* @__PURE__ */ new Map();
|
|
2406
|
-
for (const v of input.variants.filter(
|
|
2407
|
-
if (s(v.review_state) === "dismissed") continue;
|
|
2415
|
+
for (const v of input.variants.filter(isListedVariant)) {
|
|
2408
2416
|
const meta = v.metadata ?? {};
|
|
2409
2417
|
const list = variantsOf.get(s(v.model_id)) ?? [];
|
|
2410
2418
|
list.push({
|
|
@@ -2437,15 +2445,230 @@ function shapeCuratedModels(input) {
|
|
|
2437
2445
|
};
|
|
2438
2446
|
});
|
|
2439
2447
|
}
|
|
2440
|
-
async function
|
|
2448
|
+
async function readCuratedRows(client) {
|
|
2441
2449
|
const [models, variants, presentations, providers] = await Promise.all([
|
|
2442
2450
|
rows2(client, "model_definition"),
|
|
2443
2451
|
rows2(client, "model_variant"),
|
|
2444
2452
|
rows2(client, "model_presentation"),
|
|
2445
2453
|
rows2(client, "provider")
|
|
2446
2454
|
]);
|
|
2447
|
-
return
|
|
2455
|
+
return { models, variants, presentations, providers };
|
|
2456
|
+
}
|
|
2457
|
+
async function fetchCuratedModels(client) {
|
|
2458
|
+
return shapeCuratedModels(await readCuratedRows(client));
|
|
2448
2459
|
}
|
|
2449
2460
|
function curatedList(models, { offeredOnly }) {
|
|
2450
2461
|
return orderCatalogModels(offeredOnly ? models.filter((m) => m.offered) : models);
|
|
2451
2462
|
}
|
|
2463
|
+
|
|
2464
|
+
// models/catalog-reader.ts
|
|
2465
|
+
var import_sha256 = require("@ai-matrx/kit/sha256");
|
|
2466
|
+
var MODEL_CATALOG_KINDS = /* @__PURE__ */ new Set([
|
|
2467
|
+
"llm_model",
|
|
2468
|
+
"whisper_model",
|
|
2469
|
+
"tts_model_file",
|
|
2470
|
+
"image_gen_model",
|
|
2471
|
+
"video_gen_model",
|
|
2472
|
+
"ner_model",
|
|
2473
|
+
"wake_word_model",
|
|
2474
|
+
"lora"
|
|
2475
|
+
]);
|
|
2476
|
+
function catalogKindOf(m, kindOfEntry) {
|
|
2477
|
+
for (const v of m.variants)
|
|
2478
|
+
for (const id of v.catalog_entry_ids ?? []) {
|
|
2479
|
+
const k = kindOfEntry.get(id);
|
|
2480
|
+
if (k && MODEL_CATALOG_KINDS.has(k)) return k;
|
|
2481
|
+
}
|
|
2482
|
+
const out = m.capabilities.output ?? [];
|
|
2483
|
+
const inp = m.capabilities.input ?? [];
|
|
2484
|
+
if (m.presentation?.shelf === "loras") return "lora";
|
|
2485
|
+
if (out.includes("video")) return "video_gen_model";
|
|
2486
|
+
if (out.includes("image")) return "image_gen_model";
|
|
2487
|
+
if (out.includes("audio")) return "tts_model_file";
|
|
2488
|
+
if (inp.includes("audio")) return "whisper_model";
|
|
2489
|
+
if (m.capabilities.interaction === "extraction") return "ner_model";
|
|
2490
|
+
return "llm_model";
|
|
2491
|
+
}
|
|
2492
|
+
function canonicalJson(value) {
|
|
2493
|
+
if (value === void 0) return "null";
|
|
2494
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
2495
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
2496
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
2497
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(",")}}`;
|
|
2498
|
+
}
|
|
2499
|
+
function catalogFingerprint(catalog) {
|
|
2500
|
+
const { catalog_fingerprint: _omit, ...rest } = catalog;
|
|
2501
|
+
return (0, import_sha256.sha256Hex)(canonicalJson(rest));
|
|
2502
|
+
}
|
|
2503
|
+
var s2 = (v) => typeof v === "string" ? v : "";
|
|
2504
|
+
var sn2 = (v) => typeof v === "string" ? v : null;
|
|
2505
|
+
var n = (v) => typeof v === "number" && Number.isFinite(v) ? v : typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v)) ? Number(v) : null;
|
|
2506
|
+
var live2 = (r) => r.deleted_at == null;
|
|
2507
|
+
var byCodepoint2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
2508
|
+
var byId = (rows3) => new Map(rows3.map((r) => [s2(r.id), r]));
|
|
2509
|
+
var strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
2510
|
+
async function readModelCatalog(client, opts = {}) {
|
|
2511
|
+
const db = client;
|
|
2512
|
+
const offeredOnly = opts.offeredOnly ?? true;
|
|
2513
|
+
const ai = db.schema("ai");
|
|
2514
|
+
const all = async (table, filter = (q) => q) => {
|
|
2515
|
+
const { data, error } = await filter(ai.from(table).select("*").is("deleted_at", null));
|
|
2516
|
+
if (error) throw new Error(`ai.${table}: ${error.message}`);
|
|
2517
|
+
return (data ?? []).filter(live2);
|
|
2518
|
+
};
|
|
2519
|
+
const [raw, upstreams, runtimes, builds, compat] = await Promise.all([
|
|
2520
|
+
readCuratedRows(client),
|
|
2521
|
+
all("model_upstream"),
|
|
2522
|
+
all("runtime"),
|
|
2523
|
+
all("runtime_build"),
|
|
2524
|
+
all("runtime_compat")
|
|
2525
|
+
]);
|
|
2526
|
+
const curated = curatedList(shapeCuratedModels(raw), { offeredOnly });
|
|
2527
|
+
const listed = new Set(curated.map((m) => m.id));
|
|
2528
|
+
const variants = raw.variants.filter((v) => listed.has(s2(v.model_id)) && (offeredOnly ? s2(v.review_state) === "offered" : isListedVariant(v)));
|
|
2529
|
+
const entryIds = [...new Set(curated.flatMap((m) => m.variants.flatMap((v) => v.catalog_entry_ids)))].sort(byCodepoint2);
|
|
2530
|
+
const warnings = [];
|
|
2531
|
+
const [artifacts, entries] = await Promise.all([
|
|
2532
|
+
variants.length ? all("model_artifact", (q) => q.in("variant_id", variants.map((v) => s2(v.id)))) : Promise.resolve([]),
|
|
2533
|
+
entryIds.length ? Promise.resolve(db.schema("public").from("catalog_entries").select("id,kind").in("id", entryIds)).then(({ data, error }) => {
|
|
2534
|
+
if (error) {
|
|
2535
|
+
warnings.push(`public.catalog_entries: ${error.message} (models placed by what they do)`);
|
|
2536
|
+
return [];
|
|
2537
|
+
}
|
|
2538
|
+
return data ?? [];
|
|
2539
|
+
}) : Promise.resolve([])
|
|
2540
|
+
]);
|
|
2541
|
+
const kindOfEntry = new Map(entries.map((e) => [s2(e.id), s2(e.kind)]));
|
|
2542
|
+
const stamps = [];
|
|
2543
|
+
const stamp = (r) => {
|
|
2544
|
+
if (r && typeof r.updated_at === "string") stamps.push(r.updated_at);
|
|
2545
|
+
};
|
|
2546
|
+
const modelById = byId(raw.models);
|
|
2547
|
+
const providerById = byId(raw.providers);
|
|
2548
|
+
const upstreamById = byId(upstreams);
|
|
2549
|
+
const presentationOf = new Map(raw.presentations.map((p) => [s2(p.model_id), p]));
|
|
2550
|
+
const models = curated.flatMap((c) => {
|
|
2551
|
+
const m = modelById.get(c.id);
|
|
2552
|
+
if (!m) return [];
|
|
2553
|
+
stamp(m);
|
|
2554
|
+
const p = presentationOf.get(c.id);
|
|
2555
|
+
stamp(p);
|
|
2556
|
+
const maker = providerById.get(s2(m.provider_id));
|
|
2557
|
+
return [
|
|
2558
|
+
{
|
|
2559
|
+
id: s2(m.id),
|
|
2560
|
+
name: s2(m.name),
|
|
2561
|
+
desktop_id: sn2(m.metadata?.desktop_id),
|
|
2562
|
+
common_name: sn2(m.common_name),
|
|
2563
|
+
maker: sn2(maker?.name),
|
|
2564
|
+
maker_logo_file_id: sn2(maker?.logo_file_id),
|
|
2565
|
+
description: sn2(m.description),
|
|
2566
|
+
capabilities: m.capabilities ?? {},
|
|
2567
|
+
kind: catalogKindOf(c, kindOfEntry),
|
|
2568
|
+
offered: c.offered,
|
|
2569
|
+
updated_at: c.updated_at,
|
|
2570
|
+
presentation: p ? {
|
|
2571
|
+
summary: sn2(p.summary),
|
|
2572
|
+
symbol: sn2(p.symbol),
|
|
2573
|
+
color: sn2(p.color),
|
|
2574
|
+
shelf: sn2(p.shelf),
|
|
2575
|
+
shelf_title: sn2(p.shelf_title),
|
|
2576
|
+
shelf_subtitle: sn2(p.shelf_subtitle),
|
|
2577
|
+
display_order: n(p.display_order),
|
|
2578
|
+
page: sn2(p.page),
|
|
2579
|
+
params_label: sn2(p.params_label),
|
|
2580
|
+
tags: strings(p.tags),
|
|
2581
|
+
links: Array.isArray(p.links) ? p.links : [],
|
|
2582
|
+
thumbnail_file_id: sn2(p.thumbnail_file_id),
|
|
2583
|
+
hero_file_id: sn2(p.hero_file_id),
|
|
2584
|
+
gallery_file_ids: strings(p.gallery_file_ids).filter((f) => f.length > 0),
|
|
2585
|
+
facts: p.facts && typeof p.facts === "object" && !Array.isArray(p.facts) ? p.facts : {}
|
|
2586
|
+
} : null,
|
|
2587
|
+
variants: variants.filter((v) => s2(v.model_id) === c.id).sort((a, b) => byCodepoint2(s2(a.key), s2(b.key))).map((v) => {
|
|
2588
|
+
stamp(v);
|
|
2589
|
+
const up = upstreamById.get(s2(v.upstream_id));
|
|
2590
|
+
stamp(up);
|
|
2591
|
+
const arts = artifacts.filter((a) => s2(a.variant_id) === s2(v.id)).sort((a, b) => (n(a.shard_index) ?? 0) - (n(b.shard_index) ?? 0) || byCodepoint2(s2(a.path_in_repo), s2(b.path_in_repo)));
|
|
2592
|
+
arts.forEach(stamp);
|
|
2593
|
+
return {
|
|
2594
|
+
id: s2(v.id),
|
|
2595
|
+
key: s2(v.key),
|
|
2596
|
+
catalog_key: `${s2(m.name)}/${s2(v.key)}`,
|
|
2597
|
+
review_state: s2(v.review_state),
|
|
2598
|
+
catalog_entry_ids: strings(v.metadata?.catalog_entry_ids),
|
|
2599
|
+
is_default: v.is_default === true,
|
|
2600
|
+
format: s2(v.format),
|
|
2601
|
+
quant: s2(v.quant),
|
|
2602
|
+
architecture: s2(v.architecture),
|
|
2603
|
+
chat_template_kind: s2(v.chat_template_kind),
|
|
2604
|
+
os_arch: strings(v.os_arch),
|
|
2605
|
+
selection_rank: n(v.selection_rank) ?? Number.MAX_SAFE_INTEGER,
|
|
2606
|
+
// internal-bound: a row with no rank sorts last (the column is NOT NULL; this only orders a malformed row)
|
|
2607
|
+
license: sn2(v.license_id),
|
|
2608
|
+
gated: s2(v.gated),
|
|
2609
|
+
total_bytes: n(v.total_bytes),
|
|
2610
|
+
memory_bytes_min: n(v.memory_bytes_min),
|
|
2611
|
+
memory_bytes_recommended: n(v.memory_bytes_recommended),
|
|
2612
|
+
tested_on_current_runtime: v.tested_on_current_runtime === true,
|
|
2613
|
+
min_app_version: sn2(v.min_app_version),
|
|
2614
|
+
upstream: up ? { kind: s2(up.upstream_kind), repo: sn2(up.repo), revision: sn2(up.revision) } : null,
|
|
2615
|
+
artifacts: arts.map((a) => ({
|
|
2616
|
+
role: s2(a.role),
|
|
2617
|
+
path: s2(a.path_in_repo),
|
|
2618
|
+
url: s2(a.url),
|
|
2619
|
+
size_bytes: n(a.size_bytes) ?? 0,
|
|
2620
|
+
sha256: s2(a.sha256),
|
|
2621
|
+
required_for: strings(a.required_for).sort(),
|
|
2622
|
+
shard_index: n(a.shard_index),
|
|
2623
|
+
shard_count: n(a.shard_count)
|
|
2624
|
+
}))
|
|
2625
|
+
};
|
|
2626
|
+
})
|
|
2627
|
+
}
|
|
2628
|
+
];
|
|
2629
|
+
});
|
|
2630
|
+
const out = {
|
|
2631
|
+
$schema: "matrx.model-catalog.snapshot/v1",
|
|
2632
|
+
catalog_updated_at: "",
|
|
2633
|
+
models,
|
|
2634
|
+
runtimes: runtimes.sort((a, b) => byCodepoint2(s2(a.key), s2(b.key))).map((rt) => {
|
|
2635
|
+
stamp(rt);
|
|
2636
|
+
return {
|
|
2637
|
+
key: s2(rt.key),
|
|
2638
|
+
name: s2(rt.name),
|
|
2639
|
+
upstream_repo: sn2(rt.upstream_repo),
|
|
2640
|
+
builds: builds.filter((b) => s2(b.runtime_id) === s2(rt.id)).map((b) => {
|
|
2641
|
+
stamp(b);
|
|
2642
|
+
const known = b.metadata?.known_architectures;
|
|
2643
|
+
return {
|
|
2644
|
+
id: s2(b.id),
|
|
2645
|
+
version: s2(b.runtime_version),
|
|
2646
|
+
os: s2(b.os),
|
|
2647
|
+
arch: s2(b.arch),
|
|
2648
|
+
accelerator: s2(b.accelerator),
|
|
2649
|
+
build_kind: s2(b.build_kind),
|
|
2650
|
+
url: sn2(b.url),
|
|
2651
|
+
size_bytes: n(b.size_bytes),
|
|
2652
|
+
sha256: sn2(b.sha256),
|
|
2653
|
+
is_active: b.is_active === true,
|
|
2654
|
+
min_app_version: sn2(b.min_app_version),
|
|
2655
|
+
// The architectures this pinned llama-server build loads (runtime_build.metadata): the own-model judge reads it.
|
|
2656
|
+
known_architectures: Array.isArray(known) ? known.map(String).sort() : null,
|
|
2657
|
+
compat: compat.filter((c) => s2(c.runtime_build_id) === s2(b.id)).map((c) => ({
|
|
2658
|
+
hardware_class: s2(c.hardware_class),
|
|
2659
|
+
format: s2(c.format),
|
|
2660
|
+
quant: s2(c.quant),
|
|
2661
|
+
architecture: s2(c.architecture),
|
|
2662
|
+
chat_template_kind: s2(c.chat_template_kind),
|
|
2663
|
+
status: s2(c.status)
|
|
2664
|
+
}))
|
|
2665
|
+
};
|
|
2666
|
+
})
|
|
2667
|
+
};
|
|
2668
|
+
})
|
|
2669
|
+
};
|
|
2670
|
+
out.catalog_updated_at = stamps.sort().at(-1) ?? "";
|
|
2671
|
+
if (warnings.length) out.warnings = warnings;
|
|
2672
|
+
out.catalog_fingerprint = catalogFingerprint(out);
|
|
2673
|
+
return out;
|
|
2674
|
+
}
|