@iola_adm/iola-cli 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +7 -1
  2. package/package.json +2 -2
  3. package/src/cli.js +85 -1
package/README.md CHANGED
@@ -18,7 +18,11 @@ node --version
18
18
  npm --version
19
19
  ```
20
20
 
21
- Нужен Node.js `18` или новее. Если Node.js не установлен:
21
+ Нужен Node.js `22.5.0` или новее. Это нужно для встроенной SQLite-БД
22
+ `node:sqlite`, которую CLI будет использовать для локальной истории, кеша и
23
+ сессий без дополнительных нативных зависимостей.
24
+
25
+ Если Node.js не установлен или версия ниже `22.5.0`:
22
26
 
23
27
  ```bash
24
28
  # Windows
@@ -54,6 +58,8 @@ curl -fsSL https://ollama.com/install.sh | sh
54
58
  Диагностика ПК и подбор локальной модели:
55
59
 
56
60
  ```bash
61
+ npx -y @iola_adm/iola-cli init
62
+ npx -y @iola_adm/iola-cli init --upgrade-node
57
63
  npx -y @iola_adm/iola-cli ai doctor
58
64
  npx -y @iola_adm/iola-cli ai setup ollama
59
65
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iola_adm/iola-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "CLI и AI-агент для работы с открытыми данными городского округа Йошкар-Ола.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/adm-iola/iola-cli#readme",
@@ -36,6 +36,6 @@
36
36
  "cli"
37
37
  ],
38
38
  "engines": {
39
- "node": ">=18"
39
+ "node": ">=22.5.0"
40
40
  }
41
41
  }
package/src/cli.js CHANGED
@@ -7,6 +7,7 @@ import { stdin as input, stdout as output } from "node:process";
7
7
 
8
8
  const API_BASE_URL = process.env.IOLA_API_BASE_URL || "https://apiiola.yasg.ru/api/v1";
9
9
  const MCP_BASE_URL = process.env.IOLA_MCP_BASE_URL || "https://apiiola.yasg.ru";
10
+ const MIN_NODE_VERSION = "22.5.0";
10
11
  const CONFIG_DIR = path.join(os.homedir(), ".iola");
11
12
  const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
12
13
  const SECRETS_FILE = path.join(CONFIG_DIR, "secrets.json");
@@ -94,6 +95,11 @@ const COMMANDS = new Map([
94
95
 
95
96
  export async function main(argv) {
96
97
  const [command = "help", ...args] = argv;
98
+ const nodeStatus = getNodeRequirementStatus();
99
+ if (!nodeStatus.ok && !["help", "version", "doctor", "init"].includes(command)) {
100
+ throw new Error(`Нужен Node.js ${MIN_NODE_VERSION} или новее. Сейчас: ${nodeStatus.current}. Запустите: iola init --upgrade-node`);
101
+ }
102
+
97
103
  const handler = COMMANDS.get(command);
98
104
 
99
105
  if (!handler) {
@@ -148,6 +154,9 @@ Usage:
148
154
  Environment:
149
155
  IOLA_API_BASE_URL default: ${API_BASE_URL}
150
156
  IOLA_MCP_BASE_URL default: ${MCP_BASE_URL}
157
+
158
+ Requirements:
159
+ Node.js >= ${MIN_NODE_VERSION}
151
160
  `);
152
161
  }
153
162
 
@@ -461,6 +470,9 @@ async function doctor(args = []) {
461
470
  version: packageJson.default.version,
462
471
  npmLatest: latest || "-",
463
472
  update: getUpdateStatus(packageJson.default.version, latest),
473
+ node: process.version,
474
+ nodeRequired: `>=${MIN_NODE_VERSION}`,
475
+ nodeStatus: getNodeRequirementStatus().ok ? "ok" : "upgrade-required",
464
476
  },
