@iola_adm/iola-cli 0.1.30 → 0.1.31
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 +3 -0
- package/package.json +1 -1
- package/src/cli.js +204 -2
- package/wiki/Home.md +1 -0
- package/wiki//320/221/321/200/320/260/321/203/320/267/320/265/321/200/320/275/321/213/320/271-/320/260/320/263/320/265/320/275/321/202.md +68 -0
- package/wiki//320/232/320/276/320/274/320/260/320/275/320/264/321/213.md +4 -0
package/README.md
CHANGED
|
@@ -74,6 +74,7 @@ iola budget status
|
|
|
74
74
|
iola subagents list
|
|
75
75
|
iola trajectory last
|
|
76
76
|
iola review config
|
|
77
|
+
iola browser status
|
|
77
78
|
```
|
|
78
79
|
|
|
79
80
|
Локальная модель через Ollama:
|
|
@@ -100,6 +101,7 @@ iola version --check
|
|
|
100
101
|
- [Локальные файлы](https://github.com/adm-iola/iola-cli/wiki/Локальные-файлы)
|
|
101
102
|
- [Рабочая среда агента](https://github.com/adm-iola/iola-cli/wiki/Рабочая-среда-агента)
|
|
102
103
|
- [Платформа агента](https://github.com/adm-iola/iola-cli/wiki/Платформа-агента)
|
|
104
|
+
- [Браузерный агент](https://github.com/adm-iola/iola-cli/wiki/Браузерный-агент)
|
|
103
105
|
- [Расширения и локальные данные](https://github.com/adm-iola/iola-cli/wiki/Расширения-и-локальные-данные)
|
|
104
106
|
- [Архивы и мастер настройки](https://github.com/adm-iola/iola-cli/wiki/Архивы-и-мастер-настройки)
|
|
105
107
|
- [Daemon, RPC и cron](https://github.com/adm-iola/iola-cli/wiki/Daemon-RPC-и-cron)
|
|
@@ -116,6 +118,7 @@ iola version --check
|
|
|
116
118
|
- skills, toolsets, permissions, memory, hooks и готовые agents;
|
|
117
119
|
- subagents, skill bundles, layered settings, usage/budget accounting и trajectory export;
|
|
118
120
|
- полноценный локальный MCP server по stdio/http: tools, resources и prompts;
|
|
121
|
+
- браузерный runtime через Playwright: чтение страниц, скриншоты, PDF, клики, ввод и eval;
|
|
119
122
|
- управляемые локальные файловые операции с режимами `locked`, `read-only`, `workspace-write`, `full-access`;
|
|
120
123
|
- планы выполнения, traces, tasks, artifacts, snapshots и policy-профили;
|
|
121
124
|
- экспорт отчетов в Excel/Word-совместимые файлы;
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -22,6 +22,8 @@ const DB_SCHEMA_VERSION = 8;
|
|
|
22
22
|
const PROJECT_IOLA_DIR = path.join(process.cwd(), ".iola");
|
|
23
23
|
const PROJECT_CONFIG_FILE = path.join(PROJECT_IOLA_DIR, "config.json");
|
|
24
24
|
const LOCAL_CONFIG_FILE = path.join(PROJECT_IOLA_DIR, "local.json");
|
|
25
|
+
const BROWSER_RUNTIME_DIR = path.join(CONFIG_DIR, "browser-runtime");
|
|
26
|
+
const BROWSER_RUNTIME_PACKAGE = path.join(BROWSER_RUNTIME_DIR, "node_modules", "playwright", "package.json");
|
|
25
27
|
const INDEXABLE_EXTENSIONS = /\.(md|txt|csv|json|html|docx|xlsx|pptx|pdf)$/i;
|
|
26
28
|
const LOCAL_TOOLS = ["search_local", "get_card", "export_data", "run_report", "save_view"];
|
|
27
29
|
const FILE_TOOLS = ["files_tree", "files_read", "files_search", "files_write", "files_patch"];
|
|
@@ -271,6 +273,7 @@ const COMMANDS = new Map([
|
|
|
271
273
|
["index", handleIndex],
|
|
272
274
|
["reports", handleReports],
|
|
273
275
|
["plugins", handlePlugins],
|
|
276
|
+
["browser", handleBrowser],
|
|
274
277
|
["workspace", handleWorkspace],
|
|
275
278
|
["tasks", handleTasks],
|
|
276
279
|
["artifacts", handleArtifacts],
|
|
@@ -396,6 +399,7 @@ Usage:
|
|
|
396
399
|
iola index folder|status|search
|
|
397
400
|
iola reports list|run
|
|
398
401
|
iola plugins list|install|run|remove
|
|
402
|
+
iola browser status|install|open|text|html|screenshot|pdf|click|type|eval
|
|
399
403
|
iola workspace init|status|use|list
|
|
400
404
|
iola tasks list|add|done|run
|
|
401
405
|
iola artifacts list|show|open
|
|
@@ -1709,6 +1713,7 @@ async function handleWiki(args) {
|
|
|
1709
1713
|
["Локальные файлы", `${base}/Локальные-файлы`],
|
|
1710
1714
|
["Рабочая среда агента", `${base}/Рабочая-среда-агента`],
|
|
1711
1715
|
["Платформа агента", `${base}/Платформа-агента`],
|
|
1716
|
+
["Браузерный агент", `${base}/Браузерный-агент`],
|
|
1712
1717
|
["Расширения и локальные данные", `${base}/Расширения-и-локальные-данные`],
|
|
1713
1718
|
["Архивы и мастер настройки", `${base}/Архивы-и-мастер-настройки`],
|
|
1714
1719
|
["Daemon, RPC и cron", `${base}/Daemon-RPC-и-cron`],
|
|
@@ -2209,6 +2214,94 @@ async function handlePlugins(args) {
|
|
|
2209
2214
|
throw new Error("Команды plugins: list, install NAME --command CMD, run NAME, remove NAME.");
|
|
2210
2215
|
}
|
|
2211
2216
|
|
|
2217
|
+
async function handleBrowser(args) {
|
|
2218
|
+
const [action = "status", target, ...rest] = args;
|
|
2219
|
+
const options = parseOptions(rest);
|
|
2220
|
+
|
|
2221
|
+
if (action === "status") {
|
|
2222
|
+
printKeyValue(await getBrowserStatus());
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
if (action === "install") {
|
|
2227
|
+
await installBrowserRuntime();
|
|
2228
|
+
printKeyValue(await getBrowserStatus());
|
|
2229
|
+
return;
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
if (action === "open") {
|
|
2233
|
+
const url = target || options.url;
|
|
2234
|
+
if (!url) throw new Error("Пример: iola browser open https://example.com");
|
|
2235
|
+
if (options.system) {
|
|
2236
|
+
await openUrl(url);
|
|
2237
|
+
return;
|
|
2238
|
+
}
|
|
2239
|
+
await runBrowserAutomation("open", { url, headed: options.headless ? false : true, waitMs: Number(options.wait || 600000) });
|
|
2240
|
+
return;
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
if (action === "text" || action === "html") {
|
|
2244
|
+
const url = target || options.url;
|
|
2245
|
+
if (!url) throw new Error(`Пример: iola browser ${action} https://example.com`);
|
|
2246
|
+
const result = await runBrowserAutomation(action, browserParams(url, options));
|
|
2247
|
+
if (options.output) {
|
|
2248
|
+
await writeFile(options.output, result, "utf8");
|
|
2249
|
+
console.log(`Файл сохранен: ${options.output}`);
|
|
2250
|
+
} else {
|
|
2251
|
+
console.log(result);
|
|
2252
|
+
}
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
if (action === "screenshot" || action === "pdf") {
|
|
2257
|
+
const url = target || options.url;
|
|
2258
|
+
if (!url) throw new Error(`Пример: iola browser ${action} https://example.com --output page.${action === "pdf" ? "pdf" : "png"}`);
|
|
2259
|
+
const output = options.output || path.join(process.cwd(), action === "pdf" ? "browser-page.pdf" : "browser-page.png");
|
|
2260
|
+
await runBrowserAutomation(action, { ...browserParams(url, options), output: path.resolve(output) });
|
|
2261
|
+
saveArtifact(action === "pdf" ? "browser-pdf" : "browser-screenshot", url, path.resolve(output), { url });
|
|
2262
|
+
console.log(`Файл сохранен: ${output}`);
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
if (action === "click") {
|
|
2267
|
+
const url = target || options.url;
|
|
2268
|
+
if (!url || !options.selector) throw new Error('Пример: iola browser click https://example.com --selector "button" --output after.png');
|
|
2269
|
+
const result = await runBrowserAutomation("click", { ...browserParams(url, options), selector: options.selector, output: options.output ? path.resolve(options.output) : "" });
|
|
2270
|
+
if (result) console.log(result);
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
if (action === "type") {
|
|
2275
|
+
const url = target || options.url;
|
|
2276
|
+
if (!url || !options.selector || options.text === undefined) throw new Error('Пример: iola browser type https://example.com --selector "#q" --text "школа 29"');
|
|
2277
|
+
const result = await runBrowserAutomation("type", { ...browserParams(url, options), selector: options.selector, text: options.text, press: options.press || "", output: options.output ? path.resolve(options.output) : "" });
|
|
2278
|
+
if (result) console.log(result);
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
if (action === "eval") {
|
|
2283
|
+
const url = target || options.url;
|
|
2284
|
+
const script = options.script || rest.join(" ");
|
|
2285
|
+
if (!url || !script) throw new Error('Пример: iola browser eval https://example.com --script "document.title"');
|
|
2286
|
+
const result = await runBrowserAutomation("eval", { ...browserParams(url, options), script });
|
|
2287
|
+
console.log(result);
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
throw new Error("Команды browser: status, install, open URL, text URL, html URL, screenshot URL --output FILE, pdf URL --output FILE, click URL --selector SEL, type URL --selector SEL --text TEXT, eval URL --script JS.");
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
function browserParams(url, options = {}) {
|
|
2295
|
+
return {
|
|
2296
|
+
url,
|
|
2297
|
+
headed: Boolean(options.headed),
|
|
2298
|
+
timeout: Number(options.timeout || 30000),
|
|
2299
|
+
waitMs: Number(options.wait || 0),
|
|
2300
|
+
selector: options.selector || "",
|
|
2301
|
+
viewport: options.viewport || "1366x768",
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2212
2305
|
async function handleWorkspace(args) {
|
|
2213
2306
|
const [action = "status", nameOrPath] = args;
|
|
2214
2307
|
const config = await loadConfig();
|
|
@@ -5903,12 +5996,12 @@ function parseOptions(args) {
|
|
|
5903
5996
|
|
|
5904
5997
|
for (let index = 0; index < args.length; index += 1) {
|
|
5905
5998
|
const arg = args[index];
|
|
5906
|
-
if (arg === "--json" || arg === "--yes" || arg === "--silent" || arg === "--events" || arg === "--stream-json" || arg === "--stdio" || arg === "--no-history" || arg === "--summary" || arg === "--all" || arg === "--local" || arg === "--cache" || arg === "--tools" || arg === "--files" || arg === "--plan" || arg === "--trace" || arg === "--diff" || arg === "--stage" || arg === "--fts" || arg === "--bare" || arg === "--quiet" || arg === "--no-color" || arg === "--fail-on-empty" || arg === "--debug" || arg === "--fix" || arg === "--append") {
|
|
5999
|
+
if (arg === "--json" || arg === "--yes" || arg === "--silent" || arg === "--events" || arg === "--stream-json" || arg === "--stdio" || arg === "--system" || arg === "--headed" || arg === "--headless" || arg === "--no-history" || arg === "--summary" || arg === "--all" || arg === "--local" || arg === "--cache" || arg === "--tools" || arg === "--files" || arg === "--plan" || arg === "--trace" || arg === "--diff" || arg === "--stage" || arg === "--fts" || arg === "--bare" || arg === "--quiet" || arg === "--no-color" || arg === "--fail-on-empty" || arg === "--debug" || arg === "--fix" || arg === "--append") {
|
|
5907
6000
|
result[arg.slice(2)] = true;
|
|
5908
6001
|
} else if (arg === "--check" || arg === "--upgrade-node") {
|
|
5909
6002
|
result.check = true;
|
|
5910
6003
|
result[arg.slice(2)] = true;
|
|
5911
|
-
} else if (arg === "--limit" || arg === "--offset" || arg === "--search" || arg === "--replace" || arg === "--text" || arg === "--path" || arg === "--depth" || arg === "--max-bytes" || arg === "--query" || arg === "--where" || arg === "--columns" || arg === "--inn" || arg === "--model" || arg === "--provider" || arg === "--profile" || arg === "--name" || arg === "--source" || arg === "--command" || arg === "--prompt" || arg === "--description" || arg === "--base-url" || arg === "--sandbox" || arg === "--approval" || arg === "--cwd" || arg === "--codex-profile" || arg === "--format" || arg === "--output" || arg === "--schema" || arg === "--session" || arg === "--temperature" || arg === "--config" || arg === "--dataset" || arg === "--save" || arg === "--reasoning" || arg === "--agent" || arg === "--scope" || arg === "--debug-file") {
|
|
6004
|
+
} else if (arg === "--limit" || arg === "--offset" || arg === "--search" || arg === "--replace" || arg === "--text" || arg === "--path" || arg === "--depth" || arg === "--max-bytes" || arg === "--query" || arg === "--where" || arg === "--columns" || arg === "--inn" || arg === "--model" || arg === "--provider" || arg === "--profile" || arg === "--name" || arg === "--source" || arg === "--command" || arg === "--prompt" || arg === "--description" || arg === "--base-url" || arg === "--sandbox" || arg === "--approval" || arg === "--cwd" || arg === "--codex-profile" || arg === "--format" || arg === "--output" || arg === "--schema" || arg === "--session" || arg === "--temperature" || arg === "--config" || arg === "--dataset" || arg === "--save" || arg === "--reasoning" || arg === "--agent" || arg === "--scope" || arg === "--selector" || arg === "--url" || arg === "--timeout" || arg === "--wait" || arg === "--viewport" || arg === "--press" || arg === "--script" || arg === "--debug-file") {
|
|
5912
6005
|
result[arg.slice(2)] = args[index + 1];
|
|
5913
6006
|
index += 1;
|
|
5914
6007
|
} else {
|
|
@@ -6285,6 +6378,105 @@ async function installCodexIfMissing() {
|
|
|
6285
6378
|
await runCommand("npm", ["install", "-g", "@openai/codex"], { inherit: true });
|
|
6286
6379
|
}
|
|
6287
6380
|
|
|
6381
|
+
async function getBrowserStatus() {
|
|
6382
|
+
const installed = existsSync(BROWSER_RUNTIME_PACKAGE);
|
|
6383
|
+
let playwright = "не установлен";
|
|
6384
|
+
if (installed) {
|
|
6385
|
+
try {
|
|
6386
|
+
playwright = JSON.parse(await readFile(BROWSER_RUNTIME_PACKAGE, "utf8")).version || "installed";
|
|
6387
|
+
} catch {
|
|
6388
|
+
playwright = "installed";
|
|
6389
|
+
}
|
|
6390
|
+
}
|
|
6391
|
+
return {
|
|
6392
|
+
runtime: BROWSER_RUNTIME_DIR,
|
|
6393
|
+
playwright,
|
|
6394
|
+
installed: installed ? "yes" : "no",
|
|
6395
|
+
install_command: "iola browser install",
|
|
6396
|
+
chromium: installed ? "managed by Playwright" : "not installed",
|
|
6397
|
+
};
|
|
6398
|
+
}
|
|
6399
|
+
|
|
6400
|
+
async function installBrowserRuntime() {
|
|
6401
|
+
await mkdir(BROWSER_RUNTIME_DIR, { recursive: true });
|
|
6402
|
+
const packageFile = path.join(BROWSER_RUNTIME_DIR, "package.json");
|
|
6403
|
+
if (!existsSync(packageFile)) {
|
|
6404
|
+
await writeFile(packageFile, `${JSON.stringify({ private: true, type: "module", dependencies: {} }, null, 2)}\n`, "utf8");
|
|
6405
|
+
}
|
|
6406
|
+
console.log(`Устанавливаю Playwright runtime: ${BROWSER_RUNTIME_DIR}`);
|
|
6407
|
+
await runPackageManager("npm", ["install", "playwright@latest"], { inherit: true, cwd: BROWSER_RUNTIME_DIR });
|
|
6408
|
+
await runPackageManager("npx", ["playwright", "install", "chromium"], { inherit: true, cwd: BROWSER_RUNTIME_DIR });
|
|
6409
|
+
}
|
|
6410
|
+
|
|
6411
|
+
function runPackageManager(command, args, options = {}) {
|
|
6412
|
+
if (process.platform === "win32") {
|
|
6413
|
+
return runCommand(process.env.ComSpec || "cmd.exe", ["/d", "/c", [command, ...args].join(" ")], options);
|
|
6414
|
+
}
|
|
6415
|
+
return runCommand(command, args, options);
|
|
6416
|
+
}
|
|
6417
|
+
|
|
6418
|
+
async function ensureBrowserRuntime() {
|
|
6419
|
+
if (existsSync(BROWSER_RUNTIME_PACKAGE)) return;
|
|
6420
|
+
throw new Error("Browser runtime не установлен. Запустите: iola browser install");
|
|
6421
|
+
}
|
|
6422
|
+
|
|
6423
|
+
async function runBrowserAutomation(action, params) {
|
|
6424
|
+
await ensureBrowserRuntime();
|
|
6425
|
+
const scriptFile = path.join(BROWSER_RUNTIME_DIR, `iola-browser-${Date.now()}-${Math.random().toString(16).slice(2)}.mjs`);
|
|
6426
|
+
await writeFile(scriptFile, browserAutomationScript(action, params), "utf8");
|
|
6427
|
+
try {
|
|
6428
|
+
const { stdout } = await runCommand(process.execPath, [scriptFile], { cwd: BROWSER_RUNTIME_DIR });
|
|
6429
|
+
return stdout.trim();
|
|
6430
|
+
} finally {
|
|
6431
|
+
await rm(scriptFile, { force: true }).catch(() => {});
|
|
6432
|
+
}
|
|
6433
|
+
}
|
|
6434
|
+
|
|
6435
|
+
function browserAutomationScript(action, params) {
|
|
6436
|
+
return `
|
|
6437
|
+
import { chromium } from "playwright";
|
|
6438
|
+
const action = ${JSON.stringify(action)};
|
|
6439
|
+
const params = ${JSON.stringify(params)};
|
|
6440
|
+
const [width, height] = String(params.viewport || "1366x768").split("x").map(Number);
|
|
6441
|
+
const browser = await chromium.launch({ headless: !params.headed });
|
|
6442
|
+
const page = await browser.newPage({ viewport: { width: width || 1366, height: height || 768 } });
|
|
6443
|
+
page.setDefaultTimeout(params.timeout || 30000);
|
|
6444
|
+
try {
|
|
6445
|
+
await page.goto(params.url, { waitUntil: "domcontentloaded", timeout: params.timeout || 30000 });
|
|
6446
|
+
if (params.waitMs) await page.waitForTimeout(params.waitMs);
|
|
6447
|
+
if (action === "open") {
|
|
6448
|
+
if (params.waitMs > 0) await page.waitForTimeout(params.waitMs);
|
|
6449
|
+
else if (!page.context().browser()?.isConnected()) {}
|
|
6450
|
+
} else if (action === "text") {
|
|
6451
|
+
console.log((await page.locator("body").innerText()).trim());
|
|
6452
|
+
} else if (action === "html") {
|
|
6453
|
+
console.log(await page.content());
|
|
6454
|
+
} else if (action === "screenshot") {
|
|
6455
|
+
await page.screenshot({ path: params.output, fullPage: true });
|
|
6456
|
+
} else if (action === "pdf") {
|
|
6457
|
+
await page.pdf({ path: params.output, format: "A4", printBackground: true });
|
|
6458
|
+
} else if (action === "click") {
|
|
6459
|
+
await page.locator(params.selector).first().click();
|
|
6460
|
+
if (params.waitMs) await page.waitForTimeout(params.waitMs);
|
|
6461
|
+
if (params.output) await page.screenshot({ path: params.output, fullPage: true });
|
|
6462
|
+
console.log((await page.locator("body").innerText()).trim().slice(0, 4000));
|
|
6463
|
+
} else if (action === "type") {
|
|
6464
|
+
const locator = page.locator(params.selector).first();
|
|
6465
|
+
await locator.fill(params.text || "");
|
|
6466
|
+
if (params.press) await locator.press(params.press);
|
|
6467
|
+
if (params.waitMs) await page.waitForTimeout(params.waitMs);
|
|
6468
|
+
if (params.output) await page.screenshot({ path: params.output, fullPage: true });
|
|
6469
|
+
console.log((await page.locator("body").innerText()).trim().slice(0, 4000));
|
|
6470
|
+
} else if (action === "eval") {
|
|
6471
|
+
const value = await page.evaluate(new Function("return (" + params.script + ")"));
|
|
6472
|
+
console.log(typeof value === "string" ? value : JSON.stringify(value, null, 2));
|
|
6473
|
+
}
|
|
6474
|
+
} finally {
|
|
6475
|
+
await browser.close();
|
|
6476
|
+
}
|
|
6477
|
+
`;
|
|
6478
|
+
}
|
|
6479
|
+
|
|
6288
6480
|
async function probeEndpoint(url) {
|
|
6289
6481
|
try {
|
|
6290
6482
|
const response = await fetch(url, { headers: { accept: "application/json" } });
|
|
@@ -6468,6 +6660,8 @@ function mcpTools() {
|
|
|
6468
6660
|
{ name: "files.search", description: "Поиск текста в файлах workspace.", inputSchema: schema({ query: { type: "string" }, path: { type: "string" }, limit: { type: "number" } }) },
|
|
6469
6661
|
{ name: "index.search", description: "Поиск по индексу локальных документов.", inputSchema: schema({ query: { type: "string" }, limit: { type: "number" } }) },
|
|
6470
6662
|
{ name: "report", description: "Запуск встроенного отчета.", inputSchema: schema({ name: { type: "string" }, format: { type: "string" }, output: { type: "string" } }) },
|
|
6663
|
+
{ name: "browser.text", description: "Открыть страницу в headless Chromium и вернуть видимый текст.", inputSchema: schema({ url: { type: "string" }, waitMs: { type: "number" } }) },
|
|
6664
|
+
{ name: "browser.screenshot", description: "Сделать скриншот страницы через Chromium.", inputSchema: schema({ url: { type: "string" }, output: { type: "string" }, waitMs: { type: "number" } }) },
|
|
6471
6665
|
];
|
|
6472
6666
|
}
|
|
6473
6667
|
|
|
@@ -6497,6 +6691,14 @@ async function callMcpTool(name, args = {}) {
|
|
|
6497
6691
|
await handleExport([args.name || "education-contacts", "--format", args.format || "xlsx", "--output", output]);
|
|
6498
6692
|
return { output };
|
|
6499
6693
|
}
|
|
6694
|
+
if (name === "browser.text") {
|
|
6695
|
+
return runBrowserAutomation("text", { url: args.url, waitMs: Number(args.waitMs || 0), timeout: Number(args.timeout || 30000), viewport: args.viewport || "1366x768" });
|
|
6696
|
+
}
|
|
6697
|
+
if (name === "browser.screenshot") {
|
|
6698
|
+
const output = path.resolve(args.output || "browser-page.png");
|
|
6699
|
+
await runBrowserAutomation("screenshot", { url: args.url, output, waitMs: Number(args.waitMs || 0), timeout: Number(args.timeout || 30000), viewport: args.viewport || "1366x768" });
|
|
6700
|
+
return { output };
|
|
6701
|
+
}
|
|
6500
6702
|
return executeRpc(name, { ...args, _: [] });
|
|
6501
6703
|
}
|
|
6502
6704
|
|
package/wiki/Home.md
CHANGED
|
@@ -32,6 +32,7 @@ iola ask "найди школу 29"
|
|
|
32
32
|
- [Локальные файлы](Локальные-файлы)
|
|
33
33
|
- [Рабочая среда агента](Рабочая-среда-агента)
|
|
34
34
|
- [Платформа агента](Платформа-агента)
|
|
35
|
+
- [Браузерный агент](Браузерный-агент)
|
|
35
36
|
- [Расширения и локальные данные](Расширения-и-локальные-данные)
|
|
36
37
|
- [Архивы и мастер настройки](Архивы-и-мастер-настройки)
|
|
37
38
|
- [Daemon, RPC и cron](Daemon-RPC-и-cron)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Браузерный агент
|
|
2
|
+
|
|
3
|
+
`iola-cli` умеет подключать локальный браузерный runtime на Playwright. Сам npm-пакет остается легким: Chromium и Playwright ставятся отдельно при первом включении браузера.
|
|
4
|
+
|
|
5
|
+
## Установка
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
iola browser status
|
|
9
|
+
iola browser install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Runtime хранится в `~/.iola/browser-runtime`.
|
|
13
|
+
|
|
14
|
+
## Базовые команды
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
iola browser open https://example.com
|
|
18
|
+
iola browser text https://example.com
|
|
19
|
+
iola browser html https://example.com --output page.html
|
|
20
|
+
iola browser screenshot https://example.com --output page.png
|
|
21
|
+
iola browser pdf https://example.com --output page.pdf
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`open` запускает видимый Chromium и держит его открытым. По умолчанию окно живет 10 минут. Можно задать время:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
iola browser open https://example.com --wait 30000
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Действия на странице
|
|
31
|
+
|
|
32
|
+
Клик:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
iola browser click https://example.com --selector "button" --output after-click.png
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Ввод:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
iola browser type https://example.com --selector "#q" --text "школа 29" --press Enter --wait 2000 --output search.png
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Выполнение JavaScript-выражения:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
iola browser eval https://example.com --script "document.title"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## MCP
|
|
51
|
+
|
|
52
|
+
Локальный MCP server также отдает браузерные tools:
|
|
53
|
+
|
|
54
|
+
- `browser.text`;
|
|
55
|
+
- `browser.screenshot`.
|
|
56
|
+
|
|
57
|
+
Перед использованием этих tools нужно один раз выполнить:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
iola browser install
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Режимы
|
|
64
|
+
|
|
65
|
+
- Для чтения страниц используйте `text`, `html`, `screenshot`, `pdf`.
|
|
66
|
+
- Для действий используйте `click` и `type`.
|
|
67
|
+
- Для ручной авторизации или просмотра используйте `open`.
|
|
68
|
+
|
|
@@ -74,6 +74,10 @@ iola import file data.csv --dataset custom
|
|
|
74
74
|
iola index folder ./docs
|
|
75
75
|
iola reports list
|
|
76
76
|
iola plugins list
|
|
77
|
+
iola browser status
|
|
78
|
+
iola browser install
|
|
79
|
+
iola browser text https://example.com
|
|
80
|
+
iola browser screenshot https://example.com --output page.png
|
|
77
81
|
iola mcp serve
|
|
78
82
|
iola mcp serve --stdio
|
|
79
83
|
iola memory suggest
|