@poe-platform/safe-bash 0.1.714 → 0.1.716
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 +7 -0
- package/dist/safe-bash/commands/playwright/index.d.ts.map +1 -1
- package/dist/safe-bash/playwright/controller.d.ts +2 -0
- package/dist/safe-bash/playwright/controller.d.ts.map +1 -1
- package/dist/safe-bash/playwright/controller.js +112 -32
- package/dist/safe-bash/playwright/controller.js.map +1 -1
- package/dist/safe-bash/playwright/help.d.ts +1 -1
- package/dist/safe-bash/playwright/help.d.ts.map +1 -1
- package/dist/safe-bash/playwright/help.js +3 -1
- package/dist/safe-bash/playwright/help.js.map +1 -1
- package/dist/safe-bash/playwright/invocation.d.ts +1 -0
- package/dist/safe-bash/playwright/invocation.d.ts.map +1 -1
- package/dist/safe-bash/playwright/invocation.js +1 -1
- package/dist/safe-bash/playwright/invocation.js.map +1 -1
- package/dist/safe-bash-mcp/index.d.ts +1339 -0
- package/dist/safe-bash-mcp/index.js +15221 -0
- package/dist/safe-playwright-cloudflare/browser-code-executor.d.ts +1 -1
- package/dist/safe-playwright-cloudflare/shell-browser-resource.d.ts +1 -1
- package/dist/safe-playwright-cloudflare/shell-playwright.d.ts +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -295,6 +295,13 @@ Portable browser profiles restore blank tabs by default, preserving storage,
|
|
|
295
295
|
settings, tab count, and selection. Only pass `tabRestoration: 'navigate'` to
|
|
296
296
|
`restoreBrowserProfile` when replaying saved URLs is authorized; action URLs can
|
|
297
297
|
repeat effects. Use `recovery: true` to also suppress configuration and provider scripts.
|
|
298
|
+
Owner-bound hosts can enable `namedSessionAttachment: true` on
|
|
299
|
+
`createPlaywrightCli({ adapter, persistence, ... })` to support `attach NAME`.
|
|
300
|
+
It selects an existing live session or restores its committed resumable profile
|
|
301
|
+
for subsequent invocations with the same `PLAYWRIGHT_CLI_SESSION` default,
|
|
302
|
+
including an authenticated agent ID different from the target name. Explicit
|
|
303
|
+
`-s=NAME` overrides selection; `detach` retains the browser, while `close` retires it. See the
|
|
304
|
+
[host capability contract](src/contracts/playwright-sessions.md#persistence).
|
|
298
305
|
|
|
299
306
|
For Cloudflare Workers, start with the exported `cloudflareWorkerLimits` profile
|
|
300
307
|
and configure command-family buffers at no more than 8 MiB. Create a separate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/playwright/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACpI,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMpE,MAAM,MAAM,oBAAoB,GAAG,2BAA2B,GAAG;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAiBhG,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/playwright/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACpI,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMpE,MAAM,MAAM,oBAAoB,GAAG,2BAA2B,GAAG;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAiBhG,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB;;;;;;;uBAiGw1iB,CAAC;;EAH95iB;AAED,cAAc,2BAA2B,CAAC"}
|
|
@@ -8,6 +8,8 @@ export interface PlaywrightControllerOptions {
|
|
|
8
8
|
readonly adapter?: PlaywrightAdapter;
|
|
9
9
|
readonly abilities?: PlaywrightAbilities;
|
|
10
10
|
readonly persistence?: PlaywrightSessionPersistence;
|
|
11
|
+
/** Opt in only when this controller and persistence are bound to one authenticated owner. */
|
|
12
|
+
readonly namedSessionAttachment?: boolean;
|
|
11
13
|
readonly limits?: {
|
|
12
14
|
readonly maxSessions?: number;
|
|
13
15
|
readonly actionTimeoutMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/playwright/controller.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/playwright/controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -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'].includes(key)))
|
|
33
|
+
if (Object.keys(options).some(key => !['adapter', 'abilities', 'limits', 'billing', 'persistence', 'namedSessionAttachment'].includes(key)))
|
|
34
34
|
throw new TypeError('Unsupported Playwright configuration');
|
|
35
|
+
if (options.namedSessionAttachment !== undefined && typeof options.namedSessionAttachment !== 'boolean')
|
|
36
|
+
throw new TypeError('Invalid named session attachment capability');
|
|
35
37
|
if (options.persistence && ['restore', 'checkpoint', 'delete'].some(key => typeof Reflect.get(options.persistence, key) !== 'function'))
|
|
36
38
|
throw new TypeError('Invalid Playwright persistence');
|
|
37
39
|
if (options.persistence?.close !== undefined && typeof options.persistence.close !== 'function')
|
|
@@ -60,8 +62,14 @@ export function createPlaywrightController(options = {}) {
|
|
|
60
62
|
if (!Number.isSafeInteger(value) || value < 1)
|
|
61
63
|
throw new RangeError('Invalid Playwright limit');
|
|
62
64
|
const sessions = new Map();
|
|
65
|
+
const pendingRestores = new Set();
|
|
66
|
+
const occupiedSessions = (except) => new Set([
|
|
67
|
+
...[...sessions.values()].filter(session => session.state !== 'closed').map(session => session.name),
|
|
68
|
+
...pendingRestores,
|
|
69
|
+
].filter(name => name !== except)).size;
|
|
63
70
|
const outcomes = new Map();
|
|
64
71
|
const explicitlyClosed = new Set();
|
|
72
|
+
let attachedSession;
|
|
65
73
|
let suppressUnknownRestores = false;
|
|
66
74
|
const tails = new Map();
|
|
67
75
|
const work = new Set();
|
|
@@ -371,7 +379,7 @@ export function createPlaywrightController(options = {}) {
|
|
|
371
379
|
if (previous?.releasing)
|
|
372
380
|
await previous.releasing;
|
|
373
381
|
check();
|
|
374
|
-
if (
|
|
382
|
+
if (occupiedSessions(name) >= maxSessions)
|
|
375
383
|
throw new PlaywrightResourceLimitError('Playwright session capacity exceeded');
|
|
376
384
|
const epoch = Array.from(crypto.getRandomValues(new Uint32Array(4)), value => String(value).padStart(10, '0')).join('');
|
|
377
385
|
const session = { name, generation: ++generation, state: 'acquiring', cleanups: new Set(),
|
|
@@ -387,6 +395,9 @@ export function createPlaywrightController(options = {}) {
|
|
|
387
395
|
void release(session).catch(() => { }); };
|
|
388
396
|
try {
|
|
389
397
|
const restored = await acquire.call(request, { signal });
|
|
398
|
+
if ([...sessions.values()].some(other => other !== session && other.state !== 'closed' && other.lease
|
|
399
|
+
&& (other.lease === restored.lease || other.lease.context === restored.lease?.context)))
|
|
400
|
+
throw new TypeError('Restored Playwright lease is already owned by another session');
|
|
390
401
|
session.lease = restored.lease;
|
|
391
402
|
if (restored.recovery === 'saved-storage')
|
|
392
403
|
session.recovery = 'saved-storage';
|
|
@@ -449,6 +460,50 @@ export function createPlaywrightController(options = {}) {
|
|
|
449
460
|
work.delete(operation);
|
|
450
461
|
}
|
|
451
462
|
};
|
|
463
|
+
// Called only while holding this name's queue. Persistence returns a fresh
|
|
464
|
+
// owned lease from its last committed resumable profile.
|
|
465
|
+
const restorePersistedSession = async (name, signal) => {
|
|
466
|
+
signal.throwIfAborted();
|
|
467
|
+
if (!options.persistence || explicitlyClosed.has(name) || suppressUnknownRestores && !sessions.has(name))
|
|
468
|
+
return;
|
|
469
|
+
const current = sessions.get(name);
|
|
470
|
+
if (current && current.state !== 'closed')
|
|
471
|
+
return;
|
|
472
|
+
if (current?.releasing)
|
|
473
|
+
await current.releasing;
|
|
474
|
+
if (occupiedSessions(name) >= maxSessions)
|
|
475
|
+
throw new PlaywrightResourceLimitError('Playwright session capacity exceeded');
|
|
476
|
+
pendingRestores.add(name);
|
|
477
|
+
try {
|
|
478
|
+
const restored = await options.persistence.restore({ name, signal });
|
|
479
|
+
if (!restored)
|
|
480
|
+
return;
|
|
481
|
+
let transferred = false;
|
|
482
|
+
try {
|
|
483
|
+
await restoreSession({ name, signal,
|
|
484
|
+
...(restored.recovery === undefined ? {} : { recovery: restored.recovery }),
|
|
485
|
+
...(restored.expiresAt === undefined ? {} : { expiresAt: restored.expiresAt }),
|
|
486
|
+
...(restored.idleTimeoutMs === undefined ? {} : { idleTimeoutMs: restored.idleTimeoutMs }),
|
|
487
|
+
...(restored.contextOptions === undefined ? {} : { contextOptions: restored.contextOptions }),
|
|
488
|
+
...(restored.configuration === undefined ? {} : { configuration: restored.configuration }),
|
|
489
|
+
acquire: async () => { transferred = true; return restored; } }, true);
|
|
490
|
+
}
|
|
491
|
+
catch (error) {
|
|
492
|
+
if (!transferred) {
|
|
493
|
+
try {
|
|
494
|
+
await restored.lease.release();
|
|
495
|
+
}
|
|
496
|
+
catch (cleanupError) {
|
|
497
|
+
throw new AggregateError([error, cleanupError], 'Playwright restoration and cleanup failed');
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
throw error;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
finally {
|
|
504
|
+
pendingRestores.delete(name);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
452
507
|
const run = async (invocation) => {
|
|
453
508
|
const commandBudget = createPlaywrightCommandBudget(maxCommandBytes);
|
|
454
509
|
let reportedError = false;
|
|
@@ -463,6 +518,9 @@ export function createPlaywrightController(options = {}) {
|
|
|
463
518
|
if (lifetime.signal.aborted)
|
|
464
519
|
throw new Error('Playwright controller is disposed');
|
|
465
520
|
const parsed = parseInvocation(invocation, abilities, options.adapter);
|
|
521
|
+
const defaultSelection = invocation.env.PLAYWRIGHT_CLI_SESSION ?? 'default';
|
|
522
|
+
if ('session' in parsed && options.namedSessionAttachment && parsed.command !== 'attach' && !parsed.explicitSession && attachedSession?.selection === defaultSelection)
|
|
523
|
+
parsed.session = attachedSession.name;
|
|
466
524
|
if (invocation.operationId !== undefined)
|
|
467
525
|
validatePlaywrightSessionName(invocation.operationId);
|
|
468
526
|
const operationId = invocation.operationId ?? (options.persistence?.recordOperation ? crypto.randomUUID() : undefined);
|
|
@@ -851,7 +909,7 @@ export function createPlaywrightController(options = {}) {
|
|
|
851
909
|
const execute = async () => {
|
|
852
910
|
check();
|
|
853
911
|
if (parsed.command === 'help') {
|
|
854
|
-
const help = formatPlaywrightHelp(parsed.topic, abilities);
|
|
912
|
+
const help = formatPlaywrightHelp(parsed.topic, abilities, options.namedSessionAttachment);
|
|
855
913
|
await write(parsed.json ? JSON.stringify({ help: help.trimEnd() }, null, 2) + '\n' : help);
|
|
856
914
|
check();
|
|
857
915
|
return;
|
|
@@ -868,9 +926,49 @@ export function createPlaywrightController(options = {}) {
|
|
|
868
926
|
throw new Error('only one of [name], --cdp, --endpoint, or --extension can be specified');
|
|
869
927
|
if (!targets.length || parsed.options.extension === true)
|
|
870
928
|
throw new Error('no target specified for attach command; use one of [name], --cdp, --endpoint, or --extension to specify the target to attach to.');
|
|
871
|
-
|
|
929
|
+
if (!options.namedSessionAttachment)
|
|
930
|
+
throw new Error('An authenticated browser attachment broker is unavailable in this host');
|
|
931
|
+
if (Object.keys(parsed.options).length)
|
|
932
|
+
throw new Error('Only owner-scoped named session attachment is supported; attachment options are unavailable');
|
|
933
|
+
const name = parsed.args[0];
|
|
934
|
+
validatePlaywrightSessionName(name);
|
|
935
|
+
if (parsed.explicitSession && parsed.session !== name)
|
|
936
|
+
throw new Error('Attachment session must match the owned target name');
|
|
937
|
+
await enqueue(name, async () => {
|
|
938
|
+
check();
|
|
939
|
+
await retireExpired();
|
|
940
|
+
if (explicitlyClosed.has(name))
|
|
941
|
+
throw new Error(`Session closed: ${name}; reopen explicitly`);
|
|
942
|
+
const wasLive = sessions.get(name)?.state === 'open';
|
|
943
|
+
if (!wasLive && options.persistence?.list && !(await savedSessions(local.signal)).some(saved => saved.name === name))
|
|
944
|
+
throw new Error(`No resumable owned session: ${name}`);
|
|
945
|
+
await restorePersistedSession(name, local.signal);
|
|
946
|
+
const session = sessions.get(name);
|
|
947
|
+
if (!session || session.state !== 'open')
|
|
948
|
+
throw new Error(`No resumable owned session: ${name}`);
|
|
949
|
+
if (!wasLive)
|
|
950
|
+
active = session;
|
|
951
|
+
checkSession(session);
|
|
952
|
+
// Selection owns no lease and does not reset or checkpoint live state.
|
|
953
|
+
await write(parsed.json ? JSON.stringify({ session: name, status: 'attached' }, null, 2) + '\n' : `Browser '${name}' attached.\n`);
|
|
954
|
+
checkSession(session);
|
|
955
|
+
attachedSession = { name, selection: defaultSelection };
|
|
956
|
+
retained = true;
|
|
957
|
+
});
|
|
958
|
+
return;
|
|
872
959
|
}
|
|
873
960
|
if (parsed.command === 'detach' && !ability.execute) {
|
|
961
|
+
if (options.namedSessionAttachment) {
|
|
962
|
+
await enqueue(parsed.session, async () => {
|
|
963
|
+
check();
|
|
964
|
+
const attached = attachedSession?.name === parsed.session;
|
|
965
|
+
await write(parsed.json ? JSON.stringify({ session: parsed.session, status: attached ? 'detached' : 'not-attached' }, null, 2) + '\n'
|
|
966
|
+
: `Browser '${parsed.session}' is ${attached ? 'detached' : 'not attached'}.\n`);
|
|
967
|
+
if (attachedSession?.name === parsed.session)
|
|
968
|
+
attachedSession = undefined;
|
|
969
|
+
});
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
874
972
|
const known = sessions.has(parsed.session) || (await savedSessions(local.signal)).some(session => session.name === parsed.session);
|
|
875
973
|
if (known)
|
|
876
974
|
throw new Error(parsed.json ? `session '${parsed.session}' was not attached; use close to stop it.` : `session '${parsed.session}' was not attached; use \`playwright-cli${parsed.session === 'default' ? '' : ` -s=${parsed.session}`} close\` to stop it.`);
|
|
@@ -912,6 +1010,7 @@ export function createPlaywrightController(options = {}) {
|
|
|
912
1010
|
if ((parsed.command === 'close-all' || parsed.command === 'kill-all') && !ability.execute) {
|
|
913
1011
|
const saved = await savedSessions(local.signal);
|
|
914
1012
|
suppressUnknownRestores = true;
|
|
1013
|
+
attachedSession = undefined;
|
|
915
1014
|
const closed = [...new Set([...saved.map(session => session.name), ...[...sessions.values()].filter(session => session.state === 'open').map(session => session.name)])];
|
|
916
1015
|
if (parsed.command === 'kill-all')
|
|
917
1016
|
for (const session of sessions.values())
|
|
@@ -919,6 +1018,8 @@ export function createPlaywrightController(options = {}) {
|
|
|
919
1018
|
const results = await Promise.allSettled([...new Set([...sessions.keys(), ...tails.keys()])].map(name => enqueue(name, async () => {
|
|
920
1019
|
check();
|
|
921
1020
|
explicitlyClosed.add(name);
|
|
1021
|
+
if (attachedSession?.name === name)
|
|
1022
|
+
attachedSession = undefined;
|
|
922
1023
|
const session = sessions.get(name);
|
|
923
1024
|
if (session)
|
|
924
1025
|
await retireForCommand(session, parsed.command === 'kill-all');
|
|
@@ -952,33 +1053,8 @@ export function createPlaywrightController(options = {}) {
|
|
|
952
1053
|
let commandFailure;
|
|
953
1054
|
await (async () => {
|
|
954
1055
|
check();
|
|
955
|
-
if (
|
|
956
|
-
|
|
957
|
-
&& (!sessions.has(parsed.session) || sessions.get(parsed.session).state === 'closed')) {
|
|
958
|
-
const restored = await options.persistence.restore({ name: parsed.session, signal: local.signal });
|
|
959
|
-
if (restored) {
|
|
960
|
-
let transferred = false;
|
|
961
|
-
try {
|
|
962
|
-
await restoreSession({ name: parsed.session, signal: local.signal,
|
|
963
|
-
...(restored.recovery === undefined ? {} : { recovery: restored.recovery }),
|
|
964
|
-
...(restored.expiresAt === undefined ? {} : { expiresAt: restored.expiresAt }),
|
|
965
|
-
...(restored.idleTimeoutMs === undefined ? {} : { idleTimeoutMs: restored.idleTimeoutMs }),
|
|
966
|
-
...(restored.contextOptions === undefined ? {} : { contextOptions: restored.contextOptions }),
|
|
967
|
-
...(restored.configuration === undefined ? {} : { configuration: restored.configuration }),
|
|
968
|
-
acquire: async () => { transferred = true; return restored; } }, true);
|
|
969
|
-
}
|
|
970
|
-
catch (error) {
|
|
971
|
-
if (!transferred) {
|
|
972
|
-
try {
|
|
973
|
-
await restored.lease.release();
|
|
974
|
-
}
|
|
975
|
-
catch (cleanupError) {
|
|
976
|
-
throw new AggregateError([error, cleanupError], 'Playwright restoration and cleanup failed');
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
throw error;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
1056
|
+
if (ability.scope === 'session' && !['open', 'close', 'close-all', 'list', 'delete-data'].includes(parsed.command)) {
|
|
1057
|
+
await restorePersistedSession(parsed.session, local.signal);
|
|
982
1058
|
check();
|
|
983
1059
|
}
|
|
984
1060
|
const current = sessions.get(parsed.session);
|
|
@@ -1108,6 +1184,8 @@ export function createPlaywrightController(options = {}) {
|
|
|
1108
1184
|
const session = sessions.get(parsed.session);
|
|
1109
1185
|
const wasOpen = session?.state === 'open' || (await savedSessions(local.signal)).some(saved => saved.name === parsed.session);
|
|
1110
1186
|
explicitlyClosed.add(parsed.session);
|
|
1187
|
+
if (attachedSession?.name === parsed.session)
|
|
1188
|
+
attachedSession = undefined;
|
|
1111
1189
|
const errors = [];
|
|
1112
1190
|
try {
|
|
1113
1191
|
if (session)
|
|
@@ -1134,6 +1212,8 @@ export function createPlaywrightController(options = {}) {
|
|
|
1134
1212
|
if (parsed.command === 'delete-data') {
|
|
1135
1213
|
const session = sessions.get(parsed.session);
|
|
1136
1214
|
explicitlyClosed.add(parsed.session);
|
|
1215
|
+
if (attachedSession?.name === parsed.session)
|
|
1216
|
+
attachedSession = undefined;
|
|
1137
1217
|
const errors = [];
|
|
1138
1218
|
try {
|
|
1139
1219
|
if (session && session.state !== 'closed')
|
|
@@ -1172,7 +1252,7 @@ export function createPlaywrightController(options = {}) {
|
|
|
1172
1252
|
check();
|
|
1173
1253
|
// Preflight and reservation are synchronous: another session cannot
|
|
1174
1254
|
// claim this slot during retirement's asynchronous boundary.
|
|
1175
|
-
const occupied =
|
|
1255
|
+
const occupied = occupiedSessions();
|
|
1176
1256
|
if (occupied >= maxSessions)
|
|
1177
1257
|
throw new PlaywrightResourceLimitError('Playwright session capacity exceeded');
|
|
1178
1258
|
active = { name: parsed.session, generation: ++generation, state: 'acquiring', snapshot: createSnapshotEngine({ maxSnapshotBytes, maxSnapshotRefs }, () => `e${++refSequence}`), cleanups: new Set(), idleTimeoutMs: openOptions.idleTimeoutMs, contextOptions: openOptions.contextOptions };
|