metheus-governance-mcp-cli 0.2.105 → 0.2.107
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 +16 -16
- package/cli.mjs +1 -1
- package/lib/bot-commands.mjs +71 -49
- package/lib/doctor-checks.mjs +1 -1
- package/lib/selftest-bot-commands.mjs +81 -43
- package/lib/selftest-runner-scenarios.mjs +17 -17
- package/lib/selftest-telegram-e2e.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,9 +58,9 @@ TELEGRAM_BOT_TOKEN=
|
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
```env
|
|
61
|
-
# ~/.metheus/telegram-bots
|
|
61
|
+
# ~/.metheus/telegram-bots/<ServerBotName>.env
|
|
62
62
|
TELEGRAM_BOT_SERVER_BOT_ID=<server_bot_uuid>
|
|
63
|
-
TELEGRAM_BOT_SERVER_NAME
|
|
63
|
+
TELEGRAM_BOT_SERVER_NAME=<ServerBotName>
|
|
64
64
|
TELEGRAM_BOT_SERVER_ROLES=monitor,review,worker,approval
|
|
65
65
|
TELEGRAM_BOT_SERVER_ROLE_IDS=monitor:<uuid>,review:<uuid>,worker:<uuid>,approval:<uuid>
|
|
66
66
|
# Optional fallback only when server bot binding is unavailable
|
|
@@ -233,22 +233,22 @@ Direct commands:
|
|
|
233
233
|
|
|
234
234
|
```bash
|
|
235
235
|
metheus-governance-mcp-cli bot list
|
|
236
|
-
metheus-governance-mcp-cli bot show --provider telegram --bot-name
|
|
236
|
+
metheus-governance-mcp-cli bot show --provider telegram --bot-name <server_bot_name>
|
|
237
237
|
metheus-governance-mcp-cli bot add --provider telegram
|
|
238
238
|
metheus-governance-mcp-cli bot edit
|
|
239
239
|
metheus-governance-mcp-cli bot edit --provider telegram
|
|
240
240
|
metheus-governance-mcp-cli bot remove --provider telegram
|
|
241
|
-
metheus-governance-mcp-cli bot set-default --provider telegram --bot-name
|
|
242
|
-
metheus-governance-mcp-cli bot migrate --provider telegram --bot-name
|
|
241
|
+
metheus-governance-mcp-cli bot set-default --provider telegram --bot-name <server_bot_name>
|
|
242
|
+
metheus-governance-mcp-cli bot migrate --provider telegram --bot-name <server_bot_name>
|
|
243
243
|
metheus-governance-mcp-cli bot global --provider telegram
|
|
244
|
-
metheus-governance-mcp-cli bot verify --provider telegram --bot-name
|
|
244
|
+
metheus-governance-mcp-cli bot verify --provider telegram --bot-name <server_bot_name>
|
|
245
245
|
```
|
|
246
246
|
|
|
247
247
|
Behavior:
|
|
248
248
|
|
|
249
249
|
- `bot setup` asks for `Telegram / Slack / KakaoTalk` first, then prompts with numbered actions.
|
|
250
250
|
- `bot add` without flags now uses the shortest practical guided flow: provider -> token -> verify -> optional save-anyway only when verify fails -> optional username fallback only when verify cannot discover it -> optional AI model selection when the resolved defaults leave it blank -> optional default bot.
|
|
251
|
-
- In the normal Telegram path, `bot add` does not ask for a local
|
|
251
|
+
- In the normal Telegram path, `bot add` does not ask for a local selector, a server bot UUID, or an approval / worker / review / monitor choice.
|
|
252
252
|
- For Telegram, the local bot file stem is auto-generated from the matched server bot name or verified username, so you do not have to invent a separate local nickname first.
|
|
253
253
|
- For Telegram, the CLI tries to match the verified bot identity against the server `me/bots` list first. If the server exposes one logical bot name with multiple roles such as `approval`, `worker`, `review`, and `monitor`, the CLI does not ask you to choose one UUID. It binds by server bot name and keeps the local role/AI fields empty so runtime can use the server bot role for each route.
|
|
254
254
|
- When the Telegram username matches exactly one server bot role, the CLI still auto-fills the local `role_profile` and blank AI defaults from your local `bot-runner.json` `role_profiles` mapping.
|
|
@@ -284,8 +284,8 @@ Behavior:
|
|
|
284
284
|
- `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.
|
|
285
285
|
- `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.
|
|
286
286
|
- In `bot show` and `bot verify`, `saved_local_file` means the values already stored on disk under `~/.metheus/telegram-bots/*.env`, while `current_server_protocol` means the fresh `/api/v1/me/bots` response from the server right now.
|
|
287
|
-
- `bot global` edits Telegram-wide local settings such as API base URL, allowed updates, and default bot
|
|
288
|
-
- `bot set-default`
|
|
287
|
+
- `bot global` edits Telegram-wide local settings such as API base URL, allowed updates, and the default Telegram bot selector.
|
|
288
|
+
- `bot set-default` changes the default Telegram bot selection.
|
|
289
289
|
- `bot migrate` moves legacy `TELEGRAM_BOT_TOKEN` into a named Telegram bot entry.
|
|
290
290
|
|
|
291
291
|
Non-interactive examples:
|
|
@@ -294,16 +294,16 @@ Non-interactive examples:
|
|
|
294
294
|
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
|
|
295
295
|
metheus-governance-mcp-cli bot add --provider telegram --non-interactive true --server-bot-id <server_bot_uuid> --token <telegram_bot_token> --default true
|
|
296
296
|
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
|
|
297
|
-
metheus-governance-mcp-cli bot edit --provider telegram --bot-name
|
|
298
|
-
metheus-governance-mcp-cli bot set-default --provider telegram --bot-name
|
|
299
|
-
metheus-governance-mcp-cli bot migrate --provider telegram --bot-name
|
|
300
|
-
metheus-governance-mcp-cli bot remove --provider telegram --bot-name
|
|
301
|
-
metheus-governance-mcp-cli bot verify --provider telegram --bot-name
|
|
297
|
+
metheus-governance-mcp-cli bot edit --provider telegram --bot-name <server_bot_name> --non-interactive true --ai-client claude --ai-model "Sonnet 4.6r" --ai-permission-mode danger_full_access --ai-reasoning-effort high
|
|
298
|
+
metheus-governance-mcp-cli bot set-default --provider telegram --bot-name <server_bot_name> --non-interactive true
|
|
299
|
+
metheus-governance-mcp-cli bot migrate --provider telegram --bot-name <server_bot_name> --server-bot-id <server_bot_uuid> --role-profile monitor --ai-client gpt --ai-permission-mode read_only --ai-reasoning-effort low --non-interactive true
|
|
300
|
+
metheus-governance-mcp-cli bot remove --provider telegram --bot-name <server_bot_name> --non-interactive true
|
|
301
|
+
metheus-governance-mcp-cli bot verify --provider telegram --bot-name <server_bot_name> --json true
|
|
302
302
|
```
|
|
303
303
|
|
|
304
|
-
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
|
|
304
|
+
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 a legacy compatibility selector only when you intentionally need to target an older local selector directly.
|
|
305
305
|
|
|
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
|
|
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
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.
|
|
309
309
|
|
package/cli.mjs
CHANGED
|
@@ -249,7 +249,7 @@ function printUsage() {
|
|
|
249
249
|
` ${cmd} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>]`,
|
|
250
250
|
` ${cmd} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>]`,
|
|
251
251
|
` ${cmd} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--timeout-seconds <n>] [--json <true|false>]`,
|
|
252
|
-
` ${cmd} bot global --provider telegram [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-
|
|
252
|
+
` ${cmd} bot global --provider telegram [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-name <server_name>] [--default-bot-id <uuid>]`,
|
|
253
253
|
` ${cmd} doctor [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--timeout-seconds <n>] [--strict <true|false>]`,
|
|
254
254
|
` ${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>]`,
|
|
255
255
|
` ${cmd} selftest [--json <true|false>]`,
|
package/lib/bot-commands.mjs
CHANGED
|
@@ -223,18 +223,18 @@ function printBotUsage(deps) {
|
|
|
223
223
|
` ${cliName} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--non-interactive <true|false>]`,
|
|
224
224
|
` ${cliName} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--keep-legacy-token <true|false>] [--non-interactive <true|false>]`,
|
|
225
225
|
` ${cliName} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--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-
|
|
226
|
+
` ${cliName} bot global --provider telegram [--non-interactive <true|false>] [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-name <server_name>] [--default-bot-id <uuid>]`,
|
|
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
|
-
` - in the normal Telegram path, bot add does not ask for a local
|
|
232
|
-
` - server bot name/UUID is the source of truth; --bot-key
|
|
231
|
+
` - in the normal Telegram path, bot add does not ask for a local selector or a server role/profile choice.`,
|
|
232
|
+
` - server bot name/UUID is the source of truth; --bot-key remains only as a legacy compatibility selector.`,
|
|
233
233
|
` - runner commands can auto-select by --bot-name or --bot-id when one enabled route matches. Use runner list first if you are unsure.`,
|
|
234
234
|
` - bot edit without flags asks for provider, existing entry, then walks field-by-field in a numbered flow.`,
|
|
235
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.`,
|
|
236
236
|
` - bot set-default / bot verify / bot remove also support guided numbered selection when run without flags.`,
|
|
237
|
-
` -
|
|
237
|
+
` - legacy compatibility: prefer --bot-name or --bot-id in normal operator workflows; use --bot-key only when you must target an older local selector directly.`,
|
|
238
238
|
"",
|
|
239
239
|
].join("\n"),
|
|
240
240
|
);
|
|
@@ -858,7 +858,7 @@ function findTelegramEntryByFlags(parsedEnv, flags, deps) {
|
|
|
858
858
|
if (requestedKey) {
|
|
859
859
|
const match = entries.find((entry) => entry.key === requestedKey);
|
|
860
860
|
if (!match) {
|
|
861
|
-
throw new Error(`Telegram bot entry "${requestedKey}" was not found`);
|
|
861
|
+
throw new Error(`Telegram bot entry with legacy local selector "${requestedKey}" was not found`);
|
|
862
862
|
}
|
|
863
863
|
return match;
|
|
864
864
|
}
|
|
@@ -895,7 +895,7 @@ function saveTelegramBotEdit(parsed, selected, current, deps) {
|
|
|
895
895
|
nextParsed.TELEGRAM_DEFAULT_BOT_KEY = current.key;
|
|
896
896
|
}
|
|
897
897
|
const filePath = writeProviderEnvState("telegram", nextParsed, deps);
|
|
898
|
-
process.stdout.write(`Saved Telegram bot
|
|
898
|
+
process.stdout.write(`Saved Telegram bot file for "${telegramEntryDisplayName(current)}" to ${filePath}\n`);
|
|
899
899
|
return filePath;
|
|
900
900
|
}
|
|
901
901
|
|
|
@@ -1129,7 +1129,7 @@ async function editTelegramBotGuided(ui, parsed, selected, current, flags, deps)
|
|
|
1129
1129
|
parsed.TELEGRAM_DEFAULT_BOT_KEY = "";
|
|
1130
1130
|
}
|
|
1131
1131
|
|
|
1132
|
-
if (!await promptYesNo(ui, `Save changes for "${current
|
|
1132
|
+
if (!await promptYesNo(ui, `Save changes for "${telegramEntryDisplayName(current)}" now?`, true)) {
|
|
1133
1133
|
process.stdout.write("Cancelled.\n");
|
|
1134
1134
|
return;
|
|
1135
1135
|
}
|
|
@@ -1306,11 +1306,9 @@ function printBotList(provider, state, deps) {
|
|
|
1306
1306
|
process.stdout.write(" entries: none\n");
|
|
1307
1307
|
return;
|
|
1308
1308
|
}
|
|
1309
|
-
|
|
1309
|
+
const defaultEntry = entries.find((entry) => entry.isDefault) || null;
|
|
1310
|
+
process.stdout.write(` default: ${defaultEntry ? telegramEntryDisplayName(defaultEntry) : "-"}\n`);
|
|
1310
1311
|
entries.forEach((entry) => {
|
|
1311
|
-
const advancedSelectorLine = entry.key
|
|
1312
|
-
? ` advanced_local_selector: ${entry.key} (compatibility only)`
|
|
1313
|
-
: "";
|
|
1314
1312
|
process.stdout.write(
|
|
1315
1313
|
[
|
|
1316
1314
|
` - ${telegramEntryDisplayName(entry)}${entry.isDefault ? " [default]" : ""}`,
|
|
@@ -1325,7 +1323,6 @@ function printBotList(provider, state, deps) {
|
|
|
1325
1323
|
` model: ${entry.model || "-"}`,
|
|
1326
1324
|
` permission_mode: ${entry.permissionMode || "-"}`,
|
|
1327
1325
|
` reasoning_effort: ${entry.reasoningEffort || "-"}`,
|
|
1328
|
-
advancedSelectorLine,
|
|
1329
1326
|
].join("\n") + "\n",
|
|
1330
1327
|
);
|
|
1331
1328
|
});
|
|
@@ -1361,7 +1358,6 @@ function printBotShow(provider, state, entry, deps, extras = {}) {
|
|
|
1361
1358
|
`ai_model: ${selectedEntry.model || "-"}`,
|
|
1362
1359
|
`permission_mode: ${selectedEntry.permissionMode || "-"}`,
|
|
1363
1360
|
`reasoning_effort: ${selectedEntry.reasoningEffort || "-"}`,
|
|
1364
|
-
selectedEntry.key ? `advanced_local_selector: ${selectedEntry.key} (compatibility only)` : "",
|
|
1365
1361
|
]);
|
|
1366
1362
|
if (Object.keys(serverBinding).length) {
|
|
1367
1363
|
const liveLines = [
|
|
@@ -1441,7 +1437,7 @@ async function resolveTelegramEntryForShow(ui, parsedEnv, flags, deps) {
|
|
|
1441
1437
|
}
|
|
1442
1438
|
const nonInteractive = boolFromRaw(flags["non-interactive"] ?? flags.yes ?? flags.json, false);
|
|
1443
1439
|
if (nonInteractive) {
|
|
1444
|
-
throw new Error("Telegram bot selector is required when multiple entries exist; pass --bot-
|
|
1440
|
+
throw new Error("Telegram bot selector is required when multiple entries exist; pass --bot-name or --bot-id (legacy --bot-key is still supported)");
|
|
1445
1441
|
}
|
|
1446
1442
|
return chooseTelegramEntry(ui, parsedEnv, deps, "Select Telegram bot entry", flags);
|
|
1447
1443
|
}
|
|
@@ -1568,12 +1564,12 @@ async function chooseServerBot(ui, provider, baseURL, timeoutSeconds, deps, opti
|
|
|
1568
1564
|
{
|
|
1569
1565
|
value: "__manual__",
|
|
1570
1566
|
label: "Manual entry",
|
|
1571
|
-
description: "
|
|
1567
|
+
description: "enter a server bot UUID manually",
|
|
1572
1568
|
},
|
|
1573
1569
|
{
|
|
1574
1570
|
value: "__blank__",
|
|
1575
1571
|
label: "Leave empty",
|
|
1576
|
-
description: "
|
|
1572
|
+
description: "continue without a server bot binding",
|
|
1577
1573
|
},
|
|
1578
1574
|
],
|
|
1579
1575
|
{ defaultIndex: 0 },
|
|
@@ -1618,12 +1614,12 @@ async function chooseServerBot(ui, provider, baseURL, timeoutSeconds, deps, opti
|
|
|
1618
1614
|
{
|
|
1619
1615
|
value: "__manual__",
|
|
1620
1616
|
label: "Manual entry",
|
|
1621
|
-
description: "
|
|
1617
|
+
description: "enter a server bot UUID manually",
|
|
1622
1618
|
},
|
|
1623
1619
|
{
|
|
1624
1620
|
value: "__blank__",
|
|
1625
1621
|
label: "Leave empty",
|
|
1626
|
-
description: "
|
|
1622
|
+
description: "continue without a server bot binding",
|
|
1627
1623
|
},
|
|
1628
1624
|
],
|
|
1629
1625
|
{ defaultIndex: 0 },
|
|
@@ -1710,7 +1706,7 @@ async function resolveServerBotForNonInteractive(provider, flags, deps, options
|
|
|
1710
1706
|
(bot) => normalizeServerBotIdentityText(bot.name) === requestedName,
|
|
1711
1707
|
);
|
|
1712
1708
|
if (!matchedByName.length) {
|
|
1713
|
-
throw new Error(`no server bot matched ${requestedName}`);
|
|
1709
|
+
throw new Error(`no server bot matched the requested server bot name "${requestedName}"`);
|
|
1714
1710
|
}
|
|
1715
1711
|
if (matchedByName.length === 1) {
|
|
1716
1712
|
const match = matchedByName[0] || {};
|
|
@@ -1789,23 +1785,26 @@ async function promptAIModel(ui, deps, clientName, defaultValue = "", title = "S
|
|
|
1789
1785
|
const normalizedClient = requireDependency(deps, "normalizeLocalAIClientName")(clientName || "", "");
|
|
1790
1786
|
const currentValue = String(defaultValue || "").trim();
|
|
1791
1787
|
const suggestions = suggestedAIModelsForClient(normalizedClient);
|
|
1788
|
+
const currentMatchesSuggestions = currentValue && suggestions.some((item) => item.value === currentValue);
|
|
1792
1789
|
const options = [
|
|
1793
1790
|
{ value: "", label: "(blank)", description: "leave AI model empty" },
|
|
1794
1791
|
];
|
|
1795
|
-
|
|
1792
|
+
options.push(...suggestions);
|
|
1793
|
+
if (currentValue && !currentMatchesSuggestions) {
|
|
1796
1794
|
options.push({
|
|
1797
1795
|
value: currentValue,
|
|
1798
|
-
label: currentValue
|
|
1799
|
-
description: "
|
|
1796
|
+
label: `Keep current custom model (${currentValue})`,
|
|
1797
|
+
description: "reuse the model already saved on disk",
|
|
1800
1798
|
});
|
|
1801
1799
|
}
|
|
1802
|
-
options.push(...suggestions);
|
|
1803
1800
|
options.push({
|
|
1804
1801
|
value: "__manual__",
|
|
1805
1802
|
label: "Manual entry",
|
|
1806
1803
|
description: "type the model name yourself",
|
|
1807
1804
|
});
|
|
1808
|
-
const selectedIndex =
|
|
1805
|
+
const selectedIndex = currentMatchesSuggestions
|
|
1806
|
+
? Math.max(0, options.findIndex((item) => item.value === currentValue))
|
|
1807
|
+
: (suggestions.length ? 1 : Math.max(0, options.findIndex((item) => item.value === currentValue)));
|
|
1809
1808
|
const selected = await promptChoice(ui, title, options, { defaultIndex: selectedIndex >= 0 ? selectedIndex : 0 });
|
|
1810
1809
|
if (String(selected?.value || "") === "__manual__") {
|
|
1811
1810
|
return String(await promptRequiredLine(ui, "AI model", currentValue)).trim();
|
|
@@ -2154,6 +2153,11 @@ function resolveTelegramServerBindingDetailsFromBots(envConfig, bots, deps) {
|
|
|
2154
2153
|
const normalizedServerIdentity = normalizeServerBotIdentityText(current.serverBotName || current.botUsername || current.botKey);
|
|
2155
2154
|
const matches = bots.filter((bot) => normalizeServerBotIdentityText(bot.name) === normalizedServerIdentity);
|
|
2156
2155
|
if (!matches.length) {
|
|
2156
|
+
const unmatchedIdentity = String(current.botUsername || "").trim()
|
|
2157
|
+
? `@${String(current.botUsername || "").trim()}`
|
|
2158
|
+
: String(current.serverBotName || "").trim()
|
|
2159
|
+
? `"${String(current.serverBotName || "").trim()}"`
|
|
2160
|
+
: "this local Telegram bot";
|
|
2157
2161
|
return {
|
|
2158
2162
|
ok: false,
|
|
2159
2163
|
mode: "missing",
|
|
@@ -2165,7 +2169,7 @@ function resolveTelegramServerBindingDetailsFromBots(envConfig, bots, deps) {
|
|
|
2165
2169
|
serverBotID: "",
|
|
2166
2170
|
effectiveRoleProfile: null,
|
|
2167
2171
|
effectiveRoleProfiles: {},
|
|
2168
|
-
detail: `no server bot matched ${
|
|
2172
|
+
detail: `no server bot matched ${unmatchedIdentity}`,
|
|
2169
2173
|
};
|
|
2170
2174
|
}
|
|
2171
2175
|
if (matches.length > 1) {
|
|
@@ -2262,7 +2266,6 @@ async function buildTelegramEntrySelectionRows(entries, flags, deps) {
|
|
|
2262
2266
|
const descriptionParts = [
|
|
2263
2267
|
current.serverBotID ? `stored_server_bot_id:${current.serverBotID}` : "",
|
|
2264
2268
|
current.client ? `ai_client:${displayLocalAIClientName(current.client)}` : "",
|
|
2265
|
-
current.key ? `advanced_selector:${current.key}` : "",
|
|
2266
2269
|
].filter(Boolean);
|
|
2267
2270
|
return {
|
|
2268
2271
|
value: current.key,
|
|
@@ -2422,12 +2425,12 @@ async function addTelegramBot(ui, flags, deps) {
|
|
|
2422
2425
|
defaultKeyHint,
|
|
2423
2426
|
);
|
|
2424
2427
|
if (nonInteractive && existingKeys.has(botKey)) {
|
|
2425
|
-
throw new Error(`Telegram
|
|
2428
|
+
throw new Error(`Telegram legacy local selector "${botKey}" already exists`);
|
|
2426
2429
|
}
|
|
2427
2430
|
const serverGroupMatched = serverBot.matchMode === "group";
|
|
2428
2431
|
if (serverGroupMatched && !nonInteractive) {
|
|
2429
2432
|
process.stdout.write(
|
|
2430
|
-
`Matched server Telegram bot "${serverBot.name || username ||
|
|
2433
|
+
`Matched server Telegram bot "${serverBot.name || username || "current Telegram bot"}" with roles: ${ensureArray(serverBot.roles).join(", ")}. Runtime will use the server role, so local role/AI fields can stay empty.\n`,
|
|
2431
2434
|
);
|
|
2432
2435
|
}
|
|
2433
2436
|
const aiFlagOverrides = hasOwnFlag(flags, "client")
|
|
@@ -2522,19 +2525,25 @@ async function addTelegramBot(ui, flags, deps) {
|
|
|
2522
2525
|
if (
|
|
2523
2526
|
boolFromRaw(flags.default, false)
|
|
2524
2527
|
|| (nonInteractive && !hasCurrentDefault)
|
|
2525
|
-
|| (!nonInteractive && !hasCurrentDefault && await promptYesNo(ui, "Set this bot as
|
|
2528
|
+
|| (!nonInteractive && !hasCurrentDefault && await promptYesNo(ui, "Set this bot as the default Telegram bot?", true))
|
|
2526
2529
|
) {
|
|
2527
2530
|
nextParsed.TELEGRAM_DEFAULT_BOT_KEY = botKey;
|
|
2528
2531
|
}
|
|
2529
2532
|
|
|
2530
2533
|
const filePath = writeProviderEnvState("telegram", nextParsed, deps);
|
|
2531
|
-
process.stdout.write(`Saved Telegram bot
|
|
2534
|
+
process.stdout.write(`Saved Telegram bot file for "${String(serverBot.name || username || botKey).trim() || "telegram"}" to ${filePath}\n`);
|
|
2532
2535
|
}
|
|
2533
2536
|
|
|
2534
2537
|
async function editTelegramGlobalSettings(ui, flags, deps) {
|
|
2535
2538
|
const state = loadProviderEnvState("telegram", deps);
|
|
2536
2539
|
const parsed = { ...state.parsed };
|
|
2537
2540
|
const nonInteractive = boolFromRaw(flags["non-interactive"] ?? flags.yes, false);
|
|
2541
|
+
const defaultSelectorFlags = {
|
|
2542
|
+
...flags,
|
|
2543
|
+
"bot-name": firstNonEmptyString([flags["default-bot-name"], flags["bot-name"]]),
|
|
2544
|
+
"bot-id": firstNonEmptyString([flags["default-bot-id"], flags["bot-id"]]),
|
|
2545
|
+
"bot-key": firstNonEmptyString([flags["default-bot-key"], flags["bot-key"]]),
|
|
2546
|
+
};
|
|
2538
2547
|
if (nonInteractive) {
|
|
2539
2548
|
if (Object.prototype.hasOwnProperty.call(flags, "api-base-url")) {
|
|
2540
2549
|
parsed.TELEGRAM_API_BASE_URL = String(flags["api-base-url"] || "").trim();
|
|
@@ -2545,8 +2554,16 @@ async function editTelegramGlobalSettings(ui, flags, deps) {
|
|
|
2545
2554
|
if (Object.prototype.hasOwnProperty.call(flags, "allowed-updates")) {
|
|
2546
2555
|
parsed.TELEGRAM_ALLOWED_UPDATES = String(flags["allowed-updates"] || "").trim();
|
|
2547
2556
|
}
|
|
2548
|
-
if (
|
|
2549
|
-
|
|
2557
|
+
if (
|
|
2558
|
+
Object.prototype.hasOwnProperty.call(flags, "default-bot-name")
|
|
2559
|
+
|| Object.prototype.hasOwnProperty.call(flags, "default-bot-id")
|
|
2560
|
+
|| Object.prototype.hasOwnProperty.call(flags, "default-bot-key")
|
|
2561
|
+
) {
|
|
2562
|
+
const selectedDefault = findTelegramEntryByFlags(parsed, defaultSelectorFlags, deps);
|
|
2563
|
+
if (!selectedDefault) {
|
|
2564
|
+
throw new Error("Telegram default bot selector was not found");
|
|
2565
|
+
}
|
|
2566
|
+
parsed.TELEGRAM_DEFAULT_BOT_KEY = selectedDefault.key;
|
|
2550
2567
|
}
|
|
2551
2568
|
const filePath = writeProviderEnvState("telegram", parsed, deps);
|
|
2552
2569
|
process.stdout.write(`Saved Telegram global settings to ${filePath}\n`);
|
|
@@ -2559,7 +2576,13 @@ async function editTelegramGlobalSettings(ui, flags, deps) {
|
|
|
2559
2576
|
{ value: "api", label: "API base URL", description: String(parsed.TELEGRAM_API_BASE_URL || "").trim() || "(empty)" },
|
|
2560
2577
|
{ value: "webhook", label: "Auto clear webhook", description: boolFromRaw(parsed.TELEGRAM_AUTO_CLEAR_WEBHOOK, true) ? "true" : "false" },
|
|
2561
2578
|
{ value: "updates", label: "Allowed updates", description: String(parsed.TELEGRAM_ALLOWED_UPDATES || "message,edited_message").trim() },
|
|
2562
|
-
{
|
|
2579
|
+
{
|
|
2580
|
+
value: "default",
|
|
2581
|
+
label: "Default Telegram bot",
|
|
2582
|
+
description: telegramEntryDisplayName(
|
|
2583
|
+
telegramEntriesForDisplay(parsed, deps).find((entry) => entry.isDefault) || {},
|
|
2584
|
+
) || "(empty)",
|
|
2585
|
+
},
|
|
2563
2586
|
],
|
|
2564
2587
|
{ defaultIndex: 0 },
|
|
2565
2588
|
);
|
|
@@ -2591,7 +2614,7 @@ async function editTelegramBot(ui, flags, deps) {
|
|
|
2591
2614
|
? findTelegramEntryByFlags(parsed, flags, deps)
|
|
2592
2615
|
: await chooseTelegramEntry(ui, parsed, deps, "Select Telegram bot entry", flags);
|
|
2593
2616
|
if (!selected) {
|
|
2594
|
-
throw new Error("Telegram bot selector is required for non-interactive edit");
|
|
2617
|
+
throw new Error("Telegram bot selector is required for non-interactive edit; pass --bot-name or --bot-id (legacy --bot-key is still supported)");
|
|
2595
2618
|
}
|
|
2596
2619
|
let current = { ...selected };
|
|
2597
2620
|
if (nonInteractive) {
|
|
@@ -2653,11 +2676,11 @@ async function removeTelegramBot(ui, flags, deps) {
|
|
|
2653
2676
|
const parsed = { ...state.parsed };
|
|
2654
2677
|
const selected = await chooseTelegramEntry(ui, parsed, deps, "Select Telegram bot entry to remove", flags);
|
|
2655
2678
|
if (!selected) return;
|
|
2656
|
-
if (!await promptConfirmChoice(ui, `Remove Telegram bot "${selected
|
|
2679
|
+
if (!await promptConfirmChoice(ui, `Remove Telegram bot "${telegramEntryDisplayName(selected)}"?`, {
|
|
2657
2680
|
confirmLabel: "Remove bot",
|
|
2658
|
-
confirmDescription: "delete this local Telegram bot
|
|
2681
|
+
confirmDescription: "delete this local Telegram bot file",
|
|
2659
2682
|
cancelLabel: "Cancel",
|
|
2660
|
-
cancelDescription: "keep the current local bot
|
|
2683
|
+
cancelDescription: "keep the current local Telegram bot file",
|
|
2661
2684
|
defaultValue: "cancel",
|
|
2662
2685
|
})) {
|
|
2663
2686
|
process.stdout.write("Cancelled.\n");
|
|
@@ -2669,7 +2692,7 @@ async function removeTelegramBot(ui, flags, deps) {
|
|
|
2669
2692
|
nextParsed.TELEGRAM_DEFAULT_BOT_KEY = remaining[0]?.key || "";
|
|
2670
2693
|
}
|
|
2671
2694
|
const filePath = writeProviderEnvState("telegram", nextParsed, deps);
|
|
2672
|
-
process.stdout.write(`Removed Telegram bot "${selected.key}" from ${filePath}\n`);
|
|
2695
|
+
process.stdout.write(`Removed Telegram bot file for "${String(selected.serverBotName || selected.username || selected.key).trim() || "telegram"}" from ${filePath}\n`);
|
|
2673
2696
|
}
|
|
2674
2697
|
|
|
2675
2698
|
async function verifyProviderEntry(ui, provider, flags, deps) {
|
|
@@ -2690,7 +2713,7 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
|
|
|
2690
2713
|
selectors = {
|
|
2691
2714
|
botKey: selected.key,
|
|
2692
2715
|
botID: selected.serverBotID,
|
|
2693
|
-
botName: selected.username,
|
|
2716
|
+
botName: selected.serverBotName || selected.username,
|
|
2694
2717
|
};
|
|
2695
2718
|
}
|
|
2696
2719
|
}
|
|
@@ -2840,7 +2863,6 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
|
|
|
2840
2863
|
`ai_model: ${envConfig.model || "-"}`,
|
|
2841
2864
|
`permission_mode: ${envConfig.permissionMode || "-"}`,
|
|
2842
2865
|
`reasoning_effort: ${envConfig.reasoningEffort || "-"}`,
|
|
2843
|
-
envConfig.botKey ? `advanced_local_selector: ${envConfig.botKey} (compatibility only)` : "",
|
|
2844
2866
|
]);
|
|
2845
2867
|
}
|
|
2846
2868
|
if (provider === "telegram" && serverBinding) {
|
|
@@ -3097,7 +3119,7 @@ async function runBotRemove(ui, flags, deps) {
|
|
|
3097
3119
|
const state = loadProviderEnvState("telegram", deps);
|
|
3098
3120
|
const selected = findTelegramEntryByFlags(state.parsed, flags, deps);
|
|
3099
3121
|
if (!selected) {
|
|
3100
|
-
throw new Error("Telegram bot selector is required for non-interactive remove");
|
|
3122
|
+
throw new Error("Telegram bot selector is required for non-interactive remove; pass --bot-name or --bot-id (legacy --bot-key is still supported)");
|
|
3101
3123
|
}
|
|
3102
3124
|
const nextParsed = removeTelegramEntry(state.parsed, selected.key);
|
|
3103
3125
|
if (String(state.parsed.TELEGRAM_DEFAULT_BOT_KEY || "").trim() === selected.key) {
|
|
@@ -3105,7 +3127,7 @@ async function runBotRemove(ui, flags, deps) {
|
|
|
3105
3127
|
nextParsed.TELEGRAM_DEFAULT_BOT_KEY = remaining[0]?.key || "";
|
|
3106
3128
|
}
|
|
3107
3129
|
const filePath = writeProviderEnvState("telegram", nextParsed, deps);
|
|
3108
|
-
process.stdout.write(`Removed Telegram bot "${selected.key}" from ${filePath}\n`);
|
|
3130
|
+
process.stdout.write(`Removed Telegram bot file for "${String(selected.serverBotName || selected.username || selected.key).trim() || "telegram"}" from ${filePath}\n`);
|
|
3109
3131
|
return;
|
|
3110
3132
|
}
|
|
3111
3133
|
await removeTelegramBot(ui, flags, deps);
|
|
@@ -3137,11 +3159,11 @@ async function runBotSetDefault(ui, flags, deps) {
|
|
|
3137
3159
|
? findTelegramEntryByFlags(parsed, flags, deps)
|
|
3138
3160
|
: await chooseTelegramEntry(ui, parsed, deps, "Select default Telegram bot", flags);
|
|
3139
3161
|
if (!selected) {
|
|
3140
|
-
throw new Error("Telegram bot selector is required for set-default");
|
|
3162
|
+
throw new Error("Telegram bot selector is required for set-default; pass --bot-name or --bot-id (legacy --bot-key is still supported)");
|
|
3141
3163
|
}
|
|
3142
|
-
if (!nonInteractive && !await promptConfirmChoice(ui, `Set "${selected
|
|
3164
|
+
if (!nonInteractive && !await promptConfirmChoice(ui, `Set "${telegramEntryDisplayName(selected)}" as the default Telegram bot?`, {
|
|
3143
3165
|
confirmLabel: "Set default bot",
|
|
3144
|
-
confirmDescription: "make this the default
|
|
3166
|
+
confirmDescription: "make this the default Telegram bot for local delivery and fallback selection",
|
|
3145
3167
|
cancelLabel: "Cancel",
|
|
3146
3168
|
cancelDescription: "leave the current default unchanged",
|
|
3147
3169
|
defaultValue: "confirm",
|
|
@@ -3151,7 +3173,7 @@ async function runBotSetDefault(ui, flags, deps) {
|
|
|
3151
3173
|
}
|
|
3152
3174
|
parsed.TELEGRAM_DEFAULT_BOT_KEY = selected.key;
|
|
3153
3175
|
const filePath = writeProviderEnvState("telegram", parsed, deps);
|
|
3154
|
-
process.stdout.write(`Set
|
|
3176
|
+
process.stdout.write(`Set default Telegram bot to "${telegramEntryDisplayName(selected)}" in ${filePath}\n`);
|
|
3155
3177
|
}
|
|
3156
3178
|
|
|
3157
3179
|
async function runBotMigrate(ui, flags, deps) {
|
|
@@ -3178,11 +3200,11 @@ async function runBotMigrate(ui, flags, deps) {
|
|
|
3178
3200
|
const botKey = normalizeBotKey(
|
|
3179
3201
|
nonInteractive
|
|
3180
3202
|
? String(flags["bot-key"] || defaultKeyHint).trim()
|
|
3181
|
-
: await promptRequiredLine(ui, "
|
|
3203
|
+
: await promptRequiredLine(ui, "Legacy local selector for migrated entry", defaultKeyHint),
|
|
3182
3204
|
defaultKeyHint,
|
|
3183
3205
|
);
|
|
3184
3206
|
if (existingKeys.has(botKey)) {
|
|
3185
|
-
throw new Error(`Telegram
|
|
3207
|
+
throw new Error(`Telegram legacy local selector "${botKey}" already exists`);
|
|
3186
3208
|
}
|
|
3187
3209
|
const nextParsed = upsertTelegramEntry(parsed, {
|
|
3188
3210
|
key: botKey,
|
|
@@ -3203,7 +3225,7 @@ async function runBotMigrate(ui, flags, deps) {
|
|
|
3203
3225
|
}
|
|
3204
3226
|
const filePath = writeProviderEnvState("telegram", nextParsed, deps);
|
|
3205
3227
|
process.stdout.write(
|
|
3206
|
-
`Migrated TELEGRAM_BOT_TOKEN to named entry "${botKey}" in ${filePath}${boolFromRaw(flags["keep-legacy-token"], false) ? " (legacy token preserved)" : ""}\n`,
|
|
3228
|
+
`Migrated TELEGRAM_BOT_TOKEN to named entry selector "${botKey}" in ${filePath}${boolFromRaw(flags["keep-legacy-token"], false) ? " (legacy token preserved)" : ""}\n`,
|
|
3207
3229
|
);
|
|
3208
3230
|
}
|
|
3209
3231
|
|
package/lib/doctor-checks.mjs
CHANGED
|
@@ -63,7 +63,7 @@ export async function runDoctorProjectDestinationChecks({
|
|
|
63
63
|
}
|
|
64
64
|
const tokenDetailParts = [`configured (${envConfig.filePath})`];
|
|
65
65
|
if (envConfig.botKey) {
|
|
66
|
-
tokenDetailParts.push(`
|
|
66
|
+
tokenDetailParts.push(`local_selector=${envConfig.botKey}`);
|
|
67
67
|
}
|
|
68
68
|
if (envConfig.botUsername) {
|
|
69
69
|
tokenDetailParts.push(`@${envConfig.botUsername}`);
|
|
@@ -95,7 +95,7 @@ function createMockServer(options = {}) {
|
|
|
95
95
|
: [
|
|
96
96
|
{
|
|
97
97
|
id: "11111111-2222-3333-4444-555555555555",
|
|
98
|
-
name: "
|
|
98
|
+
name: "ServerProtocolMonitorBot",
|
|
99
99
|
provider: "telegram",
|
|
100
100
|
bot_role: "monitor",
|
|
101
101
|
is_active: true,
|
|
@@ -105,8 +105,8 @@ function createMockServer(options = {}) {
|
|
|
105
105
|
ensureArray(options.telegramUsersByToken).length
|
|
106
106
|
? ensureArray(options.telegramUsersByToken)
|
|
107
107
|
: [
|
|
108
|
-
["selftest-main-token", "
|
|
109
|
-
["selftest-edited-token", "
|
|
108
|
+
["selftest-main-token", "ServerProtocolMonitorBot"],
|
|
109
|
+
["selftest-edited-token", "ServerProtocolMonitorBot"],
|
|
110
110
|
],
|
|
111
111
|
);
|
|
112
112
|
|
|
@@ -290,6 +290,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
290
290
|
const telegramApiBaseURL = `${baseURL}/telegram`;
|
|
291
291
|
const telegramBotEntriesDir = path.join(tempHome, ".metheus", "telegram-bots");
|
|
292
292
|
const telegramEnvPath = path.join(telegramBotEntriesDir, "global.env");
|
|
293
|
+
const botRunnerConfigPath = path.join(tempHome, ".metheus", "bot-runner.json");
|
|
293
294
|
const readTelegramGlobals = () => parseSimpleEnvText(fs.readFileSync(telegramEnvPath, "utf8"));
|
|
294
295
|
const readTelegramBotEntry = (selector) => {
|
|
295
296
|
const requested = String(selector || "").trim().toLowerCase();
|
|
@@ -309,6 +310,42 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
309
310
|
}
|
|
310
311
|
return parseSimpleEnvText(fs.readFileSync(filePath, "utf8"));
|
|
311
312
|
};
|
|
313
|
+
fs.mkdirSync(path.join(tempHome, ".metheus"), { recursive: true });
|
|
314
|
+
fs.writeFileSync(
|
|
315
|
+
botRunnerConfigPath,
|
|
316
|
+
`${JSON.stringify({
|
|
317
|
+
version: 2,
|
|
318
|
+
project_mappings: {},
|
|
319
|
+
role_profiles: {
|
|
320
|
+
monitor: {
|
|
321
|
+
client: "gpt",
|
|
322
|
+
model: "",
|
|
323
|
+
permission_mode: "read_only",
|
|
324
|
+
reasoning_effort: "low",
|
|
325
|
+
},
|
|
326
|
+
review: {
|
|
327
|
+
client: "claude",
|
|
328
|
+
model: "Sonnet 4.6r",
|
|
329
|
+
permission_mode: "danger_full_access",
|
|
330
|
+
reasoning_effort: "high",
|
|
331
|
+
},
|
|
332
|
+
worker: {
|
|
333
|
+
client: "gpt",
|
|
334
|
+
model: "gpt-5.4",
|
|
335
|
+
permission_mode: "danger_full_access",
|
|
336
|
+
reasoning_effort: "high",
|
|
337
|
+
},
|
|
338
|
+
approval: {
|
|
339
|
+
client: "claude",
|
|
340
|
+
model: "Sonnet 4.6r",
|
|
341
|
+
permission_mode: "danger_full_access",
|
|
342
|
+
reasoning_effort: "high",
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
routes: [],
|
|
346
|
+
}, null, 2)}\n`,
|
|
347
|
+
"utf8",
|
|
348
|
+
);
|
|
312
349
|
|
|
313
350
|
const setupResult = await runCLI({
|
|
314
351
|
cliPath,
|
|
@@ -359,29 +396,29 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
359
396
|
]),
|
|
360
397
|
},
|
|
361
398
|
});
|
|
362
|
-
const addState = readTelegramBotEntry("
|
|
399
|
+
const addState = readTelegramBotEntry("serverprotocolmonitorbot");
|
|
363
400
|
const addGlobals = readTelegramGlobals();
|
|
364
401
|
push(
|
|
365
402
|
"bot_add_guided_creates_named_telegram_entry",
|
|
366
|
-
String(addState.TELEGRAM_BOT_SERVER_NAME || "") === "
|
|
403
|
+
String(addState.TELEGRAM_BOT_SERVER_NAME || "") === "ServerProtocolMonitorBot"
|
|
367
404
|
&& String(addState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor"
|
|
368
405
|
&& String(addState.TELEGRAM_BOT_TOKEN || "") === "selftest-main-token"
|
|
369
406
|
&& String(addState.TELEGRAM_BOT_ROLE_PROFILE || "") === "monitor"
|
|
370
407
|
&& String(addState.TELEGRAM_BOT_AI_CLIENT || "") === "gpt"
|
|
371
408
|
&& String(addState.TELEGRAM_BOT_AI_PERMISSION_MODE || "") === "read_only"
|
|
372
409
|
&& String(addState.TELEGRAM_BOT_AI_REASONING_EFFORT || "") === "low"
|
|
373
|
-
&& String(addGlobals.TELEGRAM_DEFAULT_BOT_KEY || "") === "
|
|
410
|
+
&& String(addGlobals.TELEGRAM_DEFAULT_BOT_KEY || "") === "serverprotocolmonitorbot",
|
|
374
411
|
`default=${String(addGlobals.TELEGRAM_DEFAULT_BOT_KEY || "")} token=${String(addState.TELEGRAM_BOT_TOKEN || "")} server_name=${String(addState.TELEGRAM_BOT_SERVER_NAME || "")} roles=${String(addState.TELEGRAM_BOT_SERVER_ROLES || "")} role=${String(addState.TELEGRAM_BOT_ROLE_PROFILE || "")} client=${String(addState.TELEGRAM_BOT_AI_CLIENT || "")}`,
|
|
375
412
|
);
|
|
376
413
|
|
|
377
414
|
const groupedMock = await createMockServer({
|
|
378
415
|
serverBots: [
|
|
379
|
-
{ id: "977ef999-c40b-4cf6-a142-ade246f1b9cf", name: "
|
|
380
|
-
{ id: "d74b57de-a635-4bac-a20f-f8ada188cf97", name: "
|
|
381
|
-
{ id: "bbae9450-4236-487c-9a05-61dc4a626215", name: "
|
|
382
|
-
{ id: "353896c5-3b6b-422f-9eeb-5dc9354f77b3", name: "
|
|
416
|
+
{ id: "977ef999-c40b-4cf6-a142-ade246f1b9cf", name: "GroupedServerProtocolBot", provider: "telegram", bot_role: "approval", is_active: true },
|
|
417
|
+
{ id: "d74b57de-a635-4bac-a20f-f8ada188cf97", name: "GroupedServerProtocolBot", provider: "telegram", bot_role: "worker", is_active: true },
|
|
418
|
+
{ id: "bbae9450-4236-487c-9a05-61dc4a626215", name: "GroupedServerProtocolBot", provider: "telegram", bot_role: "review", is_active: true },
|
|
419
|
+
{ id: "353896c5-3b6b-422f-9eeb-5dc9354f77b3", name: "GroupedServerProtocolBot", provider: "telegram", bot_role: "monitor", is_active: true },
|
|
383
420
|
],
|
|
384
|
-
telegramUsersByToken: [["selftest-group-token", "
|
|
421
|
+
telegramUsersByToken: [["selftest-group-token", "GroupedServerProtocolBot"]],
|
|
385
422
|
}).listen();
|
|
386
423
|
try {
|
|
387
424
|
await runCLI({
|
|
@@ -410,11 +447,11 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
410
447
|
]),
|
|
411
448
|
},
|
|
412
449
|
});
|
|
413
|
-
const groupedState = readTelegramBotEntry("
|
|
450
|
+
const groupedState = readTelegramBotEntry("groupedserverprotocolbot");
|
|
414
451
|
push(
|
|
415
452
|
"bot_add_guided_autoresolves_server_bot_group_without_role_prompt",
|
|
416
453
|
String(groupedState.TELEGRAM_BOT_SERVER_BOT_ID || "") === ""
|
|
417
|
-
&& String(groupedState.TELEGRAM_BOT_SERVER_NAME || "") === "
|
|
454
|
+
&& String(groupedState.TELEGRAM_BOT_SERVER_NAME || "") === "GroupedServerProtocolBot"
|
|
418
455
|
&& String(groupedState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor,review,worker,approval"
|
|
419
456
|
&& String(groupedState.TELEGRAM_BOT_ROLE_PROFILE || "") === ""
|
|
420
457
|
&& String(groupedState.TELEGRAM_BOT_AI_CLIENT || "") === ""
|
|
@@ -433,13 +470,13 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
433
470
|
...env,
|
|
434
471
|
METHEUS_SCRIPTED_PROMPT_ANSWERS: JSON.stringify([
|
|
435
472
|
"1", // provider: telegram
|
|
436
|
-
"
|
|
473
|
+
"1", // bot entry: GroupedServerProtocolBot
|
|
437
474
|
"1", // keep token
|
|
438
475
|
"2", // grouped role settings: edit one role
|
|
439
476
|
"3", // select role to edit: worker
|
|
440
477
|
"2", // worker: edit settings
|
|
441
478
|
"3", // worker AI client: claude
|
|
442
|
-
"
|
|
479
|
+
"2", // worker AI model: Sonnet 4.6r
|
|
443
480
|
"4", // worker permission: danger_full_access
|
|
444
481
|
"4", // worker reasoning: high
|
|
445
482
|
"y", // edit another role
|
|
@@ -462,15 +499,16 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
462
499
|
);
|
|
463
500
|
const groupedRunnerConfigPath = path.join(tempHome, ".metheus", "bot-runner.json");
|
|
464
501
|
const groupedRunnerConfig = readJSON(fs.readFileSync(groupedRunnerConfigPath, "utf8"));
|
|
502
|
+
const groupedRoleProfiles = safeObject(groupedRunnerConfig.role_profiles || groupedRunnerConfig.roleProfiles);
|
|
465
503
|
push(
|
|
466
504
|
"bot_edit_grouped_server_roles_updates_role_profiles",
|
|
467
|
-
String(safeObject(safeObject(
|
|
468
|
-
&& String(safeObject(safeObject(
|
|
469
|
-
&& String(safeObject(safeObject(
|
|
470
|
-
&& String(safeObject(safeObject(
|
|
471
|
-
&& String(safeObject(safeObject(
|
|
472
|
-
&& String(safeObject(safeObject(
|
|
473
|
-
`worker=${JSON.stringify(safeObject(safeObject(
|
|
505
|
+
String(safeObject(safeObject(groupedRoleProfiles).worker).client || "") === "claude"
|
|
506
|
+
&& String(safeObject(safeObject(groupedRoleProfiles).worker).model || "") === "Sonnet 4.6r"
|
|
507
|
+
&& String(safeObject(safeObject(groupedRoleProfiles).worker).permission_mode || "") === "danger_full_access"
|
|
508
|
+
&& String(safeObject(safeObject(groupedRoleProfiles).worker).reasoning_effort || "") === "high"
|
|
509
|
+
&& String(safeObject(safeObject(groupedRoleProfiles).approval).client || "") === "gemini"
|
|
510
|
+
&& String(safeObject(safeObject(groupedRoleProfiles).approval).model || "") === "gemini-3.1-pro",
|
|
511
|
+
`worker=${JSON.stringify(safeObject(safeObject(groupedRoleProfiles).worker))} approval=${JSON.stringify(safeObject(safeObject(groupedRoleProfiles).approval))}`,
|
|
474
512
|
);
|
|
475
513
|
|
|
476
514
|
const groupedShowResult = await runCLI({
|
|
@@ -478,7 +516,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
478
516
|
args: [
|
|
479
517
|
"bot", "show",
|
|
480
518
|
"--provider", "telegram",
|
|
481
|
-
"--bot-key", "
|
|
519
|
+
"--bot-key", "groupedserverprotocolbot",
|
|
482
520
|
"--base-url", `http://127.0.0.1:${groupedMock.port}`,
|
|
483
521
|
"--json", "true",
|
|
484
522
|
],
|
|
@@ -512,7 +550,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
512
550
|
args: [
|
|
513
551
|
"bot", "show",
|
|
514
552
|
"--provider", "telegram",
|
|
515
|
-
"--bot-key", "
|
|
553
|
+
"--bot-key", "serverprotocolmonitorbot",
|
|
516
554
|
"--base-url", baseURL,
|
|
517
555
|
"--json", "true",
|
|
518
556
|
],
|
|
@@ -543,7 +581,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
543
581
|
args: [
|
|
544
582
|
"bot", "show",
|
|
545
583
|
"--provider", "telegram",
|
|
546
|
-
"--bot-key", "
|
|
584
|
+
"--bot-key", "serverprotocolmonitorbot",
|
|
547
585
|
"--base-url", baseURL,
|
|
548
586
|
"--json", "true",
|
|
549
587
|
],
|
|
@@ -552,7 +590,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
552
590
|
const showWithRoutesPayload = readJSON(showWithRoutesResult.stdout);
|
|
553
591
|
push(
|
|
554
592
|
"bot_show_returns_selected_telegram_entry",
|
|
555
|
-
safeObject(showPayload.entry).key === "
|
|
593
|
+
safeObject(showPayload.entry).key === "serverprotocolmonitorbot"
|
|
556
594
|
&& safeObject(showPayload.entry).client === "gpt"
|
|
557
595
|
&& safeObject(showPayload.serverBinding).mode === "single",
|
|
558
596
|
`key=${String(safeObject(showPayload.entry).key || "")} client=${String(safeObject(showPayload.entry).client || "")} mode=${String(safeObject(showPayload.serverBinding).mode || "")}`,
|
|
@@ -574,12 +612,12 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
574
612
|
...env,
|
|
575
613
|
METHEUS_SCRIPTED_PROMPT_ANSWERS: JSON.stringify([
|
|
576
614
|
"1", // provider: telegram
|
|
577
|
-
"
|
|
615
|
+
"2", // bot entry: @serverprotocolmonitorbot
|
|
578
616
|
"1", // keep token
|
|
579
617
|
"2", // change AI client
|
|
580
618
|
"4", // gemini
|
|
581
619
|
"2", // change AI model
|
|
582
|
-
"
|
|
620
|
+
"2", // gemini model: gemini-3.1-pro
|
|
583
621
|
"2", // change permission mode
|
|
584
622
|
"3", // workspace_write
|
|
585
623
|
"2", // change reasoning effort
|
|
@@ -594,7 +632,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
594
632
|
!String(guidedEditResult.stdout || "").includes("Telegram username (without @)"),
|
|
595
633
|
String(guidedEditResult.stdout || "").split(/\r?\n/).filter((line) => line.includes("Telegram username")).join(" | ") || "username prompt skipped",
|
|
596
634
|
);
|
|
597
|
-
const guidedState = readTelegramBotEntry("
|
|
635
|
+
const guidedState = readTelegramBotEntry("serverprotocolmonitorbot");
|
|
598
636
|
push(
|
|
599
637
|
"bot_edit_guided_prompts_update_ai_binding_fields",
|
|
600
638
|
String(guidedState.TELEGRAM_BOT_AI_CLIENT || "") === "gemini"
|
|
@@ -609,7 +647,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
609
647
|
args: [
|
|
610
648
|
"bot", "edit",
|
|
611
649
|
"--provider", "telegram",
|
|
612
|
-
"--bot-key", "
|
|
650
|
+
"--bot-key", "serverprotocolmonitorbot",
|
|
613
651
|
"--non-interactive", "true",
|
|
614
652
|
"--token", "selftest-edited-token",
|
|
615
653
|
"--client", "claude",
|
|
@@ -619,7 +657,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
619
657
|
],
|
|
620
658
|
env,
|
|
621
659
|
});
|
|
622
|
-
const editedState = readTelegramBotEntry("
|
|
660
|
+
const editedState = readTelegramBotEntry("serverprotocolmonitorbot");
|
|
623
661
|
push(
|
|
624
662
|
"bot_edit_updates_ai_binding_fields",
|
|
625
663
|
String(editedState.TELEGRAM_BOT_TOKEN || "") === "selftest-edited-token"
|
|
@@ -637,7 +675,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
637
675
|
...env,
|
|
638
676
|
METHEUS_SCRIPTED_PROMPT_ANSWERS: JSON.stringify([
|
|
639
677
|
"1", // provider: telegram
|
|
640
|
-
"
|
|
678
|
+
"2", // bot entry: @serverprotocolmonitorbot
|
|
641
679
|
"1", // confirm set default
|
|
642
680
|
]),
|
|
643
681
|
},
|
|
@@ -645,7 +683,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
645
683
|
const guidedDefaultState = readTelegramGlobals();
|
|
646
684
|
push(
|
|
647
685
|
"bot_set_default_guided_selects_entry",
|
|
648
|
-
String(guidedDefaultState.TELEGRAM_DEFAULT_BOT_KEY || "") === "
|
|
686
|
+
String(guidedDefaultState.TELEGRAM_DEFAULT_BOT_KEY || "") === "serverprotocolmonitorbot",
|
|
649
687
|
`default=${String(guidedDefaultState.TELEGRAM_DEFAULT_BOT_KEY || "")}`,
|
|
650
688
|
);
|
|
651
689
|
|
|
@@ -660,7 +698,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
660
698
|
...env,
|
|
661
699
|
METHEUS_SCRIPTED_PROMPT_ANSWERS: JSON.stringify([
|
|
662
700
|
"1", // provider: telegram
|
|
663
|
-
"
|
|
701
|
+
"2", // bot entry: @serverprotocolmonitorbot
|
|
664
702
|
"2", // output format: json
|
|
665
703
|
]),
|
|
666
704
|
},
|
|
@@ -680,7 +718,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
680
718
|
args: [
|
|
681
719
|
"bot", "set-default",
|
|
682
720
|
"--provider", "telegram",
|
|
683
|
-
"--bot-key", "
|
|
721
|
+
"--bot-key", "serverprotocolmonitorbot",
|
|
684
722
|
"--non-interactive", "true",
|
|
685
723
|
],
|
|
686
724
|
env,
|
|
@@ -688,7 +726,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
688
726
|
const defaultState = readTelegramGlobals();
|
|
689
727
|
push(
|
|
690
728
|
"bot_set_default_updates_default_bot_key",
|
|
691
|
-
String(defaultState.TELEGRAM_DEFAULT_BOT_KEY || "") === "
|
|
729
|
+
String(defaultState.TELEGRAM_DEFAULT_BOT_KEY || "") === "serverprotocolmonitorbot",
|
|
692
730
|
`default=${String(defaultState.TELEGRAM_DEFAULT_BOT_KEY || "")}`,
|
|
693
731
|
);
|
|
694
732
|
|
|
@@ -697,7 +735,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
697
735
|
args: [
|
|
698
736
|
"bot", "verify",
|
|
699
737
|
"--provider", "telegram",
|
|
700
|
-
"--bot-key", "
|
|
738
|
+
"--bot-key", "serverprotocolmonitorbot",
|
|
701
739
|
"--base-url", baseURL,
|
|
702
740
|
"--timeout-seconds", "5",
|
|
703
741
|
"--json", "true",
|
|
@@ -727,7 +765,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
727
765
|
args: [
|
|
728
766
|
"bot", "remove",
|
|
729
767
|
"--provider", "telegram",
|
|
730
|
-
"--bot-key", "
|
|
768
|
+
"--bot-key", "serverprotocolmonitorbot",
|
|
731
769
|
"--non-interactive", "true",
|
|
732
770
|
],
|
|
733
771
|
env,
|
|
@@ -745,7 +783,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
745
783
|
const telegramEntry = safeObject(listPayload[0]);
|
|
746
784
|
push(
|
|
747
785
|
"bot_remove_deletes_named_telegram_entry",
|
|
748
|
-
!ensureArray(telegramEntry.entries).some((entry) => String(safeObject(entry).key || "") === "
|
|
786
|
+
!ensureArray(telegramEntry.entries).some((entry) => String(safeObject(entry).key || "") === "serverprotocolmonitorbot"),
|
|
749
787
|
`entries=${String(ensureArray(telegramEntry.entries).length)}`,
|
|
750
788
|
);
|
|
751
789
|
|
|
@@ -767,11 +805,11 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
767
805
|
],
|
|
768
806
|
env,
|
|
769
807
|
});
|
|
770
|
-
const aliasAddState = readTelegramBotEntry("
|
|
808
|
+
const aliasAddState = readTelegramBotEntry("serverprotocolmonitorbot");
|
|
771
809
|
push(
|
|
772
810
|
"bot_add_accepts_ai_prefixed_option_aliases",
|
|
773
811
|
String(aliasAddState.TELEGRAM_BOT_SERVER_BOT_ID || "") === mock.bots[0].id
|
|
774
|
-
&& String(aliasAddState.TELEGRAM_BOT_SERVER_NAME || "") === "
|
|
812
|
+
&& String(aliasAddState.TELEGRAM_BOT_SERVER_NAME || "") === "ServerProtocolMonitorBot"
|
|
775
813
|
&& String(aliasAddState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor"
|
|
776
814
|
&& String(aliasAddState.TELEGRAM_BOT_AI_CLIENT || "") === "gpt"
|
|
777
815
|
&& String(aliasAddState.TELEGRAM_BOT_AI_MODEL || "") === "gpt-5.4"
|
|
@@ -792,7 +830,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
792
830
|
const guidedRemoveBeforePayload = ensureArray(readJSON(guidedRemoveBeforeList.stdout));
|
|
793
831
|
const guidedRemoveBeforeEntry = safeObject(guidedRemoveBeforePayload[0]);
|
|
794
832
|
const guidedRemoveEntries = ensureArray(guidedRemoveBeforeEntry.entries);
|
|
795
|
-
const explicitEntryIndex = guidedRemoveEntries.findIndex((entry) => String(safeObject(entry).key || "") === "
|
|
833
|
+
const explicitEntryIndex = guidedRemoveEntries.findIndex((entry) => String(safeObject(entry).key || "") === "serverprotocolmonitorbot");
|
|
796
834
|
|
|
797
835
|
await runCLI({
|
|
798
836
|
cliPath,
|
|
@@ -838,7 +876,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
838
876
|
"--provider", "telegram",
|
|
839
877
|
"--bot-key", "legacy_main",
|
|
840
878
|
"--bot-id", mock.bots[0].id,
|
|
841
|
-
"--bot-name", "
|
|
879
|
+
"--bot-name", "ServerProtocolMonitorBot",
|
|
842
880
|
"--role-profile", "monitor",
|
|
843
881
|
"--client", "codex",
|
|
844
882
|
"--permission-mode", "read_only",
|
|
@@ -186,9 +186,9 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
186
186
|
project_id: selftestProjectID,
|
|
187
187
|
provider: "telegram",
|
|
188
188
|
role: "monitor",
|
|
189
|
-
bot_name: "
|
|
189
|
+
bot_name: "ServerProtocolMonitorBot",
|
|
190
190
|
}),
|
|
191
|
-
{ name: "
|
|
191
|
+
{ name: "ServerProtocolMonitorBot", role: "review" },
|
|
192
192
|
normalizeBotRunnerConfigContents(
|
|
193
193
|
{
|
|
194
194
|
version: 2,
|
|
@@ -211,7 +211,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
211
211
|
},
|
|
212
212
|
},
|
|
213
213
|
bot_bindings: {
|
|
214
|
-
|
|
214
|
+
ServerProtocolMonitorBot: {
|
|
215
215
|
role_profile: "approval",
|
|
216
216
|
},
|
|
217
217
|
},
|
|
@@ -237,9 +237,9 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
237
237
|
project_id: selftestProjectID,
|
|
238
238
|
provider: "telegram",
|
|
239
239
|
role: "monitor",
|
|
240
|
-
bot_name: "
|
|
240
|
+
bot_name: "ServerProtocolMonitorBot",
|
|
241
241
|
}),
|
|
242
|
-
{ name: "
|
|
242
|
+
{ name: "ServerProtocolMonitorBot", role: "monitor" },
|
|
243
243
|
normalizeBotRunnerConfigContents(
|
|
244
244
|
{
|
|
245
245
|
version: 2,
|
|
@@ -257,7 +257,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
257
257
|
},
|
|
258
258
|
},
|
|
259
259
|
bot_bindings: {
|
|
260
|
-
|
|
260
|
+
ServerProtocolMonitorBot: {
|
|
261
261
|
role_profile: "monitor",
|
|
262
262
|
client: "claude",
|
|
263
263
|
reasoning_effort: "high",
|
|
@@ -435,7 +435,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
435
435
|
provider: "telegram",
|
|
436
436
|
role: "monitor",
|
|
437
437
|
role_profile: "monitor",
|
|
438
|
-
bot_name: "
|
|
438
|
+
bot_name: "ServerProtocolMonitorBot",
|
|
439
439
|
destination_label: "AI incubating CHAT ROOM",
|
|
440
440
|
archive_work_item_id: "304ce77a-7032-421c-aeda-bc54daf088dd",
|
|
441
441
|
},
|
|
@@ -451,7 +451,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
451
451
|
provider: "telegram",
|
|
452
452
|
role: "monitor",
|
|
453
453
|
"role-profile": "monitor",
|
|
454
|
-
"bot-name": "
|
|
454
|
+
"bot-name": "ServerProtocolMonitorBot",
|
|
455
455
|
"dry-run-delivery": true,
|
|
456
456
|
},
|
|
457
457
|
"once",
|
|
@@ -463,7 +463,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
463
463
|
&& resolvedRunnerRoute.name === "telegram-monitor"
|
|
464
464
|
&& resolvedRunnerRoute.destinationLabel === "AI incubating CHAT ROOM"
|
|
465
465
|
&& resolvedRunnerRoute.dryRunDelivery === true
|
|
466
|
-
&& runnerRouteKey(resolvedRunnerRoute) === "telegram-monitor::11111111-1111-1111-1111-111111111111::telegram::monitor::
|
|
466
|
+
&& runnerRouteKey(resolvedRunnerRoute) === "telegram-monitor::11111111-1111-1111-1111-111111111111::telegram::monitor::ServerProtocolMonitorBot::AI incubating CHAT ROOM",
|
|
467
467
|
`name=${resolvedRunnerRoute.name || "(none)"} destination=${resolvedRunnerRoute.destinationLabel || "(none)"} key=${runnerRouteKey(resolvedRunnerRoute)}`,
|
|
468
468
|
);
|
|
469
469
|
} catch (err) {
|
|
@@ -515,7 +515,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
515
515
|
provider: "telegram",
|
|
516
516
|
role: "monitor",
|
|
517
517
|
role_profile: "monitor",
|
|
518
|
-
bot_name: "
|
|
518
|
+
bot_name: "ServerProtocolMonitorBot",
|
|
519
519
|
destination_label: "AI incubating CHAT ROOM",
|
|
520
520
|
},
|
|
521
521
|
],
|
|
@@ -527,7 +527,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
527
527
|
`${JSON.stringify({
|
|
528
528
|
version: 1,
|
|
529
529
|
routes: {
|
|
530
|
-
"-::11111111-1111-1111-1111-111111111111::telegram::monitor::
|
|
530
|
+
"-::11111111-1111-1111-1111-111111111111::telegram::monitor::ServerProtocolMonitorBot::-": {
|
|
531
531
|
last_processed_comment_id: "comment-a",
|
|
532
532
|
last_processed_created_at: "2026-03-13T06:00:00.000Z",
|
|
533
533
|
last_source_message_id: 41,
|
|
@@ -543,7 +543,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
543
543
|
process.env.HOME = migrationHome;
|
|
544
544
|
process.env.USERPROFILE = migrationHome;
|
|
545
545
|
const migratedRunnerState = loadBotRunnerState();
|
|
546
|
-
const canonicalRunnerStateKey = "telegram-monitor::11111111-1111-1111-1111-111111111111::telegram::monitor::
|
|
546
|
+
const canonicalRunnerStateKey = "telegram-monitor::11111111-1111-1111-1111-111111111111::telegram::monitor::ServerProtocolMonitorBot::AI incubating CHAT ROOM";
|
|
547
547
|
const persistedRunnerState = tryJsonParse(
|
|
548
548
|
fs.readFileSync(path.join(migrationMetheusDir, "bot-runner-state.json"), "utf8"),
|
|
549
549
|
);
|
|
@@ -552,7 +552,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
552
552
|
migratedRunnerState.migrated === true
|
|
553
553
|
&& migratedRunnerState.migratedKeys.length === 1
|
|
554
554
|
&& Boolean(migratedRunnerState.routes[canonicalRunnerStateKey])
|
|
555
|
-
&& !migratedRunnerState.routes["-::11111111-1111-1111-1111-111111111111::telegram::monitor::
|
|
555
|
+
&& !migratedRunnerState.routes["-::11111111-1111-1111-1111-111111111111::telegram::monitor::ServerProtocolMonitorBot::-"]
|
|
556
556
|
&& Boolean(safeObject(persistedRunnerState.routes)[canonicalRunnerStateKey]),
|
|
557
557
|
`migrated=${String(migratedRunnerState.migrated)} key=${canonicalRunnerStateKey}`,
|
|
558
558
|
);
|
|
@@ -619,7 +619,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
619
619
|
},
|
|
620
620
|
},
|
|
621
621
|
mentionOnlyRoute,
|
|
622
|
-
{ name: "
|
|
622
|
+
{ name: "ServerProtocolMonitorBot", role: "monitor" },
|
|
623
623
|
);
|
|
624
624
|
push(
|
|
625
625
|
"telegram_trigger_mentions_only_skips_unmentioned_group_message",
|
|
@@ -634,13 +634,13 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
634
634
|
kind: "telegram_message",
|
|
635
635
|
chatID: "-100123",
|
|
636
636
|
chatType: "supergroup",
|
|
637
|
-
body: "hello @
|
|
637
|
+
body: "hello @ServerProtocolMonitorBot",
|
|
638
638
|
mentionUsernames: ["ryoai_bot"],
|
|
639
639
|
replyToSenderIsBot: false,
|
|
640
640
|
},
|
|
641
641
|
},
|
|
642
642
|
mentionOnlyRoute,
|
|
643
|
-
{ name: "
|
|
643
|
+
{ name: "ServerProtocolMonitorBot", role: "monitor" },
|
|
644
644
|
);
|
|
645
645
|
push(
|
|
646
646
|
"telegram_trigger_mentions_only_accepts_bot_mention",
|
|
@@ -650,7 +650,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
650
650
|
|
|
651
651
|
const botReplyArchiveComment = formatBotReplyArchiveComment({
|
|
652
652
|
provider: "telegram",
|
|
653
|
-
bot: { id: "bot-1", name: "
|
|
653
|
+
bot: { id: "bot-1", name: "ServerProtocolMonitorBot", role: "monitor" },
|
|
654
654
|
destination: { chatID: "-100123", label: "Main Room" },
|
|
655
655
|
replyText: "hello",
|
|
656
656
|
messageID: 4321,
|
|
@@ -234,7 +234,7 @@ export async function runSelftestTelegramE2E(push, deps) {
|
|
|
234
234
|
const e2eTelegramToken = "123456:test-token";
|
|
235
235
|
const e2eBot = {
|
|
236
236
|
id: "55555555-5555-4555-8555-555555555555",
|
|
237
|
-
name: "
|
|
237
|
+
name: "ServerProtocolMonitorBot",
|
|
238
238
|
role: "monitor",
|
|
239
239
|
};
|
|
240
240
|
const e2eDestination = {
|
|
@@ -356,7 +356,7 @@ export async function runSelftestTelegramE2E(push, deps) {
|
|
|
356
356
|
&& e2eResult.execution_mode === "role_profile"
|
|
357
357
|
&& e2eResult.role_profile === "monitor"
|
|
358
358
|
&& telegramE2EServer.state.sentMessages.length === 1
|
|
359
|
-
&& String(telegramE2EServer.state.sentMessages[0]?.text || "").trim() === "Acknowledged: hello @
|
|
359
|
+
&& String(telegramE2EServer.state.sentMessages[0]?.text || "").trim() === "Acknowledged: hello @ServerProtocolMonitorBot"
|
|
360
360
|
&& intFromRawAllowZero(telegramE2EServer.state.sentMessages[0]?.reply_to_message_id, 0) === 41
|
|
361
361
|
&& telegramE2EServer.state.chatActions.length >= 1
|
|
362
362
|
&& Boolean(mirroredReply)
|