@iola_adm/iola-cli 0.1.48 → 0.1.50
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 +1 -1
- package/src/cli.js +53 -17
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -647,7 +647,13 @@ async function ensureAgentAiReady() {
|
|
|
647
647
|
if (readiness.anyReady) {
|
|
648
648
|
const fallback = getFallbackAiProfile(readiness);
|
|
649
649
|
if (fallback) {
|
|
650
|
-
|
|
650
|
+
const shouldSwitch = await confirm(`Активный AI-профиль ${readiness.activeProfile} (${readiness.activeProvider}) недоступен, найден ${fallback.name} (${fallback.provider}). Переключить активный профиль на ${fallback.name}? [Y/n] `);
|
|
651
|
+
if (shouldSwitch) {
|
|
652
|
+
await setActiveAiProfile(fallback.name, fallback);
|
|
653
|
+
console.log(`Активный AI-профиль: ${fallback.name} (${fallback.provider}, ${fallback.model || "-"})`);
|
|
654
|
+
} else {
|
|
655
|
+
console.log(`Для текстовых запросов будет использован доступный профиль ${fallback.name} (${fallback.provider}).`);
|
|
656
|
+
}
|
|
651
657
|
return readiness;
|
|
652
658
|
}
|
|
653
659
|
}
|
|
@@ -744,7 +750,7 @@ async function hasUsableCodexAuth() {
|
|
|
744
750
|
}
|
|
745
751
|
|
|
746
752
|
async function startAgentReadline() {
|
|
747
|
-
const rl = readline.createInterface({ input, output, prompt: "
|
|
753
|
+
const rl = readline.createInterface({ input, output, prompt: "> " });
|
|
748
754
|
const state = {
|
|
749
755
|
history: [],
|
|
750
756
|
};
|
|
@@ -835,7 +841,7 @@ async function startAgentRawInput() {
|
|
|
835
841
|
render();
|
|
836
842
|
continue;
|
|
837
843
|
}
|
|
838
|
-
output.write(
|
|
844
|
+
output.write(`> ${line}\n`);
|
|
839
845
|
try {
|
|
840
846
|
const shouldExit = await handleAgentLine(line, state);
|
|
841
847
|
if (shouldExit) break;
|
|
@@ -1285,7 +1291,7 @@ function currentSlashMatches(state) {
|
|
|
1285
1291
|
|
|
1286
1292
|
function renderAgentInput(state) {
|
|
1287
1293
|
clearAgentInputArea(state);
|
|
1288
|
-
const prompt = "
|
|
1294
|
+
const prompt = "> ";
|
|
1289
1295
|
const lines = state.buffer.split("\n");
|
|
1290
1296
|
const inputLines = [`${prompt}${lines[0] || ""}`, ...lines.slice(1).map((line) => ` ${line}`)];
|
|
1291
1297
|
const cwdLine = colorMuted(` ${process.cwd()}`);
|
|
@@ -4384,6 +4390,13 @@ async function useAiProfile(name) {
|
|
|
4384
4390
|
throw new Error(`AI-профиль не найден: ${name}`);
|
|
4385
4391
|
}
|
|
4386
4392
|
|
|
4393
|
+
await setActiveAiProfile(name, profile, config);
|
|
4394
|
+
|
|
4395
|
+
console.log(`Активный AI-профиль: ${name} (${profile.provider}, ${profile.model || "-"})`);
|
|
4396
|
+
}
|
|
4397
|
+
|
|
4398
|
+
async function setActiveAiProfile(name, profile, loadedConfig = null) {
|
|
4399
|
+
const config = loadedConfig || await loadConfig();
|
|
4387
4400
|
await saveConfig({
|
|
4388
4401
|
ai: {
|
|
4389
4402
|
...config.ai,
|
|
@@ -4393,8 +4406,6 @@ async function useAiProfile(name) {
|
|
|
4393
4406
|
baseUrl: profile.baseUrl || config.ai.baseUrl,
|
|
4394
4407
|
},
|
|
4395
4408
|
});
|
|
4396
|
-
|
|
4397
|
-
console.log(`Активный AI-профиль: ${name} (${profile.provider}, ${profile.model || "-"})`);
|
|
4398
4409
|
}
|
|
4399
4410
|
|
|
4400
4411
|
async function deleteAiProfile(name) {
|
|
@@ -5893,7 +5904,8 @@ async function aiAsk(args, context = {}) {
|
|
|
5893
5904
|
return localToolAsk(question, providerConfig, options);
|
|
5894
5905
|
}
|
|
5895
5906
|
applyRuntimeConfig(providerConfig, options.config);
|
|
5896
|
-
const
|
|
5907
|
+
const useDataContext = !options.bare && shouldUseDataContext(question, options);
|
|
5908
|
+
const dataContext = useDataContext ? await buildDataContext(question) : emptyDataContext(question);
|
|
5897
5909
|
emitEvent(options, "context_loaded", { schools: dataContext.schools.length, kindergartens: dataContext.kindergartens.length });
|
|
5898
5910
|
const historyEnabled = !options.bare && !options["no-history"] && isFeatureEnabled("sqlite-history");
|
|
5899
5911
|
const sessionId = historyEnabled && isFeatureEnabled("sessions") ? ensureSessionForAsk(options, providerConfig, question) : null;
|
|
@@ -6295,6 +6307,29 @@ async function buildDataContext(question) {
|
|
|
6295
6307
|
};
|
|
6296
6308
|
}
|
|
6297
6309
|
|
|
6310
|
+
function emptyDataContext(question) {
|
|
6311
|
+
return {
|
|
6312
|
+
enabled: false,
|
|
6313
|
+
layers: [],
|
|
6314
|
+
query: {
|
|
6315
|
+
text: question,
|
|
6316
|
+
terms: [],
|
|
6317
|
+
patterns: { numbers: [], inns: [], streets: [], targetLayers: [] },
|
|
6318
|
+
},
|
|
6319
|
+
schools: [],
|
|
6320
|
+
kindergartens: [],
|
|
6321
|
+
};
|
|
6322
|
+
}
|
|
6323
|
+
|
|
6324
|
+
function shouldUseDataContext(question, options = {}) {
|
|
6325
|
+
if (options.tools || options.files || options.schema || options.output) return true;
|
|
6326
|
+
const normalized = question.toLocaleLowerCase("ru-RU").trim();
|
|
6327
|
+
if (/^(привет|здравствуй|здравствуйте|добрый день|доброе утро|добрый вечер|hi|hello|hey)[!.?\s]*$/iu.test(normalized)) return false;
|
|
6328
|
+
if (/^(спасибо|благодарю|ок|окей|понял|поняла|ясно|хорошо|да|нет)[!.?\s]*$/iu.test(normalized)) return false;
|
|
6329
|
+
if (normalized.length <= 24 && /^(как дела|что нового|ты тут|ты здесь|кто ты)[?.!\s]*$/iu.test(normalized)) return false;
|
|
6330
|
+
return /\b(школ|сад|детсад|детский сад|лицей|гимнази|инн|адрес|телефон|почт|email|сайт|лиценз|руководител|директор|слой|слои|данн|отчет|отчёт|выгруз|csv|json|найди|покажи|список|карточк|организац|учрежден|йошкар|ола|петрова|строител|советск|первомайск)\b/iu.test(normalized);
|
|
6331
|
+
}
|
|
6332
|
+
|
|
6298
6333
|
function extractSearchTerms(question) {
|
|
6299
6334
|
const normalized = question
|
|
6300
6335
|
.toLocaleLowerCase("ru-RU")
|
|
@@ -6391,13 +6426,14 @@ async function buildAiMessages(question, dataContext, history, options = {}, con
|
|
|
6391
6426
|
const memoryText = options.bare ? "" : buildMemoryText();
|
|
6392
6427
|
const projectContext = options.bare ? "" : await buildProjectContextText();
|
|
6393
6428
|
const skillsText = options.bare ? "" : await buildSkillsText(config);
|
|
6429
|
+
const hasDataContext = dataContext.enabled !== false;
|
|
6394
6430
|
const system = [
|
|
6395
|
-
"Ты терминальный AI
|
|
6396
|
-
"Отвечай на русском
|
|
6397
|
-
"Используй только данные из переданного
|
|
6398
|
-
"Если в контексте нет нужных сведений, прямо напиши, что данных недостаточно.",
|
|
6399
|
-
"Не выдумывай адреса, телефоны, лицензии и руководителей.",
|
|
6400
|
-
"Если отвечаешь по конкретным организациям, укажи источник в конце: слой, название и ИНН.",
|
|
6431
|
+
"Ты терминальный AI-агент городского округа Йошкар-Ола.",
|
|
6432
|
+
"Отвечай на русском языке естественно и по смыслу запроса пользователя.",
|
|
6433
|
+
hasDataContext ? "Используй только данные из переданного контекста открытых данных." : "Для обычного диалога отвечай как полноценный AI-ассистент, не перечисляй слои и возможности без запроса пользователя.",
|
|
6434
|
+
hasDataContext ? "Если в контексте нет нужных сведений, прямо напиши, что данных недостаточно." : "",
|
|
6435
|
+
hasDataContext ? "Не выдумывай адреса, телефоны, лицензии и руководителей." : "",
|
|
6436
|
+
hasDataContext ? "Если отвечаешь по конкретным организациям, укажи источник в конце: слой, название и ИНН." : "",
|
|
6401
6437
|
options.schema === "json" ? "Верни валидный JSON без markdown-обертки." : "",
|
|
6402
6438
|
options.schema === "table" ? "Если уместно, верни ответ в виде markdown-таблицы." : "",
|
|
6403
6439
|
memoryText ? `Учитывай пользовательскую память:\n${memoryText}` : "",
|
|
@@ -6407,14 +6443,14 @@ async function buildAiMessages(question, dataContext, history, options = {}, con
|
|
|
6407
6443
|
].filter(Boolean).join(" ");
|
|
6408
6444
|
const contextText = JSON.stringify(dataContext, null, 2);
|
|
6409
6445
|
const recentHistory = history.slice(-6);
|
|
6446
|
+
const userContent = hasDataContext
|
|
6447
|
+
? `Контекст открытых данных городского округа "Город Йошкар-Ола":\n${contextText}\n\nКраткие источники контекста:\n${sourceLines}\n\nВопрос пользователя: ${question}`
|
|
6448
|
+
: question;
|
|
6410
6449
|
|
|
6411
6450
|
return [
|
|
6412
6451
|
{ role: "system", content: system },
|
|
6413
6452
|
...recentHistory,
|
|
6414
|
-
{
|
|
6415
|
-
role: "user",
|
|
6416
|
-
content: `Контекст открытых данных городского округа "Город Йошкар-Ола":\n${contextText}\n\nКраткие источники контекста:\n${sourceLines}\n\nВопрос пользователя: ${question}`,
|
|
6417
|
-
},
|
|
6453
|
+
{ role: "user", content: userContent },
|
|
6418
6454
|
];
|
|
6419
6455
|
}
|
|
6420
6456
|
|