@iola_adm/iola-cli 0.1.55 → 0.1.57

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.1.55",
3
+ "version": "0.1.57",
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
@@ -848,13 +848,16 @@ async function startAgentRawInput() {
848
848
  }
849
849
  output.write(`> ${line}\n`);
850
850
  const stopActivity = line.startsWith("/") ? () => {} : startActivityIndicator("работаю");
851
+ const restoreRawInput = line.startsWith("/") ? suspendRawInputForCommand(input) : () => {};
851
852
  try {
852
853
  const shouldExit = await handleAgentLine(line, state);
853
854
  stopActivity();
854
855
  flushPendingAgentOutput(state);
856
+ if (!shouldExit) restoreRawInput();
855
857
  if (shouldExit) break;
856
858
  } catch (error) {
857
859
  stopActivity();
860
+ restoreRawInput();
858
861
  console.error(error instanceof Error ? error.message : String(error));
859
862
  }
860
863
  render();
@@ -1370,6 +1373,17 @@ function startActivityIndicator(label = "работаю") {
1370
1373
  };
1371
1374
  }
1372
1375
 
1376
+ function suspendRawInputForCommand(stream) {
1377
+ if (!stream.isTTY || !stream.isRaw) return () => {};
1378
+ stream.setRawMode(false);
1379
+ return () => {
1380
+ if (stream.isTTY) {
1381
+ stream.setRawMode(true);
1382
+ stream.resume();
1383
+ }
1384
+ };
1385
+ }
1386
+
1373
1387
  function flushPendingAgentOutput(state) {
1374
1388
  const text = state.pendingOutput;
1375
1389
  state.pendingOutput = "";
@@ -5886,27 +5900,29 @@ async function setupOllama(args) {
5886
5900
  const diagnostics = await getLocalDiagnostics();
5887
5901
  const recommendation = recommendOllamaModel(diagnostics);
5888
5902
  const model = options.model || recommendation.model;
5903
+ const ollamaCommand = await resolveOllamaCommand();
5889
5904
 
5890
5905
  printDiagnostics(diagnostics, { ...recommendation, model });
5891
5906
 
5892
- if (!diagnostics.ollama.installed) {
5907
+ if (!ollamaCommand) {
5893
5908
  console.log("");
5894
- console.log("Ollama не найден. Установите Ollama, затем повторите команду:");
5895
- console.log(" iola ai setup ollama");
5909
+ console.log("Ollama не найден или команда пока недоступна в текущем терминале.");
5910
+ console.log("Если Ollama только что установлена, откройте новый PowerShell или повторите после обновления PATH:");
5911
+ console.log(" iola master");
5896
5912
  console.log("");
5897
5913
  console.log("Windows:");
5898
- console.log(" winget install Ollama.Ollama");
5914
+ console.log(" $env:Path += ';' + \"$env:LOCALAPPDATA\\Programs\\Ollama\"");
5899
5915
  console.log("macOS:");
5900
- console.log(" brew install --cask ollama");
5916
+ console.log(" перезапустите терминал после brew install --cask ollama");
5901
5917
  console.log("Linux:");
5902
- console.log(" curl -fsSL https://ollama.com/install.sh | sh");
5918
+ console.log(" проверьте /usr/local/bin/ollama");
5903
5919
  return;
5904
5920
  }
5905
5921
 
5906
5922
  const shouldInstall = options.yes || (await confirm(`Установить модель ${model} через "ollama pull ${model}"? [Y/n] `));
5907
5923
 
5908
5924
  if (shouldInstall) {
5909
- await runCommand("ollama", ["pull", model], { inherit: true });
5925
+ await runCommand(ollamaCommand, ["pull", model], { inherit: true });
5910
5926
  }
5911
5927
 
5912
5928
  const config = await loadConfig();
@@ -6937,9 +6953,10 @@ async function onboard(args = []) {
6937
6953
  }
6938
6954
  }
6939
6955
 
6940
- const components = options.yes ? ["workspace", "policy", "ollama", "openai", "openrouter", "codex", "codex-mcp", "index"] : await chooseOnboardComponents();
6956
+ const components = options.yes ? ["workspace", "policy", "ollama", "openai", "openrouter", "codex", "codex-mcp", "archive", "index"] : await chooseOnboardComponents();
6941
6957
  if (components.includes("workspace")) await handleWorkspace(["init"]);
6942
6958
  if (components.includes("policy")) await handlePolicy(["use", "analyst"]);
6959
+ if (components.includes("archive")) await ensureArchiveTool({ install: true });
6943
6960
  if (components.includes("ollama")) {
6944
6961
  await installOllamaIfMissing();
6945
6962
  await setupOllama(["--yes"]);
@@ -6986,9 +7003,10 @@ async function chooseOnboardComponents() {
6986
7003
  console.log("5. OpenRouter API");
6987
7004
  console.log("6. Codex CLI");
6988
7005
  console.log("7. MCP для Codex");
6989
- console.log("8. Индекс локальных документов");
6990
- console.log("9. Browser runtime");
6991
- console.log("10. Личное подключение Госуслуг");
7006
+ console.log("8. 7-Zip / архивы");
7007
+ console.log("9. Индекс локальных документов");
7008
+ console.log("10. Browser runtime");
7009
+ console.log("11. Личное подключение Госуслуг");
6992
7010
  console.log("");
6993
7011
  const rl = readline.createInterface({ input, output });
6994
7012
  try {
@@ -7002,9 +7020,10 @@ async function chooseOnboardComponents() {
7002
7020
  5: "openrouter",
7003
7021
  6: "codex",
7004
7022
  7: "codex-mcp",
7005
- 8: "index",
7006
- 9: "browser",
7007
- 10: "gosuslugi",
7023
+ 8: "archive",
7024
+ 9: "index",
7025
+ 10: "browser",
7026
+ 11: "gosuslugi",
7008
7027
  };
7009
7028
  return [...selected].map((item) => map[item] || item).filter(Boolean);
7010
7029
  } finally {
@@ -7326,14 +7345,38 @@ async function getWindowsGpu() {
7326
7345
  }
7327
7346
 
7328
7347
  async function getOllamaVersion() {
7348
+ const command = await resolveOllamaCommand();
7349
+ if (!command) return null;
7329
7350
  try {
7330
- const { stdout } = await runCommand("ollama", ["--version"]);
7351
+ const { stdout } = await runCommand(command, ["--version"]);
7331
7352
  return stdout.trim();
7332
7353
  } catch {
7333
7354
  return null;
7334
7355
  }
7335
7356
  }
7336
7357
 
7358
+ async function resolveOllamaCommand() {
7359
+ const candidates = ["ollama"];
7360
+ if (process.platform === "win32") {
7361
+ candidates.push(
7362
+ path.join(os.homedir(), "AppData", "Local", "Programs", "Ollama", "ollama.exe"),
7363
+ path.join(process.env.LOCALAPPDATA || "", "Programs", "Ollama", "ollama.exe"),
7364
+ );
7365
+ } else {
7366
+ candidates.push("/usr/local/bin/ollama", "/opt/homebrew/bin/ollama", "/usr/bin/ollama");
7367
+ }
7368
+ for (const command of [...new Set(candidates.filter(Boolean))]) {
7369
+ try {
7370
+ if (command !== "ollama" && !existsSync(command)) continue;
7371
+ await runCommand(command, ["--version"]);
7372
+ return command;
7373
+ } catch {
7374
+ // Try next candidate.
7375
+ }
7376
+ }
7377
+ return null;
7378
+ }
7379
+
7337
7380
  async function getCommandVersion(command, args) {
7338
7381
  try {
7339
7382
  const { stdout } = await runCommand(command, args);
@@ -7403,6 +7446,9 @@ async function installOllamaIfMissing() {
7403
7446
  return;
7404
7447
  }
7405
7448
  await runCommand("sh", ["-c", "curl -fsSL https://ollama.com/install.sh | sh"], { inherit: true });
7449
+ if (!(await getOllamaVersion())) {
7450
+ console.log("Ollama установлен, но текущий терминал может еще не видеть команду. CLI попробует стандартный путь установки.");
7451
+ }
7406
7452
  }
7407
7453
 
7408
7454
  async function installCodexIfMissing() {
@@ -38,5 +38,8 @@ iola index search "контракт"
38
38
  iola onboard
39
39
  ```
40
40
 
41
- Мастер проверяет Node/npm, SQLite, API, 7-Zip и предлагает подключить workspace, policy, Ollama, OpenAI, OpenRouter, Codex CLI, MCP и индекс локальных документов.
41
+ Мастер проверяет Node/npm, SQLite, API и 7-Zip.
42
42
 
43
+ В списке компонентов есть отдельный пункт `7-Zip / архивы`. Если выбрать его, CLI установит архиватор сразу из мастера настройки.
44
+
45
+ Мастер также предлагает подключить workspace, policy, Ollama, OpenAI, OpenRouter, Codex CLI, MCP, browser runtime, Госуслуги и индекс локальных документов.