@iola_adm/iola-cli 0.1.41 → 0.1.42

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +70 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iola_adm/iola-cli",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
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
@@ -120,6 +120,7 @@ const SKILL_BUNDLES = {
120
120
  requirements: ["Ollama", "локальная модель"],
121
121
  },
122
122
  };
123
+ let onboardRanThisProcess = false;
123
124
  const DEFAULT_AI_CONFIG = {
124
125
  api: {
125
126
  baseUrl: "https://apiiola.yasg.ru/api/v1",
@@ -622,6 +623,7 @@ async function runDefaultCli() {
622
623
 
623
624
  async function startAgent() {
624
625
  await showBanner();
626
+ await ensureAgentAiReady();
625
627
  console.log("Интерактивный режим. Введите /help для списка команд, /exit для выхода.");
626
628
  await runHooks("SessionStart", { mode: "agent" });
627
629
 
@@ -635,6 +637,73 @@ async function startAgent() {
635
637
  await runHooks("SessionEnd", { mode: "agent" });
636
638
  }
637
639
 
640
+ async function ensureAgentAiReady() {
641
+ const readiness = await getAiReadiness();
642
+ if (readiness.ready) return readiness;
643
+
644
+ if (!input.isTTY || !output.isTTY) {
645
+ console.log("AI-провайдер не настроен. Для настройки запустите: iola wizard");
646
+ return readiness;
647
+ }
648
+
649
+ if (onboardRanThisProcess) {
650
+ console.log("AI-провайдер пока не настроен. Агент откроется, но AI-запросы потребуют настройки.");
651
+ console.log("Повторно открыть мастер можно командой: /wizard");
652
+ return readiness;
653
+ }
654
+
655
+ console.log("AI-провайдер не настроен: нет локальной модели Ollama, API-ключей OpenAI/OpenRouter и авторизации Codex.");
656
+ console.log("Сейчас откроется мастер настройки. Уже существующие настройки не будут сброшены.");
657
+ console.log("");
658
+ await onboard([]);
659
+
660
+ const updated = await getAiReadiness();
661
+ if (!updated.ready) {
662
+ console.log("");
663
+ console.log("AI-провайдер пока не настроен. Агент откроется, но AI-запросы потребуют настройки.");
664
+ console.log("Повторно открыть мастер можно командой: /wizard");
665
+ }
666
+ return updated;
667
+ }
668
+
669
+ async function getAiReadiness() {
670
+ const [secrets, ollama, codex] = await Promise.all([
671
+ loadSecrets(),
672
+ hasUsableOllamaModel(),
673
+ hasUsableCodexAuth(),
674
+ ]);
675
+ const openai = Boolean(process.env.OPENAI_API_KEY || secrets.openai?.apiKey);
676
+ const openrouter = Boolean(process.env.OPENROUTER_API_KEY || secrets.openrouter?.apiKey);
677
+ return {
678
+ ready: Boolean(ollama || openai || openrouter || codex),
679
+ ollama,
680
+ openai,
681
+ openrouter,
682
+ codex,
683
+ };
684
+ }
685
+
686
+ async function hasUsableOllamaModel() {
687
+ try {
688
+ const config = await loadConfig();
689
+ const baseUrl = config.ai.profiles?.local?.baseUrl || "http://127.0.0.1:11434";
690
+ const response = await fetch(`${baseUrl}/api/tags`, { signal: AbortSignal.timeout(1200) });
691
+ if (!response.ok) return false;
692
+ const payload = await response.json();
693
+ const models = Array.isArray(payload.models) ? payload.models : [];
694
+ return models.length > 0;
695
+ } catch {
696
+ return false;
697
+ }
698
+ }
699
+
700
+ async function hasUsableCodexAuth() {
701
+ const version = await getCommandVersion("codex", ["--version"]);
702
+ if (version === "не найден") return false;
703
+ if (process.env.OPENAI_API_KEY) return true;
704
+ return existsSync(path.join(os.homedir(), ".codex", "auth.json"));
705
+ }
706
+
638
707
  async function startAgentReadline() {
639
708
  const rl = readline.createInterface({ input, output, prompt: "iola> " });
640
709
  const state = {
@@ -6590,6 +6659,7 @@ async function setupClient(args) {
6590
6659
  }
6591
6660
 
6592
6661
  async function onboard(args = []) {
6662
+ onboardRanThisProcess = true;
6593
6663
  const options = parseOptions(args);
6594
6664
  await showBanner();
6595
6665
  console.log("Мастер настройки iola-cli.");