@poe-platform/safe-bash 0.1.744 → 0.1.745
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 +5 -0
- package/dist/safe-bash/chunks/{chunk-2CO4WCMK.js → chunk-EAUCLWEZ.js} +16 -5
- package/dist/safe-bash/chunks/{chunk-WN7FYUWU.js → chunk-MC2KZY3D.js} +26 -13
- package/dist/safe-bash/chunks/{pdf-renderer-3TVUXNBT.js → pdf-renderer-4APIM7F7.js} +2 -2
- package/dist/safe-bash/chunks/{src-5VZS2ZKB.js → src-FTMTU65U.js} +2 -2
- package/dist/safe-bash/core.browser.js +1057 -619
- package/dist/safe-bash/opt-in/shell/extensions/read/index.js +1 -2
- package/dist/safe-bash/playwright/capability-events.d.ts +7 -0
- package/dist/safe-bash/playwright/capability-events.js +11 -3
- package/dist/safe-bash/playwright/controller.d.ts +14 -0
- package/dist/safe-bash/playwright/controller.js +36 -8
- package/dist/safe-bash/playwright/index.d.ts +1 -0
- package/dist/safe-bash/playwright/index.js +1 -0
- package/dist/safe-bash/shell/runtime.d.ts +14 -1
- package/dist/safe-bash/shell/runtime.js +1395 -717
- package/dist/safe-bash-command-ssconvert/index.js +15 -4
- package/dist/safe-bash-command-wkhtmltopdf/index.js +24 -11
- package/dist/safe-bash-command-wkhtmltopdf/limits.d.ts +1 -1
- package/dist/safe-bash-command-wkhtmltopdf/resources.d.ts +1 -1
- package/package.json +2 -2
|
@@ -2,6 +2,13 @@ import type { PlaywrightAbility } from './abilities.js';
|
|
|
2
2
|
import type { PlaywrightContext, PlaywrightPage } from './adapter.js';
|
|
3
3
|
import type { PlaywrightCommand } from './catalog.js';
|
|
4
4
|
import type { PlaywrightSessionConfiguration } from './session-configuration.js';
|
|
5
|
+
export interface PlaywrightNavigationSummary {
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly status?: number;
|
|
8
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
9
|
+
}
|
|
10
|
+
/** Read retained navigation metadata without browser I/O; absent after eviction or cleanup. */
|
|
11
|
+
export declare function getPlaywrightMainFrameNavigation(context: PlaywrightContext, page: PlaywrightPage): PlaywrightNavigationSummary | undefined;
|
|
5
12
|
export declare function observePlaywrightCapabilities(context: PlaywrightContext, registerCleanup: (cleanup: () => Promise<void>) => void, limits: {
|
|
6
13
|
maxCommandBytes: number;
|
|
7
14
|
maxArtifactBytes: number;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { PlaywrightResourceLimitError } from './resource-limit.js';
|
|
2
2
|
import { capabilityArtifact, capabilityArtifactName, capabilityResult, numeric, requirePage, requireSession, unsupported } from './capability-result.js';
|
|
3
3
|
const states = new WeakMap();
|
|
4
|
+
/** Read retained navigation metadata without browser I/O; absent after eviction or cleanup. */
|
|
5
|
+
export function getPlaywrightMainFrameNavigation(context, page) {
|
|
6
|
+
const record = states.get(context)?.pages.get(pageIdentity(page))?.requests[0];
|
|
7
|
+
if (!record?.mainFrameNavigation)
|
|
8
|
+
return undefined;
|
|
9
|
+
return { url: record.url, ...(record.response ? { status: record.response.status, headers: record.response.headers } : {}) };
|
|
10
|
+
}
|
|
4
11
|
// A host may wrap Page navigation methods while native events retain the raw Page.
|
|
5
12
|
// Playwright's main frame remains stable across those wrappers and navigations.
|
|
6
13
|
function pageIdentity(page) { return page.mainFrame?.() ?? page; }
|
|
@@ -60,7 +67,8 @@ export function observePlaywrightCapabilities(context, registerCleanup, limits)
|
|
|
60
67
|
} // Worker-only requests have no selected page.
|
|
61
68
|
const page = frame.page();
|
|
62
69
|
const events = pageEvents(page);
|
|
63
|
-
|
|
70
|
+
const mainFrameNavigation = native.isNavigationRequest() && frame.parentFrame() === null;
|
|
71
|
+
if (mainFrameNavigation) {
|
|
64
72
|
for (const record of [...events.requests])
|
|
65
73
|
forget(record);
|
|
66
74
|
events.nextRequestIndex = 0;
|
|
@@ -69,7 +77,7 @@ export function observePlaywrightCapabilities(context, registerCleanup, limits)
|
|
|
69
77
|
delete events.log;
|
|
70
78
|
events.consoleCursor = events.nextConsoleIndex;
|
|
71
79
|
}
|
|
72
|
-
const record = { index: ++events.nextRequestIndex, native, url: native.url(), method: native.method(), type: native.resourceType(), headers: { ...native.headers() } };
|
|
80
|
+
const record = { index: ++events.nextRequestIndex, native, url: native.url(), method: native.method(), type: native.resourceType(), headers: { ...native.headers() }, mainFrameNavigation };
|
|
73
81
|
requests.set(native, record);
|
|
74
82
|
events.requests.push(record);
|
|
75
83
|
// Keep native body access lazy: copying postData here turns uploads into a
|
|
@@ -83,7 +91,7 @@ export function observePlaywrightCapabilities(context, registerCleanup, limits)
|
|
|
83
91
|
const record = requests.get(native.request());
|
|
84
92
|
if (!record)
|
|
85
93
|
return;
|
|
86
|
-
const response = { native, status: native.status(), statusText: native.statusText(), headers: { ...native.headers() } };
|
|
94
|
+
const response = { native, status: native.status(), statusText: native.statusText(), headers: Object.freeze({ ...native.headers() }) };
|
|
87
95
|
record.response = response;
|
|
88
96
|
const retained = history.get(record);
|
|
89
97
|
retain(record, retained.bytes + byteLength(JSON.stringify({ status: response.status, statusText: response.statusText, headers: response.headers })), retained.evict);
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import type { PlaywrightAdapter, PlaywrightContext, PlaywrightContextOptions, PlaywrightLease, PlaywrightPage } from './adapter.js';
|
|
2
2
|
import { type PlaywrightInvocation } from './invocation.js';
|
|
3
3
|
import { type PlaywrightAbilities } from './abilities.js';
|
|
4
|
+
import { type PlaywrightNavigationSummary } from './capability-events.js';
|
|
4
5
|
import { type PlaywrightSessionConfiguration } from './session-configuration.js';
|
|
5
6
|
import { type PlaywrightCheckpointOutcome } from './checkpoint.js';
|
|
6
7
|
import { type PlaywrightOperationOutcome, type PlaywrightRecoveryResult } from './recovery.js';
|
|
8
|
+
export interface PlaywrightSnapshotHookContext<TSnapshot> {
|
|
9
|
+
readonly command: string;
|
|
10
|
+
readonly format: 'yaml' | 'json';
|
|
11
|
+
readonly context: PlaywrightContext;
|
|
12
|
+
readonly page: PlaywrightPage;
|
|
13
|
+
readonly snapshot: TSnapshot;
|
|
14
|
+
readonly navigation?: PlaywrightNavigationSummary;
|
|
15
|
+
readonly signal: AbortSignal;
|
|
16
|
+
recapture(): Promise<TSnapshot>;
|
|
17
|
+
}
|
|
18
|
+
export type PlaywrightSnapshotHook = <TSnapshot>(request: PlaywrightSnapshotHookContext<TSnapshot>) => Promise<TSnapshot>;
|
|
7
19
|
export interface PlaywrightControllerOptions {
|
|
8
20
|
/** Clock for fallback operation receipts, retained for at most 24 hours across 16 aliases. */
|
|
9
21
|
readonly operationClock?: () => number;
|
|
10
22
|
readonly adapter?: PlaywrightAdapter;
|
|
23
|
+
/** Runs inside the command queue after capture. Recapture does not invoke the hook again. */
|
|
24
|
+
readonly onSnapshot?: PlaywrightSnapshotHook;
|
|
11
25
|
readonly abilities?: PlaywrightAbilities;
|
|
12
26
|
readonly persistence?: PlaywrightSessionPersistence;
|
|
13
27
|
/** Opt in only when this controller and persistence are bound to one authenticated owner. */
|
|
@@ -9,7 +9,7 @@ import { PlaywrightReportedError, playwrightCliCompatibilityVersion, playwrightC
|
|
|
9
9
|
import { capabilityArtifactName } from './capability-result.js';
|
|
10
10
|
import { isPlaywrightSnapshotRef, resolvePlaywrightTarget } from './targets.js';
|
|
11
11
|
import { capturePlaywrightTargetScreenshot } from './target-screenshot.js';
|
|
12
|
-
import { flushPlaywrightConsole, observePlaywrightCapabilities } from './capability-events.js';
|
|
12
|
+
import { flushPlaywrightConsole, getPlaywrightMainFrameNavigation, observePlaywrightCapabilities } from './capability-events.js';
|
|
13
13
|
import { getPlaywrightModal, observePlaywrightModals, onPlaywrightModal } from './modal-capabilities.js';
|
|
14
14
|
import { findPlaywrightSnapshot } from './find.js';
|
|
15
15
|
import { collectPlaywrightDownloads, observePlaywrightDownloads } from './download-capabilities.js';
|
|
@@ -30,8 +30,10 @@ export function createPlaywrightController(options = {}) {
|
|
|
30
30
|
throw new TypeError('Invalid Playwright configuration');
|
|
31
31
|
if (options.adapter !== undefined && (!options.adapter || typeof options.adapter.acquire !== 'function'))
|
|
32
32
|
throw new TypeError('An injected Playwright adapter is required');
|
|
33
|
-
if (Object.keys(options).some(key => !['adapter', 'abilities', 'limits', 'billing', 'persistence', 'namedSessionAttachment', 'operationClock'].includes(key)))
|
|
33
|
+
if (Object.keys(options).some(key => !['adapter', 'abilities', 'limits', 'billing', 'persistence', 'namedSessionAttachment', 'operationClock', 'onSnapshot'].includes(key)))
|
|
34
34
|
throw new TypeError('Unsupported Playwright configuration');
|
|
35
|
+
if (options.onSnapshot !== undefined && typeof options.onSnapshot !== 'function')
|
|
36
|
+
throw new TypeError('Invalid Playwright snapshot hook');
|
|
35
37
|
if (options.operationClock !== undefined && typeof options.operationClock !== 'function')
|
|
36
38
|
throw new TypeError('Invalid Playwright operation clock');
|
|
37
39
|
if (options.namedSessionAttachment !== undefined && typeof options.namedSessionAttachment !== 'boolean')
|
|
@@ -966,10 +968,7 @@ export function createPlaywrightController(options = {}) {
|
|
|
966
968
|
if (consoleLink)
|
|
967
969
|
sections.push({ title: 'Events', content: `- New console entries: ${consoleLink}` });
|
|
968
970
|
}
|
|
969
|
-
|
|
970
|
-
const title = await page.title?.();
|
|
971
|
-
sections.push({ title: 'Page', content: `- Page URL: ${page.url()}${title === undefined ? '' : `\n- Page Title: ${title}`}` });
|
|
972
|
-
}
|
|
971
|
+
const pageSectionIndex = sections.length;
|
|
973
972
|
if (snapshot !== 'none' && (page.frames || page.ariaSnapshot || page._snapshotForAI || page.ariaSnapshotJSON || session.lease?.captureSnapshotJSON)) {
|
|
974
973
|
const snapshotOptions = { timeout: sessionSnapshotTimeout(session), ...(session.configuration?.snapshot?.boxes === undefined ? {} : { boxes: session.configuration.snapshot.boxes }), ...(session.lease?.captureSnapshotReferences ? { captureReferences: session.lease.captureSnapshotReferences } : {}) };
|
|
975
974
|
if (parsed.command === 'snapshot') {
|
|
@@ -984,16 +983,40 @@ export function createPlaywrightController(options = {}) {
|
|
|
984
983
|
if (parsed.args[0])
|
|
985
984
|
snapshotOptions.root = await resolveTarget(session, parsed.args[0]);
|
|
986
985
|
}
|
|
986
|
+
const captureWithHook = async (format, capture) => {
|
|
987
|
+
let active = true;
|
|
988
|
+
const recapture = async () => {
|
|
989
|
+
if (!active)
|
|
990
|
+
throw new Error('Playwright snapshot hook has completed');
|
|
991
|
+
check();
|
|
992
|
+
const value = await capture();
|
|
993
|
+
check();
|
|
994
|
+
return value;
|
|
995
|
+
};
|
|
996
|
+
try {
|
|
997
|
+
const initial = await recapture();
|
|
998
|
+
if (!options.onSnapshot)
|
|
999
|
+
return initial;
|
|
1000
|
+
const navigation = getPlaywrightMainFrameNavigation(session.lease.context, page);
|
|
1001
|
+
const result = await options.onSnapshot({ command: parsed.command, format, context: session.lease.context, page,
|
|
1002
|
+
snapshot: initial, ...(navigation ? { navigation } : {}), signal: local.signal, recapture });
|
|
1003
|
+
check();
|
|
1004
|
+
return result;
|
|
1005
|
+
}
|
|
1006
|
+
finally {
|
|
1007
|
+
active = false;
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
987
1010
|
retained = false;
|
|
988
1011
|
if (parsed.command === 'snapshot' && parsed.json && filename === undefined) {
|
|
989
|
-
const tree = await session.snapshot.captureJSON(page, local.signal, { ...snapshotOptions, ...(session.lease?.captureSnapshotJSON ? { captureJSON: session.lease.captureSnapshotJSON } : {}) });
|
|
1012
|
+
const tree = await captureWithHook('json', () => session.snapshot.captureJSON(page, local.signal, { ...snapshotOptions, ...(session.lease?.captureSnapshotJSON ? { captureJSON: session.lease.captureSnapshotJSON } : {}) }));
|
|
990
1013
|
check();
|
|
991
1014
|
retained = parsed.command === 'snapshot';
|
|
992
1015
|
sections.push({ title: 'Snapshot', content: { json: tree }, codeframe: 'json' });
|
|
993
1016
|
return { sections };
|
|
994
1017
|
}
|
|
995
1018
|
retained = false;
|
|
996
|
-
const text = await session.snapshot.capture(page, local.signal, snapshotOptions);
|
|
1019
|
+
const text = await captureWithHook('yaml', () => session.snapshot.capture(page, local.signal, snapshotOptions));
|
|
997
1020
|
check();
|
|
998
1021
|
retained = parsed.command === 'snapshot';
|
|
999
1022
|
if (filename !== undefined || snapshot === 'file' && invocation.writeArtifact) {
|
|
@@ -1009,6 +1032,11 @@ export function createPlaywrightController(options = {}) {
|
|
|
1009
1032
|
else
|
|
1010
1033
|
sections.push({ title: 'Snapshot', content: text.trimEnd(), codeframe: 'yaml' });
|
|
1011
1034
|
}
|
|
1035
|
+
if (parsed.command !== 'snapshot' || !parsed.json) {
|
|
1036
|
+
const title = await page.title?.();
|
|
1037
|
+
check();
|
|
1038
|
+
sections.splice(pageSectionIndex, 0, { title: 'Page', content: `- Page URL: ${page.url()}${title === undefined ? '' : `\n- Page Title: ${title}`}` });
|
|
1039
|
+
}
|
|
1012
1040
|
return { sections };
|
|
1013
1041
|
};
|
|
1014
1042
|
const checkSession = (session) => {
|
|
@@ -2,6 +2,7 @@ export * from './adapter.js';
|
|
|
2
2
|
export { parseBrowserProfile, encodeBrowserProfile, restoreBrowserProfile, checkpointBrowserProfile, type BrowserProfile, type BrowserProfileLimits, type BrowserProfileContext } from './profile.js';
|
|
3
3
|
export * from './billing.js';
|
|
4
4
|
export * from './controller.js';
|
|
5
|
+
export { getPlaywrightMainFrameNavigation, type PlaywrightNavigationSummary } from './capability-events.js';
|
|
5
6
|
export { parsePlaywrightOperationOutcome, type PlaywrightRecoveryResult, type PlaywrightOperationOutcome } from './recovery.js';
|
|
6
7
|
export * from './catalog.js';
|
|
7
8
|
export * from './network-policy.js';
|
|
@@ -2,6 +2,7 @@ export * from './adapter.js';
|
|
|
2
2
|
export { parseBrowserProfile, encodeBrowserProfile, restoreBrowserProfile, checkpointBrowserProfile } from './profile.js';
|
|
3
3
|
export * from './billing.js';
|
|
4
4
|
export * from './controller.js';
|
|
5
|
+
export { getPlaywrightMainFrameNavigation } from './capability-events.js';
|
|
5
6
|
export { parsePlaywrightOperationOutcome } from './recovery.js';
|
|
6
7
|
export * from './catalog.js';
|
|
7
8
|
export * from './network-policy.js';
|
|
@@ -506,6 +506,7 @@ export declare class Runtime {
|
|
|
506
506
|
private trySyncScript;
|
|
507
507
|
private isPureSyncValueWord;
|
|
508
508
|
private extractPosixBracketCondExpr;
|
|
509
|
+
private execSyncUnsetStep;
|
|
509
510
|
private extractSyncUnsetVars;
|
|
510
511
|
private extractSyncShiftCount;
|
|
511
512
|
private extractSyncLocalDeclStep;
|
|
@@ -514,6 +515,7 @@ export declare class Runtime {
|
|
|
514
515
|
private evalSyncNestedForWords;
|
|
515
516
|
private isSyncEchoCallOk;
|
|
516
517
|
private extractSyncReadHereStringSpec;
|
|
518
|
+
private isPureSyncSubIfOrCase;
|
|
517
519
|
private canSyncLoopBody;
|
|
518
520
|
private extractIntLoopStep;
|
|
519
521
|
private buildSyncLoopBody;
|
|
@@ -527,10 +529,10 @@ export declare class Runtime {
|
|
|
527
529
|
private canSyncPrintfInductionBody;
|
|
528
530
|
private isSyncPrintfCallOk;
|
|
529
531
|
private isSimpleRedirectEchoWord;
|
|
532
|
+
private execSyncReadHereStringStep;
|
|
530
533
|
private splitSyncReadLine;
|
|
531
534
|
private execSyncLocalDeclStep;
|
|
532
535
|
private _syncTouchedPositionals;
|
|
533
|
-
private _syncPendingVarAttrs;
|
|
534
536
|
private flushSyncPositionals;
|
|
535
537
|
private execSyncShiftStep;
|
|
536
538
|
private evalSyncPrintfStep;
|
|
@@ -666,6 +668,17 @@ export declare class Runtime {
|
|
|
666
668
|
}>, value: ShellValue, state: State, io: IO, hereString: boolean): Promise<ShellValue>;
|
|
667
669
|
word(word: Word, state: State, io: IO, split?: boolean, pattern?: boolean, hereString?: boolean, conditionalPattern?: boolean, regexAppend?: (text: string, literal: boolean, value: ShellValue) => void): Promise<string[]>;
|
|
668
670
|
private fastValueWord;
|
|
671
|
+
private expandSyncTrCharArray;
|
|
672
|
+
private evalSyncTr;
|
|
673
|
+
private evalSyncJq;
|
|
674
|
+
private parseSyncCutSpec;
|
|
675
|
+
private evalSyncCut;
|
|
676
|
+
private evalSyncSed;
|
|
677
|
+
private evalSyncGrep;
|
|
678
|
+
private evalSyncAwk;
|
|
679
|
+
private formatSyncTransformQ;
|
|
680
|
+
private sortSyncLines;
|
|
681
|
+
private translateSyncTr;
|
|
669
682
|
private expandSyncTrCharSet;
|
|
670
683
|
private syncBase64Encode;
|
|
671
684
|
private syncBase64DecodeBytes;
|