@ai-matrx/agents 0.59.186 → 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.
@@ -241,13 +241,13 @@ function setModelDiagnosticsSink(sink) {
241
241
  }
242
242
  function reportModelDiagnostic(dedupeKey, entry) {
243
243
  try {
244
- const s2 = state();
245
- if (s2.reported.has(dedupeKey)) return;
246
- s2.reported.add(dedupeKey);
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 (s2.sink) s2.sink(entry);
249
- else if (!s2.announced) {
250
- s2.announced = true;
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((s2) => ({ ...s2, isLoading: true, error: null }));
877
+ update((s3) => ({ ...s3, isLoading: true, error: null }));
878
878
  try {
879
879
  const rows3 = await readOptions();
880
- update((s2) => {
881
- const entities = { ...s2.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
- ...s2,
888
+ ...s3,
889
889
  entities,
890
890
  isLoading: false,
891
891
  error: null,
892
- fetchScope: s2.fetchScope !== "all" && s2.fetchScope !== "deprecated" ? "active" : s2.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((s2) => ({ ...s2, isLoading: false, error: message }));
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((s2) => {
910
- const detailErrorById = { ...s2.detailErrorById };
909
+ update((s3) => {
910
+ const detailErrorById = { ...s3.detailErrorById };
911
911
  delete detailErrorById[modelId];
912
- return { ...s2, detailStatusById: { ...s2.detailStatusById, [modelId]: "loading" }, detailErrorById };
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((s2) => {
930
- const existing = s2.entities[record.id];
931
- const detailErrorById = { ...s2.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
- ...s2,
935
- detailStatusById: { ...s2.detailStatusById, [modelId]: "succeeded" },
934
+ ...s3,
935
+ detailStatusById: { ...s3.detailStatusById, [modelId]: "succeeded" },
936
936
  detailErrorById,
937
937
  entities: {
938
- ...s2.entities,
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((s2) => ({
947
- ...s2,
948
- detailStatusById: { ...s2.detailStatusById, [modelId]: "failed" },
949
- detailErrorById: { ...s2.detailErrorById, [modelId]: message }
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((s2) => {
956
- const detailStatusById = { ...s2.detailStatusById };
957
- const detailErrorById = { ...s2.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 { ...s2, detailStatusById, detailErrorById };
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((s2) => ({ ...s2, classConfigStatusByOffering: { ...s2.classConfigStatusByOffering, [key]: "loading" } }));
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((s2) => ({
974
- ...s2,
975
- classConfigStatusByOffering: { ...s2.classConfigStatusByOffering, [key]: "succeeded" },
973
+ update((s3) => ({
974
+ ...s3,
975
+ classConfigStatusByOffering: { ...s3.classConfigStatusByOffering, [key]: "succeeded" },
976
976
  classConfigByOffering: {
977
- ...s2.classConfigByOffering,
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((s2) => ({ ...s2, classConfigStatusByOffering: { ...s2.classConfigStatusByOffering, [key]: "failed" } }));
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((s2) => ({ ...s2, modelClassStatus: "loading" }));
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((s2) => ({ ...s2, modelClassStatus: "succeeded", modelClassIndex: index }));
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((s2) => ({ ...s2, modelClassStatus: "failed" }));
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((s2) => {
1014
- if (s2.modelClassStatus === "succeeded") return s2;
1015
- const base = s2.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
1013
+ update((s3) => {
1014
+ if (s3.modelClassStatus === "succeeded") return s3;
1015
+ const base = s3.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
1016
1016
  return {
1017
- ...s2,
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((s2) => ({ ...s2, identityStatusById: { ...s2.identityStatusById, [modelId]: "loading" } }));
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((s2) => ({
1042
- ...s2,
1043
- identityById: { ...s2.identityById, [row.id]: row },
1044
- identityStatusById: { ...s2.identityStatusById, [row.id]: "succeeded" }
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((s2) => ({ ...s2, identityStatusById: { ...s2.identityStatusById, [modelId]: "failed" } }));
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((s2) => {
1058
- if (s2.modelClassStatus === "succeeded") return s2;
1059
- const base = s2.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
1057
+ update((s3) => {
1058
+ if (s3.modelClassStatus === "succeeded") return s3;
1059
+ const base = s3.modelClassIndex ?? { classesByModelId: {}, classOfOffering: {} };
1060
1060
  return {
1061
- ...s2,
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((s2) => {
1081
- const existing = s2.entities[record.id];
1082
- const detailErrorById = { ...s2.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
- ...s2,
1086
- detailStatusById: { ...s2.detailStatusById, [modelId]: "succeeded" },
1085
+ ...s3,
1086
+ detailStatusById: { ...s3.detailStatusById, [modelId]: "succeeded" },
1087
1087
  detailErrorById,
1088
1088
  entities: {
1089
- ...s2.entities,
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((s2) => {
1100
- const entities = { ...s2.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({ ...s2, entities, fetchScope, lastFetched, isLoading: false, error: null });
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(s2) {
1126
- if (!activeKey || activeKey[0] !== s2.entities || activeKey[1] !== s2.activeIds) {
1127
- activeKey = [s2.entities, s2.activeIds];
1128
- activeOut = s2.activeIds.map((id) => s2.entities[id]).filter((m) => !!m);
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(s2) {
1135
- if (!deprecatedKey || deprecatedKey[0] !== s2.entities || deprecatedKey[1] !== s2.deprecatedIds) {
1136
- deprecatedKey = [s2.entities, s2.deprecatedIds];
1137
- deprecatedOut = s2.deprecatedIds.map((id) => s2.entities[id]).filter((m) => !!m);
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 = (s2) => allOf(s2.entities);
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 = (s2) => optionsOf(selectActiveModels(s2));
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 = (s2) => allOptionsOf(s2.entities);
1158
- var selectModelById = (s2, modelId) => modelId ? s2.entities[modelId] : void 0;
1159
- function selectModelLabelById(s2, modelId) {
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 = s2.entities[modelId];
1162
- const identity = s2.identityById[modelId];
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 = (s2, modelId) => modelId ? s2.entities[modelId]?.name : void 0;
1166
- var selectModelClassName = (s2, modelId, offeringId) => modelClassName(s2.modelClassIndex, modelId, offeringId);
1167
- function selectModelLabelWithClass(s2, modelId, offeringId) {
1168
- const label = selectModelLabelById(s2, modelId);
1169
- return label ? withModelClass(label, selectModelClassName(s2, modelId, offeringId)) : void 0;
1170
- }
1171
- var selectModelControls = (s2, modelId) => s2.entities[modelId]?.controls;
1172
- var selectModelFetchType = (s2, modelId) => s2.entities[modelId]?._fetchType;
1173
- var selectModelFullyLoaded = (s2, modelId) => !!modelId && s2.entities[modelId]?._fetchType === "full";
1174
- var selectModelDetailError = (s2, modelId) => modelId && s2.detailErrorById[modelId] || null;
1175
- var selectModelClassConfig = (s2, modelId, offeringId) => modelId && offeringId ? s2.classConfigByOffering[classConfigKey(modelId, offeringId)] : void 0;
1176
- var selectActiveModelsReady = (s2) => (s2.fetchScope === "active" || s2.fetchScope === "all") && s2.activeIds.length > 0;
1177
- var selectDeprecatedModelsReady = (s2) => (s2.fetchScope === "deprecated" || s2.fetchScope === "all") && s2.deprecatedIds.length > 0;
1178
- var selectAllModelsReady = (s2) => s2.fetchScope === "all";
1179
- var selectModelIdentityById = (s2, modelId) => s2.identityById[modelId];
1180
- var selectModelIdentityLookupStatus = (s2, modelId) => s2.identityStatusById[modelId] ?? "idle";
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 s2 = state2[variant];
1456
- if (s2.status === "idle" || s2.status === "error") return run(variant);
1457
- if (s2.status === "ready" && s2.loadedAt !== null && Date.now() - s2.loadedAt > staleAfterMs) return run(variant);
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(n) {
1643
- const g = n / 2 ** 30;
1644
- if (g < 1) return `${Math.max(1, Math.round(n / 2 ** 20))} MB`;
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(n) {
1937
- if (this.pos + n > this.size) throw new GgufError("the file ends inside its header");
1938
- if (this.pos + n > MAX_HEADER) throw new GgufError("its header is larger than any real model's");
1939
- if (this.pos >= this.base && this.pos + n <= this.base + this.buf.length) return;
1940
- const len = Math.min(Math.max(n, CHUNK), this.size - this.pos);
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 < n) throw new GgufError("the file ends inside its header");
1943
+ if (this.buf.length < n2) throw new GgufError("the file ends inside its header");
1944
1944
  }
1945
- async view(n) {
1946
- await this.need(n);
1947
- const v = new DataView(this.buf.buffer, this.buf.byteOffset + (this.pos - this.base), n);
1948
- this.pos += n;
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 n = (await this.view(8)).getBigUint64(0, true);
1956
- if (n > BigInt(Number.MAX_SAFE_INTEGER)) throw new GgufError("a size in its header is out of range");
1957
- return Number(n);
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 s2 = new TextDecoder().decode(this.buf.subarray(at, at + len));
1964
+ const s3 = new TextDecoder().decode(this.buf.subarray(at, at + len));
1965
1965
  this.pos += len;
1966
- return s2;
1966
+ return s3;
1967
1967
  }
1968
- async skip(n) {
1969
- if (this.pos + n > this.size) throw new GgufError("the file ends inside its header");
1970
- this.pos += n;
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 n = await c.u64();
2023
- if (n > 64 * MAX_COUNT) throw new GgufError("an array in its header is out of range");
2024
- arrays[key] = n;
2025
- if (elem === 8) for (let j = 0; j < n; j++) await c.str();
2026
- else if (SCALAR_BYTES[elem] !== void 0) await c.skip(n * SCALAR_BYTES[elem]);
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 s2 = (k) => typeof h.kv[k] === "string" ? h.kv[k] : null;
2057
- const n = (k) => typeof h.kv[k] === "number" ? h.kv[k] : null;
2058
- const arch = s2("general.architecture");
2059
- const ft = n("general.file_type");
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: s2("general.name"),
2063
+ name: s3("general.name"),
2064
2064
  quant: ft !== null ? FILE_TYPE_QUANT[ft] ?? `FTYPE_${ft}` : null,
2065
- context_length: arch ? n(`${arch}.context_length`) : null,
2065
+ context_length: arch ? n2(`${arch}.context_length`) : null,
2066
2066
  parameter_count: params > 0 ? params : null,
2067
- split_count: n("split.count") ?? 1,
2068
- split_index: n("split.no") ?? 0,
2069
- type: s2("general.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((s2) => s2 !== null);
2110
+ const shards = names.map(shardName).filter((s3) => s3 !== null);
2111
2111
  if (!shards.length) return [];
2112
- const counts = [...new Set(shards.map((s2) => s2.count))];
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 n = counts[0];
2115
- const have = shards.map((s2) => s2.index);
2116
- const missing = Array.from({ length: n }, (_, i) => i + 1).filter((i) => !have.includes(i));
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 ${n}`).join(", ")} ${missing.length === 1 ? "is" : "are"} missing`);
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((s2) => s2 !== primary && shardName(s2.name)?.stem === shard.stem)];
2164
- const problems = splitSetProblems(same.map((s2) => s2.name));
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((s2) => s2 !== primary && extOf(s2.name) === ".gguf" && isProjectorName(s2.name));
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(live)) {
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 fetchCuratedModels(client) {
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 shapeCuratedModels({ models, variants, presentations, providers });
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,