metheus-governance-mcp-cli 0.2.110 → 0.2.112

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/cli.mjs CHANGED
@@ -1269,10 +1269,21 @@ function normalizeBotRunnerConfigContents(parsed, filePath) {
1269
1269
  if (!binding.name || (!binding.botID && !binding.botName)) continue;
1270
1270
  if (!binding.roleProfile && !binding.client && !binding.model && !binding.permissionMode && !binding.reasoningEffort) continue;
1271
1271
  botBindings[binding.name] = binding;
1272
- const rawClient = String(safeObject(rawBinding).client || "").trim().toLowerCase();
1272
+ const rawBindingObject = safeObject(rawBinding);
1273
+ const rawClient = String(rawBindingObject.client || "").trim().toLowerCase();
1273
1274
  if (rawClient === "codex") {
1274
1275
  migrated = true;
1275
1276
  }
1277
+ if (
1278
+ (!Object.prototype.hasOwnProperty.call(rawBindingObject, "server_bot_id")
1279
+ && !Object.prototype.hasOwnProperty.call(rawBindingObject, "serverBotID")
1280
+ && (Object.prototype.hasOwnProperty.call(rawBindingObject, "bot_id") || Object.prototype.hasOwnProperty.call(rawBindingObject, "botId")))
1281
+ || (!Object.prototype.hasOwnProperty.call(rawBindingObject, "server_bot_name")
1282
+ && !Object.prototype.hasOwnProperty.call(rawBindingObject, "serverBotName")
1283
+ && (Object.prototype.hasOwnProperty.call(rawBindingObject, "bot_name") || Object.prototype.hasOwnProperty.call(rawBindingObject, "botName")))
1284
+ ) {
1285
+ migrated = true;
1286
+ }
1276
1287
  }
1277
1288
 
1278
1289
  const projectMappings = {};
