@iola_adm/iola-cli 0.2.37 → 0.2.39

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iola_adm/iola-cli",
3
- "version": "0.2.37",
3
+ "version": "0.2.39",
4
4
  "description": "CLI и AI-агент городского округа Йошкар-Ола.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/adm-iola/iola-cli#readme",
package/src/cli.js CHANGED
@@ -3575,6 +3575,7 @@ async function handleYandexCloudConnector(args = []) {
3575
3575
  }
3576
3576
 
3577
3577
  if (action === "open") {
3578
+ printYandexCloudSetupGuide({ includeYandexGpt: true });
3578
3579
  await openUrl("https://console.yandex.cloud/");
3579
3580
  return;
3580
3581
  }
@@ -3585,9 +3586,13 @@ async function handleYandexCloudConnector(args = []) {
3585
3586
  async function setupYandexCloudConnector(options = {}) {
3586
3587
  console.log("Yandex Cloud Connector: геокодинг и YandexGPT.");
3587
3588
  console.log("Геокодер будет включен по умолчанию. YandexGPT можно выбрать в /model после сохранения ключей.");
3589
+ printYandexCloudSetupGuide({ includeYandexGpt: true });
3588
3590
  if (process.stdin.isTTY) {
3589
3591
  const openConsole = await askYesNo("Открыть Yandex Cloud Console для получения ключей? [Y/n] ", true);
3590
- if (openConsole) await openUrl("https://console.yandex.cloud/");
3592
+ if (openConsole) {
3593
+ console.log("Открыл Yandex Cloud Console. Вернитесь сюда после создания ключей и вставьте их в CLI.");
3594
+ await openUrl("https://console.yandex.cloud/");
3595
+ }
3591
3596
  }
3592
3597
 
3593
3598
  const secrets = await loadSecrets();
@@ -3601,6 +3606,8 @@ async function setupYandexCloudConnector(options = {}) {
3601
3606
  return;
3602
3607
  }
3603
3608
 
3609
+ console.log("");
3610
+ console.log("Вставьте ключ API Геокодера. Если ключ еще создается, оставьте мастер открытым, получите ключ в браузере и вернитесь сюда.");
3604
3611
  const geocoderKey = (await askText(`YANDEX_GEOCODER_API_KEY${currentGeocoder ? " [уже сохранен, Enter - оставить]" : ""}: `)).trim() || currentGeocoder;
3605
3612
  if (!geocoderKey) throw new Error("Для Cloud Connector нужен хотя бы Geocoder API key.");
3606
3613
 
@@ -3619,6 +3626,22 @@ async function setupYandexCloudConnector(options = {}) {
3619
3626
  await printYandexCloudConnectorStatus({ check: true });
3620
3627
  }
3621
3628
 
3629
+ function printYandexCloudSetupGuide(options = {}) {
3630
+ console.log("");
3631
+ console.log("Что делать в открывшейся консоли Яндекса:");
3632
+ console.log("1. Войдите в свой Яндекс-аккаунт.");
3633
+ console.log("2. Если Яндекс попросит создать облако или каталог, создайте их. Названия можно оставить простыми: iola-cli и default.");
3634
+ console.log("3. Для геокодера откройте Кабинет разработчика: https://developer.tech.yandex.ru/services/2");
3635
+ console.log("4. Выберите API Геокодера, создайте API key и скопируйте значение ключа.");
3636
+ console.log("5. Вернитесь в это окно CLI и вставьте ключ в поле YANDEX_GEOCODER_API_KEY.");
3637
+ if (options.includeYandexGpt) {
3638
+ console.log("6. Если нужен YandexGPT: в Yandex Cloud откройте каталог, скопируйте ID каталога, затем создайте сервисный аккаунт и API-ключ с правом yc.ai.foundationModels.execute.");
3639
+ console.log("7. После ключа геокодера CLI отдельно спросит, настраивать ли YandexGPT. Можно ответить n и подключить модель позже через /model.");
3640
+ }
3641
+ console.log("Подробная инструкция: https://github.com/adm-iola/iola-cli/wiki/Yandex-Cloud-Connector");
3642
+ console.log("");
3643
+ }
3644
+
3622
3645
  async function saveYandexCloudConnectorSecrets({ geocoderApiKey, yandexgptApiKey, folderId }) {
3623
3646
  const secrets = await loadSecrets();
3624
3647
  secrets.yandexCloud = {
@@ -10062,6 +10085,15 @@ async function askText(question) {
10062
10085
  }
10063
10086
  }
10064
10087
 
10088
+ async function askYesNo(question, defaultValue = false) {
10089
+ if (!process.stdin.isTTY) return Boolean(defaultValue);
10090
+ const answer = (await askText(question)).trim().toLocaleLowerCase("ru-RU");
10091
+ if (!answer) return Boolean(defaultValue);
10092
+ if (answer === "y" || answer === "yes" || answer === "д" || answer === "да") return true;
10093
+ if (answer === "n" || answer === "no" || answer === "н" || answer === "нет") return false;
10094
+ return Boolean(defaultValue);
10095
+ }
10096
+
10065
10097
  async function aiContext(args) {
10066
10098
  const options = parseOptions(args);
10067
10099
  const query = options._.join(" ").trim();
@@ -16465,9 +16497,6 @@ async function onboard(args = []) {
16465
16497
  await chooseAndSaveApiModel("openrouter");
16466
16498
  }
16467
16499
  }
16468
- if (components.includes("yandex-cloud")) {
16469
- await setupYandexCloudConnector({});
16470
- }
16471
16500
  if (components.includes("gigachat")) {
16472
16501
  await aiSetup(["gigachat"]);
16473
16502
  if (process.stdin.isTTY) {
@@ -16486,6 +16515,9 @@ async function onboard(args = []) {
16486
16515
  if (components.includes("yandex")) {
16487
16516
  await setupYandexConnector([]);
16488
16517
  }
16518
+ if (components.includes("yandex-cloud")) {
16519
+ await setupYandexCloudConnector({});
16520
+ }
16489
16521
  if (components.includes("codex")) {
16490
16522
  await installCodexIfMissing();
16491
16523
  await aiSetup(["codex"]);
@@ -16524,19 +16556,18 @@ async function chooseOnboardComponents(status = null) {
16524
16556
  1: "workspace",
16525
16557
  2: "policy",
16526
16558
  3: "iola",
16527
- 4: "yandex-cloud",
16528
- 5: "gigachat",
16529
- 6: "openai",
16530
- 7: "openrouter",
16531
- 8: "codex",
16532
- 9: "codex-mcp",
16533
- 10: "archive",
16534
- 11: "index",
16535
- 12: "browser",
16536
- 13: "ollama",
16537
- 14: "cloud",
16538
- 15: "yandex",
16539
- 16: "yandex",
16559
+ 4: "gigachat",
16560
+ 5: "openai",
16561
+ 6: "openrouter",
16562
+ 7: "codex",
16563
+ 8: "codex-mcp",
16564
+ 9: "archive",
16565
+ 10: "index",
16566
+ 11: "browser",
16567
+ 12: "ollama",
16568
+ 13: "yandex",
16569
+ 14: "yandex-cloud",
16570
+ 15: "yandex-cloud",
16540
16571
  };
16541
16572
  return [...selected].map((item) => map[item] || item).filter(Boolean);
16542
16573
  } finally {
@@ -16559,7 +16590,6 @@ async function getOnboardComponentStatus() {
16559
16590
  getYandexGeocoderKey(),
16560
16591
  loadSecrets(),
16561
16592
  ]);
16562
- const cloudSecrets = secrets.cloud || {};
16563
16593
  const workspaceReady = existsSync(PROJECT_CONTEXT_FILE) || existsSync(PROJECT_CONTEXT_DIR_FILE) || existsSync(PROJECT_IOLA_DIR);
16564
16594
  const policyReady = (config.toolsets?.enabled || []).includes("analyst");
16565
16595
  return {
@@ -16576,7 +16606,6 @@ async function getOnboardComponentStatus() {
16576
16606
  archive: Boolean(archive),
16577
16607
  index: false,
16578
16608
  browser: browser.installed === "yes",
16579
- cloud: Object.keys(cloudSecrets).length > 0,
16580
16609
  yandex: isYandexConnectorFullyConnected(secrets),
16581
16610
  };
16582
16611
  }
@@ -16586,18 +16615,17 @@ function onboardComponentRows(status) {
16586
16615
  ["1", "workspace", "workspace и контекст", "рабочая папка, IOLA.md и .iola/context.md"],
16587
16616
  ["2", "policy", "policy analyst", "разрешения и профиль аналитика"],
16588
16617
  ["3", "iola", "IOLA локальная модель", "локальная модель найдена"],
16589
- ["4", "yandex-cloud", "Yandex Cloud Connector", "геокодинг и YandexGPT"],
16590
- ["5", "gigachat", "GigaChat API", "authorization key сохранен или есть в env"],
16591
- ["6", "openai", "OpenAI API", "API-ключ сохранен или есть в env"],
16592
- ["7", "openrouter", "OpenRouter API", "API-ключ сохранен или есть в env"],
16593
- ["8", "codex", "Codex CLI", "CLI установлен и авторизация найдена"],
16594
- ["9", "codex-mcp", "MCP для Codex", "можно переустановить/обновить"],
16595
- ["10", "archive", "7-Zip / архивы", "архиватор найден"],
16596
- ["11", "index", "Индекс локальных документов", "настраивается под выбранную папку"],
16597
- ["12", "browser", "Browser runtime", "Playwright/Chromium установлен"],
16598
- ["13", "ollama", "Ollama", "опциональный локальный runtime"],
16599
- ["14", "cloud", "Облачный диск", "Яндекс Диск или Облако Mail.ru"],
16600
- ["15", "yandex", "Yandex Connector", "единый вход и категории сервисов Яндекса"],
16618
+ ["4", "gigachat", "GigaChat API", "authorization key сохранен или есть в env"],
16619
+ ["5", "openai", "OpenAI API", "API-ключ сохранен или есть в env"],
16620
+ ["6", "openrouter", "OpenRouter API", "API-ключ сохранен или есть в env"],
16621
+ ["7", "codex", "Codex CLI", "CLI установлен и авторизация найдена"],
16622
+ ["8", "codex-mcp", "MCP для Codex", "можно переустановить/обновить"],
16623
+ ["9", "archive", "7-Zip / архивы", "архиватор найден"],
16624
+ ["10", "index", "Индекс локальных документов", "настраивается под выбранную папку"],
16625
+ ["11", "browser", "Browser runtime", "Playwright/Chromium установлен"],
16626
+ ["12", "ollama", "Ollama", "опциональный локальный runtime"],
16627
+ ["13", "yandex", "Yandex Connector", "единый вход и категории сервисов Яндекса"],
16628
+ ["14", "yandex-cloud", "Yandex Cloud Connector", "геокодинг и YandexGPT"],
16601
16629
  ];
16602
16630
  return rows.map(([number, key, title, hint]) => ({ number, key, title, hint, status: status[key] ? "готово" : "не настроено" }));
16603
16631
  }
@@ -16607,12 +16635,12 @@ function defaultOnboardSelection(status) {
16607
16635
  if (!status.workspace) defaults.push("1");
16608
16636
  if (!status.policy) defaults.push("2");
16609
16637
  if (!status.iola) defaults.push("3");
16610
- if (!status.archive) defaults.push("10");
16638
+ if (!status.archive) defaults.push("9");
16611
16639
  return defaults.length ? defaults : ["1", "2"];
16612
16640
  }
16613
16641
 
16614
16642
  function defaultOnboardComponents(status) {
16615
- const map = { 1: "workspace", 2: "policy", 3: "iola", 4: "yandex-cloud", 5: "gigachat", 6: "openai", 7: "openrouter", 8: "codex", 9: "codex-mcp", 10: "archive", 11: "index", 12: "browser", 13: "ollama", 14: "cloud", 15: "yandex", 16: "yandex" };
16643
+ const map = { 1: "workspace", 2: "policy", 3: "iola", 4: "gigachat", 5: "openai", 6: "openrouter", 7: "codex", 8: "codex-mcp", 9: "archive", 10: "index", 11: "browser", 12: "ollama", 13: "yandex", 14: "yandex-cloud", 15: "yandex-cloud" };
16616
16644
  return defaultOnboardSelection(status).map((item) => map[item]).filter(Boolean);
16617
16645
  }
16618
16646
 
@@ -18,10 +18,22 @@ iola master
18
18
  В мастере выберите:
19
19
 
20
20
  ```text
21
- 4. Yandex Cloud Connector - геокодинг и YandexGPT
21
+ 14. Yandex Cloud Connector - геокодинг и YandexGPT
22
22
  ```
23
23
 
24
- CLI откроет консоль Yandex Cloud и попросит сохранить:
24
+ CLI не просто открывает консоль. Он печатает короткую инструкцию, что делать дальше, и только потом просит вставить ключи.
25
+
26
+ Что делает пользователь:
27
+
28
+ 1. Входит в свой Яндекс-аккаунт.
29
+ 2. Если Яндекс просит создать облако или каталог, создает их. Названия можно оставить простыми: `iola-cli` и `default`.
30
+ 3. Для геокодера открывает Кабинет разработчика: `https://developer.tech.yandex.ru/services/2`.
31
+ 4. Выбирает `API Геокодера`, создает API key и копирует значение ключа.
32
+ 5. Возвращается в окно CLI и вставляет ключ в поле `YANDEX_GEOCODER_API_KEY`.
33
+ 6. Если нужен YandexGPT, в Yandex Cloud копирует ID каталога, создает сервисный аккаунт и API-ключ с правом `yc.ai.foundationModels.execute`.
34
+ 7. Если YandexGPT пока не нужен, на вопрос CLI можно ответить `n` и подключить модель позже через `/model`.
35
+
36
+ CLI попросит сохранить:
25
37
 
26
38
  - ключ `YANDEX_GEOCODER_API_KEY`;
27
39
  - при необходимости YandexGPT API key;
@@ -30,49 +30,39 @@ iola master
30
30
 
31
31
  После настройки локальную модель можно менять в интерактивном агенте через `/model`. Помимо штатной IOLA-модели можно выбрать установленную или рекомендуемую Ollama-модель, либо вручную ввести имя любой модели из библиотеки Ollama.
32
32
 
33
- ### 4. Yandex Cloud Connector
34
-
35
- Настраивает Yandex Cloud Connector: геокодер и, при необходимости, YandexGPT.
36
-
37
- Геокодер включается по умолчанию. Он нужен для geo-skills и deeplink Яндекс Go. YandexGPT можно включить сразу или выбрать позже через `/model`.
38
-
39
- Ключи сохраняются локально у пользователя. Российский AI-провайдер вызывается напрямую, без gateway/proxy.
40
-
41
- Инструкция: [Yandex Cloud Connector](Yandex-Cloud-Connector).
42
-
43
- ### 5. GigaChat API
33
+ ### 4. GigaChat API
44
34
 
45
35
  Настраивает профиль GigaChat и сохраняет authorization key локально у пользователя.
46
36
 
47
37
  Российский провайдер вызывается напрямую, без gateway/proxy.
48
38
 
49
- ### 6. OpenAI API
39
+ ### 5. OpenAI API
50
40
 
51
41
  Настраивает профиль OpenAI и сохраняет API-ключ локально у пользователя.
52
42
 
53
43
  После сохранения ключа мастер предлагает выбрать модель из доступного списка.
54
44
 
55
- ### 7. OpenRouter API
45
+ ### 6. OpenRouter API
56
46
 
57
47
  Настраивает профиль OpenRouter и сохраняет API-ключ локально у пользователя.
58
48
 
59
49
  После сохранения ключа мастер предлагает выбрать разработчика моделей OpenRouter, а затем одну из свежих моделей для текстовой работы. В списке моделей `0` возвращает к выбору разработчика.
60
50
 
61
- ### 8. Codex CLI
51
+ ### 7. Codex CLI
62
52
 
63
53
  Проверяет наличие Codex CLI и авторизации. Если Codex уже установлен и вход выполнен, пункт показывается как `готово`.
64
54
 
65
- ### 9. MCP для Codex
55
+ ### 8. MCP для Codex
66
56
 
67
57
  Добавляет MCP-сервер открытых данных Йошкар-Олы в Codex. Этот пункт можно запускать повторно для обновления подключения.
68
58
 
69
- ### 10. 7-Zip / архивы
59
+ ### 9. 7-Zip / архивы
70
60
 
71
61
  Проверяет 7-Zip. Если архиватор не найден, мастер устанавливает его.
72
62
 
73
63
  Нужен для чтения, распаковки, сборки и индексирования архивов.
74
64
 
75
- ### 11. Индекс локальных документов
65
+ ### 10. Индекс локальных документов
76
66
 
77
67
  Готовит режим чтения файлов и подсказывает команду индексирования локальной папки:
78
68
 
@@ -80,28 +70,17 @@ iola master
80
70
  iola index folder ./docs
81
71
  ```
82
72
 
83
- ### 12. Browser runtime
73
+ ### 11. Browser runtime
84
74
 
85
75
  Проверяет Playwright/Chromium runtime. Нужен для браузерного агента.
86
76
 
87
- ### 13. Ollama
77
+ ### 12. Ollama
88
78
 
89
79
  Опциональный локальный runtime для выбора сторонних моделей из библиотеки Ollama.
90
80
 
91
81
  Если runtime уже установлен, пункт показывается как `готово`.
92
82
 
93
- ### 14. Облачный диск
94
-
95
- Подключает личный облачный диск пользователя:
96
-
97
- - Яндекс Диск;
98
- - Облако Mail.ru.
99
-
100
- Секреты сохраняются локально в `~/.iola/secrets.json`. Резервные копии CLI не включают OAuth-токены, пароли и API-ключи.
101
-
102
- Инструкция: [Облачные диски](Облачные-диски).
103
-
104
- ### 15. Yandex Connector
83
+ ### 13. Yandex Connector
105
84
 
106
85
  Настраивает единый коннектор пользовательских сервисов Яндекса.
107
86
 
@@ -116,6 +95,18 @@ iola index folder ./docs
116
95
 
117
96
  Инструкция: [Yandex Connector](Yandex-Connector).
118
97
 
98
+ ### 14. Yandex Cloud Connector
99
+
100
+ Настраивает Yandex Cloud Connector: геокодер и, при необходимости, YandexGPT.
101
+
102
+ Геокодер включается по умолчанию. Он нужен для geo-skills и deeplink Яндекс Go. YandexGPT можно включить сразу или выбрать позже через `/model`.
103
+
104
+ При запуске CLI печатает пошаговую инструкцию: войти в Яндекс, создать облако/каталог при необходимости, открыть Кабинет разработчика геокодера, создать API key, вернуться в CLI и вставить ключ. Пользователь не остается один на пустой странице консоли.
105
+
106
+ Ключи сохраняются локально у пользователя. Российский AI-провайдер вызывается напрямую, без gateway/proxy.
107
+
108
+ Инструкция: [Yandex Cloud Connector](Yandex-Cloud-Connector).
109
+
119
110
  ## Повторный запуск
120
111
 
121
112
  Если компонент уже настроен, его можно не выбирать. Если нужно переустановить или обновить компонент, выберите его номер вручную.