@iola_adm/iola-cli 0.1.25 → 0.1.26
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/README.md +7 -0
- package/package.json +1 -1
- package/src/cli.js +515 -44
- package/wiki/Home.md +1 -0
- package/wiki//320/232/320/276/320/274/320/260/320/275/320/264/321/213.md +6 -0
- package/wiki//320/240/320/260/320/261/320/276/321/207/320/260/321/217-/321/201/321/200/320/265/320/264/320/260-/320/260/320/263/320/265/320/275/321/202/320/260.md +67 -0
package/README.md
CHANGED
|
@@ -54,6 +54,10 @@ iola skills list
|
|
|
54
54
|
iola tools toolsets
|
|
55
55
|
iola files mode read-only
|
|
56
56
|
iola files tree .
|
|
57
|
+
iola policy use analyst
|
|
58
|
+
iola tasks list
|
|
59
|
+
iola artifacts list
|
|
60
|
+
iola trace last
|
|
57
61
|
iola context init
|
|
58
62
|
iola cron list
|
|
59
63
|
iola daemon status
|
|
@@ -82,6 +86,7 @@ iola version --check
|
|
|
82
86
|
- [Локальный инструментальный агент](https://github.com/adm-iola/iola-cli/wiki/Локальный-инструментальный-агент)
|
|
83
87
|
- [Skills и toolsets](https://github.com/adm-iola/iola-cli/wiki/Skills-и-toolsets)
|
|
84
88
|
- [Локальные файлы](https://github.com/adm-iola/iola-cli/wiki/Локальные-файлы)
|
|
89
|
+
- [Рабочая среда агента](https://github.com/adm-iola/iola-cli/wiki/Рабочая-среда-агента)
|
|
85
90
|
- [Daemon, RPC и cron](https://github.com/adm-iola/iola-cli/wiki/Daemon-RPC-и-cron)
|
|
86
91
|
- [Контекст и память](https://github.com/adm-iola/iola-cli/wiki/Контекст-и-память)
|
|
87
92
|
- [Команды](https://github.com/adm-iola/iola-cli/wiki/Команды)
|
|
@@ -95,6 +100,8 @@ iola version --check
|
|
|
95
100
|
- локальный tool-agent для слабых моделей;
|
|
96
101
|
- skills, toolsets, permissions, memory, hooks и готовые agents;
|
|
97
102
|
- управляемые локальные файловые операции с режимами `locked`, `read-only`, `workspace-write`, `full-access`;
|
|
103
|
+
- планы выполнения, traces, tasks, artifacts, snapshots и policy-профили;
|
|
104
|
+
- экспорт отчетов в Excel/Word-совместимые файлы;
|
|
98
105
|
- cron-задачи, локальный daemon и RPC для автоматизаций;
|
|
99
106
|
- контекстные файлы `IOLA.md` и `.iola/context.md`;
|
|
100
107
|
- интеграция с публичным MCP-сервером Йошкар-Олы.
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
|
-
import { appendFile, copyFile, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
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 readline from "node:readline/promises";
|
|
@@ -17,7 +17,7 @@ const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
|
17
17
|
const LAST_GOOD_CONFIG_FILE = path.join(CONFIG_DIR, "config.last-good.json");
|
|
18
18
|
const SECRETS_FILE = path.join(CONFIG_DIR, "secrets.json");
|
|
19
19
|
const DB_FILE = path.join(CONFIG_DIR, "iola.db");
|
|
20
|
-
const DB_SCHEMA_VERSION =
|
|
20
|
+
const DB_SCHEMA_VERSION = 5;
|
|
21
21
|
const LOCAL_TOOLS = ["search_local", "get_card", "export_data", "run_report", "save_view"];
|
|
22
22
|
const FILE_TOOLS = ["files_tree", "files_read", "files_search", "files_write", "files_patch"];
|
|
23
23
|
const ALL_LOCAL_TOOLS = [...LOCAL_TOOLS, ...FILE_TOOLS];
|
|
@@ -242,6 +242,13 @@ const COMMANDS = new Map([
|
|
|
242
242
|
["skills", handleSkills],
|
|
243
243
|
["tools", handleTools],
|
|
244
244
|
["files", handleFiles],
|
|
245
|
+
["workspace", handleWorkspace],
|
|
246
|
+
["tasks", handleTasks],
|
|
247
|
+
["artifacts", handleArtifacts],
|
|
248
|
+
["snapshot", handleSnapshot],
|
|
249
|
+
["trace", handleTrace],
|
|
250
|
+
["policy", handlePolicy],
|
|
251
|
+
["export", handleExport],
|
|
245
252
|
["cron", handleCron],
|
|
246
253
|
["daemon", handleDaemon],
|
|
247
254
|
["rpc", handleRpc],
|
|
@@ -345,6 +352,13 @@ Usage:
|
|
|
345
352
|
iola skills list|show|paths|enable|disable
|
|
346
353
|
iola tools list|toolsets|enable|disable|profile
|
|
347
354
|
iola files status|mode|approvals|tree|read|search|write|patch
|
|
355
|
+
iola workspace init|status|use|list
|
|
356
|
+
iola tasks list|add|done|run
|
|
357
|
+
iola artifacts list|show|open
|
|
358
|
+
iola snapshot create|list|restore
|
|
359
|
+
iola trace last|show
|
|
360
|
+
iola policy use safe|analyst|developer|full
|
|
361
|
+
iola export REPORT --format docx|xlsx --output FILE
|
|
348
362
|
iola cron list|add|delete|run|tick
|
|
349
363
|
iola daemon start|status
|
|
350
364
|
iola rpc call METHOD [ARGS] [--json]
|
|
@@ -374,7 +388,7 @@ Usage:
|
|
|
374
388
|
iola config set api.mcpBaseUrl URL
|
|
375
389
|
iola config reset
|
|
376
390
|
iola update
|
|
377
|
-
iola ask TEXT [--profile NAME] [--model MODEL] [--tools] [--files] [--reasoning fast|verify|vote] [--output FILE] [--schema json|table] [--events] [--no-history] [--bare] [--quiet] [--no-color] [--fail-on-empty]
|
|
391
|
+
iola ask TEXT [--profile NAME] [--model MODEL] [--tools] [--files] [--plan] [--trace] [--reasoning fast|verify|vote] [--output FILE] [--schema json|table] [--events] [--no-history] [--bare] [--quiet] [--no-color] [--fail-on-empty]
|
|
378
392
|
iola data LAYER [--limit 10] [--search TEXT] [--where FIELD=VALUE] [--columns a,b,c] [--format table|json|csv]
|
|
379
393
|
iola ai ask TEXT [--provider ollama|openai|openrouter] [--model MODEL]
|
|
380
394
|
iola ai context TEXT [--json]
|
|
@@ -590,6 +604,36 @@ async function handleAgentLine(line, state) {
|
|
|
590
604
|
return false;
|
|
591
605
|
}
|
|
592
606
|
|
|
607
|
+
if (command === "workspace") {
|
|
608
|
+
await handleWorkspace(args);
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (command === "tasks" || command === "todos") {
|
|
613
|
+
await handleTasks(args);
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (command === "artifacts") {
|
|
618
|
+
await handleArtifacts(args);
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (command === "snapshot") {
|
|
623
|
+
await handleSnapshot(args);
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (command === "trace") {
|
|
628
|
+
await handleTrace(args);
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (command === "policy") {
|
|
633
|
+
await handlePolicy(args);
|
|
634
|
+
return false;
|
|
635
|
+
}
|
|
636
|
+
|
|
593
637
|
if (command === "cron") {
|
|
594
638
|
await handleCron(args);
|
|
595
639
|
return false;
|
|
@@ -713,6 +757,13 @@ async function handleAgentLine(line, state) {
|
|
|
713
757
|
context: ["context", args],
|
|
714
758
|
skills: ["skills", args],
|
|
715
759
|
files: ["files", args],
|
|
760
|
+
workspace: ["workspace", args],
|
|
761
|
+
tasks: ["tasks", args],
|
|
762
|
+
todos: ["tasks", args],
|
|
763
|
+
artifacts: ["artifacts", args],
|
|
764
|
+
snapshot: ["snapshot", args],
|
|
765
|
+
trace: ["trace", args],
|
|
766
|
+
policy: ["policy", args],
|
|
716
767
|
cron: ["cron", args],
|
|
717
768
|
daemon: ["daemon", args],
|
|
718
769
|
rpc: ["rpc", args],
|
|
@@ -761,6 +812,11 @@ function printAgentHelp() {
|
|
|
761
812
|
/permissions
|
|
762
813
|
/tools
|
|
763
814
|
/files status
|
|
815
|
+
/workspace status
|
|
816
|
+
/tasks list
|
|
817
|
+
/artifacts list
|
|
818
|
+
/trace last
|
|
819
|
+
/policy use safe
|
|
764
820
|
/cron list
|
|
765
821
|
/daemon status
|
|
766
822
|
/rpc call status
|
|
@@ -1491,6 +1547,7 @@ async function handleWiki(args) {
|
|
|
1491
1547
|
["Локальный инструментальный агент", `${base}/Локальный-инструментальный-агент`],
|
|
1492
1548
|
["Skills и toolsets", `${base}/Skills-и-toolsets`],
|
|
1493
1549
|
["Локальные файлы", `${base}/Локальные-файлы`],
|
|
1550
|
+
["Рабочая среда агента", `${base}/Рабочая-среда-агента`],
|
|
1494
1551
|
["Daemon, RPC и cron", `${base}/Daemon-RPC-и-cron`],
|
|
1495
1552
|
["Контекст и память", `${base}/Контекст-и-память`],
|
|
1496
1553
|
["Команды", `${base}/Команды`],
|
|
@@ -1733,6 +1790,164 @@ async function handleFiles(args) {
|
|
|
1733
1790
|
throw new Error("Команды files: status, mode MODE, approvals POLICY, tree [PATH], read FILE, search TEXT, write FILE --text TEXT, patch FILE --search OLD --replace NEW.");
|
|
1734
1791
|
}
|
|
1735
1792
|
|
|
1793
|
+
async function handleWorkspace(args) {
|
|
1794
|
+
const [action = "status", nameOrPath] = args;
|
|
1795
|
+
const config = await loadConfig();
|
|
1796
|
+
if (action === "status") {
|
|
1797
|
+
printKeyValue({ root: resolveWorkspaceRoot(config), fileMode: config.files?.mode, approvals: config.files?.approvals });
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
if (action === "init") {
|
|
1801
|
+
await handleContext(["init"]);
|
|
1802
|
+
await mkdir(path.join(process.cwd(), ".iola", "skills"), { recursive: true });
|
|
1803
|
+
console.log(`Workspace готов: ${process.cwd()}`);
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
if (action === "list") {
|
|
1807
|
+
const rows = Object.entries(config.workspaces || {}).map(([name, value]) => ({ name, path: value.path }));
|
|
1808
|
+
printTable(rows, [["name", "Workspace"], ["path", "Путь"]]);
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
if (action === "use") {
|
|
1812
|
+
if (!nameOrPath) throw new Error("Пример: iola workspace use D:\\project");
|
|
1813
|
+
const root = path.resolve(nameOrPath);
|
|
1814
|
+
const name = path.basename(root);
|
|
1815
|
+
await saveConfig({ workspaces: { ...(config.workspaces || {}), [name]: { path: root } }, files: { ...(config.files || {}), workspaceRoot: root } });
|
|
1816
|
+
console.log(`Workspace выбран: ${root}`);
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
throw new Error("Команды workspace: init, status, list, use PATH.");
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
async function handleTasks(args) {
|
|
1823
|
+
const [action = "list", idOrText, ...rest] = args;
|
|
1824
|
+
if (action === "list" || action === "ls") {
|
|
1825
|
+
printTable(listTasks(), [["id", "ID"], ["status", "Статус"], ["title", "Задача"], ["command", "Команда"]]);
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
if (action === "add") {
|
|
1829
|
+
const title = [idOrText, ...rest].filter(Boolean).join(" ");
|
|
1830
|
+
if (!title) throw new Error('Пример: iola tasks add "проверить школы"');
|
|
1831
|
+
const id = addTask(title);
|
|
1832
|
+
console.log(`Задача добавлена: ${id}`);
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
if (action === "done") {
|
|
1836
|
+
updateTaskStatus(Number(idOrText), "done");
|
|
1837
|
+
console.log(`Задача выполнена: ${idOrText}`);
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
if (action === "run") {
|
|
1841
|
+
const task = getTask(Number(idOrText));
|
|
1842
|
+
if (!task.command) throw new Error("У задачи нет команды. Добавьте command через SQLite пока не реализовано редактирование.");
|
|
1843
|
+
await main(splitCommandLine(task.command));
|
|
1844
|
+
updateTaskStatus(task.id, "done");
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
throw new Error("Команды tasks: list, add TEXT, done ID, run ID.");
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
async function handleArtifacts(args) {
|
|
1851
|
+
const [action = "list", id] = args;
|
|
1852
|
+
if (action === "list" || action === "ls") {
|
|
1853
|
+
printTable(listArtifacts(), [["id", "ID"], ["kind", "Тип"], ["title", "Название"], ["file", "Файл"], ["created_at", "Дата"]]);
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
if (action === "show") {
|
|
1857
|
+
const artifact = getArtifact(Number(id));
|
|
1858
|
+
if (artifact.file && existsSync(artifact.file)) console.log(await readFile(artifact.file, "utf8"));
|
|
1859
|
+
else printJson(artifact);
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
if (action === "open") {
|
|
1863
|
+
const artifact = getArtifact(Number(id));
|
|
1864
|
+
if (!artifact.file) throw new Error("У artifact нет файла.");
|
|
1865
|
+
await openUrl(artifact.file);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
throw new Error("Команды artifacts: list, show ID, open ID.");
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
async function handleSnapshot(args) {
|
|
1872
|
+
const [action = "list", id] = args;
|
|
1873
|
+
if (action === "create") {
|
|
1874
|
+
const result = await createSnapshot();
|
|
1875
|
+
printKeyValue(result);
|
|
1876
|
+
return;
|
|
1877
|
+
}
|
|
1878
|
+
if (action === "list" || action === "ls") {
|
|
1879
|
+
printTable(listSnapshots(), [["id", "ID"], ["workspace", "Workspace"], ["path", "Папка"], ["created_at", "Дата"]]);
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
if (action === "restore") {
|
|
1883
|
+
await restoreSnapshot(Number(id));
|
|
1884
|
+
console.log(`Snapshot восстановлен: ${id}`);
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
throw new Error("Команды snapshot: create, list, restore ID.");
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
async function handleTrace(args) {
|
|
1891
|
+
const [action = "last", id] = args;
|
|
1892
|
+
if (action === "last") {
|
|
1893
|
+
printTable(listTrace(Number(id || 20)), [["id", "ID"], ["run_id", "Run"], ["tool", "Tool"], ["status", "Статус"], ["summary", "Сводка"]]);
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
if (action === "show") {
|
|
1897
|
+
printJson(getTraceRun(id));
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
throw new Error("Команды trace: last [LIMIT], show RUN_ID.");
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
async function handlePolicy(args) {
|
|
1904
|
+
const [action = "list", name] = args;
|
|
1905
|
+
const policies = {
|
|
1906
|
+
safe: { fileMode: "read-only", approvals: "always", toolProfile: "safe" },
|
|
1907
|
+
analyst: { fileMode: "read-only", approvals: "on-danger", toolsets: ["data-read", "reports", "sync", "ai", "local-files-read"] },
|
|
1908
|
+
developer: { fileMode: "workspace-write", approvals: "on-write", toolsets: ["data-read", "reports", "sync", "ai", "local-files-read", "local-files-write"] },
|
|
1909
|
+
full: { fileMode: "full-access", approvals: "on-danger", toolProfile: "full" },
|
|
1910
|
+
};
|
|
1911
|
+
if (action === "list") {
|
|
1912
|
+
printTable(Object.entries(policies).map(([policy, value]) => ({ policy, ...value, toolsets: value.toolsets?.join(", ") || value.toolProfile })), [["policy", "Policy"], ["fileMode", "Files"], ["approvals", "Approvals"], ["toolsets", "Toolsets"]]);
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
if (action === "use") {
|
|
1916
|
+
const policy = policies[name];
|
|
1917
|
+
if (!policy) throw new Error(`Policy неизвестна: ${Object.keys(policies).join(", ")}`);
|
|
1918
|
+
const config = await loadConfig();
|
|
1919
|
+
if (policy.toolProfile) {
|
|
1920
|
+
await handleTools(["profile", policy.toolProfile]);
|
|
1921
|
+
} else {
|
|
1922
|
+
await saveConfig({ toolsets: { ...(config.toolsets || {}), enabled: policy.toolsets } });
|
|
1923
|
+
}
|
|
1924
|
+
const next = await loadConfig();
|
|
1925
|
+
await saveConfig({ files: { ...(next.files || {}), mode: policy.fileMode, approvals: policy.approvals } });
|
|
1926
|
+
await setFilesMode(policy.fileMode, await loadConfig());
|
|
1927
|
+
console.log(`Policy применена: ${name}`);
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
throw new Error("Команды policy: list, use NAME.");
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
async function handleExport(args) {
|
|
1934
|
+
const [name] = args;
|
|
1935
|
+
const options = parseOptions(args.slice(1));
|
|
1936
|
+
const format = options.format || "xlsx";
|
|
1937
|
+
const output = options.output || `${name || "iola-export"}.${format}`;
|
|
1938
|
+
await ensureLocalData();
|
|
1939
|
+
const rows = buildReportRows(name || "education-contacts");
|
|
1940
|
+
if (format === "xlsx") {
|
|
1941
|
+
await writeFile(output, toSpreadsheetXml(rows), "utf8");
|
|
1942
|
+
} else if (format === "docx" || format === "doc") {
|
|
1943
|
+
await writeFile(output, toWordHtml(name || "Отчет", rows), "utf8");
|
|
1944
|
+
} else {
|
|
1945
|
+
await outputData(rows, { output }, format);
|
|
1946
|
+
}
|
|
1947
|
+
saveArtifact("export", name || "export", output, { format, rows: rows.length });
|
|
1948
|
+
console.log(`Экспорт создан: ${output}`);
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1736
1951
|
async function handleCron(args) {
|
|
1737
1952
|
const [action = "list", ...rest] = args;
|
|
1738
1953
|
const options = parseOptions(rest);
|
|
@@ -2209,6 +2424,11 @@ async function handleView(args) {
|
|
|
2209
2424
|
async function handleReport(args) {
|
|
2210
2425
|
const [name] = args;
|
|
2211
2426
|
await ensureLocalData();
|
|
2427
|
+
const options = parseOptions(args.slice(1));
|
|
2428
|
+
if (options.format === "docx" || options.format === "xlsx") {
|
|
2429
|
+
await handleExport([name || "education-contacts", "--format", options.format, "--output", options.output || `${name || "report"}.${options.format}`]);
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2212
2432
|
if (name === "schools-summary") {
|
|
2213
2433
|
printTable(getLocalSummaryRows("schools"), [["metric", "Показатель"], ["value", "Значение"]]);
|
|
2214
2434
|
return;
|
|
@@ -2228,6 +2448,43 @@ async function handleReport(args) {
|
|
|
2228
2448
|
throw new Error("Отчеты: schools-summary, education-contacts, missing-phones, licenses.");
|
|
2229
2449
|
}
|
|
2230
2450
|
|
|
2451
|
+
function buildReportRows(name) {
|
|
2452
|
+
const reportName = name || "education-contacts";
|
|
2453
|
+
if (reportName === "schools-summary") return getLocalSummaryRows("schools");
|
|
2454
|
+
if (reportName === "missing-phones") return searchLocalRecords("", { dataset: "all", limit: 500 }).filter((item) => !item.phone || item.phone === "-");
|
|
2455
|
+
if (reportName === "licenses") return searchLocalRecords("", { dataset: "all", limit: 500 }).map((item) => ({ name: item.name, license_number: item.license_number, license_status: item.license_status }));
|
|
2456
|
+
return searchLocalRecords("", { dataset: "all", limit: 500 });
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
function toSpreadsheetXml(rows) {
|
|
2460
|
+
const columns = Object.keys(rows[0] || { empty: "" });
|
|
2461
|
+
const cell = (value) => `<Cell><Data ss:Type="String">${escapeXml(value ?? "")}</Data></Cell>`;
|
|
2462
|
+
return `<?xml version="1.0"?>
|
|
2463
|
+
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
|
|
2464
|
+
<Worksheet ss:Name="IOLA"><Table>
|
|
2465
|
+
<Row>${columns.map(cell).join("")}</Row>
|
|
2466
|
+
${rows.map((row) => `<Row>${columns.map((column) => cell(row[column])).join("")}</Row>`).join("\n")}
|
|
2467
|
+
</Table></Worksheet></Workbook>`;
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
function toWordHtml(title, rows) {
|
|
2471
|
+
const columns = Object.keys(rows[0] || { empty: "" });
|
|
2472
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(title)}</title></head><body>
|
|
2473
|
+
<h1>${escapeHtml(title)}</h1>
|
|
2474
|
+
<table border="1" cellspacing="0" cellpadding="4">
|
|
2475
|
+
<thead><tr>${columns.map((column) => `<th>${escapeHtml(column)}</th>`).join("")}</tr></thead>
|
|
2476
|
+
<tbody>${rows.map((row) => `<tr>${columns.map((column) => `<td>${escapeHtml(row[column] ?? "")}</td>`).join("")}</tr>`).join("\n")}</tbody>
|
|
2477
|
+
</table></body></html>`;
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
function escapeXml(value) {
|
|
2481
|
+
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
function escapeHtml(value) {
|
|
2485
|
+
return escapeXml(value);
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2231
2488
|
async function handlePrivacy() {
|
|
2232
2489
|
printKeyValue({
|
|
2233
2490
|
config: CONFIG_FILE,
|
|
@@ -2906,6 +3163,38 @@ function initDatabase() {
|
|
|
2906
3163
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2907
3164
|
);
|
|
2908
3165
|
CREATE INDEX IF NOT EXISTS idx_cron_jobs_enabled ON cron_jobs(enabled, last_run_at);
|
|
3166
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
3167
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3168
|
+
title TEXT NOT NULL,
|
|
3169
|
+
command TEXT,
|
|
3170
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
3171
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
3172
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
3173
|
+
);
|
|
3174
|
+
CREATE TABLE IF NOT EXISTS artifacts (
|
|
3175
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3176
|
+
kind TEXT NOT NULL,
|
|
3177
|
+
title TEXT NOT NULL,
|
|
3178
|
+
file TEXT,
|
|
3179
|
+
meta_json TEXT NOT NULL DEFAULT '{}',
|
|
3180
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
3181
|
+
);
|
|
3182
|
+
CREATE TABLE IF NOT EXISTS tool_traces (
|
|
3183
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3184
|
+
run_id TEXT NOT NULL,
|
|
3185
|
+
tool TEXT NOT NULL,
|
|
3186
|
+
args_json TEXT NOT NULL,
|
|
3187
|
+
status TEXT NOT NULL,
|
|
3188
|
+
summary TEXT,
|
|
3189
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
3190
|
+
);
|
|
3191
|
+
CREATE INDEX IF NOT EXISTS idx_tool_traces_run_id ON tool_traces(run_id, id);
|
|
3192
|
+
CREATE TABLE IF NOT EXISTS snapshots (
|
|
3193
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3194
|
+
workspace TEXT NOT NULL,
|
|
3195
|
+
path TEXT NOT NULL,
|
|
3196
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
3197
|
+
);
|
|
2909
3198
|
`);
|
|
2910
3199
|
rebuildFtsIfEmpty(db);
|
|
2911
3200
|
db.prepare(`
|
|
@@ -2958,6 +3247,8 @@ function getDbStatus() {
|
|
|
2958
3247
|
const memory = db.prepare("SELECT COUNT(*) AS count FROM memory").get();
|
|
2959
3248
|
const memorySuggestions = db.prepare("SELECT COUNT(*) AS count FROM memory_suggestions WHERE status = 'pending'").get();
|
|
2960
3249
|
const cron = db.prepare("SELECT COUNT(*) AS count FROM cron_jobs").get();
|
|
3250
|
+
const tasks = db.prepare("SELECT COUNT(*) AS count FROM tasks WHERE status != 'done'").get();
|
|
3251
|
+
const artifacts = db.prepare("SELECT COUNT(*) AS count FROM artifacts").get();
|
|
2961
3252
|
return {
|
|
2962
3253
|
status: "ok",
|
|
2963
3254
|
file: DB_FILE,
|
|
@@ -2969,6 +3260,8 @@ function getDbStatus() {
|
|
|
2969
3260
|
memory: memory?.count ?? 0,
|
|
2970
3261
|
memory_suggestions: memorySuggestions?.count ?? 0,
|
|
2971
3262
|
cron_jobs: cron?.count ?? 0,
|
|
3263
|
+
open_tasks: tasks?.count ?? 0,
|
|
3264
|
+
artifacts: artifacts?.count ?? 0,
|
|
2972
3265
|
};
|
|
2973
3266
|
} finally {
|
|
2974
3267
|
db.close();
|
|
@@ -4035,7 +4328,16 @@ async function localToolAsk(question, providerConfig, options) {
|
|
|
4035
4328
|
await ensureLocalData();
|
|
4036
4329
|
const plan = await buildLocalToolPlan(question, providerConfig, options);
|
|
4037
4330
|
const validated = validateToolPlan(plan, options);
|
|
4038
|
-
|
|
4331
|
+
if (options.plan) {
|
|
4332
|
+
printToolPlan(validated);
|
|
4333
|
+
const shouldRun = await confirm("Выполнить план? [y/N] ");
|
|
4334
|
+
if (!shouldRun) {
|
|
4335
|
+
saveArtifact("plan", question.slice(0, 80), "", { plan: validated });
|
|
4336
|
+
return "План построен, выполнение отменено.";
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
const runId = `run-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
4340
|
+
const result = await executeToolPlan(validated, { ...options, runId });
|
|
4039
4341
|
const answer = formatToolResult(result, options);
|
|
4040
4342
|
|
|
4041
4343
|
if (!options["no-history"] && isFeatureEnabled("sqlite-history")) {
|
|
@@ -4049,7 +4351,8 @@ async function localToolAsk(question, providerConfig, options) {
|
|
|
4049
4351
|
});
|
|
4050
4352
|
}
|
|
4051
4353
|
|
|
4052
|
-
emitEvent(options, "tool_plan", { plan: validated });
|
|
4354
|
+
emitEvent(options, "tool_plan", { plan: validated, runId });
|
|
4355
|
+
saveArtifact("tool-result", question.slice(0, 80), "", { runId, plan: validated, outputs: result.outputs });
|
|
4053
4356
|
if (options.output) {
|
|
4054
4357
|
await assertPermission("writeFiles");
|
|
4055
4358
|
await writeFile(options.output, answer, "utf8");
|
|
@@ -4062,6 +4365,13 @@ async function localToolAsk(question, providerConfig, options) {
|
|
|
4062
4365
|
return answer;
|
|
4063
4366
|
}
|
|
4064
4367
|
|
|
4368
|
+
function printToolPlan(plan) {
|
|
4369
|
+
console.log("План выполнения:");
|
|
4370
|
+
plan.steps.forEach((step, index) => {
|
|
4371
|
+
console.log(`${index + 1}. ${step.tool} ${JSON.stringify(step.args || {})}`);
|
|
4372
|
+
});
|
|
4373
|
+
}
|
|
4374
|
+
|
|
4065
4375
|
async function buildLocalToolPlan(question, providerConfig, options) {
|
|
4066
4376
|
const mode = options.reasoning || "verify";
|
|
4067
4377
|
const prompt = [
|
|
@@ -4138,50 +4448,62 @@ function availableToolNames(options = {}) {
|
|
|
4138
4448
|
return options.files ? ALL_LOCAL_TOOLS : LOCAL_TOOLS;
|
|
4139
4449
|
}
|
|
4140
4450
|
|
|
4141
|
-
async function executeToolPlan(plan) {
|
|
4451
|
+
async function executeToolPlan(plan, options = {}) {
|
|
4142
4452
|
let current = [];
|
|
4143
4453
|
const outputs = [];
|
|
4144
4454
|
for (const step of plan.steps) {
|
|
4455
|
+
let status = "ok";
|
|
4456
|
+
let summary = "";
|
|
4145
4457
|
await assertPermission(step.tool);
|
|
4146
4458
|
await runHooks("BeforeTool", { tool: step.tool, args: step.args || {} });
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4459
|
+
try {
|
|
4460
|
+
if (step.tool === "search_local") {
|
|
4461
|
+
current = searchLocalRecords(step.args?.query || "", { dataset: step.args?.dataset || "all", limit: step.args?.limit || 20, fts: true });
|
|
4462
|
+
outputs.push({ tool: step.tool, rows: current.length });
|
|
4463
|
+
} else if (step.tool === "get_card") {
|
|
4464
|
+
const card = findCard(step.args?.query || "");
|
|
4465
|
+
current = card ? [card] : [];
|
|
4466
|
+
outputs.push({ tool: step.tool, rows: current.length });
|
|
4467
|
+
} else if (step.tool === "run_report") {
|
|
4468
|
+
current = runQuality(step.args?.name || "all");
|
|
4469
|
+
outputs.push({ tool: step.tool, rows: current.length });
|
|
4470
|
+
} else if (step.tool === "save_view") {
|
|
4471
|
+
saveView(step.args?.name, step.args?.dataset || "all", step.args?.args || []);
|
|
4472
|
+
outputs.push({ tool: step.tool, saved: step.args?.name });
|
|
4473
|
+
} else if (step.tool === "export_data") {
|
|
4474
|
+
await assertPermission("writeFiles");
|
|
4475
|
+
await runHooks("BeforeExport", { output: step.args?.output || "iola-export.csv", format: step.args?.format || "csv", rows: current.length });
|
|
4476
|
+
const text = step.args?.format === "json" ? JSON.stringify(current, null, 2) : toCsv(current);
|
|
4477
|
+
await writeFile(step.args?.output || "iola-export.csv", text, "utf8");
|
|
4478
|
+
saveArtifact("export", step.args?.output || "iola-export.csv", step.args?.output || "iola-export.csv", { rows: current.length });
|
|
4479
|
+
outputs.push({ tool: step.tool, output: step.args?.output || "iola-export.csv", rows: current.length });
|
|
4480
|
+
} else if (step.tool === "files_tree") {
|
|
4481
|
+
current = await filesTree(step.args?.path || ".", step.args || {});
|
|
4482
|
+
outputs.push({ tool: step.tool, rows: current.length });
|
|
4483
|
+
} else if (step.tool === "files_read") {
|
|
4484
|
+
const text = await filesRead(step.args?.path || step.args?.file || ".", step.args || {});
|
|
4485
|
+
current = [{ path: step.args?.path || step.args?.file || ".", text }];
|
|
4486
|
+
outputs.push({ tool: step.tool, bytes: text.length });
|
|
4487
|
+
} else if (step.tool === "files_search") {
|
|
4488
|
+
current = await filesSearch(step.args?.query || "", { path: step.args?.path || ".", limit: step.args?.limit || 50 });
|
|
4489
|
+
outputs.push({ tool: step.tool, rows: current.length });
|
|
4490
|
+
} else if (step.tool === "files_write") {
|
|
4491
|
+
await filesWrite(step.args?.path || step.args?.file, step.args?.text || "", { append: Boolean(step.args?.append) });
|
|
4492
|
+
current = [{ path: step.args?.path || step.args?.file, status: "written" }];
|
|
4493
|
+
outputs.push({ tool: step.tool, output: step.args?.path || step.args?.file, rows: 1 });
|
|
4494
|
+
} else if (step.tool === "files_patch") {
|
|
4495
|
+
const result = await filesPatch(step.args?.path || step.args?.file, step.args?.search || "", step.args?.replace || "");
|
|
4496
|
+
current = [result];
|
|
4497
|
+
outputs.push({ tool: step.tool, output: result.path, replacements: result.replacements });
|
|
4498
|
+
}
|
|
4499
|
+
summary = `rows=${current.length}`;
|
|
4500
|
+
} catch (error) {
|
|
4501
|
+
status = "error";
|
|
4502
|
+
summary = error instanceof Error ? error.message : String(error);
|
|
4503
|
+
recordToolTrace(options.runId || "manual", step.tool, step.args || {}, status, summary);
|
|
4504
|
+
throw error;
|
|
4184
4505
|
}
|
|
4506
|
+
recordToolTrace(options.runId || "manual", step.tool, step.args || {}, status, summary);
|
|
4185
4507
|
await runHooks("AfterTool", { tool: step.tool, rows: current.length });
|
|
4186
4508
|
}
|
|
4187
4509
|
return { rows: current, outputs };
|
|
@@ -4738,7 +5060,7 @@ function parseOptions(args) {
|
|
|
4738
5060
|
|
|
4739
5061
|
for (let index = 0; index < args.length; index += 1) {
|
|
4740
5062
|
const arg = args[index];
|
|
4741
|
-
if (arg === "--json" || arg === "--yes" || arg === "--silent" || arg === "--events" || arg === "--no-history" || arg === "--summary" || arg === "--all" || arg === "--local" || arg === "--cache" || arg === "--tools" || arg === "--files" || arg === "--fts" || arg === "--bare" || arg === "--quiet" || arg === "--no-color" || arg === "--fail-on-empty" || arg === "--debug" || arg === "--fix" || arg === "--append") {
|
|
5063
|
+
if (arg === "--json" || arg === "--yes" || arg === "--silent" || arg === "--events" || arg === "--no-history" || arg === "--summary" || arg === "--all" || arg === "--local" || arg === "--cache" || arg === "--tools" || arg === "--files" || arg === "--plan" || arg === "--trace" || arg === "--diff" || arg === "--fts" || arg === "--bare" || arg === "--quiet" || arg === "--no-color" || arg === "--fail-on-empty" || arg === "--debug" || arg === "--fix" || arg === "--append") {
|
|
4742
5064
|
result[arg.slice(2)] = true;
|
|
4743
5065
|
} else if (arg === "--check" || arg === "--upgrade-node") {
|
|
4744
5066
|
result.check = true;
|
|
@@ -5313,6 +5635,155 @@ async function maybeConfirmFileOperation(operation, target, preview) {
|
|
|
5313
5635
|
if (!ok) throw new Error("Файловая операция отменена.");
|
|
5314
5636
|
}
|
|
5315
5637
|
|
|
5638
|
+
function listTasks() {
|
|
5639
|
+
initDatabase();
|
|
5640
|
+
const db = openDatabase();
|
|
5641
|
+
try {
|
|
5642
|
+
return db.prepare("SELECT id, title, COALESCE(command, '-') AS command, status FROM tasks ORDER BY status, id DESC LIMIT 100").all();
|
|
5643
|
+
} finally {
|
|
5644
|
+
db.close();
|
|
5645
|
+
}
|
|
5646
|
+
}
|
|
5647
|
+
|
|
5648
|
+
function addTask(title, command = "") {
|
|
5649
|
+
initDatabase();
|
|
5650
|
+
const db = openDatabase();
|
|
5651
|
+
try {
|
|
5652
|
+
const result = db.prepare("INSERT INTO tasks(title, command) VALUES (?, ?)").run(title, command);
|
|
5653
|
+
return Number(result.lastInsertRowid);
|
|
5654
|
+
} finally {
|
|
5655
|
+
db.close();
|
|
5656
|
+
}
|
|
5657
|
+
}
|
|
5658
|
+
|
|
5659
|
+
function getTask(id) {
|
|
5660
|
+
initDatabase();
|
|
5661
|
+
const db = openDatabase();
|
|
5662
|
+
try {
|
|
5663
|
+
const row = db.prepare("SELECT * FROM tasks WHERE id = ?").get(id);
|
|
5664
|
+
if (!row) throw new Error(`Задача не найдена: ${id}`);
|
|
5665
|
+
return row;
|
|
5666
|
+
} finally {
|
|
5667
|
+
db.close();
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
5670
|
+
|
|
5671
|
+
function updateTaskStatus(id, status) {
|
|
5672
|
+
initDatabase();
|
|
5673
|
+
const db = openDatabase();
|
|
5674
|
+
try {
|
|
5675
|
+
db.prepare("UPDATE tasks SET status = ?, updated_at = datetime('now') WHERE id = ?").run(status, id);
|
|
5676
|
+
} finally {
|
|
5677
|
+
db.close();
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5680
|
+
|
|
5681
|
+
function saveArtifact(kind, title, file = "", meta = {}) {
|
|
5682
|
+
initDatabase();
|
|
5683
|
+
const db = openDatabase();
|
|
5684
|
+
try {
|
|
5685
|
+
const result = db.prepare("INSERT INTO artifacts(kind, title, file, meta_json) VALUES (?, ?, ?, ?)").run(kind, title || kind, file || "", JSON.stringify(meta));
|
|
5686
|
+
return Number(result.lastInsertRowid);
|
|
5687
|
+
} finally {
|
|
5688
|
+
db.close();
|
|
5689
|
+
}
|
|
5690
|
+
}
|
|
5691
|
+
|
|
5692
|
+
function listArtifacts() {
|
|
5693
|
+
initDatabase();
|
|
5694
|
+
const db = openDatabase();
|
|
5695
|
+
try {
|
|
5696
|
+
return db.prepare("SELECT id, kind, title, file, created_at FROM artifacts ORDER BY id DESC LIMIT 100").all();
|
|
5697
|
+
} finally {
|
|
5698
|
+
db.close();
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
|
|
5702
|
+
function getArtifact(id) {
|
|
5703
|
+
initDatabase();
|
|
5704
|
+
const db = openDatabase();
|
|
5705
|
+
try {
|
|
5706
|
+
const row = db.prepare("SELECT * FROM artifacts WHERE id = ?").get(id);
|
|
5707
|
+
if (!row) throw new Error(`Artifact не найден: ${id}`);
|
|
5708
|
+
return row;
|
|
5709
|
+
} finally {
|
|
5710
|
+
db.close();
|
|
5711
|
+
}
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5714
|
+
function recordToolTrace(runId, tool, args, status, summary) {
|
|
5715
|
+
initDatabase();
|
|
5716
|
+
const db = openDatabase();
|
|
5717
|
+
try {
|
|
5718
|
+
db.prepare("INSERT INTO tool_traces(run_id, tool, args_json, status, summary) VALUES (?, ?, ?, ?, ?)").run(runId, tool, JSON.stringify(args), status, summary || "");
|
|
5719
|
+
} finally {
|
|
5720
|
+
db.close();
|
|
5721
|
+
}
|
|
5722
|
+
}
|
|
5723
|
+
|
|
5724
|
+
function listTrace(limit = 20) {
|
|
5725
|
+
initDatabase();
|
|
5726
|
+
const db = openDatabase();
|
|
5727
|
+
try {
|
|
5728
|
+
return db.prepare("SELECT id, run_id, tool, status, summary, created_at FROM tool_traces ORDER BY id DESC LIMIT ?").all(limit);
|
|
5729
|
+
} finally {
|
|
5730
|
+
db.close();
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
|
|
5734
|
+
function getTraceRun(runId) {
|
|
5735
|
+
initDatabase();
|
|
5736
|
+
const db = openDatabase();
|
|
5737
|
+
try {
|
|
5738
|
+
return db.prepare("SELECT * FROM tool_traces WHERE run_id = ? ORDER BY id ASC").all(runId);
|
|
5739
|
+
} finally {
|
|
5740
|
+
db.close();
|
|
5741
|
+
}
|
|
5742
|
+
}
|
|
5743
|
+
|
|
5744
|
+
async function createSnapshot() {
|
|
5745
|
+
const config = await loadConfig();
|
|
5746
|
+
const workspace = resolveWorkspaceRoot(config);
|
|
5747
|
+
const snapshotsDir = path.join(CONFIG_DIR, "snapshots");
|
|
5748
|
+
await mkdir(snapshotsDir, { recursive: true });
|
|
5749
|
+
const target = path.join(snapshotsDir, `snapshot-${Date.now()}`);
|
|
5750
|
+
await cp(workspace, target, {
|
|
5751
|
+
recursive: true,
|
|
5752
|
+
filter: (source) => !isBlockedPathForConfig(source, config) && !source.includes(`${path.sep}node_modules${path.sep}`),
|
|
5753
|
+
});
|
|
5754
|
+
initDatabase();
|
|
5755
|
+
const db = openDatabase();
|
|
5756
|
+
try {
|
|
5757
|
+
const result = db.prepare("INSERT INTO snapshots(workspace, path) VALUES (?, ?)").run(workspace, target);
|
|
5758
|
+
return { id: Number(result.lastInsertRowid), workspace, path: target };
|
|
5759
|
+
} finally {
|
|
5760
|
+
db.close();
|
|
5761
|
+
}
|
|
5762
|
+
}
|
|
5763
|
+
|
|
5764
|
+
function listSnapshots() {
|
|
5765
|
+
initDatabase();
|
|
5766
|
+
const db = openDatabase();
|
|
5767
|
+
try {
|
|
5768
|
+
return db.prepare("SELECT id, workspace, path, created_at FROM snapshots ORDER BY id DESC LIMIT 50").all();
|
|
5769
|
+
} finally {
|
|
5770
|
+
db.close();
|
|
5771
|
+
}
|
|
5772
|
+
}
|
|
5773
|
+
|
|
5774
|
+
async function restoreSnapshot(id) {
|
|
5775
|
+
initDatabase();
|
|
5776
|
+
const db = openDatabase();
|
|
5777
|
+
let row;
|
|
5778
|
+
try {
|
|
5779
|
+
row = db.prepare("SELECT * FROM snapshots WHERE id = ?").get(id);
|
|
5780
|
+
} finally {
|
|
5781
|
+
db.close();
|
|
5782
|
+
}
|
|
5783
|
+
if (!row) throw new Error(`Snapshot не найден: ${id}`);
|
|
5784
|
+
await cp(row.path, row.workspace, { recursive: true, force: true });
|
|
5785
|
+
}
|
|
5786
|
+
|
|
5316
5787
|
function unifiedPreview(before, after) {
|
|
5317
5788
|
const beforeLines = before.split(/\r?\n/);
|
|
5318
5789
|
const afterLines = after.split(/\r?\n/);
|
package/wiki/Home.md
CHANGED
|
@@ -30,6 +30,7 @@ iola ask "найди школу 29"
|
|
|
30
30
|
- [Локальный инструментальный агент](Локальный-инструментальный-агент)
|
|
31
31
|
- [Skills и toolsets](Skills-и-toolsets)
|
|
32
32
|
- [Локальные файлы](Локальные-файлы)
|
|
33
|
+
- [Рабочая среда агента](Рабочая-среда-агента)
|
|
33
34
|
- [Daemon, RPC и cron](Daemon-RPC-и-cron)
|
|
34
35
|
- [Контекст и память](Контекст-и-память)
|
|
35
36
|
- [Команды](Команды)
|
|
@@ -51,6 +51,12 @@ iola files status
|
|
|
51
51
|
iola files mode read-only
|
|
52
52
|
iola files tree .
|
|
53
53
|
iola files search "Петрова" --path .
|
|
54
|
+
iola policy use analyst
|
|
55
|
+
iola tasks list
|
|
56
|
+
iola artifacts list
|
|
57
|
+
iola snapshot list
|
|
58
|
+
iola trace last
|
|
59
|
+
iola export education-contacts --format xlsx --output contacts.xlsx
|
|
54
60
|
iola memory suggest
|
|
55
61
|
```
|
|
56
62
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Рабочая среда агента
|
|
2
|
+
|
|
3
|
+
`iola-cli` поддерживает рабочие пространства, задачи, артефакты, snapshots, trace и policy-профили.
|
|
4
|
+
|
|
5
|
+
План перед выполнением:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
iola ask "найди файлы со школами и сделай отчет" --profile local --tools --files --plan
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Policy:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
iola policy list
|
|
15
|
+
iola policy use safe
|
|
16
|
+
iola policy use analyst
|
|
17
|
+
iola policy use developer
|
|
18
|
+
iola policy use full
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Workspace:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
iola workspace init
|
|
25
|
+
iola workspace status
|
|
26
|
+
iola workspace use D:\project
|
|
27
|
+
iola workspace list
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Tasks:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
iola tasks add "проверить качество данных"
|
|
34
|
+
iola tasks list
|
|
35
|
+
iola tasks done 1
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Artifacts:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
iola artifacts list
|
|
42
|
+
iola artifacts show 1
|
|
43
|
+
iola artifacts open 1
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Snapshots:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
iola snapshot create
|
|
50
|
+
iola snapshot list
|
|
51
|
+
iola snapshot restore 1
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Trace:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
iola trace last
|
|
58
|
+
iola trace show RUN_ID
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Export:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
iola export education-contacts --format xlsx --output contacts.xlsx
|
|
65
|
+
iola report missing-phones --format docx --output missing-phones.docx
|
|
66
|
+
```
|
|
67
|
+
|