ptywright 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -107,7 +107,7 @@ bunx ptywright@latest pty validate tests/cassettes/codex.pty.json
107
107
  bunx ptywright@latest pty inspect tests/cassettes/codex.pty.json
108
108
  ```
109
109
 
110
- External projects do not need to depend on aitty. Use the structural
110
+ External projects do not need a ptywright-specific PTY wrapper. Use the structural
111
111
  `wrapPtyLike` API for `node-pty`/`bun-pty` style objects:
112
112
 
113
113
  ```ts
@@ -308,9 +308,10 @@ Recording artifacts are best for failure diagnosis or manual review; prefer `sna
308
308
 
309
309
  ## Browser Agent Regression
310
310
 
311
- The new destructive path is browser-first: ptywright can launch an agent through
312
- `@aitty/cli`, drive the browser-hosted wterm DOM with Playwright, and persist a
313
- replayable run artifact plus terminal/DOM snapshots.
311
+ The browser-first path is integration-agnostic: ptywright launches any command
312
+ that prints a browser URL, drives the terminal DOM with Playwright, and persists
313
+ a replayable run artifact plus terminal/DOM snapshots. The browser page must
314
+ expose the terminal root as `[data-terminal-root]`.
314
315
 
315
316
  ```bash
316
317
  # First run records snapshots, screenshots, replay metadata, and report.
@@ -379,9 +380,77 @@ Artifacts are split intentionally:
379
380
  - `tests/agent-snapshots/<name>/` contains stable terminal/DOM baselines.
380
381
  - `--update-snapshots` is the explicit update path for intentional UI changes.
381
382
 
382
- `launch.mode=aitty` runs `aitty exec --launch print -- <agent>`. By default
383
- ptywright resolves the sibling `../aitty/packages/cli/dist/cli.js`; set
384
- `PTYWRIGHT_AITTY_CLI` or `launch.aitty.command` to override it.
383
+ ### Project Config
384
+
385
+ For repeated agent regression work, put project-level defaults in
386
+ `ptywright.config.ts` instead of repeating paths and browser defaults in every
387
+ flow file. The CLI discovers `ptywright.config.ts|mts|cts|js|mjs|cjs` from the
388
+ current directory upward, and `--config <file>` selects one explicitly.
389
+
390
+ ```ts
391
+ import { defineConfig } from "ptywright/config";
392
+
393
+ export default defineConfig({
394
+ agent: {
395
+ artifactsRoot: ".tmp/agent",
396
+ cassetteDir: "tests/agent-cassettes",
397
+ snapshotDir: "tests/agent-snapshots",
398
+ defaults: {
399
+ headless: true,
400
+ timeoutMs: 45_000,
401
+ screenshot: false,
402
+ viewports: [{ name: "desktop", width: 1280, height: 820 }],
403
+ mask: [{ regex: "session_[a-z0-9]+", replacement: "<session>" }],
404
+ },
405
+ },
406
+ });
407
+ ```
408
+
409
+ ```bash
410
+ ptywright agent run tests/agents/codex.flow.json --update-snapshots
411
+ ptywright agent check
412
+ ptywright agent replay-all --update-snapshots
413
+ ptywright agent promote .tmp/agent/codex/codex.cassette.json --update-snapshots
414
+ ```
415
+
416
+ Config paths are resolved relative to the config file directory. CLI arguments
417
+ override config defaults, and fields written in a flow file override config
418
+ defaults for that flow. The flow file remains the test case; the config file is
419
+ only for shared project defaults and common artifact locations.
420
+
421
+ `launch.mode=command` is the recommended integration contract. `command` and
422
+ `args` are spawned directly, and ptywright reads the first URL printed to stdout
423
+ or stderr. Use `waitForUrlMs` to tune startup timeouts and `urlRegex` when the
424
+ URL is embedded in structured output. Set `launch.agentFlavor` explicitly when
425
+ the command is a wrapper, so mask presets still match the underlying agent.
426
+
427
+ `launch.mode=url` skips process launch and points ptywright at an already
428
+ running browser terminal.
429
+
430
+ A wrapper integration is just a normal command that prints its browser URL:
431
+
432
+ ```json
433
+ {
434
+ "name": "codex_browser_replay",
435
+ "launch": {
436
+ "mode": "command",
437
+ "agentFlavor": "codex",
438
+ "command": "node_modules/.bin/browser-terminal-launcher",
439
+ "args": [
440
+ "--replay",
441
+ "test/recordings/codex-yolo.pty.json",
442
+ "--speed",
443
+ "0",
444
+ "--print-url"
445
+ ],
446
+ "waitForUrlMs": 15000
447
+ },
448
+ "steps": [
449
+ { "type": "waitForStableDom" },
450
+ { "type": "snapshot", "name": "codex", "targets": ["terminal", "dom"] }
451
+ ]
452
+ }
453
+ ```
385
454
 
