@hasna/browser 0.3.8 → 0.4.1
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 +259 -65
- package/dist/engines/selector.d.ts.map +1 -1
- package/dist/engines/tui.d.ts +49 -0
- package/dist/engines/tui.d.ts.map +1 -0
- package/dist/engines/tui.test.d.ts +2 -0
- package/dist/engines/tui.test.d.ts.map +1 -0
- package/dist/index.js +139 -42
- package/dist/lib/login-scripts.d.ts +89 -0
- package/dist/lib/login-scripts.d.ts.map +1 -0
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/mcp/capture.d.ts.map +1 -1
- package/dist/mcp/index.js +313 -110
- package/dist/mcp/meta.d.ts.map +1 -1
- package/dist/mcp/network.d.ts.map +1 -1
- package/dist/mcp/recordings.d.ts.map +1 -1
- package/dist/server/index.js +135 -41
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -6,60 +6,39 @@ var __defProp = Object.defineProperty;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
function __accessProp(key) {
|
|
10
|
-
return this[key];
|
|
11
|
-
}
|
|
12
|
-
var __toESMCache_node;
|
|
13
|
-
var __toESMCache_esm;
|
|
14
9
|
var __toESM = (mod, isNodeMode, target) => {
|
|
15
|
-
var canCache = mod != null && typeof mod === "object";
|
|
16
|
-
if (canCache) {
|
|
17
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
18
|
-
var cached = cache.get(mod);
|
|
19
|
-
if (cached)
|
|
20
|
-
return cached;
|
|
21
|
-
}
|
|
22
10
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
23
11
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
24
12
|
for (let key of __getOwnPropNames(mod))
|
|
25
13
|
if (!__hasOwnProp.call(to, key))
|
|
26
14
|
__defProp(to, key, {
|
|
27
|
-
get:
|
|
15
|
+
get: () => mod[key],
|
|
28
16
|
enumerable: true
|
|
29
17
|
});
|
|
30
|
-
if (canCache)
|
|
31
|
-
cache.set(mod, to);
|
|
32
18
|
return to;
|
|
33
19
|
};
|
|
20
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
34
21
|
var __toCommonJS = (from) => {
|
|
35
|
-
var entry =
|
|
22
|
+
var entry = __moduleCache.get(from), desc;
|
|
36
23
|
if (entry)
|
|
37
24
|
return entry;
|
|
38
25
|
entry = __defProp({}, "__esModule", { value: true });
|
|
39
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
45
|
-
});
|
|
46
|
-
}
|
|
26
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
27
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
28
|
+
get: () => from[key],
|
|
29
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
30
|
+
}));
|
|
47
31
|
__moduleCache.set(from, entry);
|
|
48
32
|
return entry;
|
|
49
33
|
};
|
|
50
|
-
var __moduleCache;
|
|
51
34
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
52
|
-
var __returnValue = (v) => v;
|
|
53
|
-
function __exportSetter(name, newValue) {
|
|
54
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
55
|
-
}
|
|
56
35
|
var __export = (target, all) => {
|
|
57
36
|
for (var name in all)
|
|
58
37
|
__defProp(target, name, {
|
|
59
38
|
get: all[name],
|
|
60
39
|
enumerable: true,
|
|
61
40
|
configurable: true,
|
|
62
|
-
set:
|
|
41
|
+
set: (newValue) => all[name] = () => newValue
|
|
63
42
|
});
|
|
64
43
|
};
|
|
65
44
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -2177,11 +2156,11 @@ import { homedir as homedir4 } from "os";
|
|
|
2177
2156
|
import { join as join4 } from "path";
|
|
2178
2157
|
import { join as join6, dirname } from "path";
|
|
2179
2158
|
import { homedir as homedir5, platform } from "os";
|
|
2180
|
-
function
|
|
2159
|
+
function __accessProp(key) {
|
|
2181
2160
|
return this[key];
|
|
2182
2161
|
}
|
|
2183
|
-
function
|
|
2184
|
-
this[name] =
|
|
2162
|
+
function __exportSetter(name, newValue) {
|
|
2163
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
2185
2164
|
}
|
|
2186
2165
|
function translateSql(sql, dialect) {
|
|
2187
2166
|
if (dialect === "sqlite")
|
|
@@ -3211,10 +3190,10 @@ class SyncProgressTracker {
|
|
|
3211
3190
|
}
|
|
3212
3191
|
}
|
|
3213
3192
|
}
|
|
3214
|
-
var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2,
|
|
3193
|
+
var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __toESMCache_node, __toESMCache_esm, __toESM2 = (mod, isNodeMode, target) => {
|
|
3215
3194
|
var canCache = mod != null && typeof mod === "object";
|
|
3216
3195
|
if (canCache) {
|
|
3217
|
-
var cache = isNodeMode ?
|
|
3196
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
3218
3197
|
var cached = cache.get(mod);
|
|
3219
3198
|
if (cached)
|
|
3220
3199
|
return cached;
|
|
@@ -3224,19 +3203,19 @@ var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __t
|
|
|
3224
3203
|
for (let key of __getOwnPropNames2(mod))
|
|
3225
3204
|
if (!__hasOwnProp2.call(to, key))
|
|
3226
3205
|
__defProp2(to, key, {
|
|
3227
|
-
get:
|
|
3206
|
+
get: __accessProp.bind(mod, key),
|
|
3228
3207
|
enumerable: true
|
|
3229
3208
|
});
|
|
3230
3209
|
if (canCache)
|
|
3231
3210
|
cache.set(mod, to);
|
|
3232
3211
|
return to;
|
|
3233
|
-
}, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports),
|
|
3212
|
+
}, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports), __returnValue = (v) => v, __export2 = (target, all) => {
|
|
3234
3213
|
for (var name in all)
|
|
3235
3214
|
__defProp2(target, name, {
|
|
3236
3215
|
get: all[name],
|
|
3237
3216
|
enumerable: true,
|
|
3238
3217
|
configurable: true,
|
|
3239
|
-
set:
|
|
3218
|
+
set: __exportSetter.bind(all, name)
|
|
3240
3219
|
});
|
|
3241
3220
|
}, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), __require2, require_postgres_array, require_arrayParser, require_postgres_date, require_mutable, require_postgres_interval, require_postgres_bytea, require_textParsers, require_pg_int8, require_binaryParsers, require_builtins, require_pg_types, require_defaults, require_utils, require_utils_legacy, require_utils_webcrypto, require_utils2, require_cert_signatures, require_sasl, require_type_overrides, require_pg_connection_string, require_connection_parameters, require_result, require_query, require_messages, require_buffer_writer, require_serializer, require_buffer_reader, require_parser, require_dist, require_empty, require_stream, require_connection, require_split2, require_helper, require_lib, require_client, require_pg_pool, require_query2, require_client2, require_lib2, import_lib, Client, Pool, Connection, types, Query, DatabaseError, escapeIdentifier, escapeLiteral, Result, TypeOverrides, defaults, esm_default, init_esm, init_adapter, util, objectUtil, ZodParsedType, getParsedType = (data) => {
|
|
3242
3221
|
const t = typeof data;
|
|
@@ -12653,6 +12632,89 @@ var init_bun_webview = __esm(() => {
|
|
|
12653
12632
|
};
|
|
12654
12633
|
});
|
|
12655
12634
|
|
|
12635
|
+
// src/engines/tui.ts
|
|
12636
|
+
import { execSync as execSync2, spawn as spawn2 } from "child_process";
|
|
12637
|
+
function isTuiAvailable() {
|
|
12638
|
+
try {
|
|
12639
|
+
execSync2("which ttyd", { stdio: "ignore" });
|
|
12640
|
+
return true;
|
|
12641
|
+
} catch {
|
|
12642
|
+
return false;
|
|
12643
|
+
}
|
|
12644
|
+
}
|
|
12645
|
+
async function findAvailablePort(startPort) {
|
|
12646
|
+
let port = startPort;
|
|
12647
|
+
for (let i = 0;i < 100; i++) {
|
|
12648
|
+
try {
|
|
12649
|
+
const resp = await fetch(`http://localhost:${port}`);
|
|
12650
|
+
port++;
|
|
12651
|
+
} catch {
|
|
12652
|
+
return port;
|
|
12653
|
+
}
|
|
12654
|
+
}
|
|
12655
|
+
throw new BrowserError("No available port found for ttyd", "TUI_PORT_EXHAUSTED");
|
|
12656
|
+
}
|
|
12657
|
+
async function waitForTtyd(port, timeoutMs = 1e4) {
|
|
12658
|
+
const start = Date.now();
|
|
12659
|
+
while (Date.now() - start < timeoutMs) {
|
|
12660
|
+
try {
|
|
12661
|
+
const resp = await fetch(`http://localhost:${port}`);
|
|
12662
|
+
if (resp.ok || resp.status === 200)
|
|
12663
|
+
return;
|
|
12664
|
+
} catch {}
|
|
12665
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
12666
|
+
}
|
|
12667
|
+
throw new BrowserError(`ttyd did not start within ${timeoutMs}ms`, "TUI_TIMEOUT");
|
|
12668
|
+
}
|
|
12669
|
+
async function launchTui(command, options = {}) {
|
|
12670
|
+
if (!isTuiAvailable()) {
|
|
12671
|
+
throw new BrowserError("ttyd not found \u2014 install with: brew install ttyd", "TUI_NOT_AVAILABLE");
|
|
12672
|
+
}
|
|
12673
|
+
const port = await findAvailablePort(nextPort);
|
|
12674
|
+
nextPort = port + 1;
|
|
12675
|
+
const ttydProcess = spawn2("ttyd", ["--writable", "--port", String(port), "/bin/sh", "-c", command], {
|
|
12676
|
+
stdio: "ignore",
|
|
12677
|
+
detached: false
|
|
12678
|
+
});
|
|
12679
|
+
ttydProcess.on("error", (err) => {
|
|
12680
|
+
console.error(`[tui] ttyd process error: ${err.message}`);
|
|
12681
|
+
});
|
|
12682
|
+
try {
|
|
12683
|
+
await waitForTtyd(port);
|
|
12684
|
+
const viewport = options.viewport ?? { width: 1280, height: 720 };
|
|
12685
|
+
const browser = await launchPlaywright({
|
|
12686
|
+
headless: options.headless ?? true,
|
|
12687
|
+
viewport
|
|
12688
|
+
});
|
|
12689
|
+
const page = await getPage(browser, { viewport });
|
|
12690
|
+
await page.goto(`http://localhost:${port}`, {
|
|
12691
|
+
waitUntil: "domcontentloaded"
|
|
12692
|
+
});
|
|
12693
|
+
await page.waitForSelector(".xterm-screen", { timeout: 1e4 });
|
|
12694
|
+
return { ttydProcess, port, browser, page };
|
|
12695
|
+
} catch (err) {
|
|
12696
|
+
ttydProcess.kill();
|
|
12697
|
+
throw err;
|
|
12698
|
+
}
|
|
12699
|
+
}
|
|
12700
|
+
async function closeTui(session) {
|
|
12701
|
+
try {
|
|
12702
|
+
await session.page.close();
|
|
12703
|
+
} catch {}
|
|
12704
|
+
try {
|
|
12705
|
+
await session.browser.close();
|
|
12706
|
+
} catch {}
|
|
12707
|
+
try {
|
|
12708
|
+
session.ttydProcess.kill("SIGTERM");
|
|
12709
|
+
} catch {}
|
|
12710
|
+
}
|
|
12711
|
+
var DEFAULT_TTYD_PORT_START = 7780, nextPort;
|
|
12712
|
+
var init_tui = __esm(() => {
|
|
12713
|
+
init_types();
|
|
12714
|
+
init_playwright();
|
|
12715
|
+
nextPort = DEFAULT_TTYD_PORT_START;
|
|
12716
|
+
});
|
|
12717
|
+
|
|
12656
12718
|
// src/engines/selector.ts
|
|
12657
12719
|
function selectEngine(useCase, explicit) {
|
|
12658
12720
|
if (explicit && explicit !== "auto")
|
|
@@ -12676,6 +12738,7 @@ var init_selector = __esm(() => {
|
|
|
12676
12738
|
init_types();
|
|
12677
12739
|
init_lightpanda();
|
|
12678
12740
|
init_bun_webview();
|
|
12741
|
+
init_tui();
|
|
12679
12742
|
ENGINE_MAP = {
|
|
12680
12743
|
["scrape" /* SCRAPE */]: "bun",
|
|
12681
12744
|
["extract_links" /* EXTRACT_LINKS */]: "bun",
|
|
@@ -12686,6 +12749,7 @@ var init_selector = __esm(() => {
|
|
|
12686
12749
|
["auth_flow" /* AUTH_FLOW */]: "playwright",
|
|
12687
12750
|
["multi_tab" /* MULTI_TAB */]: "playwright",
|
|
12688
12751
|
["record_replay" /* RECORD_REPLAY */]: "playwright",
|
|
12752
|
+
["terminal_test" /* TERMINAL_TEST */]: "tui",
|
|
12689
12753
|
["network_monitor" /* NETWORK_MONITOR */]: "cdp",
|
|
12690
12754
|
["har_capture" /* HAR_CAPTURE */]: "cdp",
|
|
12691
12755
|
["perf_profile" /* PERF_PROFILE */]: "cdp",
|
|
@@ -14055,7 +14119,7 @@ async function createSession2(opts = {}) {
|
|
|
14055
14119
|
try {
|
|
14056
14120
|
cleanups2.push(setupDialogHandler(page2, session2.id));
|
|
14057
14121
|
} catch {}
|
|
14058
|
-
handles.set(session2.id, { browser: cdpBrowser, bunView: null, page: page2, engine: "cdp", cleanups: cleanups2, tokenBudget: { total: 0, used: 0 }, lastActivity: Date.now(), autoGallery: opts.autoGallery ?? false });
|
|
14122
|
+
handles.set(session2.id, { browser: cdpBrowser, bunView: null, tuiSession: null, page: page2, engine: "cdp", cleanups: cleanups2, tokenBudget: { total: 0, used: 0 }, lastActivity: Date.now(), autoGallery: opts.autoGallery ?? false });
|
|
14059
14123
|
return { session: session2, page: page2 };
|
|
14060
14124
|
}
|
|
14061
14125
|
const engine = opts.engine === "auto" || !opts.engine ? selectEngine(opts.useCase ?? "spa_navigate" /* SPA_NAVIGATE */, opts.engine) : opts.engine;
|
|
@@ -14081,6 +14145,38 @@ async function createSession2(opts = {}) {
|
|
|
14081
14145
|
browser = await connectLightpanda();
|
|
14082
14146
|
const context = await browser.newContext({ viewport: opts.viewport ?? { width: 1280, height: 720 } });
|
|
14083
14147
|
page = await context.newPage();
|
|
14148
|
+
} else if (resolvedEngine === "tui") {
|
|
14149
|
+
const command = opts.startUrl ?? "bash";
|
|
14150
|
+
const tuiSess = await launchTui(command, {
|
|
14151
|
+
headless: opts.headless ?? true,
|
|
14152
|
+
viewport: opts.viewport
|
|
14153
|
+
});
|
|
14154
|
+
browser = tuiSess.browser;
|
|
14155
|
+
page = tuiSess.page;
|
|
14156
|
+
const session2 = createSession({
|
|
14157
|
+
engine: "tui",
|
|
14158
|
+
projectId: opts.projectId,
|
|
14159
|
+
agentId: opts.agentId,
|
|
14160
|
+
startUrl: opts.startUrl,
|
|
14161
|
+
name: opts.name ?? "tui"
|
|
14162
|
+
});
|
|
14163
|
+
const cleanups2 = [];
|
|
14164
|
+
cleanups2.push(() => closeTui(tuiSess));
|
|
14165
|
+
if (opts.captureNetwork !== false) {
|
|
14166
|
+
try {
|
|
14167
|
+
cleanups2.push(enableNetworkLogging(page, session2.id));
|
|
14168
|
+
} catch {}
|
|
14169
|
+
}
|
|
14170
|
+
if (opts.captureConsole !== false) {
|
|
14171
|
+
try {
|
|
14172
|
+
cleanups2.push(enableConsoleCapture(page, session2.id));
|
|
14173
|
+
} catch {}
|
|
14174
|
+
}
|
|
14175
|
+
try {
|
|
14176
|
+
cleanups2.push(setupDialogHandler(page, session2.id));
|
|
14177
|
+
} catch {}
|
|
14178
|
+
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 });
|
|
14179
|
+
return { session: session2, page };
|
|
14084
14180
|
} else {
|
|
14085
14181
|
browser = await pool.acquire(opts.headless ?? true);
|
|
14086
14182
|
if (opts.storageState) {
|
|
@@ -14151,7 +14247,7 @@ async function createSession2(opts = {}) {
|
|
|
14151
14247
|
} catch {}
|
|
14152
14248
|
}
|
|
14153
14249
|
}
|
|
14154
|
-
handles.set(session.id, { browser, bunView, page, engine: bunView ? "bun" : resolvedEngine, cleanups, tokenBudget: { total: 0, used: 0 }, lastActivity: Date.now(), autoGallery: opts.autoGallery ?? false });
|
|
14250
|
+
handles.set(session.id, { browser, bunView, tuiSession: null, page, engine: bunView ? "bun" : resolvedEngine, cleanups, tokenBudget: { total: 0, used: 0 }, lastActivity: Date.now(), autoGallery: opts.autoGallery ?? false });
|
|
14155
14251
|
if (opts.startUrl) {
|
|
14156
14252
|
try {
|
|
14157
14253
|
if (bunView) {
|
|
@@ -14221,7 +14317,7 @@ async function closeSession2(sessionId) {
|
|
|
14221
14317
|
try {
|
|
14222
14318
|
await handle.bunView.close();
|
|
14223
14319
|
} catch {}
|
|
14224
|
-
} else {
|
|
14320
|
+
} else if (handle.tuiSession) {} else {
|
|
14225
14321
|
try {
|
|
14226
14322
|
await handle.page.context().close();
|
|
14227
14323
|
} catch {}
|
|
@@ -14321,6 +14417,7 @@ var init_session = __esm(() => {
|
|
|
14321
14417
|
init_lightpanda();
|
|
14322
14418
|
init_bun_webview();
|
|
14323
14419
|
init_selector();
|
|
14420
|
+
init_tui();
|
|
14324
14421
|
init_network();
|
|
14325
14422
|
init_console();
|
|
14326
14423
|
init_stealth();
|
|
@@ -27481,7 +27578,7 @@ var init_helpers = __esm(() => {
|
|
|
27481
27578
|
// src/mcp/sessions.ts
|
|
27482
27579
|
function register4(server) {
|
|
27483
27580
|
server.tool("browser_session_create", "Create a new browser session. If agent_id is set and already has an active session, returns the existing one (use force_new to override). If session_id is omitted on other tools, the single active session is auto-selected. Use cdp_url to attach to an already-running Chrome instance.", {
|
|
27484
|
-
engine: exports_external2.enum(["playwright", "cdp", "lightpanda", "bun", "auto"]).optional().default("auto"),
|
|
27581
|
+
engine: exports_external2.enum(["playwright", "cdp", "lightpanda", "bun", "tui", "auto"]).optional().default("auto"),
|
|
27485
27582
|
use_case: exports_external2.string().optional(),
|
|
27486
27583
|
project_id: exports_external2.string().optional(),
|
|
27487
27584
|
agent_id: exports_external2.string().optional(),
|
|
@@ -28710,6 +28807,40 @@ function register6(server) {
|
|
|
28710
28807
|
return err(e);
|
|
28711
28808
|
}
|
|
28712
28809
|
});
|
|
28810
|
+
server.tool("browser_diff", "Visual diff between two URLs or a URL and a gallery entry. Screenshots both, returns a pixel diff image highlighting changes in red.", {
|
|
28811
|
+
session_id: exports_external2.string().optional(),
|
|
28812
|
+
url1: exports_external2.string().describe("First URL to screenshot"),
|
|
28813
|
+
url2: exports_external2.string().describe("Second URL to screenshot"),
|
|
28814
|
+
threshold: exports_external2.number().optional().default(10).describe("Pixel difference threshold (0-255, default 10)"),
|
|
28815
|
+
wait_ms: exports_external2.number().optional().default(1000).describe("Wait time after navigation before screenshot (ms)")
|
|
28816
|
+
}, async ({ session_id, url1, url2, threshold, wait_ms }) => {
|
|
28817
|
+
try {
|
|
28818
|
+
const sid = resolveSessionId(session_id);
|
|
28819
|
+
const page = getSessionPage(sid);
|
|
28820
|
+
await page.goto(url1, { waitUntil: "domcontentloaded" });
|
|
28821
|
+
await new Promise((r) => setTimeout(r, wait_ms));
|
|
28822
|
+
const ss1 = await takeScreenshot(page, { maxWidth: 1280, compress: true, track: false });
|
|
28823
|
+
await page.goto(url2, { waitUntil: "domcontentloaded" });
|
|
28824
|
+
await new Promise((r) => setTimeout(r, wait_ms));
|
|
28825
|
+
const ss2 = await takeScreenshot(page, { maxWidth: 1280, compress: true, track: false });
|
|
28826
|
+
const { diffImages: diffImages2 } = await Promise.resolve().then(() => (init_gallery_diff(), exports_gallery_diff));
|
|
28827
|
+
const diff = await diffImages2(ss1.path, ss2.path);
|
|
28828
|
+
logEvent(sid, "diff", { url1, url2, changed_percent: diff.changed_percent });
|
|
28829
|
+
return json({
|
|
28830
|
+
url1,
|
|
28831
|
+
url2,
|
|
28832
|
+
changed_pixels: diff.changed_pixels,
|
|
28833
|
+
total_pixels: diff.total_pixels,
|
|
28834
|
+
changed_percent: Math.round(diff.changed_percent * 100) / 100,
|
|
28835
|
+
diff_path: diff.diff_path,
|
|
28836
|
+
diff_base64: diff.diff_base64.length > 50000 ? undefined : diff.diff_base64,
|
|
28837
|
+
screenshot1_path: ss1.path,
|
|
28838
|
+
screenshot2_path: ss2.path
|
|
28839
|
+
});
|
|
28840
|
+
} catch (e) {
|
|
28841
|
+
return err(e);
|
|
28842
|
+
}
|
|
28843
|
+
});
|
|
28713
28844
|
}
|
|
28714
28845
|
var init_capture = __esm(() => {
|
|
28715
28846
|
init_helpers();
|
|
@@ -31845,6 +31976,53 @@ function register7(server) {
|
|
|
31845
31976
|
return err(e);
|
|
31846
31977
|
}
|
|
31847
31978
|
});
|
|
31979
|
+
server.tool("browser_performance_budget", "Check page performance against a budget. Set thresholds for LCP, FCP, CLS, TTFB, DOM complete, and load event. Returns pass/fail per metric with actual values.", {
|
|
31980
|
+
session_id: exports_external2.string().optional(),
|
|
31981
|
+
lcp_ms: exports_external2.number().optional().describe("Largest Contentful Paint budget in ms (good: <2500)"),
|
|
31982
|
+
fcp_ms: exports_external2.number().optional().describe("First Contentful Paint budget in ms (good: <1800)"),
|
|
31983
|
+
cls: exports_external2.number().optional().describe("Cumulative Layout Shift budget (good: <0.1)"),
|
|
31984
|
+
ttfb_ms: exports_external2.number().optional().describe("Time to First Byte budget in ms (good: <800)"),
|
|
31985
|
+
dom_complete_ms: exports_external2.number().optional().describe("DOM complete budget in ms"),
|
|
31986
|
+
load_event_ms: exports_external2.number().optional().describe("Load event budget in ms"),
|
|
31987
|
+
js_heap_mb: exports_external2.number().optional().describe("JS heap size budget in MB")
|
|
31988
|
+
}, async ({ session_id, lcp_ms, fcp_ms, cls, ttfb_ms, dom_complete_ms, load_event_ms, js_heap_mb }) => {
|
|
31989
|
+
try {
|
|
31990
|
+
const sid = resolveSessionId(session_id);
|
|
31991
|
+
const page = getSessionPage(sid);
|
|
31992
|
+
const metrics = await getPerformanceMetrics(page);
|
|
31993
|
+
const checks = [];
|
|
31994
|
+
let allPassed = true;
|
|
31995
|
+
const check = (name, budget, actual) => {
|
|
31996
|
+
if (budget === undefined)
|
|
31997
|
+
return;
|
|
31998
|
+
const passed = actual !== undefined && actual <= budget;
|
|
31999
|
+
if (!passed)
|
|
32000
|
+
allPassed = false;
|
|
32001
|
+
checks.push({ metric: name, budget, actual, passed });
|
|
32002
|
+
};
|
|
32003
|
+
check("lcp", lcp_ms, metrics.lcp);
|
|
32004
|
+
check("fcp", fcp_ms, metrics.fcp);
|
|
32005
|
+
check("cls", cls, metrics.cls);
|
|
32006
|
+
check("ttfb", ttfb_ms, metrics.ttfb);
|
|
32007
|
+
check("dom_complete", dom_complete_ms, metrics.dom_complete);
|
|
32008
|
+
check("load_event", load_event_ms, metrics.load_event);
|
|
32009
|
+
if (js_heap_mb !== undefined && metrics.js_heap_size_used !== undefined) {
|
|
32010
|
+
const heapMb = metrics.js_heap_size_used / (1024 * 1024);
|
|
32011
|
+
const passed = heapMb <= js_heap_mb;
|
|
32012
|
+
if (!passed)
|
|
32013
|
+
allPassed = false;
|
|
32014
|
+
checks.push({ metric: "js_heap_mb", budget: js_heap_mb, actual: Math.round(heapMb * 100) / 100, passed });
|
|
32015
|
+
}
|
|
32016
|
+
return json({
|
|
32017
|
+
passed: allPassed,
|
|
32018
|
+
checks,
|
|
32019
|
+
metrics,
|
|
32020
|
+
url: page.url()
|
|
32021
|
+
});
|
|
32022
|
+
} catch (e) {
|
|
32023
|
+
return err(e);
|
|
32024
|
+
}
|
|
32025
|
+
});
|
|
31848
32026
|
}
|
|
31849
32027
|
var init_network2 = __esm(() => {
|
|
31850
32028
|
init_helpers();
|
|
@@ -32218,7 +32396,7 @@ function register8(server) {
|
|
|
32218
32396
|
max_pages: exports_external2.number().optional().default(50),
|
|
32219
32397
|
same_domain: exports_external2.boolean().optional().default(true),
|
|
32220
32398
|
project_id: exports_external2.string().optional(),
|
|
32221
|
-
engine: exports_external2.enum(["playwright", "cdp", "lightpanda", "bun", "auto"]).optional().default("auto")
|
|
32399
|
+
engine: exports_external2.enum(["playwright", "cdp", "lightpanda", "bun", "tui", "auto"]).optional().default("auto")
|
|
32222
32400
|
}, async ({ url, max_depth, max_pages, same_domain, project_id, engine }) => {
|
|
32223
32401
|
try {
|
|
32224
32402
|
const result = await crawl(url, {
|
|
@@ -32293,6 +32471,19 @@ function register8(server) {
|
|
|
32293
32471
|
return err(e);
|
|
32294
32472
|
}
|
|
32295
32473
|
});
|
|
32474
|
+
server.tool("browser_record_export", "Export a recording as a Playwright test (.spec.ts), Puppeteer script, or JSON. Returns the generated code as text.", {
|
|
32475
|
+
recording_id: exports_external2.string().describe("ID of the recording to export"),
|
|
32476
|
+
format: exports_external2.enum(["playwright", "puppeteer", "json"]).optional().default("playwright").describe("Export format")
|
|
32477
|
+
}, async ({ recording_id, format }) => {
|
|
32478
|
+
try {
|
|
32479
|
+
const { exportRecording: exportRecording2 } = await Promise.resolve().then(() => (init_recorder(), exports_recorder));
|
|
32480
|
+
const code = exportRecording2(recording_id, format);
|
|
32481
|
+
const ext = format === "json" ? ".json" : format === "playwright" ? ".spec.ts" : ".js";
|
|
32482
|
+
return json({ format, filename: `recording-${recording_id}${ext}`, code });
|
|
32483
|
+
} catch (e) {
|
|
32484
|
+
return err(e);
|
|
32485
|
+
}
|
|
32486
|
+
});
|
|
32296
32487
|
}
|
|
32297
32488
|
var init_recordings2 = __esm(() => {
|
|
32298
32489
|
init_helpers();
|
|
@@ -32386,7 +32577,7 @@ function register9(server) {
|
|
|
32386
32577
|
server.tool("browser_script_run", "Run a saved script asynchronously. Returns run_id immediately \u2014 poll with browser_script_status for step-by-step progress. Scripts combine browser actions + connector calls + AI reasoning. Works with any engine (Bun.WebView, Playwright, CDP).", {
|
|
32387
32578
|
name: exports_external2.string().describe("Script name"),
|
|
32388
32579
|
session_id: exports_external2.string().optional(),
|
|
32389
|
-
engine: exports_external2.enum(["playwright", "cdp", "lightpanda", "bun", "auto"]).optional().default("auto"),
|
|
32580
|
+
engine: exports_external2.enum(["playwright", "cdp", "lightpanda", "bun", "tui", "auto"]).optional().default("auto"),
|
|
32390
32581
|
variables: exports_external2.record(exports_external2.string()).optional().describe("Override script variables")
|
|
32391
32582
|
}, async ({ name, session_id, engine, variables }) => {
|
|
32392
32583
|
try {
|
|
@@ -32641,8 +32832,8 @@ import { join as join33 } from "path";
|
|
|
32641
32832
|
import { existsSync as existsSync43, mkdirSync as mkdirSync4, readFileSync as readFileSync33, writeFileSync as writeFileSync33 } from "fs";
|
|
32642
32833
|
import { homedir as homedir33 } from "os";
|
|
32643
32834
|
import { join as join43 } from "path";
|
|
32644
|
-
function
|
|
32645
|
-
this[name] =
|
|
32835
|
+
function __exportSetter2(name, newValue) {
|
|
32836
|
+
this[name] = __returnValue2.bind(null, newValue);
|
|
32646
32837
|
}
|
|
32647
32838
|
function isInMemoryDb(path) {
|
|
32648
32839
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
@@ -35756,13 +35947,13 @@ function clearActiveModel() {
|
|
|
35756
35947
|
delete config.activeModel;
|
|
35757
35948
|
writeConfig(config);
|
|
35758
35949
|
}
|
|
35759
|
-
var __defProp3,
|
|
35950
|
+
var __defProp3, __returnValue2 = (v) => v, __export3 = (target, all) => {
|
|
35760
35951
|
for (var name in all)
|
|
35761
35952
|
__defProp3(target, name, {
|
|
35762
35953
|
get: all[name],
|
|
35763
35954
|
enumerable: true,
|
|
35764
35955
|
configurable: true,
|
|
35765
|
-
set:
|
|
35956
|
+
set: __exportSetter2.bind(all, name)
|
|
35766
35957
|
});
|
|
35767
35958
|
}, __esm3 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), exports_database, MIGRATIONS, _db2 = null, init_database, AgentConflictError, EntityNotFoundError, MemoryNotFoundError, DuplicateMemoryError, MemoryExpiredError, InvalidScopeError, VersionConflictError, MemoryConflictError, OPENAI_EMBED_URL = "https://api.openai.com/v1/embeddings", EMBED_MODEL = "text-embedding-3-small", EMBED_DIMENSIONS = 1536, REDACTED = "[REDACTED]", SECRET_PATTERNS, _idCounter = 0, hookRegistry, INSTRUCTION_PATTERNS, PROMOTIONAL_PATTERNS, RECALL_PROMOTE_THRESHOLD = 3, CONFLICT_WINDOW_MS, MEMORY_WRITE_TTL = 30, MemoryLockConflictError, sessionFocus, STOP_WORDS, DEFAULT_CONFIG, VALID_SCOPES, VALID_CATEGORIES, defaultSyncAgents, DEFAULT_AUTO_MEMORY_CONFIG, MEMORY_EXTRACTION_SYSTEM_PROMPT = `You are a precise memory extraction engine for an AI agent.
|
|
35768
35959
|
Given text, extract facts worth remembering as structured JSON.
|
|
@@ -37285,11 +37476,11 @@ import { randomUUID as randomUUID22 } from "crypto";
|
|
|
37285
37476
|
import { readFileSync as readFileSync24, writeFileSync as writeFileSync7, mkdirSync as mkdirSync34 } from "fs";
|
|
37286
37477
|
import { join as join44, dirname as dirname24 } from "path";
|
|
37287
37478
|
import { homedir as homedir42 } from "os";
|
|
37288
|
-
function
|
|
37479
|
+
function __accessProp2(key) {
|
|
37289
37480
|
return this[key];
|
|
37290
37481
|
}
|
|
37291
|
-
function
|
|
37292
|
-
this[name] =
|
|
37482
|
+
function __exportSetter3(name, newValue) {
|
|
37483
|
+
this[name] = __returnValue3.bind(null, newValue);
|
|
37293
37484
|
}
|
|
37294
37485
|
function getDbPath3() {
|
|
37295
37486
|
if (process.env.CONVERSATIONS_DB_PATH)
|
|
@@ -39274,10 +39465,10 @@ function getGraphStats() {
|
|
|
39274
39465
|
map[r.relation] = r.c;
|
|
39275
39466
|
return { total_edges: total, by_relation: map };
|
|
39276
39467
|
}
|
|
39277
|
-
var __create3, __getProtoOf3, __defProp4, __getOwnPropNames3, __getOwnPropDesc2, __hasOwnProp3,
|
|
39468
|
+
var __create3, __getProtoOf3, __defProp4, __getOwnPropNames3, __getOwnPropDesc2, __hasOwnProp3, __toESMCache_node2, __toESMCache_esm2, __toESM3 = (mod, isNodeMode, target) => {
|
|
39278
39469
|
var canCache = mod != null && typeof mod === "object";
|
|
39279
39470
|
if (canCache) {
|
|
39280
|
-
var cache = isNodeMode ?
|
|
39471
|
+
var cache = isNodeMode ? __toESMCache_node2 ??= new WeakMap : __toESMCache_esm2 ??= new WeakMap;
|
|
39281
39472
|
var cached = cache.get(mod);
|
|
39282
39473
|
if (cached)
|
|
39283
39474
|
return cached;
|
|
@@ -39287,7 +39478,7 @@ var __create3, __getProtoOf3, __defProp4, __getOwnPropNames3, __getOwnPropDesc2,
|
|
|
39287
39478
|
for (let key of __getOwnPropNames3(mod))
|
|
39288
39479
|
if (!__hasOwnProp3.call(to, key))
|
|
39289
39480
|
__defProp4(to, key, {
|
|
39290
|
-
get:
|
|
39481
|
+
get: __accessProp2.bind(mod, key),
|
|
39291
39482
|
enumerable: true
|
|
39292
39483
|
});
|
|
39293
39484
|
if (canCache)
|
|
@@ -39302,19 +39493,19 @@ var __create3, __getProtoOf3, __defProp4, __getOwnPropNames3, __getOwnPropDesc2,
|
|
|
39302
39493
|
for (var key of __getOwnPropNames3(from))
|
|
39303
39494
|
if (!__hasOwnProp3.call(entry, key))
|
|
39304
39495
|
__defProp4(entry, key, {
|
|
39305
|
-
get:
|
|
39496
|
+
get: __accessProp2.bind(from, key),
|
|
39306
39497
|
enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
|
|
39307
39498
|
});
|
|
39308
39499
|
}
|
|
39309
39500
|
__moduleCache2.set(from, entry);
|
|
39310
39501
|
return entry;
|
|
39311
|
-
}, __moduleCache2, __commonJS3 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports),
|
|
39502
|
+
}, __moduleCache2, __commonJS3 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports), __returnValue3 = (v) => v, __export4 = (target, all) => {
|
|
39312
39503
|
for (var name in all)
|
|
39313
39504
|
__defProp4(target, name, {
|
|
39314
39505
|
get: all[name],
|
|
39315
39506
|
enumerable: true,
|
|
39316
39507
|
configurable: true,
|
|
39317
|
-
set:
|
|
39508
|
+
set: __exportSetter3.bind(all, name)
|
|
39318
39509
|
});
|
|
39319
39510
|
}, exports_db, db = null, init_db = () => {}, require_react_development, require_react, cachedConfig = null, configLoadedAt = 0, CONFIG_CACHE_MS = 1e4, import_react, AGENT_NAMES, AGENT_ID_FILE, cachedAutoName = null, ONLINE_THRESHOLD_SECONDS = 60, CONFLICT_THRESHOLD_SECONDS, DEFAULT_LOCK_EXPIRY_MS, STALE_HEARTBEAT_SECONDS, STOPWORDS;
|
|
39320
39511
|
var init_dist4 = __esm(() => {
|
|
@@ -41928,7 +42119,7 @@ import { existsSync as existsSync62 } from "fs";
|
|
|
41928
42119
|
import { join as join62 } from "path";
|
|
41929
42120
|
import { readFileSync as readFileSync43, statSync as statSync22 } from "fs";
|
|
41930
42121
|
import { relative as relative2, resolve as resolve23, join as join72 } from "path";
|
|
41931
|
-
import { execSync as
|
|
42122
|
+
import { execSync as execSync3 } from "child_process";
|
|
41932
42123
|
|
|
41933
42124
|
class TodosClient {
|
|
41934
42125
|
baseUrl;
|
|
@@ -46276,7 +46467,7 @@ function parseGitHubUrl(url) {
|
|
|
46276
46467
|
return { owner: match[1], repo: match[2], number: parseInt(match[3], 10) };
|
|
46277
46468
|
}
|
|
46278
46469
|
function fetchGitHubIssue(owner, repo, number) {
|
|
46279
|
-
const json2 =
|
|
46470
|
+
const json2 = execSync3(`gh api repos/${owner}/${repo}/issues/${number}`, { encoding: "utf-8", timeout: 15000 });
|
|
46280
46471
|
const data = JSON.parse(json2);
|
|
46281
46472
|
return {
|
|
46282
46473
|
number: data.number,
|
|
@@ -47870,7 +48061,8 @@ function register10(server) {
|
|
|
47870
48061
|
{ tool: "browser_screenshot", description: "Take a screenshot (PNG/JPEG/WebP, annotate=true for labels)" },
|
|
47871
48062
|
{ tool: "browser_pdf", description: "Generate a PDF of the page" },
|
|
47872
48063
|
{ tool: "browser_scroll_and_screenshot", description: "Scroll then screenshot in one call" },
|
|
47873
|
-
{ tool: "browser_scroll_to_element", description: "Scroll element into view + screenshot" }
|
|
48064
|
+
{ tool: "browser_scroll_to_element", description: "Scroll element into view + screenshot" },
|
|
48065
|
+
{ tool: "browser_diff", description: "Visual diff between two URLs \u2014 highlights changes in red" }
|
|
47874
48066
|
],
|
|
47875
48067
|
Storage: [
|
|
47876
48068
|
{ tool: "browser_cookies_get", description: "Get cookies" },
|
|
@@ -47895,7 +48087,8 @@ function register10(server) {
|
|
|
47895
48087
|
{ tool: "browser_intercept_clear", description: "Remove all response intercepts" }
|
|
47896
48088
|
],
|
|
47897
48089
|
Performance: [
|
|
47898
|
-
{ tool: "browser_performance", description: "Get performance metrics" }
|
|
48090
|
+
{ tool: "browser_performance", description: "Get performance metrics" },
|
|
48091
|
+
{ tool: "browser_performance_budget", description: "Check perf against budget thresholds (LCP, FCP, CLS, TTFB)" }
|
|
47899
48092
|
],
|
|
47900
48093
|
Console: [
|
|
47901
48094
|
{ tool: "browser_console_log", description: "Get console messages" },
|
|
@@ -47908,6 +48101,7 @@ function register10(server) {
|
|
|
47908
48101
|
{ tool: "browser_record_step", description: "Add a step to recording" },
|
|
47909
48102
|
{ tool: "browser_record_stop", description: "Stop and save recording" },
|
|
47910
48103
|
{ tool: "browser_record_replay", description: "Replay a recorded sequence" },
|
|
48104
|
+
{ tool: "browser_record_export", description: "Export recording as Playwright test, Puppeteer script, or JSON" },
|
|
47911
48105
|
{ tool: "browser_recordings_list", description: "List all recordings" }
|
|
47912
48106
|
],
|
|
47913
48107
|
Auth: [
|
|
@@ -49506,9 +49700,9 @@ ${entries.length} entries`));
|
|
|
49506
49700
|
});
|
|
49507
49701
|
program2.command("install-browser").description("Install a browser engine").option("--engine <engine>", "Engine to install: lightpanda|chromium", "chromium").action(async (opts) => {
|
|
49508
49702
|
if (opts.engine === "chromium") {
|
|
49509
|
-
const { execSync:
|
|
49703
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
49510
49704
|
console.log(chalk4.gray("Installing Chromium via Playwright..."));
|
|
49511
|
-
|
|
49705
|
+
execSync4("bunx playwright install chromium", { stdio: "inherit" });
|
|
49512
49706
|
console.log(chalk4.green("\u2713 Chromium installed"));
|
|
49513
49707
|
} else if (opts.engine === "lightpanda") {
|
|
49514
49708
|
console.log(chalk4.yellow("Lightpanda must be installed manually."));
|
|
@@ -49528,12 +49722,12 @@ ${entries.length} entries`));
|
|
|
49528
49722
|
console.log(chalk4.gray(` PID: ${status.pid}, Port: ${status.port}, Sessions: ${status.sessions ?? "?"}`));
|
|
49529
49723
|
return;
|
|
49530
49724
|
}
|
|
49531
|
-
const { spawn:
|
|
49725
|
+
const { spawn: spawn3 } = await import("child_process");
|
|
49532
49726
|
const { writeFileSync: writeFileSync9, mkdirSync: mkdirSync17 } = await import("fs");
|
|
49533
49727
|
const { dirname: dirname6 } = await import("path");
|
|
49534
49728
|
const pidFile = getDaemonPidFile2();
|
|
49535
49729
|
mkdirSync17(dirname6(pidFile), { recursive: true });
|
|
49536
|
-
const child =
|
|
49730
|
+
const child = spawn3(process.execPath, [import.meta.dir + "/../../server/index.js"], {
|
|
49537
49731
|
detached: true,
|
|
49538
49732
|
stdio: "ignore",
|
|
49539
49733
|
env: { ...process.env, BROWSER_SERVER_PORT: opts.port }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/engines/selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/engines/selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAkC5C;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,aAAa,GACvB,aAAa,CAqBf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAQhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CA4BnD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
import type { Browser, Page } from "playwright";
|
|
3
|
+
export interface TuiSession {
|
|
4
|
+
ttydProcess: ChildProcess;
|
|
5
|
+
port: number;
|
|
6
|
+
browser: Browser;
|
|
7
|
+
page: Page;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Check if ttyd is installed on this system.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isTuiAvailable(): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Launch a terminal app via ttyd and connect Playwright to it.
|
|
15
|
+
*
|
|
16
|
+
* @param command - The shell command to run (e.g. "htop", "npm start", "python app.py")
|
|
17
|
+
* @param options - Viewport and headless options
|
|
18
|
+
* @returns TuiSession with Playwright page connected to the ttyd web UI
|
|
19
|
+
*/
|
|
20
|
+
export declare function launchTui(command: string, options?: {
|
|
21
|
+
headless?: boolean;
|
|
22
|
+
viewport?: {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
};
|
|
26
|
+
}): Promise<TuiSession>;
|
|
27
|
+
/**
|
|
28
|
+
* Send keystrokes to the TUI app via the Playwright page.
|
|
29
|
+
* Types into the terminal's xterm.js input.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sendKeys(page: Page, keys: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Send a special key (Enter, Escape, ArrowUp, etc.) to the TUI.
|
|
34
|
+
*/
|
|
35
|
+
export declare function sendSpecialKey(page: Page, key: string): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Get the visible text content from the terminal.
|
|
38
|
+
* Works with both canvas-based and DOM-based xterm.js renderers.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getTerminalText(page: Page): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Wait for specific text to appear in the terminal output.
|
|
43
|
+
*/
|
|
44
|
+
export declare function waitForTerminalText(page: Page, text: string, timeoutMs?: number): Promise<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* Close TUI session — kill ttyd and close Playwright.
|
|
47
|
+
*/
|
|
48
|
+
export declare function closeTui(session: TuiSession): Promise<void>;
|
|
49
|
+
//# sourceMappingURL=tui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../src/engines/tui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAYhD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,YAAY,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;CACZ;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAOxC;AAqCD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,GACL,OAAO,CAAC,UAAU,CAAC,CAqDrB;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAStE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO3E;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBjE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAe,GACzB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAUjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.test.d.ts","sourceRoot":"","sources":["../../src/engines/tui.test.ts"],"names":[],"mappings":""}
|