@webhands/core 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +112 -0
- package/dist/cookies-export.d.ts +5 -5
- package/dist/cookies-export.d.ts.map +1 -1
- package/dist/cookies-export.js +4 -4
- package/dist/hand-host.d.ts +217 -0
- package/dist/hand-host.d.ts.map +1 -0
- package/dist/hand-host.js +351 -0
- package/dist/hand-host.js.map +1 -0
- package/dist/hand-loading.d.ts +128 -0
- package/dist/hand-loading.d.ts.map +1 -0
- package/dist/hand-loading.js +143 -0
- package/dist/hand-loading.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/playwright-attach-transport.d.ts +9 -0
- package/dist/playwright-attach-transport.d.ts.map +1 -1
- package/dist/playwright-attach-transport.js +53 -91
- package/dist/playwright-attach-transport.js.map +1 -1
- package/dist/playwright-launch-transport.d.ts +7 -62
- package/dist/playwright-launch-transport.d.ts.map +1 -1
- package/dist/playwright-launch-transport.js +51 -204
- package/dist/playwright-launch-transport.js.map +1 -1
- package/dist/remote-session.d.ts +12 -2
- package/dist/remote-session.d.ts.map +1 -1
- package/dist/remote-session.js +37 -6
- package/dist/remote-session.js.map +1 -1
- package/dist/seam.d.ts +13 -5
- package/dist/seam.d.ts.map +1 -1
- package/dist/session-rpc.d.ts +76 -12
- package/dist/session-rpc.d.ts.map +1 -1
- package/dist/session-rpc.js +76 -8
- package/dist/session-rpc.js.map +1 -1
- package/dist/stub-transport.d.ts +2 -2
- package/dist/stub-transport.d.ts.map +1 -1
- package/dist/stub-transport.js +11 -0
- package/dist/stub-transport.js.map +1 -1
- package/package.json +21 -2
- package/src/cookies-export.ts +5 -5
- package/src/hand-host.ts +511 -0
- package/src/hand-loading.ts +254 -0
- package/src/index.ts +18 -1
- package/src/playwright-attach-transport.ts +65 -119
- package/src/playwright-launch-transport.ts +63 -244
- package/src/remote-session.ts +43 -5
- package/src/seam.ts +13 -5
- package/src/session-rpc.ts +121 -11
- package/src/stub-transport.ts +15 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export type { Cookie, Driver, LocatorString, OpenTarget,
|
|
1
|
+
export type { Cookie, Driver, LocatorString, OpenTarget, WebHandsPage, Session, Snapshot, SnapshotOptions, SnapshotView, Transport, WaitCondition, } from './seam.js';
|
|
2
2
|
export { locator } from './seam.js';
|
|
3
3
|
export { serializeCookies, deserializeCookies, COOKIES_EXPORT_VERSION, type CookiesExport, } from './cookies-export.js';
|
|
4
4
|
export { StubTransport, type StubCall } from './stub-transport.js';
|
|
5
|
+
export type { Hand, HandContext, HandContribution } from './hand-host.js';
|
|
6
|
+
export { readHandsConfig, normalizeConfig, loadHands, HandLoadError, HANDS_CONFIG_FILENAME, type HandEntry, type HandsConfig, type LoadedHand, type LoadHandsOptions, } from './hand-loading.js';
|
|
5
7
|
export { PlaywrightLaunchTransport } from './playwright-launch-transport.js';
|
|
6
8
|
export { PlaywrightAttachTransport } from './playwright-attach-transport.js';
|
|
7
9
|
export { setupProfile, buildPrompt, type PromptSink, type SetupProfileOptions, type SetupProfileResult, } from './setup-profile.js';
|
|
@@ -9,7 +11,7 @@ export { ControllerError, MissingBrowserBinaryError, MissingProfileError, Attach
|
|
|
9
11
|
export { resolveSessionEndpointPath, writeSessionEndpoint, readSessionEndpoint, clearSessionEndpoint, SESSION_ENDPOINT_FILENAME, type SessionEndpoint, } from './session-endpoint.js';
|
|
10
12
|
export { startSessionServer, sessionAlreadyActive, type SessionServerOptions, type RunningSessionServer, } from './session-server.js';
|
|
11
13
|
export { connectRemoteSession } from './remote-session.js';
|
|
12
|
-
export { SESSION_RPC_PATH, applySessionRpc, makeRpcPage, type SessionRpcRequest, type SessionRpcResponse, } from './session-rpc.js';
|
|
14
|
+
export { SESSION_RPC_PATH, applySessionRpc, makeRpcPage, callHandVerb, type SessionRpcRequest, type SessionRpcBuiltInRequest, type SessionRpcHandRequest, type SessionRpcResponse, } from './session-rpc.js';
|
|
13
15
|
export { resolveHomeRoot, resolveProfileLocation, CONTROLLER_HOME_ENV, DEFAULT_HOME_DIRNAME, PROFILES_DIRNAME, type ProfileLocation, type ProfileLocationOptions, } from './profile-location.js';
|
|
14
16
|
export { startFixtureServer, type FixtureServer, } from './test-fixtures/fixture-server.js';
|
|
15
17
|
export { FIXTURE_PAGES } from './test-fixtures/fixture-pages.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,MAAM,EACN,MAAM,EACN,aAAa,EACb,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,MAAM,EACN,MAAM,EACN,aAAa,EACb,UAAU,EACV,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,SAAS,EACT,aAAa,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,aAAa,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,aAAa,EAAE,KAAK,QAAQ,EAAC,MAAM,qBAAqB,CAAC;AAEjE,YAAY,EAAC,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AAExE,OAAO,EACN,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,gBAAgB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,yBAAyB,EAAC,MAAM,kCAAkC,CAAC;AAE3E,OAAO,EAAC,yBAAyB,EAAC,MAAM,kCAAkC,CAAC;AAE3E,OAAO,EACN,YAAY,EACZ,WAAW,EACX,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACN,eAAe,EACf,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,eAAe,GACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EACN,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC3B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,kBAAkB,EAClB,KAAK,aAAa,GAClB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAC,aAAa,EAAC,MAAM,kCAAkC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { locator } from './seam.js';
|
|
2
2
|
export { serializeCookies, deserializeCookies, COOKIES_EXPORT_VERSION, } from './cookies-export.js';
|
|
3
3
|
export { StubTransport } from './stub-transport.js';
|
|
4
|
+
export { readHandsConfig, normalizeConfig, loadHands, HandLoadError, HANDS_CONFIG_FILENAME, } from './hand-loading.js';
|
|
4
5
|
export { PlaywrightLaunchTransport } from './playwright-launch-transport.js';
|
|
5
6
|
export { PlaywrightAttachTransport } from './playwright-attach-transport.js';
|
|
6
7
|
export { setupProfile, buildPrompt, } from './setup-profile.js';
|
|
@@ -8,7 +9,7 @@ export { ControllerError, MissingBrowserBinaryError, MissingProfileError, Attach
|
|
|
8
9
|
export { resolveSessionEndpointPath, writeSessionEndpoint, readSessionEndpoint, clearSessionEndpoint, SESSION_ENDPOINT_FILENAME, } from './session-endpoint.js';
|
|
9
10
|
export { startSessionServer, sessionAlreadyActive, } from './session-server.js';
|
|
10
11
|
export { connectRemoteSession } from './remote-session.js';
|
|
11
|
-
export { SESSION_RPC_PATH, applySessionRpc, makeRpcPage, } from './session-rpc.js';
|
|
12
|
+
export { SESSION_RPC_PATH, applySessionRpc, makeRpcPage, callHandVerb, } from './session-rpc.js';
|
|
12
13
|
export { resolveHomeRoot, resolveProfileLocation, CONTROLLER_HOME_ENV, DEFAULT_HOME_DIRNAME, PROFILES_DIRNAME, } from './profile-location.js';
|
|
13
14
|
export { startFixtureServer, } from './test-fixtures/fixture-server.js';
|
|
14
15
|
export { FIXTURE_PAGES } from './test-fixtures/fixture-pages.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,GAEtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,aAAa,EAAgB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,GAEtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AAIjE,OAAO,EACN,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,qBAAqB,GAKrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,yBAAyB,EAAC,MAAM,kCAAkC,CAAC;AAE3E,OAAO,EAAC,yBAAyB,EAAC,MAAM,kCAAkC,CAAC;AAE3E,OAAO,EACN,YAAY,EACZ,WAAW,GAIX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACN,eAAe,EACf,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,GAEjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,GAEzB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,kBAAkB,EAClB,oBAAoB,GAGpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EACN,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,GAKZ,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GAGhB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,kBAAkB,GAElB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAC,aAAa,EAAC,MAAM,kCAAkC,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Hand } from './hand-host.js';
|
|
1
2
|
import type { OpenTarget, Session, Transport } from './seam.js';
|
|
2
3
|
/**
|
|
3
4
|
* The `attach` concrete transport: connect (`chromium.connectOverCDP`) to a
|
|
@@ -23,6 +24,14 @@ import type { OpenTarget, Session, Transport } from './seam.js';
|
|
|
23
24
|
* running one.
|
|
24
25
|
*/
|
|
25
26
|
export declare class PlaywrightAttachTransport implements Transport {
|
|
27
|
+
#private;
|
|
28
|
+
/**
|
|
29
|
+
* @param hands explicitly-loaded third-party hands to compose alongside the
|
|
30
|
+
* built-ins (Phase 2, ADR-0007). These come from {@link loadHands} against
|
|
31
|
+
* the operator's explicit config; the transport does NOT discover them. Omit
|
|
32
|
+
* for the built-ins-only surface.
|
|
33
|
+
*/
|
|
34
|
+
constructor(hands?: readonly Hand[]);
|
|
26
35
|
open(target: OpenTarget): Promise<Session>;
|
|
27
36
|
}
|
|
28
37
|
//# sourceMappingURL=playwright-attach-transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-attach-transport.d.ts","sourceRoot":"","sources":["../src/playwright-attach-transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"playwright-attach-transport.d.ts","sourceRoot":"","sources":["../src/playwright-attach-transport.ts"],"names":[],"mappings":"AAOA,OAAO,EAAmB,KAAK,IAAI,EAAmB,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAC,MAAM,WAAW,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,yBAA0B,YAAW,SAAS;;IAG1D;;;;;OAKG;gBACS,KAAK,GAAE,SAAS,IAAI,EAAO;IAIjC,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CA0ChD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { chromium, } from 'playwright';
|
|
2
2
|
import { AttachNoContextError, AttachNotChromiumError } from './errors.js';
|
|
3
|
-
import {
|
|
3
|
+
import { composeWithHands } from './hand-host.js';
|
|
4
4
|
/**
|
|
5
5
|
* The `attach` concrete transport: connect (`chromium.connectOverCDP`) to a
|
|
6
6
|
* browser the USER already started with remote debugging enabled, and reuse the
|
|
@@ -25,6 +25,16 @@ import { clickLocator, resolveLocator, waitFor, } from './playwright-launch-tran
|
|
|
25
25
|
* running one.
|
|
26
26
|
*/
|
|
27
27
|
export class PlaywrightAttachTransport {
|
|
28
|
+
#hands;
|
|
29
|
+
/**
|
|
30
|
+
* @param hands explicitly-loaded third-party hands to compose alongside the
|
|
31
|
+
* built-ins (Phase 2, ADR-0007). These come from {@link loadHands} against
|
|
32
|
+
* the operator's explicit config; the transport does NOT discover them. Omit
|
|
33
|
+
* for the built-ins-only surface.
|
|
34
|
+
*/
|
|
35
|
+
constructor(hands = []) {
|
|
36
|
+
this.#hands = hands;
|
|
37
|
+
}
|
|
28
38
|
async open(target) {
|
|
29
39
|
if (target.mode !== 'attach') {
|
|
30
40
|
throw new Error(`PlaywrightAttachTransport only handles 'attach'; ` +
|
|
@@ -52,7 +62,7 @@ export class PlaywrightAttachTransport {
|
|
|
52
62
|
// browser exposes a context with no page yet (single active session in
|
|
53
63
|
// v1, PRD Out of Scope).
|
|
54
64
|
const pwPage = context.pages()[0] ?? (await context.newPage());
|
|
55
|
-
return makeAttachedSession(browser, pwPage);
|
|
65
|
+
return makeAttachedSession(browser, pwPage, this.#hands);
|
|
56
66
|
}
|
|
57
67
|
catch (cause) {
|
|
58
68
|
// On any open-time refusal, disconnect from the user's browser without
|
|
@@ -66,13 +76,19 @@ export class PlaywrightAttachTransport {
|
|
|
66
76
|
/**
|
|
67
77
|
* Wrap a CDP-attached browser into the seam's {@link Session}.
|
|
68
78
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
79
|
+
* The VERB surface comes from the shared hand-host ({@link composeBuiltInPage}),
|
|
80
|
+
* the SAME single composition the launch transport uses (no duplicated
|
|
81
|
+
* page-object literal). Cookies resolve through the reused context (derived here
|
|
82
|
+
* via `pwPage.context()`) so they reflect the live, authenticated session.
|
|
83
|
+
*
|
|
84
|
+
* Only the SESSION LIFECYCLE is per-transport: this transport listens on the
|
|
85
|
+
* browser's `'disconnected'` event and its `close()` calls `browser.close()`,
|
|
86
|
+
* which DISCONNECTS the controller from the user's browser WITHOUT killing it
|
|
87
|
+
* (a `connectOverCDP` connection detaches rather than terminating the remote
|
|
88
|
+
* process, ADR-0002) — the opposite of the launch transport, which kills the
|
|
89
|
+
* browser it spawned.
|
|
74
90
|
*/
|
|
75
|
-
function makeAttachedSession(browser, pwPage) {
|
|
91
|
+
function makeAttachedSession(browser, pwPage, extraHands) {
|
|
76
92
|
const context = pwPage.context();
|
|
77
93
|
let closed = false;
|
|
78
94
|
const ensureOpen = () => {
|
|
@@ -80,96 +96,42 @@ function makeAttachedSession(browser, pwPage) {
|
|
|
80
96
|
throw new Error('session is closed');
|
|
81
97
|
}
|
|
82
98
|
};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const content = await pwPage.evaluate(() => document.documentElement.outerHTML);
|
|
96
|
-
return { url, view: 'full', content };
|
|
97
|
-
}
|
|
98
|
-
// Default: the token-cheap accessibility tree + visible text with stable
|
|
99
|
-
// `[ref=...]` refs (see the launch transport and `Snapshot` for the
|
|
100
|
-
// rationale; the string crosses the seam as opaque, transport-neutral
|
|
101
|
-
// text, ADR-0003).
|
|
102
|
-
const content = await pwPage.ariaSnapshot({ mode: 'ai' });
|
|
103
|
-
return { url, view: 'accessibility', content };
|
|
104
|
-
},
|
|
105
|
-
// `resolveLocator`/`clickLocator`/`waitFor` are imported from the launch
|
|
106
|
-
// transport so both transports resolve locators and run the verbs through
|
|
107
|
-
// ONE path (no parallel addressing scheme; the forward-note).
|
|
108
|
-
async click(t) {
|
|
109
|
-
ensureOpen();
|
|
110
|
-
// Shared `clickLocator`: normal actionability-checked click with the
|
|
111
|
-
// hidden-element dispatch fallback (PRD story 8), identical to launch.
|
|
112
|
-
await clickLocator(pwPage, t);
|
|
113
|
-
},
|
|
114
|
-
async type(t, text) {
|
|
115
|
-
ensureOpen();
|
|
116
|
-
await resolveLocator(pwPage, t).fill(text);
|
|
117
|
-
},
|
|
118
|
-
async eval(expression) {
|
|
119
|
-
ensureOpen();
|
|
120
|
-
return pwPage.evaluate(expression);
|
|
121
|
-
},
|
|
122
|
-
async wait(condition) {
|
|
123
|
-
ensureOpen();
|
|
124
|
-
// Identical to the launch transport (shared `waitFor`): selector /
|
|
125
|
-
// navigation / timeout, so the verb behaves the same on both.
|
|
126
|
-
await waitFor(pwPage, condition);
|
|
127
|
-
},
|
|
128
|
-
async cookies() {
|
|
129
|
-
ensureOpen();
|
|
130
|
-
const raw = await context.cookies();
|
|
131
|
-
return raw.map(toSeamCookie);
|
|
132
|
-
},
|
|
133
|
-
async setCookies(cookies) {
|
|
134
|
-
ensureOpen();
|
|
135
|
-
await context.addCookies(cookies.map(fromSeamCookie));
|
|
136
|
-
},
|
|
99
|
+
// Resolves when the session ends: either the user's browser goes away
|
|
100
|
+
// (Playwright fires 'disconnected' on a connectOverCDP browser) or our own
|
|
101
|
+
// close() disconnects. Lets a caller block until the session is gone.
|
|
102
|
+
let resolveClosed;
|
|
103
|
+
const closedSignal = new Promise((resolve) => {
|
|
104
|
+
resolveClosed = resolve;
|
|
105
|
+
});
|
|
106
|
+
const markClosed = () => {
|
|
107
|
+
if (closed)
|
|
108
|
+
return;
|
|
109
|
+
closed = true;
|
|
110
|
+
resolveClosed();
|
|
137
111
|
};
|
|
112
|
+
browser.on('disconnected', markClosed);
|
|
113
|
+
// Build the verb surface from the built-in hands over a live hand-context —
|
|
114
|
+
// the same shared host the launch transport uses, so the verbs behave
|
|
115
|
+
// identically across both transports. The live `pwPage`/`context` stay
|
|
116
|
+
// in-process and never cross the seam (ADR-0003).
|
|
117
|
+
const handContext = { pwPage, context, ensureOpen };
|
|
118
|
+
const { page, dispose: disposeHands } = composeWithHands(handContext, extraHands);
|
|
138
119
|
return {
|
|
139
120
|
page,
|
|
140
121
|
async close() {
|
|
141
|
-
if (closed)
|
|
122
|
+
if (closed) {
|
|
142
123
|
return;
|
|
143
|
-
|
|
144
|
-
//
|
|
124
|
+
}
|
|
125
|
+
// Dispose the hands first (their in-process resources), THEN detach from
|
|
126
|
+
// the user's browser without terminating it. browser.close() fires
|
|
127
|
+
// 'disconnected', which runs markClosed.
|
|
128
|
+
await disposeHands();
|
|
145
129
|
await browser.close();
|
|
130
|
+
markClosed();
|
|
131
|
+
},
|
|
132
|
+
waitForClose() {
|
|
133
|
+
return closedSignal;
|
|
146
134
|
},
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
/** Map a Playwright cookie to the transport-neutral seam {@link Cookie}. */
|
|
150
|
-
function toSeamCookie(c) {
|
|
151
|
-
return {
|
|
152
|
-
name: c.name,
|
|
153
|
-
value: c.value,
|
|
154
|
-
domain: c.domain,
|
|
155
|
-
path: c.path,
|
|
156
|
-
expires: c.expires,
|
|
157
|
-
httpOnly: c.httpOnly,
|
|
158
|
-
secure: c.secure,
|
|
159
|
-
sameSite: c.sameSite,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
/** Map a seam {@link Cookie} to a Playwright cookie shape. */
|
|
163
|
-
function fromSeamCookie(c) {
|
|
164
|
-
return {
|
|
165
|
-
name: c.name,
|
|
166
|
-
value: c.value,
|
|
167
|
-
domain: c.domain,
|
|
168
|
-
path: c.path,
|
|
169
|
-
expires: c.expires,
|
|
170
|
-
httpOnly: c.httpOnly,
|
|
171
|
-
secure: c.secure,
|
|
172
|
-
sameSite: c.sameSite,
|
|
173
135
|
};
|
|
174
136
|
}
|
|
175
137
|
//# sourceMappingURL=playwright-attach-transport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-attach-transport.js","sourceRoot":"","sources":["../src/playwright-attach-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,QAAQ,GAIR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,oBAAoB,EAAE,sBAAsB,EAAC,MAAM,aAAa,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"playwright-attach-transport.js","sourceRoot":"","sources":["../src/playwright-attach-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Hand } from './hand-host.js';
|
|
2
2
|
import { type ProfileLocationOptions } from './profile-location.js';
|
|
3
|
-
import type { OpenTarget, Session, Transport
|
|
3
|
+
import type { OpenTarget, Session, Transport } from './seam.js';
|
|
4
4
|
/**
|
|
5
5
|
* The v1 concrete transport: a Playwright browser the controller LAUNCHES
|
|
6
6
|
* against a dedicated, persistent profile directory it owns (PRD "Solution,
|
|
@@ -24,67 +24,12 @@ export declare class PlaywrightLaunchTransport implements Transport {
|
|
|
24
24
|
* @param location overrides for where profiles live (a `root` dir and/or an
|
|
25
25
|
* `env`). Omit in production to use `~/.webhands`; pass a temp
|
|
26
26
|
* `root` in tests to isolate the shared profile location.
|
|
27
|
+
* @param hands explicitly-loaded third-party hands to compose alongside the
|
|
28
|
+
* built-ins (Phase 2, ADR-0007). These come from {@link loadHands} against
|
|
29
|
+
* the operator's explicit config; the transport does NOT discover them. Omit
|
|
30
|
+
* for the built-ins-only surface.
|
|
27
31
|
*/
|
|
28
|
-
constructor(location?: ProfileLocationOptions);
|
|
32
|
+
constructor(location?: ProfileLocationOptions, hands?: readonly Hand[]);
|
|
29
33
|
open(target: OpenTarget): Promise<Session>;
|
|
30
34
|
}
|
|
31
|
-
/**
|
|
32
|
-
* Run the `wait` verb's three forms (PRD story 10) against a Playwright page.
|
|
33
|
-
*
|
|
34
|
-
* - `timeout` — pace by a fixed delay (`waitForTimeout`), so an agent can act
|
|
35
|
-
* like a human and let XHR-rendered content land.
|
|
36
|
-
* - `locator` — block until the addressed element appears (`Locator.waitFor()`),
|
|
37
|
-
* the form for content rendered AFTER `goto` settled on `load`.
|
|
38
|
-
* - `navigation` — block until the NEXT navigation settles to `load`. We use
|
|
39
|
-
* `waitForNavigation()` even though Playwright marks it `@deprecated` ("racy,
|
|
40
|
-
* use waitForURL"): that deprecation targets in-process TEST code that can arm
|
|
41
|
-
* the wait BEFORE the action and pass a target URL. Neither holds here. Across
|
|
42
|
-
* this seam verbs are DISCRETE sequential calls (`click` then `wait`), so we
|
|
43
|
-
* CANNOT arm before the trigger; and the realistic trigger is an async,
|
|
44
|
-
* JS-driven transition (a redirect / SPA route change that fires AFTER the
|
|
45
|
-
* agent's action, the "let XHR-rendered content load" case of story 10), so
|
|
46
|
-
* "wait for the NEXT navigation" is exactly right — whereas `waitForLoadState`
|
|
47
|
-
* would see the already-loaded current page and return before the pending
|
|
48
|
-
* transition. `waitForURL` is unusable because the verb has no target URL by
|
|
49
|
-
* design (the agent waits for "a navigation", not a known address). (See the
|
|
50
|
-
* task's ## Decisions note.)
|
|
51
|
-
*
|
|
52
|
-
* Shared by both Playwright transports so the verb behaviour stays identical
|
|
53
|
-
* (the forward-note's "do NOT write a parallel second implementation").
|
|
54
|
-
*/
|
|
55
|
-
export declare function waitFor(page: PwPage, condition: WaitCondition): Promise<void>;
|
|
56
|
-
/**
|
|
57
|
-
* Resolve a raw Playwright locator EXPRESSION (ADR-0004) against the page. The
|
|
58
|
-
* verb surface passes locator expressions like `getByRole('button', …)`; we
|
|
59
|
-
* evaluate them in a small sandbox where `page`/`p` is the page, so the full
|
|
60
|
-
* Playwright locator grammar is available without leaking the type across the
|
|
61
|
-
* seam.
|
|
62
|
-
*
|
|
63
|
-
* Exported (with {@link clickLocator}/{@link waitFor}) so the attach transport
|
|
64
|
-
* resolves locators IDENTICALLY — one resolution path, no parallel addressing
|
|
65
|
-
* scheme (the forward-note's "do NOT write a parallel second implementation").
|
|
66
|
-
*/
|
|
67
|
-
export declare function resolveLocator(page: PwPage, expression: string): import("playwright").Locator;
|
|
68
|
-
/**
|
|
69
|
-
* Run the `click` verb against a Playwright page (PRD story 8), shared by both
|
|
70
|
-
* Playwright transports so the verb behaves identically (mirrors {@link waitFor};
|
|
71
|
-
* the forward-note's "do NOT write a parallel second implementation").
|
|
72
|
-
*
|
|
73
|
-
* First try a normal `Locator.click()`, which AUTO-WAITS for the element to be
|
|
74
|
-
* visible and actionable — the right behaviour for a real button. A hidden
|
|
75
|
-
* custom input (the case the prd calls out) NEVER becomes actionable, so that
|
|
76
|
-
* click times out; on a Playwright `TimeoutError` we fall back to
|
|
77
|
-
* `dispatchEvent('click')`, which fires a click WITHOUT the actionability
|
|
78
|
-
* checks. The fallback is deliberately the documented Playwright escape (a
|
|
79
|
-
* sibling to the `eval` hatch, ADR-0004), not a reimplemented click: we keep
|
|
80
|
-
* the locator a raw resolved expression and only change HOW the resolved
|
|
81
|
-
* locator is clicked.
|
|
82
|
-
*
|
|
83
|
-
* Only a timeout triggers the fallback. The fallback `dispatchEvent` is itself
|
|
84
|
-
* bounded by the same short timeout, so a locator that resolves NO element (a
|
|
85
|
-
* bad locator) surfaces its timeout quickly instead of hanging the dispatch on
|
|
86
|
-
* Playwright's 30s default — the dispatch escape is for elements that EXIST but
|
|
87
|
-
* are not actionable (hidden custom inputs), not for absent ones.
|
|
88
|
-
*/
|
|
89
|
-
export declare function clickLocator(page: PwPage, expression: string): Promise<void>;
|
|
90
35
|
//# sourceMappingURL=playwright-launch-transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-launch-transport.d.ts","sourceRoot":"","sources":["../src/playwright-launch-transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"playwright-launch-transport.d.ts","sourceRoot":"","sources":["../src/playwright-launch-transport.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,IAAI,EAAmB,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAC,MAAM,WAAW,CAAC;AAE9D;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,yBAA0B,YAAW,SAAS;;IAI1D;;;;;;;;OAQG;gBAEF,QAAQ,GAAE,sBAA2B,EACrC,KAAK,GAAE,SAAS,IAAI,EAAO;IAMtB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CAwChD"}
|