386
455
  Set `launch.agentFlavor` to `codex`, `claude`, `droid`, or `generic` to opt
387
456
  into built-in mask presets for timestamps, generated ids, model names, token
package/dist/agent.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as runAgentSpecPath, i as runAgentSpec, n as printAittyLaunchPlan, r as replayAgentRecordPath, t as defaultSpecNameForPath } from "./runner-DzZlFrt1.mjs";
2
- export { defaultSpecNameForPath, printAittyLaunchPlan, replayAgentRecordPath, runAgentSpec, runAgentSpecPath };
1
+ import { a as runAgentSpecPath, i as runAgentSpec, n as printAgentLaunchPlan, r as replayAgentRecordPath, t as defaultSpecNameForPath } from "./runner-CembqDgJ.mjs";
2
+ export { defaultSpecNameForPath, printAgentLaunchPlan, replayAgentRecordPath, runAgentSpec, runAgentSpecPath };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { t as main } from "../cli-DIUx2w6X.mjs";
2
+ import { t as main } from "../cli-C40H_ElC.mjs";
3
3
  //#region src/bin/ptywright.ts
4
4
  await main();
5
5
  //#endregion
@@ -1,7 +1,8 @@
1
1
  import { c as createDefaultPtyAdapter, l as resolvePtyBackend } from "./runner-zApMYWZx.mjs";
2
- import { a as readScriptManifestPath, c as resolveScriptManifestPath, d as resolveScriptRunSummaryPath, f as runScriptPath, i as findScriptSummaryManifest, l as validateScriptManifest, n as runAllScripts, o as relocateScriptManifestCommands, s as resolveManifestPrimaryPath$1, t as createPtywrightServer, u as readScriptRunSummaryPath } from "./server-VHuEWWj_.mjs";
3
- import { C as isAgentManifestLike, E as writeAgentManifestPath, S as agentManifestPath, T as validateAgentManifestFiles, _ as normalizeAgentFlowSpec, a as runAgentSpecPath, b as launchAittyBrowserSession, c as agentRunModeSchema, d as readAgentRunRecordPath, f as writeAgentRunRecordPath, g as readAgentCassettePath, h as isAgentCassetteLike, l as formatAgentArgv, m as createAgentTemplateSpec, o as loadAgentSpec, p as formatArgv, r as replayAgentRecordPath, s as AGENT_RUN_RECORD_SCHEMA_URL, u as isAgentRunRecordLike, v as sanitizeArtifactName, w as readAgentManifestPath, x as AGENT_MANIFEST_FILE_NAME, y as launchAgentBrowser } from "./runner-DzZlFrt1.mjs";
4
- import { c as createPtyCassetteReplay, i as formatPtyCassetteInspectLines, l as readPtyCassettePath, o as inspectPtyCassettePath, r as createPtyCassetteRecorder, t as wrapPtyLike, v as validatePtyCassette } from "./pty_like-Cpkh_O9B.mjs";
2
+ import { a as readScriptManifestPath, c as resolveScriptManifestPath, d as resolveScriptRunSummaryPath, f as runScriptPath, i as findScriptSummaryManifest, l as validateScriptManifest, n as runAllScripts, o as relocateScriptManifestCommands, s as resolveManifestPrimaryPath$1, t as createPtywrightServer, u as readScriptRunSummaryPath } from "./server-h--2U0Ic.mjs";
3
+ import { C as agentManifestPath, D as writeAgentManifestPath, E as validateAgentManifestFiles, S as AGENT_MANIFEST_FILE_NAME, T as readAgentManifestPath, _ as isAgentCassetteLike, a as runAgentSpecPath, b as sanitizeArtifactName, c as agentRunModeSchema, d as readAgentRunRecordPath, f as writeAgentRunRecordPath, g as normalizeAgentFlowSpecWithConfig, h as resolveAgentLaunchTarget, l as formatAgentArgv, m as createAgentTemplateSpec, o as loadAgentSpec, p as formatArgv, r as replayAgentRecordPath, s as AGENT_RUN_RECORD_SCHEMA_URL, u as isAgentRunRecordLike, v as readAgentCassettePath, w as isAgentManifestLike, x as launchAgentBrowser, y as normalizeAgentFlowSpec } from "./runner-CembqDgJ.mjs";
4
+ import { n as loadPtywrightConfig } from "./config-B0r-JCFI.mjs";
5
+ import { c as createPtyCassetteReplay, i as formatPtyCassetteInspectLines, l as readPtyCassettePath, o as inspectPtyCassettePath, r as createPtyCassetteRecorder, t as wrapPtyLike, v as validatePtyCassette } from "./pty_like-DqCo7XdB.mjs";
5
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
7
  import { z } from "zod";
