@iola_adm/iola-cli 0.1.35 → 0.1.37
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/package.json +1 -1
- package/src/cli.js +146 -98
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -264,18 +264,84 @@ const DATASETS = {
|
|
|
264
264
|
endpoint: "kindergartens",
|
|
265
265
|
},
|
|
266
266
|
};
|
|
267
|
+
const SLASH_COMMANDS = [
|
|
268
|
+
{ command: "/help", description: "список slash-команд" },
|
|
269
|
+
{ command: "/health", description: "проверка публичного API/MCP" },
|
|
270
|
+
{ command: "/doctor", description: "диагностика CLI" },
|
|
271
|
+
{ command: "/wizard", description: "мастер настройки" },
|
|
272
|
+
{ command: "/db status", description: "статус локальной SQLite-БД" },
|
|
273
|
+
{ command: "/sessions", description: "AI-сессии" },
|
|
274
|
+
{ command: "/resume SESSION_ID", description: "продолжить сессию" },
|
|
275
|
+
{ command: "/features list", description: "feature flags" },
|
|
276
|
+
{ command: "/gosuslugi status", description: "личное подключение Госуслуг" },
|
|
277
|
+
{ command: "/wiki", description: "ссылки на документацию" },
|
|
278
|
+
{ command: "/context list", description: "локальный контекст проекта" },
|
|
279
|
+
{ command: "/skills list", description: "skills" },
|
|
280
|
+
{ command: "/permissions", description: "разрешения" },
|
|
281
|
+
{ command: "/tools", description: "tools и toolsets" },
|
|
282
|
+
{ command: "/files status", description: "локальные файловые операции" },
|
|
283
|
+
{ command: "/archive doctor", description: "архиватор" },
|
|
284
|
+
{ command: "/changes list", description: "подготовленные изменения" },
|
|
285
|
+
{ command: "/index status", description: "индекс документов" },
|
|
286
|
+
{ command: "/reports list", description: "пакеты отчетов" },
|
|
287
|
+
{ command: "/plugins list", description: "plugins" },
|
|
288
|
+
{ command: "/workspace status", description: "workspace" },
|
|
289
|
+
{ command: "/tasks list", description: "задачи" },
|
|
290
|
+
{ command: "/artifacts list", description: "artifacts" },
|
|
291
|
+
{ command: "/trace last", description: "последние tools trace" },
|
|
292
|
+
{ command: "/policy use safe", description: "переключить policy" },
|
|
293
|
+
{ command: "/cron list", description: "cron-задачи" },
|
|
294
|
+
{ command: "/daemon status", description: "локальный daemon" },
|
|
295
|
+
{ command: "/rpc call status", description: "RPC status" },
|
|
296
|
+
{ command: "/memory show", description: "память агента" },
|
|
297
|
+
{ command: "/hooks list", description: "hooks" },
|
|
298
|
+
{ command: "/agents list", description: "agents" },
|
|
299
|
+
{ command: "/mcp status", description: "MCP" },
|
|
300
|
+
{ command: "/cache status", description: "cache" },
|
|
301
|
+
{ command: "/sync", description: "обновить локальные данные" },
|
|
302
|
+
{ command: "/diff", description: "изменения данных" },
|
|
303
|
+
{ command: "/card школа 29", description: "карточка объекта" },
|
|
304
|
+
{ command: "/quality", description: "качество данных" },
|
|
305
|
+
{ command: "/views", description: "saved views" },
|
|
306
|
+
{ command: "/config get", description: "конфигурация" },
|
|
307
|
+
{ command: "/layers", description: "слои данных" },
|
|
308
|
+
{ command: "/data schools --limit 10", description: "данные слоя" },
|
|
309
|
+
{ command: "/schools --limit 10", description: "школы" },
|
|
310
|
+
{ command: "/kindergartens --search 29", description: "детские сады" },
|
|
311
|
+
{ command: "/search лицей --limit 3", description: "поиск" },
|
|
312
|
+
{ command: "/mcp-info", description: "публичный MCP" },
|
|
313
|
+
{ command: "/profiles", description: "AI-профили" },
|
|
314
|
+
{ command: "/models openrouter --search qwen", description: "модели" },
|
|
315
|
+
{ command: "/ai doctor", description: "AI diagnostics" },
|
|
316
|
+
{ command: "/ai setup ollama", description: "настройка Ollama" },
|
|
317
|
+
{ command: "/use openai", description: "выбрать OpenAI" },
|
|
318
|
+
{ command: "/use ollama", description: "выбрать Ollama" },
|
|
319
|
+
{ command: "/key status", description: "API-ключи" },
|
|
320
|
+
{ command: "/history", description: "история текущей сессии" },
|
|
321
|
+
{ command: "/new", description: "новая agent-сессия" },
|
|
322
|
+
{ command: "/retry", description: "повторить последний вопрос" },
|
|
323
|
+
{ command: "/undo", description: "удалить последний обмен" },
|
|
324
|
+
{ command: "/compact", description: "сжать контекст" },
|
|
325
|
+
{ command: "/usage", description: "использование контекста" },
|
|
326
|
+
{ command: "/clear", description: "очистить историю agent-сессии" },
|
|
327
|
+
{ command: "/banner", description: "показать баннер" },
|
|
328
|
+
{ command: "/update", description: "проверить обновления" },
|
|
329
|
+
{ command: "/init", description: "проверить окружение" },
|
|
330
|
+
{ command: "/exit", description: "выйти" },
|
|
331
|
+
];
|
|
267
332
|
const BANNER = `\x1b[38;5;45m┌────────────────────────────────────────────────────────────────────────────┐
|
|
268
|
-
│\x1b[38;5;51m ____ _ ___ ____ ____ ___ _____ _ _______ \x1b[38;5;45m│
|
|
269
|
-
│\x1b[38;5;51m / ___| | |_ _| | _ \\| _ \\ / _ \\| ____| |/ /_ _| \x1b[38;5;45m│
|
|
270
|
-
│\x1b[38;5;51m | | | | | |_____| |_) | |_) | | | | _| | ' / | | \x1b[38;5;45m│
|
|
271
|
-
│\x1b[38;5;51m | |___| |___ | |_____| __/| _ <| |_| | |___| . \\ | | \x1b[38;5;45m│
|
|
272
|
-
│\x1b[38;5;51m \\____|_____|___| |_| |_| \\_\\\\___/|_____|_|\\_\\ |_| \x1b[38;5;45m│
|
|
273
333
|
│ │
|
|
274
|
-
│\x1b[38;5;
|
|
334
|
+
│\x1b[38;5;51m ____ _ ___ __ ______ ____ _ _ _ __ _ ____ \x1b[38;5;45m│
|
|
335
|
+
│\x1b[38;5;51m / ___| | |_ _| \\ \\ / / ___|| _ \\| | | | |/ / / \\ | _ \\ \x1b[38;5;45m│
|
|
336
|
+
│\x1b[38;5;51m | | | | | | _____ \\ V /\\___ \\| | | | |_| | ' / / _ \\ | |_) | \x1b[38;5;45m│
|
|
337
|
+
│\x1b[38;5;51m | |___| |___ | | |_____| | | ___) | |_| | _ | . \\ / ___ \\| _ < \x1b[38;5;45m│
|
|
338
|
+
│\x1b[38;5;51m \\____|_____|___| |_| |____/|____/|_| |_|_|\\_\\/_/ \\_\\_| \\_\\ \x1b[38;5;45m│
|
|
339
|
+
│ │
|
|
340
|
+
│\x1b[38;5;213m CLI-ЙОШКАР-ОЛА \x1b[38;5;45m│
|
|
275
341
|
│ │
|
|
276
342
|
│\x1b[38;5;250m открытые данные • MCP • локальный AI \x1b[38;5;45m│
|
|
277
343
|
│ │
|
|
278
|
-
│\x1b[38;5;82m
|
|
344
|
+
│\x1b[38;5;82m VERSION_LINE \x1b[38;5;45m│
|
|
279
345
|
└────────────────────────────────────────────────────────────────────────────┘\x1b[0m`;
|
|
280
346
|
|
|
281
347
|
const COMMANDS = new Map([
|
|
@@ -405,7 +471,7 @@ export async function main(argv) {
|
|
|
405
471
|
}
|
|
406
472
|
|
|
407
473
|
async function showHelp() {
|
|
408
|
-
showBanner();
|
|
474
|
+
await showBanner();
|
|
409
475
|
console.log(`iola - CLI и AI-агент городского округа "Город Йошкар-Ола"
|
|
410
476
|
|
|
411
477
|
Запуск:
|
|
@@ -434,7 +500,7 @@ Requirements:
|
|
|
434
500
|
}
|
|
435
501
|
|
|
436
502
|
async function showCommands() {
|
|
437
|
-
showBanner();
|
|
503
|
+
await showBanner();
|
|
438
504
|
console.log(`iola - CLI для открытых данных городского округа "Город Йошкар-Ола"
|
|
439
505
|
|
|
440
506
|
Usage:
|
|
@@ -554,7 +620,7 @@ async function runDefaultCli() {
|
|
|
554
620
|
|
|
555
621
|
initDatabase();
|
|
556
622
|
if (!isFirstRunCompleted()) {
|
|
557
|
-
showBanner();
|
|
623
|
+
await showBanner();
|
|
558
624
|
console.log("Первый запуск iola-cli. Сейчас откроется мастер настройки.");
|
|
559
625
|
console.log("После мастера запустится интерактивный агент.");
|
|
560
626
|
console.log("");
|
|
@@ -567,7 +633,7 @@ async function runDefaultCli() {
|
|
|
567
633
|
}
|
|
568
634
|
|
|
569
635
|
async function startAgent() {
|
|
570
|
-
showBanner();
|
|
636
|
+
await showBanner();
|
|
571
637
|
console.log("Интерактивный режим. Введите /help для списка команд, /exit для выхода.");
|
|
572
638
|
await runHooks("SessionStart", { mode: "agent" });
|
|
573
639
|
|
|
@@ -615,9 +681,19 @@ async function handleAgentLine(line, state) {
|
|
|
615
681
|
return false;
|
|
616
682
|
}
|
|
617
683
|
|
|
684
|
+
if (line === "/") {
|
|
685
|
+
printSlashMenu("");
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
|
|
618
689
|
const [command, ...args] = splitCommandLine(line.slice(1));
|
|
619
690
|
state.lastCommand = { command, args };
|
|
620
691
|
|
|
692
|
+
if (!command) {
|
|
693
|
+
printSlashMenu("");
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
|
|
621
697
|
if (command === "exit" || command === "quit") {
|
|
622
698
|
return true;
|
|
623
699
|
}
|
|
@@ -897,7 +973,7 @@ async function handleAgentLine(line, state) {
|
|
|
897
973
|
}
|
|
898
974
|
|
|
899
975
|
if (command === "banner") {
|
|
900
|
-
showBanner();
|
|
976
|
+
await showBanner();
|
|
901
977
|
return false;
|
|
902
978
|
}
|
|
903
979
|
|
|
@@ -967,8 +1043,13 @@ async function handleAgentLine(line, state) {
|
|
|
967
1043
|
}[command];
|
|
968
1044
|
|
|
969
1045
|
if (!mapped) {
|
|
970
|
-
|
|
971
|
-
|
|
1046
|
+
const matches = getSlashCommandMatches(command);
|
|
1047
|
+
if (matches.length > 0) {
|
|
1048
|
+
printSlashMenu(command);
|
|
1049
|
+
} else {
|
|
1050
|
+
console.log(`Неизвестная slash-команда: /${command}`);
|
|
1051
|
+
printSlashMenu(command);
|
|
1052
|
+
}
|
|
972
1053
|
return false;
|
|
973
1054
|
}
|
|
974
1055
|
|
|
@@ -978,83 +1059,33 @@ async function handleAgentLine(line, state) {
|
|
|
978
1059
|
}
|
|
979
1060
|
|
|
980
1061
|
function printAgentHelp() {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
/daemon status
|
|
1009
|
-
/rpc call status
|
|
1010
|
-
/memory show
|
|
1011
|
-
/hooks list
|
|
1012
|
-
/agents list
|
|
1013
|
-
/mcp status
|
|
1014
|
-
/cache status
|
|
1015
|
-
/sync
|
|
1016
|
-
/diff
|
|
1017
|
-
/card школа 29
|
|
1018
|
-
/quality
|
|
1019
|
-
/views
|
|
1020
|
-
/config get
|
|
1021
|
-
/config set api.baseUrl URL
|
|
1022
|
-
/layers
|
|
1023
|
-
/data schools --limit 10
|
|
1024
|
-
/schools --limit 10
|
|
1025
|
-
/schools get --inn 1215067180
|
|
1026
|
-
/kindergartens --search 29
|
|
1027
|
-
/kindergartens get --inn 1215077421
|
|
1028
|
-
/search лицей --limit 3
|
|
1029
|
-
/mcp-info
|
|
1030
|
-
/context школа 29
|
|
1031
|
-
/profiles
|
|
1032
|
-
/profile use local
|
|
1033
|
-
/models openrouter --search qwen
|
|
1034
|
-
/ai doctor
|
|
1035
|
-
/ai setup ollama
|
|
1036
|
-
/use openai
|
|
1037
|
-
/use ollama
|
|
1038
|
-
/key status
|
|
1039
|
-
/key set openai
|
|
1040
|
-
/config
|
|
1041
|
-
/provider
|
|
1042
|
-
/model
|
|
1043
|
-
/history
|
|
1044
|
-
/history --limit 20
|
|
1045
|
-
/new
|
|
1046
|
-
/reset
|
|
1047
|
-
/retry
|
|
1048
|
-
/undo
|
|
1049
|
-
/compact
|
|
1050
|
-
/usage
|
|
1051
|
-
/clear
|
|
1052
|
-
/banner
|
|
1053
|
-
/update
|
|
1054
|
-
/init
|
|
1055
|
-
/exit
|
|
1056
|
-
|
|
1057
|
-
Обычный текст без slash-команды отправляется в настроенный AI-провайдер.`);
|
|
1062
|
+
printSlashMenu("");
|
|
1063
|
+
console.log("");
|
|
1064
|
+
console.log("Обычный текст без slash-команды отправляется в настроенный AI-провайдер.");
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
function printSlashMenu(filter = "") {
|
|
1068
|
+
const normalized = String(filter || "").replace(/^\//, "");
|
|
1069
|
+
const rows = getSlashCommandMatches(normalized)
|
|
1070
|
+
.slice(0, 30)
|
|
1071
|
+
.map((item) => ({ command: item.command, description: item.description }));
|
|
1072
|
+
if (rows.length === 0) {
|
|
1073
|
+
console.log(`Нет slash-команд по фильтру: ${filter}`);
|
|
1074
|
+
console.log("Введите / для списка команд.");
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
console.log(normalized ? `Slash-команды по фильтру "${filter}":` : "Slash-команды:");
|
|
1078
|
+
printTable(rows, [["command", "Команда"], ["description", "Описание"]]);
|
|
1079
|
+
if (SLASH_COMMANDS.length > rows.length && !normalized) {
|
|
1080
|
+
console.log(`Показано ${rows.length} из ${SLASH_COMMANDS.length}. Введите /текст для фильтра.`);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function getSlashCommandMatches(filter = "") {
|
|
1085
|
+
const normalized = String(filter || "").replace(/^\//, "").toLocaleLowerCase("ru-RU");
|
|
1086
|
+
return SLASH_COMMANDS.filter((item) => !normalized
|
|
1087
|
+
|| item.command.toLocaleLowerCase("ru-RU").includes(normalized)
|
|
1088
|
+
|| item.description.toLocaleLowerCase("ru-RU").includes(normalized));
|
|
1058
1089
|
}
|
|
1059
1090
|
|
|
1060
1091
|
function printAgentHistory(history) {
|
|
@@ -1101,15 +1132,32 @@ function safePrompt(rl, closed = false) {
|
|
|
1101
1132
|
}
|
|
1102
1133
|
}
|
|
1103
1134
|
|
|
1104
|
-
function showBanner() {
|
|
1135
|
+
async function showBanner(options = {}) {
|
|
1105
1136
|
const version = getPackageVersion();
|
|
1137
|
+
const latest = options.skipUpdate ? null : await getLatestNpmVersion("@iola_adm/iola-cli");
|
|
1138
|
+
const updateAvailable = latest && compareVersions(latest, version) > 0;
|
|
1139
|
+
const versionLine = updateAvailable ? `v${version} -> v${latest} • npm install -g @iola_adm/iola-cli@latest` : `v${version} • iola help`;
|
|
1106
1140
|
if (process.stdout.isTTY && process.env.NO_COLOR !== "1") {
|
|
1107
|
-
console.log(BANNER.replace("
|
|
1141
|
+
console.log(BANNER.replace("VERSION_LINE", padBannerLine(versionLine)));
|
|
1142
|
+
if (updateAvailable) {
|
|
1143
|
+
console.log(`Доступно обновление: v${version} -> v${latest}`);
|
|
1144
|
+
console.log("Обновить: npm install -g @iola_adm/iola-cli@latest");
|
|
1145
|
+
}
|
|
1108
1146
|
return;
|
|
1109
1147
|
}
|
|
1110
1148
|
|
|
1111
|
-
console.log(`CLI-ЙОШКАР-ОЛА v${version}`);
|
|
1149
|
+
console.log(`CLI-ЙОШКАР-ОЛА ${updateAvailable ? `v${version} -> v${latest}` : `v${version}`}`);
|
|
1112
1150
|
console.log("открытые данные • MCP • локальный AI");
|
|
1151
|
+
if (updateAvailable) console.log("Обновить: npm install -g @iola_adm/iola-cli@latest");
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
function padBannerLine(value) {
|
|
1155
|
+
const text = String(value).slice(0, 62);
|
|
1156
|
+
return `${text}${" ".repeat(Math.max(0, 62 - bannerVisibleLength(text)))}`;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
function bannerVisibleLength(value) {
|
|
1160
|
+
return [...String(value)].length;
|
|
1113
1161
|
}
|
|
1114
1162
|
|
|
1115
1163
|
function getPackageVersion() {
|
|
@@ -1392,7 +1440,7 @@ async function initCli(args = []) {
|
|
|
1392
1440
|
const options = parseOptions(args);
|
|
1393
1441
|
const nodeStatus = getNodeRequirementStatus();
|
|
1394
1442
|
|
|
1395
|
-
showBanner();
|
|
1443
|
+
await showBanner();
|
|
1396
1444
|
console.log("Проверка окружения");
|
|
1397
1445
|
initDatabase();
|
|
1398
1446
|
const dbStatus = getDbStatus();
|
|
@@ -1439,7 +1487,7 @@ async function handleAi(args) {
|
|
|
1439
1487
|
const [subcommand = "help", ...rest] = args;
|
|
1440
1488
|
|
|
1441
1489
|
if (subcommand === "help") {
|
|
1442
|
-
showBanner();
|
|
1490
|
+
await showBanner();
|
|
1443
1491
|
console.log(`AI-команды:
|
|
1444
1492
|
iola ai ask TEXT [--provider ollama|openai|openrouter] [--model MODEL]
|
|
1445
1493
|
iola ai context TEXT [--json]
|
|
@@ -3711,7 +3759,7 @@ async function aiSetup(args) {
|
|
|
3711
3759
|
const [provider] = args;
|
|
3712
3760
|
|
|
3713
3761
|
if (!provider) {
|
|
3714
|
-
showBanner();
|
|
3762
|
+
await showBanner();
|
|
3715
3763
|
const selected = await chooseAiProvider();
|
|
3716
3764
|
await aiSetup([selected]);
|
|
3717
3765
|
return;
|
|
@@ -6338,7 +6386,7 @@ async function setupClient(args) {
|
|
|
6338
6386
|
|
|
6339
6387
|
async function onboard(args = []) {
|
|
6340
6388
|
const options = parseOptions(args);
|
|
6341
|
-
showBanner();
|
|
6389
|
+
await showBanner();
|
|
6342
6390
|
console.log("Мастер настройки iola-cli.");
|
|
6343
6391
|
console.log("Повторный запуск обновляет только выбранные разделы и не сбрасывает остальные настройки.");
|
|
6344
6392
|
console.log("");
|