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 +76 -7
- package/dist/agent.mjs +2 -2
- package/dist/bin/ptywright.mjs +1 -1
- package/dist/{cli-DIUx2w6X.mjs → cli-C40H_ElC.mjs} +60 -28
- package/dist/cli.mjs +1 -1
- package/dist/config-B0r-JCFI.mjs +52 -0
- package/dist/config.mjs +2 -0
- package/dist/index.mjs +1 -1
- package/dist/mcp.mjs +1 -1
- package/dist/pty-cassette.mjs +1 -1
- package/dist/{runner-DzZlFrt1.mjs → runner-CembqDgJ.mjs} +211 -185
- package/dist/{server-VHuEWWj_.mjs → server-h--2U0Ic.mjs} +1 -1
- package/package.json +2 -1
- package/schemas/ptywright-agent.schema.json +3 -19
- package/skills/ptywright-testing/SKILL.md +113 -79
- package/skills/ptywright-testing/agents/openai.yaml +4 -0
- package/skills/ptywright-testing/references/agent-regression.md +132 -0
- package/skills/ptywright-testing/references/ci-and-debugging.md +95 -0
- package/skills/ptywright-testing/references/mcp-tools.md +91 -0
- package/skills/ptywright-testing/references/raw-pty-cassettes.md +82 -0
- package/skills/ptywright-testing/references/script-runner.md +80 -0
- /package/dist/{pty_like-Cpkh_O9B.mjs → pty_like-DqCo7XdB.mjs} +0 -0
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
|
|
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
|
|
312
|
-
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
|
2
|
-
export { defaultSpecNameForPath,
|
|
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 };
|
package/dist/bin/ptywright.mjs
CHANGED
|
@@ -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-
|
|
3
|
-
import { C as
|
|
4
|
-
import {
|
|
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
|
|
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)).
|
|
2134
|
+
return recordAgentSpec((await loadAgentSpec(specPath)).raw, options);
|
|
2134
2135
|
}
|
|
2135
2136
|
async function recordAgentSpec(input, options) {
|
|
2136
|
-
const spec =
|
|
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
|
|
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
|
|
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([
|
|
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
|
|
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
|
-
|
|
3444
|
-
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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 };
|
package/dist/config.mjs
ADDED
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createPtywrightServer } from "./server-
|
|
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-
|
|
1
|
+
import { t as createPtywrightServer } from "./server-h--2U0Ic.mjs";
|
|
2
2
|
export { createPtywrightServer };
|
package/dist/pty-cassette.mjs
CHANGED
|
@@ -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-
|
|
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;
|