@@ -1289,6 +1300,16 @@ function normalizeBotRunnerConfigContents(parsed, filePath) {
1289
1300
  const routeSource = safeObject(rawRoute);
1290
1301
  const route = normalizeRunnerRoute(routeSource);
1291
1302
  routes.push(route);
1303
+ if (
1304
+ (!Object.prototype.hasOwnProperty.call(routeSource, "server_bot_id")
1305
+ && !Object.prototype.hasOwnProperty.call(routeSource, "serverBotID")
1306
+ && (Object.prototype.hasOwnProperty.call(routeSource, "bot_id") || Object.prototype.hasOwnProperty.call(routeSource, "botID")))
1307
+ || (!Object.prototype.hasOwnProperty.call(routeSource, "server_bot_name")
1308
+ && !Object.prototype.hasOwnProperty.call(routeSource, "serverBotName")
1309
+ && (Object.prototype.hasOwnProperty.call(routeSource, "bot_name") || Object.prototype.hasOwnProperty.call(routeSource, "botName")))
1310
+ ) {
1311
+ migrated = true;
1312
+ }
1292
1313
  if (!Object.prototype.hasOwnProperty.call(routeSource, "trigger_policy") && !Object.prototype.hasOwnProperty.call(routeSource, "triggerPolicy")) {
1293
1314
  migrated = true;
1294
1315
  }
@@ -1797,8 +1818,27 @@ function matchesRunnerRouteText(candidate, expected) {
1797
1818
  return String(candidate || "").trim().toLowerCase() === expectedText.toLowerCase();
1798
1819
  }
1799
1820
 
1800
- function configuredRunnerRouteMatchesInlineSelection(route, inlineRoute, flags) {
1821
+ function resolveConfiguredRunnerRouteServerBotName(route, telegramEntries = []) {
1801
1822
  const candidate = normalizeRunnerRoute(route);
1823
+ if (candidate.botName) {
1824
+ return candidate.botName;
1825
+ }
1826
+ if (candidate.provider !== "telegram") {
1827
+ return "";
1828
+ }
1829
+ const matchedTelegramEntry = ensureArray(telegramEntries).find((entry) => {
1830
+ const current = safeObject(entry);
1831
+ return (
1832
+ (candidate.botID && current.serverBotID && current.serverBotID === candidate.botID)
1833
+ || (candidate.botName && current.serverBotName && current.serverBotName === candidate.botName)
1834
+ );
1835
+ });
1836
+ return String(matchedTelegramEntry?.serverBotName || "").trim();
1837
+ }
1838
+
1839
+ function configuredRunnerRouteMatchesInlineSelection(route, inlineRoute, flags, options = {}) {
1840
+ const candidate = normalizeRunnerRoute(route);
1841
+ const candidateBotName = resolveConfiguredRunnerRouteServerBotName(candidate, options.telegramEntries);
1802
1842
  if (hasRunnerFlag(flags, "route-name") && !matchesRunnerRouteText(candidate.name, flags["route-name"])) {
1803
1843
  return false;
1804
1844
  }
@@ -1817,7 +1857,7 @@ function configuredRunnerRouteMatchesInlineSelection(route, inlineRoute, flags)
1817
1857
  if (inlineRoute.botID && candidate.botID !== inlineRoute.botID) {
1818
1858
  return false;
1819
1859
  }
1820
- if (inlineRoute.botName && !matchesRunnerRouteText(candidate.botName, inlineRoute.botName)) {
1860
+ if (inlineRoute.botName && !matchesRunnerRouteText(candidateBotName, inlineRoute.botName)) {
1821
1861
  return false;
1822
1862
  }
1823
1863
  if (inlineRoute.destinationID && candidate.destinationID !== inlineRoute.destinationID) {
@@ -2014,9 +2054,10 @@ function resolveRunnerRoutes(flags, mode) {
2014
2054
  .map((rawRoute) => normalizeRunnerRoute(rawRoute))
2015
2055
  .filter((route) => route.enabled)
2016
2056
  .filter((route) => !routeNameFilter || String(route.name || "").trim().toLowerCase() === routeNameFilter);
2057
+ const telegramEntries = selectionRequested ? ensureArray(readTelegramEnvState().entries) : [];
2017
2058
 
2018
2059
  if (selectionRequested) {
2019
- const matchedRoutes = configuredRoutes.filter((route) => configuredRunnerRouteMatchesInlineSelection(route, inlineRoute, flags));
2060
+ const matchedRoutes = configuredRoutes.filter((route) => configuredRunnerRouteMatchesInlineSelection(route, inlineRoute, flags, { telegramEntries }));
2020
2061
  if (matchedRoutes.length === 1) {
2021
2062
  return [applyRunnerRouteFlagOverrides(matchedRoutes[0], flags)];
2022
2063
  }
@@ -2594,7 +2635,6 @@ function buildRunnerRouteListRows() {
2594
2635
  const resolvedBotName = firstNonEmptyString([
2595
2636
  route.botName,
2596
2637
  matchedTelegramEntry?.serverBotName,
2597
- matchedTelegramEntry?.key,
2598
2638
  "-",
2599
2639
  ]);
2600
2640
  return {
@@ -3938,6 +3978,7 @@ function buildBotCommandDeps() {
3938
3978
  normalizeBotProvider,
3939
3979
  normalizeTelegramBotEnvKey,
3940
3980
  normalizeTelegramBotUsername,
3981
+ normalizeRunnerRoute,
3941
3982
  normalizeRunnerRoleProfileName,
3942
3983
  normalizeLocalAIClientName,
3943
3984
  normalizeLocalAIPermissionMode,
@@ -1254,6 +1254,7 @@ function summarizeTelegramRouteLinks(parsedEnv, entry, serverBinding, deps) {
1254
1254
  const selectedEntry = safeObject(entry);
1255
1255
  const binding = safeObject(serverBinding);
1256
1256
  const config = safeObject(requireDependency(deps, "loadBotRunnerConfig")({ persistIfNeeded: true }));
1257
+ const normalizeRunnerRoute = requireDependency(deps, "normalizeRunnerRoute");
1257
1258
  const routes = ensureArray(config.routes);
1258
1259
  const entryKey = String(selectedEntry.key || "").trim();
1259
1260
  const defaultBotKey = String(safeObject(parsedEnv).TELEGRAM_DEFAULT_BOT_KEY || "").trim();
@@ -1267,12 +1268,12 @@ function summarizeTelegramRouteLinks(parsedEnv, entry, serverBinding, deps) {
1267
1268
  );
1268
1269
  const linkedRoutes = [];
1269
1270
  routes.forEach((rawRoute, index) => {
1270
- const route = safeObject(rawRoute);
1271
+ const route = normalizeRunnerRoute(rawRoute);
1271
1272
  if (route.enabled === false) return;
1272
1273
  if (String(route.provider || "").trim().toLowerCase() !== "telegram") return;
1273
1274
  const routeName = String(route.name || route.route_name || `telegram-route-${index + 1}`).trim();
1274
- const routeBotID = String(route.bot_id || route.botID || "").trim();
1275
- const routeBotName = normalizeServerBotIdentityText(route.bot_name || route.botName || "");
1275
+ const routeBotID = String(route.server_bot_id || route.serverBotID || route.bot_id || route.botID || "").trim();
1276
+ const routeBotName = normalizeServerBotIdentityText(route.server_bot_name || route.serverBotName || route.bot_name || route.botName || "");
1276
1277
  const routeRole = String(route.role_profile || route.roleProfile || route.role || "").trim();
1277
1278
  let matchedBy = "";
1278
1279
  if (serverBotID && routeBotID === serverBotID) {
@@ -565,7 +565,7 @@ export async function runSelftestBotCommands(push, deps) {
565
565
  enabled: true,
566
566
  project_id: "03c586a2-006d-4051-83b4-f353a5813176",
567
567
  provider: "telegram",
568
- bot_id: mock.bots[0].id,
568
+ server_bot_id: mock.bots[0].id,
569
569
  role_profile: "monitor",
570
570
  },
571
571
  {
@@ -600,7 +600,7 @@ export async function runSelftestBotCommands(push, deps) {
600
600
  intFromRaw(safeObject(showWithRoutesPayload.routeLinks).total, 0) >= 1
601
601
  && ensureArray(safeObject(showWithRoutesPayload.routeLinks).routes).some((route) => (
602
602
  String(safeObject(route).routeName || "") === "telegram-monitor"
603
- && String(safeObject(route).matchedBy || "") === "bot_id"
603
+ && String(safeObject(route).matchedBy || "") === "server_bot_id"
604
604
  )),
605
605
  `routes=${JSON.stringify(safeObject(showWithRoutesPayload.routeLinks))}`,
606
606
  );
@@ -415,7 +415,26 @@ export async function runSelftestRunnerScenarios(push, deps) {
415
415
  originalResolveUserProfile = process.env.USERPROFILE;
416
416
  const resolveHome = path.join(runnerRouteResolveTempRoot, "home");
417
417
  const resolveMetheusDir = path.join(resolveHome, ".metheus");
418
+ const resolveTelegramDir = path.join(resolveMetheusDir, "telegram-bots");
418
419
  fs.mkdirSync(resolveMetheusDir, { recursive: true });
420
+ fs.mkdirSync(resolveTelegramDir, { recursive: true });
421
+ fs.writeFileSync(
422
+ path.join(resolveTelegramDir, "global.env"),
423
+ "TELEGRAM_DEFAULT_BOT_KEY=serverprotocolmonitorbot\n",
424
+ "utf8",
425
+ );
426
+ fs.writeFileSync(
427
+ path.join(resolveTelegramDir, "ServerProtocolMonitorBot.env"),
428
+ [
429
+ "TELEGRAM_BOT_SERVER_BOT_ID=22222222-2222-2222-2222-222222222222",
430
+ "TELEGRAM_BOT_SERVER_NAME=ServerProtocolMonitorBot",
431
+ "TELEGRAM_BOT_SERVER_ROLES=monitor",
432
+ "TELEGRAM_BOT_SERVER_ROLE_IDS=monitor:22222222-2222-2222-2222-222222222222",
433
+ "TELEGRAM_BOT_TOKEN=test-token",
434
+ "",
435
+ ].join("\n"),
436
+ "utf8",
437
+ );
419
438
  fs.writeFileSync(
420
439
  path.join(resolveMetheusDir, "bot-runner.json"),
421
440
  `${JSON.stringify({
@@ -435,9 +454,21 @@ export async function runSelftestRunnerScenarios(push, deps) {
435
454
  provider: "telegram",
436
455
  role: "monitor",
437
456
  role_profile: "monitor",
438
- bot_name: "ServerProtocolMonitorBot",
457
+ bot_id: "22222222-2222-2222-2222-222222222222",
439
458
  destination_label: "AI incubating CHAT ROOM",
440
459
  archive_work_item_id: "304ce77a-7032-421c-aeda-bc54daf088dd",
460
+ trigger_policy: {
461
+ mentions_only: true,
462
+ direct_messages: true,
463
+ reply_to_bot_messages: true,
464
+ ignore_edited_messages: true,
465
+ },
466
+ archive_policy: {
467
+ mirror_replies: true,
468
+ dedupe_inbound: true,
469
+ dedupe_outbound: true,
470
+ skip_bot_messages: true,
471
+ },
441
472
  },
442
473
  ],
443
474
  }, null, 2)}\n`,
@@ -457,14 +488,18 @@ export async function runSelftestRunnerScenarios(push, deps) {
457
488
  "once",
458
489
  );
459
490
  const resolvedRunnerRoute = normalizeRunnerRoute(resolvedRunnerRoutes[0]);
491
+ const persistedRunnerConfig = JSON.parse(fs.readFileSync(path.join(resolveMetheusDir, "bot-runner.json"), "utf8"));
492
+ const persistedRoute = Array.isArray(persistedRunnerConfig.routes) ? persistedRunnerConfig.routes[0] || {} : {};
460
493
  push(
461
494
  "bot_runner_inline_filters_reuse_configured_route",
462
495
  resolvedRunnerRoutes.length === 1
463
496
  && resolvedRunnerRoute.name === "telegram-monitor"
464
497
  && resolvedRunnerRoute.destinationLabel === "AI incubating CHAT ROOM"
465
498
  && resolvedRunnerRoute.dryRunDelivery === true
466
- && runnerRouteKey(resolvedRunnerRoute) === "telegram-monitor::11111111-1111-1111-1111-111111111111::telegram::monitor::ServerProtocolMonitorBot::AI incubating CHAT ROOM",
467
- `name=${resolvedRunnerRoute.name || "(none)"} destination=${resolvedRunnerRoute.destinationLabel || "(none)"} key=${runnerRouteKey(resolvedRunnerRoute)}`,
499
+ && runnerRouteKey(resolvedRunnerRoute) === "telegram-monitor::11111111-1111-1111-1111-111111111111::telegram::monitor::22222222-2222-2222-2222-222222222222::AI incubating CHAT ROOM"
500
+ && String(persistedRoute.server_bot_id || "") === "22222222-2222-2222-2222-222222222222"
501
+ && !Object.prototype.hasOwnProperty.call(persistedRoute, "bot_id"),
502
+ `name=${resolvedRunnerRoute.name || "(none)"} destination=${resolvedRunnerRoute.destinationLabel || "(none)"} key=${runnerRouteKey(resolvedRunnerRoute)} persisted=${JSON.stringify(persistedRoute)}`,
468
503
  );
469
504
  } catch (err) {
470
505
  push("bot_runner_inline_filters_reuse_configured_route", false, String(err?.message || err));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.110",
3
+ "version": "0.2.112",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [