metheus-governance-mcp-cli 0.2.112 → 0.2.113

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.
Files changed (3) hide show
  1. package/README.md +9 -1
  2. package/cli.mjs +138 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -305,7 +305,7 @@ For direct Telegram adds, the CLI derives the local file name from the matched s
305
305
 
306
306
  For direct Telegram edits, prefer `--bot-name` or `--bot-id` because server bot identity is the source of truth. Use `--bot-key` only when you intentionally need the legacy local selector. If one server bot name expands to multiple roles such as `approval / worker / review / monitor`, prefer the guided `bot edit` flow so you can keep the current grouped settings, edit one role only, or walk every role in sequence instead of forcing one entry-level AI override.
307
307
 
308
- For runner commands, you can still use `--route-name` directly, but normal operator workflows can also use `--bot-name` or `--bot-id` when those identify one enabled route uniquely. Use `runner list` first if you are not sure which route belongs to which server bot.
308
+ For runner commands, routes are the executable unit. Use `--route-name` as the primary selector. `--bot-name` and `--bot-id` are convenience route aliases only when they identify one enabled route uniquely. Use `runner list` first if you are not sure which route belongs to which server bot, and use `runner show` to inspect the resolved route, server identity, workspace mapping, and execution profile together.
309
309
 
310
310
  Current support status:
311
311
 
@@ -388,6 +388,7 @@ Commands:
388
388
 
389
389
  ```bash
390
390
  metheus-governance-mcp-cli runner list
391
+ metheus-governance-mcp-cli runner show --route-name telegram-monitor
391
392
  metheus-governance-mcp-cli runner once --route-name telegram-monitor
392
393
  metheus-governance-mcp-cli runner start --route-name telegram-monitor
393
394
  ```
@@ -399,9 +400,16 @@ metheus-governance-mcp-cli runner once --route-name telegram-monitor --dry-run-d
399
400
  metheus-governance-mcp-cli runner start --route-name telegram-monitor
400
401
  ```
401
402
 
403
+ What `runner list` means:
404
+ - `server_bot_name` may come from `route.server_bot_name` or be resolved from the Telegram bot env file by `server_bot_id`
405
+ - `server_bot_name_source=route_config` means the route file already stores the name directly
406
+ - `server_bot_name_source=telegram_env_lookup` means the CLI resolved the name from the local Telegram bot file
407
+ - `route_alias_by_server_bot_name` is a convenience selector, not a separate execution target
408
+
402
409
  Debug/selection overrides:
403
410
 
404
411
  ```bash
412
+ metheus-governance-mcp-cli runner show --bot-name <server_bot_name>
405
413
  metheus-governance-mcp-cli runner once --project-id <project_uuid> --provider telegram --role monitor
406
414
  metheus-governance-mcp-cli runner start --project-id <project_uuid> --provider telegram --role monitor --poll-interval-ms 5000
407
415
  metheus-governance-mcp-cli runner once --project-id <project_uuid> --provider telegram --role monitor --role-profile review
