@iola_adm/iola-cli 0.1.106 → 0.1.108

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.106",
3
+ "version": "0.1.108",
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
@@ -611,7 +611,7 @@ Usage:
611
611
  iola ai models iola|ollama|openai|openrouter|codex [--search TEXT]
612
612
  iola ai doctor [--json]
613
613
  iola ai setup
614
- iola ai setup iola [--yes]
614
+ iola ai setup iola [--yes] [--force]
615
615
  iola ai setup ollama [--yes] [--model MODEL]
616
616
  iola health [--json]
617
617
  iola layers [--json]
@@ -2053,7 +2053,7 @@ async function handleAi(args) {
2053
2053
  iola ai models iola|ollama|openai|openrouter|codex [--search TEXT]
2054
2054
  iola ai doctor [--json]
2055
2055
  iola ai setup
2056
- iola ai setup iola [--yes]
2056
+ iola ai setup iola [--yes] [--force]
2057
2057
  iola ai setup ollama [--yes] [--model MODEL]
2058
2058
  iola ai setup openai [--model MODEL]
2059
2059
  iola ai setup openrouter [--model MODEL]
@@ -4747,6 +4747,15 @@ async function chooseAiModel(provider) {
4747
4747
  return filtered[answer - 1]?.id || "";
4748
4748
  }
4749
4749
 
4750
+ async function chooseAndSaveApiModel(provider) {
4751
+ const model = await chooseAiModel(provider);
4752
+ if (!model) {
4753
+ console.log("Модель не выбрана. Оставлена модель по умолчанию.");
4754
+ return;
4755
+ }
4756
+ await switchModelTarget(provider, model);
4757
+ }
4758
+
4750
4759
  async function switchModelTarget(target, model) {
4751
4760
  const config = await loadConfig();
4752
4761
  const provider = target === "local" ? "iola" : target;
@@ -4816,6 +4825,8 @@ async function isOllamaModelInstalled(model, loadedConfig = null) {
4816
4825
 
4817
4826
  async function askText(question) {
4818
4827
  if (!process.stdin.isTTY) return "";
4828
+ if (input.isRaw) input.setRawMode(false);
4829
+ input.resume();
4819
4830
  const rl = readline.createInterface({ input, output });
4820
4831
  try {
4821
4832
  return await rl.question(question);
@@ -4850,22 +4861,16 @@ async function setAiKey(provider) {
4850
4861
  }
4851
4862
 
4852
4863
  const envName = provider === "openai" ? "OPENAI_API_KEY" : "OPENROUTER_API_KEY";
4853
- const rl = readline.createInterface({ input, output });
4864
+ const key = (await askText(`Введите ${envName}: `)).trim();
4854
4865
 
4855
- try {
4856
- const key = (await rl.question(`Введите ${envName}: `)).trim();
4857
-
4858
- if (!key) {
4859
- throw new Error("Ключ пустой, сохранение отменено.");
4860
- }
4861
-
4862
- const secrets = await loadSecrets();
4863
- secrets[provider] = { apiKey: key };
4864
- await saveSecrets(secrets);
4865
- console.log(`Ключ ${provider} сохранен локально: ${SECRETS_FILE}`);
4866
- } finally {
4867
- rl.close();
4866
+ if (!key) {
4867
+ throw new Error("Ключ пустой, сохранение отменено.");
4868
4868
  }
4869
+
4870
+ const secrets = await loadSecrets();
4871
+ secrets[provider] = { apiKey: key };
4872
+ await saveSecrets(secrets);
4873
+ console.log(`Ключ ${provider} сохранен локально: ${SECRETS_FILE}`);
4869
4874
  }
4870
4875
 
4871
4876
  async function printAiKeyStatus() {
@@ -6147,19 +6152,14 @@ async function chooseAiProvider() {
6147
6152
  console.log("4. Codex/MCP");
6148
6153
  console.log("5. Ollama");
6149
6154
 
6150
- const rl = readline.createInterface({ input, output });
6151
- try {
6152
- const answer = (await rl.question("Введите номер [1]: ")).trim() || "1";
6153
- return {
6154
- 1: "iola",
6155
- 2: "openai",
6156
- 3: "openrouter",
6157
- 4: "codex",
6158
- 5: "ollama",
6159
- }[answer] || "iola";
6160
- } finally {
6161
- rl.close();
6162
- }
6155
+ const answer = (await askText("Введите номер [1]: ")).trim() || "1";
6156
+ return {
6157
+ 1: "iola",
6158
+ 2: "openai",
6159
+ 3: "openrouter",
6160
+ 4: "codex",
6161
+ 5: "ollama",
6162
+ }[answer] || "iola";
6163
6163
  }
6164
6164
 
6165
6165
  async function setupOllama(args) {
@@ -6239,7 +6239,7 @@ async function setupIolaLocal(args) {
6239
6239
  ggufFile,
6240
6240
  modelDir,
6241
6241
  model,
6242
- force: true,
6242
+ force: Boolean(options.force),
6243
6243
  quiet: Boolean(options.quiet),
6244
6244
  });
6245
6245
  } catch (error) {
@@ -8502,11 +8502,17 @@ async function onboard(args = []) {
8502
8502
  }
8503
8503
  if (components.includes("openai")) {
8504
8504
  await aiSetup(["openai"]);
8505
- if (process.stdin.isTTY) await setAiKey("openai");
8505
+ if (process.stdin.isTTY) {
8506
+ await setAiKey("openai");
8507
+ await chooseAndSaveApiModel("openai");
8508
+ }
8506
8509
  }
8507
8510
  if (components.includes("openrouter")) {
8508
8511
  await aiSetup(["openrouter"]);
8509
- if (process.stdin.isTTY) await setAiKey("openrouter");
8512
+ if (process.stdin.isTTY) {
8513
+ await setAiKey("openrouter");
8514
+ await chooseAndSaveApiModel("openrouter");
8515
+ }
8510
8516
  }
8511
8517
  if (components.includes("codex")) {
8512
8518
  await installCodexIfMissing();
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
6
6
  const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
7
7
  const binPath = resolve(rootDir, "bin", "iola.js");
8
8
  const packageJson = JSON.parse(await readFile(resolve(rootDir, "package.json"), "utf8"));
9
+ const cliSource = await readFile(resolve(rootDir, "src", "cli.js"), "utf8");
9
10
 
10
11
  function runCli(args) {
11
12
  return new Promise((resolvePromise, reject) => {
@@ -45,6 +46,8 @@ const help = await runCli(["--help"]);
45
46
  assertIncludes(help, "iola master", "help");
46
47
  assertIncludes(help, "iola ask", "help");
47
48
 
49
+ assertIncludes(cliSource, "force: Boolean(options.force)", "IOLA setup should not force model reinstall by default");
50
+
48
51
  const commands = await runCli(["commands"]);
49
52
  assertIncludes(commands, "iola browser status|install|open|text|html|screenshot|pdf|click|type|eval", "commands");
50
53
  assertIncludes(commands, "iola mcp list|status|install|remove|serve [--stdio]", "commands");