@iola_adm/iola-cli 0.1.69 → 0.1.70
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 +29 -10
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1343,27 +1343,35 @@ function clearAgentInputArea(state = null) {
|
|
|
1343
1343
|
function startActivityIndicator(label = "работаю") {
|
|
1344
1344
|
const doneLabel = "готово";
|
|
1345
1345
|
if (!output.isTTY || process.env.NO_COLOR === "1") {
|
|
1346
|
-
output.write(`${label}
|
|
1346
|
+
output.write(`${formatActivityLine(label)}\n`);
|
|
1347
1347
|
const started = Date.now();
|
|
1348
1348
|
return () => {
|
|
1349
1349
|
const seconds = ((Date.now() - started) / 1000).toFixed(1);
|
|
1350
|
-
output.write(
|
|
1350
|
+
output.write(`${formatActivityLine(doneLabel, seconds)}\n`);
|
|
1351
1351
|
};
|
|
1352
1352
|
}
|
|
1353
1353
|
const started = Date.now();
|
|
1354
1354
|
const render = () => {
|
|
1355
1355
|
const seconds = ((Date.now() - started) / 1000).toFixed(1);
|
|
1356
|
-
output.write(`\r\x1b[2K${colorMuted(
|
|
1356
|
+
output.write(`\r\x1b[2K${colorMuted(formatActivityLine(label, seconds))}`);
|
|
1357
1357
|
};
|
|
1358
1358
|
render();
|
|
1359
1359
|
const timer = setInterval(render, 120);
|
|
1360
1360
|
return () => {
|
|
1361
1361
|
clearInterval(timer);
|
|
1362
1362
|
const seconds = ((Date.now() - started) / 1000).toFixed(1);
|
|
1363
|
-
output.write(`\r\x1b[2K${colorMuted(
|
|
1363
|
+
output.write(`\r\x1b[2K${colorMuted(formatActivityLine(doneLabel, seconds))}\n`);
|
|
1364
1364
|
};
|
|
1365
1365
|
}
|
|
1366
1366
|
|
|
1367
|
+
function formatActivityLine(label, seconds = null) {
|
|
1368
|
+
const columns = Math.max(60, Number(output.columns || 100));
|
|
1369
|
+
const middle = ` ${label}${seconds == null ? "" : ` ${seconds}s`} `;
|
|
1370
|
+
const leftWidth = Math.max(1, Math.floor((columns - visibleLength(middle)) / 3));
|
|
1371
|
+
const rightWidth = Math.max(1, columns - leftWidth - visibleLength(middle));
|
|
1372
|
+
return `${"─".repeat(leftWidth)}${middle}${"─".repeat(rightWidth)}`;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1367
1375
|
function suspendRawInputForCommand(stream) {
|
|
1368
1376
|
if (!stream.isTTY || !stream.isRaw) return () => {};
|
|
1369
1377
|
stream.setRawMode(false);
|
|
@@ -4085,12 +4093,15 @@ async function listAiModels(provider) {
|
|
|
4085
4093
|
}
|
|
4086
4094
|
|
|
4087
4095
|
const payload = await response.json();
|
|
4088
|
-
const
|
|
4096
|
+
const installed = (payload.models || []).map((model) => ({
|
|
4089
4097
|
id: model.name,
|
|
4090
4098
|
provider: "ollama",
|
|
4091
4099
|
note: model.modified_at ? `updated ${model.modified_at}` : "local",
|
|
4092
4100
|
}));
|
|
4093
|
-
|
|
4101
|
+
const installedIds = new Set(installed.map((model) => model.id));
|
|
4102
|
+
const recommended = getRecommendedOllamaModels("not installed")
|
|
4103
|
+
.filter((model) => !installedIds.has(model.id));
|
|
4104
|
+
return [...installed, ...recommended];
|
|
4094
4105
|
} catch {
|
|
4095
4106
|
return getRecommendedOllamaModels("recommended");
|
|
4096
4107
|
}
|
|
@@ -4145,10 +4156,12 @@ async function listAiModels(provider) {
|
|
|
4145
4156
|
|
|
4146
4157
|
function getRecommendedOllamaModels(notePrefix = "recommended") {
|
|
4147
4158
|
return [
|
|
4148
|
-
{ id: "
|
|
4149
|
-
{ id: "
|
|
4150
|
-
{ id: "
|
|
4151
|
-
{ id: "
|
|
4159
|
+
{ id: "qwen3:1.7b", provider: "ollama", note: `${notePrefix} recommended low RAM` },
|
|
4160
|
+
{ id: "qwen3:4b", provider: "ollama", note: `${notePrefix} recommended balanced` },
|
|
4161
|
+
{ id: "gemma3:1b", provider: "ollama", note: `${notePrefix} Gemma low RAM` },
|
|
4162
|
+
{ id: "gemma3:4b", provider: "ollama", note: `${notePrefix} Gemma balanced` },
|
|
4163
|
+
{ id: "llama3.2:3b", provider: "ollama", note: `${notePrefix} legacy fallback` },
|
|
4164
|
+
{ id: "llama3.2:1b", provider: "ollama", note: `${notePrefix} minimal fallback only` },
|
|
4152
4165
|
];
|
|
4153
4166
|
}
|
|
4154
4167
|
|
|
@@ -6567,7 +6580,10 @@ async function buildAiMessages(question, dataContext, history, options = {}, con
|
|
|
6567
6580
|
const system = [
|
|
6568
6581
|
"Ты терминальный AI-агент городского округа Йошкар-Ола.",
|
|
6569
6582
|
"Отвечай на русском языке естественно и по смыслу запроса пользователя.",
|
|
6583
|
+
"Не смешивай языки. Не выдумывай факты, географию и числа.",
|
|
6584
|
+
"Если пользователь просто здоровается, ответь коротким приветствием и спроси, чем помочь.",
|
|
6570
6585
|
hasDataContext ? "Используй только данные из переданного контекста открытых данных." : "Для обычного диалога отвечай как полноценный AI-ассистент, не перечисляй слои и возможности без запроса пользователя.",
|
|
6586
|
+
hasDataContext ? "" : "Не рассказывай сведения о Йошкар-Оле, школах или детских садах без прямого запроса и контекста данных.",
|
|
6571
6587
|
hasDataContext ? "Если в контексте нет нужных сведений, прямо напиши, что данных недостаточно." : "",
|
|
6572
6588
|
hasDataContext ? "Не выдумывай адреса, телефоны, лицензии и руководителей." : "",
|
|
6573
6589
|
hasDataContext ? "Если отвечаешь по конкретным организациям, укажи источник в конце: слой, название и ИНН." : "",
|
|
@@ -6673,6 +6689,9 @@ async function callOllama(config, messages) {
|
|
|
6673
6689
|
model: config.model || "llama3.2:1b",
|
|
6674
6690
|
messages,
|
|
6675
6691
|
stream: false,
|
|
6692
|
+
options: {
|
|
6693
|
+
temperature: Number(config.temperature ?? 0.1),
|
|
6694
|
+
},
|
|
6676
6695
|
}),
|
|
6677
6696
|
});
|
|
6678
6697
|
} catch {
|