7
8
  import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
@@ -1901,7 +1902,7 @@ async function promoteAgentCassette(options) {
1901
1902
  const sourceCassette = readAgentCassettePath(resolveSourceCassettePath(resolve(process.cwd(), options.sourcePath)));
1902
1903
  const name = sanitizeArtifactName(sourceCassette.name);
1903
1904
  const cassetteDir = options.cassetteDir ?? "tests/agent-cassettes";
1904
- const snapshotDir = options.snapshotDir ?? join("tests", "agent-snapshots", name);
1905
+ const snapshotDir = options.snapshotDir ?? join(options.snapshotRoot ?? "tests/agent-snapshots", name);
1905
1906
  const artifactsRoot = options.artifactsRoot ?? join(".tmp", "agent-promote", name);
1906
1907
  const targetDir = join(cassetteDir, name);
1907
1908
  const targetCassettePath = join(targetDir, `${name}.cassette.json`);
@@ -2130,18 +2131,16 @@ function emptyReplayResult(dir, suiteDir, updateSnapshots) {
2130
2131
  //#endregion
2131
2132
  //#region src/agent/recorder.ts
2132
2133
  async function recordAgentSpecPath(specPath, options) {
2133
- return recordAgentSpec((await loadAgentSpec(specPath)).spec, options);
2134
+ return recordAgentSpec((await loadAgentSpec(specPath)).raw, options);
2134
2135
  }
2135
2136
  async function recordAgentSpec(input, options) {
2136
- const spec = normalizeAgentFlowSpec(input);
2137
+ const spec = normalizeAgentFlowSpecWithConfig(input, options.config);
2137
2138
  const rootDir = options.rootDir ? resolve(process.cwd(), options.rootDir) : process.cwd();
2138
- const launchMode = spec.launch.mode ?? (spec.launch.url ? "url" : "aitty");
2139
2139
  const outPath = isAbsolute(options.outPath) ? options.outPath : resolve(process.cwd(), options.outPath);
2140
2140
  const durationMs = options.durationMs ?? 3e4;
2141
2141
  const steps = [];
2142
2142
  let browser = null;
2143
- const session = launchMode === "aitty" ? await launchAittyBrowserSession(spec.launch, { rootDir }) : null;
2144
- const url = launchMode === "url" ? spec.launch.url : session.url;
2143
+ const launchTarget = await resolveAgentLaunchTarget(spec.launch, { rootDir });
2145
2144
  try {
2146
2145
  browser = await launchAgentBrowser({ headless: options.headless ?? false });
2147
2146
  const viewport = spec.viewports?.[0] ?? {
@@ -2160,7 +2159,7 @@ async function recordAgentSpec(input, options) {
2160
2159
  });
2161
2160
  const page = await context.newPage();
2162
2161
  await installRecorderHooks(page);
2163
- await page.goto(url, {
2162
+ await page.goto(launchTarget.url, {
2164
2163
  waitUntil: "domcontentloaded",
2165
2164
  timeout: spec.defaults?.timeoutMs ?? 3e4
2166
2165
  });
@@ -2198,19 +2197,19 @@ async function recordAgentSpec(input, options) {
2198
2197
  ok: true,
2199
2198
  outPath,
2200
2199
  stepCount: recorded.steps.length,
2201
- url
2200
+ url: launchTarget.url
2202
2201
  };
2203
2202
  } catch (error) {
2204
2203
  return {
2205
2204
  ok: false,
2206
2205
  outPath,
2207
2206
  stepCount: steps.length,
2208
- url,
2207
+ url: launchTarget.url,
2209
2208
  error: error instanceof Error ? error.message : String(error)
2210
2209
  };
2211
2210
  } finally {
2212
2211
  await browser?.close();
2213
- await session?.close();
2212
+ await launchTarget.session?.close();
2214
2213
  }
2215
2214
  }
2216
2215
  async function installRecorderHooks(page) {
@@ -2925,6 +2924,7 @@ function usage() {
2925
2924
  " --json Print machine-readable script artifact output",
2926
2925
  "",
2927
2926
  "Agent options:",
2927
+ " --config <file> Use a ptywright.config.* file",
2928
2928
  " --artifacts-dir <dir> Override agent run artifact directory",
2929
2929
  " --cassette-dir <dir> Committed cassette directory for promote/check",
2930
2930
  " --snapshot-dir <dir> Snapshot directory for promoted cassettes",
@@ -3266,6 +3266,12 @@ function parseAgentArgs(argv) {
3266
3266
  out.flavor = parseAgentFlavor(arg);
3267
3267
  continue;
3268
3268
  }
3269
+ if (arg === "--config") {
3270
+ if (!next) throw new Error(`missing <file> for --config`);
3271
+ out.configPath = next;
3272
+ i += 1;
3273
+ continue;
3274
+ }
3269
3275
  if (arg === "--artifacts-root" && next) {
3270
3276
  out.artifactsRoot = next;
3271
3277
  i += 1;
@@ -3336,13 +3342,32 @@ function parseAgentArgs(argv) {
3336
3342
  outPath: out.outPath,
3337
3343
  durationMs: out.durationMs,
3338
3344
  commandName: out.commandName,
3345
+ configPath: out.configPath,
3339
3346
  updateSnapshots: out.updateSnapshots,
3340
3347
  headed: out.headed,
3341
3348
  json: out.json
3342
3349
  };
3343
3350
  }
3351
+ function shouldLoadAgentConfig(mode) {
3352
+ return mode === "run" || mode === "record" || mode === "replay" || mode === "promote" || mode === "replay-all" || mode === "rerun" || mode === "check";
3353
+ }
3354
+ function resolveAgentHeadless(args, config) {
3355
+ if (args.headed) return false;
3356
+ return config?.agent?.defaults?.headless ?? true;
3357
+ }
3358
+ function resolveAgentConfigPath(config, path) {
3359
+ if (!path) return void 0;
3360
+ if (isAbsolute(path)) return path;
3361
+ return resolve(config?.rootDir ?? process.cwd(), path);
3362
+ }
3363
+ function resolveCliPath(path) {
3364
+ if (!path) return void 0;
3365
+ return isAbsolute(path) ? path : resolve(process.cwd(), path);
3366
+ }
3344
3367
  async function cmdAgent(argv) {
3345
3368
  const args = parseAgentArgs(argv);
3369
+ const config = shouldLoadAgentConfig(args.mode) ? await loadPtywrightConfig({ configPath: args.configPath }) : void 0;
3370
+ const headless = resolveAgentHeadless(args, config);
3346
3371
  if (args.mode === "init") {
3347
3372
  const spec = createAgentTemplateSpec(args.flavor ?? "generic");
3348
3373
  const path = args.path;
@@ -3358,7 +3383,8 @@ async function cmdAgent(argv) {
3358
3383
  const result = await recordAgentSpecPath(args.path, {
3359
3384
  outPath: args.outPath,
3360
3385
  durationMs: args.durationMs,
3361
- headless: !args.headed
3386
+ headless,
3387
+ config
3362
3388
  });
3363
3389
  logLines([
3364
3390
  `${result.ok ? "ok" : "failed"} record=${result.outPath}`,
@@ -3422,13 +3448,17 @@ async function cmdAgent(argv) {
3422
3448
  const argv = selected.command.argv;
3423
3449
  validateAgentCommandArgv(argv, selected.name);
3424
3450
  const [, , subcommand, ...rest] = argv;
3425
- return cmdAgent([subcommand ?? "", ...rest]);
3451
+ return cmdAgent([
3452
+ subcommand ?? "",
3453
+ ...rest,
3454
+ ...args.configPath ? ["--config", args.configPath] : []
3455
+ ]);
3426
3456
  }
3427
3457
  if (args.mode === "check") {
3428
3458
  const result = await checkAgentRegression({
3429
- cassetteDir: args.path ?? args.cassetteDir,
3430
- artifactsRoot: args.artifactsRoot,
3431
- headless: !args.headed,
3459
+ cassetteDir: args.path ?? args.cassetteDir ?? resolveAgentConfigPath(config, config?.agent?.cassetteDir),
3460
+ artifactsRoot: args.artifactsRoot ?? resolveAgentConfigPath(config, config?.agent?.artifactsRoot),
3461
+ headless,
3432
3462
  updateSnapshots: args.updateSnapshots
3433
3463
  });
3434
3464
  if (args.json) logLines([JSON.stringify(formatAgentCheckJson(result), null, 2)], false);
@@ -3438,10 +3468,11 @@ async function cmdAgent(argv) {
3438
3468
  if (args.mode === "promote") {
3439
3469
  const result = await promoteAgentCassette({
3440
3470
  sourcePath: args.path,
3441
- cassetteDir: args.cassetteDir,
3471
+ cassetteDir: args.cassetteDir ?? resolveAgentConfigPath(config, config?.agent?.cassetteDir),
3442
3472
  snapshotDir: args.snapshotDir,
3443
- artifactsRoot: args.artifactsRoot,
3444
- headless: !args.headed,
3473
+ snapshotRoot: args.snapshotDir ? void 0 : resolveAgentConfigPath(config, config?.agent?.snapshotDir),
3474
+ artifactsRoot: args.artifactsRoot ?? resolveAgentConfigPath(config, config?.agent?.artifactsRoot),
3475
+ headless,
3445
3476
  updateSnapshots: args.updateSnapshots
3446
3477
  });
3447
3478
  if (args.json) logLines([JSON.stringify(formatAgentPromoteSummary(result), null, 2)], false);
@@ -3451,8 +3482,8 @@ async function cmdAgent(argv) {
3451
3482
  if (args.mode === "rerun") {
3452
3483
  const rerun = await rerunAgentSummary({
3453
3484
  path: args.path,
3454
- artifactsRoot: args.artifactsRoot,
3455
- headless: !args.headed,
3485
+ artifactsRoot: args.artifactsRoot ?? resolveAgentConfigPath(config, config?.agent?.artifactsRoot),
3486
+ headless,
3456
3487
  updateSnapshots: args.updateSnapshots
3457
3488
  });
3458
3489
  if (rerun.kind === "check-summary") {
@@ -3482,9 +3513,9 @@ async function cmdAgent(argv) {
3482
3513
  }
3483
3514
  if (args.mode === "replay-all") {
3484
3515
  const result = await replayAllAgentRecords({
3485
- dir: args.path,
3486
- artifactsRoot: args.artifactsRoot,
3487
- headless: !args.headed,
3516
+ dir: args.path ?? resolveAgentConfigPath(config, config?.agent?.cassetteDir),
3517
+ artifactsRoot: args.artifactsRoot ?? resolveAgentConfigPath(config, config?.agent?.artifactsRoot),
3518
+ headless,
3488
3519
  updateSnapshots: args.updateSnapshots
3489
3520
  });
3490
3521
  const failures = result.entries.filter((entry) => !entry.result.ok);
@@ -3509,9 +3540,10 @@ async function cmdAgent(argv) {
3509
3540
  return 1;
3510
3541
  }
3511
3542
  const options = {
3512
- artifactsDir: args.artifactsDir,
3543
+ artifactsDir: resolveCliPath(args.artifactsDir),
3513
3544
  updateSnapshots: args.updateSnapshots,
3514
- headless: !args.headed
3545
+ headless,
3546
+ config
3515
3547
  };
3516
3548
  const result = args.mode === "run" ? await runAgentSpecPath(args.path, options) : await replayAgentRecordPath(args.path, options);
3517
3549
  if (args.json) {
package/dist/cli.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as main } from "./cli-DIUx2w6X.mjs";
1
+ import { t as main } from "./cli-C40H_ElC.mjs";
2
2
  export { main };
@@ -0,0 +1,52 @@
1
+ import { dirname, isAbsolute, resolve } from "node:path";
2
+ import { pathToFileURL } from "node:url";
3
+ import { existsSync } from "node:fs";
4
+ //#region src/config.ts
5
+ const CONFIG_FILE_NAMES = [
6
+ "ptywright.config.ts",
7
+ "ptywright.config.mts",
8
+ "ptywright.config.cts",
9
+ "ptywright.config.js",
10
+ "ptywright.config.mjs",
11
+ "ptywright.config.cjs"
12
+ ];
13
+ function defineConfig(config) {
14
+ return config;
15
+ }
16
+ async function loadPtywrightConfig(options = {}) {
17
+ const cwd = resolve(options.cwd ?? process.cwd());
18
+ const configPath = resolveConfigPath({
19
+ cwd,
20
+ configPath: options.configPath
21
+ });
22
+ if (!configPath) return { rootDir: cwd };
23
+ const mod = await import(`${pathToFileURL(configPath).href}?t=${Date.now()}`);
24
+ return {
25
+ ...normalizePtywrightConfig(mod.default ?? mod.config, configPath),
26
+ configPath,
27
+ rootDir: dirname(configPath)
28
+ };
29
+ }
30
+ function resolveConfigPath(options) {
31
+ if (options.configPath) {
32
+ const explicitPath = isAbsolute(options.configPath) ? options.configPath : resolve(options.cwd, options.configPath);
33
+ if (!existsSync(explicitPath)) throw new Error(`ptywright config not found: ${options.configPath}`);
34
+ return explicitPath;
35
+ }
36
+ let current = options.cwd;
37
+ while (true) {
38
+ for (const fileName of CONFIG_FILE_NAMES) {
39
+ const candidate = resolve(current, fileName);
40
+ if (existsSync(candidate)) return candidate;
41
+ }
42
+ const parent = dirname(current);
43
+ if (parent === current) return;
44
+ current = parent;
45
+ }
46
+ }
47
+ function normalizePtywrightConfig(input, configPath) {
48
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error(`invalid ptywright config: expected object in ${configPath}`);
49
+ return input;
50
+ }
51
+ //#endregion
52
+ export { loadPtywrightConfig as n, defineConfig as t };
@@ -0,0 +1,2 @@
1
+ import { n as loadPtywrightConfig, t as defineConfig } from "./config-B0r-JCFI.mjs";
2
+ export { defineConfig, loadPtywrightConfig };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as createPtywrightServer } from "./server-VHuEWWj_.mjs";
1
+ import { t as createPtywrightServer } from "./server-h--2U0Ic.mjs";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  //#region src/index.ts
4
4
  const { server, sessions } = createPtywrightServer();
package/dist/mcp.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createPtywrightServer } from "./server-VHuEWWj_.mjs";
1
+ import { t as createPtywrightServer } from "./server-h--2U0Ic.mjs";
2
2
  export { createPtywrightServer };
@@ -1,4 +1,4 @@
1
- import { S as dataToBytes, _ as ptyCassetteSchema, a as inspectPtyCassette, b as byteLength, c as createPtyCassetteReplay, d as PTY_CASSETTE_SCHEMA_URL, f as normalizePtyCassette, g as ptyCassetteResizeEventSchema, h as ptyCassetteExitEventSchema, i as formatPtyCassetteInspectLines, l as readPtyCassettePath, m as ptyCassetteEventSchema, n as PtyCassetteRecorder, o as inspectPtyCassettePath, p as ptyCassetteDataEventSchema, r as createPtyCassetteRecorder, s as PtyCassetteReplay, t as wrapPtyLike, u as writePtyCassettePath, v as validatePtyCassette, x as dataToBase64, y as base64ToBytes } from "./pty_like-Cpkh_O9B.mjs";
1
+ import { S as dataToBytes, _ as ptyCassetteSchema, a as inspectPtyCassette, b as byteLength, c as createPtyCassetteReplay, d as PTY_CASSETTE_SCHEMA_URL, f as normalizePtyCassette, g as ptyCassetteResizeEventSchema, h as ptyCassetteExitEventSchema, i as formatPtyCassetteInspectLines, l as readPtyCassettePath, m as ptyCassetteEventSchema, n as PtyCassetteRecorder, o as inspectPtyCassettePath, p as ptyCassetteDataEventSchema, r as createPtyCassetteRecorder, s as PtyCassetteReplay, t as wrapPtyLike, u as writePtyCassettePath, v as validatePtyCassette, x as dataToBase64, y as base64ToBytes } from "./pty_like-DqCo7XdB.mjs";
2
2
  //#region src/pty-cassette/bun_terminal.ts
3
3
  function wrapBunTerminalOptions(options, recorder) {
4
4
  const onData = options.data;