@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.js
CHANGED
|
@@ -241,13 +241,13 @@ function setModelDiagnosticsSink(sink) {
|
|
|
241
241
|
}
|
|
242
242
|
function reportModelDiagnostic(dedupeKey, entry) {
|
|
243
243
|
try {
|
|
244
|
-
const
|
|
245
|
-
if (
|
|
246
|
-
|
|
244
|
+
const s3 = state();
|
|
245
|
+
if (s3.reported.has(dedupeKey)) return;
|
|
246
|
+
s3.reported.add(dedupeKey);
|
|
247
247
|
console.warn(`[parseCapabilities] ${entry.message}`);
|
|
248
|
-
if (
|
|
249
|
-
else if (!
|
|
250
|
-
|
|
248
|
+
if (s3.sink) s3.sink(entry);
|
|
249
|
+
else if (!s3.announced) {
|
|
250
|
+
s3.announced = true;
|
|
251
251
|
console.error(
|
|
252
252
|
"[@ai-matrx/agents/models] No diagnostics sink is bound \u2014 capability-vocabulary drift reaches the console only. Call setModelDiagnosticsSink(...) with your error store."
|
|
253
253
|
);
|
|
@@ -874,29 +874,29 @@ function createModelRecords(config) {
|
|
|
874
874
|
loadOptions() {
|
|
875
875
|
if (state2.fetchScope === "active" || state2.fetchScope === "all") return Promise.resolve();
|
|
876
876
|
return once("options", async () => {
|
|
877
|
-
update((
|
|
877
|
+
update((s3) => ({ ...s3, isLoading: true, error: null }));
|
|
878
878
|
try {
|
|
879
879
|
const rows3 = await readOptions();
|
|
880
|
-
update((
|
|
881
|
-
const entities = { ...
|
|
880
|
+
update((s3) => {
|
|
881
|
+
const entities = { ...s3.entities };
|
|
882
882
|
for (const row of rows3) {
|
|
883
883
|
const existing = entities[row.id];
|
|
884
884
|
if (existing?._fetchType === "full") continue;
|
|
885
885
|
entities[row.id] = { ...emptyRecord(), ...existing, ...row, _fetchType: "options" };
|
|
886
886
|
}
|
|
887
887
|
return withIdLists({
|
|
888
|
-
...
|
|
888
|
+
...s3,
|
|
889
889
|
entities,
|
|
890
890
|
isLoading: false,
|
|
891
891
|
error: null,
|
|
892
|
-
fetchScope:
|
|
892
|
+
fetchScope: s3.fetchScope !== "all" && s3.fetchScope !== "deprecated" ? "active" : s3.fetchScope,
|
|
893
893
|
lastFetched: Date.now()
|
|
894
894
|
});
|
|
895
895
|
});
|
|
896
896
|
} catch (err) {
|
|
897
897
|
const message = messageOf(err);
|
|
898
898
|
errorSink({ code: "model-records-options-load-failed", message });
|
|
899
|
-
update((
|
|
899
|
+
update((s3) => ({ ...s3, isLoading: false, error: message }));
|
|
900
900
|
}
|
|
901
901
|
});
|
|
902
902
|
},
|
|
@@ -906,10 +906,10 @@ function createModelRecords(config) {
|
|
|
906
906
|
return inFlight.get(`model:${modelId}`) ?? Promise.resolve();
|
|
907
907
|
}
|
|
908
908
|
return once(`model:${modelId}`, async () => {
|
|
909
|
-
update((
|
|
910
|
-
const detailErrorById = { ...
|
|
909
|
+
update((s3) => {
|
|
910
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
911
911
|
delete detailErrorById[modelId];
|
|
912
|
-
return { ...
|
|
912
|
+
return { ...s3, detailStatusById: { ...s3.detailStatusById, [modelId]: "loading" }, detailErrorById };
|
|
913
913
|
});
|
|
914
914
|
try {
|
|
915
915
|
const relation = await isSignedIn() ? "model_config" : "model_public";
|
|
@@ -926,16 +926,16 @@ function createModelRecords(config) {
|
|
|
926
926
|
capabilities: requireCanonicalCapabilities(row.capabilities, { modelId: row.id, modelName: row.name })
|
|
927
927
|
};
|
|
928
928
|
const record = normalizeModel(read);
|
|
929
|
-
update((
|
|
930
|
-
const existing =
|
|
931
|
-
const detailErrorById = { ...
|
|
929
|
+
update((s3) => {
|
|
930
|
+
const existing = s3.entities[record.id];
|
|
931
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
932
932
|
delete detailErrorById[modelId];
|
|
933
933
|
return withIdLists({
|
|
934
|
-
...
|
|
935
|
-
detailStatusById: { ...
|
|
934
|
+
...s3,
|
|
935
|
+
detailStatusById: { ...s3.detailStatusById, [modelId]: "succeeded" },
|
|
936
936
|
detailErrorById,
|
|
937
937
|
entities: {
|
|
938
|
-
...
|
|
938
|
+
...s3.entities,
|
|
939
939
|
[record.id]: { ...emptyRecord(), ...existing, ...record, maker: record.maker ?? existing?.maker ?? null, _fetchType: "full" }
|
|
940
940
|
}
|
|
941
941
|
});
|
|
@@ -943,21 +943,21 @@ function createModelRecords(config) {
|
|
|
943
943
|
} catch (err) {
|
|
944
944
|
const message = `Model configuration ${modelId}: ${messageOf(err)}`;
|
|
945
945
|
errorSink({ code: "model-records-model-load-failed", message, context: { modelId } });
|
|
946
|
-
update((
|
|
947
|
-
...
|
|
948
|
-
detailStatusById: { ...
|
|
949
|
-
detailErrorById: { ...
|
|
946
|
+
update((s3) => ({
|
|
947
|
+
...s3,
|
|
948
|
+
detailStatusById: { ...s3.detailStatusById, [modelId]: "failed" },
|
|
949
|
+
detailErrorById: { ...s3.detailErrorById, [modelId]: message }
|
|
950
950
|
}));
|
|
951
951
|
}
|
|
952
952
|
});
|
|
953
953
|
},
|
|
954
954
|
retryModel(modelId) {
|
|
955
|
-
update((
|
|
956
|
-
const detailStatusById = { ...
|
|
957
|
-
const detailErrorById = { ...
|
|
955
|
+
update((s3) => {
|
|
956
|
+
const detailStatusById = { ...s3.detailStatusById };
|
|
957
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
958
958
|
delete detailStatusById[modelId];
|
|
959
959
|
delete detailErrorById[modelId];
|
|
960
|
-
return { ...
|
|
960
|
+
return { ...s3, detailStatusById, detailErrorById };
|
|
961
961
|
});
|
|
962
962
|
},
|
|
963
963
|
loadClassConfig(modelId, offeringId) {
|
|
@@ -965,37 +965,37 @@ function createModelRecords(config) {
|
|
|
965
965
|
const status = state2.classConfigStatusByOffering[key];
|
|
966
966
|
if (status === "loading" || status === "succeeded") return inFlight.get(`class:${key}`) ?? Promise.resolve();
|
|
967
967
|
return once(`class:${key}`, async () => {
|
|
968
|
-
update((
|
|
968
|
+
update((s3) => ({ ...s3, classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "loading" } }));
|
|
969
969
|
try {
|
|
970
970
|
const { data, error } = await ai().rpc("resolve_model_config", { p_model_id: modelId, p_offering_id: offeringId });
|
|
971
971
|
if (error) throw error;
|
|
972
972
|
const cfg = data && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
973
|
-
update((
|
|
974
|
-
...
|
|
975
|
-
classConfigStatusByOffering: { ...
|
|
973
|
+
update((s3) => ({
|
|
974
|
+
...s3,
|
|
975
|
+
classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "succeeded" },
|
|
976
976
|
classConfigByOffering: {
|
|
977
|
-
...
|
|
977
|
+
...s3.classConfigByOffering,
|
|
978
978
|
[key]: { modelId, controls: cfg?.controls ?? null, constraints: cfg?.constraints ?? null }
|
|
979
979
|
}
|
|
980
980
|
}));
|
|
981
981
|
} catch (err) {
|
|
982
982
|
errorSink({ code: "model-records-class-config-failed", message: `Model class configuration ${modelId} / ${offeringId}: ${messageOf(err)}` });
|
|
983
|
-
update((
|
|
983
|
+
update((s3) => ({ ...s3, classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "failed" } }));
|
|
984
984
|
}
|
|
985
985
|
});
|
|
986
986
|
},
|
|
987
987
|
loadClasses() {
|
|
988
988
|
if (state2.modelClassStatus === "loading" || state2.modelClassStatus === "succeeded") return inFlight.get("classes") ?? Promise.resolve();
|
|
989
989
|
return once("classes", async () => {
|
|
990
|
-
update((
|
|
990
|
+
update((s3) => ({ ...s3, modelClassStatus: "loading" }));
|
|
991
991
|
try {
|
|
992
992
|
const { data, error } = await ai().from("model_offering").select("model_id, offering_id, served_via, served_via_endpoint_id, priority");
|
|
993
993
|
if (error) throw error;
|
|
994
994
|
const index = buildModelClassIndex(data ?? []);
|
|
995
|
-
update((
|
|
995
|
+
update((s3) => ({ ...s3, modelClassStatus: "succeeded", modelClassIndex: index }));
|
|
996
996
|
} catch (err) {
|
|
997
997
|
errorSink({ code: "model-records-classes-failed", message: `Model classes: ${messageOf(err)}` });
|
|
998
|
-
update((
|
|
998
|
+
update((s3) => ({ ...s3, modelClassStatus: "failed" }));
|
|
999
999
|
}
|
|
1000
1000
|
});
|
|
1001
1001
|
},
|
|
@@ -1010,11 +1010,11 @@ function createModelRecords(config) {
|
|
|
1010
1010
|
if (error) throw error;
|
|
1011
1011
|
const slice = buildModelClassIndex(data ?? []);
|
|
1012
1012
|
classesReadFor.add(modelId);
|
|
1013
|
-
update((
|
|
1014
|
-
if (
|
|
1015
|
-
const base =
|
|
1013
|
+
update((s3) => {
|
|
1014
|
+
if (s3.modelClassStatus === "succeeded") return s3;
|
|
1015
|
+
const base = s3.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
|
|
1016
1016
|
return {
|
|
1017
|
-
...
|
|
1017
|
+
...s3,
|
|
1018
1018
|
modelClassIndex: {
|
|
1019
1019
|
classesByModelId: { ...base.classesByModelId, ...slice.classesByModelId },
|
|
1020
1020
|
classOfOffering: { ...base.classOfOffering, ...slice.classOfOffering }
|
|
@@ -1032,20 +1032,20 @@ function createModelRecords(config) {
|
|
|
1032
1032
|
return inFlight.get(`identity:${modelId}`) ?? Promise.resolve();
|
|
1033
1033
|
}
|
|
1034
1034
|
return once(`identity:${modelId}`, async () => {
|
|
1035
|
-
update((
|
|
1035
|
+
update((s3) => ({ ...s3, identityStatusById: { ...s3.identityStatusById, [modelId]: "loading" } }));
|
|
1036
1036
|
try {
|
|
1037
1037
|
const { data, error } = await ai().from("model_definition").select("id, name, common_name, is_deprecated").eq("id", modelId).maybeSingle();
|
|
1038
1038
|
if (error) throw error;
|
|
1039
1039
|
if (!data) throw new Error(`AI model ${modelId} is not available (ai.model_definition has no such row)`);
|
|
1040
1040
|
const row = data;
|
|
1041
|
-
update((
|
|
1042
|
-
...
|
|
1043
|
-
identityById: { ...
|
|
1044
|
-
identityStatusById: { ...
|
|
1041
|
+
update((s3) => ({
|
|
1042
|
+
...s3,
|
|
1043
|
+
identityById: { ...s3.identityById, [row.id]: row },
|
|
1044
|
+
identityStatusById: { ...s3.identityStatusById, [row.id]: "succeeded" }
|
|
1045
1045
|
}));
|
|
1046
1046
|
} catch (err) {
|
|
1047
1047
|
errorSink({ code: "model-records-identity-failed", message: messageOf(err), context: { modelId } });
|
|
1048
|
-
update((
|
|
1048
|
+
update((s3) => ({ ...s3, identityStatusById: { ...s3.identityStatusById, [modelId]: "failed" } }));
|
|
1049
1049
|
}
|
|
1050
1050
|
});
|
|
1051
1051
|
},
|
|
@@ -1054,11 +1054,11 @@ function createModelRecords(config) {
|
|
|
1054
1054
|
if (!classesReadFor.has(modelId) && state2.modelClassStatus !== "succeeded") {
|
|
1055
1055
|
const slice = buildModelClassIndex(offerings.filter((o) => o.model_id === modelId));
|
|
1056
1056
|
classesReadFor.add(modelId);
|
|
1057
|
-
update((
|
|
1058
|
-
if (
|
|
1059
|
-
const base =
|
|
1057
|
+
update((s3) => {
|
|
1058
|
+
if (s3.modelClassStatus === "succeeded") return s3;
|
|
1059
|
+
const base = s3.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
|
|
1060
1060
|
return {
|
|
1061
|
-
...
|
|
1061
|
+
...s3,
|
|
1062
1062
|
modelClassIndex: {
|
|
1063
1063
|
classesByModelId: { ...base.classesByModelId, ...slice.classesByModelId },
|
|
1064
1064
|
classOfOffering: { ...base.classOfOffering, ...slice.classOfOffering }
|
|
@@ -1077,16 +1077,16 @@ function createModelRecords(config) {
|
|
|
1077
1077
|
controls: row.controls ?? null,
|
|
1078
1078
|
capabilities: requireCanonicalCapabilities(row.capabilities, { modelId: row.id, modelName: row.name })
|
|
1079
1079
|
});
|
|
1080
|
-
update((
|
|
1081
|
-
const existing =
|
|
1082
|
-
const detailErrorById = { ...
|
|
1080
|
+
update((s3) => {
|
|
1081
|
+
const existing = s3.entities[record.id];
|
|
1082
|
+
const detailErrorById = { ...s3.detailErrorById };
|
|
1083
1083
|
delete detailErrorById[modelId];
|
|
1084
1084
|
return withIdLists({
|
|
1085
|
-
...
|
|
1086
|
-
detailStatusById: { ...
|
|
1085
|
+
...s3,
|
|
1086
|
+
detailStatusById: { ...s3.detailStatusById, [modelId]: "succeeded" },
|
|
1087
1087
|
detailErrorById,
|
|
1088
1088
|
entities: {
|
|
1089
|
-
...
|
|
1089
|
+
...s3.entities,
|
|
1090
1090
|
[record.id]: { ...emptyRecord(), ...existing, ...record, maker: record.maker ?? existing?.maker ?? null, _fetchType: "full" }
|
|
1091
1091
|
}
|
|
1092
1092
|
});
|
|
@@ -1096,14 +1096,14 @@ function createModelRecords(config) {
|
|
|
1096
1096
|
}
|
|
1097
1097
|
},
|
|
1098
1098
|
hydrate({ models, fetchType, fetchScope, lastFetched }) {
|
|
1099
|
-
update((
|
|
1100
|
-
const entities = { ...
|
|
1099
|
+
update((s3) => {
|
|
1100
|
+
const entities = { ...s3.entities };
|
|
1101
1101
|
for (const raw of models) {
|
|
1102
1102
|
const existing = entities[raw.id];
|
|
1103
1103
|
if (existing?._fetchType === "full" && fetchType === "options") continue;
|
|
1104
1104
|
entities[raw.id] = { ...emptyRecord(), ...normalizeModel({ ...raw, controls: raw.controls ?? null }), _fetchType: fetchType };
|
|
1105
1105
|
}
|
|
1106
|
-
return withIdLists({ ...
|
|
1106
|
+
return withIdLists({ ...s3, entities, fetchScope, lastFetched, isLoading: false, error: null });
|
|
1107
1107
|
});
|
|
1108
1108
|
}
|
|
1109
1109
|
};
|
|
@@ -1122,28 +1122,28 @@ function memo(fn) {
|
|
|
1122
1122
|
var UNSET = /* @__PURE__ */ Symbol("unset");
|
|
1123
1123
|
var activeKey = null;
|
|
1124
1124
|
var activeOut = [];
|
|
1125
|
-
function selectActiveModels(
|
|
1126
|
-
if (!activeKey || activeKey[0] !==
|
|
1127
|
-
activeKey = [
|
|
1128
|
-
activeOut =
|
|
1125
|
+
function selectActiveModels(s3) {
|
|
1126
|
+
if (!activeKey || activeKey[0] !== s3.entities || activeKey[1] !== s3.activeIds) {
|
|
1127
|
+
activeKey = [s3.entities, s3.activeIds];
|
|
1128
|
+
activeOut = s3.activeIds.map((id) => s3.entities[id]).filter((m) => !!m);
|
|
1129
1129
|
}
|
|
1130
1130
|
return activeOut;
|
|
1131
1131
|
}
|
|
1132
1132
|
var deprecatedKey = null;
|
|
1133
1133
|
var deprecatedOut = [];
|
|
1134
|
-
function selectDeprecatedModels(
|
|
1135
|
-
if (!deprecatedKey || deprecatedKey[0] !==
|
|
1136
|
-
deprecatedKey = [
|
|
1137
|
-
deprecatedOut =
|
|
1134
|
+
function selectDeprecatedModels(s3) {
|
|
1135
|
+
if (!deprecatedKey || deprecatedKey[0] !== s3.entities || deprecatedKey[1] !== s3.deprecatedIds) {
|
|
1136
|
+
deprecatedKey = [s3.entities, s3.deprecatedIds];
|
|
1137
|
+
deprecatedOut = s3.deprecatedIds.map((id) => s3.entities[id]).filter((m) => !!m);
|
|
1138
1138
|
}
|
|
1139
1139
|
return deprecatedOut;
|
|
1140
1140
|
}
|
|
1141
1141
|
var allOf = memo((entities) => Object.values(entities));
|
|
1142
|
-
var selectAllModels = (
|
|
1142
|
+
var selectAllModels = (s3) => allOf(s3.entities);
|
|
1143
1143
|
var optionsOf = memo(
|
|
1144
1144
|
(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 }))
|
|
1145
1145
|
);
|
|
1146
|
-
var selectModelOptions = (
|
|
1146
|
+
var selectModelOptions = (s3) => optionsOf(selectActiveModels(s3));
|
|
1147
1147
|
var allOptionsOf = memo(
|
|
1148
1148
|
(entities) => Object.values(entities).map((m) => ({
|
|
1149
1149
|
value: m.id,
|
|
@@ -1154,30 +1154,30 @@ var allOptionsOf = memo(
|
|
|
1154
1154
|
successorId: m.successor_id ?? null
|
|
1155
1155
|
}))
|
|
1156
1156
|
);
|
|
1157
|
-
var selectAllModelOptions = (
|
|
1158
|
-
var selectModelById = (
|
|
1159
|
-
function selectModelLabelById(
|
|
1157
|
+
var selectAllModelOptions = (s3) => allOptionsOf(s3.entities);
|
|
1158
|
+
var selectModelById = (s3, modelId) => modelId ? s3.entities[modelId] : void 0;
|
|
1159
|
+
function selectModelLabelById(s3, modelId) {
|
|
1160
1160
|
if (!modelId) return void 0;
|
|
1161
|
-
const m =
|
|
1162
|
-
const identity =
|
|
1161
|
+
const m = s3.entities[modelId];
|
|
1162
|
+
const identity = s3.identityById[modelId];
|
|
1163
1163
|
return m?.common_name || m?.name || identity?.common_name || identity?.name || void 0;
|
|
1164
1164
|
}
|
|
1165
|
-
var selectModelNameById = (
|
|
1166
|
-
var selectModelClassName = (
|
|
1167
|
-
function selectModelLabelWithClass(
|
|
1168
|
-
const label = selectModelLabelById(
|
|
1169
|
-
return label ? withModelClass(label, selectModelClassName(
|
|
1170
|
-
}
|
|
1171
|
-
var selectModelControls = (
|
|
1172
|
-
var selectModelFetchType = (
|
|
1173
|
-
var selectModelFullyLoaded = (
|
|
1174
|
-
var selectModelDetailError = (
|
|
1175
|
-
var selectModelClassConfig = (
|
|
1176
|
-
var selectActiveModelsReady = (
|
|
1177
|
-
var selectDeprecatedModelsReady = (
|
|
1178
|
-
var selectAllModelsReady = (
|
|
1179
|
-
var selectModelIdentityById = (
|
|
1180
|
-
var selectModelIdentityLookupStatus = (
|
|
1165
|
+
var selectModelNameById = (s3, modelId) => modelId ? s3.entities[modelId]?.name : void 0;
|
|
1166
|
+
var selectModelClassName = (s3, modelId, offeringId) => modelClassName(s3.modelClassIndex, modelId, offeringId);
|
|
1167
|
+
function selectModelLabelWithClass(s3, modelId, offeringId) {
|
|
1168
|
+
const label = selectModelLabelById(s3, modelId);
|
|
1169
|
+
return label ? withModelClass(label, selectModelClassName(s3, modelId, offeringId)) : void 0;
|
|
1170
|
+
}
|
|
1171
|
+
var selectModelControls = (s3, modelId) => s3.entities[modelId]?.controls;
|
|
1172
|
+
var selectModelFetchType = (s3, modelId) => s3.entities[modelId]?._fetchType;
|
|
1173
|
+
var selectModelFullyLoaded = (s3, modelId) => !!modelId && s3.entities[modelId]?._fetchType === "full";
|
|
1174
|
+
var selectModelDetailError = (s3, modelId) => modelId && s3.detailErrorById[modelId] || null;
|
|
1175
|
+
var selectModelClassConfig = (s3, modelId, offeringId) => modelId && offeringId ? s3.classConfigByOffering[classConfigKey(modelId, offeringId)] : void 0;
|
|
1176
|
+
var selectActiveModelsReady = (s3) => (s3.fetchScope === "active" || s3.fetchScope === "all") && s3.activeIds.length > 0;
|
|
1177
|
+
var selectDeprecatedModelsReady = (s3) => (s3.fetchScope === "deprecated" || s3.fetchScope === "all") && s3.deprecatedIds.length > 0;
|
|
1178
|
+
var selectAllModelsReady = (s3) => s3.fetchScope === "all";
|
|
1179
|
+
var selectModelIdentityById = (s3, modelId) => s3.identityById[modelId];
|
|
1180
|
+
var selectModelIdentityLookupStatus = (s3, modelId) => s3.identityStatusById[modelId] ?? "idle";
|
|
1181
1181
|
|
|
1182
1182
|
// models/catalog/store.ts
|
|
1183
1183
|
var IDLE = { status: "idle", models: [], error: null, loadedAt: null };
|
|
@@ -1452,9 +1452,9 @@ function createModelCatalog(config) {
|
|
|
1452
1452
|
};
|
|
1453
1453
|
},
|
|
1454
1454
|
load(variant) {
|
|
1455
|
-
const
|
|
1456
|
-
if (
|
|
1457
|
-
if (
|
|
1455
|
+
const s3 = state2[variant];
|
|
1456
|
+
if (s3.status === "idle" || s3.status === "error") return run(variant);
|
|
1457
|
+
if (s3.status === "ready" && s3.loadedAt !== null && Date.now() - s3.loadedAt > staleAfterMs) return run(variant);
|
|
1458
1458
|
return inFlight[variant] ?? Promise.resolve();
|
|
1459
1459
|
},
|
|
1460
1460
|
reload: (variant) => run(variant)
|
|
@@ -1639,9 +1639,9 @@ function placement(v, runtimes, device) {
|
|
|
1639
1639
|
}
|
|
1640
1640
|
return "not_compatible";
|
|
1641
1641
|
}
|
|
1642
|
-
function formatMemoryBytes(
|
|
1643
|
-
const g =
|
|
1644
|
-
if (g < 1) return `${Math.max(1, Math.round(
|
|
1642
|
+
function formatMemoryBytes(n2) {
|
|
1643
|
+
const g = n2 / 2 ** 30;
|
|
1644
|
+
if (g < 1) return `${Math.max(1, Math.round(n2 / 2 ** 20))} MB`;
|
|
1645
1645
|
return `${g < 10 ? Math.round(g * 10) / 10 : Math.round(g)} GB`;
|
|
1646
1646
|
}
|
|
1647
1647
|
function describe(c, decided, runnerUp, device) {
|
|
@@ -1933,41 +1933,41 @@ var Cursor = class {
|
|
|
1933
1933
|
this.read = read;
|
|
1934
1934
|
this.size = size;
|
|
1935
1935
|
}
|
|
1936
|
-
async need(
|
|
1937
|
-
if (this.pos +
|
|
1938
|
-
if (this.pos +
|
|
1939
|
-
if (this.pos >= this.base && this.pos +
|
|
1940
|
-
const len = Math.min(Math.max(
|
|
1936
|
+
async need(n2) {
|
|
1937
|
+
if (this.pos + n2 > this.size) throw new GgufError("the file ends inside its header");
|
|
1938
|
+
if (this.pos + n2 > MAX_HEADER) throw new GgufError("its header is larger than any real model's");
|
|
1939
|
+
if (this.pos >= this.base && this.pos + n2 <= this.base + this.buf.length) return;
|
|
1940
|
+
const len = Math.min(Math.max(n2, CHUNK), this.size - this.pos);
|
|
1941
1941
|
this.buf = await this.read(this.pos, len);
|
|
1942
1942
|
this.base = this.pos;
|
|
1943
|
-
if (this.buf.length <
|
|
1943
|
+
if (this.buf.length < n2) throw new GgufError("the file ends inside its header");
|
|
1944
1944
|
}
|
|
1945
|
-
async view(
|
|
1946
|
-
await this.need(
|
|
1947
|
-
const v = new DataView(this.buf.buffer, this.buf.byteOffset + (this.pos - this.base),
|
|
1948
|
-
this.pos +=
|
|
1945
|
+
async view(n2) {
|
|
1946
|
+
await this.need(n2);
|
|
1947
|
+
const v = new DataView(this.buf.buffer, this.buf.byteOffset + (this.pos - this.base), n2);
|
|
1948
|
+
this.pos += n2;
|
|
1949
1949
|
return v;
|
|
1950
1950
|
}
|
|
1951
1951
|
async u32() {
|
|
1952
1952
|
return (await this.view(4)).getUint32(0, true);
|
|
1953
1953
|
}
|
|
1954
1954
|
async u64() {
|
|
1955
|
-
const
|
|
1956
|
-
if (
|
|
1957
|
-
return Number(
|
|
1955
|
+
const n2 = (await this.view(8)).getBigUint64(0, true);
|
|
1956
|
+
if (n2 > BigInt(Number.MAX_SAFE_INTEGER)) throw new GgufError("a size in its header is out of range");
|
|
1957
|
+
return Number(n2);
|
|
1958
1958
|
}
|
|
1959
1959
|
async str() {
|
|
1960
1960
|
const len = await this.u64();
|
|
1961
1961
|
if (len > MAX_STRING) throw new GgufError("a text value in its header is out of range");
|
|
1962
1962
|
await this.need(len);
|
|
1963
1963
|
const at = this.pos - this.base;
|
|
1964
|
-
const
|
|
1964
|
+
const s3 = new TextDecoder().decode(this.buf.subarray(at, at + len));
|
|
1965
1965
|
this.pos += len;
|
|
1966
|
-
return
|
|
1966
|
+
return s3;
|
|
1967
1967
|
}
|
|
1968
|
-
async skip(
|
|
1969
|
-
if (this.pos +
|
|
1970
|
-
this.pos +=
|
|
1968
|
+
async skip(n2) {
|
|
1969
|
+
if (this.pos + n2 > this.size) throw new GgufError("the file ends inside its header");
|
|
1970
|
+
this.pos += n2;
|
|
1971
1971
|
}
|
|
1972
1972
|
async scalar(type) {
|
|
1973
1973
|
switch (type) {
|
|
@@ -2019,11 +2019,11 @@ async function readGgufHeader(read, size) {
|
|
|
2019
2019
|
const type = await c.u32();
|
|
2020
2020
|
if (type === 9) {
|
|
2021
2021
|
const elem = await c.u32();
|
|
2022
|
-
const
|
|
2023
|
-
if (
|
|
2024
|
-
arrays[key] =
|
|
2025
|
-
if (elem === 8) for (let j = 0; j <
|
|
2026
|
-
else if (SCALAR_BYTES[elem] !== void 0) await c.skip(
|
|
2022
|
+
const n2 = await c.u64();
|
|
2023
|
+
if (n2 > 64 * MAX_COUNT) throw new GgufError("an array in its header is out of range");
|
|
2024
|
+
arrays[key] = n2;
|
|
2025
|
+
if (elem === 8) for (let j = 0; j < n2; j++) await c.str();
|
|
2026
|
+
else if (SCALAR_BYTES[elem] !== void 0) await c.skip(n2 * SCALAR_BYTES[elem]);
|
|
2027
2027
|
else throw new GgufError(`its header has an array of unknown type ${elem}`);
|
|
2028
2028
|
} else kv[key] = await c.scalar(type);
|
|
2029
2029
|
}
|
|
@@ -2053,20 +2053,20 @@ async function readGgufHeader(read, size) {
|
|
|
2053
2053
|
return { version, kv, array_lengths: arrays, tensors, data_offset: dataOffset, data_end: end };
|
|
2054
2054
|
}
|
|
2055
2055
|
function ggufFacts(h) {
|
|
2056
|
-
const
|
|
2057
|
-
const
|
|
2058
|
-
const arch =
|
|
2059
|
-
const ft =
|
|
2056
|
+
const s3 = (k) => typeof h.kv[k] === "string" ? h.kv[k] : null;
|
|
2057
|
+
const n2 = (k) => typeof h.kv[k] === "number" ? h.kv[k] : null;
|
|
2058
|
+
const arch = s3("general.architecture");
|
|
2059
|
+
const ft = n2("general.file_type");
|
|
2060
2060
|
const params = h.tensors.reduce((t, x) => t + x.dims.reduce((a, b) => a * b, 1), 0);
|
|
2061
2061
|
return {
|
|
2062
2062
|
architecture: arch,
|
|
2063
|
-
name:
|
|
2063
|
+
name: s3("general.name"),
|
|
2064
2064
|
quant: ft !== null ? FILE_TYPE_QUANT[ft] ?? `FTYPE_${ft}` : null,
|
|
2065
|
-
context_length: arch ?
|
|
2065
|
+
context_length: arch ? n2(`${arch}.context_length`) : null,
|
|
2066
2066
|
parameter_count: params > 0 ? params : null,
|
|
2067
|
-
split_count:
|
|
2068
|
-
split_index:
|
|
2069
|
-
type:
|
|
2067
|
+
split_count: n2("split.count") ?? 1,
|
|
2068
|
+
split_index: n2("split.no") ?? 0,
|
|
2069
|
+
type: s3("general.type"),
|
|
2070
2070
|
has_tokenizer: typeof h.kv["tokenizer.ggml.model"] === "string"
|
|
2071
2071
|
};
|
|
2072
2072
|
}
|
|
@@ -2107,16 +2107,16 @@ var isHelperGguf = (name) => HELPER_RE.test(name);
|
|
|
2107
2107
|
var isProjectorName = (name) => name.toLowerCase().includes("mmproj");
|
|
2108
2108
|
var quantFromName = (name) => QUANT_RE.exec(name.split("/").pop() ?? name)?.[1]?.toUpperCase() ?? null;
|
|
2109
2109
|
function splitSetProblems(names) {
|
|
2110
|
-
const shards = names.map(shardName).filter((
|
|
2110
|
+
const shards = names.map(shardName).filter((s3) => s3 !== null);
|
|
2111
2111
|
if (!shards.length) return [];
|
|
2112
|
-
const counts = [...new Set(shards.map((
|
|
2112
|
+
const counts = [...new Set(shards.map((s3) => s3.count))];
|
|
2113
2113
|
if (counts.length !== 1) return [`its parts disagree on how many parts there are (${counts.sort((a, b) => a - b).join(", ")})`];
|
|
2114
|
-
const
|
|
2115
|
-
const have = shards.map((
|
|
2116
|
-
const missing = Array.from({ length:
|
|
2114
|
+
const n2 = counts[0];
|
|
2115
|
+
const have = shards.map((s3) => s3.index);
|
|
2116
|
+
const missing = Array.from({ length: n2 }, (_, i) => i + 1).filter((i) => !have.includes(i));
|
|
2117
2117
|
const dupes = [...new Set(have.filter((i, k) => have.indexOf(i) !== k))].sort((a, b) => a - b);
|
|
2118
2118
|
const out = [];
|
|
2119
|
-
if (missing.length) out.push(`part${missing.length === 1 ? "" : "s"} ${missing.map((i) => `${i} of ${
|
|
2119
|
+
if (missing.length) out.push(`part${missing.length === 1 ? "" : "s"} ${missing.map((i) => `${i} of ${n2}`).join(", ")} ${missing.length === 1 ? "is" : "are"} missing`);
|
|
2120
2120
|
if (dupes.length) out.push(`part${dupes.length === 1 ? "" : "s"} ${dupes.join(", ")} appear${dupes.length === 1 ? "s" : ""} twice`);
|
|
2121
2121
|
return out;
|
|
2122
2122
|
}
|
|
@@ -2160,8 +2160,8 @@ async function validateModelSet(primary, siblings, env) {
|
|
|
2160
2160
|
let parts = [primary];
|
|
2161
2161
|
if (shard) {
|
|
2162
2162
|
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)}.` };
|
|
2163
|
-
const same = [primary, ...siblings.filter((
|
|
2164
|
-
const problems = splitSetProblems(same.map((
|
|
2163
|
+
const same = [primary, ...siblings.filter((s3) => s3 !== primary && shardName(s3.name)?.stem === shard.stem)];
|
|
2164
|
+
const problems = splitSetProblems(same.map((s3) => s3.name));
|
|
2165
2165
|
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).` };
|
|
2166
2166
|
parts = same.sort((a, b) => (shardName(a.name)?.index ?? 0) - (shardName(b.name)?.index ?? 0));
|
|
2167
2167
|
}
|
|
@@ -2194,7 +2194,7 @@ async function validateModelSet(primary, siblings, env) {
|
|
|
2194
2194
|
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?).` };
|
|
2195
2195
|
}
|
|
2196
2196
|
const quant = f.quant ?? quantFromName(primary.name) ?? "unknown";
|
|
2197
|
-
const projectorFiles = siblings.filter((
|
|
2197
|
+
const projectorFiles = siblings.filter((s3) => s3 !== primary && extOf(s3.name) === ".gguf" && isProjectorName(s3.name));
|
|
2198
2198
|
const pickedName = pickProjector(quant === "unknown" ? null : quant, projectorFiles.map((p) => p.name));
|
|
2199
2199
|
let projector = null;
|
|
2200
2200
|
const picked = projectorFiles.find((p) => p.name === pickedName);
|
|
@@ -2259,12 +2259,13 @@ async function rows2(client, table) {
|
|
|
2259
2259
|
if (error) throw new Error(`ai.${table}: ${error.message}`);
|
|
2260
2260
|
return (data ?? []).filter(live);
|
|
2261
2261
|
}
|
|
2262
|
+
var EXCLUDED_REVIEW_STATES = /* @__PURE__ */ new Set(["rejected", "withdrawn"]);
|
|
2263
|
+
var isListedVariant = (v) => live(v) && !EXCLUDED_REVIEW_STATES.has(s(v.review_state));
|
|
2262
2264
|
function shapeCuratedModels(input) {
|
|
2263
2265
|
const providerName = new Map(input.providers.map((p) => [s(p.id), sn(p.name)]));
|
|
2264
2266
|
const presentationOf = new Map(input.presentations.filter(live).map((p) => [s(p.model_id), p]));
|
|
2265
2267
|
const variantsOf = /* @__PURE__ */ new Map();
|
|
2266
|
-
for (const v of input.variants.filter(
|
|
2267
|
-
if (s(v.review_state) === "dismissed") continue;
|
|
2268
|
+
for (const v of input.variants.filter(isListedVariant)) {
|
|
2268
2269
|
const meta = v.metadata ?? {};
|
|
2269
2270
|
const list = variantsOf.get(s(v.model_id)) ?? [];
|
|
2270
2271
|
list.push({
|
|
@@ -2297,23 +2298,239 @@ function shapeCuratedModels(input) {
|
|
|
2297
2298
|
};
|
|
2298
2299
|
});
|
|
2299
2300
|
}
|
|
2300
|
-
async function
|
|
2301
|
+
async function readCuratedRows(client) {
|
|
2301
2302
|
const [models, variants, presentations, providers] = await Promise.all([
|
|
2302
2303
|
rows2(client, "model_definition"),
|
|
2303
2304
|
rows2(client, "model_variant"),
|
|
2304
2305
|
rows2(client, "model_presentation"),
|
|
2305
2306
|
rows2(client, "provider")
|
|
2306
2307
|
]);
|
|
2307
|
-
return
|
|
2308
|
+
return { models, variants, presentations, providers };
|
|
2309
|
+
}
|
|
2310
|
+
async function fetchCuratedModels(client) {
|
|
2311
|
+
return shapeCuratedModels(await readCuratedRows(client));
|
|
2308
2312
|
}
|
|
2309
2313
|
function curatedList(models, { offeredOnly }) {
|
|
2310
2314
|
return orderCatalogModels(offeredOnly ? models.filter((m) => m.offered) : models);
|
|
2311
2315
|
}
|
|
2316
|
+
|
|
2317
|
+
// models/catalog-reader.ts
|
|
2318
|
+
import { sha256Hex } from "@ai-matrx/kit/sha256";
|
|
2319
|
+
var MODEL_CATALOG_KINDS = /* @__PURE__ */ new Set([
|
|
2320
|
+
"llm_model",
|
|
2321
|
+
"whisper_model",
|
|
2322
|
+
"tts_model_file",
|
|
2323
|
+
"image_gen_model",
|
|
2324
|
+
"video_gen_model",
|
|
2325
|
+
"ner_model",
|
|
2326
|
+
"wake_word_model",
|
|
2327
|
+
"lora"
|
|
2328
|
+
]);
|
|
2329
|
+
function catalogKindOf(m, kindOfEntry) {
|
|
2330
|
+
for (const v of m.variants)
|
|
2331
|
+
for (const id of v.catalog_entry_ids ?? []) {
|
|
2332
|
+
const k = kindOfEntry.get(id);
|
|
2333
|
+
if (k && MODEL_CATALOG_KINDS.has(k)) return k;
|
|
2334
|
+
}
|
|
2335
|
+
const out = m.capabilities.output ?? [];
|
|
2336
|
+
const inp = m.capabilities.input ?? [];
|
|
2337
|
+
if (m.presentation?.shelf === "loras") return "lora";
|
|
2338
|
+
if (out.includes("video")) return "video_gen_model";
|
|
2339
|
+
if (out.includes("image")) return "image_gen_model";
|
|
2340
|
+
if (out.includes("audio")) return "tts_model_file";
|
|
2341
|
+
if (inp.includes("audio")) return "whisper_model";
|
|
2342
|
+
if (m.capabilities.interaction === "extraction") return "ner_model";
|
|
2343
|
+
return "llm_model";
|
|
2344
|
+
}
|
|
2345
|
+
function canonicalJson(value) {
|
|
2346
|
+
if (value === void 0) return "null";
|
|
2347
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
2348
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
2349
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
2350
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(",")}}`;
|
|
2351
|
+
}
|
|
2352
|
+
function catalogFingerprint(catalog) {
|
|
2353
|
+
const { catalog_fingerprint: _omit, ...rest } = catalog;
|
|
2354
|
+
return sha256Hex(canonicalJson(rest));
|
|
2355
|
+
}
|
|
2356
|
+
var s2 = (v) => typeof v === "string" ? v : "";
|
|
2357
|
+
var sn2 = (v) => typeof v === "string" ? v : null;
|
|
2358
|
+
var n = (v) => typeof v === "number" && Number.isFinite(v) ? v : typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v)) ? Number(v) : null;
|
|
2359
|
+
var live2 = (r) => r.deleted_at == null;
|
|
2360
|
+
var byCodepoint2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
2361
|
+
var byId = (rows3) => new Map(rows3.map((r) => [s2(r.id), r]));
|
|
2362
|
+
var strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
2363
|
+
async function readModelCatalog(client, opts = {}) {
|
|
2364
|
+
const db = client;
|
|
2365
|
+
const offeredOnly = opts.offeredOnly ?? true;
|
|
2366
|
+
const ai = db.schema("ai");
|
|
2367
|
+
const all = async (table, filter = (q) => q) => {
|
|
2368
|
+
const { data, error } = await filter(ai.from(table).select("*").is("deleted_at", null));
|
|
2369
|
+
if (error) throw new Error(`ai.${table}: ${error.message}`);
|
|
2370
|
+
return (data ?? []).filter(live2);
|
|
2371
|
+
};
|
|
2372
|
+
const [raw, upstreams, runtimes, builds, compat] = await Promise.all([
|
|
2373
|
+
readCuratedRows(client),
|
|
2374
|
+
all("model_upstream"),
|
|
2375
|
+
all("runtime"),
|
|
2376
|
+
all("runtime_build"),
|
|
2377
|
+
all("runtime_compat")
|
|
2378
|
+
]);
|
|
2379
|
+
const curated = curatedList(shapeCuratedModels(raw), { offeredOnly });
|
|
2380
|
+
const listed = new Set(curated.map((m) => m.id));
|
|
2381
|
+
const variants = raw.variants.filter((v) => listed.has(s2(v.model_id)) && (offeredOnly ? s2(v.review_state) === "offered" : isListedVariant(v)));
|
|
2382
|
+
const entryIds = [...new Set(curated.flatMap((m) => m.variants.flatMap((v) => v.catalog_entry_ids)))].sort(byCodepoint2);
|
|
2383
|
+
const warnings = [];
|
|
2384
|
+
const [artifacts, entries] = await Promise.all([
|
|
2385
|
+
variants.length ? all("model_artifact", (q) => q.in("variant_id", variants.map((v) => s2(v.id)))) : Promise.resolve([]),
|
|
2386
|
+
entryIds.length ? Promise.resolve(db.schema("public").from("catalog_entries").select("id,kind").in("id", entryIds)).then(({ data, error }) => {
|
|
2387
|
+
if (error) {
|
|
2388
|
+
warnings.push(`public.catalog_entries: ${error.message} (models placed by what they do)`);
|
|
2389
|
+
return [];
|
|
2390
|
+
}
|
|
2391
|
+
return data ?? [];
|
|
2392
|
+
}) : Promise.resolve([])
|
|
2393
|
+
]);
|
|
2394
|
+
const kindOfEntry = new Map(entries.map((e) => [s2(e.id), s2(e.kind)]));
|
|
2395
|
+
const stamps = [];
|
|
2396
|
+
const stamp = (r) => {
|
|
2397
|
+
if (r && typeof r.updated_at === "string") stamps.push(r.updated_at);
|
|
2398
|
+
};
|
|
2399
|
+
const modelById = byId(raw.models);
|
|
2400
|
+
const providerById = byId(raw.providers);
|
|
2401
|
+
const upstreamById = byId(upstreams);
|
|
2402
|
+
const presentationOf = new Map(raw.presentations.map((p) => [s2(p.model_id), p]));
|
|
2403
|
+
const models = curated.flatMap((c) => {
|
|
2404
|
+
const m = modelById.get(c.id);
|
|
2405
|
+
if (!m) return [];
|
|
2406
|
+
stamp(m);
|
|
2407
|
+
const p = presentationOf.get(c.id);
|
|
2408
|
+
stamp(p);
|
|
2409
|
+
const maker = providerById.get(s2(m.provider_id));
|
|
2410
|
+
return [
|
|
2411
|
+
{
|
|
2412
|
+
id: s2(m.id),
|
|
2413
|
+
name: s2(m.name),
|
|
2414
|
+
desktop_id: sn2(m.metadata?.desktop_id),
|
|
2415
|
+
common_name: sn2(m.common_name),
|
|
2416
|
+
maker: sn2(maker?.name),
|
|
2417
|
+
maker_logo_file_id: sn2(maker?.logo_file_id),
|
|
2418
|
+
description: sn2(m.description),
|
|
2419
|
+
capabilities: m.capabilities ?? {},
|
|
2420
|
+
kind: catalogKindOf(c, kindOfEntry),
|
|
2421
|
+
offered: c.offered,
|
|
2422
|
+
updated_at: c.updated_at,
|
|
2423
|
+
presentation: p ? {
|
|
2424
|
+
summary: sn2(p.summary),
|
|
2425
|
+
symbol: sn2(p.symbol),
|
|
2426
|
+
color: sn2(p.color),
|
|
2427
|
+
shelf: sn2(p.shelf),
|
|
2428
|
+
shelf_title: sn2(p.shelf_title),
|
|
2429
|
+
shelf_subtitle: sn2(p.shelf_subtitle),
|
|
2430
|
+
display_order: n(p.display_order),
|
|
2431
|
+
page: sn2(p.page),
|
|
2432
|
+
params_label: sn2(p.params_label),
|
|
2433
|
+
tags: strings(p.tags),
|
|
2434
|
+
links: Array.isArray(p.links) ? p.links : [],
|
|
2435
|
+
thumbnail_file_id: sn2(p.thumbnail_file_id),
|
|
2436
|
+
hero_file_id: sn2(p.hero_file_id),
|
|
2437
|
+
gallery_file_ids: strings(p.gallery_file_ids).filter((f) => f.length > 0),
|
|
2438
|
+
facts: p.facts && typeof p.facts === "object" && !Array.isArray(p.facts) ? p.facts : {}
|
|
2439
|
+
} : null,
|
|
2440
|
+
variants: variants.filter((v) => s2(v.model_id) === c.id).sort((a, b) => byCodepoint2(s2(a.key), s2(b.key))).map((v) => {
|
|
2441
|
+
stamp(v);
|
|
2442
|
+
const up = upstreamById.get(s2(v.upstream_id));
|
|
2443
|
+
stamp(up);
|
|
2444
|
+
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)));
|
|
2445
|
+
arts.forEach(stamp);
|
|
2446
|
+
return {
|
|
2447
|
+
id: s2(v.id),
|
|
2448
|
+
key: s2(v.key),
|
|
2449
|
+
catalog_key: `${s2(m.name)}/${s2(v.key)}`,
|
|
2450
|
+
review_state: s2(v.review_state),
|
|
2451
|
+
catalog_entry_ids: strings(v.metadata?.catalog_entry_ids),
|
|
2452
|
+
is_default: v.is_default === true,
|
|
2453
|
+
format: s2(v.format),
|
|
2454
|
+
quant: s2(v.quant),
|
|
2455
|
+
architecture: s2(v.architecture),
|
|
2456
|
+
chat_template_kind: s2(v.chat_template_kind),
|
|
2457
|
+
os_arch: strings(v.os_arch),
|
|
2458
|
+
selection_rank: n(v.selection_rank) ?? Number.MAX_SAFE_INTEGER,
|
|
2459
|
+
// internal-bound: a row with no rank sorts last (the column is NOT NULL; this only orders a malformed row)
|
|
2460
|
+
license: sn2(v.license_id),
|
|
2461
|
+
gated: s2(v.gated),
|
|
2462
|
+
total_bytes: n(v.total_bytes),
|
|
2463
|
+
memory_bytes_min: n(v.memory_bytes_min),
|
|
2464
|
+
memory_bytes_recommended: n(v.memory_bytes_recommended),
|
|
2465
|
+
tested_on_current_runtime: v.tested_on_current_runtime === true,
|
|
2466
|
+
min_app_version: sn2(v.min_app_version),
|
|
2467
|
+
upstream: up ? { kind: s2(up.upstream_kind), repo: sn2(up.repo), revision: sn2(up.revision) } : null,
|
|
2468
|
+
artifacts: arts.map((a) => ({
|
|
2469
|
+
role: s2(a.role),
|
|
2470
|
+
path: s2(a.path_in_repo),
|
|
2471
|
+
url: s2(a.url),
|
|
2472
|
+
size_bytes: n(a.size_bytes) ?? 0,
|
|
2473
|
+
sha256: s2(a.sha256),
|
|
2474
|
+
required_for: strings(a.required_for).sort(),
|
|
2475
|
+
shard_index: n(a.shard_index),
|
|
2476
|
+
shard_count: n(a.shard_count)
|
|
2477
|
+
}))
|
|
2478
|
+
};
|
|
2479
|
+
})
|
|
2480
|
+
}
|
|
2481
|
+
];
|
|
2482
|
+
});
|
|
2483
|
+
const out = {
|
|
2484
|
+
$schema: "matrx.model-catalog.snapshot/v1",
|
|
2485
|
+
catalog_updated_at: "",
|
|
2486
|
+
models,
|
|
2487
|
+
runtimes: runtimes.sort((a, b) => byCodepoint2(s2(a.key), s2(b.key))).map((rt) => {
|
|
2488
|
+
stamp(rt);
|
|
2489
|
+
return {
|
|
2490
|
+
key: s2(rt.key),
|
|
2491
|
+
name: s2(rt.name),
|
|
2492
|
+
upstream_repo: sn2(rt.upstream_repo),
|
|
2493
|
+
builds: builds.filter((b) => s2(b.runtime_id) === s2(rt.id)).map((b) => {
|
|
2494
|
+
stamp(b);
|
|
2495
|
+
const known = b.metadata?.known_architectures;
|
|
2496
|
+
return {
|
|
2497
|
+
id: s2(b.id),
|
|
2498
|
+
version: s2(b.runtime_version),
|
|
2499
|
+
os: s2(b.os),
|
|
2500
|
+
arch: s2(b.arch),
|
|
2501
|
+
accelerator: s2(b.accelerator),
|
|
2502
|
+
build_kind: s2(b.build_kind),
|
|
2503
|
+
url: sn2(b.url),
|
|
2504
|
+
size_bytes: n(b.size_bytes),
|
|
2505
|
+
sha256: sn2(b.sha256),
|
|
2506
|
+
is_active: b.is_active === true,
|
|
2507
|
+
min_app_version: sn2(b.min_app_version),
|
|
2508
|
+
// The architectures this pinned llama-server build loads (runtime_build.metadata): the own-model judge reads it.
|
|
2509
|
+
known_architectures: Array.isArray(known) ? known.map(String).sort() : null,
|
|
2510
|
+
compat: compat.filter((c) => s2(c.runtime_build_id) === s2(b.id)).map((c) => ({
|
|
2511
|
+
hardware_class: s2(c.hardware_class),
|
|
2512
|
+
format: s2(c.format),
|
|
2513
|
+
quant: s2(c.quant),
|
|
2514
|
+
architecture: s2(c.architecture),
|
|
2515
|
+
chat_template_kind: s2(c.chat_template_kind),
|
|
2516
|
+
status: s2(c.status)
|
|
2517
|
+
}))
|
|
2518
|
+
};
|
|
2519
|
+
})
|
|
2520
|
+
};
|
|
2521
|
+
})
|
|
2522
|
+
};
|
|
2523
|
+
out.catalog_updated_at = stamps.sort().at(-1) ?? "";
|
|
2524
|
+
if (warnings.length) out.warnings = warnings;
|
|
2525
|
+
out.catalog_fingerprint = catalogFingerprint(out);
|
|
2526
|
+
return out;
|
|
2527
|
+
}
|
|
2312
2528
|
export {
|
|
2313
2529
|
CHAT_DEFAULT_MODEL_KNOB,
|
|
2314
2530
|
CONTENT_TYPES,
|
|
2315
2531
|
DEFAULT_CAPABILITIES,
|
|
2316
2532
|
EMPTY_MODEL_RECORDS,
|
|
2533
|
+
EXCLUDED_REVIEW_STATES,
|
|
2317
2534
|
FEATURE_BUCKETS,
|
|
2318
2535
|
FEATURE_BUCKET_ORDER,
|
|
2319
2536
|
FEATURE_KEYS,
|
|
@@ -2322,6 +2539,7 @@ export {
|
|
|
2322
2539
|
INPUT_MODALITIES,
|
|
2323
2540
|
INTERACTION_MODES,
|
|
2324
2541
|
MAX_SUCCESSION_HOPS,
|
|
2542
|
+
MODEL_CATALOG_KINDS,
|
|
2325
2543
|
MODEL_FAVORITE_ENTITY_TYPE,
|
|
2326
2544
|
OUTPUT_MODALITIES,
|
|
2327
2545
|
SERVICE_LABEL,
|
|
@@ -2331,7 +2549,9 @@ export {
|
|
|
2331
2549
|
acceptsTextInstructions,
|
|
2332
2550
|
buildModelClassIndex,
|
|
2333
2551
|
buildSuccessionIndex,
|
|
2552
|
+
catalogFingerprint,
|
|
2334
2553
|
catalogForApp,
|
|
2554
|
+
catalogKindOf,
|
|
2335
2555
|
classConfigKey,
|
|
2336
2556
|
collapseTiersByClass,
|
|
2337
2557
|
costRatingTier,
|
|
@@ -2359,6 +2579,7 @@ export {
|
|
|
2359
2579
|
isFeatureKey,
|
|
2360
2580
|
isHelperGguf,
|
|
2361
2581
|
isInteractionMode,
|
|
2582
|
+
isListedVariant,
|
|
2362
2583
|
isLocalModelCatalog,
|
|
2363
2584
|
isManagedAgentModelCapability,
|
|
2364
2585
|
isProjectorName,
|
|
@@ -2384,7 +2605,9 @@ export {
|
|
|
2384
2605
|
priceTierRating,
|
|
2385
2606
|
quantFromName,
|
|
2386
2607
|
rankVariants,
|
|
2608
|
+
readCuratedRows,
|
|
2387
2609
|
readGgufHeader,
|
|
2610
|
+
readModelCatalog,
|
|
2388
2611
|
reconcileModelFavoriteIds,
|
|
2389
2612
|
reportModelDiagnostic,
|
|
2390
2613
|
requireCanonicalCapabilities,
|