ptywright 0.5.0 → 0.6.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/agent.mjs +1 -1
- package/dist/bin/ptywright.mjs +1 -1
- package/dist/{cli-PnG6UR43.mjs → cli-XLR4BPhA.mjs} +5 -5
- package/dist/cli.mjs +1 -1
- package/dist/data-sdbf3IDh.mjs +18 -0
- package/dist/index.mjs +1 -1
- package/dist/mcp.mjs +1 -1
- package/dist/pty-cassette.mjs +2 -1
- package/dist/{pty_like-BjeBibSL.mjs → pty_like-DWIlWGgA.mjs} +2 -18
- package/dist/{runner-wW_DCBX7.mjs → runner-BHXXwxYp.mjs} +3 -2
- package/dist/{runner-C1gPRyCM.mjs → runner-XEimk7TO.mjs} +491 -40
- package/dist/script.mjs +1 -1
- package/dist/{server-DMnnXjWv.mjs → server-COuf3mW7.mjs} +2 -2
- package/dist/session.mjs +1 -1
- package/dist/style-BtIUv5H0.mjs +65 -0
- package/dist/{terminal_session-DJKr-O3X.mjs → terminal_session-MX_vWpRG.mjs} +2 -65
- package/package.json +1 -1
package/dist/agent.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as formatAgentLaunchPlan, i as runAgentSpecPath, n as replayAgentRecordPath, r as runAgentSpec, t as defaultSpecNameForPath } from "./runner-
|
|
1
|
+
import { a as formatAgentLaunchPlan, i as runAgentSpecPath, n as replayAgentRecordPath, r as runAgentSpec, t as defaultSpecNameForPath } from "./runner-XEimk7TO.mjs";
|
|
2
2
|
export { defaultSpecNameForPath, formatAgentLaunchPlan, replayAgentRecordPath, runAgentSpec, runAgentSpecPath };
|
package/dist/bin/ptywright.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { n as loadPtywrightConfig } from "./config-bGg636EW.mjs";
|
|
2
|
-
import { C as writeAgentManifestPath, D as escapeHtml, E as escapeAttribute, O as normalizeAgentFlowSpec, S as validateAgentManifestFiles, T as readAgentCassettePath, _ as formatArgv, b as isAgentManifestLike, c as launchAgentBrowser, d as AGENT_RUN_RECORD_SCHEMA_URL, f as agentRunModeSchema, g as writeAgentRunRecordPath, h as readAgentRunRecordPath, i as runAgentSpecPath, k as sanitizeArtifactName, l as createAgentTemplateSpec, m as isAgentRunRecordLike, n as replayAgentRecordPath, o as resolveAgentLaunchTarget, p as formatAgentArgv, s as normalizeAgentFlowSpecWithConfig, u as loadAgentSpec, v as AGENT_MANIFEST_FILE_NAME, w as isAgentCassetteLike, x as readAgentManifestPath, y as agentManifestPath } from "./runner-
|
|
2
|
+
import { C as writeAgentManifestPath, D as escapeHtml, E as escapeAttribute, O as normalizeAgentFlowSpec, S as validateAgentManifestFiles, T as readAgentCassettePath, _ as formatArgv, b as isAgentManifestLike, c as launchAgentBrowser, d as AGENT_RUN_RECORD_SCHEMA_URL, f as agentRunModeSchema, g as writeAgentRunRecordPath, h as readAgentRunRecordPath, i as runAgentSpecPath, k as sanitizeArtifactName, l as createAgentTemplateSpec, m as isAgentRunRecordLike, n as replayAgentRecordPath, o as resolveAgentLaunchTarget, p as formatAgentArgv, s as normalizeAgentFlowSpecWithConfig, u as loadAgentSpec, v as AGENT_MANIFEST_FILE_NAME, w as isAgentCassetteLike, x as readAgentManifestPath, y as agentManifestPath } from "./runner-XEimk7TO.mjs";
|
|
3
3
|
import { a as sameArgv, i as diffCommandMaps, r as formatZodIssues } from "./manifest_files-DW80c1H7.mjs";
|
|
4
4
|
import { i as portableCliPath, n as mergeProcessEnv, o as relativeHref, s as samePath } from "./env-DPYHo-zH.mjs";
|
|
5
|
-
import { d as resolvePtyBackend, u as createDefaultPtyAdapter } from "./runner-
|
|
6
|
-
import { a as resolveScriptManifestPath, c as relocateScriptManifestCommands, d as resolveScriptRunSummaryPath, f as runScriptPath, i as readScriptManifestPath, l as resolveManifestPrimaryPath$1, n as runAllScripts, o as validateScriptManifest, r as findScriptSummaryManifest, t as createPtywrightServer, u as readScriptRunSummaryPath } from "./server-
|
|
7
|
-
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-
|
|
5
|
+
import { d as resolvePtyBackend, u as createDefaultPtyAdapter } from "./runner-BHXXwxYp.mjs";
|
|
6
|
+
import { a as resolveScriptManifestPath, c as relocateScriptManifestCommands, d as resolveScriptRunSummaryPath, f as runScriptPath, i as readScriptManifestPath, l as resolveManifestPrimaryPath$1, n as runAllScripts, o as validateScriptManifest, r as findScriptSummaryManifest, t as createPtywrightServer, u as readScriptRunSummaryPath } from "./server-COuf3mW7.mjs";
|
|
7
|
+
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-DWIlWGgA.mjs";
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import { Buffer } from "node:buffer";
|
|
11
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
12
13
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
13
|
-
import { Buffer } from "node:buffer";
|
|
14
14
|
//#region src/agent/check_summary_schema.ts
|
|
15
15
|
const AGENT_CHECK_SCHEMA_URL = "https://ptywright.local/schemas/ptywright-agent-check.schema.json";
|
|
16
16
|
const countSummarySchema$1 = z.object({
|
package/dist/cli.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as main } from "./cli-
|
|
1
|
+
import { t as main } from "./cli-XLR4BPhA.mjs";
|
|
2
2
|
export { main };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
//#region src/pty-cassette/data.ts
|
|
3
|
+
function dataToBytes(data) {
|
|
4
|
+
if (typeof data === "string") return Buffer.from(data, "utf8");
|
|
5
|
+
if (data instanceof ArrayBuffer) return new Uint8Array(data);
|
|
6
|
+
return data;
|
|
7
|
+
}
|
|
8
|
+
function dataToBase64(data) {
|
|
9
|
+
return Buffer.from(dataToBytes(data)).toString("base64");
|
|
10
|
+
}
|
|
11
|
+
function base64ToBytes(dataBase64) {
|
|
12
|
+
return Buffer.from(dataBase64, "base64");
|
|
13
|
+
}
|
|
14
|
+
function byteLength(data) {
|
|
15
|
+
return dataToBytes(data).byteLength;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { dataToBytes as i, byteLength as n, dataToBase64 as r, base64ToBytes as t };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createPtywrightServer } from "./server-
|
|
1
|
+
import { t as createPtywrightServer } from "./server-COuf3mW7.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-COuf3mW7.mjs";
|
|
2
2
|
export { createPtywrightServer };
|
package/dist/pty-cassette.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as dataToBytes, n as byteLength, r as dataToBase64, t as base64ToBytes } from "./data-sdbf3IDh.mjs";
|
|
2
|
+
import { _ as ptyCassetteSchema, a as inspectPtyCassette, 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 } from "./pty_like-DWIlWGgA.mjs";
|
|
2
3
|
//#region src/pty-cassette/bun_terminal.ts
|
|
3
4
|
function wrapBunTerminalOptions(options, recorder) {
|
|
4
5
|
const onData = options.data;
|
|
@@ -1,23 +1,7 @@
|
|
|
1
|
+
import { n as byteLength, r as dataToBase64, t as base64ToBytes } from "./data-sdbf3IDh.mjs";
|
|
1
2
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
3
|
import { dirname } from "node:path";
|
|
3
4
|
import { z } from "zod";
|
|
4
|
-
import { Buffer } from "node:buffer";
|
|
5
|
-
//#region src/pty-cassette/data.ts
|
|
6
|
-
function dataToBytes(data) {
|
|
7
|
-
if (typeof data === "string") return Buffer.from(data, "utf8");
|
|
8
|
-
if (data instanceof ArrayBuffer) return new Uint8Array(data);
|
|
9
|
-
return data;
|
|
10
|
-
}
|
|
11
|
-
function dataToBase64(data) {
|
|
12
|
-
return Buffer.from(dataToBytes(data)).toString("base64");
|
|
13
|
-
}
|
|
14
|
-
function base64ToBytes(dataBase64) {
|
|
15
|
-
return Buffer.from(dataBase64, "base64");
|
|
16
|
-
}
|
|
17
|
-
function byteLength(data) {
|
|
18
|
-
return dataToBytes(data).byteLength;
|
|
19
|
-
}
|
|
20
|
-
//#endregion
|
|
21
5
|
//#region src/pty-cassette/schema.ts
|
|
22
6
|
const PTY_CASSETTE_SCHEMA_URL = "https://ptywright.local/schemas/ptywright-pty-cassette.schema.json";
|
|
23
7
|
const base64Schema = z.string().refine((value) => value.length % 4 === 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(value), { message: "expected base64-encoded data" });
|
|
@@ -401,4 +385,4 @@ function dispose(disposable) {
|
|
|
401
385
|
disposable.dispose();
|
|
402
386
|
}
|
|
403
387
|
//#endregion
|
|
404
|
-
export {
|
|
388
|
+
export { ptyCassetteSchema as _, inspectPtyCassette as a, createPtyCassetteReplay as c, PTY_CASSETTE_SCHEMA_URL as d, normalizePtyCassette as f, ptyCassetteResizeEventSchema as g, ptyCassetteExitEventSchema as h, formatPtyCassetteInspectLines as i, readPtyCassettePath as l, ptyCassetteEventSchema as m, PtyCassetteRecorder as n, inspectPtyCassettePath as o, ptyCassetteDataEventSchema as p, createPtyCassetteRecorder as r, PtyCassetteReplay as s, wrapPtyLike as t, writePtyCassettePath as u, validatePtyCassette as v };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { n as mergeProcessEnv, o as relativeHref, t as envTruthy } from "./env-DPYHo-zH.mjs";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as styleKey, i as isDefaultStyle, n as extractStyle, r as findMeaningfulEndCol } from "./style-BtIUv5H0.mjs";
|
|
3
|
+
import { a as fnv1a32, c as encodeSgrMouse, i as TraceRecorder, l as encodeKey, n as sleep, o as snapshotGrid, r as applyTextMaskRules, s as snapshotLines, t as TerminalSession } from "./terminal_session-MX_vWpRG.mjs";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
6
|
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
6
7
|
import { pathToFileURL } from "node:url";
|
|
7
8
|
import { z } from "zod";
|
|
8
|
-
import { spawn } from "bun-pty";
|
|
9
9
|
import { Terminal } from "@xterm/headless";
|
|
10
|
+
import { spawn } from "bun-pty";
|
|
10
11
|
//#region src/pty/bun_pty_adapter.ts
|
|
11
12
|
function toForkOptions(options) {
|
|
12
13
|
return {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { a as sameArgv, n as validateManifestFiles, r as formatZodIssues, t as collectManifestFiles } from "./manifest_files-DW80c1H7.mjs";
|
|
2
2
|
import { t as envTruthy } from "./env-DPYHo-zH.mjs";
|
|
3
|
+
import { t as base64ToBytes } from "./data-sdbf3IDh.mjs";
|
|
4
|
+
import { a as styleKey, i as isDefaultStyle, n as extractStyle, r as findMeaningfulEndCol, t as DEFAULT_STYLE } from "./style-BtIUv5H0.mjs";
|
|
3
5
|
import { createRequire } from "node:module";
|
|
4
6
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
7
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
@@ -7,6 +9,7 @@ import { pathToFileURL } from "node:url";
|
|
|
7
9
|
import { z } from "zod";
|
|
8
10
|
import { createServer } from "node:http";
|
|
9
11
|
import { chromium } from "playwright";
|
|
12
|
+
import { Terminal } from "@xterm/headless";
|
|
10
13
|
import { spawn } from "node:child_process";
|
|
11
14
|
//#region src/agent/normalize.ts
|
|
12
15
|
function applyAgentMasks(input, rules = [], options = {}) {
|
|
@@ -1390,23 +1393,23 @@ function renderArtifactViewerShellCss() {
|
|
|
1390
1393
|
}
|
|
1391
1394
|
.viewer-stage {
|
|
1392
1395
|
display: grid;
|
|
1393
|
-
grid-template-columns:
|
|
1394
|
-
grid-template-rows:
|
|
1396
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1397
|
+
grid-template-rows: minmax(0, 1fr);
|
|
1395
1398
|
min-width: 0;
|
|
1396
1399
|
min-height: 0;
|
|
1397
|
-
justify-
|
|
1400
|
+
justify-items: center;
|
|
1398
1401
|
align-content: start;
|
|
1399
|
-
overflow:
|
|
1402
|
+
overflow: hidden;
|
|
1400
1403
|
background:
|
|
1401
1404
|
radial-gradient(circle at top left, rgba(121, 192, 255, 0.1), transparent 32%),
|
|
1402
1405
|
#060a13;
|
|
1403
1406
|
padding: 14px;
|
|
1404
1407
|
}
|
|
1405
1408
|
.viewer-viewport {
|
|
1406
|
-
width: var(--config-viewport-width);
|
|
1407
|
-
height: var(--config-viewport-height);
|
|
1408
|
-
max-width:
|
|
1409
|
-
max-height:
|
|
1409
|
+
width: min(var(--config-viewport-width), 100%);
|
|
1410
|
+
height: min(var(--config-viewport-height), 100%);
|
|
1411
|
+
max-width: 100%;
|
|
1412
|
+
max-height: 100%;
|
|
1410
1413
|
overflow: auto;
|
|
1411
1414
|
overscroll-behavior: contain;
|
|
1412
1415
|
border: 0;
|
|
@@ -1416,7 +1419,7 @@ function renderArtifactViewerShellCss() {
|
|
|
1416
1419
|
box-shadow: 0 18px 52px rgba(0, 0, 0, 0.34);
|
|
1417
1420
|
}
|
|
1418
1421
|
.viewer-viewport[data-mobile="true"] {
|
|
1419
|
-
width: var(--config-viewport-width);
|
|
1422
|
+
width: min(var(--config-viewport-width), 100%);
|
|
1420
1423
|
}
|
|
1421
1424
|
.dom-viewport {
|
|
1422
1425
|
overflow: hidden;
|
|
@@ -1455,8 +1458,8 @@ function renderArtifactViewerShellCss() {
|
|
|
1455
1458
|
padding: 0;
|
|
1456
1459
|
}
|
|
1457
1460
|
.viewer-viewport {
|
|
1458
|
-
width: var(--config-viewport-width);
|
|
1459
|
-
height: var(--config-viewport-height);
|
|
1461
|
+
width: min(var(--config-viewport-width), 100%);
|
|
1462
|
+
height: min(var(--config-viewport-height), 100%);
|
|
1460
1463
|
border-radius: 0;
|
|
1461
1464
|
}
|
|
1462
1465
|
}`;
|
|
@@ -1511,22 +1514,19 @@ function renderConfiguredViewportStyle(viewport) {
|
|
|
1511
1514
|
return `--config-viewport-width: ${viewport.width}px; --config-viewport-height: ${viewport.height}px;`;
|
|
1512
1515
|
}
|
|
1513
1516
|
//#endregion
|
|
1514
|
-
//#region src/agent/
|
|
1515
|
-
function
|
|
1516
|
-
return
|
|
1517
|
+
//#region src/agent/report_launch_args.ts
|
|
1518
|
+
function readReportLaunchArgSets(result) {
|
|
1519
|
+
return [readFlowLaunchArgs(result.flowPath), readCassetteLaunchArgs(result.replaySourceCassettePath ?? result.cassettePath)];
|
|
1517
1520
|
}
|
|
1518
|
-
function
|
|
1519
|
-
const
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
screenMode: screenModeArg && screenModeArg !== "termvision" ? "plain" : "termvision",
|
|
1528
|
-
theme: themeArg === "light" ? "light" : "dark"
|
|
1529
|
-
};
|
|
1521
|
+
function readFlagValueFromArgSets(argSets, flag) {
|
|
1522
|
+
for (const args of argSets) {
|
|
1523
|
+
const value = readFlagValue(args, flag);
|
|
1524
|
+
if (value !== void 0) return value;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
function readFlagValue(args, flag) {
|
|
1528
|
+
const index = args.indexOf(flag);
|
|
1529
|
+
return index >= 0 ? args[index + 1] : void 0;
|
|
1530
1530
|
}
|
|
1531
1531
|
function readCassetteLaunchArgs(cassettePath) {
|
|
1532
1532
|
try {
|
|
@@ -1545,21 +1545,41 @@ function readFlowLaunchArgs(flowPath) {
|
|
|
1545
1545
|
function normalizeStringArray(value) {
|
|
1546
1546
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
1547
1547
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
}
|
|
1548
|
+
//#endregion
|
|
1549
|
+
//#region src/agent/report_view_options.ts
|
|
1550
|
+
function isMobileViewport(viewport) {
|
|
1551
|
+
return Boolean(viewport?.isMobile || viewport?.hasTouch || (viewport?.width ?? 9999) <= 720);
|
|
1553
1552
|
}
|
|
1554
|
-
function
|
|
1555
|
-
const
|
|
1556
|
-
|
|
1553
|
+
function resolveReportViewOptions(result, config) {
|
|
1554
|
+
const launchArgSets = readReportLaunchArgSets(result);
|
|
1555
|
+
const ptyReplayArg = readFlagValueFromArgSets(launchArgSets, "--pty-replay");
|
|
1556
|
+
const screenModeArg = readFlagValueFromArgSets(launchArgSets, "--experimental-screen-mode");
|
|
1557
|
+
const themeArg = readFlagValueFromArgSets(launchArgSets, "--theme");
|
|
1558
|
+
const fontSizeArg = readFlagValueFromArgSets(launchArgSets, "--font-size");
|
|
1559
|
+
const lineHeightArg = readFlagValueFromArgSets(launchArgSets, "--line-height");
|
|
1560
|
+
const stableFrameConfig = resolveStableFrameConfig$1(config, result.name);
|
|
1561
|
+
const themeOverride = ptyReplayArg && stableFrameConfig.enabled !== false && !stableFrameConfig.skip ? stableFrameConfig.theme : void 0;
|
|
1562
|
+
return {
|
|
1563
|
+
fontSize: parsePositiveNumber(fontSizeArg) ?? 15,
|
|
1564
|
+
lineHeight: parsePositiveNumber(lineHeightArg) ?? 1.6,
|
|
1565
|
+
screenMode: screenModeArg && screenModeArg !== "termvision" ? "plain" : "termvision",
|
|
1566
|
+
theme: themeOverride ?? (themeArg === "light" ? "light" : "dark")
|
|
1567
|
+
};
|
|
1557
1568
|
}
|
|
1558
1569
|
function parsePositiveNumber(value) {
|
|
1559
1570
|
if (value === void 0) return void 0;
|
|
1560
1571
|
const parsed = Number(value);
|
|
1561
1572
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
1562
1573
|
}
|
|
1574
|
+
function resolveStableFrameConfig$1(config, flowName) {
|
|
1575
|
+
const stableFrames = config?.agent?.report?.stableFrames;
|
|
1576
|
+
const flowConfig = stableFrames?.flows?.[flowName];
|
|
1577
|
+
return {
|
|
1578
|
+
enabled: flowConfig?.enabled ?? stableFrames?.enabled,
|
|
1579
|
+
skip: flowConfig?.skip ?? stableFrames?.skip,
|
|
1580
|
+
theme: flowConfig?.theme ?? stableFrames?.theme ?? "dark"
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1563
1583
|
//#endregion
|
|
1564
1584
|
//#region src/agent/report_artifact_viewer.ts
|
|
1565
1585
|
function renderArtifactViewerHtml(args) {
|
|
@@ -1584,6 +1604,424 @@ function renderArtifactViewerHtml(args) {
|
|
|
1584
1604
|
});
|
|
1585
1605
|
}
|
|
1586
1606
|
//#endregion
|
|
1607
|
+
//#region src/agent/report_pty_stable_frame.ts
|
|
1608
|
+
async function extractPtyReplayStableFrameForReport(args) {
|
|
1609
|
+
const replayPathArg = readFlagValueFromArgSets(readReportLaunchArgSets(args.result), "--pty-replay");
|
|
1610
|
+
if (!replayPathArg) return null;
|
|
1611
|
+
const config = resolveStableFrameConfig(args.config, args.result.name);
|
|
1612
|
+
if (config.enabled === false || config.skip) return null;
|
|
1613
|
+
const replayPath = resolvePtyReplayPath(replayPathArg, args.config);
|
|
1614
|
+
if (!existsSync(replayPath)) return null;
|
|
1615
|
+
const recording = JSON.parse(readFileSync(replayPath, "utf8"));
|
|
1616
|
+
const events = Array.isArray(recording.events) ? recording.events : [];
|
|
1617
|
+
const firstResize = events.find((event) => event.type === "resize");
|
|
1618
|
+
const terminal = new Terminal({
|
|
1619
|
+
allowProposedApi: true,
|
|
1620
|
+
cols: config.cols ?? recording.terminal?.cols ?? recording.command?.cols ?? recording.cols ?? firstResize?.cols ?? 80,
|
|
1621
|
+
convertEol: true,
|
|
1622
|
+
rows: config.rows ?? recording.terminal?.rows ?? recording.command?.rows ?? recording.rows ?? firstResize?.rows ?? 24,
|
|
1623
|
+
scrollback: 2e4
|
|
1624
|
+
});
|
|
1625
|
+
try {
|
|
1626
|
+
return await extractStableFrame({
|
|
1627
|
+
config,
|
|
1628
|
+
events,
|
|
1629
|
+
terminal
|
|
1630
|
+
});
|
|
1631
|
+
} finally {
|
|
1632
|
+
terminal.dispose();
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
function renderPtyReplayStableFramePreviewDocument(args) {
|
|
1636
|
+
const targetCols = resolveTargetCols({
|
|
1637
|
+
config: resolveStableFrameConfig(args.config, args.flowName),
|
|
1638
|
+
fontSize: args.viewOptions.fontSize,
|
|
1639
|
+
frameCols: args.frame.cols,
|
|
1640
|
+
viewport: args.viewport
|
|
1641
|
+
});
|
|
1642
|
+
const body = renderAittyPreviewBody({
|
|
1643
|
+
snapshot: renderStableFrameDom(args.frame, targetCols),
|
|
1644
|
+
snapshotLayout: {
|
|
1645
|
+
cols: targetCols,
|
|
1646
|
+
fontSize: args.viewOptions.fontSize,
|
|
1647
|
+
lineHeight: args.viewOptions.lineHeight,
|
|
1648
|
+
paddingInline: isMobileViewport(args.viewport) ? 16 : 32,
|
|
1649
|
+
rows: args.frame.rows
|
|
1650
|
+
},
|
|
1651
|
+
viewOptions: args.viewOptions
|
|
1652
|
+
});
|
|
1653
|
+
const style = renderAittyPreviewCss(args.viewOptions);
|
|
1654
|
+
const assetTags = renderAittyPreviewAssetTags(args.aittyAssets);
|
|
1655
|
+
return `<!doctype html>
|
|
1656
|
+
<html lang="en" data-theme="${escapeAttribute(args.viewOptions.theme)}">
|
|
1657
|
+
<head>
|
|
1658
|
+
<meta charset="utf-8" />
|
|
1659
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
1660
|
+
<title>stable-frame preview (atMs=${args.frame.atMs})</title>
|
|
1661
|
+
${assetTags} <style>
|
|
1662
|
+
${style}
|
|
1663
|
+
</style>
|
|
1664
|
+
</head>
|
|
1665
|
+
<body>
|
|
1666
|
+
${body}
|
|
1667
|
+
</body>
|
|
1668
|
+
</html>`;
|
|
1669
|
+
}
|
|
1670
|
+
function resolveStableFrameConfig(config, flowName) {
|
|
1671
|
+
const stableFrames = config?.agent?.report?.stableFrames;
|
|
1672
|
+
const flowConfig = stableFrames?.flows?.[flowName];
|
|
1673
|
+
return {
|
|
1674
|
+
...stableFrames,
|
|
1675
|
+
...flowConfig,
|
|
1676
|
+
stableMs: flowConfig?.stableMs ?? stableFrames?.stableMs ?? 200,
|
|
1677
|
+
theme: flowConfig?.theme ?? stableFrames?.theme ?? "dark",
|
|
1678
|
+
viewportOnly: flowConfig?.viewportOnly ?? stableFrames?.viewportOnly ?? false,
|
|
1679
|
+
viewportTargets: {
|
|
1680
|
+
...stableFrames?.viewportTargets,
|
|
1681
|
+
...flowConfig?.viewportTargets
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
function resolvePtyReplayPath(replayPathArg, config) {
|
|
1686
|
+
if (isAbsolute(replayPathArg)) return replayPathArg;
|
|
1687
|
+
return resolve(config?.rootDir ?? process.cwd(), replayPathArg);
|
|
1688
|
+
}
|
|
1689
|
+
async function extractStableFrame(args) {
|
|
1690
|
+
const { config, events, terminal } = args;
|
|
1691
|
+
const targetFrameIndex = config.frameIndex;
|
|
1692
|
+
const matcher = createStableFrameMatcher(config);
|
|
1693
|
+
let matchedFrame = null;
|
|
1694
|
+
const retainedFrames = [];
|
|
1695
|
+
const retainCount = targetFrameIndex === void 0 ? 24 : targetFrameIndex < 0 ? -targetFrameIndex : 1;
|
|
1696
|
+
let totalFrames = 0;
|
|
1697
|
+
let pendingDirtySinceMs = null;
|
|
1698
|
+
let lastEventAtMs = 0;
|
|
1699
|
+
const captureFrame = (atMs, reason) => {
|
|
1700
|
+
const shouldRetain = targetFrameIndex === void 0 || targetFrameIndex >= 0 && totalFrames === targetFrameIndex || targetFrameIndex < 0;
|
|
1701
|
+
if (shouldRetain || matcher) {
|
|
1702
|
+
const frame = {
|
|
1703
|
+
...snapshotTerminalFrame(terminal, {
|
|
1704
|
+
atMs,
|
|
1705
|
+
index: totalFrames,
|
|
1706
|
+
reason,
|
|
1707
|
+
viewportOnly: config.viewportOnly
|
|
1708
|
+
}),
|
|
1709
|
+
score: scoreTerminalFrame(terminal)
|
|
1710
|
+
};
|
|
1711
|
+
if (matcher?.matches(stableFrameText(frame))) {
|
|
1712
|
+
if (matcher.mode === "last" || !matchedFrame) matchedFrame = frame;
|
|
1713
|
+
}
|
|
1714
|
+
if (shouldRetain) retainedFrames.push(frame);
|
|
1715
|
+
if (retainedFrames.length > retainCount) retainedFrames.splice(0, retainedFrames.length - retainCount);
|
|
1716
|
+
}
|
|
1717
|
+
totalFrames += 1;
|
|
1718
|
+
pendingDirtySinceMs = null;
|
|
1719
|
+
};
|
|
1720
|
+
const flushIfStable = (nowMs) => {
|
|
1721
|
+
if (pendingDirtySinceMs === null) return;
|
|
1722
|
+
if (nowMs - pendingDirtySinceMs >= config.stableMs) captureFrame(pendingDirtySinceMs, "stable");
|
|
1723
|
+
};
|
|
1724
|
+
for (const event of events) {
|
|
1725
|
+
const atMs = event.atMs ?? lastEventAtMs;
|
|
1726
|
+
flushIfStable(atMs);
|
|
1727
|
+
lastEventAtMs = atMs;
|
|
1728
|
+
if (event.type === "output" && event.dataBase64) {
|
|
1729
|
+
await writeTerminal(terminal, base64ToBytes(event.dataBase64));
|
|
1730
|
+
pendingDirtySinceMs = pendingDirtySinceMs ?? atMs;
|
|
1731
|
+
continue;
|
|
1732
|
+
}
|
|
1733
|
+
if (event.type === "resize" && event.cols && event.rows) {
|
|
1734
|
+
terminal.resize(event.cols, event.rows);
|
|
1735
|
+
pendingDirtySinceMs = pendingDirtySinceMs ?? atMs;
|
|
1736
|
+
continue;
|
|
1737
|
+
}
|
|
1738
|
+
if (event.type === "exit") flushIfStable(atMs);
|
|
1739
|
+
}
|
|
1740
|
+
flushIfStable(lastEventAtMs + config.stableMs);
|
|
1741
|
+
if (totalFrames === 0) captureFrame(lastEventAtMs, "final");
|
|
1742
|
+
if (targetFrameIndex !== void 0 && targetFrameIndex >= 0) {
|
|
1743
|
+
const exact = retainedFrames.find((frame) => frame.index === targetFrameIndex);
|
|
1744
|
+
if (exact) return exact;
|
|
1745
|
+
return null;
|
|
1746
|
+
}
|
|
1747
|
+
if (targetFrameIndex !== void 0 && targetFrameIndex < 0) {
|
|
1748
|
+
const resolved = totalFrames + targetFrameIndex;
|
|
1749
|
+
const exact = retainedFrames.find((frame) => frame.index === resolved);
|
|
1750
|
+
if (exact) return exact;
|
|
1751
|
+
}
|
|
1752
|
+
if (matchedFrame) return matchedFrame;
|
|
1753
|
+
return chooseBestStableFrame(retainedFrames);
|
|
1754
|
+
}
|
|
1755
|
+
function writeTerminal(terminal, data) {
|
|
1756
|
+
return new Promise((resolveWrite) => {
|
|
1757
|
+
terminal.write(data, resolveWrite);
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
function snapshotTerminalFrame(terminal, options) {
|
|
1761
|
+
const buffer = terminal.buffer.active;
|
|
1762
|
+
const startY = options.viewportOnly ? buffer.viewportY : 0;
|
|
1763
|
+
const count = options.viewportOnly ? terminal.rows : buffer.length;
|
|
1764
|
+
const logicalLines = [];
|
|
1765
|
+
for (let offset = 0; offset < count; offset += 1) {
|
|
1766
|
+
const y = startY + offset;
|
|
1767
|
+
const line = buffer.getLine(y);
|
|
1768
|
+
const cells = readStableLineCells(terminal, y);
|
|
1769
|
+
const live = options.viewportOnly || y >= buffer.viewportY;
|
|
1770
|
+
const previous = logicalLines.at(-1);
|
|
1771
|
+
if (line?.isWrapped && previous) {
|
|
1772
|
+
previous.cells.push(...cells);
|
|
1773
|
+
previous.live = previous.live || live;
|
|
1774
|
+
previous.physicalRows += 1;
|
|
1775
|
+
continue;
|
|
1776
|
+
}
|
|
1777
|
+
logicalLines.push({
|
|
1778
|
+
cells,
|
|
1779
|
+
live,
|
|
1780
|
+
physicalRows: 1
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
return {
|
|
1784
|
+
atMs: options.atMs,
|
|
1785
|
+
cols: terminal.cols,
|
|
1786
|
+
index: options.index,
|
|
1787
|
+
lines: logicalLines,
|
|
1788
|
+
reason: options.reason,
|
|
1789
|
+
rows: terminal.rows
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
function readStableLineCells(terminal, y) {
|
|
1793
|
+
const buffer = terminal.buffer.active;
|
|
1794
|
+
const nullCell = buffer.getNullCell();
|
|
1795
|
+
const line = buffer.getLine(y);
|
|
1796
|
+
const endCol = findMeaningfulEndCol(line, terminal.cols, nullCell);
|
|
1797
|
+
const cells = [];
|
|
1798
|
+
for (let x = 0; x < endCol; x += 1) {
|
|
1799
|
+
const cell = line?.getCell(x, nullCell);
|
|
1800
|
+
if (!cell) {
|
|
1801
|
+
cells.push({
|
|
1802
|
+
style: DEFAULT_STYLE,
|
|
1803
|
+
text: " ",
|
|
1804
|
+
width: 1
|
|
1805
|
+
});
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1808
|
+
const width = cell.getWidth();
|
|
1809
|
+
if (width === 0) continue;
|
|
1810
|
+
cells.push({
|
|
1811
|
+
style: extractStyle(cell),
|
|
1812
|
+
text: cell.getChars() || " ",
|
|
1813
|
+
width
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
return cells;
|
|
1817
|
+
}
|
|
1818
|
+
function scoreTerminalFrame(terminal) {
|
|
1819
|
+
const buffer = terminal.buffer.active;
|
|
1820
|
+
const nullCell = buffer.getNullCell();
|
|
1821
|
+
let score = 0;
|
|
1822
|
+
for (let y = 0; y < buffer.length; y += 1) {
|
|
1823
|
+
const endCol = findMeaningfulEndCol(buffer.getLine(y), terminal.cols, nullCell);
|
|
1824
|
+
score += endCol;
|
|
1825
|
+
}
|
|
1826
|
+
return score;
|
|
1827
|
+
}
|
|
1828
|
+
function chooseBestStableFrame(frames) {
|
|
1829
|
+
return frames.filter((frame) => frame.score > 0).at(-1) ?? frames.at(-1) ?? null;
|
|
1830
|
+
}
|
|
1831
|
+
function createStableFrameMatcher(config) {
|
|
1832
|
+
const matchText = toStringArray(config.matchText);
|
|
1833
|
+
const matchRegex = toStringArray(config.matchRegex).map((pattern) => {
|
|
1834
|
+
try {
|
|
1835
|
+
return new RegExp(pattern);
|
|
1836
|
+
} catch (error) {
|
|
1837
|
+
throw new Error(`invalid agent.report.stableFrames.matchRegex pattern ${JSON.stringify(pattern)}: ${String(error)}`);
|
|
1838
|
+
}
|
|
1839
|
+
});
|
|
1840
|
+
if (matchText.length === 0 && matchRegex.length === 0) return null;
|
|
1841
|
+
return {
|
|
1842
|
+
mode: config.matchMode ?? "last",
|
|
1843
|
+
matches: (text) => matchText.some((needle) => text.includes(needle)) || matchRegex.some((regex) => regex.test(text))
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
function stableFrameText(frame) {
|
|
1847
|
+
return frame.lines.map((line) => line.cells.map((cell) => cell.text).join("").trimEnd()).join("\n");
|
|
1848
|
+
}
|
|
1849
|
+
function toStringArray(value) {
|
|
1850
|
+
if (value === void 0) return [];
|
|
1851
|
+
return Array.isArray(value) ? value : [value];
|
|
1852
|
+
}
|
|
1853
|
+
function resolveTargetCols(args) {
|
|
1854
|
+
const explicit = args.viewport ? args.config.viewportTargets?.[args.viewport.name] : void 0;
|
|
1855
|
+
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0) return Math.trunc(explicit);
|
|
1856
|
+
if (explicit === null) return args.frameCols;
|
|
1857
|
+
if (isMobileViewport(args.viewport)) {
|
|
1858
|
+
const width = args.viewport?.width ?? 390;
|
|
1859
|
+
const cellWidth = Math.max(1, args.fontSize * .6);
|
|
1860
|
+
return Math.max(20, Math.floor(width / cellWidth));
|
|
1861
|
+
}
|
|
1862
|
+
return args.frameCols;
|
|
1863
|
+
}
|
|
1864
|
+
function renderStableFrameDom(frame, targetCols) {
|
|
1865
|
+
let html = "";
|
|
1866
|
+
let totalRows = 0;
|
|
1867
|
+
let wideBlockId = 0;
|
|
1868
|
+
for (const line of frame.lines) {
|
|
1869
|
+
const lineCols = cellsDisplayWidth(line.cells);
|
|
1870
|
+
if (shouldRenderViewportPan(line, lineCols, targetCols)) {
|
|
1871
|
+
wideBlockId += 1;
|
|
1872
|
+
const blockCols = Math.max(targetCols, lineCols);
|
|
1873
|
+
html += `<div class="term-wide-row-block" data-aitty-wide-block="true" data-aitty-wide-block-id="${wideBlockId}" data-aitty-wide-block-kind="viewport-pan" style="--aitty-wide-block-cols: ${blockCols}">`;
|
|
1874
|
+
html += renderStableFrameRow(line, blockCols, totalRows);
|
|
1875
|
+
html += "</div>";
|
|
1876
|
+
totalRows += 1;
|
|
1877
|
+
} else for (const row of wrapStableLogicalLine(line, targetCols)) {
|
|
1878
|
+
html += renderStableFrameRow(row, targetCols, totalRows);
|
|
1879
|
+
totalRows += 1;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
return `<div class="term-grid" data-cols="${targetCols}" data-rows="${totalRows}" style="--term-cols: ${targetCols}; --term-rows: ${totalRows};">${html}</div>`;
|
|
1883
|
+
}
|
|
1884
|
+
function shouldRenderViewportPan(line, lineCols, targetCols) {
|
|
1885
|
+
if (lineCols <= targetCols) return false;
|
|
1886
|
+
return isDiffLikeLine(stableLineText(line));
|
|
1887
|
+
}
|
|
1888
|
+
function stableLineText(line) {
|
|
1889
|
+
return line.cells.map((cell) => cell.text).join("").trimEnd();
|
|
1890
|
+
}
|
|
1891
|
+
function isDiffLikeLine(text) {
|
|
1892
|
+
const normalized = text.replace(/[│┃┆┊▏▕]/g, " ").trimStart();
|
|
1893
|
+
if (normalized === "") return false;
|
|
1894
|
+
if (/^(?:diff --git|index [0-9a-f]{6,}\.\.|@@\s|[-+]{3}\s)/.test(normalized)) return true;
|
|
1895
|
+
if (/^\d+\s+[+-]/.test(normalized)) return true;
|
|
1896
|
+
const signed = normalized.match(/^[+-]\s*(.*)$/);
|
|
1897
|
+
if (!signed) return false;
|
|
1898
|
+
return isCodeLikeText(signed[1] ?? "");
|
|
1899
|
+
}
|
|
1900
|
+
function isCodeLikeText(text) {
|
|
1901
|
+
return /[{}()[\];=<>]/.test(text) || /\b(?:async|await|class|const|def|export|from|function|if|import|interface|let|return|type|var)\b/.test(text) || /(?:^|\s)(?:--?[a-z][\w-]*|#[\w-]+|\/[A-Za-z0-9._/-]+)(?:\s|$)/.test(text);
|
|
1902
|
+
}
|
|
1903
|
+
function wrapStableLogicalLine(line, targetCols) {
|
|
1904
|
+
if (cellsDisplayWidth(line.cells) <= targetCols) return [line];
|
|
1905
|
+
const rows = [];
|
|
1906
|
+
let cells = [];
|
|
1907
|
+
let cols = 0;
|
|
1908
|
+
const flush = () => {
|
|
1909
|
+
rows.push({
|
|
1910
|
+
cells,
|
|
1911
|
+
live: line.live,
|
|
1912
|
+
physicalRows: 1
|
|
1913
|
+
});
|
|
1914
|
+
cells = [];
|
|
1915
|
+
cols = 0;
|
|
1916
|
+
};
|
|
1917
|
+
for (const cell of line.cells) {
|
|
1918
|
+
if (cols > 0 && cols + cell.width > targetCols) flush();
|
|
1919
|
+
cells.push(cell);
|
|
1920
|
+
cols += cell.width;
|
|
1921
|
+
if (cols >= targetCols) flush();
|
|
1922
|
+
}
|
|
1923
|
+
if (cells.length > 0 || rows.length === 0) flush();
|
|
1924
|
+
return rows;
|
|
1925
|
+
}
|
|
1926
|
+
function renderStableFrameRow(line, lineCols, lineIndex) {
|
|
1927
|
+
return `<div class="${line.live ? "term-row" : "term-row term-scrollback-row"}"${line.live ? ` data-aitty-live-grid-row="${lineIndex + 1}"` : ""} data-aitty-line-cols="${lineCols}">${renderStableFrameCells(line.cells, lineCols)}</div>`;
|
|
1928
|
+
}
|
|
1929
|
+
function renderStableFrameCells(cells, lineCols) {
|
|
1930
|
+
const out = [];
|
|
1931
|
+
let usedCols = 0;
|
|
1932
|
+
let runText = "";
|
|
1933
|
+
let runWidth = 0;
|
|
1934
|
+
let runStyle = null;
|
|
1935
|
+
let runKey = null;
|
|
1936
|
+
const flush = () => {
|
|
1937
|
+
if (runText === "" && runWidth === 0) return;
|
|
1938
|
+
out.push(renderSpan(runText, runWidth, runStyle ?? DEFAULT_STYLE));
|
|
1939
|
+
runText = "";
|
|
1940
|
+
runWidth = 0;
|
|
1941
|
+
runStyle = null;
|
|
1942
|
+
runKey = null;
|
|
1943
|
+
};
|
|
1944
|
+
for (const cell of cells) {
|
|
1945
|
+
const key = styleKey(cell.style);
|
|
1946
|
+
const wide = cell.width !== 1;
|
|
1947
|
+
if (!wide && runKey === key) {
|
|
1948
|
+
runText += cell.text;
|
|
1949
|
+
runWidth += cell.width;
|
|
1950
|
+
usedCols += cell.width;
|
|
1951
|
+
continue;
|
|
1952
|
+
}
|
|
1953
|
+
flush();
|
|
1954
|
+
if (wide) {
|
|
1955
|
+
out.push(renderSpan(cell.text, cell.width, cell.style, "term-wide"));
|
|
1956
|
+
usedCols += cell.width;
|
|
1957
|
+
continue;
|
|
1958
|
+
}
|
|
1959
|
+
runText = cell.text;
|
|
1960
|
+
runWidth = cell.width;
|
|
1961
|
+
runStyle = cell.style;
|
|
1962
|
+
runKey = key;
|
|
1963
|
+
usedCols += cell.width;
|
|
1964
|
+
}
|
|
1965
|
+
flush();
|
|
1966
|
+
const remaining = lineCols - usedCols;
|
|
1967
|
+
if (remaining > 0) out.push(renderSpan("", remaining, DEFAULT_STYLE));
|
|
1968
|
+
return out.join("");
|
|
1969
|
+
}
|
|
1970
|
+
function renderSpan(text, width, style, className) {
|
|
1971
|
+
const declarations = styleDeclarations(style);
|
|
1972
|
+
declarations.push(widthDeclaration(width));
|
|
1973
|
+
if (className === "term-wide") declarations.push("overflow: hidden");
|
|
1974
|
+
return `<span${className ? ` class="${escapeAttribute(className)}"` : ""} style="${escapeAttribute(declarations.join("; "))}">${escapeHtml(text)}</span>`;
|
|
1975
|
+
}
|
|
1976
|
+
function styleDeclarations(style) {
|
|
1977
|
+
if (isDefaultStyle(style)) return [];
|
|
1978
|
+
const declarations = [];
|
|
1979
|
+
const fg = colorToCss(style.fg);
|
|
1980
|
+
const bg = colorToCss(style.bg);
|
|
1981
|
+
if (fg) declarations.push(`color: ${fg}`);
|
|
1982
|
+
if (bg) declarations.push(`background-color: ${bg}`);
|
|
1983
|
+
if (style.bold) declarations.push("font-weight: 700");
|
|
1984
|
+
if (style.dim) declarations.push("opacity: 0.72");
|
|
1985
|
+
if (style.italic) declarations.push("font-style: italic");
|
|
1986
|
+
const decorations = [style.underline ? "underline" : "", style.strikethrough ? "line-through" : ""].filter(Boolean);
|
|
1987
|
+
if (decorations.length > 0) declarations.push(`text-decoration: ${decorations.join(" ")}`);
|
|
1988
|
+
if (style.inverse) declarations.push("filter: invert(1)");
|
|
1989
|
+
return declarations;
|
|
1990
|
+
}
|
|
1991
|
+
function colorToCss(color) {
|
|
1992
|
+
if (color.mode === "default") return null;
|
|
1993
|
+
if (color.mode === "palette") return paletteColorToCss(color.value);
|
|
1994
|
+
const value = color.value;
|
|
1995
|
+
return `rgb(${value >> 16 & 255},${value >> 8 & 255},${value & 255})`;
|
|
1996
|
+
}
|
|
1997
|
+
function paletteColorToCss(value) {
|
|
1998
|
+
if (value >= 0 && value <= 15) return `var(--term-color-${value})`;
|
|
1999
|
+
if (value >= 16 && value <= 231) {
|
|
2000
|
+
const index = value - 16;
|
|
2001
|
+
const steps = [
|
|
2002
|
+
0,
|
|
2003
|
+
95,
|
|
2004
|
+
135,
|
|
2005
|
+
175,
|
|
2006
|
+
215,
|
|
2007
|
+
255
|
|
2008
|
+
];
|
|
2009
|
+
return `rgb(${steps[Math.floor(index / 36)] ?? 0},${steps[Math.floor(index % 36 / 6)] ?? 0},${steps[index % 6] ?? 0})`;
|
|
2010
|
+
}
|
|
2011
|
+
if (value >= 232 && value <= 255) {
|
|
2012
|
+
const channel = 8 + (value - 232) * 10;
|
|
2013
|
+
return `rgb(${channel},${channel},${channel})`;
|
|
2014
|
+
}
|
|
2015
|
+
return `var(--term-color-${value})`;
|
|
2016
|
+
}
|
|
2017
|
+
function widthDeclaration(width) {
|
|
2018
|
+
if (width <= 1) return "width: var(--term-cell-width, 1ch)";
|
|
2019
|
+
return `width: calc(var(--term-cell-width, 1ch) * ${width})`;
|
|
2020
|
+
}
|
|
2021
|
+
function cellsDisplayWidth(cells) {
|
|
2022
|
+
return cells.reduce((sum, cell) => sum + cell.width, 0);
|
|
2023
|
+
}
|
|
2024
|
+
//#endregion
|
|
1587
2025
|
//#region src/agent/report_terminal_layout.ts
|
|
1588
2026
|
function resolveTerminalSnapshotLayout(snapshot, viewport, viewOptions) {
|
|
1589
2027
|
const cols = inferTerminalCols(snapshot);
|
|
@@ -1635,9 +2073,9 @@ ${body}
|
|
|
1635
2073
|
}
|
|
1636
2074
|
//#endregion
|
|
1637
2075
|
//#region src/agent/report_artifact_writer.ts
|
|
1638
|
-
function writeArtifactViewerPages(result) {
|
|
2076
|
+
async function writeArtifactViewerPages(result, options = {}) {
|
|
1639
2077
|
const viewportsByName = new Map(result.viewports.map((viewport) => [viewport.name, viewport]));
|
|
1640
|
-
const viewOptions = resolveReportViewOptions(result);
|
|
2078
|
+
const viewOptions = resolveReportViewOptions(result, options.config);
|
|
1641
2079
|
const readableArtifacts = [];
|
|
1642
2080
|
for (const artifact of result.artifacts) {
|
|
1643
2081
|
const viewerPath = artifactViewerPath(artifact);
|
|
@@ -1657,12 +2095,25 @@ function writeArtifactViewerPages(result) {
|
|
|
1657
2095
|
reportPath: result.reportPath
|
|
1658
2096
|
}) : null;
|
|
1659
2097
|
const writtenDomPreviewPaths = /* @__PURE__ */ new Set();
|
|
2098
|
+
const ptyReplayStableFrame = aittyAssets ? await extractPtyReplayStableFrameForReport({
|
|
2099
|
+
config: options.config,
|
|
2100
|
+
result
|
|
2101
|
+
}) : null;
|
|
1660
2102
|
if (aittyAssets) for (const { artifact, content } of readableArtifacts) {
|
|
1661
2103
|
if (artifact.kind !== "dom") continue;
|
|
1662
2104
|
const viewport = viewportsByName.get(artifact.viewport);
|
|
1663
2105
|
const domPreviewPath = artifactDomPreviewPath(artifact);
|
|
2106
|
+
const aittyPreviewAssets = resolveAittyPreviewAssets(domPreviewPath, aittyAssets, result.artifactsDir);
|
|
2107
|
+
const previewDocument = ptyReplayStableFrame ? renderPtyReplayStableFramePreviewDocument({
|
|
2108
|
+
aittyAssets: aittyPreviewAssets,
|
|
2109
|
+
config: options.config,
|
|
2110
|
+
flowName: result.name,
|
|
2111
|
+
frame: ptyReplayStableFrame,
|
|
2112
|
+
viewOptions,
|
|
2113
|
+
viewport
|
|
2114
|
+
}) : renderDomPreviewDocument(content, viewport, viewOptions, aittyPreviewAssets);
|
|
1664
2115
|
mkdirSync(dirname(domPreviewPath), { recursive: true });
|
|
1665
|
-
writeFileSync(domPreviewPath,
|
|
2116
|
+
writeFileSync(domPreviewPath, previewDocument, "utf8");
|
|
1666
2117
|
writtenDomPreviewPaths.add(domPreviewPath);
|
|
1667
2118
|
}
|
|
1668
2119
|
for (const { artifact, content, viewerPath } of readableArtifacts) {
|
|
@@ -2045,9 +2496,9 @@ ${renderAgentReportCss()}
|
|
|
2045
2496
|
}
|
|
2046
2497
|
//#endregion
|
|
2047
2498
|
//#region src/agent/report.ts
|
|
2048
|
-
function writeAgentReport(path, result) {
|
|
2499
|
+
async function writeAgentReport(path, result, options = {}) {
|
|
2049
2500
|
mkdirSync(dirname(path), { recursive: true });
|
|
2050
|
-
writeArtifactViewerPages(result);
|
|
2501
|
+
await writeArtifactViewerPages(result, options);
|
|
2051
2502
|
writeFileSync(path, renderAgentReportHtml(result), "utf8");
|
|
2052
2503
|
}
|
|
2053
2504
|
//#endregion
|
|
@@ -2797,7 +3248,7 @@ async function runAgentSpec(input, options = {}) {
|
|
|
2797
3248
|
else writeFileSync(cassettePath, JSON.stringify(cassette, null, 2) + "\n", "utf8");
|
|
2798
3249
|
result.cassetteFrameCount = cassette.frames.length;
|
|
2799
3250
|
writeRunRecord(result, spec);
|
|
2800
|
-
writeAgentReport(reportPath, result);
|
|
3251
|
+
await writeAgentReport(reportPath, result, { config: options.config });
|
|
2801
3252
|
writeRunManifest(result);
|
|
2802
3253
|
}
|
|
2803
3254
|
return result;
|
package/dist/script.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as runScriptFile, t as runScript } from "./runner-
|
|
1
|
+
import { n as runScriptFile, t as runScript } from "./runner-BHXXwxYp.mjs";
|
|
2
2
|
export { runScript, runScriptFile };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as sameArgv, i as diffCommandMaps, n as validateManifestFiles, r as formatZodIssues, t as collectManifestFiles } from "./manifest_files-DW80c1H7.mjs";
|
|
2
2
|
import { i as portableCliPath, o as relativeHref, r as normalizePath, s as samePath } from "./env-DPYHo-zH.mjs";
|
|
3
|
-
import { a as jsonForHtml, c as scriptSchema, i as escapeHtml, l as SessionManager, o as ensureAsciinemaPlayerAssets, r as generateTraceReportHtml, s as formatSnapshotView, t as runScript } from "./runner-
|
|
3
|
+
import { a as jsonForHtml, c as scriptSchema, i as escapeHtml, l as SessionManager, o as ensureAsciinemaPlayerAssets, r as generateTraceReportHtml, s as formatSnapshotView, t as runScript } from "./runner-BHXXwxYp.mjs";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
@@ -144,7 +144,7 @@ var ScriptRecordingManager = class {
|
|
|
144
144
|
};
|
|
145
145
|
//#endregion
|
|
146
146
|
//#region package.json
|
|
147
|
-
var version = "0.
|
|
147
|
+
var version = "0.6.1";
|
|
148
148
|
//#endregion
|
|
149
149
|
//#region src/mcp/tool_result.ts
|
|
150
150
|
function toolError(message, extra = {}) {
|
package/dist/session.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as TerminalSession } from "./terminal_session-
|
|
1
|
+
import { t as TerminalSession } from "./terminal_session-MX_vWpRG.mjs";
|
|
2
2
|
export { TerminalSession };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//#region src/terminal/style.ts
|
|
2
|
+
const DEFAULT_STYLE = {
|
|
3
|
+
fg: { mode: "default" },
|
|
4
|
+
bg: { mode: "default" },
|
|
5
|
+
bold: false,
|
|
6
|
+
dim: false,
|
|
7
|
+
italic: false,
|
|
8
|
+
underline: false,
|
|
9
|
+
inverse: false,
|
|
10
|
+
strikethrough: false
|
|
11
|
+
};
|
|
12
|
+
function extractStyle(cell) {
|
|
13
|
+
const style = {
|
|
14
|
+
fg: extractColor(cell.isFgDefault(), cell.isFgPalette(), cell.isFgRGB(), cell.getFgColor()),
|
|
15
|
+
bg: extractColor(cell.isBgDefault(), cell.isBgPalette(), cell.isBgRGB(), cell.getBgColor()),
|
|
16
|
+
bold: cell.isBold() !== 0,
|
|
17
|
+
dim: cell.isDim() !== 0,
|
|
18
|
+
italic: cell.isItalic() !== 0,
|
|
19
|
+
underline: cell.isUnderline() !== 0,
|
|
20
|
+
inverse: cell.isInverse() !== 0,
|
|
21
|
+
strikethrough: cell.isStrikethrough() !== 0
|
|
22
|
+
};
|
|
23
|
+
return isDefaultStyle(style) ? DEFAULT_STYLE : style;
|
|
24
|
+
}
|
|
25
|
+
function isDefaultStyle(style) {
|
|
26
|
+
return style.fg.mode === "default" && style.bg.mode === "default" && !style.bold && !style.dim && !style.italic && !style.underline && !style.inverse && !style.strikethrough;
|
|
27
|
+
}
|
|
28
|
+
function styleKey(style) {
|
|
29
|
+
return [
|
|
30
|
+
style.fg.mode === "default" ? "d" : `${style.fg.mode}:${style.fg.value}`,
|
|
31
|
+
style.bg.mode === "default" ? "d" : `${style.bg.mode}:${style.bg.value}`,
|
|
32
|
+
style.bold ? "b" : "",
|
|
33
|
+
style.dim ? "d" : "",
|
|
34
|
+
style.italic ? "i" : "",
|
|
35
|
+
style.underline ? "u" : "",
|
|
36
|
+
style.inverse ? "r" : "",
|
|
37
|
+
style.strikethrough ? "s" : ""
|
|
38
|
+
].join("|");
|
|
39
|
+
}
|
|
40
|
+
function findMeaningfulEndCol(line, cols, nullCell) {
|
|
41
|
+
if (!line) return 0;
|
|
42
|
+
for (let x = cols - 1; x >= 0; x -= 1) {
|
|
43
|
+
const cell = line.getCell(x, nullCell);
|
|
44
|
+
if (!cell) continue;
|
|
45
|
+
if (cell.getWidth() === 0) continue;
|
|
46
|
+
const chars = cell.getChars();
|
|
47
|
+
const style = extractStyle(cell);
|
|
48
|
+
if (chars !== "" && chars !== " " || !isDefaultStyle(style)) return x + 1;
|
|
49
|
+
}
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
function extractColor(isDefault, isPalette, isRgb, value) {
|
|
53
|
+
if (isDefault) return { mode: "default" };
|
|
54
|
+
if (isRgb) return {
|
|
55
|
+
mode: "rgb",
|
|
56
|
+
value
|
|
57
|
+
};
|
|
58
|
+
if (isPalette) return {
|
|
59
|
+
mode: "palette",
|
|
60
|
+
value
|
|
61
|
+
};
|
|
62
|
+
return { mode: "default" };
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { styleKey as a, isDefaultStyle as i, extractStyle as n, findMeaningfulEndCol as r, DEFAULT_STYLE as t };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { a as styleKey, i as isDefaultStyle, n as extractStyle, r as findMeaningfulEndCol, t as DEFAULT_STYLE } from "./style-BtIUv5H0.mjs";
|
|
1
2
|
import { Terminal } from "@xterm/headless";
|
|
2
3
|
//#region src/terminal/keys.ts
|
|
3
4
|
const CSI = "\x1B[";
|
|
@@ -180,70 +181,6 @@ function clampInt(value, min, max) {
|
|
|
180
181
|
return int;
|
|
181
182
|
}
|
|
182
183
|
//#endregion
|
|
183
|
-
//#region src/terminal/style.ts
|
|
184
|
-
const DEFAULT_STYLE = {
|
|
185
|
-
fg: { mode: "default" },
|
|
186
|
-
bg: { mode: "default" },
|
|
187
|
-
bold: false,
|
|
188
|
-
dim: false,
|
|
189
|
-
italic: false,
|
|
190
|
-
underline: false,
|
|
191
|
-
inverse: false,
|
|
192
|
-
strikethrough: false
|
|
193
|
-
};
|
|
194
|
-
function extractStyle(cell) {
|
|
195
|
-
const style = {
|
|
196
|
-
fg: extractColor(cell.isFgDefault(), cell.isFgPalette(), cell.isFgRGB(), cell.getFgColor()),
|
|
197
|
-
bg: extractColor(cell.isBgDefault(), cell.isBgPalette(), cell.isBgRGB(), cell.getBgColor()),
|
|
198
|
-
bold: cell.isBold() !== 0,
|
|
199
|
-
dim: cell.isDim() !== 0,
|
|
200
|
-
italic: cell.isItalic() !== 0,
|
|
201
|
-
underline: cell.isUnderline() !== 0,
|
|
202
|
-
inverse: cell.isInverse() !== 0,
|
|
203
|
-
strikethrough: cell.isStrikethrough() !== 0
|
|
204
|
-
};
|
|
205
|
-
return isDefaultStyle(style) ? DEFAULT_STYLE : style;
|
|
206
|
-
}
|
|
207
|
-
function isDefaultStyle(style) {
|
|
208
|
-
return style.fg.mode === "default" && style.bg.mode === "default" && !style.bold && !style.dim && !style.italic && !style.underline && !style.inverse && !style.strikethrough;
|
|
209
|
-
}
|
|
210
|
-
function styleKey(style) {
|
|
211
|
-
return [
|
|
212
|
-
style.fg.mode === "default" ? "d" : `${style.fg.mode}:${style.fg.value}`,
|
|
213
|
-
style.bg.mode === "default" ? "d" : `${style.bg.mode}:${style.bg.value}`,
|
|
214
|
-
style.bold ? "b" : "",
|
|
215
|
-
style.dim ? "d" : "",
|
|
216
|
-
style.italic ? "i" : "",
|
|
217
|
-
style.underline ? "u" : "",
|
|
218
|
-
style.inverse ? "r" : "",
|
|
219
|
-
style.strikethrough ? "s" : ""
|
|
220
|
-
].join("|");
|
|
221
|
-
}
|
|
222
|
-
function findMeaningfulEndCol(line, cols, nullCell) {
|
|
223
|
-
if (!line) return 0;
|
|
224
|
-
for (let x = cols - 1; x >= 0; x -= 1) {
|
|
225
|
-
const cell = line.getCell(x, nullCell);
|
|
226
|
-
if (!cell) continue;
|
|
227
|
-
if (cell.getWidth() === 0) continue;
|
|
228
|
-
const chars = cell.getChars();
|
|
229
|
-
const style = extractStyle(cell);
|
|
230
|
-
if (chars !== "" && chars !== " " || !isDefaultStyle(style)) return x + 1;
|
|
231
|
-
}
|
|
232
|
-
return 0;
|
|
233
|
-
}
|
|
234
|
-
function extractColor(isDefault, isPalette, isRgb, value) {
|
|
235
|
-
if (isDefault) return { mode: "default" };
|
|
236
|
-
if (isRgb) return {
|
|
237
|
-
mode: "rgb",
|
|
238
|
-
value
|
|
239
|
-
};
|
|
240
|
-
if (isPalette) return {
|
|
241
|
-
mode: "palette",
|
|
242
|
-
value
|
|
243
|
-
};
|
|
244
|
-
return { mode: "default" };
|
|
245
|
-
}
|
|
246
|
-
//#endregion
|
|
247
184
|
//#region src/terminal/snapshot_rows.ts
|
|
248
185
|
function snapshotPlainLine(line, cols, nullCell, trimRight) {
|
|
249
186
|
let endCol = cols;
|
|
@@ -911,4 +848,4 @@ var TerminalSession = class {
|
|
|
911
848
|
}
|
|
912
849
|
};
|
|
913
850
|
//#endregion
|
|
914
|
-
export { fnv1a32 as a,
|
|
851
|
+
export { fnv1a32 as a, encodeSgrMouse as c, TraceRecorder as i, encodeKey as l, sleep as n, snapshotGrid as o, applyTextMaskRules as r, snapshotLines as s, TerminalSession as t };
|