metheus-governance-mcp-cli 0.2.101 → 0.2.102
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/README.md +20 -14
- package/cli.mjs +23 -13
- package/lib/bot-commands.mjs +72 -39
- package/lib/selftest-bot-commands.mjs +3 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,8 +58,11 @@ TELEGRAM_BOT_TOKEN=
|
|
|
58
58
|
|
|
59
59
|
```env
|
|
60
60
|
# ~/.metheus/telegram-bots/ryoai_bot.env
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
TELEGRAM_BOT_SERVER_BOT_ID=<server_bot_uuid>
|
|
62
|
+
TELEGRAM_BOT_SERVER_NAME=RyoAI_bot
|
|
63
|
+
TELEGRAM_BOT_SERVER_ROLES=monitor,review,worker,approval
|
|
64
|
+
# Optional fallback only when server bot binding is unavailable
|
|
65
|
+
# TELEGRAM_BOT_USERNAME=ryoai_bot
|
|
63
66
|
TELEGRAM_BOT_TOKEN=
|
|
64
67
|
TELEGRAM_BOT_ROLE_PROFILE=
|
|
65
68
|
TELEGRAM_BOT_AI_CLIENT=
|
|
@@ -223,15 +226,15 @@ Direct commands:
|
|
|
223
226
|
|
|
224
227
|
```bash
|
|
225
228
|
metheus-governance-mcp-cli bot list
|
|
226
|
-
metheus-governance-mcp-cli bot show --provider telegram --bot-
|
|
229
|
+
metheus-governance-mcp-cli bot show --provider telegram --bot-name RyoAI_bot
|
|
227
230
|
metheus-governance-mcp-cli bot add --provider telegram
|
|
228
231
|
metheus-governance-mcp-cli bot edit
|
|
229
232
|
metheus-governance-mcp-cli bot edit --provider telegram
|
|
230
233
|
metheus-governance-mcp-cli bot remove --provider telegram
|
|
231
|
-
metheus-governance-mcp-cli bot set-default --provider telegram --bot-
|
|
232
|
-
metheus-governance-mcp-cli bot migrate --provider telegram --bot-
|
|
234
|
+
metheus-governance-mcp-cli bot set-default --provider telegram --bot-name RyoAI_bot
|
|
235
|
+
metheus-governance-mcp-cli bot migrate --provider telegram --bot-name RyoAI_bot
|
|
233
236
|
metheus-governance-mcp-cli bot global --provider telegram
|
|
234
|
-
metheus-governance-mcp-cli bot verify --provider telegram --bot-
|
|
237
|
+
metheus-governance-mcp-cli bot verify --provider telegram --bot-name RyoAI_bot
|
|
235
238
|
```
|
|
236
239
|
|
|
237
240
|
Behavior:
|
|
@@ -259,8 +262,10 @@ Behavior:
|
|
|
259
262
|
- `bot verify` without flags starts a guided numbered flow: provider -> bot entry -> output format.
|
|
260
263
|
- `bot remove` without flags starts a guided numbered flow: provider -> bot entry -> confirm removal.
|
|
261
264
|
- Telegram stores one bot file per entry under `~/.metheus/telegram-bots/<server-bot-name>.env` with generic fields:
|
|
262
|
-
- `TELEGRAM_BOT_NAME`
|
|
263
265
|
- `TELEGRAM_BOT_SERVER_BOT_ID`
|
|
266
|
+
- `TELEGRAM_BOT_SERVER_NAME`
|
|
267
|
+
- `TELEGRAM_BOT_SERVER_ROLES`
|
|
268
|
+
- `TELEGRAM_BOT_USERNAME` only as a fallback when server bot binding is unavailable
|
|
264
269
|
- `TELEGRAM_BOT_TOKEN`
|
|
265
270
|
- `TELEGRAM_BOT_ROLE_PROFILE`
|
|
266
271
|
- `TELEGRAM_BOT_AI_CLIENT`
|
|
@@ -270,6 +275,7 @@ Behavior:
|
|
|
270
275
|
- Slack and KakaoTalk currently use a single local token entry per provider in this command flow.
|
|
271
276
|
- `bot verify` checks the configured local token, cross-checks the server bot binding, prints the effective runtime role profile summary that the runner will use, and shows which local runner routes currently point at this bot entry.
|
|
272
277
|
- `bot show` prints one local bot entry in detail, including grouped role summaries when one server bot name expands to multiple roles and any linked local runner routes.
|
|
278
|
+
- In `bot show` and `bot verify`, `stored_*` fields come from the local env file and `live_server_*` fields come from the current server `me/bots` response.
|
|
273
279
|
- `bot global` edits Telegram-wide local settings such as API base URL, allowed updates, and default bot key.
|
|
274
280
|
- `bot set-default` updates `TELEGRAM_DEFAULT_BOT_KEY`.
|
|
275
281
|
- `bot migrate` moves legacy `TELEGRAM_BOT_TOKEN` into a named Telegram bot entry.
|
|
@@ -280,16 +286,16 @@ Non-interactive examples:
|
|
|
280
286
|
metheus-governance-mcp-cli bot global --provider telegram --non-interactive true --api-base-url http://127.0.0.1:8999/telegram --auto-clear-webhook false --allowed-updates message,edited_message,channel_post
|
|
281
287
|
metheus-governance-mcp-cli bot add --provider telegram --non-interactive true --server-bot-id <server_bot_uuid> --token <telegram_bot_token> --default true
|
|
282
288
|
metheus-governance-mcp-cli bot add --provider telegram --non-interactive true --server-bot-id <server_bot_uuid> --token <telegram_bot_token> --ai-client gpt --ai-model "gpt-5.4" --ai-permission-mode read_only --ai-reasoning-effort low
|
|
283
|
-
metheus-governance-mcp-cli bot edit --provider telegram --bot-
|
|
284
|
-
metheus-governance-mcp-cli bot set-default --provider telegram --bot-
|
|
285
|
-
metheus-governance-mcp-cli bot migrate --provider telegram --bot-
|
|
286
|
-
metheus-governance-mcp-cli bot remove --provider telegram --bot-
|
|
287
|
-
metheus-governance-mcp-cli bot verify --provider telegram --bot-
|
|
289
|
+
metheus-governance-mcp-cli bot edit --provider telegram --bot-name RyoAI_bot --non-interactive true --ai-client claude --ai-model "Sonnet 4.6r" --ai-permission-mode danger_full_access --ai-reasoning-effort high
|
|
290
|
+
metheus-governance-mcp-cli bot set-default --provider telegram --bot-name RyoAI_bot --non-interactive true
|
|
291
|
+
metheus-governance-mcp-cli bot migrate --provider telegram --bot-name RyoAI_bot --server-bot-id <server_bot_uuid> --role-profile monitor --ai-client gpt --ai-permission-mode read_only --ai-reasoning-effort low --non-interactive true
|
|
292
|
+
metheus-governance-mcp-cli bot remove --provider telegram --bot-name RyoAI_bot --non-interactive true
|
|
293
|
+
metheus-governance-mcp-cli bot verify --provider telegram --bot-name RyoAI_bot --json true
|
|
288
294
|
```
|
|
289
295
|
|
|
290
|
-
For direct Telegram adds, the CLI
|
|
296
|
+
For direct Telegram adds, the CLI derives the local file name from the matched server bot name. You normally do not need `--bot-key` or `--username`. Treat `--bot-key` as an advanced compatibility selector only when you intentionally need a different local file stem.
|
|
291
297
|
|
|
292
|
-
For direct Telegram edits, `--bot-key`
|
|
298
|
+
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 advanced 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.
|
|
293
299
|
|
|
294
300
|
Current support status:
|
|
295
301
|
|
package/cli.mjs
CHANGED
|
@@ -241,13 +241,13 @@ function printUsage() {
|
|
|
241
241
|
` ${cmd} setup [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--workspace-dir <path|auto>] [--workspace-fallback-dir <path>] [--name <server_name>]`,
|
|
242
242
|
` ${cmd} bot setup [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>]`,
|
|
243
243
|
` ${cmd} bot list [--provider <telegram|slack|kakaotalk>] [--json <true|false>]`,
|
|
244
|
-
` ${cmd} bot show [--provider <telegram|slack|kakaotalk>] [--bot-
|
|
244
|
+
` ${cmd} bot show [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--json <true|false>]`,
|
|
245
245
|
` ${cmd} bot add [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>]`,
|
|
246
246
|
` ${cmd} bot edit [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>]`,
|
|
247
247
|
` ${cmd} bot remove [--provider <telegram|slack|kakaotalk>]`,
|
|
248
|
-
` ${cmd} bot set-default --provider telegram [--bot-key <
|
|
249
|
-
` ${cmd} bot migrate --provider telegram [--bot-
|
|
250
|
-
` ${cmd} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-key <
|
|
248
|
+
` ${cmd} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>]`,
|
|
249
|
+
` ${cmd} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>]`,
|
|
250
|
+
` ${cmd} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--timeout-seconds <n>] [--json <true|false>]`,
|
|
251
251
|
` ${cmd} bot global --provider telegram [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-key <key>]`,
|
|
252
252
|
` ${cmd} doctor [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--timeout-seconds <n>] [--strict <true|false>]`,
|
|
253
253
|
` ${cmd} proxy [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--workspace-dir <path|auto>] [--include-drafts <true|false>] [--auto-pull-on-conflict <true|false>] [--timeout-seconds <n>]`,
|
|
@@ -759,7 +759,7 @@ function providerEnvTemplate(provider) {
|
|
|
759
759
|
"# Keep this file on your machine only. Do not commit it.",
|
|
760
760
|
"# Store Telegram-wide settings here.",
|
|
761
761
|
"# This global file now lives in ~/.metheus/telegram-bots/_global.env.",
|
|
762
|
-
"# Per-bot secrets and AI settings live in ~/.metheus/telegram-bots/<bot-
|
|
762
|
+
"# Per-bot secrets and AI settings live in ~/.metheus/telegram-bots/<server-bot-name>.env.",
|
|
763
763
|
"# Project chat destinations must be managed on the Metheus server.",
|
|
764
764
|
"",
|
|
765
765
|
"TELEGRAM_API_BASE_URL=",
|
|
@@ -2778,10 +2778,13 @@ function parseTelegramBotEntryFile(filePath) {
|
|
|
2778
2778
|
const raw = fs.readFileSync(filePath, "utf8");
|
|
2779
2779
|
const parsed = parseSimpleEnvText(raw);
|
|
2780
2780
|
const keyFromFile = normalizeTelegramBotEnvKey(path.basename(filePath, path.extname(filePath)), "telegram_bot");
|
|
2781
|
-
const keyFromName = normalizeTelegramBotEnvKey(
|
|
2781
|
+
const keyFromName = normalizeTelegramBotEnvKey(
|
|
2782
|
+
parsed.TELEGRAM_BOT_USERNAME || parsed.TELEGRAM_BOT_NAME || parsed.TELEGRAM_BOT_SERVER_NAME || "",
|
|
2783
|
+
"",
|
|
2784
|
+
);
|
|
2782
2785
|
return {
|
|
2783
|
-
key:
|
|
2784
|
-
username: normalizeTelegramBotUsername(parsed.
|
|
2786
|
+
key: keyFromFile || keyFromName,
|
|
2787
|
+
username: normalizeTelegramBotUsername(parsed.TELEGRAM_BOT_USERNAME || parsed.TELEGRAM_BOT_NAME || ""),
|
|
2785
2788
|
serverBotID: String(parsed.TELEGRAM_BOT_SERVER_BOT_ID || "").trim(),
|
|
2786
2789
|
serverBotName: String(parsed.TELEGRAM_BOT_SERVER_NAME || "").trim(),
|
|
2787
2790
|
serverRoles: parseTelegramServerRoles(parsed.TELEGRAM_BOT_SERVER_ROLES || ""),
|
|
@@ -2933,7 +2936,7 @@ function renderNormalizedTelegramEnv(parsedEnv) {
|
|
|
2933
2936
|
"# Keep this file on your machine only. Do not commit it.",
|
|
2934
2937
|
"# Store Telegram-wide settings here.",
|
|
2935
2938
|
"# This global file lives in ~/.metheus/telegram-bots/_global.env.",
|
|
2936
|
-
"# Per-bot secrets and AI settings live in ~/.metheus/telegram-bots/<bot-
|
|
2939
|
+
"# Per-bot secrets and AI settings live in ~/.metheus/telegram-bots/<server-bot-name>.env.",
|
|
2937
2940
|
"",
|
|
2938
2941
|
`TELEGRAM_API_BASE_URL=${formatProviderEnvValue(parsed.TELEGRAM_API_BASE_URL || "")}`,
|
|
2939
2942
|
`TELEGRAM_AUTO_CLEAR_WEBHOOK=${boolFromRaw(parsed.TELEGRAM_AUTO_CLEAR_WEBHOOK, true) ? "true" : "false"}`,
|
|
@@ -2970,12 +2973,19 @@ function renderTelegramBotEntryEnv(entryRaw) {
|
|
|
2970
2973
|
const serverRoles = parseTelegramServerRoles(entry.serverRoles || "");
|
|
2971
2974
|
const lines = [
|
|
2972
2975
|
"# Metheus local Telegram bot entry",
|
|
2973
|
-
`#
|
|
2976
|
+
`# Server bot: ${botName}`,
|
|
2974
2977
|
"",
|
|
2975
|
-
`TELEGRAM_BOT_NAME=${formatProviderEnvValue(botName)}`,
|
|
2976
2978
|
`TELEGRAM_BOT_SERVER_BOT_ID=${formatProviderEnvValue(entry.serverBotID || "")}`,
|
|
2977
2979
|
`TELEGRAM_BOT_SERVER_NAME=${formatProviderEnvValue(entry.serverBotName || "")}`,
|
|
2978
2980
|
`TELEGRAM_BOT_SERVER_ROLES=${formatProviderEnvValue(serverRoles.join(","))}`,
|
|
2981
|
+
];
|
|
2982
|
+
if (!String(entry.serverBotID || "").trim() && !String(entry.serverBotName || "").trim() && String(entry.username || "").trim()) {
|
|
2983
|
+
lines.push(
|
|
2984
|
+
"# Fallback only when server bot binding is unavailable",
|
|
2985
|
+
`TELEGRAM_BOT_USERNAME=${formatProviderEnvValue(entry.username || "")}`,
|
|
2986
|
+
);
|
|
2987
|
+
}
|
|
2988
|
+
lines.push(
|
|
2979
2989
|
`TELEGRAM_BOT_TOKEN=${formatProviderEnvValue(entry.token || "")}`,
|
|
2980
2990
|
`TELEGRAM_BOT_ROLE_PROFILE=${formatProviderEnvValue(entry.roleProfile || "")}`,
|
|
2981
2991
|
`TELEGRAM_BOT_AI_CLIENT=${formatProviderEnvValue(entry.client || "")}`,
|
|
@@ -2983,7 +2993,7 @@ function renderTelegramBotEntryEnv(entryRaw) {
|
|
|
2983
2993
|
`TELEGRAM_BOT_AI_PERMISSION_MODE=${formatProviderEnvValue(entry.permissionMode || "")}`,
|
|
2984
2994
|
`TELEGRAM_BOT_AI_REASONING_EFFORT=${formatProviderEnvValue(entry.reasoningEffort || "")}`,
|
|
2985
2995
|
"",
|
|
2986
|
-
|
|
2996
|
+
);
|
|
2987
2997
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
2988
2998
|
}
|
|
2989
2999
|
|
|
@@ -5523,8 +5533,8 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
|
|
|
5523
5533
|
normalizedGlobalText.includes("TELEGRAM_DEFAULT_BOT_KEY=ryoai_bot")
|
|
5524
5534
|
&& !normalizedGlobalText.includes("TELEGRAM_BOT_RYOAI_BOT_TOKEN")
|
|
5525
5535
|
&& !normalizedGlobalText.includes("TELEGRAM_BOT_RYOAI_TOKEN")
|
|
5526
|
-
&& normalizedBotText.includes("TELEGRAM_BOT_NAME=ryoai_bot")
|
|
5527
5536
|
&& normalizedBotText.includes("TELEGRAM_BOT_SERVER_BOT_ID=bot-ryoai")
|
|
5537
|
+
&& normalizedBotText.includes("TELEGRAM_BOT_SERVER_NAME=")
|
|
5528
5538
|
&& normalizedBotText.includes("TELEGRAM_BOT_TOKEN=ryoai-token"),
|
|
5529
5539
|
`${normalizedGlobalText}\n---\n${normalizedBotText}`,
|
|
5530
5540
|
);
|
package/lib/bot-commands.mjs
CHANGED
|
@@ -216,20 +216,21 @@ function printBotUsage(deps) {
|
|
|
216
216
|
"",
|
|
217
217
|
` ${cliName} bot setup`,
|
|
218
218
|
` ${cliName} bot list [--provider <telegram|slack|kakaotalk>] [--json <true|false>]`,
|
|
219
|
-
` ${cliName} bot show [--provider <telegram|slack|kakaotalk>] [--bot-
|
|
219
|
+
` ${cliName} bot show [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--json <true|false>]`,
|
|
220
220
|
` ${cliName} bot add [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--server-bot-id <uuid>] [--token <token>] [--default <true|false>] [--verify <true|false>] [--ai-client <name>] [--ai-model <name>] [--ai-permission-mode <mode>] [--ai-reasoning-effort <level>] [--bot-key <advanced_key>] [--username <fallback_name>] [--role-profile <name>]`,
|
|
221
|
-
` ${cliName} bot edit [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--bot-
|
|
222
|
-
` ${cliName} bot remove [--provider <telegram|slack|kakaotalk>] [--non-interactive <true|false>] [--bot-key <
|
|
223
|
-
` ${cliName} bot set-default --provider telegram [--bot-key <
|
|
224
|
-
` ${cliName} bot migrate --provider telegram [--bot-
|
|
225
|
-
` ${cliName} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-key <
|
|
226
|
-
` ${cliName} bot global --provider telegram [--non-interactive <true|false>] [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-key <
|
|
221
|
+
` ${cliName} bot edit [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--username <fallback_name>] [--token <token>] [--role-profile <name>] [--ai-client <name>] [--ai-model <name>] [--ai-permission-mode <mode>] [--ai-reasoning-effort <level>]`,
|
|
222
|
+
` ${cliName} bot remove [--provider <telegram|slack|kakaotalk>] [--non-interactive <true|false>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>]`,
|
|
223
|
+
` ${cliName} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--non-interactive <true|false>]`,
|
|
224
|
+
` ${cliName} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--keep-legacy-token <true|false>] [--non-interactive <true|false>]`,
|
|
225
|
+
` ${cliName} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--timeout-seconds <n>] [--json <true|false>]`,
|
|
226
|
+
` ${cliName} bot global --provider telegram [--non-interactive <true|false>] [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-key <advanced_key>]`,
|
|
227
227
|
"",
|
|
228
228
|
`Behavior:`,
|
|
229
229
|
` - bot setup asks for provider first, then shows a numbered action menu.`,
|
|
230
230
|
` - bot add without flags uses the shortest practical guided flow: provider -> token -> verify -> optional username fallback -> optional default bot.`,
|
|
231
231
|
` - in the normal Telegram path, bot add does not ask for a local bot key or a server role/profile choice.`,
|
|
232
|
-
` - server bot name/UUID is the source of truth;
|
|
232
|
+
` - server bot name/UUID is the source of truth; --bot-key is an advanced local selector only.`,
|
|
233
|
+
` - runner commands use --route-name, not bot name. Use bot verify/show first, then run the linked route.`,
|
|
233
234
|
` - bot edit without flags asks for provider, existing entry, then walks field-by-field in a numbered flow.`,
|
|
234
235
|
` - in the normal Telegram edit path, the CLI keeps or re-resolves the server bot binding automatically instead of asking you to pick a server role/profile UUID first.`,
|
|
235
236
|
` - bot set-default / bot verify / bot remove also support guided numbered selection when run without flags.`,
|
|
@@ -469,6 +470,8 @@ function persistTelegramUsername(entry) {
|
|
|
469
470
|
const current = safeObject(entry);
|
|
470
471
|
if (current.__preferServerIdentity) return "";
|
|
471
472
|
if (String(current.serverBotID || "").trim()) return "";
|
|
473
|
+
if (String(current.serverBotName || "").trim()) return "";
|
|
474
|
+
if (ensureArray(current.serverRoles).length) return "";
|
|
472
475
|
return normalizeServerBotIdentityText(current.username || "");
|
|
473
476
|
}
|
|
474
477
|
|
|
@@ -631,12 +634,19 @@ function renderTelegramBotEntryFile(entryRaw) {
|
|
|
631
634
|
const serverRoles = ensureArray(entry.serverRoles).join(",");
|
|
632
635
|
const lines = [
|
|
633
636
|
"# Metheus local Telegram bot entry",
|
|
634
|
-
`#
|
|
637
|
+
`# Server bot: ${botName}`,
|
|
635
638
|
"",
|
|
636
|
-
`TELEGRAM_BOT_NAME=${formatEnvValue(botName)}`,
|
|
637
639
|
`TELEGRAM_BOT_SERVER_BOT_ID=${formatEnvValue(entry.serverBotID || "")}`,
|
|
638
640
|
`TELEGRAM_BOT_SERVER_NAME=${formatEnvValue(entry.serverBotName || "")}`,
|
|
639
641
|
`TELEGRAM_BOT_SERVER_ROLES=${formatEnvValue(serverRoles)}`,
|
|
642
|
+
];
|
|
643
|
+
if (!String(entry.serverBotID || "").trim() && !String(entry.serverBotName || "").trim() && String(entry.username || "").trim()) {
|
|
644
|
+
lines.push(
|
|
645
|
+
"# Fallback only when server bot binding is unavailable",
|
|
646
|
+
`TELEGRAM_BOT_USERNAME=${formatEnvValue(entry.username || "")}`,
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
lines.push(
|
|
640
650
|
`TELEGRAM_BOT_TOKEN=${formatEnvValue(entry.token || "")}`,
|
|
641
651
|
`TELEGRAM_BOT_ROLE_PROFILE=${formatEnvValue(entry.roleProfile || "")}`,
|
|
642
652
|
`TELEGRAM_BOT_AI_CLIENT=${formatEnvValue(entry.client || "")}`,
|
|
@@ -644,7 +654,7 @@ function renderTelegramBotEntryFile(entryRaw) {
|
|
|
644
654
|
`TELEGRAM_BOT_AI_PERMISSION_MODE=${formatEnvValue(entry.permissionMode || "")}`,
|
|
645
655
|
`TELEGRAM_BOT_AI_REASONING_EFFORT=${formatEnvValue(entry.reasoningEffort || "")}`,
|
|
646
656
|
"",
|
|
647
|
-
|
|
657
|
+
);
|
|
648
658
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
649
659
|
}
|
|
650
660
|
|
|
@@ -741,9 +751,9 @@ function formatRuntimeReasoningField(clientName, reasoningEffort, style = "equal
|
|
|
741
751
|
function telegramEntryDisplayDescription(entry) {
|
|
742
752
|
const current = safeObject(entry);
|
|
743
753
|
const detail = [
|
|
744
|
-
current.key ? `
|
|
745
|
-
current.serverBotID ? `
|
|
746
|
-
current.client ? `
|
|
754
|
+
current.key ? `local_selector:${current.key}` : "",
|
|
755
|
+
current.serverBotID ? `stored_server_bot_id:${current.serverBotID}` : "",
|
|
756
|
+
current.client ? `ai_client:${displayLocalAIClientName(current.client)}` : "",
|
|
747
757
|
].filter(Boolean);
|
|
748
758
|
return detail.join(" ");
|
|
749
759
|
}
|
|
@@ -752,7 +762,9 @@ function findTelegramEntryByFlags(parsedEnv, flags, deps) {
|
|
|
752
762
|
const entries = telegramEntriesForDisplay(parsedEnv, deps);
|
|
753
763
|
const requestedKey = String(flags["bot-key"] || "").trim();
|
|
754
764
|
const requestedBotID = String(flags["bot-id"] || flags["server-bot-id"] || "").trim();
|
|
755
|
-
const
|
|
765
|
+
const requestedNameRaw = String(flags["bot-name"] || flags.username || "").trim();
|
|
766
|
+
const requestedUsername = requireDependency(deps, "normalizeTelegramBotUsername")(requestedNameRaw);
|
|
767
|
+
const requestedIdentity = normalizeServerBotIdentityText(requestedNameRaw);
|
|
756
768
|
if (requestedKey) {
|
|
757
769
|
const match = entries.find((entry) => entry.key === requestedKey);
|
|
758
770
|
if (!match) {
|
|
@@ -767,16 +779,16 @@ function findTelegramEntryByFlags(parsedEnv, flags, deps) {
|
|
|
767
779
|
}
|
|
768
780
|
return match;
|
|
769
781
|
}
|
|
770
|
-
if (
|
|
782
|
+
if (requestedNameRaw) {
|
|
771
783
|
const match = entries.find(
|
|
772
784
|
(entry) => (
|
|
773
|
-
entry.username ===
|
|
774
|
-
|| normalizeServerBotIdentityText(entry.serverBotName) ===
|
|
775
|
-
|| normalizeServerBotIdentityText(entry.key) ===
|
|
785
|
+
entry.username === requestedUsername
|
|
786
|
+
|| normalizeServerBotIdentityText(entry.serverBotName) === requestedIdentity
|
|
787
|
+
|| normalizeServerBotIdentityText(entry.key) === requestedIdentity
|
|
776
788
|
),
|
|
777
789
|
);
|
|
778
790
|
if (!match) {
|
|
779
|
-
throw new Error(`Telegram bot entry with server bot name "${
|
|
791
|
+
throw new Error(`Telegram bot entry with server bot name "${requestedNameRaw}" was not found`);
|
|
780
792
|
}
|
|
781
793
|
return match;
|
|
782
794
|
}
|
|
@@ -1198,9 +1210,9 @@ function printBotList(provider, state, deps) {
|
|
|
1198
1210
|
process.stdout.write(
|
|
1199
1211
|
[
|
|
1200
1212
|
` - ${telegramEntryDisplayName(entry)}${entry.isDefault ? " [default]" : ""}`,
|
|
1201
|
-
`
|
|
1213
|
+
` local_selector: ${entry.key || "-"}${entry.key ? " (advanced)" : ""}`,
|
|
1202
1214
|
` server_bot_id: ${entry.serverBotID || "-"}`,
|
|
1203
|
-
`
|
|
1215
|
+
` fallback_username: ${entry.username ? `@${entry.username}` : "-"}`,
|
|
1204
1216
|
` token: ${entry.token ? maskSecret(entry.token) : "-"}`,
|
|
1205
1217
|
` role_profile: ${entry.roleProfile || "-"}`,
|
|
1206
1218
|
` ai_client: ${entry.client ? displayLocalAIClientName(entry.client) : "-"}`,
|
|
@@ -1224,11 +1236,13 @@ function printBotShow(provider, state, entry, deps, extras = {}) {
|
|
|
1224
1236
|
const routeLinks = safeObject(extras.routeLinks);
|
|
1225
1237
|
process.stdout.write(`${providerLabel(provider, deps)} bot\n`);
|
|
1226
1238
|
process.stdout.write(` file: ${state.filePath}\n`);
|
|
1227
|
-
process.stdout.write(`
|
|
1228
|
-
process.stdout.write(`
|
|
1239
|
+
process.stdout.write(` server_name: ${telegramEntryDisplayName(selectedEntry)}\n`);
|
|
1240
|
+
process.stdout.write(` local_selector: ${selectedEntry.key || "-"}${selectedEntry.key ? " (advanced)" : ""}\n`);
|
|
1229
1241
|
process.stdout.write(` default: ${selectedEntry.isDefault ? "yes" : "no"}\n`);
|
|
1230
|
-
process.stdout.write(`
|
|
1231
|
-
process.stdout.write(`
|
|
1242
|
+
process.stdout.write(` stored_server_bot_id: ${selectedEntry.serverBotID || "-"}\n`);
|
|
1243
|
+
process.stdout.write(` stored_server_name: ${selectedEntry.serverBotName || "-"}\n`);
|
|
1244
|
+
process.stdout.write(` stored_server_roles: ${ensureArray(selectedEntry.serverRoles).join(", ") || "-" }\n`);
|
|
1245
|
+
process.stdout.write(` fallback_username: ${selectedEntry.username ? `@${selectedEntry.username}` : "-"}\n`);
|
|
1232
1246
|
process.stdout.write(` token: ${selectedEntry.token ? maskSecret(selectedEntry.token) : "(not configured)"}\n`);
|
|
1233
1247
|
process.stdout.write(` role_profile: ${selectedEntry.roleProfile || "-"}\n`);
|
|
1234
1248
|
process.stdout.write(` ai_client: ${selectedEntry.client ? displayLocalAIClientName(selectedEntry.client) : "-"}\n`);
|
|
@@ -1237,17 +1251,17 @@ function printBotShow(provider, state, entry, deps, extras = {}) {
|
|
|
1237
1251
|
process.stdout.write(` reasoning_effort: ${selectedEntry.reasoningEffort || "-"}\n`);
|
|
1238
1252
|
if (Object.keys(serverBinding).length) {
|
|
1239
1253
|
process.stdout.write(` server_binding: ${serverBinding.ok ? "OK" : "FAIL"}${serverBinding.detail ? ` (${serverBinding.detail})` : ""}\n`);
|
|
1240
|
-
process.stdout.write(`
|
|
1241
|
-
process.stdout.write(`
|
|
1242
|
-
process.stdout.write(`
|
|
1254
|
+
process.stdout.write(` binding_mode: ${serverBinding.mode || "-"}\n`);
|
|
1255
|
+
process.stdout.write(` live_server_name: ${serverBinding.name || "-"}\n`);
|
|
1256
|
+
process.stdout.write(` live_server_bot_id: ${serverBinding.serverBotID || selectedEntry.serverBotID || "-" }\n`);
|
|
1243
1257
|
if (serverBinding.mode === "group") {
|
|
1244
|
-
process.stdout.write(`
|
|
1258
|
+
process.stdout.write(` live_server_roles: ${ensureArray(serverBinding.roles).join(", ") || "-"}\n`);
|
|
1245
1259
|
const groupedProfiles = safeObject(serverBinding.effectiveRoleProfiles);
|
|
1246
1260
|
Object.keys(groupedProfiles).forEach((role) => {
|
|
1247
1261
|
process.stdout.write(` runtime_role_profile[${role}]: ${formatRoleProfileOutputLine(groupedProfiles[role])}\n`);
|
|
1248
1262
|
});
|
|
1249
1263
|
} else if (serverBinding.effectiveRoleProfile) {
|
|
1250
|
-
process.stdout.write(`
|
|
1264
|
+
process.stdout.write(` live_server_role: ${serverBinding.role || "-"}\n`);
|
|
1251
1265
|
process.stdout.write(` runtime_role_profile: ${formatRoleProfileOutputLine(serverBinding.effectiveRoleProfile)}\n`);
|
|
1252
1266
|
}
|
|
1253
1267
|
}
|
|
@@ -2105,9 +2119,9 @@ async function buildTelegramEntrySelectionRows(entries, flags, deps) {
|
|
|
2105
2119
|
label = serverName;
|
|
2106
2120
|
}
|
|
2107
2121
|
const descriptionParts = [
|
|
2108
|
-
current.key ? `
|
|
2109
|
-
current.serverBotID ? `
|
|
2110
|
-
current.client ? `
|
|
2122
|
+
current.key ? `local_selector:${current.key} (advanced)` : "",
|
|
2123
|
+
current.serverBotID ? `stored_server_bot_id:${current.serverBotID}` : "",
|
|
2124
|
+
current.client ? `ai_client:${displayLocalAIClientName(current.client)}` : "",
|
|
2111
2125
|
].filter(Boolean);
|
|
2112
2126
|
return {
|
|
2113
2127
|
value: current.key,
|
|
@@ -2588,6 +2602,25 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
|
|
|
2588
2602
|
envConfig.serverBotName = desiredServerBotName;
|
|
2589
2603
|
envConfig.serverRoles = desiredServerRoles;
|
|
2590
2604
|
}
|
|
2605
|
+
const rewriteEntry = needsMetadataBackfill
|
|
2606
|
+
? {
|
|
2607
|
+
...selectedEntry,
|
|
2608
|
+
serverBotID: desiredServerBotID,
|
|
2609
|
+
serverBotName: desiredServerBotName,
|
|
2610
|
+
serverRoles: desiredServerRoles,
|
|
2611
|
+
}
|
|
2612
|
+
: selectedEntry;
|
|
2613
|
+
const currentEntryFilePath = String(
|
|
2614
|
+
rewriteEntry.entryFilePath
|
|
2615
|
+
|| requireDependency(deps, "telegramBotEntryFilePath")(rewriteEntry.key),
|
|
2616
|
+
).trim();
|
|
2617
|
+
const expectedEntryText = renderTelegramBotEntryFile(rewriteEntry);
|
|
2618
|
+
const currentEntryText = currentEntryFilePath && fs.existsSync(currentEntryFilePath)
|
|
2619
|
+
? fs.readFileSync(currentEntryFilePath, "utf8")
|
|
2620
|
+
: "";
|
|
2621
|
+
if (currentEntryText !== expectedEntryText) {
|
|
2622
|
+
rewriteTelegramEntryFile(rewriteEntry, deps);
|
|
2623
|
+
}
|
|
2591
2624
|
}
|
|
2592
2625
|
}
|
|
2593
2626
|
routeLinks = summarizeTelegramRouteLinks(state.parsed, {
|
|
@@ -2636,8 +2669,8 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
|
|
|
2636
2669
|
const lines = [
|
|
2637
2670
|
`${providerLabel(provider, deps)} verify: ${overallOK ? "OK" : "FAIL"}`,
|
|
2638
2671
|
`file: ${envConfig.filePath}`,
|
|
2639
|
-
provider === "telegram" ? `
|
|
2640
|
-
provider === "telegram" ? `
|
|
2672
|
+
provider === "telegram" ? `local_selector: ${envConfig.botKey || "-"}${envConfig.botKey ? " (advanced)" : ""}` : "",
|
|
2673
|
+
provider === "telegram" ? `stored_server_bot_id: ${envConfig.serverBotID || "-"}` : "",
|
|
2641
2674
|
provider === "telegram" ? `stored_server_name: ${envConfig.serverBotName || "-"}` : "",
|
|
2642
2675
|
provider === "telegram" ? `stored_server_roles: ${ensureArray(envConfig.serverRoles).join(", ") || "-"}` : "",
|
|
2643
2676
|
provider === "telegram" ? `role_profile: ${envConfig.roleProfile || "-"}` : "",
|
|
@@ -2650,9 +2683,9 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
|
|
|
2650
2683
|
routeLinks ? `route_links: ${intFromRaw(routeLinks.total, 0)}` : "",
|
|
2651
2684
|
].filter(Boolean);
|
|
2652
2685
|
if (provider === "telegram" && serverBinding) {
|
|
2653
|
-
lines.push(`
|
|
2654
|
-
lines.push(`
|
|
2655
|
-
lines.push(`
|
|
2686
|
+
lines.push(`binding_mode: ${serverBinding.mode || "-"}`);
|
|
2687
|
+
lines.push(`live_server_name: ${serverBinding.name || "-"}`);
|
|
2688
|
+
lines.push(`live_server_roles: ${ensureArray(serverBinding.roles).join(", ") || "-"}`);
|
|
2656
2689
|
if (serverBinding.mode === "group") {
|
|
2657
2690
|
const groupedProfiles = safeObject(serverBinding.effectiveRoleProfiles);
|
|
2658
2691
|
Object.keys(groupedProfiles).forEach((role) => {
|
|
@@ -352,8 +352,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
352
352
|
const addGlobals = readTelegramGlobals();
|
|
353
353
|
push(
|
|
354
354
|
"bot_add_guided_creates_named_telegram_entry",
|
|
355
|
-
String(addState.
|
|
356
|
-
&& String(addState.TELEGRAM_BOT_SERVER_NAME || "") === "MonitorSelftestBot"
|
|
355
|
+
String(addState.TELEGRAM_BOT_SERVER_NAME || "") === "MonitorSelftestBot"
|
|
357
356
|
&& String(addState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor"
|
|
358
357
|
&& String(addState.TELEGRAM_BOT_TOKEN || "") === "selftest-main-token"
|
|
359
358
|
&& String(addState.TELEGRAM_BOT_ROLE_PROFILE || "") === "monitor"
|
|
@@ -403,14 +402,13 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
403
402
|
const groupedState = readTelegramBotEntry("ryoai_bot");
|
|
404
403
|
push(
|
|
405
404
|
"bot_add_guided_autoresolves_server_bot_group_without_role_prompt",
|
|
406
|
-
String(groupedState.
|
|
407
|
-
&& String(groupedState.TELEGRAM_BOT_SERVER_BOT_ID || "") === ""
|
|
405
|
+
String(groupedState.TELEGRAM_BOT_SERVER_BOT_ID || "") === ""
|
|
408
406
|
&& String(groupedState.TELEGRAM_BOT_SERVER_NAME || "") === "RyoAI_bot"
|
|
409
407
|
&& String(groupedState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor,review,worker,approval"
|
|
410
408
|
&& String(groupedState.TELEGRAM_BOT_ROLE_PROFILE || "") === ""
|
|
411
409
|
&& String(groupedState.TELEGRAM_BOT_AI_CLIENT || "") === ""
|
|
412
410
|
&& String(groupedState.TELEGRAM_BOT_AI_PERMISSION_MODE || "") === "",
|
|
413
|
-
`
|
|
411
|
+
`server_name=${String(groupedState.TELEGRAM_BOT_SERVER_NAME || "")} roles=${String(groupedState.TELEGRAM_BOT_SERVER_ROLES || "")} server_bot_id=${String(groupedState.TELEGRAM_BOT_SERVER_BOT_ID || "")} role=${String(groupedState.TELEGRAM_BOT_ROLE_PROFILE || "")}`,
|
|
414
412
|
);
|
|
415
413
|
|
|
416
414
|
const groupedEditResult = await runCLI({
|