package/cli.mjs CHANGED
@@ -255,8 +255,9 @@ function printUsage() {
255
255
  ` ${cmd} selftest [--json <true|false>]`,
256
256
  ` ${cmd} local-bot-bridge [--client <gpt|claude|gemini|sample>] [--cwd <path>] [--model <name>] [--permission-mode <read_only|workspace_write|danger_full_access>] [--reasoning-effort <low|medium|high>]`,
257
257
  ` ${cmd} runner list [--json <true|false>]`,
258
- ` ${cmd} runner once [--route-name <name> | --bot-name <server_name> | --bot-id <uuid>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--context-comments <n>] [--archive-replies <true|false>]`,
259
- ` ${cmd} runner start [--route-name <name> | --bot-name <server_name> | --bot-id <uuid>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--poll-interval-ms <n>] [--context-comments <n>] [--archive-replies <true|false>]`,
258
+ ` ${cmd} runner show [--route-name <name> | --bot-name <server_name> | --bot-id <uuid>] [--json <true|false>]`,
259
+ ` ${cmd} runner once [--route-name <name> | --bot-name <server_name when one enabled route matches> | --bot-id <uuid when one enabled route matches>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--context-comments <n>] [--archive-replies <true|false>]`,
260
+ ` ${cmd} runner start [--route-name <name> | --bot-name <server_name when one enabled route matches> | --bot-id <uuid when one enabled route matches>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--poll-interval-ms <n>] [--context-comments <n>] [--archive-replies <true|false>]`,
260
261
  ` ${cmd} ctxpack pull [--project-id <uuid>] [--base-url <url>] [--workspace-dir <path|auto>] [--paths <csv>] [--timeout-seconds <n>]`,
261
262
  ` ${cmd} auth status`,
262
263
  ` ${cmd} auth login [--base-url <url>] [--flow <auto|device|callback|manual>] [--keycloak-url <url>] [--realm <name>] [--client-id <id>] [--open-browser <true|false>] [--callback-port <n>] [--timeout-seconds <n>] [--manual <true|false>]`,
@@ -2632,6 +2633,11 @@ function buildRunnerRouteListRows() {
2632
2633
  );
2633
2634
  })
2634
2635
  : null;
2636
+ const botNameSource = route.botName
2637
+ ? "route_config"
2638
+ : matchedTelegramEntry?.serverBotName
2639
+ ? "telegram_env_lookup"
2640
+ : "unresolved";
2635
2641
  const resolvedBotName = firstNonEmptyString([
2636
2642
  route.botName,
2637
2643
  matchedTelegramEntry?.serverBotName,
@@ -2644,6 +2650,7 @@ function buildRunnerRouteListRows() {
2644
2650
  provider: route.provider || "-",
2645
2651
  projectID: route.projectID || "-",
2646
2652
  botName: resolvedBotName,
2653
+ botNameSource,
2647
2654
  botID: route.botID || "-",
2648
2655
  role: route.role || "-",
2649
2656
  roleProfile: route.roleProfile || "-",
@@ -2661,6 +2668,7 @@ async function runRunnerList(flags) {
2661
2668
  return;
2662
2669
  }
2663
2670
  process.stdout.write("Runner routes\n");
2671
+ process.stdout.write(" note: routes are the executable unit. --bot-name and --bot-id are convenience selectors that resolve one enabled route when the match is unique.\n");
2664
2672
  if (!rows.length) {
2665
2673
  process.stdout.write(" none configured\n");
2666
2674
  return;
@@ -2673,18 +2681,141 @@ async function runRunnerList(flags) {
2673
2681
  ` provider: ${row.provider}`,
2674
2682
  ` project_id: ${row.projectID}`,
2675
2683
  ` server_bot_name: ${row.botName}`,
2684
+ ` server_bot_name_source: ${row.botNameSource}`,
2676
2685
  ` server_bot_id: ${row.botID}`,
2677
2686
  ` role: ${row.role}`,
2678
2687
  ` role_profile: ${row.roleProfile}`,
2679
2688
  ` destination_label: ${row.destinationLabel}`,
2680
2689
  ` poll_interval_ms: ${row.pollIntervalMs}`,
2681
2690
  ` run_once: ${CLI_NAME} runner once --route-name ${row.name}`,
2682
- row.botName ? ` run_once_by_server_bot_name: ${CLI_NAME} runner once --bot-name "${row.botName}"` : "",
2691
+ row.botName && row.botNameSource !== "unresolved"
2692
+ ? ` route_alias_by_server_bot_name: ${CLI_NAME} runner once --bot-name "${row.botName}"`
2693
+ : "",
2683
2694
  ].join("\n") + "\n",
2684
2695
  );
2685
2696
  });
2686
2697
  }
2687
2698
 
