@iola_adm/iola-cli 0.1.100 → 0.1.101
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 +225 -12
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { execFile, spawn } from "node:child_process";
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
4
|
import { appendFile, copyFile, cp, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { emitKeypressEvents } from "node:readline";
|
|
8
8
|
import readline from "node:readline/promises";
|
|
9
|
+
import { Readable } from "node:stream";
|
|
9
10
|
import { stdin as input, stdout as output } from "node:process";
|
|
10
11
|
import { DatabaseSync } from "node:sqlite";
|
|
11
12
|
import { fileURLToPath } from "node:url";
|
|
@@ -21,9 +22,11 @@ const LAST_GOOD_CONFIG_FILE = path.join(CONFIG_DIR, "config.last-good.json");
|
|
|
21
22
|
const SECRETS_FILE = path.join(CONFIG_DIR, "secrets.json");
|
|
22
23
|
const DB_FILE = path.join(CONFIG_DIR, "iola.db");
|
|
23
24
|
const DB_SCHEMA_VERSION = 8;
|
|
24
|
-
const IOLA_LOCAL_MODEL = "iola-router-
|
|
25
|
-
const IOLA_LOCAL_OLLAMA_MODEL =
|
|
25
|
+
const IOLA_LOCAL_MODEL = "iola-router:qwen3-1.7b-v4-q8";
|
|
26
|
+
const IOLA_LOCAL_OLLAMA_MODEL = IOLA_LOCAL_MODEL;
|
|
26
27
|
const IOLA_ROUTER_HF_REPO = process.env.IOLA_ROUTER_HF_REPO || "LMSerg/iola-1b-router-2026-05-28-merged";
|
|
28
|
+
const IOLA_ROUTER_GGUF_REPO = process.env.IOLA_ROUTER_GGUF_REPO || "LMSerg/iola-router-qwen3-1.7b-v4-gguf";
|
|
29
|
+
const IOLA_ROUTER_GGUF_FILE = process.env.IOLA_ROUTER_GGUF_FILE || "iola-router-qwen3-1.7b-v4-q8_0.gguf";
|
|
27
30
|
const IOLA_MODEL_DIR = path.join(CONFIG_DIR, "models", "router");
|
|
28
31
|
const IOLA_MODEL_RUNTIME_DIR = path.join(CONFIG_DIR, "model-runtime");
|
|
29
32
|
const IOLA_MODEL_RUNNER = path.resolve(__dirname, "iola_hf_runner.py");
|
|
@@ -127,7 +130,10 @@ const DEFAULT_AI_CONFIG = {
|
|
|
127
130
|
local: {
|
|
128
131
|
provider: "iola",
|
|
129
132
|
model: IOLA_LOCAL_MODEL,
|
|
130
|
-
|
|
133
|
+
runtime: "ollama",
|
|
134
|
+
baseUrl: "http://127.0.0.1:11434",
|
|
135
|
+
ggufRepo: IOLA_ROUTER_GGUF_REPO,
|
|
136
|
+
ggufFile: IOLA_ROUTER_GGUF_FILE,
|
|
131
137
|
modelDir: IOLA_MODEL_DIR,
|
|
132
138
|
},
|
|
133
139
|
openai: {
|
|
@@ -469,7 +475,12 @@ async function maybeRefreshIolaModelForCommand(command, args = []) {
|
|
|
469
475
|
const profile = config.ai.profiles?.[getActiveProfileName(config)];
|
|
470
476
|
if (profile?.provider !== "iola" && config.ai.provider !== "iola") return;
|
|
471
477
|
await ensureIolaModelFresh({
|
|
478
|
+
runtime: profile?.runtime,
|
|
472
479
|
repo: profile?.repo || IOLA_ROUTER_HF_REPO,
|
|
480
|
+
ggufRepo: profile?.ggufRepo,
|
|
481
|
+
ggufFile: profile?.ggufFile,
|
|
482
|
+
model: profile?.model,
|
|
483
|
+
baseUrl: profile?.baseUrl,
|
|
473
484
|
modelDir: profile?.modelDir || IOLA_MODEL_DIR,
|
|
474
485
|
quiet: true,
|
|
475
486
|
}).catch((error) => {
|
|
@@ -4503,7 +4514,11 @@ function buildProfileFromOptions(provider, options) {
|
|
|
4503
4514
|
}
|
|
4504
4515
|
|
|
4505
4516
|
if (provider === "iola") {
|
|
4517
|
+
profile.runtime = options.runtime || defaults.runtime || "ollama";
|
|
4518
|
+
profile.baseUrl = options["base-url"] || defaults.baseUrl || "http://127.0.0.1:11434";
|
|
4506
4519
|
profile.repo = options.repo || defaults.repo || IOLA_ROUTER_HF_REPO;
|
|
4520
|
+
profile.ggufRepo = options["gguf-repo"] || defaults.ggufRepo || IOLA_ROUTER_GGUF_REPO;
|
|
4521
|
+
profile.ggufFile = options["gguf-file"] || defaults.ggufFile || IOLA_ROUTER_GGUF_FILE;
|
|
4507
4522
|
profile.modelDir = options["model-dir"] || defaults.modelDir || IOLA_MODEL_DIR;
|
|
4508
4523
|
}
|
|
4509
4524
|
|
|
@@ -4692,7 +4707,7 @@ async function switchModelTarget(target, model) {
|
|
|
4692
4707
|
const config = await loadConfig();
|
|
4693
4708
|
const provider = target === "local" ? "iola" : target;
|
|
4694
4709
|
if (provider === "iola") {
|
|
4695
|
-
await ensureIolaModelFresh({ quiet: false });
|
|
4710
|
+
await ensureIolaModelFresh({ model, quiet: false });
|
|
4696
4711
|
}
|
|
4697
4712
|
if (provider === "ollama") {
|
|
4698
4713
|
const ready = await ensureOllamaModelAvailable(model, config);
|
|
@@ -6160,16 +6175,29 @@ async function setupOllama(args) {
|
|
|
6160
6175
|
async function setupIolaLocal(args) {
|
|
6161
6176
|
const options = parseOptions(args);
|
|
6162
6177
|
const repo = options.repo || IOLA_ROUTER_HF_REPO;
|
|
6178
|
+
const ggufRepo = options["gguf-repo"] || IOLA_ROUTER_GGUF_REPO;
|
|
6179
|
+
const ggufFile = options["gguf-file"] || IOLA_ROUTER_GGUF_FILE;
|
|
6163
6180
|
const modelDir = options["model-dir"] || IOLA_MODEL_DIR;
|
|
6164
6181
|
const profileName = options.name || "local";
|
|
6165
6182
|
const optional = Boolean(options.optional);
|
|
6183
|
+
const runtime = options.runtime || "ollama";
|
|
6184
|
+
const model = options.model || IOLA_LOCAL_MODEL;
|
|
6166
6185
|
|
|
6167
6186
|
if (optional && process.env.CI === "true") {
|
|
6168
6187
|
return;
|
|
6169
6188
|
}
|
|
6170
6189
|
|
|
6171
6190
|
try {
|
|
6172
|
-
await ensureIolaModelFresh({
|
|
6191
|
+
await ensureIolaModelFresh({
|
|
6192
|
+
runtime,
|
|
6193
|
+
repo,
|
|
6194
|
+
ggufRepo,
|
|
6195
|
+
ggufFile,
|
|
6196
|
+
modelDir,
|
|
6197
|
+
model,
|
|
6198
|
+
force: true,
|
|
6199
|
+
quiet: Boolean(options.quiet),
|
|
6200
|
+
});
|
|
6173
6201
|
} catch (error) {
|
|
6174
6202
|
if (!optional) throw error;
|
|
6175
6203
|
console.warn(`IOLA local model не установлена: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -6181,13 +6209,18 @@ async function setupIolaLocal(args) {
|
|
|
6181
6209
|
...config.ai,
|
|
6182
6210
|
activeProfile: profileName,
|
|
6183
6211
|
provider: "iola",
|
|
6184
|
-
model
|
|
6212
|
+
model,
|
|
6213
|
+
baseUrl: "http://127.0.0.1:11434",
|
|
6185
6214
|
profiles: {
|
|
6186
6215
|
...(config.ai.profiles || {}),
|
|
6187
6216
|
[profileName]: {
|
|
6188
6217
|
provider: "iola",
|
|
6189
|
-
model
|
|
6218
|
+
model,
|
|
6219
|
+
runtime,
|
|
6220
|
+
baseUrl: "http://127.0.0.1:11434",
|
|
6190
6221
|
repo,
|
|
6222
|
+
ggufRepo,
|
|
6223
|
+
ggufFile,
|
|
6191
6224
|
modelDir,
|
|
6192
6225
|
},
|
|
6193
6226
|
},
|
|
@@ -6197,9 +6230,9 @@ async function setupIolaLocal(args) {
|
|
|
6197
6230
|
if (options.quiet) return;
|
|
6198
6231
|
console.log("");
|
|
6199
6232
|
console.log("IOLA local mode готов:");
|
|
6200
|
-
console.log(` runtime: Python transformers/peft`);
|
|
6201
|
-
console.log(` model: ${
|
|
6202
|
-
console.log(` Hugging Face: ${repo}`);
|
|
6233
|
+
console.log(` runtime: ${runtime === "transformers" ? "Python transformers/peft" : "Ollama GGUF"}`);
|
|
6234
|
+
console.log(` model: ${model}`);
|
|
6235
|
+
console.log(` Hugging Face: ${runtime === "transformers" ? repo : ggufRepo}`);
|
|
6203
6236
|
console.log(` cache: ${modelDir}`);
|
|
6204
6237
|
console.log(" точные данные: https://apiiola.yasg.ru/api/v1/resolve-entity-field");
|
|
6205
6238
|
}
|
|
@@ -7457,6 +7490,28 @@ async function callAiProvider(config, messages) {
|
|
|
7457
7490
|
}
|
|
7458
7491
|
|
|
7459
7492
|
async function callIolaLocal(config, messages) {
|
|
7493
|
+
if ((config.runtime || "ollama") !== "transformers") {
|
|
7494
|
+
const model = config.model || IOLA_LOCAL_MODEL;
|
|
7495
|
+
await ensureIolaModelFresh({
|
|
7496
|
+
runtime: "ollama",
|
|
7497
|
+
model,
|
|
7498
|
+
baseUrl: config.baseUrl,
|
|
7499
|
+
modelDir: config.modelDir || IOLA_MODEL_DIR,
|
|
7500
|
+
ggufRepo: config.ggufRepo || IOLA_ROUTER_GGUF_REPO,
|
|
7501
|
+
ggufFile: config.ggufFile || IOLA_ROUTER_GGUF_FILE,
|
|
7502
|
+
quiet: true,
|
|
7503
|
+
});
|
|
7504
|
+
const routerMessages = withIolaRouterSystemPrompt(messages);
|
|
7505
|
+
return callOllama({
|
|
7506
|
+
...config,
|
|
7507
|
+
provider: "ollama",
|
|
7508
|
+
model,
|
|
7509
|
+
temperature: 0,
|
|
7510
|
+
numPredict: Number(config.numPredict || 128),
|
|
7511
|
+
qwenNoThink: true,
|
|
7512
|
+
}, routerMessages);
|
|
7513
|
+
}
|
|
7514
|
+
|
|
7460
7515
|
const runtime = await ensureIolaModelRuntime({ quiet: true });
|
|
7461
7516
|
const repo = config.repo || IOLA_ROUTER_HF_REPO;
|
|
7462
7517
|
const modelDir = config.modelDir || IOLA_MODEL_DIR;
|
|
@@ -7482,11 +7537,16 @@ async function callIolaLocal(config, messages) {
|
|
|
7482
7537
|
}
|
|
7483
7538
|
|
|
7484
7539
|
async function hasUsableIolaModel() {
|
|
7540
|
+
if (await hasOllamaModel(IOLA_LOCAL_MODEL)) return true;
|
|
7485
7541
|
const state = readConfigLayerSync(getIolaModelStateFile(IOLA_MODEL_DIR));
|
|
7486
|
-
return Boolean(state?.repo && state?.revision && existsSync(IOLA_MODEL_DIR));
|
|
7542
|
+
return Boolean(state?.runtime === "transformers" && state?.repo && state?.revision && existsSync(IOLA_MODEL_DIR));
|
|
7487
7543
|
}
|
|
7488
7544
|
|
|
7489
7545
|
async function ensureIolaModelFresh(options = {}) {
|
|
7546
|
+
if ((options.runtime || "ollama") !== "transformers") {
|
|
7547
|
+
return ensureIolaOllamaModelFresh(options);
|
|
7548
|
+
}
|
|
7549
|
+
|
|
7490
7550
|
const repo = options.repo || IOLA_ROUTER_HF_REPO;
|
|
7491
7551
|
const modelDir = options.modelDir || IOLA_MODEL_DIR;
|
|
7492
7552
|
await mkdir(modelDir, { recursive: true });
|
|
@@ -7526,6 +7586,142 @@ function getIolaModelStateFile(modelDir = IOLA_MODEL_DIR) {
|
|
|
7526
7586
|
return path.join(modelDir, "manifest.json");
|
|
7527
7587
|
}
|
|
7528
7588
|
|
|
7589
|
+
async function ensureIolaOllamaModelFresh(options = {}) {
|
|
7590
|
+
const model = options.model || IOLA_LOCAL_MODEL;
|
|
7591
|
+
const modelDir = options.modelDir || IOLA_MODEL_DIR;
|
|
7592
|
+
const repo = options.ggufRepo || IOLA_ROUTER_GGUF_REPO;
|
|
7593
|
+
const ggufFile = options.ggufFile || IOLA_ROUTER_GGUF_FILE;
|
|
7594
|
+
const baseUrl = options.baseUrl || "http://127.0.0.1:11434";
|
|
7595
|
+
const ollamaCommand = await resolveOllamaCommand();
|
|
7596
|
+
if (!ollamaCommand) {
|
|
7597
|
+
throw new Error("Ollama не найден. Установите Ollama и повторите: iola ai setup iola --yes");
|
|
7598
|
+
}
|
|
7599
|
+
|
|
7600
|
+
await mkdir(modelDir, { recursive: true });
|
|
7601
|
+
const stateFile = getIolaModelStateFile(modelDir);
|
|
7602
|
+
const state = readConfigLayerSync(stateFile) || {};
|
|
7603
|
+
const remote = await getRemoteIolaModelRevision(repo).catch(() => null);
|
|
7604
|
+
const installed = await hasOllamaModel(model, baseUrl);
|
|
7605
|
+
if (installed && !options.force && (!state.revision || state.runtime !== "ollama" || state.model !== model || state.repo !== repo)) {
|
|
7606
|
+
const nextState = {
|
|
7607
|
+
repo,
|
|
7608
|
+
ggufFile,
|
|
7609
|
+
revision: remote?.sha || state.revision || `local-${Date.now()}`,
|
|
7610
|
+
installedAt: state.installedAt || new Date().toISOString(),
|
|
7611
|
+
runtime: "ollama",
|
|
7612
|
+
model,
|
|
7613
|
+
};
|
|
7614
|
+
await writeFile(stateFile, `${JSON.stringify(nextState, null, 2)}\n`, "utf8");
|
|
7615
|
+
return nextState;
|
|
7616
|
+
}
|
|
7617
|
+
const stale = options.force || !installed || state.runtime !== "ollama" || state.model !== model || state.repo !== repo || !state.revision || (remote?.sha && remote.sha !== state.revision);
|
|
7618
|
+
if (!stale) return state;
|
|
7619
|
+
|
|
7620
|
+
if (!options.quiet) {
|
|
7621
|
+
const reason = installed ? "обновляю" : "устанавливаю";
|
|
7622
|
+
console.log(`IOLA local model: ${reason} ${model}`);
|
|
7623
|
+
console.log(`Источник GGUF: https://huggingface.co/${repo}`);
|
|
7624
|
+
}
|
|
7625
|
+
|
|
7626
|
+
const ggufPath = path.join(modelDir, ggufFile);
|
|
7627
|
+
const modelfilePath = path.join(modelDir, "Modelfile");
|
|
7628
|
+
const url = `https://huggingface.co/${repo}/resolve/main/${encodeURIComponent(ggufFile)}`;
|
|
7629
|
+
if (options.force || !existsSync(ggufPath)) {
|
|
7630
|
+
await downloadFile(url, ggufPath, { quiet: options.quiet });
|
|
7631
|
+
}
|
|
7632
|
+
|
|
7633
|
+
await writeFile(modelfilePath, buildIolaOllamaModelfile(ggufPath), "utf8");
|
|
7634
|
+
await runCommand(ollamaCommand, ["create", model, "-f", modelfilePath], { inherit: !options.quiet });
|
|
7635
|
+
|
|
7636
|
+
const nextState = {
|
|
7637
|
+
repo,
|
|
7638
|
+
ggufFile,
|
|
7639
|
+
revision: remote?.sha || state.revision || `local-${Date.now()}`,
|
|
7640
|
+
installedAt: new Date().toISOString(),
|
|
7641
|
+
runtime: "ollama",
|
|
7642
|
+
model,
|
|
7643
|
+
};
|
|
7644
|
+
await writeFile(stateFile, `${JSON.stringify(nextState, null, 2)}\n`, "utf8");
|
|
7645
|
+
return nextState;
|
|
7646
|
+
}
|
|
7647
|
+
|
|
7648
|
+
async function hasOllamaModel(model, baseUrl = "http://127.0.0.1:11434") {
|
|
7649
|
+
try {
|
|
7650
|
+
const response = await fetch(`${baseUrl}/api/tags`, { signal: AbortSignal.timeout(2000) });
|
|
7651
|
+
if (!response.ok) return false;
|
|
7652
|
+
const payload = await response.json();
|
|
7653
|
+
return (payload.models || []).some((item) => item.name === model);
|
|
7654
|
+
} catch {
|
|
7655
|
+
return false;
|
|
7656
|
+
}
|
|
7657
|
+
}
|
|
7658
|
+
|
|
7659
|
+
async function downloadFile(url, targetPath, options = {}) {
|
|
7660
|
+
const response = await fetch(url, {
|
|
7661
|
+
headers: { "user-agent": "@iola_adm/iola-cli" },
|
|
7662
|
+
});
|
|
7663
|
+
if (!response.ok || !response.body) {
|
|
7664
|
+
throw new Error(`Не удалось скачать модель: ${response.status} ${response.statusText} (${url})`);
|
|
7665
|
+
}
|
|
7666
|
+
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
7667
|
+
if (!options.quiet) console.log(`Скачиваю модель: ${targetPath}`);
|
|
7668
|
+
await new Promise((resolve, reject) => {
|
|
7669
|
+
const file = createWriteStream(targetPath);
|
|
7670
|
+
Readable.fromWeb(response.body).pipe(file);
|
|
7671
|
+
file.on("finish", resolve);
|
|
7672
|
+
file.on("error", reject);
|
|
7673
|
+
});
|
|
7674
|
+
}
|
|
7675
|
+
|
|
7676
|
+
function buildIolaOllamaModelfile(ggufPath) {
|
|
7677
|
+
return `FROM ${ggufPath}
|
|
7678
|
+
|
|
7679
|
+
TEMPLATE """{{- if .System }}<|im_start|>system
|
|
7680
|
+
{{ .System }}<|im_end|>
|
|
7681
|
+
{{ end -}}
|
|
7682
|
+
{{- range .Messages }}
|
|
7683
|
+
{{- if eq .Role "user" }}<|im_start|>user
|
|
7684
|
+
{{ .Content }}<|im_end|>
|
|
7685
|
+
{{ else if eq .Role "assistant" }}<|im_start|>assistant
|
|
7686
|
+
{{ .Content }}<|im_end|>
|
|
7687
|
+
{{ end -}}
|
|
7688
|
+
{{ end -}}
|
|
7689
|
+
<|im_start|>assistant
|
|
7690
|
+
"""
|
|
7691
|
+
|
|
7692
|
+
PARAMETER temperature 0
|
|
7693
|
+
PARAMETER repeat_penalty 1
|
|
7694
|
+
PARAMETER stop <|im_start|>
|
|
7695
|
+
PARAMETER stop <|im_end|>
|
|
7696
|
+
`;
|
|
7697
|
+
}
|
|
7698
|
+
|
|
7699
|
+
function withIolaRouterSystemPrompt(messages = []) {
|
|
7700
|
+
const normalized = messages.map((message) => ({ ...message }));
|
|
7701
|
+
const hasSystem = normalized.some((message) => message.role === "system");
|
|
7702
|
+
const withNoThink = normalized.map((message, index) => {
|
|
7703
|
+
if (message.role === "user" && index === normalized.findLastIndex((item) => item.role === "user")) {
|
|
7704
|
+
return { ...message, content: `${message.content}\n/no_think` };
|
|
7705
|
+
}
|
|
7706
|
+
return message;
|
|
7707
|
+
});
|
|
7708
|
+
return hasSystem ? withNoThink : [{ role: "system", content: IOLA_ROUTER_SYSTEM_PROMPT }, ...withNoThink];
|
|
7709
|
+
}
|
|
7710
|
+
|
|
7711
|
+
const IOLA_ROUTER_SYSTEM_PROMPT = `You are the IOLA CLI router for public open data of Yoshkar-Ola.
|
|
7712
|
+
Return only valid JSON. No markdown, no prose.
|
|
7713
|
+
Allowed actions:
|
|
7714
|
+
- {"action":"tool_call","tool":"resolve_entity_field","args":{"layer":"schools|kindergartens","entity_number":1,"field":"address|phone|email|website|inn|head|license_status"}}
|
|
7715
|
+
- {"action":"tool_call","tool":"search_entities","args":{"layer":"schools|kindergartens","query":"..."}}
|
|
7716
|
+
- {"action":"tool_call","tool":"rag_search","args":{"query":"...","collections":["city_history","official_documents"]}}
|
|
7717
|
+
- {"action":"tool_call","tool":"get_current_official","args":{"jurisdiction":"yoshkar_ola","office_query":"..."}}
|
|
7718
|
+
- {"action":"tool_call","tool":"get_official_by_date","args":{"jurisdiction":"yoshkar_ola","office_query":"...","date":"YYYY or date"}}
|
|
7719
|
+
- {"action":"clarify","question":"..."}
|
|
7720
|
+
- {"action":"refuse","reason":"field_not_public"}
|
|
7721
|
+
- {"action":"direct_answer","answer":"..."}
|
|
7722
|
+
Never invent current officials, salaries, private data, addresses, phones, websites, heads, or license statuses.
|
|
7723
|
+
Use tool calls for public entity data. Use refuse for non-public fields.`;
|
|
7724
|
+
|
|
7529
7725
|
async function ensureIolaModelRuntime(options = {}) {
|
|
7530
7726
|
const python = await getIolaRuntimePython();
|
|
7531
7727
|
if (python && await checkIolaPythonDeps(python)) return { python };
|
|
@@ -7652,8 +7848,10 @@ async function callOllama(config, messages) {
|
|
|
7652
7848
|
model: config.model || "llama3.2:1b",
|
|
7653
7849
|
messages,
|
|
7654
7850
|
stream: false,
|
|
7851
|
+
think: config.qwenNoThink ? false : undefined,
|
|
7655
7852
|
options: {
|
|
7656
7853
|
temperature: Number(config.temperature ?? 0.1),
|
|
7854
|
+
num_predict: config.numPredict ? Number(config.numPredict) : undefined,
|
|
7657
7855
|
},
|
|
7658
7856
|
}),
|
|
7659
7857
|
});
|
|
@@ -10027,6 +10225,21 @@ function sanitizeConfig(config) {
|
|
|
10027
10225
|
if (Array.isArray(next.skills?.enabled) && next.skills.enabled.includes("open-data") && !next.skills.enabled.includes("education")) {
|
|
10028
10226
|
next.skills.enabled = ["education", ...next.skills.enabled];
|
|
10029
10227
|
}
|
|
10228
|
+
const localProfile = next.ai?.profiles?.local;
|
|
10229
|
+
if (localProfile?.provider === "iola") {
|
|
10230
|
+
if (!localProfile.runtime || localProfile.model === "iola-router-1b") {
|
|
10231
|
+
localProfile.runtime = "ollama";
|
|
10232
|
+
localProfile.model = IOLA_LOCAL_MODEL;
|
|
10233
|
+
localProfile.baseUrl = localProfile.baseUrl || "http://127.0.0.1:11434";
|
|
10234
|
+
localProfile.ggufRepo = localProfile.ggufRepo || IOLA_ROUTER_GGUF_REPO;
|
|
10235
|
+
localProfile.ggufFile = localProfile.ggufFile || IOLA_ROUTER_GGUF_FILE;
|
|
10236
|
+
localProfile.modelDir = localProfile.modelDir || IOLA_MODEL_DIR;
|
|
10237
|
+
}
|
|
10238
|
+
}
|
|
10239
|
+
if (next.ai?.activeProfile === "local" && next.ai.provider === "iola" && next.ai.model === "iola-router-1b") {
|
|
10240
|
+
next.ai.model = IOLA_LOCAL_MODEL;
|
|
10241
|
+
next.ai.baseUrl = next.ai.baseUrl || "http://127.0.0.1:11434";
|
|
10242
|
+
}
|
|
10030
10243
|
return next;
|
|
10031
10244
|
}
|
|
10032
10245
|
|