@hasna/browser 0.2.1 → 0.2.2
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 +104 -27
- package/dist/lib/login-scripts.d.ts +26 -1
- package/dist/lib/login-scripts.d.ts.map +1 -1
- package/dist/mcp/index.js +98 -21
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -19363,14 +19363,24 @@ var init_dist = __esm(() => {
|
|
|
19363
19363
|
var exports_login_scripts = {};
|
|
19364
19364
|
__export(exports_login_scripts, {
|
|
19365
19365
|
saveScript: () => saveScript,
|
|
19366
|
+
runScriptAsync: () => runScriptAsync,
|
|
19366
19367
|
runScript: () => runScript,
|
|
19367
19368
|
loadScript: () => loadScript,
|
|
19368
19369
|
listScripts: () => listScripts,
|
|
19370
|
+
listJobs: () => listJobs,
|
|
19371
|
+
getJob: () => getJob,
|
|
19369
19372
|
deleteScript: () => deleteScript,
|
|
19370
19373
|
createUsestableScript: () => createUsestableScript
|
|
19371
19374
|
});
|
|
19375
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
19372
19376
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync8, readdirSync as readdirSync4 } from "fs";
|
|
19373
19377
|
import { join as join9 } from "path";
|
|
19378
|
+
function getJob(jobId) {
|
|
19379
|
+
return activeJobs.get(jobId) ?? null;
|
|
19380
|
+
}
|
|
19381
|
+
function listJobs() {
|
|
19382
|
+
return Array.from(activeJobs.values());
|
|
19383
|
+
}
|
|
19374
19384
|
function getScriptsDir() {
|
|
19375
19385
|
const dir = join9(getDataDir(), "scripts");
|
|
19376
19386
|
mkdirSync8(dir, { recursive: true });
|
|
@@ -19417,15 +19427,34 @@ function interpolate(template, vars) {
|
|
|
19417
19427
|
return vars[key] ?? match;
|
|
19418
19428
|
});
|
|
19419
19429
|
}
|
|
19420
|
-
|
|
19430
|
+
function stepDescription(step) {
|
|
19431
|
+
return step.description ?? `${step.type}${step.action ? `:${step.action}` : ""}${step.connector ? `:${step.connector}` : ""}`;
|
|
19432
|
+
}
|
|
19433
|
+
async function runScript(script, page, overrides = {}, jobId) {
|
|
19421
19434
|
const t0 = Date.now();
|
|
19422
19435
|
const vars = { ...script.variables, ...overrides };
|
|
19423
19436
|
const errors = [];
|
|
19424
19437
|
let executed = 0;
|
|
19425
19438
|
let failed = 0;
|
|
19439
|
+
const job = jobId && activeJobs.has(jobId) ? activeJobs.get(jobId) : {
|
|
19440
|
+
id: jobId ?? randomUUID10(),
|
|
19441
|
+
script_name: script.name,
|
|
19442
|
+
status: "running",
|
|
19443
|
+
current_step: 0,
|
|
19444
|
+
total_steps: script.steps.length,
|
|
19445
|
+
current_step_description: "Starting...",
|
|
19446
|
+
steps_log: [],
|
|
19447
|
+
started_at: new Date().toISOString()
|
|
19448
|
+
};
|
|
19449
|
+
activeJobs.set(job.id, job);
|
|
19426
19450
|
for (let i = 0;i < script.steps.length; i++) {
|
|
19427
19451
|
const step = script.steps[i];
|
|
19452
|
+
const desc = stepDescription(step);
|
|
19428
19453
|
executed++;
|
|
19454
|
+
job.current_step = i + 1;
|
|
19455
|
+
job.current_step_description = desc;
|
|
19456
|
+
job.steps_log.push({ step: i + 1, type: step.type, description: desc, status: "running" });
|
|
19457
|
+
const stepStart = Date.now();
|
|
19429
19458
|
try {
|
|
19430
19459
|
switch (step.type) {
|
|
19431
19460
|
case "browser":
|
|
@@ -19462,15 +19491,22 @@ async function runScript(script, page, overrides = {}) {
|
|
|
19462
19491
|
break;
|
|
19463
19492
|
}
|
|
19464
19493
|
}
|
|
19494
|
+
const logEntry = job.steps_log[job.steps_log.length - 1];
|
|
19495
|
+
logEntry.status = "ok";
|
|
19496
|
+
logEntry.duration_ms = Date.now() - stepStart;
|
|
19465
19497
|
} catch (err) {
|
|
19466
19498
|
failed++;
|
|
19467
19499
|
const msg = `Step ${i + 1} (${step.type}/${step.action ?? step.connector ?? ""}): ${err instanceof Error ? err.message : String(err)}`;
|
|
19468
19500
|
errors.push(msg);
|
|
19501
|
+
const logEntry = job.steps_log[job.steps_log.length - 1];
|
|
19502
|
+
logEntry.status = "failed";
|
|
19503
|
+
logEntry.error = err instanceof Error ? err.message : String(err);
|
|
19504
|
+
logEntry.duration_ms = Date.now() - stepStart;
|
|
19469
19505
|
if (step.type === "browser" && step.action === "navigate")
|
|
19470
19506
|
break;
|
|
19471
19507
|
}
|
|
19472
19508
|
}
|
|
19473
|
-
|
|
19509
|
+
const result = {
|
|
19474
19510
|
success: failed === 0,
|
|
19475
19511
|
steps_executed: executed,
|
|
19476
19512
|
steps_failed: failed,
|
|
@@ -19478,6 +19514,28 @@ async function runScript(script, page, overrides = {}) {
|
|
|
19478
19514
|
errors,
|
|
19479
19515
|
duration_ms: Date.now() - t0
|
|
19480
19516
|
};
|
|
19517
|
+
job.status = failed === 0 ? "completed" : "failed";
|
|
19518
|
+
job.result = result;
|
|
19519
|
+
return result;
|
|
19520
|
+
}
|
|
19521
|
+
function runScriptAsync(script, page, overrides = {}) {
|
|
19522
|
+
const jobId = randomUUID10();
|
|
19523
|
+
const job = {
|
|
19524
|
+
id: jobId,
|
|
19525
|
+
script_name: script.name,
|
|
19526
|
+
status: "running",
|
|
19527
|
+
current_step: 0,
|
|
19528
|
+
total_steps: script.steps.length,
|
|
19529
|
+
current_step_description: "Starting...",
|
|
19530
|
+
steps_log: [],
|
|
19531
|
+
started_at: new Date().toISOString()
|
|
19532
|
+
};
|
|
19533
|
+
activeJobs.set(jobId, job);
|
|
19534
|
+
runScript(script, page, overrides, jobId).catch((err) => {
|
|
19535
|
+
job.status = "failed";
|
|
19536
|
+
job.current_step_description = `Fatal error: ${err instanceof Error ? err.message : String(err)}`;
|
|
19537
|
+
});
|
|
19538
|
+
return jobId;
|
|
19481
19539
|
}
|
|
19482
19540
|
async function runBrowserStep(step, page, vars) {
|
|
19483
19541
|
const action = step.action;
|
|
@@ -19637,8 +19695,10 @@ function createUsestableScript(email) {
|
|
|
19637
19695
|
updated_at: new Date().toISOString()
|
|
19638
19696
|
};
|
|
19639
19697
|
}
|
|
19698
|
+
var activeJobs;
|
|
19640
19699
|
var init_login_scripts = __esm(() => {
|
|
19641
19700
|
init_schema();
|
|
19701
|
+
activeJobs = new Map;
|
|
19642
19702
|
});
|
|
19643
19703
|
|
|
19644
19704
|
// src/lib/daemon-client.ts
|
|
@@ -23767,7 +23827,7 @@ __export(exports_downloads, {
|
|
|
23767
23827
|
deleteDownload: () => deleteDownload,
|
|
23768
23828
|
cleanStaleDownloads: () => cleanStaleDownloads
|
|
23769
23829
|
});
|
|
23770
|
-
import { randomUUID as
|
|
23830
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
23771
23831
|
import { join as join11, basename, extname } from "path";
|
|
23772
23832
|
import { mkdirSync as mkdirSync9, existsSync as existsSync8, readdirSync as readdirSync5, statSync as statSync2, unlinkSync as unlinkSync2, copyFileSync, writeFileSync as writeFileSync4, readFileSync as readFileSync6 } from "fs";
|
|
23773
23833
|
import { homedir as homedir10 } from "os";
|
|
@@ -23788,7 +23848,7 @@ function metaPath(filePath) {
|
|
|
23788
23848
|
}
|
|
23789
23849
|
function saveToDownloads(buffer, filename, opts) {
|
|
23790
23850
|
const dir = getDownloadsDir(opts?.sessionId);
|
|
23791
|
-
const id =
|
|
23851
|
+
const id = randomUUID11();
|
|
23792
23852
|
const ext = extname(filename) || "";
|
|
23793
23853
|
const stem = basename(filename, ext);
|
|
23794
23854
|
const uniqueName = `${stem}-${id.slice(0, 8)}${ext}`;
|
|
@@ -24196,10 +24256,10 @@ __export(exports_workflows, {
|
|
|
24196
24256
|
getWorkflow: () => getWorkflow,
|
|
24197
24257
|
deleteWorkflow: () => deleteWorkflow
|
|
24198
24258
|
});
|
|
24199
|
-
import { randomUUID as
|
|
24259
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
24200
24260
|
function saveWorkflow(data) {
|
|
24201
24261
|
const db = getDatabase();
|
|
24202
|
-
const id =
|
|
24262
|
+
const id = randomUUID12();
|
|
24203
24263
|
db.prepare("INSERT OR REPLACE INTO workflows (id, name, description, steps, start_url) VALUES (?, ?, ?, ?, ?)").run(id, data.name, data.description ?? null, JSON.stringify(data.steps), data.startUrl ?? null);
|
|
24204
24264
|
return getWorkflow(id);
|
|
24205
24265
|
}
|
|
@@ -24359,10 +24419,10 @@ __export(exports_auth_flow, {
|
|
|
24359
24419
|
getAuthFlow: () => getAuthFlow,
|
|
24360
24420
|
deleteAuthFlow: () => deleteAuthFlow
|
|
24361
24421
|
});
|
|
24362
|
-
import { randomUUID as
|
|
24422
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
24363
24423
|
function saveAuthFlow(data) {
|
|
24364
24424
|
const db = getDatabase();
|
|
24365
|
-
const id =
|
|
24425
|
+
const id = randomUUID13();
|
|
24366
24426
|
db.prepare("INSERT OR REPLACE INTO auth_flows (id, name, domain, recording_id, storage_state_path) VALUES (?, ?, ?, ?, ?)").run(id, data.name, data.domain, data.recordingId ?? null, data.storageStatePath ?? null);
|
|
24367
24427
|
return getAuthFlow(id);
|
|
24368
24428
|
}
|
|
@@ -24542,13 +24602,13 @@ __export(exports_datasets, {
|
|
|
24542
24602
|
exportDataset: () => exportDataset,
|
|
24543
24603
|
deleteDataset: () => deleteDataset
|
|
24544
24604
|
});
|
|
24545
|
-
import { randomUUID as
|
|
24605
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
24546
24606
|
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync11 } from "fs";
|
|
24547
24607
|
import { join as join13 } from "path";
|
|
24548
24608
|
import { homedir as homedir12 } from "os";
|
|
24549
24609
|
function saveDataset(data) {
|
|
24550
24610
|
const db = getDatabase();
|
|
24551
|
-
const id =
|
|
24611
|
+
const id = randomUUID14();
|
|
24552
24612
|
const existing = db.query("SELECT id FROM datasets WHERE name = ?").get(data.name);
|
|
24553
24613
|
if (existing) {
|
|
24554
24614
|
db.prepare("UPDATE datasets SET data = ?, row_count = ?, source_url = ?, schema = ?, last_refresh = datetime('now'), updated_at = datetime('now') WHERE name = ?").run(JSON.stringify(data.rows), data.rows.length, data.sourceUrl ?? null, data.schema ? JSON.stringify(data.schema) : null, data.name);
|
|
@@ -29349,7 +29409,7 @@ import { Database as Database3 } from "bun:sqlite";
|
|
|
29349
29409
|
import { mkdirSync as mkdirSync13 } from "fs";
|
|
29350
29410
|
import { join as join15, dirname as dirname6 } from "path";
|
|
29351
29411
|
import { homedir as homedir14 } from "os";
|
|
29352
|
-
import { randomUUID as
|
|
29412
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
29353
29413
|
import { mkdirSync as mkdirSync23, copyFileSync as copyFileSync3, statSync as statSync3 } from "fs";
|
|
29354
29414
|
import { join as join34 } from "path";
|
|
29355
29415
|
import { homedir as homedir33 } from "os";
|
|
@@ -29729,7 +29789,7 @@ function guessMimeType(name) {
|
|
|
29729
29789
|
function sendMessage(opts) {
|
|
29730
29790
|
const db2 = getDb();
|
|
29731
29791
|
const explicitSession = opts.session_id && opts.session_id.trim().length > 0 ? opts.session_id : undefined;
|
|
29732
|
-
const sessionId = explicitSession ?? (opts.space ? `space:${opts.space}` : `${[opts.from, opts.to].sort().join("-")}-${
|
|
29792
|
+
const sessionId = explicitSession ?? (opts.space ? `space:${opts.space}` : `${[opts.from, opts.to].sort().join("-")}-${randomUUID15().slice(0, 8)}`);
|
|
29733
29793
|
const metadata = opts.metadata ? JSON.stringify(opts.metadata) : null;
|
|
29734
29794
|
const normalizedPriority = opts.priority === "low" || opts.priority === "normal" || opts.priority === "high" || opts.priority === "urgent" ? opts.priority : "normal";
|
|
29735
29795
|
const blocking = opts.blocking ? 1 : 0;
|
|
@@ -41418,7 +41478,7 @@ __export(exports_cron_manager, {
|
|
|
41418
41478
|
deleteCronJob: () => deleteCronJob,
|
|
41419
41479
|
createCronJob: () => createCronJob
|
|
41420
41480
|
});
|
|
41421
|
-
import { randomUUID as
|
|
41481
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
41422
41482
|
function ensureCronTable() {
|
|
41423
41483
|
const db2 = getDatabase();
|
|
41424
41484
|
db2.exec(`
|
|
@@ -41447,7 +41507,7 @@ function ensureCronTable() {
|
|
|
41447
41507
|
function createCronJob(schedule, task, name) {
|
|
41448
41508
|
ensureCronTable();
|
|
41449
41509
|
const db2 = getDatabase();
|
|
41450
|
-
const id =
|
|
41510
|
+
const id = randomUUID16();
|
|
41451
41511
|
db2.prepare(`
|
|
41452
41512
|
INSERT INTO cron_jobs (id, name, schedule, task_json, enabled)
|
|
41453
41513
|
VALUES (?, ?, ?, ?, 1)
|
|
@@ -41505,7 +41565,7 @@ function getCronEvents(jobId, limit = 10) {
|
|
|
41505
41565
|
async function executeCronJob(job) {
|
|
41506
41566
|
ensureCronTable();
|
|
41507
41567
|
const db2 = getDatabase();
|
|
41508
|
-
const eventId =
|
|
41568
|
+
const eventId = randomUUID16();
|
|
41509
41569
|
const startedAt = new Date().toISOString();
|
|
41510
41570
|
db2.prepare("INSERT INTO cron_events (id, job_id, started_at) VALUES (?, ?, ?)").run(eventId, job.id, startedAt);
|
|
41511
41571
|
try {
|
|
@@ -41596,7 +41656,7 @@ __export(exports_url_watcher, {
|
|
|
41596
41656
|
deleteWatchJob: () => deleteWatchJob,
|
|
41597
41657
|
createWatchJob: () => createWatchJob
|
|
41598
41658
|
});
|
|
41599
|
-
import { randomUUID as
|
|
41659
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
41600
41660
|
import { createHash } from "crypto";
|
|
41601
41661
|
function ensureWatchTables() {
|
|
41602
41662
|
const db2 = getDatabase();
|
|
@@ -41628,7 +41688,7 @@ function ensureWatchTables() {
|
|
|
41628
41688
|
function createWatchJob(url, schedule, opts) {
|
|
41629
41689
|
ensureWatchTables();
|
|
41630
41690
|
const db2 = getDatabase();
|
|
41631
|
-
const id =
|
|
41691
|
+
const id = randomUUID17();
|
|
41632
41692
|
db2.prepare(`
|
|
41633
41693
|
INSERT INTO watch_jobs (id, name, url, schedule, selector, extract_schema, enabled)
|
|
41634
41694
|
VALUES (?, ?, ?, ?, ?, ?, 1)
|
|
@@ -41664,7 +41724,7 @@ function getWatchEvents(watchId, limit = 20) {
|
|
|
41664
41724
|
async function checkWatchJob(job) {
|
|
41665
41725
|
ensureWatchTables();
|
|
41666
41726
|
const db2 = getDatabase();
|
|
41667
|
-
const eventId =
|
|
41727
|
+
const eventId = randomUUID17();
|
|
41668
41728
|
const checkedAt = new Date().toISOString();
|
|
41669
41729
|
let newContent = "";
|
|
41670
41730
|
try {
|
|
@@ -43571,13 +43631,13 @@ var init_mcp = __esm(async () => {
|
|
|
43571
43631
|
return err(e);
|
|
43572
43632
|
}
|
|
43573
43633
|
});
|
|
43574
|
-
server.tool("browser_script_run", "Run a saved login script \u2014
|
|
43634
|
+
server.tool("browser_script_run", "Run a saved login script asynchronously. Returns a job_id immediately \u2014 poll with browser_script_status for step-by-step progress. Combines browser actions + connector calls (e.g. magic link login via Gmail).", {
|
|
43575
43635
|
name: exports_external.string().describe("Script name (e.g. 'usestable')"),
|
|
43576
43636
|
session_id: exports_external.string().optional(),
|
|
43577
43637
|
variables: exports_external.record(exports_external.string()).optional().describe("Override script variables (e.g. {email: 'foo@bar.com'})")
|
|
43578
43638
|
}, async ({ name, session_id, variables }) => {
|
|
43579
43639
|
try {
|
|
43580
|
-
const { loadScript: loadScript2,
|
|
43640
|
+
const { loadScript: loadScript2, runScriptAsync: runScriptAsync2 } = await Promise.resolve().then(() => (init_login_scripts(), exports_login_scripts));
|
|
43581
43641
|
const script = loadScript2(name);
|
|
43582
43642
|
if (!script)
|
|
43583
43643
|
return err(new Error(`Script '${name}' not found. Use browser_script_list to see available scripts.`));
|
|
@@ -43587,12 +43647,29 @@ var init_mcp = __esm(async () => {
|
|
|
43587
43647
|
sid = resolveSessionId(session_id);
|
|
43588
43648
|
page = getSessionPage(sid);
|
|
43589
43649
|
} else {
|
|
43590
|
-
const
|
|
43591
|
-
sid =
|
|
43592
|
-
page =
|
|
43650
|
+
const result = await createSession2({ headless: true });
|
|
43651
|
+
sid = result.session.id;
|
|
43652
|
+
page = result.page;
|
|
43593
43653
|
}
|
|
43594
|
-
const
|
|
43595
|
-
return json({
|
|
43654
|
+
const jobId = runScriptAsync2(script, page, variables ?? {});
|
|
43655
|
+
return json({ job_id: jobId, session_id: sid, script: name, total_steps: script.steps.length, message: "Script running in background. Poll with browser_script_status for progress." });
|
|
43656
|
+
} catch (e) {
|
|
43657
|
+
return err(e);
|
|
43658
|
+
}
|
|
43659
|
+
});
|
|
43660
|
+
server.tool("browser_script_status", "Check the progress of a running login script. Shows current step, step-by-step log with durations, and final result when complete.", { job_id: exports_external.string() }, async ({ job_id }) => {
|
|
43661
|
+
try {
|
|
43662
|
+
const { getJob: getJob2 } = await Promise.resolve().then(() => (init_login_scripts(), exports_login_scripts));
|
|
43663
|
+
const job = getJob2(job_id);
|
|
43664
|
+
if (!job)
|
|
43665
|
+
return err(new Error(`Job '${job_id}' not found`));
|
|
43666
|
+
return json({
|
|
43667
|
+
status: job.status,
|
|
43668
|
+
progress: `${job.current_step}/${job.total_steps}`,
|
|
43669
|
+
current_step: job.current_step_description,
|
|
43670
|
+
steps_log: job.steps_log,
|
|
43671
|
+
result: job.result ?? undefined
|
|
43672
|
+
});
|
|
43596
43673
|
} catch (e) {
|
|
43597
43674
|
return err(e);
|
|
43598
43675
|
}
|
|
@@ -44362,10 +44439,10 @@ __export(exports_snapshots, {
|
|
|
44362
44439
|
deleteSnapshot: () => deleteSnapshot,
|
|
44363
44440
|
createSnapshot: () => createSnapshot
|
|
44364
44441
|
});
|
|
44365
|
-
import { randomUUID as
|
|
44442
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
44366
44443
|
function createSnapshot(data) {
|
|
44367
44444
|
const db2 = getDatabase();
|
|
44368
|
-
const id =
|
|
44445
|
+
const id = randomUUID18();
|
|
44369
44446
|
db2.prepare("INSERT INTO snapshots (id, session_id, url, title, html, screenshot_path) VALUES (?, ?, ?, ?, ?, ?)").run(id, data.session_id, data.url, data.title ?? null, data.html ?? null, data.screenshot_path ?? null);
|
|
44370
44447
|
return getSnapshot(id);
|
|
44371
44448
|
}
|
|
@@ -45,6 +45,26 @@ export interface ScriptRunResult {
|
|
|
45
45
|
errors: string[];
|
|
46
46
|
duration_ms: number;
|
|
47
47
|
}
|
|
48
|
+
export interface ScriptJob {
|
|
49
|
+
id: string;
|
|
50
|
+
script_name: string;
|
|
51
|
+
status: "running" | "completed" | "failed";
|
|
52
|
+
current_step: number;
|
|
53
|
+
total_steps: number;
|
|
54
|
+
current_step_description: string;
|
|
55
|
+
steps_log: Array<{
|
|
56
|
+
step: number;
|
|
57
|
+
type: string;
|
|
58
|
+
description: string;
|
|
59
|
+
status: "ok" | "failed" | "running";
|
|
60
|
+
duration_ms?: number;
|
|
61
|
+
error?: string;
|
|
62
|
+
}>;
|
|
63
|
+
result?: ScriptRunResult;
|
|
64
|
+
started_at: string;
|
|
65
|
+
}
|
|
66
|
+
export declare function getJob(jobId: string): ScriptJob | null;
|
|
67
|
+
export declare function listJobs(): ScriptJob[];
|
|
48
68
|
export declare function saveScript(script: LoginScript): string;
|
|
49
69
|
export declare function loadScript(name: string): LoginScript | null;
|
|
50
70
|
export declare function listScripts(): Array<{
|
|
@@ -54,6 +74,11 @@ export declare function listScripts(): Array<{
|
|
|
54
74
|
steps: number;
|
|
55
75
|
}>;
|
|
56
76
|
export declare function deleteScript(name: string): boolean;
|
|
57
|
-
export declare function runScript(script: LoginScript, page: Page, overrides?: Record<string, string
|
|
77
|
+
export declare function runScript(script: LoginScript, page: Page, overrides?: Record<string, string>, jobId?: string): Promise<ScriptRunResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Run a script asynchronously — returns immediately with a job ID.
|
|
80
|
+
* Poll with getJob(jobId) for progress.
|
|
81
|
+
*/
|
|
82
|
+
export declare function runScriptAsync(script: LoginScript, page: Page, overrides?: Record<string, string>): string;
|
|
58
83
|
export declare function createUsestableScript(email: string): LoginScript;
|
|
59
84
|
//# sourceMappingURL=login-scripts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-scripts.d.ts","sourceRoot":"","sources":["../../src/lib/login-scripts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,CAAC;AAEjG,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,qBAAqB,GAAG,eAAe,GAAG,UAAU,CAAC;IAC7G,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAOtD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI3D;AAED,wBAAgB,WAAW,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAY1G;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMlD;
|
|
1
|
+
{"version":3,"file":"login-scripts.d.ts","sourceRoot":"","sources":["../../src/lib/login-scripts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,CAAC;AAEjG,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,qBAAqB,GAAG,eAAe,GAAG,UAAU,CAAC;IAC7G,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,wBAAwB,EAAE,MAAM,CAAC;IACjC,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,SAAS,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjJ,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtD;AAED,wBAAgB,QAAQ,IAAI,SAAS,EAAE,CAEtC;AAUD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAOtD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI3D;AAED,wBAAgB,WAAW,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAY1G;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMlD;AAgBD,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,IAAI,EACV,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACtC,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC,CA0G1B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,IAAI,EACV,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACrC,MAAM,CAqBR;AAmID,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CA2ChE"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -17120,14 +17120,24 @@ var init_dist = __esm(() => {
|
|
|
17120
17120
|
var exports_login_scripts = {};
|
|
17121
17121
|
__export(exports_login_scripts, {
|
|
17122
17122
|
saveScript: () => saveScript,
|
|
17123
|
+
runScriptAsync: () => runScriptAsync,
|
|
17123
17124
|
runScript: () => runScript,
|
|
17124
17125
|
loadScript: () => loadScript,
|
|
17125
17126
|
listScripts: () => listScripts,
|
|
17127
|
+
listJobs: () => listJobs,
|
|
17128
|
+
getJob: () => getJob,
|
|
17126
17129
|
deleteScript: () => deleteScript,
|
|
17127
17130
|
createUsestableScript: () => createUsestableScript
|
|
17128
17131
|
});
|
|
17132
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
17129
17133
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync10, readdirSync as readdirSync5 } from "fs";
|
|
17130
17134
|
import { join as join10 } from "path";
|
|
17135
|
+
function getJob(jobId) {
|
|
17136
|
+
return activeJobs.get(jobId) ?? null;
|
|
17137
|
+
}
|
|
17138
|
+
function listJobs() {
|
|
17139
|
+
return Array.from(activeJobs.values());
|
|
17140
|
+
}
|
|
17131
17141
|
function getScriptsDir() {
|
|
17132
17142
|
const dir = join10(getDataDir(), "scripts");
|
|
17133
17143
|
mkdirSync10(dir, { recursive: true });
|
|
@@ -17174,15 +17184,34 @@ function interpolate(template, vars) {
|
|
|
17174
17184
|
return vars[key] ?? match;
|
|
17175
17185
|
});
|
|
17176
17186
|
}
|
|
17177
|
-
|
|
17187
|
+
function stepDescription(step) {
|
|
17188
|
+
return step.description ?? `${step.type}${step.action ? `:${step.action}` : ""}${step.connector ? `:${step.connector}` : ""}`;
|
|
17189
|
+
}
|
|
17190
|
+
async function runScript(script, page, overrides = {}, jobId) {
|
|
17178
17191
|
const t0 = Date.now();
|
|
17179
17192
|
const vars = { ...script.variables, ...overrides };
|
|
17180
17193
|
const errors2 = [];
|
|
17181
17194
|
let executed = 0;
|
|
17182
17195
|
let failed = 0;
|
|
17196
|
+
const job = jobId && activeJobs.has(jobId) ? activeJobs.get(jobId) : {
|
|
17197
|
+
id: jobId ?? randomUUID12(),
|
|
17198
|
+
script_name: script.name,
|
|
17199
|
+
status: "running",
|
|
17200
|
+
current_step: 0,
|
|
17201
|
+
total_steps: script.steps.length,
|
|
17202
|
+
current_step_description: "Starting...",
|
|
17203
|
+
steps_log: [],
|
|
17204
|
+
started_at: new Date().toISOString()
|
|
17205
|
+
};
|
|
17206
|
+
activeJobs.set(job.id, job);
|
|
17183
17207
|
for (let i = 0;i < script.steps.length; i++) {
|
|
17184
17208
|
const step = script.steps[i];
|
|
17209
|
+
const desc = stepDescription(step);
|
|
17185
17210
|
executed++;
|
|
17211
|
+
job.current_step = i + 1;
|
|
17212
|
+
job.current_step_description = desc;
|
|
17213
|
+
job.steps_log.push({ step: i + 1, type: step.type, description: desc, status: "running" });
|
|
17214
|
+
const stepStart = Date.now();
|
|
17186
17215
|
try {
|
|
17187
17216
|
switch (step.type) {
|
|
17188
17217
|
case "browser":
|
|
@@ -17219,15 +17248,22 @@ async function runScript(script, page, overrides = {}) {
|
|
|
17219
17248
|
break;
|
|
17220
17249
|
}
|
|
17221
17250
|
}
|
|
17251
|
+
const logEntry = job.steps_log[job.steps_log.length - 1];
|
|
17252
|
+
logEntry.status = "ok";
|
|
17253
|
+
logEntry.duration_ms = Date.now() - stepStart;
|
|
17222
17254
|
} catch (err) {
|
|
17223
17255
|
failed++;
|
|
17224
17256
|
const msg = `Step ${i + 1} (${step.type}/${step.action ?? step.connector ?? ""}): ${err instanceof Error ? err.message : String(err)}`;
|
|
17225
17257
|
errors2.push(msg);
|
|
17258
|
+
const logEntry = job.steps_log[job.steps_log.length - 1];
|
|
17259
|
+
logEntry.status = "failed";
|
|
17260
|
+
logEntry.error = err instanceof Error ? err.message : String(err);
|
|
17261
|
+
logEntry.duration_ms = Date.now() - stepStart;
|
|
17226
17262
|
if (step.type === "browser" && step.action === "navigate")
|
|
17227
17263
|
break;
|
|
17228
17264
|
}
|
|
17229
17265
|
}
|
|
17230
|
-
|
|
17266
|
+
const result = {
|
|
17231
17267
|
success: failed === 0,
|
|
17232
17268
|
steps_executed: executed,
|
|
17233
17269
|
steps_failed: failed,
|
|
@@ -17235,6 +17271,28 @@ async function runScript(script, page, overrides = {}) {
|
|
|
17235
17271
|
errors: errors2,
|
|
17236
17272
|
duration_ms: Date.now() - t0
|
|
17237
17273
|
};
|
|
17274
|
+
job.status = failed === 0 ? "completed" : "failed";
|
|
17275
|
+
job.result = result;
|
|
17276
|
+
return result;
|
|
17277
|
+
}
|
|
17278
|
+
function runScriptAsync(script, page, overrides = {}) {
|
|
17279
|
+
const jobId = randomUUID12();
|
|
17280
|
+
const job = {
|
|
17281
|
+
id: jobId,
|
|
17282
|
+
script_name: script.name,
|
|
17283
|
+
status: "running",
|
|
17284
|
+
current_step: 0,
|
|
17285
|
+
total_steps: script.steps.length,
|
|
17286
|
+
current_step_description: "Starting...",
|
|
17287
|
+
steps_log: [],
|
|
17288
|
+
started_at: new Date().toISOString()
|
|
17289
|
+
};
|
|
17290
|
+
activeJobs.set(jobId, job);
|
|
17291
|
+
runScript(script, page, overrides, jobId).catch((err) => {
|
|
17292
|
+
job.status = "failed";
|
|
17293
|
+
job.current_step_description = `Fatal error: ${err instanceof Error ? err.message : String(err)}`;
|
|
17294
|
+
});
|
|
17295
|
+
return jobId;
|
|
17238
17296
|
}
|
|
17239
17297
|
async function runBrowserStep(step, page, vars) {
|
|
17240
17298
|
const action = step.action;
|
|
@@ -17394,8 +17452,10 @@ function createUsestableScript(email) {
|
|
|
17394
17452
|
updated_at: new Date().toISOString()
|
|
17395
17453
|
};
|
|
17396
17454
|
}
|
|
17455
|
+
var activeJobs;
|
|
17397
17456
|
var init_login_scripts = __esm(() => {
|
|
17398
17457
|
init_schema();
|
|
17458
|
+
activeJobs = new Map;
|
|
17399
17459
|
});
|
|
17400
17460
|
|
|
17401
17461
|
// src/lib/api-detector.ts
|
|
@@ -17404,7 +17464,7 @@ __export(exports_api_detector, {
|
|
|
17404
17464
|
listDiscoveredAPIs: () => listDiscoveredAPIs,
|
|
17405
17465
|
detectAPIs: () => detectAPIs
|
|
17406
17466
|
});
|
|
17407
|
-
import { randomUUID as
|
|
17467
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
17408
17468
|
function detectAPIs(sessionId) {
|
|
17409
17469
|
const db = getDatabase();
|
|
17410
17470
|
const requests = db.query(`SELECT method, url, status_code, response_headers, body_size
|
|
@@ -17440,7 +17500,7 @@ function detectAPIs(sessionId) {
|
|
|
17440
17500
|
}
|
|
17441
17501
|
const apis = Array.from(seen.values());
|
|
17442
17502
|
for (const api of apis) {
|
|
17443
|
-
const id =
|
|
17503
|
+
const id = randomUUID13();
|
|
17444
17504
|
db.prepare("INSERT OR IGNORE INTO api_endpoints (id, session_id, url, method, status_code, content_type) VALUES (?, ?, ?, ?, ?, ?)").run(id, sessionId, api.url, api.method, api.status_code, api.content_type);
|
|
17445
17505
|
}
|
|
17446
17506
|
return apis;
|
|
@@ -17545,13 +17605,13 @@ __export(exports_datasets, {
|
|
|
17545
17605
|
exportDataset: () => exportDataset,
|
|
17546
17606
|
deleteDataset: () => deleteDataset
|
|
17547
17607
|
});
|
|
17548
|
-
import { randomUUID as
|
|
17608
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
17549
17609
|
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync11 } from "fs";
|
|
17550
17610
|
import { join as join11 } from "path";
|
|
17551
17611
|
import { homedir as homedir10 } from "os";
|
|
17552
17612
|
function saveDataset(data) {
|
|
17553
17613
|
const db = getDatabase();
|
|
17554
|
-
const id =
|
|
17614
|
+
const id = randomUUID14();
|
|
17555
17615
|
const existing = db.query("SELECT id FROM datasets WHERE name = ?").get(data.name);
|
|
17556
17616
|
if (existing) {
|
|
17557
17617
|
db.prepare("UPDATE datasets SET data = ?, row_count = ?, source_url = ?, schema = ?, last_refresh = datetime('now'), updated_at = datetime('now') WHERE name = ?").run(JSON.stringify(data.rows), data.rows.length, data.sourceUrl ?? null, data.schema ? JSON.stringify(data.schema) : null, data.name);
|
|
@@ -22442,7 +22502,7 @@ import { Database as Database3 } from "bun:sqlite";
|
|
|
22442
22502
|
import { mkdirSync as mkdirSync13 } from "fs";
|
|
22443
22503
|
import { join as join14, dirname as dirname6 } from "path";
|
|
22444
22504
|
import { homedir as homedir13 } from "os";
|
|
22445
|
-
import { randomUUID as
|
|
22505
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
22446
22506
|
import { mkdirSync as mkdirSync23, copyFileSync as copyFileSync3, statSync as statSync3 } from "fs";
|
|
22447
22507
|
import { join as join34 } from "path";
|
|
22448
22508
|
import { homedir as homedir33 } from "os";
|
|
@@ -22822,7 +22882,7 @@ function guessMimeType(name) {
|
|
|
22822
22882
|
function sendMessage(opts) {
|
|
22823
22883
|
const db2 = getDb();
|
|
22824
22884
|
const explicitSession = opts.session_id && opts.session_id.trim().length > 0 ? opts.session_id : undefined;
|
|
22825
|
-
const sessionId = explicitSession ?? (opts.space ? `space:${opts.space}` : `${[opts.from, opts.to].sort().join("-")}-${
|
|
22885
|
+
const sessionId = explicitSession ?? (opts.space ? `space:${opts.space}` : `${[opts.from, opts.to].sort().join("-")}-${randomUUID15().slice(0, 8)}`);
|
|
22826
22886
|
const metadata = opts.metadata ? JSON.stringify(opts.metadata) : null;
|
|
22827
22887
|
const normalizedPriority = opts.priority === "low" || opts.priority === "normal" || opts.priority === "high" || opts.priority === "urgent" ? opts.priority : "normal";
|
|
22828
22888
|
const blocking = opts.blocking ? 1 : 0;
|
|
@@ -34511,7 +34571,7 @@ __export(exports_cron_manager, {
|
|
|
34511
34571
|
deleteCronJob: () => deleteCronJob,
|
|
34512
34572
|
createCronJob: () => createCronJob
|
|
34513
34573
|
});
|
|
34514
|
-
import { randomUUID as
|
|
34574
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
34515
34575
|
function ensureCronTable() {
|
|
34516
34576
|
const db2 = getDatabase();
|
|
34517
34577
|
db2.exec(`
|
|
@@ -34540,7 +34600,7 @@ function ensureCronTable() {
|
|
|
34540
34600
|
function createCronJob(schedule, task, name) {
|
|
34541
34601
|
ensureCronTable();
|
|
34542
34602
|
const db2 = getDatabase();
|
|
34543
|
-
const id =
|
|
34603
|
+
const id = randomUUID16();
|
|
34544
34604
|
db2.prepare(`
|
|
34545
34605
|
INSERT INTO cron_jobs (id, name, schedule, task_json, enabled)
|
|
34546
34606
|
VALUES (?, ?, ?, ?, 1)
|
|
@@ -34598,7 +34658,7 @@ function getCronEvents(jobId, limit = 10) {
|
|
|
34598
34658
|
async function executeCronJob(job) {
|
|
34599
34659
|
ensureCronTable();
|
|
34600
34660
|
const db2 = getDatabase();
|
|
34601
|
-
const eventId =
|
|
34661
|
+
const eventId = randomUUID16();
|
|
34602
34662
|
const startedAt = new Date().toISOString();
|
|
34603
34663
|
db2.prepare("INSERT INTO cron_events (id, job_id, started_at) VALUES (?, ?, ?)").run(eventId, job.id, startedAt);
|
|
34604
34664
|
try {
|
|
@@ -34689,7 +34749,7 @@ __export(exports_url_watcher, {
|
|
|
34689
34749
|
deleteWatchJob: () => deleteWatchJob,
|
|
34690
34750
|
createWatchJob: () => createWatchJob
|
|
34691
34751
|
});
|
|
34692
|
-
import { randomUUID as
|
|
34752
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
34693
34753
|
import { createHash } from "crypto";
|
|
34694
34754
|
function ensureWatchTables() {
|
|
34695
34755
|
const db2 = getDatabase();
|
|
@@ -34721,7 +34781,7 @@ function ensureWatchTables() {
|
|
|
34721
34781
|
function createWatchJob(url, schedule, opts) {
|
|
34722
34782
|
ensureWatchTables();
|
|
34723
34783
|
const db2 = getDatabase();
|
|
34724
|
-
const id =
|
|
34784
|
+
const id = randomUUID17();
|
|
34725
34785
|
db2.prepare(`
|
|
34726
34786
|
INSERT INTO watch_jobs (id, name, url, schedule, selector, extract_schema, enabled)
|
|
34727
34787
|
VALUES (?, ?, ?, ?, ?, ?, 1)
|
|
@@ -34757,7 +34817,7 @@ function getWatchEvents(watchId, limit = 20) {
|
|
|
34757
34817
|
async function checkWatchJob(job) {
|
|
34758
34818
|
ensureWatchTables();
|
|
34759
34819
|
const db2 = getDatabase();
|
|
34760
|
-
const eventId =
|
|
34820
|
+
const eventId = randomUUID17();
|
|
34761
34821
|
const checkedAt = new Date().toISOString();
|
|
34762
34822
|
let newContent = "";
|
|
34763
34823
|
try {
|
|
@@ -41384,13 +41444,13 @@ server.tool("browser_profile_delete", "Delete a saved browser profile", { name:
|
|
|
41384
41444
|
return err(e);
|
|
41385
41445
|
}
|
|
41386
41446
|
});
|
|
41387
|
-
server.tool("browser_script_run", "Run a saved login script \u2014
|
|
41447
|
+
server.tool("browser_script_run", "Run a saved login script asynchronously. Returns a job_id immediately \u2014 poll with browser_script_status for step-by-step progress. Combines browser actions + connector calls (e.g. magic link login via Gmail).", {
|
|
41388
41448
|
name: exports_external.string().describe("Script name (e.g. 'usestable')"),
|
|
41389
41449
|
session_id: exports_external.string().optional(),
|
|
41390
41450
|
variables: exports_external.record(exports_external.string()).optional().describe("Override script variables (e.g. {email: 'foo@bar.com'})")
|
|
41391
41451
|
}, async ({ name, session_id, variables }) => {
|
|
41392
41452
|
try {
|
|
41393
|
-
const { loadScript: loadScript2,
|
|
41453
|
+
const { loadScript: loadScript2, runScriptAsync: runScriptAsync2 } = await Promise.resolve().then(() => (init_login_scripts(), exports_login_scripts));
|
|
41394
41454
|
const script = loadScript2(name);
|
|
41395
41455
|
if (!script)
|
|
41396
41456
|
return err(new Error(`Script '${name}' not found. Use browser_script_list to see available scripts.`));
|
|
@@ -41400,12 +41460,29 @@ server.tool("browser_script_run", "Run a saved login script \u2014 multi-step wo
|
|
|
41400
41460
|
sid = resolveSessionId(session_id);
|
|
41401
41461
|
page = getSessionPage(sid);
|
|
41402
41462
|
} else {
|
|
41403
|
-
const
|
|
41404
|
-
sid =
|
|
41405
|
-
page =
|
|
41463
|
+
const result = await createSession2({ headless: true });
|
|
41464
|
+
sid = result.session.id;
|
|
41465
|
+
page = result.page;
|
|
41406
41466
|
}
|
|
41407
|
-
const
|
|
41408
|
-
return json({
|
|
41467
|
+
const jobId = runScriptAsync2(script, page, variables ?? {});
|
|
41468
|
+
return json({ job_id: jobId, session_id: sid, script: name, total_steps: script.steps.length, message: "Script running in background. Poll with browser_script_status for progress." });
|
|
41469
|
+
} catch (e) {
|
|
41470
|
+
return err(e);
|
|
41471
|
+
}
|
|
41472
|
+
});
|
|
41473
|
+
server.tool("browser_script_status", "Check the progress of a running login script. Shows current step, step-by-step log with durations, and final result when complete.", { job_id: exports_external.string() }, async ({ job_id }) => {
|
|
41474
|
+
try {
|
|
41475
|
+
const { getJob: getJob2 } = await Promise.resolve().then(() => (init_login_scripts(), exports_login_scripts));
|
|
41476
|
+
const job = getJob2(job_id);
|
|
41477
|
+
if (!job)
|
|
41478
|
+
return err(new Error(`Job '${job_id}' not found`));
|
|
41479
|
+
return json({
|
|
41480
|
+
status: job.status,
|
|
41481
|
+
progress: `${job.current_step}/${job.total_steps}`,
|
|
41482
|
+
current_step: job.current_step_description,
|
|
41483
|
+
steps_log: job.steps_log,
|
|
41484
|
+
result: job.result ?? undefined
|
|
41485
|
+
});
|
|
41409
41486
|
} catch (e) {
|
|
41410
41487
|
return err(e);
|
|
41411
41488
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/browser",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "General-purpose browser agent toolkit — Playwright, Chrome DevTools Protocol, Lightpanda with auto engine selection. CLI + MCP + REST + SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|