2699
+ function resolveRunnerShowSelection(flags) {
2700
+ const routes = resolveRunnerRoutes(flags, "once");
2701
+ if (!routes.length) {
2702
+ throw new Error("no runner route matched the provided filters");
2703
+ }
2704
+ if (routes.length > 1) {
2705
+ const names = routes.map((route) => normalizeRunnerRoute(route).name || runnerRouteKey(route)).join(", ");
2706
+ throw new Error(`Multiple enabled runner routes matched. Narrow with --route-name, --bot-name, or --bot-id. Matches: ${names}`);
2707
+ }
2708
+ return normalizeRunnerRoute(routes[0]);
2709
+ }
2710
+
2711
+ function findRunnerTelegramEntryForRoute(route, telegramEntries) {
2712
+ const normalizedRoute = normalizeRunnerRoute(route);
2713
+ if (normalizedRoute.provider !== "telegram") return null;
2714
+ return ensureArray(telegramEntries).find((entry) => {
2715
+ const current = safeObject(entry);
2716
+ return (
2717
+ (normalizedRoute.botID && current.serverBotID && current.serverBotID === normalizedRoute.botID)
2718
+ || (normalizedRoute.botName && current.serverBotName && current.serverBotName === normalizedRoute.botName)
2719
+ );
2720
+ }) || null;
2721
+ }
2722
+
2723
+ function buildRunnerShowPayload(route, flags = {}) {
2724
+ const normalizedRoute = normalizeRunnerRoute(route);
2725
+ const runnerConfig = loadBotRunnerConfig({ persistIfNeeded: true });
2726
+ const diagnostics = collectRunnerRouteDiagnostics(normalizedRoute, runnerConfig);
2727
+ const telegramState = readTelegramEnvState();
2728
+ const telegramEntries = ensureArray(telegramState.entries);
2729
+ const matchedTelegramEntry = findRunnerTelegramEntryForRoute(normalizedRoute, telegramEntries);
2730
+ const botNameSource = normalizedRoute.botName
2731
+ ? "route_config"
2732
+ : matchedTelegramEntry?.serverBotName
2733
+ ? "telegram_env_lookup"
2734
+ : "unresolved";
2735
+ const resolvedServerBotName = firstNonEmptyString([
2736
+ normalizedRoute.botName,
2737
+ matchedTelegramEntry?.serverBotName,
2738
+ "-",
2739
+ ]);
2740
+ const envConfig = normalizedRoute.provider
2741
+ ? loadProviderEnvConfig(normalizedRoute.provider, {
2742
+ botID: normalizedRoute.botID,
2743
+ botName: resolvedServerBotName !== "-" ? resolvedServerBotName : "",
2744
+ route: normalizedRoute,
2745
+ })
2746
+ : null;
2747
+ return {
2748
+ ok: diagnostics.errors.length === 0,
2749
+ route_name: normalizedRoute.name || runnerRouteKey(normalizedRoute),
2750
+ route_key: runnerRouteKey(normalizedRoute),
2751
+ route_config_file: runnerConfig.filePath,
2752
+ route_config: serializeRunnerRoute(normalizedRoute),
2753
+ resolved_server_identity: {
2754
+ server_bot_name: resolvedServerBotName,
2755
+ server_bot_name_source: botNameSource,
2756
+ server_bot_id: normalizedRoute.botID || "-",
2757
+ telegram_entry_file: String(envConfig?.entryFilePath || "").trim() || "-",
2758
+ },
2759
+ workspace_mapping: {
2760
+ workspace_dir: diagnostics.workspaceDir || "-",
2761
+ workspace_source: diagnostics.workspaceSource || "-",
2762
+ },
2763
+ execution_profile: {
2764
+ route_role: normalizedRoute.role || "-",
2765
+ role_profile_name: diagnostics.roleProfileName || "-",
2766
+ client: String(diagnostics.roleProfile?.client || "").trim() || "-",
2767
+ model: String(diagnostics.roleProfile?.model || "").trim() || "-",
2768
+ permission_mode: String(diagnostics.roleProfile?.permissionMode || "").trim() || "-",
2769
+ reasoning_effort: String(diagnostics.roleProfile?.reasoningEffort || "").trim() || "-",
2770
+ },
2771
+ route_selection_note: "Routes are the executable unit. --bot-name and --bot-id are convenience selectors that resolve one enabled route when the match is unique.",
2772
+ warnings: diagnostics.warnings,
2773
+ errors: diagnostics.errors,
2774
+ };
2775
+ }
2776
+
2777
+ async function runRunnerShow(flags) {
2778
+ const route = resolveRunnerShowSelection(flags);
2779
+ const payload = buildRunnerShowPayload(route, flags);
2780
+ if (boolFromRaw(flags.json, false)) {
2781
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
2782
+ return;
2783
+ }
2784
+ process.stdout.write("Runner route details\n");
2785
+ process.stdout.write(" note: routes are the executable unit. --bot-name and --bot-id are convenience selectors that resolve one enabled route when the match is unique.\n");
2786
+ process.stdout.write(
2787
+ [
2788
+ ` route_name: ${payload.route_name}`,
2789
+ ` route_key: ${payload.route_key}`,
2790
+ ` route_config_file: ${payload.route_config_file}`,
2791
+ " route_config:",
2792
+ ` provider: ${payload.route_config.provider || "-"}`,
2793
+ ` project_id: ${payload.route_config.project_id || "-"}`,
2794
+ ` role: ${payload.route_config.role || "-"}`,
2795
+ ` role_profile: ${payload.route_config.role_profile || "-"}`,
2796
+ ` destination_label: ${payload.route_config.destination_label || "-"}`,
2797
+ ` poll_interval_ms: ${payload.route_config.poll_interval_ms || 0}`,
2798
+ " resolved_server_identity:",
2799
+ ` server_bot_name: ${payload.resolved_server_identity.server_bot_name}`,
2800
+ ` server_bot_name_source: ${payload.resolved_server_identity.server_bot_name_source}`,
2801
+ ` server_bot_id: ${payload.resolved_server_identity.server_bot_id}`,
2802
+ ` telegram_entry_file: ${payload.resolved_server_identity.telegram_entry_file}`,
2803
+ " workspace_mapping:",
2804
+ ` workspace_dir: ${payload.workspace_mapping.workspace_dir}`,
2805
+ ` workspace_source: ${payload.workspace_mapping.workspace_source}`,
2806
+ " execution_profile:",
2807
+ ` route_role: ${payload.execution_profile.route_role}`,
2808
+ ` role_profile_name: ${payload.execution_profile.role_profile_name}`,
2809
+ ` client: ${payload.execution_profile.client}`,
2810
+ ` model: ${payload.execution_profile.model}`,
2811
+ ` permission_mode: ${payload.execution_profile.permission_mode}`,
2812
+ ` reasoning_effort: ${payload.execution_profile.reasoning_effort}`,
2813
+ payload.warnings.length ? ` warnings: ${payload.warnings.join("; ")}` : " warnings: -",
2814
+ payload.errors.length ? ` errors: ${payload.errors.join("; ")}` : " errors: -",
2815
+ ].join("\n") + "\n",
2816
+ );
2817
+ }
2818
+
2688
2819
  async function runRunnerStart(flags) {
2689
2820
  const jsonMode = boolFromRaw(flags.json, false);
2690
2821
  const routes = resolveRunnerRoutes(flags, "start");
@@ -2749,6 +2880,10 @@ async function runRunner(argv) {
2749
2880
  await runRunnerList(flags);
2750
2881
  return;
2751
2882
  }
2883
+ if (subcommand === "show") {
2884
+ await runRunnerShow(flags);
2885
+ return;
2886
+ }
2752
2887
  if (subcommand === "once") {
2753
2888
  await runRunnerOnce(flags);
2754
2889
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.112",
3
+ "version": "0.2.113",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [