metheus-governance-mcp-cli 0.2.82 → 0.2.84
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 +10 -1
- package/cli.mjs +2 -0
- package/lib/bot-commands.mjs +7 -7
- package/lib/local-ai-adapters.mjs +77 -3
- package/lib/selftest-bot-commands.mjs +24 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -233,6 +233,15 @@ Behavior:
|
|
|
233
233
|
- 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.
|
|
234
234
|
- `bot edit` without flags now uses the same sequential flow every time: provider -> bot entry -> username/token review -> grouped server-role review when needed -> AI field choices -> default choice -> save.
|
|
235
235
|
- when the CLI asks for `AI model`, it now shows client-specific model choices first and still allows manual entry when you need a custom model name.
|
|
236
|
+
- display labels are converted to tested execution model IDs at runtime:
|
|
237
|
+
- `gpt-5.4` -> `gpt-5.4`
|
|
238
|
+
- `gpt-5.3-codex` -> `gpt-5.3-codex`
|
|
239
|
+
- `gpt-5.3-codex-spark` -> `gpt-5.3-codex-spark`
|
|
240
|
+
- older uppercase GPT labels are still accepted as compatibility aliases
|
|
241
|
+
- `Sonnet 4.6r` -> `sonnet`
|
|
242
|
+
- `Haiku 4.5` -> `haiku`
|
|
243
|
+
- `Opus 4.6` -> `opus`
|
|
244
|
+
- `Gemini 3.1 Pro` -> `gemini-2.5-pro`
|
|
236
245
|
- if one server bot name maps to multiple server roles, `bot edit` keeps the Telegram env entry bound to the server identity and lets you review the local `role_profiles` for each detected role instead of forcing one role/profile UUID choice up front.
|
|
237
246
|
- In the normal Telegram edit path, the CLI keeps or re-resolves the server bot binding automatically. It no longer asks you to pick `approval / worker / review / monitor` or a server bot UUID first.
|
|
238
247
|
- `bot set-default` without flags starts a guided numbered flow: provider -> bot entry -> confirm default change.
|
|
@@ -259,7 +268,7 @@ Non-interactive examples:
|
|
|
259
268
|
```bash
|
|
260
269
|
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
|
|
261
270
|
metheus-governance-mcp-cli bot add --provider telegram --non-interactive true --server-bot-id <server_bot_uuid> --token <telegram_bot_token> --default true
|
|
262
|
-
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 "
|
|
271
|
+
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
|
|
263
272
|
metheus-governance-mcp-cli bot edit --provider telegram --bot-key ryoai_bot --non-interactive true --ai-client claude --ai-model "Sonnet 4.6r" --ai-permission-mode danger_full_access --ai-reasoning-effort high
|
|
264
273
|
metheus-governance-mcp-cli bot set-default --provider telegram --bot-key main --non-interactive true
|
|
265
274
|
metheus-governance-mcp-cli bot migrate --provider telegram --bot-key main --server-bot-id <server_bot_uuid> --bot-name <telegram_username> --role-profile monitor --ai-client codex --ai-permission-mode read_only --ai-reasoning-effort low --non-interactive true
|
package/cli.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import http from "node:http";
|
|
|
10
10
|
import https from "node:https";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_LOCAL_AI_CLIENT,
|
|
13
|
+
resolveLocalAIExecutionModel,
|
|
13
14
|
SUPPORTED_LOCAL_AI_CLIENTS,
|
|
14
15
|
normalizeLocalAIClientName,
|
|
15
16
|
normalizeLocalAIPermissionMode,
|
|
@@ -5207,6 +5208,7 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
|
|
|
5207
5208
|
await runSelftestBotCommands(push, {
|
|
5208
5209
|
cliPath: fileURLToPath(import.meta.url),
|
|
5209
5210
|
parseSimpleEnvText,
|
|
5211
|
+
resolveLocalAIExecutionModel,
|
|
5210
5212
|
});
|
|
5211
5213
|
|
|
5212
5214
|
const payload = buildSelftestPayload(checks);
|
package/lib/bot-commands.mjs
CHANGED
|
@@ -1462,21 +1462,21 @@ function suggestedAIModelsForClient(clientName) {
|
|
|
1462
1462
|
const normalizedClient = String(clientName || "").trim().toLowerCase();
|
|
1463
1463
|
if (normalizedClient === "codex") {
|
|
1464
1464
|
return [
|
|
1465
|
-
{ value: "
|
|
1466
|
-
{ value: "
|
|
1467
|
-
{ value: "
|
|
1465
|
+
{ value: "gpt-5.4", label: "gpt-5.4", description: "recommended GPT model" },
|
|
1466
|
+
{ value: "gpt-5.3-codex", label: "gpt-5.3-codex", description: "stable GPT codex model" },
|
|
1467
|
+
{ value: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark", description: "faster GPT codex model" },
|
|
1468
1468
|
];
|
|
1469
1469
|
}
|
|
1470
1470
|
if (normalizedClient === "claude") {
|
|
1471
1471
|
return [
|
|
1472
|
-
{ value: "Sonnet 4.6r", label: "Sonnet 4.6r", description: "
|
|
1473
|
-
{ value: "Haiku 4.5", label: "Haiku 4.5", description: "
|
|
1474
|
-
{ value: "Opus 4.6", label: "Opus 4.6", description: "
|
|
1472
|
+
{ value: "Sonnet 4.6r", label: "Sonnet 4.6r", description: "display label; runs as sonnet" },
|
|
1473
|
+
{ value: "Haiku 4.5", label: "Haiku 4.5", description: "display label; runs as haiku" },
|
|
1474
|
+
{ value: "Opus 4.6", label: "Opus 4.6", description: "display label; runs as opus" },
|
|
1475
1475
|
];
|
|
1476
1476
|
}
|
|
1477
1477
|
if (normalizedClient === "gemini") {
|
|
1478
1478
|
return [
|
|
1479
|
-
{ value: "Gemini 3.1 Pro", label: "Gemini 3.1 Pro", description: "
|
|
1479
|
+
{ value: "Gemini 3.1 Pro", label: "Gemini 3.1 Pro", description: "display label; runs as gemini-2.5-pro" },
|
|
1480
1480
|
];
|
|
1481
1481
|
}
|
|
1482
1482
|
if (normalizedClient === "sample") {
|
|
@@ -8,6 +8,50 @@ export const DEFAULT_LOCAL_AI_CLIENT = "codex";
|
|
|
8
8
|
|
|
9
9
|
const SUPPORTED_PERMISSION_MODES = ["read_only", "workspace_write", "danger_full_access"];
|
|
10
10
|
const SUPPORTED_REASONING_EFFORTS = ["low", "medium", "high"];
|
|
11
|
+
const LOCAL_AI_MODEL_MAPPINGS = {
|
|
12
|
+
codex: [
|
|
13
|
+
{
|
|
14
|
+
display: "gpt-5.4",
|
|
15
|
+
execution: "gpt-5.4",
|
|
16
|
+
aliases: ["gpt-5.4", "gpt 5.4", "GPT-5.4"],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
display: "gpt-5.3-codex",
|
|
20
|
+
execution: "gpt-5.3-codex",
|
|
21
|
+
aliases: ["gpt-5.3-codex", "gpt 5.3 codex", "GPT-5.3-CODEX"],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
display: "gpt-5.3-codex-spark",
|
|
25
|
+
execution: "gpt-5.3-codex-spark",
|
|
26
|
+
aliases: ["gpt-5.3-codex-spark", "gpt 5.3 codex spark", "GPT-5.3-CODEX-Spark"],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
claude: [
|
|
30
|
+
{
|
|
31
|
+
display: "Sonnet 4.6r",
|
|
32
|
+
execution: "sonnet",
|
|
33
|
+
aliases: ["sonnet 4.6r", "claude-sonnet-4", "claude-3.7-sonnet", "sonnet"],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
display: "Haiku 4.5",
|
|
37
|
+
execution: "haiku",
|
|
38
|
+
aliases: ["haiku 4.5", "haiku"],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
display: "Opus 4.6",
|
|
42
|
+
execution: "opus",
|
|
43
|
+
aliases: ["opus 4.6", "opus"],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
gemini: [
|
|
47
|
+
{
|
|
48
|
+
display: "Gemini 3.1 Pro",
|
|
49
|
+
execution: "gemini-2.5-pro",
|
|
50
|
+
aliases: ["gemini 3.1 pro", "gemini-3.1-pro", "gemini-2.5-pro", "gemini 2.5 pro"],
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
sample: [],
|
|
54
|
+
};
|
|
11
55
|
|
|
12
56
|
function tryJsonParse(text) {
|
|
13
57
|
try {
|
|
@@ -25,6 +69,10 @@ function firstNonEmptyString(values) {
|
|
|
25
69
|
return "";
|
|
26
70
|
}
|
|
27
71
|
|
|
72
|
+
function ensureArray(value) {
|
|
73
|
+
return Array.isArray(value) ? value : [];
|
|
74
|
+
}
|
|
75
|
+
|
|
28
76
|
function intFromRawAllowZero(rawValue, fallback = 0) {
|
|
29
77
|
const parsed = Number.parseInt(String(rawValue ?? "").trim(), 10);
|
|
30
78
|
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
@@ -176,6 +224,30 @@ function normalizeCliOutput(rawText) {
|
|
|
176
224
|
};
|
|
177
225
|
}
|
|
178
226
|
|
|
227
|
+
function normalizeModelAliasText(rawValue) {
|
|
228
|
+
return String(rawValue || "")
|
|
229
|
+
.trim()
|
|
230
|
+
.toLowerCase()
|
|
231
|
+
.replace(/[_\s]+/g, "-");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function localAIModelMappingsForClient(clientName) {
|
|
235
|
+
const normalizedClient = normalizeLocalAIClientName(clientName, "");
|
|
236
|
+
return Array.isArray(LOCAL_AI_MODEL_MAPPINGS[normalizedClient]) ? LOCAL_AI_MODEL_MAPPINGS[normalizedClient] : [];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function resolveLocalAIExecutionModel(clientName, rawModelValue = "") {
|
|
240
|
+
const modelValue = String(rawModelValue || "").trim();
|
|
241
|
+
if (!modelValue) return "";
|
|
242
|
+
const normalizedModel = normalizeModelAliasText(modelValue);
|
|
243
|
+
const match = localAIModelMappingsForClient(clientName).find((item) => (
|
|
244
|
+
normalizeModelAliasText(item.display) === normalizedModel
|
|
245
|
+
|| normalizeModelAliasText(item.execution) === normalizedModel
|
|
246
|
+
|| ensureArray(item.aliases).some((alias) => normalizeModelAliasText(alias) === normalizedModel)
|
|
247
|
+
));
|
|
248
|
+
return match ? String(match.execution || "").trim() : modelValue;
|
|
249
|
+
}
|
|
250
|
+
|
|
179
251
|
function buildCodexArgs({ workspaceDir, model, permissionMode, reasoningEffort, outputPath }) {
|
|
180
252
|
const args = ["exec"];
|
|
181
253
|
if (model) {
|
|
@@ -487,6 +559,7 @@ export function runLocalAIClient({
|
|
|
487
559
|
const normalizedClient = normalizeLocalAIClientName(client);
|
|
488
560
|
const normalizedPermissionMode = normalizeLocalAIPermissionMode(permissionMode);
|
|
489
561
|
const normalizedReasoningEffort = normalizeLocalAIReasoningEffort(reasoningEffort);
|
|
562
|
+
const resolvedExecutionModel = resolveLocalAIExecutionModel(normalizedClient, model);
|
|
490
563
|
const resolvedWorkspaceDir = ensureWorkspaceDir(workspaceDir);
|
|
491
564
|
const promptText = buildLocalBotPrompt(inputPayload);
|
|
492
565
|
if (normalizedClient === "sample") {
|
|
@@ -497,6 +570,7 @@ export function runLocalAIClient({
|
|
|
497
570
|
...env,
|
|
498
571
|
METHEUS_AI_RUNNER_CLIENT: normalizedClient,
|
|
499
572
|
METHEUS_AI_RUNNER_MODEL: String(model || "").trim(),
|
|
573
|
+
METHEUS_AI_RUNNER_EXECUTION_MODEL: resolvedExecutionModel,
|
|
500
574
|
METHEUS_AI_RUNNER_PERMISSION_MODE: normalizedPermissionMode,
|
|
501
575
|
METHEUS_AI_RUNNER_REASONING_EFFORT: normalizedReasoningEffort,
|
|
502
576
|
METHEUS_RUNNER_WORKSPACE_DIR: resolvedWorkspaceDir,
|
|
@@ -505,7 +579,7 @@ export function runLocalAIClient({
|
|
|
505
579
|
return runCodexAdapter({
|
|
506
580
|
promptText,
|
|
507
581
|
workspaceDir: resolvedWorkspaceDir,
|
|
508
|
-
model:
|
|
582
|
+
model: resolvedExecutionModel,
|
|
509
583
|
permissionMode: normalizedPermissionMode,
|
|
510
584
|
reasoningEffort: normalizedReasoningEffort,
|
|
511
585
|
env: nextEnv,
|
|
@@ -515,7 +589,7 @@ export function runLocalAIClient({
|
|
|
515
589
|
return runClaudeAdapter({
|
|
516
590
|
promptText,
|
|
517
591
|
workspaceDir: resolvedWorkspaceDir,
|
|
518
|
-
model:
|
|
592
|
+
model: resolvedExecutionModel,
|
|
519
593
|
permissionMode: normalizedPermissionMode,
|
|
520
594
|
reasoningEffort: normalizedReasoningEffort,
|
|
521
595
|
env: nextEnv,
|
|
@@ -525,7 +599,7 @@ export function runLocalAIClient({
|
|
|
525
599
|
return runGeminiAdapter({
|
|
526
600
|
promptText,
|
|
527
601
|
workspaceDir: resolvedWorkspaceDir,
|
|
528
|
-
model:
|
|
602
|
+
model: resolvedExecutionModel,
|
|
529
603
|
permissionMode: normalizedPermissionMode,
|
|
530
604
|
env: nextEnv,
|
|
531
605
|
});
|
|
@@ -228,9 +228,31 @@ function runCLI({ cliPath, args, env, input = "" }) {
|
|
|
228
228
|
export async function runSelftestBotCommands(push, deps) {
|
|
229
229
|
const cliPath = String(requireDependency(deps, "cliPath") || "").trim();
|
|
230
230
|
const parseSimpleEnvText = requireDependency(deps, "parseSimpleEnvText");
|
|
231
|
+
const resolveLocalAIExecutionModel = requireDependency(deps, "resolveLocalAIExecutionModel");
|
|
231
232
|
let tempHome = "";
|
|
232
233
|
let mock = null;
|
|
233
234
|
try {
|
|
235
|
+
push(
|
|
236
|
+
"display_model_labels_map_to_tested_execution_ids",
|
|
237
|
+
resolveLocalAIExecutionModel("codex", "gpt-5.4") === "gpt-5.4"
|
|
238
|
+
&& resolveLocalAIExecutionModel("codex", "gpt-5.3-codex") === "gpt-5.3-codex"
|
|
239
|
+
&& resolveLocalAIExecutionModel("codex", "gpt-5.3-codex-spark") === "gpt-5.3-codex-spark"
|
|
240
|
+
&& resolveLocalAIExecutionModel("codex", "GPT-5.4") === "gpt-5.4"
|
|
241
|
+
&& resolveLocalAIExecutionModel("codex", "GPT-5.3-CODEX") === "gpt-5.3-codex"
|
|
242
|
+
&& resolveLocalAIExecutionModel("codex", "GPT-5.3-CODEX-Spark") === "gpt-5.3-codex-spark"
|
|
243
|
+
&& resolveLocalAIExecutionModel("claude", "Sonnet 4.6r") === "sonnet"
|
|
244
|
+
&& resolveLocalAIExecutionModel("claude", "Haiku 4.5") === "haiku"
|
|
245
|
+
&& resolveLocalAIExecutionModel("claude", "Opus 4.6") === "opus"
|
|
246
|
+
&& resolveLocalAIExecutionModel("gemini", "Gemini 3.1 Pro") === "gemini-2.5-pro",
|
|
247
|
+
[
|
|
248
|
+
`gpt54=${resolveLocalAIExecutionModel("codex", "gpt-5.4")}`,
|
|
249
|
+
`gpt53codex=${resolveLocalAIExecutionModel("codex", "gpt-5.3-codex")}`,
|
|
250
|
+
`spark=${resolveLocalAIExecutionModel("codex", "gpt-5.3-codex-spark")}`,
|
|
251
|
+
`claude=${resolveLocalAIExecutionModel("claude", "Sonnet 4.6r")}`,
|
|
252
|
+
`gemini=${resolveLocalAIExecutionModel("gemini", "Gemini 3.1 Pro")}`,
|
|
253
|
+
].join(" "),
|
|
254
|
+
);
|
|
255
|
+
|
|
234
256
|
tempHome = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-bot-selftest-"));
|
|
235
257
|
mock = await createMockServer().listen();
|
|
236
258
|
const env = buildSpawnEnv(tempHome);
|
|
@@ -684,7 +706,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
684
706
|
"--server-bot-id", mock.bots[0].id,
|
|
685
707
|
"--token", "selftest-main-token",
|
|
686
708
|
"--ai-client", "gpt",
|
|
687
|
-
"--ai-model", "
|
|
709
|
+
"--ai-model", "gpt-5.4",
|
|
688
710
|
"--ai-permission-mode", "read_only",
|
|
689
711
|
"--ai-reasoning-effort", "low",
|
|
690
712
|
"--verify", "true",
|
|
@@ -697,7 +719,7 @@ export async function runSelftestBotCommands(push, deps) {
|
|
|
697
719
|
String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_SERVER_BOT_ID || "") === mock.bots[0].id
|
|
698
720
|
&& String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_USERNAME || "") === ""
|
|
699
721
|
&& String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_CLIENT || "") === "codex"
|
|
700
|
-
&& String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_MODEL || "") === "
|
|
722
|
+
&& String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_MODEL || "") === "gpt-5.4"
|
|
701
723
|
&& String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_PERMISSION_MODE || "") === "read_only"
|
|
702
724
|
&& String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_REASONING_EFFORT || "") === "low",
|
|
703
725
|
`client=${String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_CLIENT || "")} model=${String(aliasAddState.TELEGRAM_BOT_MONITORSELFTESTBOT_AI_MODEL || "")}`,
|