@hasna/browser 0.2.5 → 0.3.0
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/dist/cli/index.js +815 -549
- package/dist/db/scripts.d.ts +84 -0
- package/dist/db/scripts.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/lib/ai-inference.d.ts +21 -0
- package/dist/lib/ai-inference.d.ts.map +1 -0
- package/dist/lib/login-scripts.d.ts +5 -1
- package/dist/lib/login-scripts.d.ts.map +1 -1
- package/dist/lib/script-engine.d.ts +28 -0
- package/dist/lib/script-engine.d.ts.map +1 -0
- package/dist/mcp/index.js +645 -389
- package/dist/server/index.js +44 -0
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -4,6 +4,7 @@ var __create = Object.create;
|
|
|
4
4
|
var __getProtoOf = Object.getPrototypeOf;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
9
|
var __toESM = (mod, isNodeMode, target) => {
|
|
9
10
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
@@ -16,6 +17,20 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
16
17
|
});
|
|
17
18
|
return to;
|
|
18
19
|
};
|
|
20
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
21
|
+
var __toCommonJS = (from) => {
|
|
22
|
+
var entry = __moduleCache.get(from), desc;
|
|
23
|
+
if (entry)
|
|
24
|
+
return entry;
|
|
25
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
26
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
27
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
28
|
+
get: () => from[key],
|
|
29
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
30
|
+
}));
|
|
31
|
+
__moduleCache.set(from, entry);
|
|
32
|
+
return entry;
|
|
33
|
+
};
|
|
19
34
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
20
35
|
var __export = (target, all) => {
|
|
21
36
|
for (var name in all)
|
|
@@ -372,6 +387,50 @@ function runMigrations(db) {
|
|
|
372
387
|
);
|
|
373
388
|
CREATE INDEX IF NOT EXISTS idx_api_endpoints_session ON api_endpoints(session_id);
|
|
374
389
|
`
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
version: 9,
|
|
393
|
+
sql: `
|
|
394
|
+
CREATE TABLE IF NOT EXISTS scripts (
|
|
395
|
+
id TEXT PRIMARY KEY,
|
|
396
|
+
name TEXT NOT NULL UNIQUE,
|
|
397
|
+
domain TEXT NOT NULL DEFAULT '',
|
|
398
|
+
description TEXT DEFAULT '',
|
|
399
|
+
variables TEXT NOT NULL DEFAULT '{}',
|
|
400
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
401
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
402
|
+
last_run TEXT,
|
|
403
|
+
run_count INTEGER DEFAULT 0
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
CREATE TABLE IF NOT EXISTS script_steps (
|
|
407
|
+
id TEXT PRIMARY KEY,
|
|
408
|
+
script_id TEXT NOT NULL REFERENCES scripts(id) ON DELETE CASCADE,
|
|
409
|
+
step_order INTEGER NOT NULL,
|
|
410
|
+
type TEXT NOT NULL,
|
|
411
|
+
config TEXT NOT NULL DEFAULT '{}',
|
|
412
|
+
description TEXT DEFAULT '',
|
|
413
|
+
ai_enabled INTEGER DEFAULT 0,
|
|
414
|
+
ai_config TEXT DEFAULT '{}'
|
|
415
|
+
);
|
|
416
|
+
CREATE INDEX IF NOT EXISTS idx_script_steps_order ON script_steps(script_id, step_order);
|
|
417
|
+
|
|
418
|
+
CREATE TABLE IF NOT EXISTS script_runs (
|
|
419
|
+
id TEXT PRIMARY KEY,
|
|
420
|
+
script_id TEXT NOT NULL REFERENCES scripts(id) ON DELETE CASCADE,
|
|
421
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
422
|
+
current_step INTEGER DEFAULT 0,
|
|
423
|
+
total_steps INTEGER DEFAULT 0,
|
|
424
|
+
current_description TEXT DEFAULT '',
|
|
425
|
+
variables TEXT DEFAULT '{}',
|
|
426
|
+
steps_log TEXT DEFAULT '[]',
|
|
427
|
+
errors TEXT DEFAULT '[]',
|
|
428
|
+
started_at TEXT DEFAULT (datetime('now')),
|
|
429
|
+
completed_at TEXT,
|
|
430
|
+
duration_ms INTEGER
|
|
431
|
+
);
|
|
432
|
+
CREATE INDEX IF NOT EXISTS idx_script_runs_script ON script_runs(script_id, status);
|
|
433
|
+
`
|
|
375
434
|
}
|
|
376
435
|
];
|
|
377
436
|
for (const m of migrations) {
|
|
@@ -2271,6 +2330,10 @@ var init_snapshot = __esm(() => {
|
|
|
2271
2330
|
});
|
|
2272
2331
|
|
|
2273
2332
|
// src/lib/self-heal.ts
|
|
2333
|
+
var exports_self_heal = {};
|
|
2334
|
+
__export(exports_self_heal, {
|
|
2335
|
+
healSelector: () => healSelector
|
|
2336
|
+
});
|
|
2274
2337
|
async function healSelector(page, selector, sessionId) {
|
|
2275
2338
|
const attempts = [];
|
|
2276
2339
|
attempts.push(`selector: ${selector}`);
|
|
@@ -6583,7 +6646,7 @@ var require_operation = __commonJS((exports, module) => {
|
|
|
6583
6646
|
// node_modules/@img/colour/color.cjs
|
|
6584
6647
|
var require_color = __commonJS((exports, module) => {
|
|
6585
6648
|
var __defProp2 = Object.defineProperty;
|
|
6586
|
-
var
|
|
6649
|
+
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
6587
6650
|
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
6588
6651
|
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
6589
6652
|
var __export2 = (target, all) => {
|
|
@@ -6594,16 +6657,16 @@ var require_color = __commonJS((exports, module) => {
|
|
|
6594
6657
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
6595
6658
|
for (let key of __getOwnPropNames2(from))
|
|
6596
6659
|
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
6597
|
-
__defProp2(to, key, { get: () => from[key], enumerable: !(desc =
|
|
6660
|
+
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
6598
6661
|
}
|
|
6599
6662
|
return to;
|
|
6600
6663
|
};
|
|
6601
|
-
var
|
|
6664
|
+
var __toCommonJS2 = (mod) => __copyProps(__defProp2({}, "__esModule", { value: true }), mod);
|
|
6602
6665
|
var index_exports = {};
|
|
6603
6666
|
__export2(index_exports, {
|
|
6604
6667
|
default: () => index_default
|
|
6605
6668
|
});
|
|
6606
|
-
module.exports =
|
|
6669
|
+
module.exports = __toCommonJS2(index_exports);
|
|
6607
6670
|
var colors = {
|
|
6608
6671
|
aliceblue: [240, 248, 255],
|
|
6609
6672
|
antiquewhite: [250, 235, 215],
|
|
@@ -10602,325 +10665,498 @@ async function clickByVision(page, description, opts) {
|
|
|
10602
10665
|
}
|
|
10603
10666
|
var DEFAULT_MODEL = "claude-sonnet-4-5-20250929";
|
|
10604
10667
|
|
|
10605
|
-
// src/
|
|
10606
|
-
var
|
|
10607
|
-
__export(
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
10668
|
+
// src/db/scripts.ts
|
|
10669
|
+
var exports_scripts = {};
|
|
10670
|
+
__export(exports_scripts, {
|
|
10671
|
+
upsertScript: () => upsertScript,
|
|
10672
|
+
updateRunProgress: () => updateRunProgress,
|
|
10673
|
+
startRun: () => startRun,
|
|
10674
|
+
migrateJsonScripts: () => migrateJsonScripts,
|
|
10612
10675
|
listScripts: () => listScripts,
|
|
10613
|
-
|
|
10614
|
-
|
|
10676
|
+
listRuns: () => listRuns,
|
|
10677
|
+
getSteps: () => getSteps,
|
|
10678
|
+
getScriptByName: () => getScriptByName,
|
|
10679
|
+
getScript: () => getScript,
|
|
10680
|
+
getRun: () => getRun,
|
|
10681
|
+
deleteScriptByName: () => deleteScriptByName,
|
|
10615
10682
|
deleteScript: () => deleteScript,
|
|
10616
|
-
|
|
10617
|
-
|
|
10683
|
+
createScript: () => createScript,
|
|
10684
|
+
completeRun: () => completeRun
|
|
10618
10685
|
});
|
|
10619
10686
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10687
|
+
function createScript(data) {
|
|
10688
|
+
const db = getDatabase();
|
|
10689
|
+
const id = randomUUID12();
|
|
10690
|
+
db.prepare("INSERT INTO scripts (id, name, domain, description, variables) VALUES (?, ?, ?, ?, ?)").run(id, data.name, data.domain ?? "", data.description ?? "", JSON.stringify(data.variables ?? {}));
|
|
10691
|
+
for (let i = 0;i < data.steps.length; i++) {
|
|
10692
|
+
const step = data.steps[i];
|
|
10693
|
+
db.prepare("INSERT INTO script_steps (id, script_id, step_order, type, config, description, ai_enabled, ai_config) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(randomUUID12(), id, i, step.type, JSON.stringify(step.config), step.description ?? "", step.ai_enabled ? 1 : 0, JSON.stringify(step.ai_config ?? {}));
|
|
10694
|
+
}
|
|
10695
|
+
return getScript(id);
|
|
10627
10696
|
}
|
|
10628
|
-
function
|
|
10629
|
-
const
|
|
10630
|
-
|
|
10631
|
-
|
|
10697
|
+
function upsertScript(data) {
|
|
10698
|
+
const existing = getScriptByName(data.name);
|
|
10699
|
+
if (existing) {
|
|
10700
|
+
deleteScript(existing.id);
|
|
10701
|
+
}
|
|
10702
|
+
return createScript(data);
|
|
10632
10703
|
}
|
|
10633
|
-
function
|
|
10634
|
-
const
|
|
10635
|
-
const
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
writeFileSync3(path, JSON.stringify(script, null, 2));
|
|
10640
|
-
return path;
|
|
10704
|
+
function getScript(id) {
|
|
10705
|
+
const db = getDatabase();
|
|
10706
|
+
const row = db.query("SELECT * FROM scripts WHERE id = ?").get(id);
|
|
10707
|
+
if (!row)
|
|
10708
|
+
return null;
|
|
10709
|
+
return { ...row, variables: JSON.parse(row.variables), run_count: row.run_count ?? 0 };
|
|
10641
10710
|
}
|
|
10642
|
-
function
|
|
10643
|
-
const
|
|
10644
|
-
|
|
10711
|
+
function getScriptByName(name) {
|
|
10712
|
+
const db = getDatabase();
|
|
10713
|
+
const row = db.query("SELECT * FROM scripts WHERE name = ?").get(name);
|
|
10714
|
+
if (!row)
|
|
10645
10715
|
return null;
|
|
10646
|
-
return JSON.parse(
|
|
10716
|
+
return { ...row, variables: JSON.parse(row.variables), run_count: row.run_count ?? 0 };
|
|
10647
10717
|
}
|
|
10648
10718
|
function listScripts() {
|
|
10649
|
-
const
|
|
10719
|
+
const db = getDatabase();
|
|
10720
|
+
return db.query("SELECT * FROM scripts ORDER BY updated_at DESC").all().map((row) => ({ ...row, variables: JSON.parse(row.variables), run_count: row.run_count ?? 0 }));
|
|
10721
|
+
}
|
|
10722
|
+
function deleteScript(id) {
|
|
10723
|
+
const db = getDatabase();
|
|
10724
|
+
return db.prepare("DELETE FROM scripts WHERE id = ?").run(id).changes > 0;
|
|
10725
|
+
}
|
|
10726
|
+
function deleteScriptByName(name) {
|
|
10727
|
+
const db = getDatabase();
|
|
10728
|
+
return db.prepare("DELETE FROM scripts WHERE name = ?").run(name).changes > 0;
|
|
10729
|
+
}
|
|
10730
|
+
function getSteps(scriptId) {
|
|
10731
|
+
const db = getDatabase();
|
|
10732
|
+
return db.query("SELECT * FROM script_steps WHERE script_id = ? ORDER BY step_order").all(scriptId).map((row) => ({
|
|
10733
|
+
...row,
|
|
10734
|
+
config: JSON.parse(row.config),
|
|
10735
|
+
ai_enabled: !!row.ai_enabled,
|
|
10736
|
+
ai_config: JSON.parse(row.ai_config)
|
|
10737
|
+
}));
|
|
10738
|
+
}
|
|
10739
|
+
function startRun(scriptId, totalSteps) {
|
|
10740
|
+
const db = getDatabase();
|
|
10741
|
+
const id = randomUUID12();
|
|
10742
|
+
db.prepare("INSERT INTO script_runs (id, script_id, status, total_steps) VALUES (?, ?, 'running', ?)").run(id, scriptId, totalSteps);
|
|
10743
|
+
return getRun(id);
|
|
10744
|
+
}
|
|
10745
|
+
function updateRunProgress(runId, step, description, stepsLog, variables) {
|
|
10746
|
+
const db = getDatabase();
|
|
10747
|
+
db.prepare("UPDATE script_runs SET current_step = ?, current_description = ?, steps_log = ?, variables = ? WHERE id = ?").run(step, description, JSON.stringify(stepsLog), JSON.stringify(variables), runId);
|
|
10748
|
+
}
|
|
10749
|
+
function completeRun(runId, status, errors2, durationMs) {
|
|
10750
|
+
const db = getDatabase();
|
|
10751
|
+
db.prepare("UPDATE script_runs SET status = ?, errors = ?, duration_ms = ?, completed_at = datetime('now') WHERE id = ?").run(status, JSON.stringify(errors2), durationMs, runId);
|
|
10752
|
+
const run = getRun(runId);
|
|
10753
|
+
if (run) {
|
|
10754
|
+
db.prepare("UPDATE scripts SET last_run = datetime('now'), run_count = run_count + 1, updated_at = datetime('now') WHERE id = ?").run(run.script_id);
|
|
10755
|
+
}
|
|
10756
|
+
}
|
|
10757
|
+
function getRun(runId) {
|
|
10758
|
+
const db = getDatabase();
|
|
10759
|
+
const row = db.query("SELECT * FROM script_runs WHERE id = ?").get(runId);
|
|
10760
|
+
if (!row)
|
|
10761
|
+
return null;
|
|
10762
|
+
return {
|
|
10763
|
+
...row,
|
|
10764
|
+
variables: JSON.parse(row.variables),
|
|
10765
|
+
steps_log: JSON.parse(row.steps_log),
|
|
10766
|
+
errors: JSON.parse(row.errors)
|
|
10767
|
+
};
|
|
10768
|
+
}
|
|
10769
|
+
function listRuns(scriptId) {
|
|
10770
|
+
const db = getDatabase();
|
|
10771
|
+
const query = scriptId ? db.query("SELECT * FROM script_runs WHERE script_id = ? ORDER BY started_at DESC LIMIT 20").all(scriptId) : db.query("SELECT * FROM script_runs ORDER BY started_at DESC LIMIT 20").all();
|
|
10772
|
+
return query.map((row) => ({
|
|
10773
|
+
...row,
|
|
10774
|
+
variables: JSON.parse(row.variables),
|
|
10775
|
+
steps_log: JSON.parse(row.steps_log),
|
|
10776
|
+
errors: JSON.parse(row.errors)
|
|
10777
|
+
}));
|
|
10778
|
+
}
|
|
10779
|
+
function migrateJsonScripts() {
|
|
10780
|
+
const { existsSync: existsSync5, readdirSync: readdirSync4, readFileSync: readFileSync3 } = __require("fs");
|
|
10781
|
+
const { join: join9 } = __require("path");
|
|
10782
|
+
const { getDataDir: getDataDir4 } = (init_schema(), __toCommonJS(exports_schema));
|
|
10783
|
+
const dir = join9(getDataDir4(), "scripts");
|
|
10650
10784
|
if (!existsSync5(dir))
|
|
10651
|
-
return
|
|
10652
|
-
|
|
10785
|
+
return 0;
|
|
10786
|
+
const files = readdirSync4(dir).filter((f) => f.endsWith(".json"));
|
|
10787
|
+
let migrated = 0;
|
|
10788
|
+
for (const file of files) {
|
|
10653
10789
|
try {
|
|
10654
|
-
const
|
|
10655
|
-
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10790
|
+
const raw = JSON.parse(readFileSync3(join9(dir, file), "utf8"));
|
|
10791
|
+
if (!raw.name || !raw.steps)
|
|
10792
|
+
continue;
|
|
10793
|
+
if (getScriptByName(raw.name))
|
|
10794
|
+
continue;
|
|
10795
|
+
const steps = raw.steps.map((s) => {
|
|
10796
|
+
const isAI = s.type === "ai";
|
|
10797
|
+
return {
|
|
10798
|
+
type: isAI ? "extract" : s.type,
|
|
10799
|
+
config: {
|
|
10800
|
+
action: s.action,
|
|
10801
|
+
selector: s.selector,
|
|
10802
|
+
url: s.url,
|
|
10803
|
+
value: s.value,
|
|
10804
|
+
text: s.text,
|
|
10805
|
+
timeout: s.timeout,
|
|
10806
|
+
connector: s.connector,
|
|
10807
|
+
args: s.args,
|
|
10808
|
+
format: s.format,
|
|
10809
|
+
pattern: s.pattern,
|
|
10810
|
+
json_path: s.json_path,
|
|
10811
|
+
check: s.check,
|
|
10812
|
+
source: s.check,
|
|
10813
|
+
seconds: s.seconds,
|
|
10814
|
+
equals: s.equals,
|
|
10815
|
+
contains: s.contains,
|
|
10816
|
+
skip_to: s.skip_to,
|
|
10817
|
+
name: s.name,
|
|
10818
|
+
save_as: s.save_as,
|
|
10819
|
+
...isAI ? { prompt: s.prompt, source: s.check ?? "last_output" } : {}
|
|
10820
|
+
},
|
|
10821
|
+
description: s.description ?? "",
|
|
10822
|
+
ai_enabled: isAI || !!s.ai?.enabled,
|
|
10823
|
+
ai_config: isAI ? { provider: s.model === "haiku" || s.model === "sonnet" || s.model === "opus" ? "anthropic" : "cerebras", model: s.model ?? "fast" } : s.ai ?? {}
|
|
10824
|
+
};
|
|
10825
|
+
});
|
|
10826
|
+
createScript({
|
|
10827
|
+
name: raw.name,
|
|
10828
|
+
domain: raw.domain ?? "",
|
|
10829
|
+
description: raw.description ?? "",
|
|
10830
|
+
variables: raw.variables ?? {},
|
|
10831
|
+
steps
|
|
10832
|
+
});
|
|
10833
|
+
migrated++;
|
|
10834
|
+
} catch {}
|
|
10835
|
+
}
|
|
10836
|
+
return migrated;
|
|
10660
10837
|
}
|
|
10661
|
-
|
|
10662
|
-
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10838
|
+
var init_scripts = __esm(() => {
|
|
10839
|
+
init_schema();
|
|
10840
|
+
});
|
|
10841
|
+
|
|
10842
|
+
// src/lib/ai-inference.ts
|
|
10843
|
+
function resolve(opts) {
|
|
10844
|
+
if (opts?.model && ALIASES[opts.model])
|
|
10845
|
+
return ALIASES[opts.model];
|
|
10846
|
+
if (opts?.provider && opts?.model)
|
|
10847
|
+
return { provider: opts.provider, model: opts.model };
|
|
10848
|
+
if (opts?.provider === "anthropic")
|
|
10849
|
+
return ALIASES.haiku;
|
|
10850
|
+
return ALIASES.fast;
|
|
10851
|
+
}
|
|
10852
|
+
async function infer(prompt, opts) {
|
|
10853
|
+
const { provider, model } = resolve(opts);
|
|
10854
|
+
const maxTokens = opts?.maxTokens ?? 1024;
|
|
10855
|
+
if (provider === "anthropic") {
|
|
10856
|
+
const apiKey2 = process.env["ANTHROPIC_API_KEY"];
|
|
10857
|
+
if (!apiKey2)
|
|
10858
|
+
throw new Error("ANTHROPIC_API_KEY not set");
|
|
10859
|
+
const res2 = await fetch("https://api.anthropic.com/v1/messages", {
|
|
10860
|
+
method: "POST",
|
|
10861
|
+
headers: { "content-type": "application/json", "x-api-key": apiKey2, "anthropic-version": "2023-06-01" },
|
|
10862
|
+
body: JSON.stringify({ model, max_tokens: maxTokens, messages: [{ role: "user", content: prompt }] })
|
|
10863
|
+
});
|
|
10864
|
+
if (!res2.ok)
|
|
10865
|
+
throw new Error(`Anthropic API ${res2.status}: ${(await res2.text()).slice(0, 200)}`);
|
|
10866
|
+
const data2 = await res2.json();
|
|
10867
|
+
return data2.content?.[0]?.text ?? "";
|
|
10868
|
+
}
|
|
10869
|
+
const apiKey = process.env["CEREBRAS_API_KEY"];
|
|
10870
|
+
if (!apiKey)
|
|
10871
|
+
throw new Error("CEREBRAS_API_KEY not set");
|
|
10872
|
+
const res = await fetch("https://api.cerebras.ai/v1/chat/completions", {
|
|
10873
|
+
method: "POST",
|
|
10874
|
+
headers: { "content-type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
10875
|
+
body: JSON.stringify({ model, max_tokens: maxTokens, temperature: opts?.temperature ?? 0, messages: [{ role: "user", content: prompt }] })
|
|
10876
|
+
});
|
|
10877
|
+
if (!res.ok)
|
|
10878
|
+
throw new Error(`Cerebras API ${res.status}: ${(await res.text()).slice(0, 200)}`);
|
|
10879
|
+
const data = await res.json();
|
|
10880
|
+
return data.choices?.[0]?.message?.content ?? "";
|
|
10668
10881
|
}
|
|
10882
|
+
var ALIASES;
|
|
10883
|
+
var init_ai_inference = __esm(() => {
|
|
10884
|
+
ALIASES = {
|
|
10885
|
+
fast: { provider: "cerebras", model: "llama-4-scout-17b-16e-instruct" },
|
|
10886
|
+
scout: { provider: "cerebras", model: "llama-4-scout-17b-16e-instruct" },
|
|
10887
|
+
maverick: { provider: "cerebras", model: "llama-4-maverick-17b-128e-instruct" },
|
|
10888
|
+
haiku: { provider: "anthropic", model: "claude-haiku-4-5-20251001" },
|
|
10889
|
+
sonnet: { provider: "anthropic", model: "claude-sonnet-4-5-20250929" },
|
|
10890
|
+
opus: { provider: "anthropic", model: "claude-opus-4-6" }
|
|
10891
|
+
};
|
|
10892
|
+
});
|
|
10893
|
+
|
|
10894
|
+
// src/lib/script-engine.ts
|
|
10895
|
+
var exports_script_engine = {};
|
|
10896
|
+
__export(exports_script_engine, {
|
|
10897
|
+
executeScriptSync: () => executeScriptSync,
|
|
10898
|
+
executeScript: () => executeScript
|
|
10899
|
+
});
|
|
10669
10900
|
function interpolate(template, vars) {
|
|
10670
|
-
return template.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (
|
|
10671
|
-
|
|
10901
|
+
return template.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
10902
|
+
}
|
|
10903
|
+
function interpolateConfig(config, vars) {
|
|
10904
|
+
const result = {};
|
|
10905
|
+
for (const [k, v] of Object.entries(config)) {
|
|
10906
|
+
if (typeof v === "string")
|
|
10907
|
+
result[k] = interpolate(v, vars);
|
|
10908
|
+
else if (Array.isArray(v))
|
|
10909
|
+
result[k] = v.map((item) => typeof item === "string" ? interpolate(item, vars) : item);
|
|
10910
|
+
else
|
|
10911
|
+
result[k] = v;
|
|
10912
|
+
}
|
|
10913
|
+
return result;
|
|
10914
|
+
}
|
|
10915
|
+
function executeScript(scriptId, page, overrides = {}) {
|
|
10916
|
+
const steps = getSteps(scriptId);
|
|
10917
|
+
const run = startRun(scriptId, steps.length);
|
|
10918
|
+
_runSteps(run.id, scriptId, steps, page, overrides).catch((err) => {
|
|
10919
|
+
completeRun(run.id, "failed", [err instanceof Error ? err.message : String(err)], 0);
|
|
10672
10920
|
});
|
|
10921
|
+
return run.id;
|
|
10673
10922
|
}
|
|
10674
|
-
function
|
|
10675
|
-
|
|
10923
|
+
async function executeScriptSync(scriptId, page, overrides = {}) {
|
|
10924
|
+
const steps = getSteps(scriptId);
|
|
10925
|
+
const run = startRun(scriptId, steps.length);
|
|
10926
|
+
return _runSteps(run.id, scriptId, steps, page, overrides);
|
|
10676
10927
|
}
|
|
10677
|
-
async function
|
|
10928
|
+
async function _runSteps(runId, scriptId, steps, page, overrides) {
|
|
10678
10929
|
const t0 = Date.now();
|
|
10679
|
-
const
|
|
10930
|
+
const { getScript: getScript2 } = await Promise.resolve().then(() => (init_scripts(), exports_scripts));
|
|
10931
|
+
const script = getScript2(scriptId);
|
|
10932
|
+
const vars = { ...script?.variables ?? {}, ...overrides };
|
|
10680
10933
|
const errors2 = [];
|
|
10934
|
+
const stepsLog = [];
|
|
10681
10935
|
let executed = 0;
|
|
10682
10936
|
let failed = 0;
|
|
10683
|
-
|
|
10684
|
-
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
current_step: 0,
|
|
10688
|
-
total_steps: script.steps.length,
|
|
10689
|
-
current_step_description: "Starting...",
|
|
10690
|
-
steps_log: [],
|
|
10691
|
-
started_at: new Date().toISOString()
|
|
10692
|
-
};
|
|
10693
|
-
activeJobs.set(job.id, job);
|
|
10694
|
-
for (let i = 0;i < script.steps.length; i++) {
|
|
10695
|
-
const step = script.steps[i];
|
|
10696
|
-
const desc = stepDescription(step);
|
|
10937
|
+
for (let i = 0;i < steps.length; i++) {
|
|
10938
|
+
const step = steps[i];
|
|
10939
|
+
const cfg = interpolateConfig(step.config, vars);
|
|
10940
|
+
const desc = step.description || `${step.type}`;
|
|
10697
10941
|
executed++;
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
job.steps_log.push({ step: i + 1, type: step.type, description: desc, status: "running" });
|
|
10942
|
+
stepsLog.push({ step: i + 1, type: step.type, description: desc, status: "running" });
|
|
10943
|
+
updateRunProgress(runId, i + 1, desc, stepsLog, vars);
|
|
10701
10944
|
const stepStart = Date.now();
|
|
10702
10945
|
try {
|
|
10703
10946
|
switch (step.type) {
|
|
10704
10947
|
case "browser":
|
|
10705
|
-
await
|
|
10948
|
+
await execBrowser(cfg, step, page, vars);
|
|
10706
10949
|
break;
|
|
10707
10950
|
case "connector":
|
|
10708
|
-
await
|
|
10951
|
+
await execConnector(cfg, step, vars);
|
|
10709
10952
|
break;
|
|
10710
10953
|
case "extract":
|
|
10711
|
-
|
|
10954
|
+
await execExtract(cfg, step, vars);
|
|
10712
10955
|
break;
|
|
10713
10956
|
case "wait":
|
|
10714
|
-
await new Promise((r) => setTimeout(r, (
|
|
10957
|
+
await new Promise((r) => setTimeout(r, (cfg.seconds ?? 3) * 1000));
|
|
10715
10958
|
break;
|
|
10716
|
-
case "condition":
|
|
10717
|
-
|
|
10718
|
-
let conditionMet = true;
|
|
10719
|
-
if (step.equals !== undefined)
|
|
10720
|
-
conditionMet = checkVal === interpolate(step.equals, vars);
|
|
10721
|
-
if (step.contains !== undefined)
|
|
10722
|
-
conditionMet = checkVal?.includes(interpolate(step.contains, vars)) ?? false;
|
|
10723
|
-
if (!conditionMet && step.skip_to !== undefined) {
|
|
10724
|
-
i = step.skip_to - 1;
|
|
10725
|
-
}
|
|
10959
|
+
case "condition":
|
|
10960
|
+
i = execCondition(cfg, vars, i);
|
|
10726
10961
|
break;
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
const stateName = interpolate(step.name ?? script.name, vars);
|
|
10730
|
-
try {
|
|
10731
|
-
const { saveStateFromPage: saveStateFromPage2 } = await Promise.resolve().then(() => (init_storage_state(), exports_storage_state));
|
|
10732
|
-
const path = await saveStateFromPage2(page, stateName);
|
|
10733
|
-
vars["saved_state_path"] = path;
|
|
10734
|
-
} catch {}
|
|
10962
|
+
case "save_state":
|
|
10963
|
+
await execSaveState(cfg, page, vars);
|
|
10735
10964
|
break;
|
|
10736
|
-
}
|
|
10737
10965
|
}
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
logEntry.duration_ms = Date.now() - stepStart;
|
|
10966
|
+
stepsLog[stepsLog.length - 1].status = "ok";
|
|
10967
|
+
stepsLog[stepsLog.length - 1].duration_ms = Date.now() - stepStart;
|
|
10741
10968
|
} catch (err) {
|
|
10742
10969
|
failed++;
|
|
10743
|
-
const msg = `Step ${i + 1} (${step.type}
|
|
10970
|
+
const msg = `Step ${i + 1} (${step.type}): ${err instanceof Error ? err.message : String(err)}`;
|
|
10744
10971
|
errors2.push(msg);
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
if (step.type === "browser" && step.action === "navigate")
|
|
10972
|
+
stepsLog[stepsLog.length - 1].status = "failed";
|
|
10973
|
+
stepsLog[stepsLog.length - 1].error = err instanceof Error ? err.message : String(err);
|
|
10974
|
+
stepsLog[stepsLog.length - 1].duration_ms = Date.now() - stepStart;
|
|
10975
|
+
if (step.type === "browser" && cfg.action === "navigate")
|
|
10750
10976
|
break;
|
|
10751
10977
|
}
|
|
10978
|
+
updateRunProgress(runId, i + 1, desc, stepsLog, vars);
|
|
10752
10979
|
}
|
|
10753
|
-
const
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
variables: vars,
|
|
10758
|
-
errors: errors2,
|
|
10759
|
-
duration_ms: Date.now() - t0
|
|
10760
|
-
};
|
|
10761
|
-
job.status = failed === 0 ? "completed" : "failed";
|
|
10762
|
-
job.result = result;
|
|
10763
|
-
return result;
|
|
10764
|
-
}
|
|
10765
|
-
function runScriptAsync(script, page, overrides = {}) {
|
|
10766
|
-
const jobId = randomUUID12();
|
|
10767
|
-
const job = {
|
|
10768
|
-
id: jobId,
|
|
10769
|
-
script_name: script.name,
|
|
10770
|
-
status: "running",
|
|
10771
|
-
current_step: 0,
|
|
10772
|
-
total_steps: script.steps.length,
|
|
10773
|
-
current_step_description: "Starting...",
|
|
10774
|
-
steps_log: [],
|
|
10775
|
-
started_at: new Date().toISOString()
|
|
10776
|
-
};
|
|
10777
|
-
activeJobs.set(jobId, job);
|
|
10778
|
-
runScript(script, page, overrides, jobId).catch((err) => {
|
|
10779
|
-
job.status = "failed";
|
|
10780
|
-
job.current_step_description = `Fatal error: ${err instanceof Error ? err.message : String(err)}`;
|
|
10781
|
-
});
|
|
10782
|
-
return jobId;
|
|
10980
|
+
const durationMs = Date.now() - t0;
|
|
10981
|
+
const status = failed === 0 ? "completed" : "failed";
|
|
10982
|
+
completeRun(runId, status, errors2, durationMs);
|
|
10983
|
+
return { run_id: runId, success: failed === 0, steps_executed: executed, steps_failed: failed, errors: errors2, duration_ms: durationMs, variables: vars };
|
|
10783
10984
|
}
|
|
10784
|
-
async function
|
|
10785
|
-
const action =
|
|
10786
|
-
if (!action)
|
|
10787
|
-
throw new Error("Browser step missing action");
|
|
10985
|
+
async function execBrowser(cfg, step, page, vars) {
|
|
10986
|
+
const action = cfg.action;
|
|
10788
10987
|
switch (action) {
|
|
10789
|
-
case "navigate":
|
|
10790
|
-
|
|
10791
|
-
await page.goto(url, { waitUntil: "domcontentloaded", timeout: step.timeout ?? 30000 });
|
|
10988
|
+
case "navigate":
|
|
10989
|
+
await page.goto(cfg.url, { waitUntil: "domcontentloaded", timeout: cfg.timeout ?? 30000 });
|
|
10792
10990
|
await new Promise((r) => setTimeout(r, 1000));
|
|
10793
10991
|
vars["current_url"] = page.url();
|
|
10794
10992
|
vars["current_title"] = await page.title();
|
|
10795
10993
|
break;
|
|
10796
|
-
}
|
|
10797
10994
|
case "type": {
|
|
10798
|
-
const selector =
|
|
10799
|
-
const value =
|
|
10800
|
-
|
|
10995
|
+
const selector = cfg.selector ?? "input";
|
|
10996
|
+
const value = cfg.value ?? cfg.text ?? "";
|
|
10997
|
+
try {
|
|
10998
|
+
await page.fill(selector, value);
|
|
10999
|
+
} catch (origErr) {
|
|
11000
|
+
if (step.ai_enabled) {
|
|
11001
|
+
const healed = await aiSelfHeal(page, `input field for typing "${value}"`, step);
|
|
11002
|
+
if (healed) {
|
|
11003
|
+
await page.mouse.click(healed.x, healed.y);
|
|
11004
|
+
await page.keyboard.type(value);
|
|
11005
|
+
} else
|
|
11006
|
+
throw origErr;
|
|
11007
|
+
} else {
|
|
11008
|
+
const { healSelector: healSelector2 } = await Promise.resolve().then(() => exports_self_heal);
|
|
11009
|
+
const result = await healSelector2(page, selector);
|
|
11010
|
+
if (result.found && result.locator)
|
|
11011
|
+
await result.locator.fill(value);
|
|
11012
|
+
else
|
|
11013
|
+
throw origErr;
|
|
11014
|
+
}
|
|
11015
|
+
}
|
|
10801
11016
|
break;
|
|
10802
11017
|
}
|
|
10803
11018
|
case "click": {
|
|
10804
|
-
const selector =
|
|
10805
|
-
|
|
11019
|
+
const selector = cfg.selector;
|
|
11020
|
+
try {
|
|
11021
|
+
await page.click(selector, { timeout: cfg.timeout ?? 1e4 });
|
|
11022
|
+
} catch (origErr) {
|
|
11023
|
+
if (step.ai_enabled) {
|
|
11024
|
+
const healed = await aiSelfHeal(page, `clickable element matching "${selector}"`, step);
|
|
11025
|
+
if (healed)
|
|
11026
|
+
await page.mouse.click(healed.x, healed.y);
|
|
11027
|
+
else
|
|
11028
|
+
throw origErr;
|
|
11029
|
+
} else {
|
|
11030
|
+
const { healSelector: healSelector2 } = await Promise.resolve().then(() => exports_self_heal);
|
|
11031
|
+
const result = await healSelector2(page, selector);
|
|
11032
|
+
if (result.found && result.locator)
|
|
11033
|
+
await result.locator.click();
|
|
11034
|
+
else
|
|
11035
|
+
throw origErr;
|
|
11036
|
+
}
|
|
11037
|
+
}
|
|
10806
11038
|
await new Promise((r) => setTimeout(r, 500));
|
|
10807
11039
|
break;
|
|
10808
11040
|
}
|
|
10809
11041
|
case "click_text": {
|
|
10810
|
-
const text =
|
|
10811
|
-
|
|
11042
|
+
const text = cfg.text;
|
|
11043
|
+
try {
|
|
11044
|
+
await page.getByText(text, { exact: false }).first().click({ timeout: cfg.timeout ?? 1e4 });
|
|
11045
|
+
} catch (origErr) {
|
|
11046
|
+
if (step.ai_enabled) {
|
|
11047
|
+
const healed = await aiSelfHeal(page, `button or link with text "${text}"`, step);
|
|
11048
|
+
if (healed)
|
|
11049
|
+
await page.mouse.click(healed.x, healed.y);
|
|
11050
|
+
else
|
|
11051
|
+
throw origErr;
|
|
11052
|
+
} else
|
|
11053
|
+
throw origErr;
|
|
11054
|
+
}
|
|
10812
11055
|
await new Promise((r) => setTimeout(r, 500));
|
|
10813
11056
|
break;
|
|
10814
11057
|
}
|
|
10815
|
-
case "wait_for_navigation":
|
|
11058
|
+
case "wait_for_navigation":
|
|
10816
11059
|
try {
|
|
10817
|
-
await page.waitForNavigation({ timeout:
|
|
11060
|
+
await page.waitForNavigation({ timeout: cfg.timeout ?? 15000 });
|
|
10818
11061
|
} catch {}
|
|
10819
11062
|
await new Promise((r) => setTimeout(r, 1000));
|
|
10820
11063
|
vars["current_url"] = page.url();
|
|
10821
11064
|
break;
|
|
10822
|
-
}
|
|
10823
11065
|
case "wait_for_text": {
|
|
10824
|
-
const text =
|
|
10825
|
-
await page.waitForSelector(`text=${text}`, { timeout:
|
|
11066
|
+
const text = cfg.text;
|
|
11067
|
+
await page.waitForSelector(`text=${text}`, { timeout: cfg.timeout ?? 1e4 });
|
|
10826
11068
|
break;
|
|
10827
11069
|
}
|
|
10828
|
-
case "snapshot":
|
|
11070
|
+
case "snapshot":
|
|
10829
11071
|
vars["page_text"] = await page.evaluate(() => document.body?.textContent?.trim() ?? "");
|
|
10830
11072
|
break;
|
|
10831
|
-
}
|
|
10832
11073
|
}
|
|
10833
11074
|
}
|
|
10834
|
-
async function
|
|
10835
|
-
const
|
|
10836
|
-
if (!
|
|
10837
|
-
throw new Error("Connector step missing connector
|
|
10838
|
-
const args =
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
|
|
10845
|
-
|
|
10846
|
-
|
|
10847
|
-
|
|
10848
|
-
|
|
10849
|
-
|
|
10850
|
-
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
|
|
10867
|
-
|
|
10868
|
-
|
|
11075
|
+
async function execConnector(cfg, step, vars) {
|
|
11076
|
+
const connector = cfg.connector;
|
|
11077
|
+
if (!connector)
|
|
11078
|
+
throw new Error("Connector step missing 'connector' in config");
|
|
11079
|
+
const args = cfg.args ?? [];
|
|
11080
|
+
const proc = Bun.spawn([`connect-${connector}`, ...args], {
|
|
11081
|
+
stdout: "pipe",
|
|
11082
|
+
stderr: "pipe",
|
|
11083
|
+
env: { ...process.env, HOME: process.env.HOME ?? "" }
|
|
11084
|
+
});
|
|
11085
|
+
const stdout = await new Response(proc.stdout).text();
|
|
11086
|
+
const stderr = await new Response(proc.stderr).text();
|
|
11087
|
+
const exitCode = await proc.exited;
|
|
11088
|
+
if (exitCode !== 0 && !stdout)
|
|
11089
|
+
throw new Error(`Connector ${connector} failed: ${stderr.slice(0, 200)}`);
|
|
11090
|
+
const raw = stdout || stderr;
|
|
11091
|
+
vars["last_output"] = raw;
|
|
11092
|
+
if (step.ai_enabled && step.ai_config?.prompt) {
|
|
11093
|
+
const aiPrompt = interpolate(step.ai_config.prompt, { ...vars, last_output: raw });
|
|
11094
|
+
const provider = step.ai_config.provider ?? "cerebras";
|
|
11095
|
+
const model = step.ai_config.model ?? "fast";
|
|
11096
|
+
const parsed = await infer(aiPrompt, { provider, model });
|
|
11097
|
+
const saveTo = cfg.save_as ?? "last_output";
|
|
11098
|
+
vars[saveTo] = parsed.trim();
|
|
11099
|
+
} else if (cfg.save_as) {
|
|
11100
|
+
vars[cfg.save_as] = raw;
|
|
11101
|
+
}
|
|
11102
|
+
}
|
|
11103
|
+
async function execExtract(cfg, step, vars) {
|
|
11104
|
+
const saveTo = cfg.save_as ?? "extracted";
|
|
11105
|
+
if (step.ai_enabled || cfg.prompt) {
|
|
11106
|
+
const source = cfg.source ? vars[cfg.source] ?? "" : vars["last_output"] ?? "";
|
|
11107
|
+
const prompt = interpolate(cfg.prompt ?? `Extract the key information from this text:
|
|
11108
|
+
|
|
11109
|
+
${source}`, { ...vars, source });
|
|
11110
|
+
const provider = step.ai_config?.provider ?? "cerebras";
|
|
11111
|
+
const model = step.ai_config?.model ?? "fast";
|
|
11112
|
+
const result = await infer(prompt, { provider, model });
|
|
11113
|
+
vars[saveTo] = result.trim();
|
|
11114
|
+
vars["last_output"] = result.trim();
|
|
11115
|
+
return;
|
|
10869
11116
|
}
|
|
10870
|
-
|
|
10871
|
-
|
|
10872
|
-
|
|
10873
|
-
}
|
|
10874
|
-
function runExtractStep(step, vars) {
|
|
10875
|
-
const saveTo = step.save_as ?? "extracted";
|
|
10876
|
-
if (step.pattern) {
|
|
10877
|
-
const source = step.check ? vars[step.check] ?? "" : vars["last_output"] ?? "";
|
|
10878
|
-
const regex = new RegExp(step.pattern);
|
|
10879
|
-
const match = regex.exec(source);
|
|
11117
|
+
if (cfg.pattern) {
|
|
11118
|
+
const source = cfg.source ? vars[cfg.source] ?? "" : vars["last_output"] ?? "";
|
|
11119
|
+
const match = new RegExp(cfg.pattern).exec(source);
|
|
10880
11120
|
if (match) {
|
|
10881
11121
|
vars[saveTo] = decodeHtmlEntities(match[1] ?? match[0]);
|
|
10882
11122
|
}
|
|
10883
11123
|
}
|
|
10884
|
-
if (step.json_path) {
|
|
10885
|
-
const source = vars["last_output"] ?? "{}";
|
|
10886
|
-
try {
|
|
10887
|
-
let obj = JSON.parse(source);
|
|
10888
|
-
for (const key of step.json_path.split(".")) {
|
|
10889
|
-
obj = obj?.[key];
|
|
10890
|
-
}
|
|
10891
|
-
if (obj !== undefined)
|
|
10892
|
-
vars[saveTo] = String(obj);
|
|
10893
|
-
} catch {}
|
|
10894
|
-
}
|
|
10895
11124
|
}
|
|
10896
|
-
function
|
|
10897
|
-
const
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
return
|
|
10906
|
-
name: parsed.name,
|
|
10907
|
-
domain: parsed.domain,
|
|
10908
|
-
description: parsed.description ?? "",
|
|
10909
|
-
variables: parsed.variables ?? {},
|
|
10910
|
-
steps: parsed.steps,
|
|
10911
|
-
created_at: new Date().toISOString(),
|
|
10912
|
-
updated_at: new Date().toISOString()
|
|
10913
|
-
};
|
|
11125
|
+
function execCondition(cfg, vars, i) {
|
|
11126
|
+
const checkVal = vars[cfg.check ?? ""];
|
|
11127
|
+
let met = true;
|
|
11128
|
+
if (cfg.equals !== undefined)
|
|
11129
|
+
met = checkVal === interpolate(cfg.equals, vars);
|
|
11130
|
+
if (cfg.contains !== undefined)
|
|
11131
|
+
met = checkVal?.includes(interpolate(cfg.contains, vars)) ?? false;
|
|
11132
|
+
if (!met && cfg.skip_to !== undefined)
|
|
11133
|
+
return cfg.skip_to - 1;
|
|
11134
|
+
return i;
|
|
10914
11135
|
}
|
|
10915
|
-
function
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
11136
|
+
async function execSaveState(cfg, page, vars) {
|
|
11137
|
+
const name = interpolate(cfg.name ?? "default", vars);
|
|
11138
|
+
try {
|
|
11139
|
+
const { saveStateFromPage: saveStateFromPage2 } = await Promise.resolve().then(() => (init_storage_state(), exports_storage_state));
|
|
11140
|
+
vars["saved_state_path"] = await saveStateFromPage2(page, name);
|
|
11141
|
+
} catch {}
|
|
10919
11142
|
}
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
11143
|
+
async function aiSelfHeal(page, description, step) {
|
|
11144
|
+
try {
|
|
11145
|
+
const { findElementByVision: findElementByVision2 } = await Promise.resolve().then(() => exports_vision_fallback);
|
|
11146
|
+
const provider = step.ai_config?.provider ?? undefined;
|
|
11147
|
+
const model = step.ai_config?.model ?? undefined;
|
|
11148
|
+
const result = await findElementByVision2(page, description, { model: model ?? provider });
|
|
11149
|
+
if (result.found)
|
|
11150
|
+
return { x: result.x, y: result.y };
|
|
11151
|
+
} catch {}
|
|
11152
|
+
return null;
|
|
11153
|
+
}
|
|
11154
|
+
function decodeHtmlEntities(str) {
|
|
11155
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'");
|
|
11156
|
+
}
|
|
11157
|
+
var init_script_engine = __esm(() => {
|
|
11158
|
+
init_scripts();
|
|
11159
|
+
init_ai_inference();
|
|
10924
11160
|
});
|
|
10925
11161
|
|
|
10926
11162
|
// src/lib/api-detector.ts
|
|
@@ -11071,8 +11307,8 @@ __export(exports_datasets, {
|
|
|
11071
11307
|
deleteDataset: () => deleteDataset
|
|
11072
11308
|
});
|
|
11073
11309
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
11074
|
-
import { writeFileSync as
|
|
11075
|
-
import { join as
|
|
11310
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync9 } from "fs";
|
|
11311
|
+
import { join as join9 } from "path";
|
|
11076
11312
|
import { homedir as homedir9 } from "os";
|
|
11077
11313
|
function saveDataset(data) {
|
|
11078
11314
|
const db = getDatabase();
|
|
@@ -11111,14 +11347,14 @@ function exportDataset(name, format) {
|
|
|
11111
11347
|
const dataset = getDatasetByName(name);
|
|
11112
11348
|
if (!dataset)
|
|
11113
11349
|
throw new Error(`Dataset '${name}' not found`);
|
|
11114
|
-
const dir =
|
|
11115
|
-
|
|
11350
|
+
const dir = join9(process.env["BROWSER_DATA_DIR"] ?? join9(homedir9(), ".browser"), "exports");
|
|
11351
|
+
mkdirSync9(dir, { recursive: true });
|
|
11116
11352
|
const filename = `${name}.${format}`;
|
|
11117
|
-
const path =
|
|
11353
|
+
const path = join9(dir, filename);
|
|
11118
11354
|
if (format === "csv") {
|
|
11119
11355
|
const rows = dataset.data;
|
|
11120
11356
|
if (rows.length === 0) {
|
|
11121
|
-
|
|
11357
|
+
writeFileSync3(path, "");
|
|
11122
11358
|
return { path, size: 0 };
|
|
11123
11359
|
}
|
|
11124
11360
|
const headers = Object.keys(rows[0]);
|
|
@@ -11131,11 +11367,11 @@ function exportDataset(name, format) {
|
|
|
11131
11367
|
}
|
|
11132
11368
|
const content = csvLines.join(`
|
|
11133
11369
|
`);
|
|
11134
|
-
|
|
11370
|
+
writeFileSync3(path, content);
|
|
11135
11371
|
return { path, size: content.length };
|
|
11136
11372
|
} else {
|
|
11137
11373
|
const content = JSON.stringify(dataset.data, null, 2);
|
|
11138
|
-
|
|
11374
|
+
writeFileSync3(path, content);
|
|
11139
11375
|
return { path, size: content.length };
|
|
11140
11376
|
}
|
|
11141
11377
|
}
|
|
@@ -11149,8 +11385,8 @@ __export(exports_auth, {
|
|
|
11149
11385
|
loginWithCredentials: () => loginWithCredentials,
|
|
11150
11386
|
getCredentials: () => getCredentials
|
|
11151
11387
|
});
|
|
11152
|
-
import { existsSync as
|
|
11153
|
-
import { join as
|
|
11388
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
11389
|
+
import { join as join10 } from "path";
|
|
11154
11390
|
import { homedir as homedir10 } from "os";
|
|
11155
11391
|
async function getCredentials(service) {
|
|
11156
11392
|
try {
|
|
@@ -11161,9 +11397,9 @@ async function getCredentials(service) {
|
|
|
11161
11397
|
return { email: email.value, password: password.value };
|
|
11162
11398
|
}
|
|
11163
11399
|
} catch {}
|
|
11164
|
-
const secretsPath =
|
|
11165
|
-
if (
|
|
11166
|
-
const content =
|
|
11400
|
+
const secretsPath = join10(homedir10(), ".secrets");
|
|
11401
|
+
if (existsSync5(secretsPath)) {
|
|
11402
|
+
const content = readFileSync3(secretsPath, "utf8");
|
|
11167
11403
|
const lines = content.split(`
|
|
11168
11404
|
`);
|
|
11169
11405
|
const prefix = service.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
@@ -11343,11 +11579,11 @@ __export(exports_dist, {
|
|
|
11343
11579
|
DEFAULT_CONFIG: () => DEFAULT_CONFIG
|
|
11344
11580
|
});
|
|
11345
11581
|
import { Database as Database2 } from "bun:sqlite";
|
|
11346
|
-
import { existsSync as
|
|
11347
|
-
import { dirname, join as
|
|
11348
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as
|
|
11582
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync10 } from "fs";
|
|
11583
|
+
import { dirname, join as join11, resolve as resolve2 } from "path";
|
|
11584
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as readFileSync4, readdirSync as readdirSync4, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
11349
11585
|
import { homedir as homedir11 } from "os";
|
|
11350
|
-
import { basename as basename2, dirname as dirname2, join as join22, resolve as
|
|
11586
|
+
import { basename as basename2, dirname as dirname2, join as join22, resolve as resolve22 } from "path";
|
|
11351
11587
|
import { existsSync as existsSync32, mkdirSync as mkdirSync32, readFileSync as readFileSync22, writeFileSync as writeFileSync22 } from "fs";
|
|
11352
11588
|
import { homedir as homedir22 } from "os";
|
|
11353
11589
|
import { join as join32 } from "path";
|
|
@@ -11358,10 +11594,10 @@ function isInMemoryDb(path) {
|
|
|
11358
11594
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
11359
11595
|
}
|
|
11360
11596
|
function findNearestMementosDb(startDir) {
|
|
11361
|
-
let dir =
|
|
11597
|
+
let dir = resolve2(startDir);
|
|
11362
11598
|
while (true) {
|
|
11363
|
-
const candidate =
|
|
11364
|
-
if (
|
|
11599
|
+
const candidate = join11(dir, ".mementos", "mementos.db");
|
|
11600
|
+
if (existsSync6(candidate))
|
|
11365
11601
|
return candidate;
|
|
11366
11602
|
const parent = dirname(dir);
|
|
11367
11603
|
if (parent === dir)
|
|
@@ -11371,9 +11607,9 @@ function findNearestMementosDb(startDir) {
|
|
|
11371
11607
|
return null;
|
|
11372
11608
|
}
|
|
11373
11609
|
function findGitRoot(startDir) {
|
|
11374
|
-
let dir =
|
|
11610
|
+
let dir = resolve2(startDir);
|
|
11375
11611
|
while (true) {
|
|
11376
|
-
if (
|
|
11612
|
+
if (existsSync6(join11(dir, ".git")))
|
|
11377
11613
|
return dir;
|
|
11378
11614
|
const parent = dirname(dir);
|
|
11379
11615
|
if (parent === dir)
|
|
@@ -11393,18 +11629,18 @@ function getDbPath() {
|
|
|
11393
11629
|
if (process.env["MEMENTOS_DB_SCOPE"] === "project") {
|
|
11394
11630
|
const gitRoot = findGitRoot(cwd);
|
|
11395
11631
|
if (gitRoot) {
|
|
11396
|
-
return
|
|
11632
|
+
return join11(gitRoot, ".mementos", "mementos.db");
|
|
11397
11633
|
}
|
|
11398
11634
|
}
|
|
11399
11635
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
11400
|
-
return
|
|
11636
|
+
return join11(home, ".mementos", "mementos.db");
|
|
11401
11637
|
}
|
|
11402
11638
|
function ensureDir2(filePath) {
|
|
11403
11639
|
if (isInMemoryDb(filePath))
|
|
11404
11640
|
return;
|
|
11405
|
-
const dir = dirname(
|
|
11406
|
-
if (!
|
|
11407
|
-
|
|
11641
|
+
const dir = dirname(resolve2(filePath));
|
|
11642
|
+
if (!existsSync6(dir)) {
|
|
11643
|
+
mkdirSync10(dir, { recursive: true });
|
|
11408
11644
|
}
|
|
11409
11645
|
}
|
|
11410
11646
|
function getDatabase2(dbPath) {
|
|
@@ -13258,7 +13494,7 @@ function loadConfig() {
|
|
|
13258
13494
|
let fileConfig = {};
|
|
13259
13495
|
if (existsSync22(configPath)) {
|
|
13260
13496
|
try {
|
|
13261
|
-
const raw =
|
|
13497
|
+
const raw = readFileSync4(configPath, "utf-8");
|
|
13262
13498
|
fileConfig = JSON.parse(raw);
|
|
13263
13499
|
} catch {}
|
|
13264
13500
|
}
|
|
@@ -13291,7 +13527,7 @@ function readGlobalConfig() {
|
|
|
13291
13527
|
if (!existsSync22(p))
|
|
13292
13528
|
return {};
|
|
13293
13529
|
try {
|
|
13294
|
-
return JSON.parse(
|
|
13530
|
+
return JSON.parse(readFileSync4(p, "utf-8"));
|
|
13295
13531
|
} catch {
|
|
13296
13532
|
return {};
|
|
13297
13533
|
}
|
|
@@ -13299,7 +13535,7 @@ function readGlobalConfig() {
|
|
|
13299
13535
|
function writeGlobalConfig(data) {
|
|
13300
13536
|
const p = globalConfigPath();
|
|
13301
13537
|
ensureDir22(dirname2(p));
|
|
13302
|
-
|
|
13538
|
+
writeFileSync4(p, JSON.stringify(data, null, 2), "utf-8");
|
|
13303
13539
|
}
|
|
13304
13540
|
function getActiveProfile() {
|
|
13305
13541
|
const envProfile = process.env["MEMENTOS_PROFILE"];
|
|
@@ -13321,7 +13557,7 @@ function listProfiles2() {
|
|
|
13321
13557
|
const dir = profilesDir();
|
|
13322
13558
|
if (!existsSync22(dir))
|
|
13323
13559
|
return [];
|
|
13324
|
-
return
|
|
13560
|
+
return readdirSync4(dir).filter((f) => f.endsWith(".db")).map((f) => basename2(f, ".db")).sort();
|
|
13325
13561
|
}
|
|
13326
13562
|
function deleteProfile2(name) {
|
|
13327
13563
|
const dbPath = join22(profilesDir(), `${name}.db`);
|
|
@@ -15964,30 +16200,30 @@ __export(exports_dist2, {
|
|
|
15964
16200
|
acquireLock: () => acquireLock2
|
|
15965
16201
|
});
|
|
15966
16202
|
import { Database as Database3 } from "bun:sqlite";
|
|
15967
|
-
import { mkdirSync as
|
|
15968
|
-
import { join as
|
|
16203
|
+
import { mkdirSync as mkdirSync11 } from "fs";
|
|
16204
|
+
import { join as join12, dirname as dirname3 } from "path";
|
|
15969
16205
|
import { homedir as homedir12 } from "os";
|
|
15970
16206
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
15971
16207
|
import { mkdirSync as mkdirSync23, copyFileSync as copyFileSync3, statSync as statSync2 } from "fs";
|
|
15972
16208
|
import { join as join33 } from "path";
|
|
15973
16209
|
import { homedir as homedir33 } from "os";
|
|
15974
|
-
import { readFileSync as
|
|
16210
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
15975
16211
|
import { join as join23 } from "path";
|
|
15976
16212
|
import { homedir as homedir23 } from "os";
|
|
15977
16213
|
import { randomUUID as randomUUID22 } from "crypto";
|
|
15978
|
-
import { readFileSync as readFileSync23, writeFileSync as
|
|
16214
|
+
import { readFileSync as readFileSync23, writeFileSync as writeFileSync5, mkdirSync as mkdirSync33 } from "fs";
|
|
15979
16215
|
import { join as join43, dirname as dirname22 } from "path";
|
|
15980
16216
|
import { homedir as homedir42 } from "os";
|
|
15981
16217
|
function getDbPath2() {
|
|
15982
16218
|
if (process.env.CONVERSATIONS_DB_PATH)
|
|
15983
16219
|
return process.env.CONVERSATIONS_DB_PATH;
|
|
15984
|
-
return
|
|
16220
|
+
return join12(homedir12(), ".conversations", "messages.db");
|
|
15985
16221
|
}
|
|
15986
16222
|
function getDb() {
|
|
15987
16223
|
if (db)
|
|
15988
16224
|
return db;
|
|
15989
16225
|
const dbPath = getDbPath2();
|
|
15990
|
-
|
|
16226
|
+
mkdirSync11(dirname3(dbPath), { recursive: true });
|
|
15991
16227
|
db = new Database3(dbPath, { create: true });
|
|
15992
16228
|
db.exec("PRAGMA journal_mode = WAL");
|
|
15993
16229
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
@@ -16229,7 +16465,7 @@ function loadConfig2() {
|
|
|
16229
16465
|
if (cachedConfig && now2 - configLoadedAt < CONFIG_CACHE_MS)
|
|
16230
16466
|
return cachedConfig;
|
|
16231
16467
|
try {
|
|
16232
|
-
const raw =
|
|
16468
|
+
const raw = readFileSync5(getConfigPath(), "utf-8");
|
|
16233
16469
|
cachedConfig = JSON.parse(raw);
|
|
16234
16470
|
configLoadedAt = now2;
|
|
16235
16471
|
return cachedConfig;
|
|
@@ -17146,7 +17382,7 @@ function useSpaceMessages(spaceName) {
|
|
|
17146
17382
|
}
|
|
17147
17383
|
function isNameTaken(name) {
|
|
17148
17384
|
try {
|
|
17149
|
-
const { getDb: getDb2 } = (init_db(),
|
|
17385
|
+
const { getDb: getDb2 } = (init_db(), __toCommonJS2(exports_db));
|
|
17150
17386
|
const db2 = getDb2();
|
|
17151
17387
|
const row = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(name);
|
|
17152
17388
|
return !!row;
|
|
@@ -17175,7 +17411,7 @@ function getAutoName() {
|
|
|
17175
17411
|
cachedAutoName = name;
|
|
17176
17412
|
try {
|
|
17177
17413
|
mkdirSync33(dirname22(AGENT_ID_FILE), { recursive: true });
|
|
17178
|
-
|
|
17414
|
+
writeFileSync5(AGENT_ID_FILE, name + `
|
|
17179
17415
|
`, "utf-8");
|
|
17180
17416
|
} catch {}
|
|
17181
17417
|
return name;
|
|
@@ -17781,7 +18017,7 @@ function getGraphStats() {
|
|
|
17781
18017
|
map[r.relation] = r.c;
|
|
17782
18018
|
return { total_edges: total, by_relation: map };
|
|
17783
18019
|
}
|
|
17784
|
-
var __create2, __getProtoOf2, __defProp3, __getOwnPropNames2,
|
|
18020
|
+
var __create2, __getProtoOf2, __defProp3, __getOwnPropNames2, __getOwnPropDesc2, __hasOwnProp2, __toESM2 = (mod, isNodeMode, target) => {
|
|
17785
18021
|
target = mod != null ? __create2(__getProtoOf2(mod)) : {};
|
|
17786
18022
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp3(target, "default", { value: mod, enumerable: true }) : target;
|
|
17787
18023
|
for (let key of __getOwnPropNames2(mod))
|
|
@@ -17791,17 +18027,17 @@ var __create2, __getProtoOf2, __defProp3, __getOwnPropNames2, __getOwnPropDesc,
|
|
|
17791
18027
|
enumerable: true
|
|
17792
18028
|
});
|
|
17793
18029
|
return to;
|
|
17794
|
-
},
|
|
17795
|
-
var entry =
|
|
18030
|
+
}, __moduleCache2, __toCommonJS2 = (from) => {
|
|
18031
|
+
var entry = __moduleCache2.get(from), desc;
|
|
17796
18032
|
if (entry)
|
|
17797
18033
|
return entry;
|
|
17798
18034
|
entry = __defProp3({}, "__esModule", { value: true });
|
|
17799
18035
|
if (from && typeof from === "object" || typeof from === "function")
|
|
17800
18036
|
__getOwnPropNames2(from).map((key) => !__hasOwnProp2.call(entry, key) && __defProp3(entry, key, {
|
|
17801
18037
|
get: () => from[key],
|
|
17802
|
-
enumerable: !(desc =
|
|
18038
|
+
enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
|
|
17803
18039
|
}));
|
|
17804
|
-
|
|
18040
|
+
__moduleCache2.set(from, entry);
|
|
17805
18041
|
return entry;
|
|
17806
18042
|
}, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports), __export3 = (target, all) => {
|
|
17807
18043
|
for (var name in all)
|
|
@@ -17817,9 +18053,9 @@ var init_dist2 = __esm(() => {
|
|
|
17817
18053
|
__getProtoOf2 = Object.getPrototypeOf;
|
|
17818
18054
|
__defProp3 = Object.defineProperty;
|
|
17819
18055
|
__getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
17820
|
-
|
|
18056
|
+
__getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
17821
18057
|
__hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
17822
|
-
|
|
18058
|
+
__moduleCache2 = /* @__PURE__ */ new WeakMap;
|
|
17823
18059
|
exports_db = {};
|
|
17824
18060
|
__export3(exports_db, {
|
|
17825
18061
|
getDbPath: () => getDbPath2,
|
|
@@ -20389,18 +20625,18 @@ __export(exports_dist3, {
|
|
|
20389
20625
|
AgentNotFoundError: () => AgentNotFoundError2
|
|
20390
20626
|
});
|
|
20391
20627
|
import { Database as Database4 } from "bun:sqlite";
|
|
20392
|
-
import { existsSync as
|
|
20393
|
-
import { dirname as dirname5, join as
|
|
20628
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync12 } from "fs";
|
|
20629
|
+
import { dirname as dirname5, join as join13, resolve as resolve3 } from "path";
|
|
20394
20630
|
import { existsSync as existsSync33 } from "fs";
|
|
20395
20631
|
import { join as join34 } from "path";
|
|
20396
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as
|
|
20632
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as readFileSync6, readdirSync as readdirSync5, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
20397
20633
|
import { join as join24 } from "path";
|
|
20398
20634
|
import { existsSync as existsSync43, readFileSync as readFileSync24, readdirSync as readdirSync22, writeFileSync as writeFileSync23 } from "fs";
|
|
20399
20635
|
import { join as join44 } from "path";
|
|
20400
20636
|
import { existsSync as existsSync52 } from "fs";
|
|
20401
20637
|
import { join as join52 } from "path";
|
|
20402
20638
|
import { readFileSync as readFileSync33, statSync as statSync22 } from "fs";
|
|
20403
|
-
import { relative, resolve as
|
|
20639
|
+
import { relative, resolve as resolve23, join as join62 } from "path";
|
|
20404
20640
|
import { execSync as execSync2 } from "child_process";
|
|
20405
20641
|
|
|
20406
20642
|
class TodosClient {
|
|
@@ -20623,8 +20859,8 @@ function isInMemoryDb2(path) {
|
|
|
20623
20859
|
function findNearestTodosDb(startDir) {
|
|
20624
20860
|
let dir = resolve3(startDir);
|
|
20625
20861
|
while (true) {
|
|
20626
|
-
const candidate =
|
|
20627
|
-
if (
|
|
20862
|
+
const candidate = join13(dir, ".todos", "todos.db");
|
|
20863
|
+
if (existsSync7(candidate))
|
|
20628
20864
|
return candidate;
|
|
20629
20865
|
const parent = dirname5(dir);
|
|
20630
20866
|
if (parent === dir)
|
|
@@ -20636,7 +20872,7 @@ function findNearestTodosDb(startDir) {
|
|
|
20636
20872
|
function findGitRoot2(startDir) {
|
|
20637
20873
|
let dir = resolve3(startDir);
|
|
20638
20874
|
while (true) {
|
|
20639
|
-
if (
|
|
20875
|
+
if (existsSync7(join13(dir, ".git")))
|
|
20640
20876
|
return dir;
|
|
20641
20877
|
const parent = dirname5(dir);
|
|
20642
20878
|
if (parent === dir)
|
|
@@ -20656,18 +20892,18 @@ function getDbPath3() {
|
|
|
20656
20892
|
if (process.env["TODOS_DB_SCOPE"] === "project") {
|
|
20657
20893
|
const gitRoot = findGitRoot2(cwd);
|
|
20658
20894
|
if (gitRoot) {
|
|
20659
|
-
return
|
|
20895
|
+
return join13(gitRoot, ".todos", "todos.db");
|
|
20660
20896
|
}
|
|
20661
20897
|
}
|
|
20662
20898
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
20663
|
-
return
|
|
20899
|
+
return join13(home, ".todos", "todos.db");
|
|
20664
20900
|
}
|
|
20665
20901
|
function ensureDir3(filePath) {
|
|
20666
20902
|
if (isInMemoryDb2(filePath))
|
|
20667
20903
|
return;
|
|
20668
20904
|
const dir = dirname5(resolve3(filePath));
|
|
20669
|
-
if (!
|
|
20670
|
-
|
|
20905
|
+
if (!existsSync7(dir)) {
|
|
20906
|
+
mkdirSync12(dir, { recursive: true });
|
|
20671
20907
|
}
|
|
20672
20908
|
}
|
|
20673
20909
|
function getDatabase3(dbPath) {
|
|
@@ -21133,28 +21369,28 @@ function ensureDir23(dir) {
|
|
|
21133
21369
|
function listJsonFiles(dir) {
|
|
21134
21370
|
if (!existsSync23(dir))
|
|
21135
21371
|
return [];
|
|
21136
|
-
return
|
|
21372
|
+
return readdirSync5(dir).filter((f) => f.endsWith(".json"));
|
|
21137
21373
|
}
|
|
21138
21374
|
function readJsonFile(path) {
|
|
21139
21375
|
try {
|
|
21140
|
-
return JSON.parse(
|
|
21376
|
+
return JSON.parse(readFileSync6(path, "utf-8"));
|
|
21141
21377
|
} catch {
|
|
21142
21378
|
return null;
|
|
21143
21379
|
}
|
|
21144
21380
|
}
|
|
21145
21381
|
function writeJsonFile(path, data) {
|
|
21146
|
-
|
|
21382
|
+
writeFileSync6(path, JSON.stringify(data, null, 2) + `
|
|
21147
21383
|
`);
|
|
21148
21384
|
}
|
|
21149
21385
|
function readHighWaterMark(dir) {
|
|
21150
21386
|
const path = join24(dir, ".highwatermark");
|
|
21151
21387
|
if (!existsSync23(path))
|
|
21152
21388
|
return 1;
|
|
21153
|
-
const val = parseInt(
|
|
21389
|
+
const val = parseInt(readFileSync6(path, "utf-8").trim(), 10);
|
|
21154
21390
|
return isNaN(val) ? 1 : val;
|
|
21155
21391
|
}
|
|
21156
21392
|
function writeHighWaterMark(dir, value) {
|
|
21157
|
-
|
|
21393
|
+
writeFileSync6(join24(dir, ".highwatermark"), String(value));
|
|
21158
21394
|
}
|
|
21159
21395
|
function getFileMtimeMs(path) {
|
|
21160
21396
|
try {
|
|
@@ -24516,7 +24752,7 @@ function collectFiles(basePath, extensions) {
|
|
|
24516
24752
|
return files.sort();
|
|
24517
24753
|
}
|
|
24518
24754
|
function extractTodos(options, db2) {
|
|
24519
|
-
const basePath =
|
|
24755
|
+
const basePath = resolve23(options.path);
|
|
24520
24756
|
const tags = options.patterns || [...EXTRACT_TAGS];
|
|
24521
24757
|
const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
|
|
24522
24758
|
const files = collectFiles(basePath, extensions);
|
|
@@ -24525,7 +24761,7 @@ function extractTodos(options, db2) {
|
|
|
24525
24761
|
const fullPath = statSync22(basePath).isFile() ? basePath : join62(basePath, file);
|
|
24526
24762
|
try {
|
|
24527
24763
|
const source = readFileSync33(fullPath, "utf-8");
|
|
24528
|
-
const relPath = statSync22(basePath).isFile() ? relative(
|
|
24764
|
+
const relPath = statSync22(basePath).isFile() ? relative(resolve23(basePath, ".."), fullPath) : file;
|
|
24529
24765
|
const comments = extractFromSource(source, relPath, tags);
|
|
24530
24766
|
allComments.push(...comments);
|
|
24531
24767
|
} catch {}
|
|
@@ -25744,8 +25980,8 @@ __export(exports_dist4, {
|
|
|
25744
25980
|
CATEGORIES: () => CATEGORIES,
|
|
25745
25981
|
AGENT_TARGETS: () => AGENT_TARGETS
|
|
25746
25982
|
});
|
|
25747
|
-
import { existsSync as
|
|
25748
|
-
import { join as
|
|
25983
|
+
import { existsSync as existsSync8, cpSync, mkdirSync as mkdirSync13, writeFileSync as writeFileSync7, rmSync as rmSync2, readdirSync as readdirSync6, statSync as statSync4, readFileSync as readFileSync7, accessSync, constants } from "fs";
|
|
25984
|
+
import { join as join14, dirname as dirname6 } from "path";
|
|
25749
25985
|
import { homedir as homedir13 } from "os";
|
|
25750
25986
|
import { fileURLToPath } from "url";
|
|
25751
25987
|
import { existsSync as existsSync24, readFileSync as readFileSync25, readdirSync as readdirSync23 } from "fs";
|
|
@@ -25857,35 +26093,35 @@ function normalizeSkillName(name) {
|
|
|
25857
26093
|
function findSkillsDir() {
|
|
25858
26094
|
let dir = __dirname2;
|
|
25859
26095
|
for (let i = 0;i < 5; i++) {
|
|
25860
|
-
const candidate =
|
|
25861
|
-
if (
|
|
26096
|
+
const candidate = join14(dir, "skills");
|
|
26097
|
+
if (existsSync8(candidate)) {
|
|
25862
26098
|
return candidate;
|
|
25863
26099
|
}
|
|
25864
26100
|
dir = dirname6(dir);
|
|
25865
26101
|
}
|
|
25866
|
-
return
|
|
26102
|
+
return join14(__dirname2, "..", "skills");
|
|
25867
26103
|
}
|
|
25868
26104
|
function getSkillPath(name) {
|
|
25869
26105
|
const skillName = normalizeSkillName(name);
|
|
25870
|
-
return
|
|
26106
|
+
return join14(SKILLS_DIR, skillName);
|
|
25871
26107
|
}
|
|
25872
26108
|
function skillExists(name) {
|
|
25873
|
-
return
|
|
26109
|
+
return existsSync8(getSkillPath(name));
|
|
25874
26110
|
}
|
|
25875
26111
|
function installSkill(name, options = {}) {
|
|
25876
26112
|
const { targetDir = process.cwd(), overwrite = false } = options;
|
|
25877
26113
|
const skillName = normalizeSkillName(name);
|
|
25878
26114
|
const sourcePath = getSkillPath(name);
|
|
25879
|
-
const destDir =
|
|
25880
|
-
const destPath =
|
|
25881
|
-
if (!
|
|
26115
|
+
const destDir = join14(targetDir, ".skills");
|
|
26116
|
+
const destPath = join14(destDir, skillName);
|
|
26117
|
+
if (!existsSync8(sourcePath)) {
|
|
25882
26118
|
return {
|
|
25883
26119
|
skill: name,
|
|
25884
26120
|
success: false,
|
|
25885
26121
|
error: `Skill '${name}' not found`
|
|
25886
26122
|
};
|
|
25887
26123
|
}
|
|
25888
|
-
if (
|
|
26124
|
+
if (existsSync8(destPath) && !overwrite) {
|
|
25889
26125
|
return {
|
|
25890
26126
|
skill: name,
|
|
25891
26127
|
success: false,
|
|
@@ -25894,10 +26130,10 @@ function installSkill(name, options = {}) {
|
|
|
25894
26130
|
};
|
|
25895
26131
|
}
|
|
25896
26132
|
try {
|
|
25897
|
-
if (!
|
|
25898
|
-
|
|
26133
|
+
if (!existsSync8(destDir)) {
|
|
26134
|
+
mkdirSync13(destDir, { recursive: true });
|
|
25899
26135
|
}
|
|
25900
|
-
if (
|
|
26136
|
+
if (existsSync8(destPath) && overwrite) {
|
|
25901
26137
|
rmSync2(destPath, { recursive: true, force: true });
|
|
25902
26138
|
}
|
|
25903
26139
|
cpSync(sourcePath, destPath, {
|
|
@@ -25936,10 +26172,10 @@ function installSkills(names, options = {}) {
|
|
|
25936
26172
|
return names.map((name) => installSkill(name, options));
|
|
25937
26173
|
}
|
|
25938
26174
|
function updateSkillsIndex(skillsDir) {
|
|
25939
|
-
const indexPath =
|
|
26175
|
+
const indexPath = join14(skillsDir, "index.ts");
|
|
25940
26176
|
const meta = loadMeta(skillsDir);
|
|
25941
26177
|
const disabledSet = new Set(meta.disabled || []);
|
|
25942
|
-
const skills =
|
|
26178
|
+
const skills = readdirSync6(skillsDir).filter((f) => f.startsWith("skill-") && !f.includes(".") && !disabledSet.has(f.replace("skill-", "")));
|
|
25943
26179
|
const exports = skills.map((s) => {
|
|
25944
26180
|
const name = s.replace("skill-", "").replace(/-/g, "_");
|
|
25945
26181
|
return `export * as ${name} from './${s}/src/index.js';`;
|
|
@@ -25952,31 +26188,31 @@ function updateSkillsIndex(skillsDir) {
|
|
|
25952
26188
|
|
|
25953
26189
|
${exports}
|
|
25954
26190
|
`;
|
|
25955
|
-
|
|
26191
|
+
writeFileSync7(indexPath, content);
|
|
25956
26192
|
}
|
|
25957
26193
|
function getMetaPath(skillsDir) {
|
|
25958
|
-
return
|
|
26194
|
+
return join14(skillsDir, ".meta.json");
|
|
25959
26195
|
}
|
|
25960
26196
|
function loadMeta(skillsDir) {
|
|
25961
26197
|
const metaPath2 = getMetaPath(skillsDir);
|
|
25962
|
-
if (
|
|
26198
|
+
if (existsSync8(metaPath2)) {
|
|
25963
26199
|
try {
|
|
25964
|
-
return JSON.parse(
|
|
26200
|
+
return JSON.parse(readFileSync7(metaPath2, "utf-8"));
|
|
25965
26201
|
} catch {}
|
|
25966
26202
|
}
|
|
25967
26203
|
return { skills: {} };
|
|
25968
26204
|
}
|
|
25969
26205
|
function saveMeta(skillsDir, meta) {
|
|
25970
|
-
|
|
26206
|
+
writeFileSync7(getMetaPath(skillsDir), JSON.stringify(meta, null, 2));
|
|
25971
26207
|
}
|
|
25972
26208
|
function recordInstall(skillsDir, name) {
|
|
25973
26209
|
const meta = loadMeta(skillsDir);
|
|
25974
26210
|
const skillName = normalizeSkillName(name);
|
|
25975
26211
|
let version = "unknown";
|
|
25976
26212
|
try {
|
|
25977
|
-
const pkgPath =
|
|
25978
|
-
if (
|
|
25979
|
-
const pkg = JSON.parse(
|
|
26213
|
+
const pkgPath = join14(skillsDir, skillName, "package.json");
|
|
26214
|
+
if (existsSync8(pkgPath)) {
|
|
26215
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
25980
26216
|
version = pkg.version || "unknown";
|
|
25981
26217
|
}
|
|
25982
26218
|
} catch {}
|
|
@@ -25989,12 +26225,12 @@ function recordRemove(skillsDir, name) {
|
|
|
25989
26225
|
saveMeta(skillsDir, meta);
|
|
25990
26226
|
}
|
|
25991
26227
|
function getInstallMeta(targetDir = process.cwd()) {
|
|
25992
|
-
return loadMeta(
|
|
26228
|
+
return loadMeta(join14(targetDir, ".skills"));
|
|
25993
26229
|
}
|
|
25994
26230
|
function disableSkill(name, targetDir = process.cwd()) {
|
|
25995
|
-
const skillsDir =
|
|
26231
|
+
const skillsDir = join14(targetDir, ".skills");
|
|
25996
26232
|
const skillName = normalizeSkillName(name);
|
|
25997
|
-
if (!
|
|
26233
|
+
if (!existsSync8(join14(skillsDir, skillName)))
|
|
25998
26234
|
return false;
|
|
25999
26235
|
const meta = loadMeta(skillsDir);
|
|
26000
26236
|
const disabled = new Set(meta.disabled || []);
|
|
@@ -26007,7 +26243,7 @@ function disableSkill(name, targetDir = process.cwd()) {
|
|
|
26007
26243
|
return true;
|
|
26008
26244
|
}
|
|
26009
26245
|
function enableSkill(name, targetDir = process.cwd()) {
|
|
26010
|
-
const skillsDir =
|
|
26246
|
+
const skillsDir = join14(targetDir, ".skills");
|
|
26011
26247
|
const meta = loadMeta(skillsDir);
|
|
26012
26248
|
const disabled = new Set(meta.disabled || []);
|
|
26013
26249
|
if (!disabled.has(name))
|
|
@@ -26019,24 +26255,24 @@ function enableSkill(name, targetDir = process.cwd()) {
|
|
|
26019
26255
|
return true;
|
|
26020
26256
|
}
|
|
26021
26257
|
function getDisabledSkills(targetDir = process.cwd()) {
|
|
26022
|
-
const meta = loadMeta(
|
|
26258
|
+
const meta = loadMeta(join14(targetDir, ".skills"));
|
|
26023
26259
|
return meta.disabled || [];
|
|
26024
26260
|
}
|
|
26025
26261
|
function getInstalledSkills(targetDir = process.cwd()) {
|
|
26026
|
-
const skillsDir =
|
|
26027
|
-
if (!
|
|
26262
|
+
const skillsDir = join14(targetDir, ".skills");
|
|
26263
|
+
if (!existsSync8(skillsDir)) {
|
|
26028
26264
|
return [];
|
|
26029
26265
|
}
|
|
26030
|
-
return
|
|
26031
|
-
const fullPath =
|
|
26266
|
+
return readdirSync6(skillsDir).filter((f) => {
|
|
26267
|
+
const fullPath = join14(skillsDir, f);
|
|
26032
26268
|
return f.startsWith("skill-") && statSync4(fullPath).isDirectory();
|
|
26033
26269
|
}).map((f) => f.replace("skill-", ""));
|
|
26034
26270
|
}
|
|
26035
26271
|
function removeSkill(name, targetDir = process.cwd()) {
|
|
26036
26272
|
const skillName = normalizeSkillName(name);
|
|
26037
|
-
const skillsDir =
|
|
26038
|
-
const skillPath =
|
|
26039
|
-
if (!
|
|
26273
|
+
const skillsDir = join14(targetDir, ".skills");
|
|
26274
|
+
const skillPath = join14(skillsDir, skillName);
|
|
26275
|
+
if (!existsSync8(skillPath)) {
|
|
26040
26276
|
return false;
|
|
26041
26277
|
}
|
|
26042
26278
|
rmSync2(skillPath, { recursive: true, force: true });
|
|
@@ -26047,25 +26283,25 @@ function removeSkill(name, targetDir = process.cwd()) {
|
|
|
26047
26283
|
function getAgentSkillsDir(agent, scope = "global", projectDir) {
|
|
26048
26284
|
const agentDir = `.${agent}`;
|
|
26049
26285
|
if (scope === "project") {
|
|
26050
|
-
return
|
|
26286
|
+
return join14(projectDir || process.cwd(), agentDir, "skills");
|
|
26051
26287
|
}
|
|
26052
|
-
return
|
|
26288
|
+
return join14(homedir13(), agentDir, "skills");
|
|
26053
26289
|
}
|
|
26054
26290
|
function getAgentSkillPath(name, agent, scope = "global", projectDir) {
|
|
26055
26291
|
const skillName = normalizeSkillName(name);
|
|
26056
|
-
return
|
|
26292
|
+
return join14(getAgentSkillsDir(agent, scope, projectDir), skillName);
|
|
26057
26293
|
}
|
|
26058
26294
|
function installSkillForAgent(name, options, generateSkillMd) {
|
|
26059
26295
|
const { agent, scope = "global", projectDir } = options;
|
|
26060
26296
|
const skillName = normalizeSkillName(name);
|
|
26061
26297
|
const sourcePath = getSkillPath(name);
|
|
26062
|
-
if (!
|
|
26298
|
+
if (!existsSync8(sourcePath)) {
|
|
26063
26299
|
return { skill: name, success: false, error: `Skill '${name}' not found` };
|
|
26064
26300
|
}
|
|
26065
26301
|
let skillMdContent = null;
|
|
26066
|
-
const skillMdPath =
|
|
26067
|
-
if (
|
|
26068
|
-
skillMdContent =
|
|
26302
|
+
const skillMdPath = join14(sourcePath, "SKILL.md");
|
|
26303
|
+
if (existsSync8(skillMdPath)) {
|
|
26304
|
+
skillMdContent = readFileSync7(skillMdPath, "utf-8");
|
|
26069
26305
|
} else if (generateSkillMd) {
|
|
26070
26306
|
skillMdContent = generateSkillMd(name);
|
|
26071
26307
|
}
|
|
@@ -26074,8 +26310,8 @@ function installSkillForAgent(name, options, generateSkillMd) {
|
|
|
26074
26310
|
}
|
|
26075
26311
|
const destDir = getAgentSkillPath(name, agent, scope, projectDir);
|
|
26076
26312
|
if (scope === "global") {
|
|
26077
|
-
const agentBaseDir2 =
|
|
26078
|
-
if (!
|
|
26313
|
+
const agentBaseDir2 = join14(homedir13(), `.${agent}`);
|
|
26314
|
+
if (!existsSync8(agentBaseDir2)) {
|
|
26079
26315
|
const agentLabels = {
|
|
26080
26316
|
claude: "Claude Code",
|
|
26081
26317
|
codex: "Codex CLI",
|
|
@@ -26098,8 +26334,8 @@ function installSkillForAgent(name, options, generateSkillMd) {
|
|
|
26098
26334
|
}
|
|
26099
26335
|
}
|
|
26100
26336
|
try {
|
|
26101
|
-
|
|
26102
|
-
|
|
26337
|
+
mkdirSync13(destDir, { recursive: true });
|
|
26338
|
+
writeFileSync7(join14(destDir, "SKILL.md"), skillMdContent);
|
|
26103
26339
|
return { skill: name, success: true, path: destDir };
|
|
26104
26340
|
} catch (error) {
|
|
26105
26341
|
return {
|
|
@@ -26112,7 +26348,7 @@ function installSkillForAgent(name, options, generateSkillMd) {
|
|
|
26112
26348
|
function removeSkillForAgent(name, options) {
|
|
26113
26349
|
const { agent, scope = "global", projectDir } = options;
|
|
26114
26350
|
const destDir = getAgentSkillPath(name, agent, scope, projectDir);
|
|
26115
|
-
if (!
|
|
26351
|
+
if (!existsSync8(destDir)) {
|
|
26116
26352
|
return false;
|
|
26117
26353
|
}
|
|
26118
26354
|
rmSync2(destDir, { recursive: true, force: true });
|
|
@@ -32433,8 +32669,8 @@ var NEVER = INVALID;
|
|
|
32433
32669
|
// src/mcp/index.ts
|
|
32434
32670
|
init_session();
|
|
32435
32671
|
init_actions();
|
|
32436
|
-
import { readFileSync as
|
|
32437
|
-
import { join as
|
|
32672
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
32673
|
+
import { join as join15 } from "path";
|
|
32438
32674
|
|
|
32439
32675
|
// src/lib/screenshot.ts
|
|
32440
32676
|
init_types();
|
|
@@ -33204,7 +33440,7 @@ async function closeTab(page, index) {
|
|
|
33204
33440
|
init_dialogs();
|
|
33205
33441
|
init_profiles();
|
|
33206
33442
|
init_types();
|
|
33207
|
-
var _pkg = JSON.parse(
|
|
33443
|
+
var _pkg = JSON.parse(readFileSync8(join15(import.meta.dir, "../../package.json"), "utf8"));
|
|
33208
33444
|
var networkLogCleanup = new Map;
|
|
33209
33445
|
var consoleCaptureCleanup = new Map;
|
|
33210
33446
|
var harCaptures = new Map;
|
|
@@ -34909,14 +35145,17 @@ server.tool("browser_profile_delete", "Delete a saved browser profile", { name:
|
|
|
34909
35145
|
return err(e);
|
|
34910
35146
|
}
|
|
34911
35147
|
});
|
|
34912
|
-
server.tool("browser_script_run", "Run a saved
|
|
34913
|
-
name: exports_external.string().describe("Script name
|
|
35148
|
+
server.tool("browser_script_run", "Run a saved script asynchronously. Returns run_id immediately \u2014 poll with browser_script_status for step-by-step progress. Scripts combine browser actions + connector calls + AI reasoning. Works with any engine (Bun.WebView, Playwright, CDP).", {
|
|
35149
|
+
name: exports_external.string().describe("Script name"),
|
|
34914
35150
|
session_id: exports_external.string().optional(),
|
|
34915
|
-
|
|
34916
|
-
|
|
35151
|
+
engine: exports_external.enum(["playwright", "cdp", "lightpanda", "bun", "auto"]).optional().default("auto"),
|
|
35152
|
+
variables: exports_external.record(exports_external.string()).optional().describe("Override script variables")
|
|
35153
|
+
}, async ({ name, session_id, engine, variables }) => {
|
|
34917
35154
|
try {
|
|
34918
|
-
const {
|
|
34919
|
-
const
|
|
35155
|
+
const { getScriptByName: getScriptByName2, migrateJsonScripts: migrateJsonScripts2, getSteps: getSteps2 } = await Promise.resolve().then(() => (init_scripts(), exports_scripts));
|
|
35156
|
+
const { executeScript: executeScript2 } = await Promise.resolve().then(() => (init_script_engine(), exports_script_engine));
|
|
35157
|
+
migrateJsonScripts2();
|
|
35158
|
+
const script = getScriptByName2(name);
|
|
34920
35159
|
if (!script)
|
|
34921
35160
|
return err(new Error(`Script '${name}' not found. Use browser_script_list to see available scripts.`));
|
|
34922
35161
|
let sid;
|
|
@@ -34925,55 +35164,72 @@ server.tool("browser_script_run", "Run a saved login script asynchronously. Retu
|
|
|
34925
35164
|
sid = resolveSessionId(session_id);
|
|
34926
35165
|
page = getSessionPage(sid);
|
|
34927
35166
|
} else {
|
|
34928
|
-
const result = await createSession2({ headless: true });
|
|
35167
|
+
const result = await createSession2({ engine: engine ?? "auto", headless: true });
|
|
34929
35168
|
sid = result.session.id;
|
|
34930
35169
|
page = result.page;
|
|
34931
35170
|
}
|
|
34932
|
-
const
|
|
34933
|
-
|
|
35171
|
+
const steps = getSteps2(script.id);
|
|
35172
|
+
const runId = executeScript2(script.id, page, variables ?? {});
|
|
35173
|
+
return json({ run_id: runId, session_id: sid, script: name, total_steps: steps.length, message: "Script running. Poll with browser_script_status." });
|
|
34934
35174
|
} catch (e) {
|
|
34935
35175
|
return err(e);
|
|
34936
35176
|
}
|
|
34937
35177
|
});
|
|
34938
|
-
server.tool("browser_script_status", "Check
|
|
35178
|
+
server.tool("browser_script_status", "Check progress of a running script. Shows current step, step-by-step log with durations, and final result when complete.", { run_id: exports_external.string() }, async ({ run_id }) => {
|
|
34939
35179
|
try {
|
|
34940
|
-
const {
|
|
34941
|
-
const
|
|
34942
|
-
if (!
|
|
34943
|
-
return err(new Error(`
|
|
35180
|
+
const { getRun: getRun3 } = await Promise.resolve().then(() => (init_scripts(), exports_scripts));
|
|
35181
|
+
const run = getRun3(run_id);
|
|
35182
|
+
if (!run)
|
|
35183
|
+
return err(new Error(`Run '${run_id}' not found`));
|
|
34944
35184
|
return json({
|
|
34945
|
-
status:
|
|
34946
|
-
progress: `${
|
|
34947
|
-
current_step:
|
|
34948
|
-
steps_log:
|
|
34949
|
-
|
|
35185
|
+
status: run.status,
|
|
35186
|
+
progress: `${run.current_step}/${run.total_steps}`,
|
|
35187
|
+
current_step: run.current_description,
|
|
35188
|
+
steps_log: run.steps_log,
|
|
35189
|
+
errors: run.errors.length > 0 ? run.errors : undefined,
|
|
35190
|
+
duration_ms: run.duration_ms,
|
|
35191
|
+
completed: run.completed_at
|
|
34950
35192
|
});
|
|
34951
35193
|
} catch (e) {
|
|
34952
35194
|
return err(e);
|
|
34953
35195
|
}
|
|
34954
35196
|
});
|
|
34955
|
-
server.tool("browser_script_list", "List all saved
|
|
35197
|
+
server.tool("browser_script_list", "List all saved scripts", {}, async () => {
|
|
34956
35198
|
try {
|
|
34957
|
-
const { listScripts: listScripts2 } = await Promise.resolve().then(() => (
|
|
34958
|
-
|
|
35199
|
+
const { listScripts: listScripts2, migrateJsonScripts: migrateJsonScripts2 } = await Promise.resolve().then(() => (init_scripts(), exports_scripts));
|
|
35200
|
+
migrateJsonScripts2();
|
|
35201
|
+
const scripts = listScripts2();
|
|
35202
|
+
return json({ scripts: scripts.map((s) => ({ name: s.name, domain: s.domain, description: s.description, run_count: s.run_count, last_run: s.last_run })), count: scripts.length });
|
|
34959
35203
|
} catch (e) {
|
|
34960
35204
|
return err(e);
|
|
34961
35205
|
}
|
|
34962
35206
|
});
|
|
34963
|
-
server.tool("browser_script_save", "Save a
|
|
35207
|
+
server.tool("browser_script_save", "Save a script. Steps are stored in SQLite. Each step has a type (browser/connector/extract/wait/condition/save_state), config, and optional AI config for intelligent fallbacks.", {
|
|
35208
|
+
name: exports_external.string(),
|
|
35209
|
+
domain: exports_external.string().optional().default(""),
|
|
35210
|
+
description: exports_external.string().optional().default(""),
|
|
35211
|
+
variables: exports_external.record(exports_external.string()).optional().default({}),
|
|
35212
|
+
steps: exports_external.array(exports_external.object({
|
|
35213
|
+
type: exports_external.enum(["browser", "connector", "extract", "wait", "condition", "save_state"]),
|
|
35214
|
+
config: exports_external.record(exports_external.unknown()).default({}),
|
|
35215
|
+
description: exports_external.string().optional().default(""),
|
|
35216
|
+
ai_enabled: exports_external.boolean().optional().default(false),
|
|
35217
|
+
ai_config: exports_external.record(exports_external.unknown()).optional().default({})
|
|
35218
|
+
}))
|
|
35219
|
+
}, async ({ name, domain, description, variables, steps }) => {
|
|
34964
35220
|
try {
|
|
34965
|
-
const {
|
|
34966
|
-
const script =
|
|
34967
|
-
const
|
|
34968
|
-
return json({
|
|
35221
|
+
const { upsertScript: upsertScript2, getSteps: getSteps2 } = await Promise.resolve().then(() => (init_scripts(), exports_scripts));
|
|
35222
|
+
const script = upsertScript2({ name, domain, description, variables, steps });
|
|
35223
|
+
const savedSteps = getSteps2(script.id);
|
|
35224
|
+
return json({ id: script.id, name: script.name, steps: savedSteps.length });
|
|
34969
35225
|
} catch (e) {
|
|
34970
35226
|
return err(e);
|
|
34971
35227
|
}
|
|
34972
35228
|
});
|
|
34973
|
-
server.tool("browser_script_delete", "Delete a saved
|
|
35229
|
+
server.tool("browser_script_delete", "Delete a saved script", { name: exports_external.string() }, async ({ name }) => {
|
|
34974
35230
|
try {
|
|
34975
|
-
const {
|
|
34976
|
-
return json({ deleted:
|
|
35231
|
+
const { deleteScriptByName: deleteScriptByName2 } = await Promise.resolve().then(() => (init_scripts(), exports_scripts));
|
|
35232
|
+
return json({ deleted: deleteScriptByName2(name) });
|
|
34977
35233
|
} catch (e) {
|
|
34978
35234
|
return err(e);
|
|
34979
35235
|
}
|