@dereekb/firebase-server 13.12.2 → 13.12.3

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/mcp/index.cjs.js CHANGED
@@ -357,7 +357,7 @@ function stringifyResult(result) {
357
357
  return firebase.callModelOidcScopeForCallType(callType);
358
358
  }
359
359
 
360
- function _array_like_to_array$5(arr, len) {
360
+ function _array_like_to_array$6(arr, len) {
361
361
  if (len == null || len > arr.length) len = arr.length;
362
362
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
363
363
  return arr2;
@@ -393,19 +393,19 @@ function _non_iterable_rest$2() {
393
393
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
394
394
  }
395
395
  function _sliced_to_array$2(arr, i) {
396
- return _array_with_holes$2(arr) || _iterable_to_array_limit$2(arr, i) || _unsupported_iterable_to_array$5(arr, i) || _non_iterable_rest$2();
396
+ return _array_with_holes$2(arr) || _iterable_to_array_limit$2(arr, i) || _unsupported_iterable_to_array$6(arr, i) || _non_iterable_rest$2();
397
397
  }
398
398
  function _type_of$1(obj) {
399
399
  "@swc/helpers - typeof";
400
400
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
401
401
  }
402
- function _unsupported_iterable_to_array$5(o, minLen) {
402
+ function _unsupported_iterable_to_array$6(o, minLen) {
403
403
  if (!o) return;
404
- if (typeof o === "string") return _array_like_to_array$5(o, minLen);
404
+ if (typeof o === "string") return _array_like_to_array$6(o, minLen);
405
405
  var n = Object.prototype.toString.call(o).slice(8, -1);
406
406
  if (n === "Object" && o.constructor) n = o.constructor.name;
407
407
  if (n === "Map" || n === "Set") return Array.from(n);
408
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$5(o, minLen);
408
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$6(o, minLen);
409
409
  }
410
410
  /**
411
411
  * Default `toJsonSchema()` options.
@@ -691,13 +691,13 @@ function resolveInputSchema(context) {
691
691
  return result;
692
692
  }
693
693
 
694
- function _array_like_to_array$4(arr, len) {
694
+ function _array_like_to_array$5(arr, len) {
695
695
  if (len == null || len > arr.length) len = arr.length;
696
696
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
697
697
  return arr2;
698
698
  }
699
- function _array_without_holes$4(arr) {
700
- if (Array.isArray(arr)) return _array_like_to_array$4(arr);
699
+ function _array_without_holes$5(arr) {
700
+ if (Array.isArray(arr)) return _array_like_to_array$5(arr);
701
701
  }
702
702
  function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
703
703
  try {
@@ -728,22 +728,22 @@ function _async_to_generator$3(fn) {
728
728
  });
729
729
  };
730
730
  }
731
- function _iterable_to_array$4(iter) {
731
+ function _iterable_to_array$5(iter) {
732
732
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
733
733
  }
734
- function _non_iterable_spread$4() {
734
+ function _non_iterable_spread$5() {
735
735
  throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
736
736
  }
737
- function _to_consumable_array$4(arr) {
738
- return _array_without_holes$4(arr) || _iterable_to_array$4(arr) || _unsupported_iterable_to_array$4(arr) || _non_iterable_spread$4();
737
+ function _to_consumable_array$5(arr) {
738
+ return _array_without_holes$5(arr) || _iterable_to_array$5(arr) || _unsupported_iterable_to_array$5(arr) || _non_iterable_spread$5();
739
739
  }
740
- function _unsupported_iterable_to_array$4(o, minLen) {
740
+ function _unsupported_iterable_to_array$5(o, minLen) {
741
741
  if (!o) return;
742
- if (typeof o === "string") return _array_like_to_array$4(o, minLen);
742
+ if (typeof o === "string") return _array_like_to_array$5(o, minLen);
743
743
  var n = Object.prototype.toString.call(o).slice(8, -1);
744
744
  if (n === "Object" && o.constructor) n = o.constructor.name;
745
745
  if (n === "Map" || n === "Set") return Array.from(n);
746
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$4(o, minLen);
746
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$5(o, minLen);
747
747
  }
748
748
  function _ts_generator$3(thisArg, body) {
749
749
  var f, y, t, _ = {
@@ -1048,8 +1048,8 @@ function readInChunks(input) {
1048
1048
  ];
1049
1049
  case 2:
1050
1050
  partial = _state.sent();
1051
- (_merged_results = merged.results).push.apply(_merged_results, _to_consumable_array$4(partial.results));
1052
- (_merged_errors = merged.errors).push.apply(_merged_errors, _to_consumable_array$4(partial.errors));
1051
+ (_merged_results = merged.results).push.apply(_merged_results, _to_consumable_array$5(partial.results));
1052
+ (_merged_errors = merged.errors).push.apply(_merged_errors, _to_consumable_array$5(partial.errors));
1053
1053
  _state.label = 3;
1054
1054
  case 3:
1055
1055
  offset += MCP_MODEL_GET_BATCH_SIZE;
@@ -1140,6 +1140,14 @@ var MODEL_GET_OUTPUT_SCHEMA = {
1140
1140
  }
1141
1141
  };
1142
1142
 
1143
+ function _array_like_to_array$4(arr, len) {
1144
+ if (len == null || len > arr.length) len = arr.length;
1145
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
1146
+ return arr2;
1147
+ }
1148
+ function _array_without_holes$4(arr) {
1149
+ if (Array.isArray(arr)) return _array_like_to_array$4(arr);
1150
+ }
1143
1151
  function _define_property$6(obj, key, value) {
1144
1152
  if (key in obj) {
1145
1153
  Object.defineProperty(obj, key, {
@@ -1153,6 +1161,12 @@ function _define_property$6(obj, key, value) {
1153
1161
  }
1154
1162
  return obj;
1155
1163
  }
1164
+ function _iterable_to_array$4(iter) {
1165
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1166
+ }
1167
+ function _non_iterable_spread$4() {
1168
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1169
+ }
1156
1170
  function _object_spread$2(target) {
1157
1171
  for(var i = 1; i < arguments.length; i++){
1158
1172
  var source = arguments[i] != null ? arguments[i] : {};
@@ -1168,6 +1182,36 @@ function _object_spread$2(target) {
1168
1182
  }
1169
1183
  return target;
1170
1184
  }
1185
+ function ownKeys(object, enumerableOnly) {
1186
+ var keys = Object.keys(object);
1187
+ if (Object.getOwnPropertySymbols) {
1188
+ var symbols = Object.getOwnPropertySymbols(object);
1189
+ keys.push.apply(keys, symbols);
1190
+ }
1191
+ return keys;
1192
+ }
1193
+ function _object_spread_props(target, source) {
1194
+ source = source != null ? source : {};
1195
+ if (Object.getOwnPropertyDescriptors) {
1196
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
1197
+ } else {
1198
+ ownKeys(Object(source)).forEach(function(key) {
1199
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
1200
+ });
1201
+ }
1202
+ return target;
1203
+ }
1204
+ function _to_consumable_array$4(arr) {
1205
+ return _array_without_holes$4(arr) || _iterable_to_array$4(arr) || _unsupported_iterable_to_array$4(arr) || _non_iterable_spread$4();
1206
+ }
1207
+ function _unsupported_iterable_to_array$4(o, minLen) {
1208
+ if (!o) return;
1209
+ if (typeof o === "string") return _array_like_to_array$4(o, minLen);
1210
+ var n = Object.prototype.toString.call(o).slice(8, -1);
1211
+ if (n === "Object" && o.constructor) n = o.constructor.name;
1212
+ if (n === "Map" || n === "Set") return Array.from(n);
1213
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$4(o, minLen);
1214
+ }
1171
1215
  // MARK: Constants
1172
1216
  /**
1173
1217
  * Reserved tool name for the built-in `model-info` static tool.
@@ -1180,13 +1224,27 @@ function _object_spread$2(target) {
1180
1224
  * Synthetic model type used in the tool's dispatch identity. Mirrors {@link MODEL_GET_DISPATCH_MODEL_TYPE};
1181
1225
  * apps avoiding collisions should not register a real model literally named "model".
1182
1226
  */ var MODEL_INFO_DISPATCH_MODEL_TYPE = 'model';
1227
+ /**
1228
+ * Group label applied to manifest entries that declare no `modelGroup`. Keeps the `groups` mode
1229
+ * total reconcilable with the catalog size (sum of group counts always equals `totalModels`).
1230
+ */ var MODEL_INFO_UNGROUPED_LABEL = '(ungrouped)';
1231
+ /**
1232
+ * Hint string surfaced alongside the default `groups` response so callers know how to drill in.
1233
+ */ var MODEL_INFO_GROUPS_HINT = 'Pass `model` for one/many models, `modelGroup` for a group, or `all:true` for the full catalog.';
1183
1234
  // MARK: Factory
1184
1235
  /**
1185
1236
  * Builds the built-in `model-info` MCP tool definition.
1186
1237
  *
1187
- * Mirrors dbx-cli's `model-info [model]` command:
1188
- * - Without a `model` arg: returns a summary list (modelType, modelName, prefix, group, identity, field count).
1189
- * - With a `model` arg: matches by `modelType`, `identityConst`, or `collectionPrefix` and returns the full entry.
1238
+ * Modes (selected by input):
1239
+ * - No args: returns model groups + counts (`mode: 'groups'`) — the cheap default for browsing.
1240
+ * - `model` (string): returns the full entry for one model (`mode: 'single'`).
1241
+ * - `model` (string array): returns full detail per match (`mode: 'multiple'`); misses land in `notFound`.
1242
+ * - `modelGroup`: returns the summary list of that group's models (`mode: 'list'`).
1243
+ * - `all: true`: returns the full catalog summary (`mode: 'list'`).
1244
+ * - `fields`: forces (`true`) or suppresses (`false`) full persisted-field detail in list/multiple modes.
1245
+ *
1246
+ * Each `model` query matches by `modelType`, `identityConst`, or `collectionPrefix`. When several
1247
+ * params are supplied, precedence is `model` > `modelGroup` > `all` > the default `groups` view.
1190
1248
  *
1191
1249
  * Output is delivered as both stringified JSON in `content[0].text` and `structuredContent`
1192
1250
  * so MCP clients can consume either form.
@@ -1199,7 +1257,8 @@ function _object_spread$2(target) {
1199
1257
  return Promise.resolve(modelInfoToolHandler(args, ctx, deps));
1200
1258
  };
1201
1259
  var name = MODEL_INFO_TOOL_NAME;
1202
- var description = "Browse the Firestore model catalog (".concat(deps.manifest.length, " model").concat(deps.manifest.length === 1 ? '' : 's', "). Without `model`, returns a summary list of every model. With `model` (matched by modelType, identityConst, or collectionPrefix), returns the full entry with persisted fields.");
1260
+ var count = deps.manifest.length;
1261
+ var description = "Browse the Firestore model catalog (".concat(count, " model").concat(count === 1 ? '' : 's', "). No args returns model groups + counts (start here). ") + '`model` (a modelType/identityConst/collectionPrefix string, or an array of them) returns full detail per match — misses are reported in `notFound`. ' + '`modelGroup` returns the summary list for that group. `all:true` returns the full catalog summary. ' + '`fields` (boolean) forces or suppresses persisted-field detail in list/multiple modes.';
1203
1262
  return {
1204
1263
  name: name,
1205
1264
  description: description,
@@ -1230,7 +1289,7 @@ function modelInfoToolHandler(args, _ctx, deps) {
1230
1289
  var result;
1231
1290
  try {
1232
1291
  var input = parseModelInfoInput(args);
1233
- var output = input.model == null ? buildListOutput(deps.manifest) : buildSingleOutput(input.model, deps.manifest);
1292
+ var output = resolveModelInfoOutput(input, deps.manifest);
1234
1293
  result = {
1235
1294
  content: [
1236
1295
  {
@@ -1245,60 +1304,285 @@ function modelInfoToolHandler(args, _ctx, deps) {
1245
1304
  }
1246
1305
  return result;
1247
1306
  }
1307
+ function resolveModelInfoOutput(input, manifest) {
1308
+ var output;
1309
+ if (input.modelQueries != null) {
1310
+ output = buildModelLookupOutput({
1311
+ queries: input.modelQueries,
1312
+ isArray: input.modelIsArray,
1313
+ manifest: manifest,
1314
+ fields: input.fields
1315
+ });
1316
+ } else if (input.modelGroup != null) {
1317
+ output = buildGroupFilterOutput({
1318
+ group: input.modelGroup,
1319
+ manifest: manifest,
1320
+ fields: input.fields
1321
+ });
1322
+ } else if (input.all) {
1323
+ output = buildAllOutput(manifest, input.fields);
1324
+ } else {
1325
+ output = buildGroupsOutput(manifest);
1326
+ }
1327
+ return output;
1328
+ }
1329
+ // MARK: Input parsing
1248
1330
  function parseModelInfoInput(args) {
1249
- var raw = args['model'];
1250
- var model;
1331
+ var modelQueries = parseModelArg(args['model']);
1332
+ var modelGroup = parseModelGroupArg(args['modelGroup']);
1333
+ var all = parseBooleanArg(args['all'], 'all');
1334
+ var fields = parseBooleanArg(args['fields'], 'fields');
1335
+ return _object_spread$2(_object_spread_props(_object_spread$2(_object_spread_props(_object_spread$2({}, modelQueries == null ? {} : {
1336
+ modelQueries: modelQueries
1337
+ }), {
1338
+ modelIsArray: Array.isArray(args['model'])
1339
+ }), modelGroup == null ? {} : {
1340
+ modelGroup: modelGroup
1341
+ }), {
1342
+ all: all !== null && all !== void 0 ? all : false
1343
+ }), fields == null ? {} : {
1344
+ fields: fields
1345
+ });
1346
+ }
1347
+ function parseModelArg(raw) {
1348
+ var result;
1251
1349
  if (raw == null) {
1252
- model = undefined;
1350
+ result = undefined;
1253
1351
  } else if (typeof raw === 'string') {
1254
- var trimmed = raw.trim();
1255
- if (trimmed.length === 0) {
1256
- throw new Error('model-info: "model" must be a non-empty string when provided.');
1352
+ result = [
1353
+ requireNonEmptyString(raw, 'model')
1354
+ ];
1355
+ } else if (Array.isArray(raw)) {
1356
+ if (raw.length === 0) {
1357
+ throw new Error('model-info: "model" array must contain at least one entry.');
1257
1358
  }
1258
- model = trimmed;
1359
+ result = raw.map(function(value, index) {
1360
+ return requireNonEmptyString(value, "model[".concat(index, "]"));
1361
+ });
1362
+ } else {
1363
+ throw new TypeError('model-info: "model" must be a string or an array of strings when provided.');
1364
+ }
1365
+ return result;
1366
+ }
1367
+ function parseModelGroupArg(raw) {
1368
+ var result;
1369
+ if (raw == null) {
1370
+ result = undefined;
1371
+ } else if (typeof raw === 'string') {
1372
+ result = requireNonEmptyString(raw, 'modelGroup');
1259
1373
  } else {
1260
- throw new TypeError('model-info: "model" must be a string when provided.');
1374
+ throw new TypeError('model-info: "modelGroup" must be a string when provided.');
1375
+ }
1376
+ return result;
1377
+ }
1378
+ function parseBooleanArg(raw, label) {
1379
+ var result;
1380
+ if (raw == null) {
1381
+ result = undefined;
1382
+ } else if (typeof raw === 'boolean') {
1383
+ result = raw;
1384
+ } else {
1385
+ throw new TypeError('model-info: "'.concat(label, '" must be a boolean when provided.'));
1386
+ }
1387
+ return result;
1388
+ }
1389
+ function requireNonEmptyString(value, label) {
1390
+ if (typeof value !== 'string') {
1391
+ throw new TypeError('model-info: "'.concat(label, '" must be a string.'));
1261
1392
  }
1393
+ var trimmed = value.trim();
1394
+ if (trimmed.length === 0) {
1395
+ throw new Error('model-info: "'.concat(label, '" must be a non-empty string.'));
1396
+ }
1397
+ return trimmed;
1398
+ }
1399
+ // MARK: Output builders
1400
+ function buildGroupsOutput(manifest) {
1262
1401
  return {
1263
- model: model
1402
+ mode: 'groups',
1403
+ groups: computeGroupCounts(manifest),
1404
+ totalModels: manifest.length,
1405
+ hint: MODEL_INFO_GROUPS_HINT
1264
1406
  };
1265
1407
  }
1266
- function buildListOutput(manifest) {
1267
- var models = manifest.map(function(entry) {
1268
- var row = _object_spread$2({
1269
- modelType: entry.modelType,
1270
- modelName: entry.modelName,
1271
- identityConst: entry.identityConst,
1272
- collectionPrefix: entry.collectionPrefix,
1273
- sourcePackage: entry.sourcePackage,
1274
- fieldCount: entry.fields.length
1275
- }, entry.modelGroup == null ? {} : {
1276
- modelGroup: entry.modelGroup
1277
- }, entry.parentIdentityConst == null ? {} : {
1278
- parentIdentityConst: entry.parentIdentityConst
1279
- }, entry.description == null ? {} : {
1280
- description: entry.description
1281
- }, entry.read == null ? {} : {
1282
- read: entry.read
1283
- }, entry.serviceFactory == null ? {} : {
1284
- serviceFactoryExport: entry.serviceFactory.exportName
1285
- });
1286
- return row;
1408
+ function buildGroupFilterOutput(config) {
1409
+ var group = config.group, manifest = config.manifest, fields = config.fields;
1410
+ var detailed = fields !== null && fields !== void 0 ? fields : false;
1411
+ var lower = group.toLowerCase();
1412
+ var matches = manifest.filter(function(entry) {
1413
+ var _entry_modelGroup;
1414
+ return ((_entry_modelGroup = entry.modelGroup) === null || _entry_modelGroup === void 0 ? void 0 : _entry_modelGroup.toLowerCase()) === lower;
1287
1415
  });
1416
+ var result;
1417
+ if (matches.length === 0) {
1418
+ throw new Error(buildUnknownGroupMessage(group, manifest));
1419
+ } else {
1420
+ var canonical = matches[0].modelGroup;
1421
+ result = {
1422
+ mode: 'list',
1423
+ modelGroup: canonical,
1424
+ models: matches.map(function(entry) {
1425
+ return toModelRow(entry, detailed);
1426
+ })
1427
+ };
1428
+ }
1429
+ return result;
1430
+ }
1431
+ function buildAllOutput(manifest, fields) {
1432
+ var detailed = fields !== null && fields !== void 0 ? fields : false;
1288
1433
  return {
1289
1434
  mode: 'list',
1290
- models: models
1435
+ models: manifest.map(function(entry) {
1436
+ return toModelRow(entry, detailed);
1437
+ })
1291
1438
  };
1292
1439
  }
1293
- function buildSingleOutput(query, manifest) {
1294
- var entry = findModelEntry(query, manifest);
1295
- if (entry == null) {
1296
- throw new Error('model-info: no model matches "'.concat(query, '". Call `model-info` without arguments to list available models.'));
1440
+ function buildModelLookupOutput(config) {
1441
+ var queries = config.queries, isArray = config.isArray, manifest = config.manifest, fields = config.fields;
1442
+ var detailed = fields !== null && fields !== void 0 ? fields : true;
1443
+ var matched = [];
1444
+ var notFound = [];
1445
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1446
+ try {
1447
+ for(var _iterator = queries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1448
+ var query = _step.value;
1449
+ var entry = findModelEntry(query, manifest);
1450
+ if (entry == null) {
1451
+ notFound.push({
1452
+ query: query,
1453
+ message: buildModelNotFoundMessage(query, manifest)
1454
+ });
1455
+ } else {
1456
+ matched.push(toModelRow(entry, detailed));
1457
+ }
1458
+ }
1459
+ } catch (err) {
1460
+ _didIteratorError = true;
1461
+ _iteratorError = err;
1462
+ } finally{
1463
+ try {
1464
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1465
+ _iterator.return();
1466
+ }
1467
+ } finally{
1468
+ if (_didIteratorError) {
1469
+ throw _iteratorError;
1470
+ }
1471
+ }
1297
1472
  }
1298
- return {
1299
- mode: 'single',
1300
- model: entry
1301
- };
1473
+ var result;
1474
+ if (isArray) {
1475
+ result = notFound.length > 0 ? {
1476
+ mode: 'multiple',
1477
+ models: matched,
1478
+ notFound: notFound
1479
+ } : {
1480
+ mode: 'multiple',
1481
+ models: matched
1482
+ };
1483
+ } else if (matched.length > 0) {
1484
+ result = {
1485
+ mode: 'single',
1486
+ model: matched[0]
1487
+ };
1488
+ } else {
1489
+ throw new Error(notFound[0].message);
1490
+ }
1491
+ return result;
1492
+ }
1493
+ // MARK: Row + group helpers
1494
+ function toModelRow(entry, detailed) {
1495
+ return detailed ? entry : toSummaryRow(entry);
1496
+ }
1497
+ function toSummaryRow(entry) {
1498
+ return _object_spread$2({
1499
+ modelType: entry.modelType,
1500
+ modelName: entry.modelName,
1501
+ identityConst: entry.identityConst,
1502
+ collectionPrefix: entry.collectionPrefix,
1503
+ sourcePackage: entry.sourcePackage,
1504
+ fieldCount: entry.fields.length
1505
+ }, entry.modelGroup == null ? {} : {
1506
+ modelGroup: entry.modelGroup
1507
+ }, entry.parentIdentityConst == null ? {} : {
1508
+ parentIdentityConst: entry.parentIdentityConst
1509
+ }, entry.description == null ? {} : {
1510
+ description: entry.description
1511
+ }, entry.read == null ? {} : {
1512
+ read: entry.read
1513
+ }, entry.serviceFactory == null ? {} : {
1514
+ serviceFactoryExport: entry.serviceFactory.exportName
1515
+ });
1516
+ }
1517
+ /**
1518
+ * Counts models per `modelGroup`, bucketing entries without a group under
1519
+ * {@link MODEL_INFO_UNGROUPED_LABEL}. Sorted by count descending, then group name ascending.
1520
+ *
1521
+ * @param manifest - Model manifest to summarize.
1522
+ * @returns One {@link ModelInfoGroupCount} per group, ordered most-populous-first.
1523
+ *
1524
+ * @__NO_SIDE_EFFECTS__
1525
+ */ function computeGroupCounts(manifest) {
1526
+ var grouped = util.makeValuesGroupMap(_to_consumable_array$4(manifest), function(entry) {
1527
+ var _entry_modelGroup;
1528
+ return (_entry_modelGroup = entry.modelGroup) !== null && _entry_modelGroup !== void 0 ? _entry_modelGroup : MODEL_INFO_UNGROUPED_LABEL;
1529
+ });
1530
+ var counts = [];
1531
+ grouped.forEach(function(entries, group) {
1532
+ counts.push({
1533
+ modelGroup: group,
1534
+ modelCount: entries.length
1535
+ });
1536
+ });
1537
+ counts.sort(function(a, b) {
1538
+ return b.modelCount - a.modelCount || a.modelGroup.localeCompare(b.modelGroup);
1539
+ });
1540
+ return counts;
1541
+ }
1542
+ function findGroupCount(query, manifest) {
1543
+ var lower = query.toLowerCase();
1544
+ var result;
1545
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1546
+ try {
1547
+ for(var _iterator = computeGroupCounts(manifest)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1548
+ var count = _step.value;
1549
+ if (count.modelGroup.toLowerCase() === lower) {
1550
+ result = count;
1551
+ break;
1552
+ }
1553
+ }
1554
+ } catch (err) {
1555
+ _didIteratorError = true;
1556
+ _iteratorError = err;
1557
+ } finally{
1558
+ try {
1559
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1560
+ _iterator.return();
1561
+ }
1562
+ } finally{
1563
+ if (_didIteratorError) {
1564
+ throw _iteratorError;
1565
+ }
1566
+ }
1567
+ }
1568
+ return result;
1569
+ }
1570
+ function buildModelNotFoundMessage(query, manifest) {
1571
+ var groupMatch = findGroupCount(query, manifest);
1572
+ var message;
1573
+ if (groupMatch != null) {
1574
+ var plural = groupMatch.modelCount === 1 ? '' : 's';
1575
+ message = 'model-info: no exact match for "'.concat(query, '" — did you mean group:"').concat(groupMatch.modelGroup, '" (').concat(groupMatch.modelCount, " model").concat(plural, ')? Use modelGroup:"').concat(groupMatch.modelGroup, '", or all:true for everything.');
1576
+ } else {
1577
+ message = 'model-info: no exact match for "'.concat(query, '". Call `model-info` with no arguments to list groups, or pass all:true for the full catalog.');
1578
+ }
1579
+ return message;
1580
+ }
1581
+ function buildUnknownGroupMessage(group, manifest) {
1582
+ var available = computeGroupCounts(manifest).map(function(count) {
1583
+ return "".concat(count.modelGroup, " (").concat(count.modelCount, ")");
1584
+ }).join(', ');
1585
+ return 'model-info: no model group matches "'.concat(group, '". Available groups: ').concat(available || '(none)', ". Call `model-info` with no arguments to list groups.");
1302
1586
  }
1303
1587
  /**
1304
1588
  * Resolves a manifest entry by `modelType`, `identityConst`, or `collectionPrefix`.
@@ -1340,160 +1624,205 @@ var MODEL_INFO_INPUT_SCHEMA = {
1340
1624
  type: 'object',
1341
1625
  properties: {
1342
1626
  model: {
1627
+ description: 'One model (string) or many (string array), each matched by modelType, identityConst, or collectionPrefix. A string → `mode:"single"`; an array → `mode:"multiple"`. Misses are reported in `notFound`.',
1628
+ oneOf: [
1629
+ {
1630
+ type: 'string',
1631
+ minLength: 1
1632
+ },
1633
+ {
1634
+ type: 'array',
1635
+ minItems: 1,
1636
+ items: {
1637
+ type: 'string',
1638
+ minLength: 1
1639
+ }
1640
+ }
1641
+ ]
1642
+ },
1643
+ modelGroup: {
1343
1644
  type: 'string',
1344
1645
  minLength: 1,
1345
- description: 'Model to inspect (modelType, identityConst, or collectionPrefix). Omit to list every model.'
1646
+ description: 'Return the summary list of models in this group (`mode:"list"`). Matched case-insensitively.'
1647
+ },
1648
+ all: {
1649
+ type: 'boolean',
1650
+ description: 'Opt in to the full catalog summary (every model). Never the default — omit to get groups instead.'
1651
+ },
1652
+ fields: {
1653
+ type: 'boolean',
1654
+ description: 'Force (true) or suppress (false) full persisted-field detail. Defaults to summary rows for list mode and full entries for single/multiple modes.'
1346
1655
  }
1347
1656
  },
1348
1657
  additionalProperties: false
1349
1658
  };
1659
+ // Shared item schema for model-bearing rows. Required props cover the summary form; full entries
1660
+ // add `fields`, `sourceFile`, and `serviceFactory` (allowed as additional properties).
1661
+ var MODEL_ROW_SCHEMA = {
1662
+ type: 'object',
1663
+ required: [
1664
+ 'modelType',
1665
+ 'modelName',
1666
+ 'identityConst',
1667
+ 'collectionPrefix',
1668
+ 'sourcePackage'
1669
+ ],
1670
+ properties: {
1671
+ modelType: {
1672
+ type: 'string'
1673
+ },
1674
+ modelName: {
1675
+ type: 'string'
1676
+ },
1677
+ modelGroup: {
1678
+ type: 'string'
1679
+ },
1680
+ identityConst: {
1681
+ type: 'string'
1682
+ },
1683
+ collectionPrefix: {
1684
+ type: 'string'
1685
+ },
1686
+ parentIdentityConst: {
1687
+ type: 'string'
1688
+ },
1689
+ sourcePackage: {
1690
+ type: 'string'
1691
+ },
1692
+ sourceFile: {
1693
+ type: 'string'
1694
+ },
1695
+ fieldCount: {
1696
+ type: 'integer'
1697
+ },
1698
+ description: {
1699
+ type: 'string'
1700
+ },
1701
+ read: {
1702
+ type: 'string',
1703
+ enum: [
1704
+ 'system',
1705
+ 'owner',
1706
+ 'admin-only',
1707
+ 'permissions'
1708
+ ]
1709
+ },
1710
+ serviceFactoryExport: {
1711
+ type: 'string'
1712
+ },
1713
+ fields: {
1714
+ type: 'array',
1715
+ items: {
1716
+ type: 'object'
1717
+ }
1718
+ },
1719
+ serviceFactory: {
1720
+ type: 'object',
1721
+ required: [
1722
+ 'exportName',
1723
+ 'sourceFile'
1724
+ ],
1725
+ properties: {
1726
+ exportName: {
1727
+ type: 'string'
1728
+ },
1729
+ sourceFile: {
1730
+ type: 'string'
1731
+ }
1732
+ }
1733
+ }
1734
+ }
1735
+ };
1350
1736
  // MCP's `tools/list` validator requires `outputSchema.type === 'object'` at the root
1351
- // (see @modelcontextprotocol/sdk Zod schema), so the list/single union is expressed via a
1352
- // top-level object whose nested `oneOf` discriminates by the `mode` literal.
1737
+ // (see @modelcontextprotocol/sdk Zod schema), so the variants are expressed via a top-level
1738
+ // object whose nested `oneOf` discriminates by the `mode` literal.
1353
1739
  var MODEL_INFO_OUTPUT_SCHEMA = {
1354
1740
  type: 'object',
1355
1741
  required: [
1356
1742
  'mode'
1357
1743
  ],
1358
- description: 'Either lists every model in the manifest (when `model` is omitted) or returns a full entry for the requested model (when `model` is provided). The `mode` field discriminates the variant.',
1744
+ description: 'Discriminated by `mode`: `groups` (default model groups + counts), `list` (summary/full list for `modelGroup` or `all`), `single` (one `model`), or `multiple` (a `model` array, with misses in `notFound`).',
1359
1745
  properties: {
1360
1746
  mode: {
1361
1747
  type: 'string',
1362
1748
  enum: [
1749
+ 'groups',
1363
1750
  'list',
1364
- 'single'
1751
+ 'single',
1752
+ 'multiple'
1365
1753
  ]
1366
1754
  },
1367
- models: {
1755
+ groups: {
1368
1756
  type: 'array',
1369
- description: 'Present when `mode` is `"list"`. One summary entry per registered model.',
1757
+ description: 'Present when `mode` is `"groups"`. One entry per model group.',
1370
1758
  items: {
1371
1759
  type: 'object',
1372
1760
  required: [
1373
- 'modelType',
1374
- 'modelName',
1375
- 'identityConst',
1376
- 'collectionPrefix',
1377
- 'sourcePackage',
1378
- 'fieldCount'
1761
+ 'modelGroup',
1762
+ 'modelCount'
1379
1763
  ],
1380
1764
  properties: {
1381
- modelType: {
1382
- type: 'string'
1383
- },
1384
- modelName: {
1385
- type: 'string'
1386
- },
1387
1765
  modelGroup: {
1388
1766
  type: 'string'
1389
1767
  },
1390
- identityConst: {
1391
- type: 'string'
1392
- },
1393
- collectionPrefix: {
1394
- type: 'string'
1395
- },
1396
- parentIdentityConst: {
1397
- type: 'string'
1398
- },
1399
- sourcePackage: {
1400
- type: 'string'
1401
- },
1402
- fieldCount: {
1768
+ modelCount: {
1403
1769
  type: 'integer'
1404
- },
1405
- description: {
1770
+ }
1771
+ }
1772
+ }
1773
+ },
1774
+ totalModels: {
1775
+ type: 'integer',
1776
+ description: 'Present when `mode` is `"groups"`. Total models across all groups.'
1777
+ },
1778
+ hint: {
1779
+ type: 'string',
1780
+ description: 'Present when `mode` is `"groups"`. Guidance on how to drill into the catalog.'
1781
+ },
1782
+ models: {
1783
+ type: 'array',
1784
+ description: 'Present when `mode` is `"list"` or `"multiple"`. Summary rows by default; full entries when `fields` requests detail.',
1785
+ items: MODEL_ROW_SCHEMA
1786
+ },
1787
+ modelGroup: {
1788
+ type: 'string',
1789
+ description: 'Present when `mode` is `"list"` from a `modelGroup` filter. The canonical group name.'
1790
+ },
1791
+ model: _object_spread_props(_object_spread$2({}, MODEL_ROW_SCHEMA), {
1792
+ description: 'Present when `mode` is `"single"`. The matched model entry (full detail unless `fields:false`).'
1793
+ }),
1794
+ notFound: {
1795
+ type: 'array',
1796
+ description: 'Present when `mode` is `"multiple"` and one or more queries matched nothing.',
1797
+ items: {
1798
+ type: 'object',
1799
+ required: [
1800
+ 'query',
1801
+ 'message'
1802
+ ],
1803
+ properties: {
1804
+ query: {
1406
1805
  type: 'string'
1407
1806
  },
1408
- read: {
1409
- type: 'string',
1410
- enum: [
1411
- 'system',
1412
- 'owner',
1413
- 'admin-only',
1414
- 'permissions'
1415
- ]
1416
- },
1417
- serviceFactoryExport: {
1807
+ message: {
1418
1808
  type: 'string'
1419
1809
  }
1420
1810
  }
1421
1811
  }
1422
- },
1423
- model: {
1424
- type: 'object',
1425
- description: 'Present when `mode` is `"single"`. The full manifest entry for the requested model.',
1812
+ }
1813
+ },
1814
+ oneOf: [
1815
+ {
1426
1816
  required: [
1427
- 'modelType',
1428
- 'modelName',
1429
- 'identityConst',
1430
- 'collectionPrefix',
1431
- 'sourcePackage',
1432
- 'sourceFile',
1433
- 'fields'
1817
+ 'groups',
1818
+ 'totalModels'
1434
1819
  ],
1435
1820
  properties: {
1436
- modelType: {
1437
- type: 'string'
1438
- },
1439
- modelName: {
1440
- type: 'string'
1441
- },
1442
- modelGroup: {
1443
- type: 'string'
1444
- },
1445
- identityConst: {
1446
- type: 'string'
1447
- },
1448
- collectionPrefix: {
1449
- type: 'string'
1450
- },
1451
- parentIdentityConst: {
1452
- type: 'string'
1453
- },
1454
- description: {
1455
- type: 'string'
1456
- },
1457
- sourcePackage: {
1458
- type: 'string'
1459
- },
1460
- sourceFile: {
1461
- type: 'string'
1462
- },
1463
- fields: {
1464
- type: 'array',
1465
- items: {
1466
- type: 'object'
1467
- }
1468
- },
1469
- read: {
1470
- type: 'string',
1471
- enum: [
1472
- 'system',
1473
- 'owner',
1474
- 'admin-only',
1475
- 'permissions'
1476
- ]
1477
- },
1478
- serviceFactory: {
1479
- type: 'object',
1480
- required: [
1481
- 'exportName',
1482
- 'sourceFile'
1483
- ],
1484
- properties: {
1485
- exportName: {
1486
- type: 'string'
1487
- },
1488
- sourceFile: {
1489
- type: 'string'
1490
- }
1491
- }
1821
+ mode: {
1822
+ const: 'groups'
1492
1823
  }
1493
1824
  }
1494
- }
1495
- },
1496
- oneOf: [
1825
+ },
1497
1826
  {
1498
1827
  required: [
1499
1828
  'models'
@@ -1513,6 +1842,16 @@ var MODEL_INFO_OUTPUT_SCHEMA = {
1513
1842
  const: 'single'
1514
1843
  }
1515
1844
  }
1845
+ },
1846
+ {
1847
+ required: [
1848
+ 'models'
1849
+ ],
1850
+ properties: {
1851
+ mode: {
1852
+ const: 'multiple'
1853
+ }
1854
+ }
1516
1855
  }
1517
1856
  ]
1518
1857
  };
@@ -3959,7 +4298,9 @@ exports.MODEL_GET_DISPATCH_MODEL_TYPE = MODEL_GET_DISPATCH_MODEL_TYPE;
3959
4298
  exports.MODEL_GET_TOOL_NAME = MODEL_GET_TOOL_NAME;
3960
4299
  exports.MODEL_INFO_DISPATCH_CALL = MODEL_INFO_DISPATCH_CALL;
3961
4300
  exports.MODEL_INFO_DISPATCH_MODEL_TYPE = MODEL_INFO_DISPATCH_MODEL_TYPE;
4301
+ exports.MODEL_INFO_GROUPS_HINT = MODEL_INFO_GROUPS_HINT;
3962
4302
  exports.MODEL_INFO_TOOL_NAME = MODEL_INFO_TOOL_NAME;
4303
+ exports.MODEL_INFO_UNGROUPED_LABEL = MODEL_INFO_UNGROUPED_LABEL;
3963
4304
  exports.McpAnalyticsService = McpAnalyticsService;
3964
4305
  exports.McpModuleConfig = McpModuleConfig;
3965
4306
  exports.appMcpAnalyticsModuleMetadata = appMcpAnalyticsModuleMetadata;