@iola_adm/iola-cli 0.1.46 → 0.1.48
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
package/src/cli.js
CHANGED
|
@@ -644,6 +644,14 @@ async function ensureAgentAiReady() {
|
|
|
644
644
|
const readiness = await getAiReadiness();
|
|
645
645
|
if (readiness.ready) return readiness;
|
|
646
646
|
|
|
647
|
+
if (readiness.anyReady) {
|
|
648
|
+
const fallback = getFallbackAiProfile(readiness);
|
|
649
|
+
if (fallback) {
|
|
650
|
+
console.log(`Активный AI-профиль ${readiness.activeProfile} (${readiness.activeProvider}) недоступен. Для текстовых запросов будет использован доступный профиль ${fallback.name} (${fallback.provider}).`);
|
|
651
|
+
return readiness;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
647
655
|
if (!input.isTTY || !output.isTTY) {
|
|
648
656
|
console.log("AI-провайдер не настроен. Для настройки запустите: iola wizard");
|
|
649
657
|
return readiness;
|
|
@@ -655,7 +663,7 @@ async function ensureAgentAiReady() {
|
|
|
655
663
|
return readiness;
|
|
656
664
|
}
|
|
657
665
|
|
|
658
|
-
console.log(
|
|
666
|
+
console.log(`AI-провайдер не настроен: активный профиль ${readiness.activeProfile} (${readiness.activeProvider}) недоступен.`);
|
|
659
667
|
console.log("Сейчас откроется мастер настройки. Уже существующие настройки не будут сброшены.");
|
|
660
668
|
console.log("");
|
|
661
669
|
await onboard([]);
|
|
@@ -670,6 +678,13 @@ async function ensureAgentAiReady() {
|
|
|
670
678
|
}
|
|
671
679
|
|
|
672
680
|
async function getAiReadiness() {
|
|
681
|
+
const config = await loadConfig();
|
|
682
|
+
const activeProfileName = getActiveProfileName(config);
|
|
683
|
+
const activeProfile = config.ai.profiles?.[activeProfileName] || {
|
|
684
|
+
provider: config.ai.provider,
|
|
685
|
+
model: config.ai.model,
|
|
686
|
+
baseUrl: config.ai.baseUrl,
|
|
687
|
+
};
|
|
673
688
|
const [secrets, ollama, codex] = await Promise.all([
|
|
674
689
|
loadSecrets(),
|
|
675
690
|
hasUsableOllamaModel(),
|
|
@@ -677,8 +692,19 @@ async function getAiReadiness() {
|
|
|
677
692
|
]);
|
|
678
693
|
const openai = Boolean(process.env.OPENAI_API_KEY || secrets.openai?.apiKey);
|
|
679
694
|
const openrouter = Boolean(process.env.OPENROUTER_API_KEY || secrets.openrouter?.apiKey);
|
|
695
|
+
const providerReady = {
|
|
696
|
+
ollama,
|
|
697
|
+
openai,
|
|
698
|
+
openrouter,
|
|
699
|
+
codex,
|
|
700
|
+
};
|
|
680
701
|
return {
|
|
681
|
-
ready: Boolean(
|
|
702
|
+
ready: Boolean(providerReady[activeProfile.provider]),
|
|
703
|
+
activeProfile: activeProfileName,
|
|
704
|
+
activeProvider: activeProfile.provider || "-",
|
|
705
|
+
activeModel: activeProfile.model || "-",
|
|
706
|
+
anyReady: Boolean(ollama || openai || openrouter || codex),
|
|
707
|
+
profiles: config.ai.profiles || {},
|
|
682
708
|
ollama,
|
|
683
709
|
openai,
|
|
684
710
|
openrouter,
|
|
@@ -686,6 +712,16 @@ async function getAiReadiness() {
|
|
|
686
712
|
};
|
|
687
713
|
}
|
|
688
714
|
|
|
715
|
+
function getFallbackAiProfile(readiness) {
|
|
716
|
+
const priority = ["openai", "openrouter", "codex", "ollama"];
|
|
717
|
+
for (const provider of priority) {
|
|
718
|
+
if (!readiness[provider]) continue;
|
|
719
|
+
const entry = Object.entries(readiness.profiles || {}).find(([, profile]) => profile.provider === provider);
|
|
720
|
+
if (entry) return { name: entry[0], ...entry[1] };
|
|
721
|
+
}
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
|
|
689
725
|
async function hasUsableOllamaModel() {
|
|
690
726
|
try {
|
|
691
727
|
const config = await loadConfig();
|
|
@@ -5849,7 +5885,7 @@ async function aiAsk(args, context = {}) {
|
|
|
5849
5885
|
}
|
|
5850
5886
|
|
|
5851
5887
|
const config = await loadConfig();
|
|
5852
|
-
const providerConfig =
|
|
5888
|
+
const providerConfig = await resolveUsableAiProfile(config, options);
|
|
5853
5889
|
if (providerConfig.provider === "codex") await assertPermission("codex");
|
|
5854
5890
|
if (providerConfig.provider !== "ollama") await assertPermission("externalAi");
|
|
5855
5891
|
if (options["stream-json"]) options.events = true;
|
|
@@ -5911,6 +5947,33 @@ async function aiAsk(args, context = {}) {
|
|
|
5911
5947
|
return answer;
|
|
5912
5948
|
}
|
|
5913
5949
|
|
|
5950
|
+
async function resolveUsableAiProfile(config, options = {}) {
|
|
5951
|
+
const explicit = Boolean(options.profile || options.provider);
|
|
5952
|
+
const providerConfig = resolveAiProfile(config, options);
|
|
5953
|
+
if (explicit) return providerConfig;
|
|
5954
|
+
|
|
5955
|
+
const readiness = await getAiReadiness();
|
|
5956
|
+
if (isProviderReady(providerConfig.provider, readiness)) return providerConfig;
|
|
5957
|
+
|
|
5958
|
+
const fallback = getFallbackAiProfile(readiness);
|
|
5959
|
+
if (!fallback) return providerConfig;
|
|
5960
|
+
|
|
5961
|
+
if (!options.quiet) {
|
|
5962
|
+
console.log(`Активный AI-профиль ${providerConfig.name} (${providerConfig.provider}) недоступен. Использую ${fallback.name} (${fallback.provider}).`);
|
|
5963
|
+
}
|
|
5964
|
+
|
|
5965
|
+
return {
|
|
5966
|
+
name: fallback.name,
|
|
5967
|
+
...fallback,
|
|
5968
|
+
model: fallback.model || providerConfig.model,
|
|
5969
|
+
baseUrl: fallback.baseUrl || providerConfig.baseUrl,
|
|
5970
|
+
};
|
|
5971
|
+
}
|
|
5972
|
+
|
|
5973
|
+
function isProviderReady(provider, readiness) {
|
|
5974
|
+
return Boolean(readiness?.[provider]);
|
|
5975
|
+
}
|
|
5976
|
+
|
|
5914
5977
|
function resolveAiProfile(config, options = {}) {
|
|
5915
5978
|
const profileName = options.profile || (options.provider && config.ai.profiles?.[options.provider]
|
|
5916
5979
|
? options.provider
|
|
@@ -6,19 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Согласие пользователя
|
|
8
8
|
|
|
9
|
-
Перед входом CLI показывает текст
|
|
10
|
-
|
|
11
|
-
```text
|
|
12
|
-
Вы подключаете личную учетную запись Госуслуг к локальному CLI-агенту iola-cli на этом компьютере.
|
|
13
|
-
|
|
14
|
-
Нажимая "Да", вы подтверждаете, что:
|
|
15
|
-
- используете собственную учетную запись Госуслуг;
|
|
16
|
-
- понимаете, что все действия, выполненные через CLI-агента после подключения, считаются действиями владельца этой учетной записи;
|
|
17
|
-
- разрешаете iola-cli локально сохранить данные доступа, необходимые для повторного входа или выполнения запросов от вашего имени;
|
|
18
|
-
- понимаете, что данные доступа хранятся только на этом компьютере в локальном хранилище пользователя и не передаются разработчикам CLI, администрации города или третьим лицам;
|
|
19
|
-
- обязуетесь не подключать чужие учетные записи и не передавать локальные файлы доступа другим лицам;
|
|
20
|
-
- понимаете, что перед юридически значимыми действиями, отправкой заявлений, оплатой, подписанием или изменением персональных данных CLI должен запросить отдельное подтверждение.
|
|
21
|
-
```
|
|
9
|
+
Перед входом CLI показывает текст согласия в терминале. В wiki он не дублируется, чтобы пользователь видел актуальную формулировку именно в установленной версии CLI.
|
|
22
10
|
|
|
23
11
|
Посмотреть текст:
|
|
24
12
|
|