465
477
  api: {
466
478
  baseUrl: apiBaseUrl,
@@ -514,6 +526,69 @@ function getUpdateStatus(current, latest) {
514
526
  return "ok";
515
527
  }
516
528
 
529
+ function getNodeRequirementStatus() {
530
+ const current = process.versions.node;
531
+ return {
532
+ current,
533
+ required: MIN_NODE_VERSION,
534
+ ok: compareVersions(current, MIN_NODE_VERSION) >= 0,
535
+ };
536
+ }
537
+
538
+ async function offerNodeUpgrade(options, status) {
539
+ console.log(`Текущая версия Node.js: ${status.current}. Нужна ${MIN_NODE_VERSION} или новее.`);
540
+
541
+ if (!process.stdin.isTTY && !options["upgrade-node"]) {
542
+ printNodeUpgradeInstructions();
543
+ return;
544
+ }
545
+
546
+ const shouldUpgrade = options["upgrade-node"] || (await confirm("Обновить Node.js установщиком сейчас? [y/N] "));
547
+
548
+ if (!shouldUpgrade) {
549
+ printNodeUpgradeInstructions();
550
+ return;
551
+ }
552
+
553
+ await upgradeNodeWithInstaller();
554
+ console.log("");
555
+ console.log("После обновления перезапустите терминал и проверьте:");
556
+ console.log(" node --version");
557
+ console.log(" iola init");
558
+ }
559
+
560
+ function printNodeUpgradeInstructions() {
561
+ console.log("Обновите Node.js:");
562
+ console.log(" Windows: winget install OpenJS.NodeJS.LTS");
563
+ console.log(" macOS: brew install node");
564
+ console.log(" Linux: curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt-get install -y nodejs");
565
+ }
566
+
567
+ async function upgradeNodeWithInstaller() {
568
+ if (process.platform === "win32") {
569
+ try {
570
+ await runCommand("winget", ["upgrade", "OpenJS.NodeJS.LTS", "--accept-package-agreements", "--accept-source-agreements"], { inherit: true });
571
+ } catch {
572
+ await runCommand("winget", ["install", "OpenJS.NodeJS.LTS", "--accept-package-agreements", "--accept-source-agreements"], { inherit: true });
573
+ }
574
+ return;
575
+ }
576
+
577
+ if (process.platform === "darwin") {
578
+ try {
579
+ await runCommand("brew", ["upgrade", "node"], { inherit: true });
580
+ } catch {
581
+ await runCommand("brew", ["install", "node"], { inherit: true });
582
+ }
583
+ return;
584
+ }
585
+
586
+ await runCommand("sh", [
587
+ "-c",
588
+ "curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt-get install -y nodejs",
589
+ ], { inherit: true });
590
+ }
591
+
517
592
  async function checkConfiguredModel(config) {
518
593
  if (config.ai.provider !== "ollama") {
519
594
  return "external-api";
@@ -536,17 +611,25 @@ async function checkConfiguredModel(config) {
536
611
 
537
612
  async function initCli(args = []) {
538
613
  const options = parseOptions(args);
614
+ const nodeStatus = getNodeRequirementStatus();
539
615
 
540
616
  showBanner();
541
617
  console.log("Проверка окружения");
542
618
  printKeyValue({
543
619
  node: process.version,
620
+ node_required: `>=${MIN_NODE_VERSION}`,
621
+ node_status: nodeStatus.ok ? "ok" : "нужно обновить",
544
622
  npm: await getCommandVersion("npm", ["--version"]),
545
623
  api: await probeEndpoint(`${await getMcpBaseUrl()}/mcp-health`),
546
624
  mcp: await getMcpBaseUrl(),
547
625
  });
548
626
  console.log("");
549
627
 
628
+ if (!nodeStatus.ok) {
629
+ await offerNodeUpgrade(options, nodeStatus);
630
+ console.log("");
631
+ }
632
+
550
633
  await aiDoctor(options.json ? ["--json"] : []);
551
634
 
552
635
  if (!process.stdin.isTTY || options.yes) {
@@ -1744,8 +1827,9 @@ function parseOptions(args) {
1744
1827
  const arg = args[index];
1745
1828
  if (arg === "--json" || arg === "--yes") {
1746
1829
  result[arg.slice(2)] = true;
1747
- } else if (arg === "--check") {
1830
+ } else if (arg === "--check" || arg === "--upgrade-node") {
1748
1831
  result.check = true;
1832
+ result[arg.slice(2)] = true;
1749
1833
  } else if (arg === "--limit" || arg === "--offset" || arg === "--search" || arg === "--where" || arg === "--columns" || arg === "--inn" || arg === "--model" || arg === "--provider" || arg === "--profile" || arg === "--name" || arg === "--base-url" || arg === "--sandbox" || arg === "--approval" || arg === "--cwd" || arg === "--codex-profile" || arg === "--format") {
1750
1834
  result[arg.slice(2)] = args[index + 1];
1751
1835
  index += 1;