@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.
@@ -128,8 +128,7 @@ async function parse(context, validate) {
128
128
  }
129
129
  else {
130
130
  options.count = number;
131
- if (flag === "N")
132
- options.exact = true;
131
+ options.exact = flag === "N";
133
132
  }
134
133
  }
135
134
  break;
@@ -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
- if (native.isNavigationRequest() && frame.parentFrame() === null) {
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
- if (parsed.command !== 'snapshot' || !parsed.json) {
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;