@hasna/browser 0.4.8 → 0.4.10
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 +355 -249
- package/dist/db/gallery.d.ts.map +1 -1
- package/dist/engines/tui.d.ts.map +1 -1
- package/dist/index.js +121 -96
- package/dist/lib/auth.d.ts +7 -1
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/gallery-diff.d.ts +1 -1
- package/dist/lib/gallery-diff.d.ts.map +1 -1
- package/dist/lib/recorder.d.ts +1 -0
- package/dist/lib/recorder.d.ts.map +1 -1
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/stealth.d.ts.map +1 -1
- package/dist/lib/tui-recording.d.ts +3 -0
- package/dist/lib/tui-recording.d.ts.map +1 -0
- package/dist/mcp/http.d.ts +17 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.test.d.ts +2 -0
- package/dist/mcp/http.test.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +2 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +18 -18
- package/dist/mcp/integration.d.ts.map +1 -1
- package/dist/mcp/tui.d.ts.map +1 -1
- package/dist/server/index.js +103 -101
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -14383,7 +14383,7 @@ function buildRowRefs(rows, method, totalRows, rowCount) {
|
|
|
14383
14383
|
row: index,
|
|
14384
14384
|
text,
|
|
14385
14385
|
visible: method === "dom" ? true : index >= firstVisibleRow,
|
|
14386
|
-
selector: method === "dom" ? `#takumi-tui-dom-root [data-row="${index}"]` : undefined
|
|
14386
|
+
selector: method === "dom" ? `#takumi-tui-dom-root .takumi-tui-dom-row[data-row="${index}"]` : undefined
|
|
14387
14387
|
};
|
|
14388
14388
|
});
|
|
14389
14389
|
return refs;
|
|
@@ -14591,7 +14591,7 @@ async function readDomMirrorState(page) {
|
|
|
14591
14591
|
const runtime = window.__takumiTuiDomRenderer;
|
|
14592
14592
|
if (runtime?.sync)
|
|
14593
14593
|
return runtime.sync();
|
|
14594
|
-
const rowEls = Array.from(document.querySelectorAll("#takumi-tui-dom-root
|
|
14594
|
+
const rowEls = Array.from(document.querySelectorAll("#takumi-tui-dom-root .takumi-tui-dom-row"));
|
|
14595
14595
|
const rows = rowEls.map((row) => row.getAttribute("aria-label") ?? row.textContent ?? "");
|
|
14596
14596
|
const term = window.term ?? window.terminal;
|
|
14597
14597
|
const active = term?.buffer?.active;
|
|
@@ -14614,17 +14614,14 @@ function isDomMethod(method) {
|
|
|
14614
14614
|
return method === "dom";
|
|
14615
14615
|
}
|
|
14616
14616
|
async function withTimeout(label, operation, timeoutMs = DEFAULT_TOOL_TIMEOUT_MS) {
|
|
14617
|
-
let
|
|
14618
|
-
const
|
|
14619
|
-
|
|
14620
|
-
|
|
14617
|
+
let timer;
|
|
14618
|
+
const timeout = new Promise((_, reject) => {
|
|
14619
|
+
timer = setTimeout(() => {
|
|
14620
|
+
reject(new BrowserError(`${label} timed out after ${timeoutMs}ms \u2014 ttyd/playwright connection may be unhealthy. Try closing and re-opening the session.`, "TUI_TIMEOUT"));
|
|
14621
|
+
}, timeoutMs);
|
|
14622
|
+
});
|
|
14621
14623
|
try {
|
|
14622
|
-
return await operation();
|
|
14623
|
-
} catch (err) {
|
|
14624
|
-
if (timedOut) {
|
|
14625
|
-
throw new BrowserError(`${label} timed out after ${timeoutMs}ms \u2014 ttyd/playwright connection may be unhealthy. Try closing and re-opening the session.`, "TUI_TIMEOUT");
|
|
14626
|
-
}
|
|
14627
|
-
throw err;
|
|
14624
|
+
return await Promise.race([operation(), timeout]);
|
|
14628
14625
|
} finally {
|
|
14629
14626
|
clearTimeout(timer);
|
|
14630
14627
|
}
|
|
@@ -14894,7 +14891,7 @@ async function waitForTerminalText(page, text, timeoutMs = 30000, method = "buff
|
|
|
14894
14891
|
return { found: true, elapsed_ms: Date.now() - start, stuck: false };
|
|
14895
14892
|
await new Promise((r) => setTimeout(r, 250));
|
|
14896
14893
|
}
|
|
14897
|
-
return { found: false, elapsed_ms:
|
|
14894
|
+
return { found: false, elapsed_ms: Date.now() - start, stuck: false };
|
|
14898
14895
|
}
|
|
14899
14896
|
async function closeTui(session) {
|
|
14900
14897
|
await destroyDomRenderer(session.page);
|
|
@@ -15007,6 +15004,23 @@ var init_selector = __esm(() => {
|
|
|
15007
15004
|
};
|
|
15008
15005
|
});
|
|
15009
15006
|
|
|
15007
|
+
// src/lib/tui-recording.ts
|
|
15008
|
+
function trackTuiRecording(sessionId, intervalId) {
|
|
15009
|
+
stopTuiRecording(sessionId);
|
|
15010
|
+
recordingIntervals.set(sessionId, intervalId);
|
|
15011
|
+
}
|
|
15012
|
+
function stopTuiRecording(sessionId) {
|
|
15013
|
+
const intervalId = recordingIntervals.get(sessionId);
|
|
15014
|
+
if (!intervalId)
|
|
15015
|
+
return;
|
|
15016
|
+
clearInterval(intervalId);
|
|
15017
|
+
recordingIntervals.delete(sessionId);
|
|
15018
|
+
}
|
|
15019
|
+
var recordingIntervals;
|
|
15020
|
+
var init_tui_recording = __esm(() => {
|
|
15021
|
+
recordingIntervals = new Map;
|
|
15022
|
+
});
|
|
15023
|
+
|
|
15010
15024
|
// src/db/network-log.ts
|
|
15011
15025
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
15012
15026
|
function logRequest(data) {
|
|
@@ -15226,7 +15240,9 @@ async function applyStealthPatches(page) {
|
|
|
15226
15240
|
"User-Agent": REALISTIC_USER_AGENT
|
|
15227
15241
|
});
|
|
15228
15242
|
}
|
|
15229
|
-
var REALISTIC_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36", STEALTH_SCRIPT
|
|
15243
|
+
var REALISTIC_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36", STEALTH_SCRIPT;
|
|
15244
|
+
var init_stealth = __esm(() => {
|
|
15245
|
+
STEALTH_SCRIPT = `
|
|
15230
15246
|
// \u2500\u2500 1. Remove navigator.webdriver flag \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
15231
15247
|
Object.defineProperty(navigator, 'webdriver', {
|
|
15232
15248
|
get: () => false,
|
|
@@ -15274,8 +15290,14 @@ if (!window.chrome.runtime) {
|
|
|
15274
15290
|
id: undefined,
|
|
15275
15291
|
};
|
|
15276
15292
|
}
|
|
15293
|
+
|
|
15294
|
+
// \u2500\u2500 5. Override navigator.userAgent to match HTTP header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
15295
|
+
Object.defineProperty(navigator, 'userAgent', {
|
|
15296
|
+
get: () => "${REALISTIC_USER_AGENT}",
|
|
15297
|
+
configurable: true,
|
|
15298
|
+
});
|
|
15277
15299
|
`;
|
|
15278
|
-
|
|
15300
|
+
});
|
|
15279
15301
|
|
|
15280
15302
|
// src/lib/dialogs.ts
|
|
15281
15303
|
var exports_dialogs = {};
|
|
@@ -16339,6 +16361,29 @@ __export(exports_session, {
|
|
|
16339
16361
|
function createBunProxy(view) {
|
|
16340
16362
|
return view;
|
|
16341
16363
|
}
|
|
16364
|
+
function attachPlaywrightListeners(page, sessionId, cleanups, opts = {}) {
|
|
16365
|
+
if (opts.captureNetwork !== false) {
|
|
16366
|
+
try {
|
|
16367
|
+
cleanups.push(enableNetworkLogging(page, sessionId));
|
|
16368
|
+
} catch {}
|
|
16369
|
+
}
|
|
16370
|
+
if (opts.captureConsole !== false) {
|
|
16371
|
+
try {
|
|
16372
|
+
cleanups.push(enableConsoleCapture(page, sessionId));
|
|
16373
|
+
} catch {}
|
|
16374
|
+
}
|
|
16375
|
+
try {
|
|
16376
|
+
cleanups.push(setupDialogHandler(page, sessionId));
|
|
16377
|
+
} catch {}
|
|
16378
|
+
}
|
|
16379
|
+
function detachPlaywrightListeners(cleanups) {
|
|
16380
|
+
while (cleanups.length > 1) {
|
|
16381
|
+
const cleanup = cleanups.pop();
|
|
16382
|
+
try {
|
|
16383
|
+
cleanup?.();
|
|
16384
|
+
} catch {}
|
|
16385
|
+
}
|
|
16386
|
+
}
|
|
16342
16387
|
async function createSession2(opts = {}) {
|
|
16343
16388
|
if (opts.cdpUrl) {
|
|
16344
16389
|
const { connectToExistingBrowser: connectToExistingBrowser2 } = await Promise.resolve().then(() => (init_cdp(), exports_cdp));
|
|
@@ -16376,9 +16421,11 @@ async function createSession2(opts = {}) {
|
|
|
16376
16421
|
let browser = null;
|
|
16377
16422
|
let bunView = null;
|
|
16378
16423
|
let page;
|
|
16424
|
+
let actualEngine = resolvedEngine;
|
|
16379
16425
|
if (resolvedEngine === "bun") {
|
|
16380
16426
|
if (!isBunWebViewAvailable()) {
|
|
16381
16427
|
console.warn("[browser] Bun.WebView requested but not available \u2014 falling back to playwright. Run: bun upgrade --canary");
|
|
16428
|
+
actualEngine = "playwright";
|
|
16382
16429
|
browser = await launchPlaywright({ headless: opts.headless ?? true, viewport: opts.viewport, userAgent: opts.userAgent });
|
|
16383
16430
|
page = await getPage(browser, { viewport: opts.viewport, userAgent: opts.userAgent });
|
|
16384
16431
|
} else {
|
|
@@ -16398,9 +16445,11 @@ async function createSession2(opts = {}) {
|
|
|
16398
16445
|
}
|
|
16399
16446
|
if (!bunWorks) {
|
|
16400
16447
|
console.warn("[browser] Bun.WebView exists but Chrome not available \u2014 falling back to playwright");
|
|
16448
|
+
actualEngine = "playwright";
|
|
16401
16449
|
browser = await launchPlaywright({ headless: opts.headless ?? true, viewport: opts.viewport, userAgent: opts.userAgent });
|
|
16402
16450
|
page = await getPage(browser, { viewport: opts.viewport, userAgent: opts.userAgent });
|
|
16403
16451
|
} else {
|
|
16452
|
+
actualEngine = "bun";
|
|
16404
16453
|
bunView = testView;
|
|
16405
16454
|
if (opts.stealth) {}
|
|
16406
16455
|
page = createBunProxy(bunView);
|
|
@@ -16430,19 +16479,10 @@ async function createSession2(opts = {}) {
|
|
|
16430
16479
|
});
|
|
16431
16480
|
const cleanups2 = [];
|
|
16432
16481
|
cleanups2.push(() => closeTui(tuiSess));
|
|
16433
|
-
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
}
|
|
16438
|
-
if (opts.captureConsole !== false) {
|
|
16439
|
-
try {
|
|
16440
|
-
cleanups2.push(enableConsoleCapture(page, session2.id));
|
|
16441
|
-
} catch {}
|
|
16442
|
-
}
|
|
16443
|
-
try {
|
|
16444
|
-
cleanups2.push(setupDialogHandler(page, session2.id));
|
|
16445
|
-
} catch {}
|
|
16482
|
+
attachPlaywrightListeners(page, session2.id, cleanups2, {
|
|
16483
|
+
captureNetwork: opts.captureNetwork,
|
|
16484
|
+
captureConsole: opts.captureConsole
|
|
16485
|
+
});
|
|
16446
16486
|
handles.set(session2.id, { browser, bunView: null, tuiSession: tuiSess, page, engine: "tui", cleanups: cleanups2, tokenBudget: { total: 0, used: 0 }, lastActivity: Date.now(), autoGallery: opts.autoGallery ?? false, startUrl: opts.startUrl ?? "bash" });
|
|
16447
16487
|
return { session: session2, page };
|
|
16448
16488
|
} else {
|
|
@@ -16472,7 +16512,7 @@ async function createSession2(opts = {}) {
|
|
|
16472
16512
|
}
|
|
16473
16513
|
})() : undefined);
|
|
16474
16514
|
const session = createSession({
|
|
16475
|
-
engine:
|
|
16515
|
+
engine: actualEngine,
|
|
16476
16516
|
projectId: opts.projectId,
|
|
16477
16517
|
agentId: opts.agentId,
|
|
16478
16518
|
startUrl: opts.startUrl,
|
|
@@ -16485,37 +16525,12 @@ async function createSession2(opts = {}) {
|
|
|
16485
16525
|
}
|
|
16486
16526
|
const cleanups = [];
|
|
16487
16527
|
if (!bunView) {
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
}
|
|
16493
|
-
if (opts.captureConsole !== false) {
|
|
16494
|
-
try {
|
|
16495
|
-
cleanups.push(enableConsoleCapture(page, session.id));
|
|
16496
|
-
} catch {}
|
|
16497
|
-
}
|
|
16498
|
-
try {
|
|
16499
|
-
cleanups.push(setupDialogHandler(page, session.id));
|
|
16500
|
-
} catch {}
|
|
16501
|
-
} else {
|
|
16502
|
-
if (opts.captureConsole !== false) {
|
|
16503
|
-
try {
|
|
16504
|
-
const { logConsoleMessage: logConsoleMessage2 } = await Promise.resolve().then(() => (init_console_log(), exports_console_log));
|
|
16505
|
-
await bunView.addInitScript(`
|
|
16506
|
-
(() => {
|
|
16507
|
-
const orig = { log: console.log, warn: console.warn, error: console.error, debug: console.debug, info: console.info };
|
|
16508
|
-
['log','warn','error','debug','info'].forEach(level => {
|
|
16509
|
-
console[level] = (...args) => {
|
|
16510
|
-
orig[level](...args);
|
|
16511
|
-
};
|
|
16512
|
-
});
|
|
16513
|
-
})()
|
|
16514
|
-
`);
|
|
16515
|
-
} catch {}
|
|
16516
|
-
}
|
|
16528
|
+
attachPlaywrightListeners(page, session.id, cleanups, {
|
|
16529
|
+
captureNetwork: opts.captureNetwork,
|
|
16530
|
+
captureConsole: opts.captureConsole
|
|
16531
|
+
});
|
|
16517
16532
|
}
|
|
16518
|
-
handles.set(session.id, { browser, bunView, tuiSession: null, page, engine:
|
|
16533
|
+
handles.set(session.id, { browser, bunView, tuiSession: null, page, engine: actualEngine, cleanups, tokenBudget: { total: 0, used: 0 }, lastActivity: Date.now(), autoGallery: opts.autoGallery ?? false, startUrl: opts.startUrl ?? "" });
|
|
16519
16534
|
if (opts.startUrl) {
|
|
16520
16535
|
try {
|
|
16521
16536
|
if (bunView) {
|
|
@@ -16548,7 +16563,8 @@ function getSessionBunView(sessionId) {
|
|
|
16548
16563
|
return handles.get(sessionId)?.bunView ?? null;
|
|
16549
16564
|
}
|
|
16550
16565
|
function isBunSession(sessionId) {
|
|
16551
|
-
|
|
16566
|
+
const handle = handles.get(sessionId);
|
|
16567
|
+
return handle?.engine === "bun" && handle.bunView !== null;
|
|
16552
16568
|
}
|
|
16553
16569
|
function getSessionBrowser(sessionId) {
|
|
16554
16570
|
const handle = handles.get(sessionId);
|
|
@@ -16574,11 +16590,16 @@ function setSessionTui(sessionId, tuiSess) {
|
|
|
16574
16590
|
const handle = handles.get(sessionId);
|
|
16575
16591
|
if (!handle)
|
|
16576
16592
|
throw new SessionNotFoundError(sessionId);
|
|
16593
|
+
detachPlaywrightListeners(handle.cleanups);
|
|
16577
16594
|
handle.tuiSession = tuiSess;
|
|
16578
16595
|
handle.page = tuiSess.page;
|
|
16579
16596
|
if (tuiSess.browser !== handle.browser) {
|
|
16580
16597
|
handle.browser = tuiSess.browser;
|
|
16581
16598
|
}
|
|
16599
|
+
attachPlaywrightListeners(tuiSess.page, sessionId, handle.cleanups, {
|
|
16600
|
+
captureNetwork: true,
|
|
16601
|
+
captureConsole: true
|
|
16602
|
+
});
|
|
16582
16603
|
handle.lastActivity = Date.now();
|
|
16583
16604
|
}
|
|
16584
16605
|
function getSessionCommand(sessionId) {
|
|
@@ -16594,9 +16615,12 @@ async function closeSession2(sessionId) {
|
|
|
16594
16615
|
const handle = handles.get(sessionId);
|
|
16595
16616
|
try {
|
|
16596
16617
|
if (handle) {
|
|
16618
|
+
if (handle.engine === "tui") {
|
|
16619
|
+
stopTuiRecording(sessionId);
|
|
16620
|
+
}
|
|
16597
16621
|
for (const cleanup of handle.cleanups) {
|
|
16598
16622
|
try {
|
|
16599
|
-
cleanup();
|
|
16623
|
+
await cleanup();
|
|
16600
16624
|
} catch {}
|
|
16601
16625
|
}
|
|
16602
16626
|
if (handle.bunView) {
|
|
@@ -16708,6 +16732,7 @@ var init_session = __esm(() => {
|
|
|
16708
16732
|
init_bun_webview();
|
|
16709
16733
|
init_selector();
|
|
16710
16734
|
init_tui();
|
|
16735
|
+
init_tui_recording();
|
|
16711
16736
|
init_network();
|
|
16712
16737
|
init_console();
|
|
16713
16738
|
init_stealth();
|
|
@@ -23335,10 +23360,17 @@ __export(exports_gallery, {
|
|
|
23335
23360
|
createEntry: () => createEntry
|
|
23336
23361
|
});
|
|
23337
23362
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
23363
|
+
import { join as join11, resolve, relative as relative2, isAbsolute } from "path";
|
|
23338
23364
|
function validateDataPath(filePath) {
|
|
23339
23365
|
if (filePath.includes("..")) {
|
|
23340
23366
|
throw new Error(`File path must not contain '..': ${filePath}`);
|
|
23341
23367
|
}
|
|
23368
|
+
const dataDir = resolve(getDataDir2());
|
|
23369
|
+
const resolved = resolve(isAbsolute(filePath) ? filePath : join11(dataDir, filePath));
|
|
23370
|
+
const rel = relative2(dataDir, resolved);
|
|
23371
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
23372
|
+
throw new Error(`File path must be within data directory: ${filePath}`);
|
|
23373
|
+
}
|
|
23342
23374
|
return filePath;
|
|
23343
23375
|
}
|
|
23344
23376
|
function deserialize(row) {
|
|
@@ -23356,7 +23388,13 @@ function deserialize(row) {
|
|
|
23356
23388
|
original_size_bytes: row.original_size_bytes ?? undefined,
|
|
23357
23389
|
compressed_size_bytes: row.compressed_size_bytes ?? undefined,
|
|
23358
23390
|
compression_ratio: row.compression_ratio ?? undefined,
|
|
23359
|
-
tags:
|
|
23391
|
+
tags: (() => {
|
|
23392
|
+
try {
|
|
23393
|
+
return JSON.parse(row.tags);
|
|
23394
|
+
} catch {
|
|
23395
|
+
return [];
|
|
23396
|
+
}
|
|
23397
|
+
})(),
|
|
23360
23398
|
notes: row.notes ?? undefined,
|
|
23361
23399
|
is_favorite: row.is_favorite === 1,
|
|
23362
23400
|
created_at: row.created_at
|
|
@@ -23487,12 +23525,12 @@ var init_gallery = __esm(() => {
|
|
|
23487
23525
|
});
|
|
23488
23526
|
|
|
23489
23527
|
// src/lib/screenshot.ts
|
|
23490
|
-
import { join as
|
|
23528
|
+
import { join as join12 } from "path";
|
|
23491
23529
|
import { mkdirSync as mkdirSync8 } from "fs";
|
|
23492
23530
|
function getScreenshotDir(projectId) {
|
|
23493
|
-
const base =
|
|
23531
|
+
const base = join12(getDataDir2(), "screenshots");
|
|
23494
23532
|
const date = new Date().toISOString().split("T")[0];
|
|
23495
|
-
const dir = projectId ?
|
|
23533
|
+
const dir = projectId ? join12(base, projectId, date) : join12(base, date);
|
|
23496
23534
|
mkdirSync8(dir, { recursive: true });
|
|
23497
23535
|
return dir;
|
|
23498
23536
|
}
|
|
@@ -23508,7 +23546,7 @@ async function compressBuffer(raw, format, quality, maxWidth) {
|
|
|
23508
23546
|
}
|
|
23509
23547
|
}
|
|
23510
23548
|
async function generateThumbnail(raw, dir, stem) {
|
|
23511
|
-
const thumbPath =
|
|
23549
|
+
const thumbPath = join12(dir, `${stem}.thumb.webp`);
|
|
23512
23550
|
const thumbBuffer = await import_sharp.default(raw).resize({ width: 200, withoutEnlargement: true }).webp({ quality: 70, effort: 3 }).toBuffer();
|
|
23513
23551
|
await Bun.write(thumbPath, thumbBuffer);
|
|
23514
23552
|
return { path: thumbPath, base64: thumbBuffer.toString("base64") };
|
|
@@ -23576,7 +23614,7 @@ async function takeScreenshot(page, opts) {
|
|
|
23576
23614
|
const compressedSizeBytes = finalBuffer.length;
|
|
23577
23615
|
const compressionRatio = originalSizeBytes > 0 ? compressedSizeBytes / originalSizeBytes : 1;
|
|
23578
23616
|
const ext = format;
|
|
23579
|
-
const screenshotPath = opts?.path ??
|
|
23617
|
+
const screenshotPath = opts?.path ?? join12(dir, `${stem}.${ext}`);
|
|
23580
23618
|
await Bun.write(screenshotPath, finalBuffer);
|
|
23581
23619
|
let thumbnailPath;
|
|
23582
23620
|
let thumbnailBase64;
|
|
@@ -23636,12 +23674,12 @@ async function takeScreenshot(page, opts) {
|
|
|
23636
23674
|
}
|
|
23637
23675
|
async function generatePDF(page, opts) {
|
|
23638
23676
|
try {
|
|
23639
|
-
const base =
|
|
23677
|
+
const base = join12(getDataDir2(), "pdfs");
|
|
23640
23678
|
const date = new Date().toISOString().split("T")[0];
|
|
23641
|
-
const dir = opts?.projectId ?
|
|
23679
|
+
const dir = opts?.projectId ? join12(base, opts.projectId, date) : join12(base, date);
|
|
23642
23680
|
mkdirSync8(dir, { recursive: true });
|
|
23643
23681
|
const timestamp = Date.now();
|
|
23644
|
-
const pdfPath = opts?.path ??
|
|
23682
|
+
const pdfPath = opts?.path ?? join12(dir, `${timestamp}.pdf`);
|
|
23645
23683
|
const buffer = await page.pdf({
|
|
23646
23684
|
path: pdfPath,
|
|
23647
23685
|
format: opts?.format ?? "A4",
|
|
@@ -24159,9 +24197,9 @@ var exports_gallery_diff = {};
|
|
|
24159
24197
|
__export(exports_gallery_diff, {
|
|
24160
24198
|
diffImages: () => diffImages
|
|
24161
24199
|
});
|
|
24162
|
-
import { join as
|
|
24200
|
+
import { join as join13 } from "path";
|
|
24163
24201
|
import { mkdirSync as mkdirSync9 } from "fs";
|
|
24164
|
-
async function diffImages(path1, path2) {
|
|
24202
|
+
async function diffImages(path1, path2, threshold = 10) {
|
|
24165
24203
|
const img1 = import_sharp2.default(path1);
|
|
24166
24204
|
const img2 = import_sharp2.default(path2);
|
|
24167
24205
|
const [meta1, meta2] = await Promise.all([img1.metadata(), img2.metadata()]);
|
|
@@ -24180,7 +24218,7 @@ async function diffImages(path1, path2) {
|
|
|
24180
24218
|
const dg = Math.abs(raw1[i + 1] - raw2[i + 1]);
|
|
24181
24219
|
const db = Math.abs(raw1[i + 2] - raw2[i + 2]);
|
|
24182
24220
|
const diff = (dr + dg + db) / 3;
|
|
24183
|
-
if (diff >
|
|
24221
|
+
if (diff > threshold) {
|
|
24184
24222
|
changedPixels++;
|
|
24185
24223
|
diffBuffer[i] = 255;
|
|
24186
24224
|
diffBuffer[i + 1] = 0;
|
|
@@ -24192,9 +24230,9 @@ async function diffImages(path1, path2) {
|
|
|
24192
24230
|
}
|
|
24193
24231
|
}
|
|
24194
24232
|
const dataDir = getDataDir2();
|
|
24195
|
-
const diffDir =
|
|
24233
|
+
const diffDir = join13(dataDir, "diffs");
|
|
24196
24234
|
mkdirSync9(diffDir, { recursive: true });
|
|
24197
|
-
const diffPath =
|
|
24235
|
+
const diffPath = join13(diffDir, `diff-${Date.now()}.webp`);
|
|
24198
24236
|
const diffImageBuffer = await import_sharp2.default(diffBuffer, { raw: { width: w, height: h, channels } }).webp({ quality: 85 }).toBuffer();
|
|
24199
24237
|
await Bun.write(diffPath, diffImageBuffer);
|
|
24200
24238
|
return {
|
|
@@ -24386,7 +24424,7 @@ var init_scripts = __esm(() => {
|
|
|
24386
24424
|
});
|
|
24387
24425
|
|
|
24388
24426
|
// src/lib/ai-inference.ts
|
|
24389
|
-
function
|
|
24427
|
+
function resolve2(opts) {
|
|
24390
24428
|
if (opts?.model && ALIASES[opts.model])
|
|
24391
24429
|
return ALIASES[opts.model];
|
|
24392
24430
|
if (opts?.provider && opts?.model)
|
|
@@ -24396,7 +24434,7 @@ function resolve(opts) {
|
|
|
24396
24434
|
return ALIASES.fast;
|
|
24397
24435
|
}
|
|
24398
24436
|
async function infer(prompt, opts) {
|
|
24399
|
-
const { provider, model } =
|
|
24437
|
+
const { provider, model } = resolve2(opts);
|
|
24400
24438
|
const maxTokens = opts?.maxTokens ?? 1024;
|
|
24401
24439
|
if (provider === "anthropic") {
|
|
24402
24440
|
const apiKey2 = process.env["ANTHROPIC_API_KEY"];
|
|
@@ -25022,6 +25060,7 @@ var exports_recorder = {};
|
|
|
25022
25060
|
__export(exports_recorder, {
|
|
25023
25061
|
stopRecording: () => stopRecording,
|
|
25024
25062
|
startRecording: () => startRecording,
|
|
25063
|
+
resetRecorderState: () => resetRecorderState,
|
|
25025
25064
|
replayRecording: () => replayRecording,
|
|
25026
25065
|
recordStep: () => recordStep,
|
|
25027
25066
|
listRecordings: () => listRecordings,
|
|
@@ -25029,6 +25068,14 @@ __export(exports_recorder, {
|
|
|
25029
25068
|
exportRecording: () => exportRecording,
|
|
25030
25069
|
attachPageListeners: () => attachPageListeners
|
|
25031
25070
|
});
|
|
25071
|
+
function resetRecorderState() {
|
|
25072
|
+
for (const active of activeRecordings.values()) {
|
|
25073
|
+
try {
|
|
25074
|
+
active.cleanup();
|
|
25075
|
+
} catch {}
|
|
25076
|
+
}
|
|
25077
|
+
activeRecordings.clear();
|
|
25078
|
+
}
|
|
25032
25079
|
function startRecording(sessionId, name, startUrl) {
|
|
25033
25080
|
const steps = [];
|
|
25034
25081
|
const recording = createRecording({ name, start_url: startUrl, steps });
|
|
@@ -25203,21 +25250,21 @@ __export(exports_profiles, {
|
|
|
25203
25250
|
applyProfile: () => applyProfile
|
|
25204
25251
|
});
|
|
25205
25252
|
import { mkdirSync as mkdirSync10, existsSync as existsSync11, readdirSync as readdirSync7, rmSync, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
25206
|
-
import { join as
|
|
25253
|
+
import { join as join14 } from "path";
|
|
25207
25254
|
function getProfilesDir() {
|
|
25208
25255
|
const dataDir = getDataDir2();
|
|
25209
|
-
const dir =
|
|
25256
|
+
const dir = join14(dataDir, "profiles");
|
|
25210
25257
|
mkdirSync10(dir, { recursive: true });
|
|
25211
25258
|
return dir;
|
|
25212
25259
|
}
|
|
25213
25260
|
function getProfileDir2(name) {
|
|
25214
|
-
return
|
|
25261
|
+
return join14(getProfilesDir(), name);
|
|
25215
25262
|
}
|
|
25216
25263
|
async function saveProfile(page, name) {
|
|
25217
25264
|
const dir = getProfileDir2(name);
|
|
25218
25265
|
mkdirSync10(dir, { recursive: true });
|
|
25219
25266
|
const cookies = await page.context().cookies();
|
|
25220
|
-
writeFileSync3(
|
|
25267
|
+
writeFileSync3(join14(dir, "cookies.json"), JSON.stringify(cookies, null, 2));
|
|
25221
25268
|
let localStorage2 = {};
|
|
25222
25269
|
try {
|
|
25223
25270
|
localStorage2 = await page.evaluate(() => {
|
|
@@ -25229,11 +25276,11 @@ async function saveProfile(page, name) {
|
|
|
25229
25276
|
return result;
|
|
25230
25277
|
});
|
|
25231
25278
|
} catch {}
|
|
25232
|
-
writeFileSync3(
|
|
25279
|
+
writeFileSync3(join14(dir, "storage.json"), JSON.stringify(localStorage2, null, 2));
|
|
25233
25280
|
const savedAt = new Date().toISOString();
|
|
25234
25281
|
const url = page.url();
|
|
25235
25282
|
const meta = { saved_at: savedAt, url };
|
|
25236
|
-
writeFileSync3(
|
|
25283
|
+
writeFileSync3(join14(dir, "meta.json"), JSON.stringify(meta, null, 2));
|
|
25237
25284
|
return {
|
|
25238
25285
|
name,
|
|
25239
25286
|
saved_at: savedAt,
|
|
@@ -25247,9 +25294,9 @@ function loadProfile(name) {
|
|
|
25247
25294
|
if (!existsSync11(dir)) {
|
|
25248
25295
|
throw new Error(`Profile not found: ${name}`);
|
|
25249
25296
|
}
|
|
25250
|
-
const cookiesPath =
|
|
25251
|
-
const storagePath =
|
|
25252
|
-
const metaPath =
|
|
25297
|
+
const cookiesPath = join14(dir, "cookies.json");
|
|
25298
|
+
const storagePath = join14(dir, "storage.json");
|
|
25299
|
+
const metaPath = join14(dir, "meta.json");
|
|
25253
25300
|
const cookies = existsSync11(cookiesPath) ? JSON.parse(readFileSync3(cookiesPath, "utf8")) : [];
|
|
25254
25301
|
const localStorage2 = existsSync11(storagePath) ? JSON.parse(readFileSync3(storagePath, "utf8")) : {};
|
|
25255
25302
|
let savedAt = new Date().toISOString();
|
|
@@ -25290,24 +25337,24 @@ function listProfiles() {
|
|
|
25290
25337
|
if (!entry.isDirectory())
|
|
25291
25338
|
continue;
|
|
25292
25339
|
const name = entry.name;
|
|
25293
|
-
const profileDir =
|
|
25340
|
+
const profileDir = join14(dir, name);
|
|
25294
25341
|
let savedAt = "";
|
|
25295
25342
|
let url;
|
|
25296
25343
|
let cookieCount = 0;
|
|
25297
25344
|
let storageKeyCount = 0;
|
|
25298
25345
|
try {
|
|
25299
|
-
const metaPath =
|
|
25346
|
+
const metaPath = join14(profileDir, "meta.json");
|
|
25300
25347
|
if (existsSync11(metaPath)) {
|
|
25301
25348
|
const meta = JSON.parse(readFileSync3(metaPath, "utf8"));
|
|
25302
25349
|
savedAt = meta.saved_at ?? "";
|
|
25303
25350
|
url = meta.url;
|
|
25304
25351
|
}
|
|
25305
|
-
const cookiesPath =
|
|
25352
|
+
const cookiesPath = join14(profileDir, "cookies.json");
|
|
25306
25353
|
if (existsSync11(cookiesPath)) {
|
|
25307
25354
|
const cookies = JSON.parse(readFileSync3(cookiesPath, "utf8"));
|
|
25308
25355
|
cookieCount = Array.isArray(cookies) ? cookies.length : 0;
|
|
25309
25356
|
}
|
|
25310
|
-
const storagePath =
|
|
25357
|
+
const storagePath = join14(profileDir, "storage.json");
|
|
25311
25358
|
if (existsSync11(storagePath)) {
|
|
25312
25359
|
const storage = JSON.parse(readFileSync3(storagePath, "utf8"));
|
|
25313
25360
|
storageKeyCount = Object.keys(storage).length;
|
|
@@ -25341,13 +25388,14 @@ var init_profiles = __esm(() => {
|
|
|
25341
25388
|
// src/lib/auth.ts
|
|
25342
25389
|
var exports_auth = {};
|
|
25343
25390
|
__export(exports_auth, {
|
|
25391
|
+
lookupCredentials: () => lookupCredentials,
|
|
25344
25392
|
loginWithCredentials: () => loginWithCredentials,
|
|
25345
25393
|
getCredentials: () => getCredentials
|
|
25346
25394
|
});
|
|
25347
25395
|
import { existsSync as existsSync12, readFileSync as readFileSync5 } from "fs";
|
|
25348
|
-
import { join as
|
|
25396
|
+
import { join as join15 } from "path";
|
|
25349
25397
|
import { homedir as homedir8 } from "os";
|
|
25350
|
-
async function
|
|
25398
|
+
async function lookupCredentials(service) {
|
|
25351
25399
|
try {
|
|
25352
25400
|
const secretsVaultPath = process.env["BROWSER_SECRETS_VAULT_PATH"];
|
|
25353
25401
|
if (secretsVaultPath) {
|
|
@@ -25355,11 +25403,14 @@ async function getCredentials(service) {
|
|
|
25355
25403
|
const email = getSecret(`${service}_email`) ?? getSecret(`${service}_username`) ?? getSecret(`${service}_login`);
|
|
25356
25404
|
const password = getSecret(`${service}_password`) ?? getSecret(`${service}_pass`);
|
|
25357
25405
|
if (email?.value && password?.value) {
|
|
25358
|
-
return {
|
|
25406
|
+
return {
|
|
25407
|
+
credential: { email: email.value, password: password.value },
|
|
25408
|
+
method: "secrets_vault"
|
|
25409
|
+
};
|
|
25359
25410
|
}
|
|
25360
25411
|
}
|
|
25361
25412
|
} catch {}
|
|
25362
|
-
const secretsPath =
|
|
25413
|
+
const secretsPath = join15(homedir8(), ".secrets");
|
|
25363
25414
|
if (existsSync12(secretsPath)) {
|
|
25364
25415
|
let content;
|
|
25365
25416
|
try {
|
|
@@ -25378,27 +25429,33 @@ async function getCredentials(service) {
|
|
|
25378
25429
|
}
|
|
25379
25430
|
const email = vars[`${prefix}_EMAIL`] ?? vars[`${prefix}_USERNAME`];
|
|
25380
25431
|
const password = vars[`${prefix}_PASSWORD`];
|
|
25381
|
-
if (email && password)
|
|
25382
|
-
return { email, password };
|
|
25432
|
+
if (email && password) {
|
|
25433
|
+
return { credential: { email, password }, method: "env_file" };
|
|
25434
|
+
}
|
|
25383
25435
|
}
|
|
25384
25436
|
const envPrefix = service.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
25385
25437
|
const envEmail = process.env[`${envPrefix}_EMAIL`] ?? process.env[`${envPrefix}_USERNAME`];
|
|
25386
25438
|
const envPass = process.env[`${envPrefix}_PASSWORD`];
|
|
25387
|
-
if (envEmail && envPass)
|
|
25388
|
-
return { email: envEmail, password: envPass };
|
|
25389
|
-
|
|
25439
|
+
if (envEmail && envPass) {
|
|
25440
|
+
return { credential: { email: envEmail, password: envPass }, method: "process_env" };
|
|
25441
|
+
}
|
|
25442
|
+
return { credential: null, method: "not_found" };
|
|
25443
|
+
}
|
|
25444
|
+
async function getCredentials(service) {
|
|
25445
|
+
return (await lookupCredentials(service)).credential;
|
|
25390
25446
|
}
|
|
25391
25447
|
async function loginWithCredentials(page, credentials, opts) {
|
|
25392
|
-
const { fillForm: fillForm2 } = await Promise.resolve().then(() => (init_actions(), exports_actions));
|
|
25448
|
+
const { fillForm: fillForm2, waitForText: waitForText2 } = await Promise.resolve().then(() => (init_actions(), exports_actions));
|
|
25393
25449
|
const { saveProfile: saveProfile2 } = await Promise.resolve().then(() => (init_profiles(), exports_profiles));
|
|
25394
25450
|
try {
|
|
25395
25451
|
if (opts?.loginUrl) {
|
|
25396
25452
|
await page.goto(opts.loginUrl, { waitUntil: "domcontentloaded" });
|
|
25397
25453
|
await new Promise((r) => setTimeout(r, 500));
|
|
25398
25454
|
}
|
|
25455
|
+
const urlBefore = page.url();
|
|
25399
25456
|
const emailSel = opts?.emailSelector ?? 'input[type="email"], input[name="email"], input[id*="email"], input[placeholder*="email" i]';
|
|
25400
25457
|
const passSel = opts?.passwordSelector ?? 'input[type="password"]';
|
|
25401
|
-
const submitSel = opts?.submitSelector ?? 'button[type="submit"], input[type="submit"]
|
|
25458
|
+
const submitSel = opts?.submitSelector ?? 'button[type="submit"], input[type="submit"]';
|
|
25402
25459
|
const fields = {};
|
|
25403
25460
|
if (credentials.email)
|
|
25404
25461
|
fields[emailSel] = credentials.email;
|
|
@@ -25407,10 +25464,38 @@ async function loginWithCredentials(page, credentials, opts) {
|
|
|
25407
25464
|
if (credentials.password)
|
|
25408
25465
|
fields[passSel] = credentials.password;
|
|
25409
25466
|
const fillResult = await fillForm2(page, fields, submitSel);
|
|
25410
|
-
|
|
25411
|
-
|
|
25412
|
-
|
|
25413
|
-
|
|
25467
|
+
if (fillResult.errors.some((e) => e.startsWith("submit("))) {
|
|
25468
|
+
try {
|
|
25469
|
+
await page.getByRole("button", { name: /sign in|log in|login|submit/i }).first().click({ timeout: 5000 });
|
|
25470
|
+
} catch {
|
|
25471
|
+
try {
|
|
25472
|
+
await page.locator('input[type="submit"]').first().click({ timeout: 3000 });
|
|
25473
|
+
} catch {}
|
|
25474
|
+
}
|
|
25475
|
+
}
|
|
25476
|
+
const successPattern = opts?.waitForText ?? "dashboard|profile|account|welcome|signed in|logout";
|
|
25477
|
+
const patterns = successPattern.split("|").map((p) => p.trim()).filter(Boolean);
|
|
25478
|
+
let logged_in = false;
|
|
25479
|
+
for (const pattern of patterns) {
|
|
25480
|
+
try {
|
|
25481
|
+
await waitForText2(page, pattern, { timeout: 5000 });
|
|
25482
|
+
logged_in = fillResult.errors.length === 0;
|
|
25483
|
+
break;
|
|
25484
|
+
} catch {}
|
|
25485
|
+
}
|
|
25486
|
+
if (!logged_in) {
|
|
25487
|
+
await page.waitForLoadState("domcontentloaded").catch(() => {});
|
|
25488
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
25489
|
+
const currentUrl2 = page.url();
|
|
25490
|
+
const bodyText = await page.evaluate(() => document.body?.innerText?.toLowerCase() ?? "").catch(() => "");
|
|
25491
|
+
const urlChanged = currentUrl2 !== urlBefore;
|
|
25492
|
+
const textMatch = patterns.some((p) => {
|
|
25493
|
+
const needle = p.toLowerCase();
|
|
25494
|
+
return bodyText.includes(needle) || currentUrl2.toLowerCase().includes(needle);
|
|
25495
|
+
});
|
|
25496
|
+
logged_in = fillResult.errors.length === 0 && (urlChanged || textMatch);
|
|
25497
|
+
}
|
|
25498
|
+
const currentUrl = page.url();
|
|
25414
25499
|
let profile_saved = false;
|
|
25415
25500
|
if (opts?.saveProfile && logged_in) {
|
|
25416
25501
|
try {
|
|
@@ -25422,14 +25507,14 @@ async function loginWithCredentials(page, credentials, opts) {
|
|
|
25422
25507
|
logged_in,
|
|
25423
25508
|
redirect_url: currentUrl,
|
|
25424
25509
|
profile_saved,
|
|
25425
|
-
method: "secrets_vault"
|
|
25510
|
+
method: opts?.method ?? "secrets_vault"
|
|
25426
25511
|
};
|
|
25427
25512
|
} catch (err) {
|
|
25428
25513
|
return {
|
|
25429
25514
|
logged_in: false,
|
|
25430
25515
|
redirect_url: "",
|
|
25431
25516
|
profile_saved: false,
|
|
25432
|
-
method: "not_found",
|
|
25517
|
+
method: opts?.method ?? "not_found",
|
|
25433
25518
|
error: err instanceof Error ? err.message : String(err)
|
|
25434
25519
|
};
|
|
25435
25520
|
}
|
|
@@ -25449,11 +25534,11 @@ __export(exports_downloads, {
|
|
|
25449
25534
|
cleanStaleDownloads: () => cleanStaleDownloads
|
|
25450
25535
|
});
|
|
25451
25536
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
25452
|
-
import { join as
|
|
25537
|
+
import { join as join16, basename, extname } from "path";
|
|
25453
25538
|
import { mkdirSync as mkdirSync11, existsSync as existsSync13, readdirSync as readdirSync8, statSync as statSync2, unlinkSync as unlinkSync3, copyFileSync as copyFileSync3, writeFileSync as writeFileSync5, readFileSync as readFileSync6 } from "fs";
|
|
25454
25539
|
function getDownloadsDir(sessionId) {
|
|
25455
|
-
const base =
|
|
25456
|
-
const dir = sessionId ?
|
|
25540
|
+
const base = join16(getDataDir2(), "downloads");
|
|
25541
|
+
const dir = sessionId ? join16(base, sessionId) : base;
|
|
25457
25542
|
mkdirSync11(dir, { recursive: true });
|
|
25458
25543
|
return dir;
|
|
25459
25544
|
}
|
|
@@ -25469,7 +25554,7 @@ function saveToDownloads(buffer, filename, opts) {
|
|
|
25469
25554
|
const ext = extname(filename) || "";
|
|
25470
25555
|
const stem = basename(filename, ext);
|
|
25471
25556
|
const uniqueName = `${stem}-${id.slice(0, 8)}${ext}`;
|
|
25472
|
-
const filePath =
|
|
25557
|
+
const filePath = join16(dir, uniqueName);
|
|
25473
25558
|
writeFileSync5(filePath, buffer);
|
|
25474
25559
|
const meta = {
|
|
25475
25560
|
id,
|
|
@@ -25504,7 +25589,7 @@ function listDownloads(sessionId) {
|
|
|
25504
25589
|
for (const entry of entries) {
|
|
25505
25590
|
if (entry.endsWith(".meta.json"))
|
|
25506
25591
|
continue;
|
|
25507
|
-
const full =
|
|
25592
|
+
const full = join16(d, entry);
|
|
25508
25593
|
const stat = statSync2(full);
|
|
25509
25594
|
if (stat.isDirectory()) {
|
|
25510
25595
|
scanDir(full);
|
|
@@ -25600,7 +25685,7 @@ __export(exports_daemon_client, {
|
|
|
25600
25685
|
getDaemonPid: () => getDaemonPid
|
|
25601
25686
|
});
|
|
25602
25687
|
import { existsSync as existsSync14, readFileSync as readFileSync7 } from "fs";
|
|
25603
|
-
import { join as
|
|
25688
|
+
import { join as join17 } from "path";
|
|
25604
25689
|
function getDaemonPidFile() {
|
|
25605
25690
|
return PID_FILE;
|
|
25606
25691
|
}
|
|
@@ -25643,7 +25728,7 @@ async function getDaemonStatus() {
|
|
|
25643
25728
|
var PID_FILE, DEFAULT_PORT = 7030;
|
|
25644
25729
|
var init_daemon_client = __esm(() => {
|
|
25645
25730
|
init_schema();
|
|
25646
|
-
PID_FILE =
|
|
25731
|
+
PID_FILE = join17(getDataDir2(), "daemon.pid");
|
|
25647
25732
|
});
|
|
25648
25733
|
|
|
25649
25734
|
// node_modules/zod/v3/helpers/util.js
|
|
@@ -29705,7 +29790,7 @@ async function setSessionStorage(page, key, value) {
|
|
|
29705
29790
|
}
|
|
29706
29791
|
|
|
29707
29792
|
// src/lib/files-integration.ts
|
|
29708
|
-
import { join as
|
|
29793
|
+
import { join as join18 } from "path";
|
|
29709
29794
|
import { mkdirSync as mkdirSync12, copyFileSync as copyFileSync4 } from "fs";
|
|
29710
29795
|
async function persistFile(localPath, opts) {
|
|
29711
29796
|
try {
|
|
@@ -29717,10 +29802,10 @@ async function persistFile(localPath, opts) {
|
|
|
29717
29802
|
} catch {}
|
|
29718
29803
|
const dataDir = getDataDir2();
|
|
29719
29804
|
const date = new Date().toISOString().split("T")[0];
|
|
29720
|
-
const dir =
|
|
29805
|
+
const dir = join18(dataDir, "persistent", date);
|
|
29721
29806
|
mkdirSync12(dir, { recursive: true });
|
|
29722
29807
|
const filename = localPath.split("/").pop() ?? "file";
|
|
29723
|
-
const targetPath =
|
|
29808
|
+
const targetPath = join18(dir, filename);
|
|
29724
29809
|
copyFileSync4(localPath, targetPath);
|
|
29725
29810
|
return {
|
|
29726
29811
|
id: `local-${Date.now()}`,
|
|
@@ -30494,7 +30579,7 @@ function register5(server) {
|
|
|
30494
30579
|
page.on("response", onResponse);
|
|
30495
30580
|
page.on("requestfailed", onFailed);
|
|
30496
30581
|
try {
|
|
30497
|
-
await new Promise((
|
|
30582
|
+
await new Promise((resolve3, reject) => {
|
|
30498
30583
|
const check = () => {
|
|
30499
30584
|
const now = Date.now();
|
|
30500
30585
|
if (now - t0 > timeout) {
|
|
@@ -30502,7 +30587,7 @@ function register5(server) {
|
|
|
30502
30587
|
return;
|
|
30503
30588
|
}
|
|
30504
30589
|
if (pending === 0 && now - lastActivity >= idle_time) {
|
|
30505
|
-
|
|
30590
|
+
resolve3();
|
|
30506
30591
|
return;
|
|
30507
30592
|
}
|
|
30508
30593
|
setTimeout(check, 100);
|
|
@@ -31178,7 +31263,7 @@ function register6(server) {
|
|
|
31178
31263
|
await new Promise((r) => setTimeout(r, wait_ms));
|
|
31179
31264
|
const ss2 = await takeScreenshot(page, { maxWidth: 1280, compress: true, track: false });
|
|
31180
31265
|
const { diffImages: diffImages2 } = await Promise.resolve().then(() => (init_gallery_diff(), exports_gallery_diff));
|
|
31181
|
-
const diff = await diffImages2(ss1.path, ss2.path);
|
|
31266
|
+
const diff = await diffImages2(ss1.path, ss2.path, threshold);
|
|
31182
31267
|
logEvent(sid, "diff", { url1, url2, changed_percent: diff.changed_percent });
|
|
31183
31268
|
return json({
|
|
31184
31269
|
url1,
|
|
@@ -31247,7 +31332,7 @@ __export(exports_dist2, {
|
|
|
31247
31332
|
AGENT_TARGETS: () => AGENT_TARGETS
|
|
31248
31333
|
});
|
|
31249
31334
|
import { existsSync as existsSync15, readFileSync as readFileSync8, readdirSync as readdirSync9 } from "fs";
|
|
31250
|
-
import { join as
|
|
31335
|
+
import { join as join19 } from "path";
|
|
31251
31336
|
import { homedir as homedir9 } from "os";
|
|
31252
31337
|
import { existsSync as existsSync22, cpSync, mkdirSync as mkdirSync13, writeFileSync as writeFileSync6, rmSync as rmSync2, readdirSync as readdirSync22, statSync as statSync3, readFileSync as readFileSync22, accessSync, constants } from "fs";
|
|
31253
31338
|
import { join as join22, dirname as dirname2 } from "path";
|
|
@@ -31297,7 +31382,7 @@ function discoverSkillsInDir(dir) {
|
|
|
31297
31382
|
for (const entry of entries) {
|
|
31298
31383
|
if (!entry.isDirectory())
|
|
31299
31384
|
continue;
|
|
31300
|
-
const skillMdPath =
|
|
31385
|
+
const skillMdPath = join19(dir, entry.name, "SKILL.md");
|
|
31301
31386
|
if (!existsSync15(skillMdPath))
|
|
31302
31387
|
continue;
|
|
31303
31388
|
let content;
|
|
@@ -31328,11 +31413,11 @@ function loadRegistry(cwd) {
|
|
|
31328
31413
|
return _registryCache;
|
|
31329
31414
|
}
|
|
31330
31415
|
const official = SKILLS.map((s) => ({ ...s, source: "official" }));
|
|
31331
|
-
const globalCustomNew = discoverSkillsInDir(
|
|
31332
|
-
const globalCustomOld = discoverSkillsInDir(
|
|
31416
|
+
const globalCustomNew = discoverSkillsInDir(join19(homedir9(), ".hasna", "skills", "custom"));
|
|
31417
|
+
const globalCustomOld = discoverSkillsInDir(join19(homedir9(), ".skills"));
|
|
31333
31418
|
const oldNames = new Set(globalCustomNew.map((s) => s.name));
|
|
31334
31419
|
const globalCustom = [...globalCustomNew, ...globalCustomOld.filter((s) => !oldNames.has(s.name))];
|
|
31335
|
-
const projectCustom = discoverSkillsInDir(
|
|
31420
|
+
const projectCustom = discoverSkillsInDir(join19(cwd || process.cwd(), ".skills", "custom-skills"));
|
|
31336
31421
|
const customNames = new Set([...globalCustom, ...projectCustom].map((s) => s.name));
|
|
31337
31422
|
const filtered = official.filter((s) => !customNames.has(s.name));
|
|
31338
31423
|
_registryCache = [...filtered, ...globalCustom, ...projectCustom];
|
|
@@ -33793,11 +33878,11 @@ var init_skills_runner = __esm(() => {
|
|
|
33793
33878
|
},
|
|
33794
33879
|
login: async (page, params) => {
|
|
33795
33880
|
const { service, login_url } = params;
|
|
33796
|
-
const {
|
|
33797
|
-
const creds = await
|
|
33881
|
+
const { lookupCredentials: lookupCredentials2, loginWithCredentials: loginWithCredentials2 } = await Promise.resolve().then(() => (init_auth(), exports_auth));
|
|
33882
|
+
const { credential: creds, method } = await lookupCredentials2(service);
|
|
33798
33883
|
if (!creds)
|
|
33799
33884
|
return { logged_in: false, error: `No credentials found for ${service}` };
|
|
33800
|
-
const result = await loginWithCredentials2(page, creds, { loginUrl: login_url, saveProfile: service });
|
|
33885
|
+
const result = await loginWithCredentials2(page, creds, { loginUrl: login_url, saveProfile: service, method });
|
|
33801
33886
|
return result;
|
|
33802
33887
|
},
|
|
33803
33888
|
"extract-text": async (page, params) => {
|
|
@@ -34871,7 +34956,7 @@ __export(exports_datasets, {
|
|
|
34871
34956
|
});
|
|
34872
34957
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
34873
34958
|
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync14 } from "fs";
|
|
34874
|
-
import { join as
|
|
34959
|
+
import { join as join20 } from "path";
|
|
34875
34960
|
function saveDataset(data) {
|
|
34876
34961
|
const db = getDatabase();
|
|
34877
34962
|
const id = randomUUID15();
|
|
@@ -34909,10 +34994,10 @@ function exportDataset(name, format) {
|
|
|
34909
34994
|
const dataset = getDatasetByName(name);
|
|
34910
34995
|
if (!dataset)
|
|
34911
34996
|
throw new Error(`Dataset '${name}' not found`);
|
|
34912
|
-
const dir =
|
|
34997
|
+
const dir = join20(getDataDir2(), "exports");
|
|
34913
34998
|
mkdirSync14(dir, { recursive: true });
|
|
34914
34999
|
const filename = `${name}.${format}`;
|
|
34915
|
-
const path =
|
|
35000
|
+
const path = join20(dir, filename);
|
|
34916
35001
|
if (format === "csv") {
|
|
34917
35002
|
const rows = dataset.data;
|
|
34918
35003
|
if (rows.length === 0) {
|
|
@@ -35413,7 +35498,7 @@ import {
|
|
|
35413
35498
|
copyFileSync as copyFileSync6
|
|
35414
35499
|
} from "fs";
|
|
35415
35500
|
import { homedir as homedir10 } from "os";
|
|
35416
|
-
import { join as
|
|
35501
|
+
import { join as join21, relative as relative3 } from "path";
|
|
35417
35502
|
import { existsSync as existsSync23, mkdirSync as mkdirSync23, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
35418
35503
|
import { homedir as homedir23 } from "os";
|
|
35419
35504
|
import { join as join23 } from "path";
|
|
@@ -35425,7 +35510,7 @@ import { join as join43 } from "path";
|
|
|
35425
35510
|
import { join as join62, dirname as dirname3 } from "path";
|
|
35426
35511
|
import { homedir as homedir52, platform as platform2 } from "os";
|
|
35427
35512
|
import { existsSync as existsSync43, mkdirSync as mkdirSync33, cpSync as cpSync2 } from "fs";
|
|
35428
|
-
import { dirname as dirname23, join as join53, resolve as
|
|
35513
|
+
import { dirname as dirname23, join as join53, resolve as resolve3 } from "path";
|
|
35429
35514
|
import { existsSync as existsSync62, mkdirSync as mkdirSync5, readFileSync as readFileSync23, readdirSync as readdirSync33, writeFileSync as writeFileSync23, unlinkSync as unlinkSync4, cpSync as cpSync22 } from "fs";
|
|
35430
35515
|
import { homedir as homedir62 } from "os";
|
|
35431
35516
|
import { basename as basename2, dirname as dirname32, join as join72, resolve as resolve22 } from "path";
|
|
@@ -36251,13 +36336,13 @@ function custom3(check, _params = {}, fatal) {
|
|
|
36251
36336
|
return ZodAny3.create();
|
|
36252
36337
|
}
|
|
36253
36338
|
function getDataDir4(serviceName) {
|
|
36254
|
-
const dir =
|
|
36339
|
+
const dir = join21(HASNA_DIR2, serviceName);
|
|
36255
36340
|
mkdirSync15(dir, { recursive: true });
|
|
36256
36341
|
return dir;
|
|
36257
36342
|
}
|
|
36258
36343
|
function getDbPath2(serviceName) {
|
|
36259
36344
|
const dir = getDataDir4(serviceName);
|
|
36260
|
-
return
|
|
36345
|
+
return join21(dir, `${serviceName}.db`);
|
|
36261
36346
|
}
|
|
36262
36347
|
function getConfigDir2() {
|
|
36263
36348
|
return CONFIG_DIR3;
|
|
@@ -36476,7 +36561,7 @@ function isInMemoryDb(path) {
|
|
|
36476
36561
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
36477
36562
|
}
|
|
36478
36563
|
function findNearestMementosDb(startDir) {
|
|
36479
|
-
let dir =
|
|
36564
|
+
let dir = resolve3(startDir);
|
|
36480
36565
|
while (true) {
|
|
36481
36566
|
const candidate = join53(dir, ".mementos", "mementos.db");
|
|
36482
36567
|
if (existsSync43(candidate))
|
|
@@ -36489,7 +36574,7 @@ function findNearestMementosDb(startDir) {
|
|
|
36489
36574
|
return null;
|
|
36490
36575
|
}
|
|
36491
36576
|
function findGitRoot(startDir) {
|
|
36492
|
-
let dir =
|
|
36577
|
+
let dir = resolve3(startDir);
|
|
36493
36578
|
while (true) {
|
|
36494
36579
|
if (existsSync43(join53(dir, ".git")))
|
|
36495
36580
|
return dir;
|
|
@@ -36531,7 +36616,7 @@ function getDbPath22() {
|
|
|
36531
36616
|
function ensureDir2(filePath) {
|
|
36532
36617
|
if (isInMemoryDb(filePath))
|
|
36533
36618
|
return;
|
|
36534
|
-
const dir = dirname23(
|
|
36619
|
+
const dir = dirname23(resolve3(filePath));
|
|
36535
36620
|
if (!existsSync43(dir)) {
|
|
36536
36621
|
mkdirSync33(dir, { recursive: true });
|
|
36537
36622
|
}
|
|
@@ -42769,7 +42854,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
42769
42854
|
function parse(stream, callback) {
|
|
42770
42855
|
const parser = new parser_1.Parser;
|
|
42771
42856
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
42772
|
-
return new Promise((
|
|
42857
|
+
return new Promise((resolve4) => stream.on("end", () => resolve4()));
|
|
42773
42858
|
}
|
|
42774
42859
|
exports.parse = parse;
|
|
42775
42860
|
});
|
|
@@ -43434,12 +43519,12 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
43434
43519
|
this._connect(callback);
|
|
43435
43520
|
return;
|
|
43436
43521
|
}
|
|
43437
|
-
return new this._Promise((
|
|
43522
|
+
return new this._Promise((resolve4, reject) => {
|
|
43438
43523
|
this._connect((error) => {
|
|
43439
43524
|
if (error) {
|
|
43440
43525
|
reject(error);
|
|
43441
43526
|
} else {
|
|
43442
|
-
|
|
43527
|
+
resolve4(this);
|
|
43443
43528
|
}
|
|
43444
43529
|
});
|
|
43445
43530
|
});
|
|
@@ -43771,8 +43856,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
43771
43856
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
43772
43857
|
query = new Query3(config, values, callback);
|
|
43773
43858
|
if (!query.callback) {
|
|
43774
|
-
result = new this._Promise((
|
|
43775
|
-
query.callback = (err2, res) => err2 ? reject(err2) :
|
|
43859
|
+
result = new this._Promise((resolve4, reject) => {
|
|
43860
|
+
query.callback = (err2, res) => err2 ? reject(err2) : resolve4(res);
|
|
43776
43861
|
}).catch((err2) => {
|
|
43777
43862
|
Error.captureStackTrace(err2);
|
|
43778
43863
|
throw err2;
|
|
@@ -43847,8 +43932,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
43847
43932
|
if (cb) {
|
|
43848
43933
|
this.connection.once("end", cb);
|
|
43849
43934
|
} else {
|
|
43850
|
-
return new this._Promise((
|
|
43851
|
-
this.connection.once("end",
|
|
43935
|
+
return new this._Promise((resolve4) => {
|
|
43936
|
+
this.connection.once("end", resolve4);
|
|
43852
43937
|
});
|
|
43853
43938
|
}
|
|
43854
43939
|
}
|
|
@@ -43893,8 +43978,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
43893
43978
|
const cb = function(err2, client) {
|
|
43894
43979
|
err2 ? rej(err2) : res(client);
|
|
43895
43980
|
};
|
|
43896
|
-
const result = new Promise2(function(
|
|
43897
|
-
res =
|
|
43981
|
+
const result = new Promise2(function(resolve4, reject) {
|
|
43982
|
+
res = resolve4;
|
|
43898
43983
|
rej = reject;
|
|
43899
43984
|
}).catch((err2) => {
|
|
43900
43985
|
Error.captureStackTrace(err2);
|
|
@@ -43955,7 +44040,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
43955
44040
|
if (typeof Promise2.try === "function") {
|
|
43956
44041
|
return Promise2.try(f);
|
|
43957
44042
|
}
|
|
43958
|
-
return new Promise2((
|
|
44043
|
+
return new Promise2((resolve4) => resolve4(f()));
|
|
43959
44044
|
}
|
|
43960
44045
|
_isFull() {
|
|
43961
44046
|
return this._clients.length >= this.options.max;
|
|
@@ -44329,8 +44414,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
44329
44414
|
NativeQuery.prototype._getPromise = function() {
|
|
44330
44415
|
if (this._promise)
|
|
44331
44416
|
return this._promise;
|
|
44332
|
-
this._promise = new Promise(function(
|
|
44333
|
-
this._once("end",
|
|
44417
|
+
this._promise = new Promise(function(resolve4, reject) {
|
|
44418
|
+
this._once("end", resolve4);
|
|
44334
44419
|
this._once("error", reject);
|
|
44335
44420
|
}.bind(this));
|
|
44336
44421
|
return this._promise;
|
|
@@ -44504,12 +44589,12 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
44504
44589
|
this._connect(callback);
|
|
44505
44590
|
return;
|
|
44506
44591
|
}
|
|
44507
|
-
return new this._Promise((
|
|
44592
|
+
return new this._Promise((resolve4, reject) => {
|
|
44508
44593
|
this._connect((error) => {
|
|
44509
44594
|
if (error) {
|
|
44510
44595
|
reject(error);
|
|
44511
44596
|
} else {
|
|
44512
|
-
|
|
44597
|
+
resolve4(this);
|
|
44513
44598
|
}
|
|
44514
44599
|
});
|
|
44515
44600
|
});
|
|
@@ -44533,8 +44618,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
44533
44618
|
query = new NativeQuery(config, values, callback);
|
|
44534
44619
|
if (!query.callback) {
|
|
44535
44620
|
let resolveOut, rejectOut;
|
|
44536
|
-
result = new this._Promise((
|
|
44537
|
-
resolveOut =
|
|
44621
|
+
result = new this._Promise((resolve4, reject) => {
|
|
44622
|
+
resolveOut = resolve4;
|
|
44538
44623
|
rejectOut = reject;
|
|
44539
44624
|
}).catch((err2) => {
|
|
44540
44625
|
Error.captureStackTrace(err2);
|
|
@@ -44592,8 +44677,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
44592
44677
|
}
|
|
44593
44678
|
let result;
|
|
44594
44679
|
if (!cb) {
|
|
44595
|
-
result = new this._Promise(function(
|
|
44596
|
-
cb = (err2) => err2 ? reject(err2) :
|
|
44680
|
+
result = new this._Promise(function(resolve4, reject) {
|
|
44681
|
+
cb = (err2) => err2 ? reject(err2) : resolve4();
|
|
44597
44682
|
});
|
|
44598
44683
|
}
|
|
44599
44684
|
this.native.end(function() {
|
|
@@ -47881,7 +47966,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
47881
47966
|
init_external3();
|
|
47882
47967
|
});
|
|
47883
47968
|
init_dotfile2 = __esm22(() => {
|
|
47884
|
-
HASNA_DIR2 =
|
|
47969
|
+
HASNA_DIR2 = join21(homedir10(), ".hasna");
|
|
47885
47970
|
});
|
|
47886
47971
|
exports_config2 = {};
|
|
47887
47972
|
__export22(exports_config2, {
|
|
@@ -49457,10 +49542,10 @@ import {
|
|
|
49457
49542
|
copyFileSync as copyFileSync7
|
|
49458
49543
|
} from "fs";
|
|
49459
49544
|
import { homedir as homedir11 } from "os";
|
|
49460
|
-
import { join as
|
|
49545
|
+
import { join as join24, relative as relative4 } from "path";
|
|
49461
49546
|
import { existsSync as existsSync24, mkdirSync as mkdirSync24, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
49462
49547
|
import { homedir as homedir24 } from "os";
|
|
49463
|
-
import { join as
|
|
49548
|
+
import { join as join25 } from "path";
|
|
49464
49549
|
import { readdirSync as readdirSync24, existsSync as existsSync34 } from "fs";
|
|
49465
49550
|
import { join as join34 } from "path";
|
|
49466
49551
|
import { homedir as homedir34 } from "os";
|
|
@@ -50300,13 +50385,13 @@ function custom4(check, _params = {}, fatal) {
|
|
|
50300
50385
|
return ZodAny4.create();
|
|
50301
50386
|
}
|
|
50302
50387
|
function getDataDir5(serviceName) {
|
|
50303
|
-
const dir =
|
|
50388
|
+
const dir = join24(HASNA_DIR3, serviceName);
|
|
50304
50389
|
mkdirSync16(dir, { recursive: true });
|
|
50305
50390
|
return dir;
|
|
50306
50391
|
}
|
|
50307
50392
|
function getDbPath3(serviceName) {
|
|
50308
50393
|
const dir = getDataDir5(serviceName);
|
|
50309
|
-
return
|
|
50394
|
+
return join24(dir, `${serviceName}.db`);
|
|
50310
50395
|
}
|
|
50311
50396
|
function getConfigDir3() {
|
|
50312
50397
|
return CONFIG_DIR5;
|
|
@@ -55765,7 +55850,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
55765
55850
|
function parse(stream, callback) {
|
|
55766
55851
|
const parser = new parser_1.Parser;
|
|
55767
55852
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
55768
|
-
return new Promise((
|
|
55853
|
+
return new Promise((resolve4) => stream.on("end", () => resolve4()));
|
|
55769
55854
|
}
|
|
55770
55855
|
exports.parse = parse;
|
|
55771
55856
|
});
|
|
@@ -56430,12 +56515,12 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
56430
56515
|
this._connect(callback);
|
|
56431
56516
|
return;
|
|
56432
56517
|
}
|
|
56433
|
-
return new this._Promise((
|
|
56518
|
+
return new this._Promise((resolve4, reject) => {
|
|
56434
56519
|
this._connect((error) => {
|
|
56435
56520
|
if (error) {
|
|
56436
56521
|
reject(error);
|
|
56437
56522
|
} else {
|
|
56438
|
-
|
|
56523
|
+
resolve4(this);
|
|
56439
56524
|
}
|
|
56440
56525
|
});
|
|
56441
56526
|
});
|
|
@@ -56767,8 +56852,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
56767
56852
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
56768
56853
|
query = new Query4(config, values, callback);
|
|
56769
56854
|
if (!query.callback) {
|
|
56770
|
-
result = new this._Promise((
|
|
56771
|
-
query.callback = (err2, res) => err2 ? reject(err2) :
|
|
56855
|
+
result = new this._Promise((resolve4, reject) => {
|
|
56856
|
+
query.callback = (err2, res) => err2 ? reject(err2) : resolve4(res);
|
|
56772
56857
|
}).catch((err2) => {
|
|
56773
56858
|
Error.captureStackTrace(err2);
|
|
56774
56859
|
throw err2;
|
|
@@ -56843,8 +56928,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
56843
56928
|
if (cb) {
|
|
56844
56929
|
this.connection.once("end", cb);
|
|
56845
56930
|
} else {
|
|
56846
|
-
return new this._Promise((
|
|
56847
|
-
this.connection.once("end",
|
|
56931
|
+
return new this._Promise((resolve4) => {
|
|
56932
|
+
this.connection.once("end", resolve4);
|
|
56848
56933
|
});
|
|
56849
56934
|
}
|
|
56850
56935
|
}
|
|
@@ -56889,8 +56974,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
56889
56974
|
const cb = function(err2, client) {
|
|
56890
56975
|
err2 ? rej(err2) : res(client);
|
|
56891
56976
|
};
|
|
56892
|
-
const result = new Promise2(function(
|
|
56893
|
-
res =
|
|
56977
|
+
const result = new Promise2(function(resolve4, reject) {
|
|
56978
|
+
res = resolve4;
|
|
56894
56979
|
rej = reject;
|
|
56895
56980
|
}).catch((err2) => {
|
|
56896
56981
|
Error.captureStackTrace(err2);
|
|
@@ -56951,7 +57036,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
56951
57036
|
if (typeof Promise2.try === "function") {
|
|
56952
57037
|
return Promise2.try(f);
|
|
56953
57038
|
}
|
|
56954
|
-
return new Promise2((
|
|
57039
|
+
return new Promise2((resolve4) => resolve4(f()));
|
|
56955
57040
|
}
|
|
56956
57041
|
_isFull() {
|
|
56957
57042
|
return this._clients.length >= this.options.max;
|
|
@@ -57325,8 +57410,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
57325
57410
|
NativeQuery.prototype._getPromise = function() {
|
|
57326
57411
|
if (this._promise)
|
|
57327
57412
|
return this._promise;
|
|
57328
|
-
this._promise = new Promise(function(
|
|
57329
|
-
this._once("end",
|
|
57413
|
+
this._promise = new Promise(function(resolve4, reject) {
|
|
57414
|
+
this._once("end", resolve4);
|
|
57330
57415
|
this._once("error", reject);
|
|
57331
57416
|
}.bind(this));
|
|
57332
57417
|
return this._promise;
|
|
@@ -57500,12 +57585,12 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
57500
57585
|
this._connect(callback);
|
|
57501
57586
|
return;
|
|
57502
57587
|
}
|
|
57503
|
-
return new this._Promise((
|
|
57588
|
+
return new this._Promise((resolve4, reject) => {
|
|
57504
57589
|
this._connect((error) => {
|
|
57505
57590
|
if (error) {
|
|
57506
57591
|
reject(error);
|
|
57507
57592
|
} else {
|
|
57508
|
-
|
|
57593
|
+
resolve4(this);
|
|
57509
57594
|
}
|
|
57510
57595
|
});
|
|
57511
57596
|
});
|
|
@@ -57529,8 +57614,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
57529
57614
|
query = new NativeQuery(config, values, callback);
|
|
57530
57615
|
if (!query.callback) {
|
|
57531
57616
|
let resolveOut, rejectOut;
|
|
57532
|
-
result = new this._Promise((
|
|
57533
|
-
resolveOut =
|
|
57617
|
+
result = new this._Promise((resolve4, reject) => {
|
|
57618
|
+
resolveOut = resolve4;
|
|
57534
57619
|
rejectOut = reject;
|
|
57535
57620
|
}).catch((err2) => {
|
|
57536
57621
|
Error.captureStackTrace(err2);
|
|
@@ -57588,8 +57673,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
57588
57673
|
}
|
|
57589
57674
|
let result;
|
|
57590
57675
|
if (!cb) {
|
|
57591
|
-
result = new this._Promise(function(
|
|
57592
|
-
cb = (err2) => err2 ? reject(err2) :
|
|
57676
|
+
result = new this._Promise(function(resolve4, reject) {
|
|
57677
|
+
cb = (err2) => err2 ? reject(err2) : resolve4();
|
|
57593
57678
|
});
|
|
57594
57679
|
}
|
|
57595
57680
|
this.native.end(function() {
|
|
@@ -60877,7 +60962,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
60877
60962
|
init_external4();
|
|
60878
60963
|
});
|
|
60879
60964
|
init_dotfile3 = __esm23(() => {
|
|
60880
|
-
HASNA_DIR3 =
|
|
60965
|
+
HASNA_DIR3 = join24(homedir11(), ".hasna");
|
|
60881
60966
|
});
|
|
60882
60967
|
exports_config3 = {};
|
|
60883
60968
|
__export23(exports_config3, {
|
|
@@ -60908,8 +60993,8 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
60908
60993
|
schedule_minutes: exports_external4.number().default(0)
|
|
60909
60994
|
}).default({})
|
|
60910
60995
|
});
|
|
60911
|
-
CONFIG_DIR5 =
|
|
60912
|
-
CONFIG_PATH3 =
|
|
60996
|
+
CONFIG_DIR5 = join25(homedir24(), ".hasna", "cloud");
|
|
60997
|
+
CONFIG_PATH3 = join25(CONFIG_DIR5, "config.json");
|
|
60913
60998
|
});
|
|
60914
60999
|
exports_discover3 = {};
|
|
60915
61000
|
__export23(exports_discover3, {
|
|
@@ -62639,14 +62724,14 @@ Check the top-level render call using <` + parentName + ">.";
|
|
|
62639
62724
|
var thenableResult = result;
|
|
62640
62725
|
var wasAwaited = false;
|
|
62641
62726
|
var thenable = {
|
|
62642
|
-
then: function(
|
|
62727
|
+
then: function(resolve4, reject) {
|
|
62643
62728
|
wasAwaited = true;
|
|
62644
62729
|
thenableResult.then(function(returnValue2) {
|
|
62645
62730
|
popActScope(prevActScopeDepth);
|
|
62646
62731
|
if (actScopeDepth === 0) {
|
|
62647
|
-
recursivelyFlushAsyncActWork(returnValue2,
|
|
62732
|
+
recursivelyFlushAsyncActWork(returnValue2, resolve4, reject);
|
|
62648
62733
|
} else {
|
|
62649
|
-
|
|
62734
|
+
resolve4(returnValue2);
|
|
62650
62735
|
}
|
|
62651
62736
|
}, function(error2) {
|
|
62652
62737
|
popActScope(prevActScopeDepth);
|
|
@@ -62675,20 +62760,20 @@ Check the top-level render call using <` + parentName + ">.";
|
|
|
62675
62760
|
ReactCurrentActQueue.current = null;
|
|
62676
62761
|
}
|
|
62677
62762
|
var _thenable = {
|
|
62678
|
-
then: function(
|
|
62763
|
+
then: function(resolve4, reject) {
|
|
62679
62764
|
if (ReactCurrentActQueue.current === null) {
|
|
62680
62765
|
ReactCurrentActQueue.current = [];
|
|
62681
|
-
recursivelyFlushAsyncActWork(returnValue,
|
|
62766
|
+
recursivelyFlushAsyncActWork(returnValue, resolve4, reject);
|
|
62682
62767
|
} else {
|
|
62683
|
-
|
|
62768
|
+
resolve4(returnValue);
|
|
62684
62769
|
}
|
|
62685
62770
|
}
|
|
62686
62771
|
};
|
|
62687
62772
|
return _thenable;
|
|
62688
62773
|
} else {
|
|
62689
62774
|
var _thenable2 = {
|
|
62690
|
-
then: function(
|
|
62691
|
-
|
|
62775
|
+
then: function(resolve4, reject) {
|
|
62776
|
+
resolve4(returnValue);
|
|
62692
62777
|
}
|
|
62693
62778
|
};
|
|
62694
62779
|
return _thenable2;
|
|
@@ -62704,7 +62789,7 @@ Check the top-level render call using <` + parentName + ">.";
|
|
|
62704
62789
|
actScopeDepth = prevActScopeDepth;
|
|
62705
62790
|
}
|
|
62706
62791
|
}
|
|
62707
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
62792
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve4, reject) {
|
|
62708
62793
|
{
|
|
62709
62794
|
var queue = ReactCurrentActQueue.current;
|
|
62710
62795
|
if (queue !== null) {
|
|
@@ -62713,16 +62798,16 @@ Check the top-level render call using <` + parentName + ">.";
|
|
|
62713
62798
|
enqueueTask(function() {
|
|
62714
62799
|
if (queue.length === 0) {
|
|
62715
62800
|
ReactCurrentActQueue.current = null;
|
|
62716
|
-
|
|
62801
|
+
resolve4(returnValue);
|
|
62717
62802
|
} else {
|
|
62718
|
-
recursivelyFlushAsyncActWork(returnValue,
|
|
62803
|
+
recursivelyFlushAsyncActWork(returnValue, resolve4, reject);
|
|
62719
62804
|
}
|
|
62720
62805
|
});
|
|
62721
62806
|
} catch (error2) {
|
|
62722
62807
|
reject(error2);
|
|
62723
62808
|
}
|
|
62724
62809
|
} else {
|
|
62725
|
-
|
|
62810
|
+
resolve4(returnValue);
|
|
62726
62811
|
}
|
|
62727
62812
|
}
|
|
62728
62813
|
}
|
|
@@ -63642,11 +63727,11 @@ __export(exports_dist5, {
|
|
|
63642
63727
|
import { hostname as osHostname, platform as osPlatform } from "os";
|
|
63643
63728
|
import { Database as Database4 } from "bun:sqlite";
|
|
63644
63729
|
import { existsSync as existsSync18, mkdirSync as mkdirSync17 } from "fs";
|
|
63645
|
-
import { dirname as dirname5, join as
|
|
63730
|
+
import { dirname as dirname5, join as join26, resolve as resolve4 } from "path";
|
|
63646
63731
|
import { existsSync as existsSync35 } from "fs";
|
|
63647
63732
|
import { join as join35 } from "path";
|
|
63648
63733
|
import { existsSync as existsSync25, mkdirSync as mkdirSync25, readFileSync as readFileSync11, readdirSync as readdirSync12, statSync as statSync5, writeFileSync as writeFileSync10 } from "fs";
|
|
63649
|
-
import { join as
|
|
63734
|
+
import { join as join27 } from "path";
|
|
63650
63735
|
import { existsSync as existsSync45, mkdirSync as mkdirSync35, readFileSync as readFileSync25, writeFileSync as writeFileSync25 } from "fs";
|
|
63651
63736
|
import { homedir as homedir12 } from "os";
|
|
63652
63737
|
import { join as join45 } from "path";
|
|
@@ -63663,7 +63748,7 @@ import {
|
|
|
63663
63748
|
copyFileSync as copyFileSync8
|
|
63664
63749
|
} from "fs";
|
|
63665
63750
|
import { homedir as homedir25 } from "os";
|
|
63666
|
-
import { join as join74, relative as
|
|
63751
|
+
import { join as join74, relative as relative5 } from "path";
|
|
63667
63752
|
import { existsSync as existsSync222, mkdirSync as mkdirSync222, readFileSync as readFileSync44, writeFileSync as writeFileSync42 } from "fs";
|
|
63668
63753
|
import { homedir as homedir222 } from "os";
|
|
63669
63754
|
import { join as join222 } from "path";
|
|
@@ -64121,9 +64206,9 @@ function isInMemoryDb2(path) {
|
|
|
64121
64206
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
64122
64207
|
}
|
|
64123
64208
|
function findNearestTodosDb(startDir) {
|
|
64124
|
-
let dir =
|
|
64209
|
+
let dir = resolve4(startDir);
|
|
64125
64210
|
while (true) {
|
|
64126
|
-
const candidate =
|
|
64211
|
+
const candidate = join26(dir, ".todos", "todos.db");
|
|
64127
64212
|
if (existsSync18(candidate))
|
|
64128
64213
|
return candidate;
|
|
64129
64214
|
const parent = dirname5(dir);
|
|
@@ -64134,9 +64219,9 @@ function findNearestTodosDb(startDir) {
|
|
|
64134
64219
|
return null;
|
|
64135
64220
|
}
|
|
64136
64221
|
function findGitRoot2(startDir) {
|
|
64137
|
-
let dir =
|
|
64222
|
+
let dir = resolve4(startDir);
|
|
64138
64223
|
while (true) {
|
|
64139
|
-
if (existsSync18(
|
|
64224
|
+
if (existsSync18(join26(dir, ".git")))
|
|
64140
64225
|
return dir;
|
|
64141
64226
|
const parent = dirname5(dir);
|
|
64142
64227
|
if (parent === dir)
|
|
@@ -64159,12 +64244,12 @@ function getDbPath4() {
|
|
|
64159
64244
|
if (process.env["TODOS_DB_SCOPE"] === "project") {
|
|
64160
64245
|
const gitRoot = findGitRoot2(cwd);
|
|
64161
64246
|
if (gitRoot) {
|
|
64162
|
-
return
|
|
64247
|
+
return join26(gitRoot, ".todos", "todos.db");
|
|
64163
64248
|
}
|
|
64164
64249
|
}
|
|
64165
64250
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
64166
|
-
const newPath =
|
|
64167
|
-
const legacyPath =
|
|
64251
|
+
const newPath = join26(home, ".hasna", "todos", "todos.db");
|
|
64252
|
+
const legacyPath = join26(home, ".todos", "todos.db");
|
|
64168
64253
|
if (!existsSync18(newPath) && existsSync18(legacyPath)) {
|
|
64169
64254
|
return legacyPath;
|
|
64170
64255
|
}
|
|
@@ -64173,7 +64258,7 @@ function getDbPath4() {
|
|
|
64173
64258
|
function ensureDir3(filePath) {
|
|
64174
64259
|
if (isInMemoryDb2(filePath))
|
|
64175
64260
|
return;
|
|
64176
|
-
const dir = dirname5(
|
|
64261
|
+
const dir = dirname5(resolve4(filePath));
|
|
64177
64262
|
if (!existsSync18(dir)) {
|
|
64178
64263
|
mkdirSync17(dir, { recursive: true });
|
|
64179
64264
|
}
|
|
@@ -64792,14 +64877,14 @@ function writeJsonFile(path, data) {
|
|
|
64792
64877
|
`);
|
|
64793
64878
|
}
|
|
64794
64879
|
function readHighWaterMark(dir) {
|
|
64795
|
-
const path =
|
|
64880
|
+
const path = join27(dir, ".highwatermark");
|
|
64796
64881
|
if (!existsSync25(path))
|
|
64797
64882
|
return 1;
|
|
64798
64883
|
const val = parseInt(readFileSync11(path, "utf-8").trim(), 10);
|
|
64799
64884
|
return isNaN(val) ? 1 : val;
|
|
64800
64885
|
}
|
|
64801
64886
|
function writeHighWaterMark(dir, value) {
|
|
64802
|
-
writeFileSync10(
|
|
64887
|
+
writeFileSync10(join27(dir, ".highwatermark"), String(value));
|
|
64803
64888
|
}
|
|
64804
64889
|
function getFileMtimeMs(path) {
|
|
64805
64890
|
try {
|
|
@@ -80829,13 +80914,14 @@ function registerIntegrationAndMeta(server) {
|
|
|
80829
80914
|
try {
|
|
80830
80915
|
const sid = resolveSessionId(session_id);
|
|
80831
80916
|
const page = getSessionPage(sid);
|
|
80832
|
-
const {
|
|
80833
|
-
const creds = await
|
|
80917
|
+
const { lookupCredentials: lookupCredentials2, loginWithCredentials: loginWithCredentials2 } = await Promise.resolve().then(() => (init_auth(), exports_auth));
|
|
80918
|
+
const { credential: creds, method } = await lookupCredentials2(service);
|
|
80834
80919
|
if (!creds)
|
|
80835
80920
|
return err(new Error(`No credentials found for '${service}'. Add them: secrets set ${service}_email yourlogin && secrets set ${service}_password yourpass`));
|
|
80836
80921
|
const result = await loginWithCredentials2(page, creds, {
|
|
80837
80922
|
loginUrl: login_url,
|
|
80838
|
-
saveProfile: save_profile ? service : undefined
|
|
80923
|
+
saveProfile: save_profile ? service : undefined,
|
|
80924
|
+
method
|
|
80839
80925
|
});
|
|
80840
80926
|
return json(result);
|
|
80841
80927
|
} catch (e) {
|
|
@@ -81218,7 +81304,11 @@ function assertTuiSession(sessionId) {
|
|
|
81218
81304
|
}
|
|
81219
81305
|
}
|
|
81220
81306
|
function getTuiSession(sessionId) {
|
|
81221
|
-
|
|
81307
|
+
const session = getSessionTuiSession(sessionId);
|
|
81308
|
+
if (!session) {
|
|
81309
|
+
throw new Error(`TUI session handle missing for session ${sessionId}. Close and re-open with engine="tui".`);
|
|
81310
|
+
}
|
|
81311
|
+
return session;
|
|
81222
81312
|
}
|
|
81223
81313
|
function getTuiMeta(sessionId) {
|
|
81224
81314
|
const session = getTuiSession(sessionId);
|
|
@@ -81264,19 +81354,19 @@ async function withTuiHealth(sessionId, operation, options = {}) {
|
|
|
81264
81354
|
} else if (!health.healthy) {
|
|
81265
81355
|
throw Object.assign(new Error(`TUI session is unhealthy: ${health.reason}. Close and reopen the session.`), { code: "TUI_UNHEALTHY" });
|
|
81266
81356
|
}
|
|
81267
|
-
let
|
|
81268
|
-
const
|
|
81269
|
-
|
|
81270
|
-
}, timeoutMs);
|
|
81271
|
-
try {
|
|
81272
|
-
return await operation(page, session);
|
|
81273
|
-
} catch (error) {
|
|
81274
|
-
if (timedOut) {
|
|
81357
|
+
let timer;
|
|
81358
|
+
const timeout = new Promise((_, reject) => {
|
|
81359
|
+
timer = setTimeout(() => {
|
|
81275
81360
|
const err2 = new Error(`${operationName} timed out after ${timeoutMs}ms \u2014 ttyd/playwright connection may be unhealthy. Status: ${health.healthy ? "was healthy before op" : "was already unhealthy"}. Try closing and re-opening the session.`);
|
|
81276
81361
|
Object.assign(err2, { code: "TUI_TIMEOUT" });
|
|
81277
|
-
|
|
81278
|
-
}
|
|
81279
|
-
|
|
81362
|
+
reject(err2);
|
|
81363
|
+
}, timeoutMs);
|
|
81364
|
+
});
|
|
81365
|
+
try {
|
|
81366
|
+
return await Promise.race([
|
|
81367
|
+
operation(page, session),
|
|
81368
|
+
timeout
|
|
81369
|
+
]);
|
|
81280
81370
|
} finally {
|
|
81281
81371
|
clearTimeout(timer);
|
|
81282
81372
|
}
|
|
@@ -81575,6 +81665,7 @@ CONDITION SYNTAX:
|
|
|
81575
81665
|
}, interval_ms)
|
|
81576
81666
|
};
|
|
81577
81667
|
activeRecordings2.set(sid, recording);
|
|
81668
|
+
trackTuiRecording(sid, recording.intervalId);
|
|
81578
81669
|
return json({
|
|
81579
81670
|
recording: true,
|
|
81580
81671
|
session_id: sid,
|
|
@@ -81594,6 +81685,7 @@ CONDITION SYNTAX:
|
|
|
81594
81685
|
if (!recording)
|
|
81595
81686
|
return err(new Error("No active recording for this session"));
|
|
81596
81687
|
clearInterval(recording.intervalId);
|
|
81688
|
+
stopTuiRecording(sid);
|
|
81597
81689
|
activeRecordings2.delete(sid);
|
|
81598
81690
|
const duration = (Date.now() - recording.startTime) / 1000;
|
|
81599
81691
|
const header = {
|
|
@@ -81644,6 +81736,7 @@ var init_tui2 = __esm(() => {
|
|
|
81644
81736
|
init_helpers();
|
|
81645
81737
|
init_tui();
|
|
81646
81738
|
init_session();
|
|
81739
|
+
init_tui_recording();
|
|
81647
81740
|
KEY_MAP = {
|
|
81648
81741
|
"ctrl+c": "\x03",
|
|
81649
81742
|
"ctrl+d": "\x04",
|
|
@@ -81692,23 +81785,21 @@ var init_tui2 = __esm(() => {
|
|
|
81692
81785
|
activeRecordings2 = new Map;
|
|
81693
81786
|
});
|
|
81694
81787
|
|
|
81788
|
+
// src/mcp/http.ts
|
|
81789
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
81790
|
+
var init_http = () => {};
|
|
81791
|
+
|
|
81695
81792
|
// src/mcp/index.ts
|
|
81696
81793
|
var exports_mcp = {};
|
|
81794
|
+
__export(exports_mcp, {
|
|
81795
|
+
buildServer: () => buildServer
|
|
81796
|
+
});
|
|
81697
81797
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
81698
81798
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
81699
81799
|
import { readFileSync as readFileSync12 } from "fs";
|
|
81700
|
-
import { join as
|
|
81701
|
-
|
|
81702
|
-
|
|
81703
|
-
init_dist();
|
|
81704
|
-
init_sessions2();
|
|
81705
|
-
init_actions2();
|
|
81706
|
-
init_capture();
|
|
81707
|
-
init_network2();
|
|
81708
|
-
init_data();
|
|
81709
|
-
init_tui2();
|
|
81710
|
-
_pkg = JSON.parse(readFileSync12(join27(import.meta.dir, "../../package.json"), "utf8"));
|
|
81711
|
-
server = new McpServer2({
|
|
81800
|
+
import { join as join28 } from "path";
|
|
81801
|
+
function buildServer() {
|
|
81802
|
+
const server = new McpServer2({
|
|
81712
81803
|
name: "@hasna/browser",
|
|
81713
81804
|
version: _pkg.version
|
|
81714
81805
|
});
|
|
@@ -81719,10 +81810,20 @@ var init_mcp = __esm(async () => {
|
|
|
81719
81810
|
register11(server);
|
|
81720
81811
|
register12(server);
|
|
81721
81812
|
registerCloudTools(server, "browser");
|
|
81722
|
-
|
|
81723
|
-
|
|
81724
|
-
|
|
81725
|
-
|
|
81813
|
+
return server;
|
|
81814
|
+
}
|
|
81815
|
+
var _pkg;
|
|
81816
|
+
var init_mcp = __esm(() => {
|
|
81817
|
+
init_dist();
|
|
81818
|
+
init_sessions2();
|
|
81819
|
+
init_actions2();
|
|
81820
|
+
init_capture();
|
|
81821
|
+
init_network2();
|
|
81822
|
+
init_data();
|
|
81823
|
+
init_tui2();
|
|
81824
|
+
init_http();
|
|
81825
|
+
_pkg = JSON.parse(readFileSync12(join28(import.meta.dir, "../../package.json"), "utf8"));
|
|
81826
|
+
if (false) {}
|
|
81726
81827
|
});
|
|
81727
81828
|
|
|
81728
81829
|
// src/db/snapshots.ts
|
|
@@ -81763,7 +81864,7 @@ var init_snapshots = __esm(() => {
|
|
|
81763
81864
|
|
|
81764
81865
|
// src/server/index.ts
|
|
81765
81866
|
var exports_server = {};
|
|
81766
|
-
import { join as
|
|
81867
|
+
import { join as join30 } from "path";
|
|
81767
81868
|
import { existsSync as existsSync19 } from "fs";
|
|
81768
81869
|
function corsHeaders(origin) {
|
|
81769
81870
|
const headers = {
|
|
@@ -81829,7 +81930,7 @@ function serverError(e, extraHeaders) {
|
|
|
81829
81930
|
headers: { "Content-Type": "application/json", ...extraHeaders ?? {} }
|
|
81830
81931
|
});
|
|
81831
81932
|
}
|
|
81832
|
-
var PORT, API_KEY, ALLOWED_ORIGIN, startTime, networkCleanup, consoleCleanup, harCaptures2,
|
|
81933
|
+
var PORT, API_KEY, ALLOWED_ORIGIN, startTime, networkCleanup, consoleCleanup, harCaptures2, server;
|
|
81833
81934
|
var init_server = __esm(() => {
|
|
81834
81935
|
init_session();
|
|
81835
81936
|
init_actions();
|
|
@@ -81854,7 +81955,7 @@ var init_server = __esm(() => {
|
|
|
81854
81955
|
networkCleanup = new Map;
|
|
81855
81956
|
consoleCleanup = new Map;
|
|
81856
81957
|
harCaptures2 = new Map;
|
|
81857
|
-
|
|
81958
|
+
server = Bun.serve({
|
|
81858
81959
|
port: PORT,
|
|
81859
81960
|
async fetch(req) {
|
|
81860
81961
|
const url = new URL(req.url);
|
|
@@ -82150,19 +82251,19 @@ var init_server = __esm(() => {
|
|
|
82150
82251
|
const id = path.split("/")[3];
|
|
82151
82252
|
return ok({ deleted: deleteDownload(id) });
|
|
82152
82253
|
}
|
|
82153
|
-
const dashboardDist =
|
|
82254
|
+
const dashboardDist = join30(import.meta.dir, "../../dashboard/dist");
|
|
82154
82255
|
if (existsSync19(dashboardDist)) {
|
|
82155
82256
|
const cleanPath = path.replace(/^\//, "");
|
|
82156
82257
|
if (cleanPath.includes("..") || cleanPath.startsWith("/"))
|
|
82157
82258
|
return notFound("Not found", headers);
|
|
82158
|
-
const filePath = path === "/" ?
|
|
82159
|
-
const resolved = await Bun.file(filePath).arrayBuffer().then(() =>
|
|
82259
|
+
const filePath = path === "/" ? join30(dashboardDist, "index.html") : join30(dashboardDist, cleanPath);
|
|
82260
|
+
const resolved = await Bun.file(filePath).arrayBuffer().then(() => join30(dashboardDist, cleanPath)) || "";
|
|
82160
82261
|
if (!resolved.startsWith(dashboardDist))
|
|
82161
82262
|
return notFound("Not found", headers);
|
|
82162
82263
|
if (existsSync19(filePath)) {
|
|
82163
82264
|
return new Response(Bun.file(filePath), { headers });
|
|
82164
82265
|
}
|
|
82165
|
-
return new Response(Bun.file(
|
|
82266
|
+
return new Response(Bun.file(join30(dashboardDist, "index.html")), { headers });
|
|
82166
82267
|
}
|
|
82167
82268
|
if (path === "/" || path === "") {
|
|
82168
82269
|
return new Response("@hasna/browser REST API running. Dashboard not built.", {
|
|
@@ -82197,7 +82298,7 @@ var {
|
|
|
82197
82298
|
// src/cli/index.tsx
|
|
82198
82299
|
init_dist();
|
|
82199
82300
|
import { readFileSync as readFileSync13 } from "fs";
|
|
82200
|
-
import { join as
|
|
82301
|
+
import { join as join31 } from "path";
|
|
82201
82302
|
|
|
82202
82303
|
// src/cli/commands/browse.ts
|
|
82203
82304
|
init_session();
|
|
@@ -83022,7 +83123,7 @@ Stopping watch. ${checkCount} checks performed.`));
|
|
|
83022
83123
|
});
|
|
83023
83124
|
});
|
|
83024
83125
|
program2.command("mcp").description("Start the MCP server (stdio)").action(async () => {
|
|
83025
|
-
await
|
|
83126
|
+
await Promise.resolve().then(() => (init_mcp(), exports_mcp));
|
|
83026
83127
|
});
|
|
83027
83128
|
program2.command("serve").description("Start the REST API server").option("--port <port>", "Port to listen on", "7030").action(async (opts) => {
|
|
83028
83129
|
process.env["BROWSER_SERVER_PORT"] = opts.port;
|
|
@@ -83055,7 +83156,7 @@ Stopping watch. ${checkCount} checks performed.`));
|
|
|
83055
83156
|
}
|
|
83056
83157
|
|
|
83057
83158
|
// src/cli/index.tsx
|
|
83058
|
-
var pkg = JSON.parse(readFileSync13(
|
|
83159
|
+
var pkg = JSON.parse(readFileSync13(join31(import.meta.dir, "../../package.json"), "utf8"));
|
|
83059
83160
|
var program2 = new Command;
|
|
83060
83161
|
program2.name("browser").description("@hasna/browser \u2014 general-purpose browser agent CLI").version(pkg.version);
|
|
83061
83162
|
register(program2);
|
|
@@ -83063,4 +83164,9 @@ register2(program2);
|
|
|
83063
83164
|
register3(program2);
|
|
83064
83165
|
register13(program2);
|
|
83065
83166
|
registerCloudCommands(program2, "browser");
|
|
83066
|
-
|
|
83167
|
+
try {
|
|
83168
|
+
await program2.parseAsync(process.argv);
|
|
83169
|
+
} finally {
|
|
83170
|
+
const { closeAllSessions: closeAllSessions2 } = await Promise.resolve().then(() => (init_session(), exports_session));
|
|
83171
|
+
await closeAllSessions2();
|
|
83172
|
+
}
|