@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.
Files changed (50) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +112 -0
  3. package/dist/cookies-export.d.ts +5 -5
  4. package/dist/cookies-export.d.ts.map +1 -1
  5. package/dist/cookies-export.js +4 -4
  6. package/dist/hand-host.d.ts +217 -0
  7. package/dist/hand-host.d.ts.map +1 -0
  8. package/dist/hand-host.js +351 -0
  9. package/dist/hand-host.js.map +1 -0
  10. package/dist/hand-loading.d.ts +128 -0
  11. package/dist/hand-loading.d.ts.map +1 -0
  12. package/dist/hand-loading.js +143 -0
  13. package/dist/hand-loading.js.map +1 -0
  14. package/dist/index.d.ts +4 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/playwright-attach-transport.d.ts +9 -0
  19. package/dist/playwright-attach-transport.d.ts.map +1 -1
  20. package/dist/playwright-attach-transport.js +53 -91
  21. package/dist/playwright-attach-transport.js.map +1 -1
  22. package/dist/playwright-launch-transport.d.ts +7 -62
  23. package/dist/playwright-launch-transport.d.ts.map +1 -1
  24. package/dist/playwright-launch-transport.js +51 -204
  25. package/dist/playwright-launch-transport.js.map +1 -1
  26. package/dist/remote-session.d.ts +12 -2
  27. package/dist/remote-session.d.ts.map +1 -1
  28. package/dist/remote-session.js +37 -6
  29. package/dist/remote-session.js.map +1 -1
  30. package/dist/seam.d.ts +13 -5
  31. package/dist/seam.d.ts.map +1 -1
  32. package/dist/session-rpc.d.ts +76 -12
  33. package/dist/session-rpc.d.ts.map +1 -1
  34. package/dist/session-rpc.js +76 -8
  35. package/dist/session-rpc.js.map +1 -1
  36. package/dist/stub-transport.d.ts +2 -2
  37. package/dist/stub-transport.d.ts.map +1 -1
  38. package/dist/stub-transport.js +11 -0
  39. package/dist/stub-transport.js.map +1 -1
  40. package/package.json +21 -2
  41. package/src/cookies-export.ts +5 -5
  42. package/src/hand-host.ts +511 -0
  43. package/src/hand-loading.ts +254 -0
  44. package/src/index.ts +18 -1
  45. package/src/playwright-attach-transport.ts +65 -119
  46. package/src/playwright-launch-transport.ts +63 -244
  47. package/src/remote-session.ts +43 -5
  48. package/src/seam.ts +13 -5
  49. package/src/session-rpc.ts +121 -11
  50. package/src/stub-transport.ts +15 -3
@@ -1 +1 @@
1
- {"version":3,"file":"session-rpc.d.ts","sourceRoot":"","sources":["../src/session-rpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,MAAM,EAEX,KAAK,aAAa,EAClB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;;;;GAgBG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,8DAA8D;AAC9D,MAAM,MAAM,iBAAiB,GAC1B;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAC,GACjD;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAC,GACpD;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAClD;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GACxE;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAC,GACpD;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAA;CAAC,GAC1D;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GAC1B;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAC,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAC3B;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,GAC7C;IAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC;AAEhD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iBAAiB,GACxB,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,GACpD,IAAI,CA8BN"}
1
+ {"version":3,"file":"session-rpc.d.ts","sourceRoot":"","sources":["../src/session-rpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,MAAM,EAEX,KAAK,aAAa,EAClB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,WAAW,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,8DAA8D;AAC9D,MAAM,MAAM,iBAAiB,GAC1B,wBAAwB,GACxB,qBAAqB,CAAC;AAEzB;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GACjC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAC,GACjD;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAC,GACpD;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAClD;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GACxE;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAC,GACpD;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAA;CAAC,GAC1D;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GAC1B;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAC,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAC3B;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,GAC7C;IAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC;AAEhD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACpC,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,iBAAiB,GACxB,OAAO,CAAC,OAAO,CAAC,CA0BlB;AAmCD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,GACpD,YAAY,CA8Bd;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CACjC,IAAI,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,EACtD,IAAI,EAAE,MAAM,EACZ,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,GACzB,OAAO,CAAC,OAAO,CAAC,CAElB"}
@@ -2,7 +2,7 @@ import { locator, } from './seam.js';
2
2
  /**
3
3
  * The wire protocol for driving the long-lived session over HTTP (ADR-0005).
4
4
  *
5
- * The served process holds ONE live {@link Page} in memory; a thin client verb
5
+ * The served process holds ONE live {@link WebHandsPage} in memory; a thin client verb
6
6
  * cannot hold a JS reference to it across the process boundary, so each verb
7
7
  * call is sent as a small JSON request to the server, which runs it against its
8
8
  * live page and returns the result. This module is the SINGLE source of truth
@@ -10,16 +10,40 @@ import { locator, } from './seam.js';
10
10
  * client proxy so they cannot drift (mirrors how `serializeCookies` is shared
11
11
  * by the cookies verb and its test).
12
12
  *
13
- * It is a thin transport detail, NOT a second verb surface: every request maps
14
- * 1:1 to a {@link Page} method, and the seam's verb semantics (ADR-0003/0004)
15
- * are unchanged. The {@link LocatorString} brand and the structured
16
- * {@link WaitCondition} cross as plain JSON and are re-branded on the server
17
- * with {@link locator}; no Playwright/CDP type is ever named here.
13
+ * It is a thin transport detail, NOT a second verb surface: every built-in
14
+ * request maps 1:1 to a {@link WebHandsPage} method, and the seam's verb semantics
15
+ * (ADR-0003/0004) are unchanged. The {@link LocatorString} brand and the
16
+ * structured {@link WaitCondition} cross as plain JSON and are re-branded on the
17
+ * server with {@link locator}; no Playwright/CDP type is ever named here.
18
+ *
19
+ * THIRD-PARTY HAND VERBS (Phase 2, Model B of the "hands" prd; ADR-0007). The
20
+ * eight built-in verbs stay a CLOSED union (the 1:1 source of truth above). A
21
+ * dynamically-loaded hand contributes a verb whose name `core` does NOT know at
22
+ * compile time, so it cannot be a named member of that closed union without
23
+ * re-meaning "closed". Instead it crosses as a SINGLE generic
24
+ * {@link SessionRpcHandRequest} variant (`{verb: 'hand', name, args}`) that
25
+ * names the contributed verb at runtime and carries its arguments. This is the
26
+ * exact wire parallel of how a hand verb composes into the page object: by name,
27
+ * dynamically, alongside the typed built-ins. The agent thereby gains a new tool
28
+ * over the wire WITHOUT ever holding a live page handle.
29
+ *
30
+ * SERIALIZATION BOUNDARY (the load-bearing rule; prd's resolved Q3). A hand
31
+ * verb's result crosses this RPC, so it MUST be serializable under the same
32
+ * structured-clone contract `eval` documents (see {@link WebHandsPage.eval}): richer
33
+ * than JSON, but a value with no transferable form does not round-trip. This is
34
+ * enforced by CONVENTION + TYPES (a hand author returns serializable values),
35
+ * NOT a blanket runtime clone here — a blanket clone would corrupt legitimate
36
+ * in-process (Model A) returns, where a hand may pass/return live Playwright
37
+ * handles within a single in-process call chain. A host-side runtime clone of
38
+ * agent-verb results is available HARDENING for untrusted hands, not built here.
39
+ * A page/in-hand throw REJECTS faithfully on the client exactly as the `eval`
40
+ * path already does (the server maps it to an `ok: false` reply carrying the
41
+ * message; the client re-throws a faithful `Error`).
18
42
  */
19
43
  /** The path the session RPC is served under, below the server's base URL. */
20
44
  export const SESSION_RPC_PATH = '/session/call';
21
45
  /**
22
- * Run one {@link SessionRpcRequest} against a live {@link Page}, returning the
46
+ * Run one {@link SessionRpcRequest} against a live {@link WebHandsPage}, returning the
23
47
  * value the wire should carry back. The server's HTTP handler is just this plus
24
48
  * JSON framing; keeping the dispatch here (not inline in the handler) means the
25
49
  * verb-to-page mapping is in one place and unit-testable without HTTP.
@@ -51,10 +75,36 @@ export async function applySessionRpc(page, request) {
51
75
  case 'setCookies':
52
76
  await page.setCookies(request.cookies);
53
77
  return undefined;
78
+ case 'hand':
79
+ return applyHandVerb(page, request);
54
80
  }
55
81
  }
56
82
  /**
57
- * A {@link Page} whose verbs forward to a server via the supplied transport.
83
+ * Invoke a dynamically-loaded hand verb by name against the live composed page.
84
+ *
85
+ * The composed {@link WebHandsPage} carries the hand's verbs at runtime (the host merged
86
+ * them in by name alongside the built-ins, see `composePage`), even though the
87
+ * seam `WebHandsPage` TYPE only names the eight built-ins. We therefore look the verb up
88
+ * on the page object as a runtime method and invoke it with the request's args.
89
+ * An unknown name is a faithful error (the hand was not loaded / named that
90
+ * verb), surfaced the same way a page-side throw is so the client rejects.
91
+ *
92
+ * The result is returned as-is: the serializable-only boundary is enforced by
93
+ * convention + types on the hand author, NOT a runtime clone here (a blanket
94
+ * clone would corrupt legitimate in-process Model A returns; see this module's
95
+ * overview). What the hand returns is what the wire carries back; the JSON
96
+ * framing in the server handler is the only encoding applied.
97
+ */
98
+ async function applyHandVerb(page, request) {
99
+ const verb = page[request.name];
100
+ if (typeof verb !== 'function') {
101
+ throw new Error(`no such hand verb '${request.name}' on the live page ` +
102
+ `(is the hand loaded and named in config?)`);
103
+ }
104
+ return verb.call(page, ...request.args);
105
+ }
106
+ /**
107
+ * A {@link WebHandsPage} whose verbs forward to a server via the supplied transport.
58
108
  *
59
109
  * Used by the client-side proxy (see `remote-session.ts`): each verb builds a
60
110
  * {@link SessionRpcRequest}, hands it to `send`, and shapes the reply back into
@@ -93,6 +143,24 @@ export function makeRpcPage(send) {
93
143
  },
94
144
  };
95
145
  }
146
+ /**
147
+ * Invoke a dynamically-loaded hand verb over the session RPC by name (Phase 2,
148
+ * Model B; ADR-0007). The client-side mirror of {@link applyHandVerb}: it builds
149
+ * the single generic {@link SessionRpcHandRequest} and hands it to the SAME
150
+ * `send` the built-in verbs use, so request/response shapes cannot drift.
151
+ *
152
+ * This is how the agent gains a new tool over the wire WITHOUT holding a live
153
+ * page handle: it names the contributed verb and passes serializable args; the
154
+ * server runs the hand against its own live page and returns a serializable
155
+ * result. A page/in-hand throw rejects faithfully (the `send` re-throws the
156
+ * server's error message), exactly as the `eval` path does.
157
+ *
158
+ * The result type is `unknown` because the hand decides the shape; callers
159
+ * narrow it (mirrors {@link WebHandsPage.eval}).
160
+ */
161
+ export async function callHandVerb(send, name, ...args) {
162
+ return send({ verb: 'hand', name, args });
163
+ }
96
164
  /**
97
165
  * Re-brand a {@link WaitCondition} that arrived as plain JSON: only the
98
166
  * `locator` form carries a branded string, which JSON flattens to a plain
@@ -1 +1 @@
1
- {"version":3,"file":"session-rpc.js","sourceRoot":"","sources":["../src/session-rpc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-rpc.js","sourceRoot":"","sources":["../src/session-rpc.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import type { OpenTarget, Page, Session, Transport } from './seam.js';
1
+ import type { OpenTarget, WebHandsPage, Session, Transport } from './seam.js';
2
2
  /**
3
3
  * A record of one verb call against the stub, for assertions in seam tests.
4
4
  */
5
5
  export interface StubCall {
6
- readonly verb: keyof Page;
6
+ readonly verb: keyof WebHandsPage;
7
7
  readonly args: readonly unknown[];
8
8
  }
9
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"stub-transport.d.ts","sourceRoot":"","sources":["../src/stub-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,UAAU,EACV,IAAI,EACJ,OAAO,EAGP,SAAS,EAET,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAM;IAE1B,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CAgEhD"}
1
+ {"version":3,"file":"stub-transport.d.ts","sourceRoot":"","sources":["../src/stub-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,UAAU,EACV,YAAY,EACZ,OAAO,EAGP,SAAS,EAET,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,YAAY,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAM;IAE1B,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CA4EhD"}
@@ -16,6 +16,10 @@ export class StubTransport {
16
16
  async open(target) {
17
17
  const calls = this.calls;
18
18
  let closed = false;
19
+ let resolveClosed;
20
+ const closedSignal = new Promise((resolve) => {
21
+ resolveClosed = resolve;
22
+ });
19
23
  const ensureOpen = () => {
20
24
  if (closed) {
21
25
  throw new Error('session is closed');
@@ -68,7 +72,14 @@ export class StubTransport {
68
72
  return {
69
73
  page,
70
74
  async close() {
75
+ if (closed) {
76
+ return;
77
+ }
71
78
  closed = true;
79
+ resolveClosed();
80
+ },
81
+ waitForClose() {
82
+ return closedSignal;
72
83
  },
73
84
  };
74
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stub-transport.js","sourceRoot":"","sources":["../src/stub-transport.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,aAAa;IACzB,4EAA4E;IACnE,KAAK,GAAe,EAAE,CAAC;IAEhC,KAAK,CAAC,IAAI,CAAC,MAAkB;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,MAAM,GAAG,KAAK,CAAC;QAEnB,MAAM,UAAU,GAAG,GAAG,EAAE;YACvB,IAAI,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACtC,CAAC;QACF,CAAC,CAAC;QAEF,MAAM,GAAG,GACR,MAAM,CAAC,IAAI,KAAK,QAAQ;YACvB,CAAC,CAAC,iBAAiB,MAAM,CAAC,OAAO,EAAE;YACnC,CAAC,CAAC,iBAAiB,MAAM,CAAC,QAAQ,EAAE,CAAC;QAEvC,MAAM,IAAI,GAAS;YAClB,KAAK,CAAC,QAAQ,CAAC,EAAU;gBACxB,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAC,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,CAAC,QAAQ,CAAC,OAAyB;gBACvC,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAC,CAAC,CAAC;gBAChD,OAAO;oBACN,GAAG;oBACH,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe;oBACvD,OAAO,EAAE,EAAE;iBACX,CAAC;YACH,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,CAAC;gBACZ,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC;YACxC,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI;gBACjB,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAC,CAAC,CAAC;YAC7C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,UAAkB;gBAC5B,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,EAAC,CAAC,CAAC;gBAC/C,OAAO,SAAS,CAAC;YAClB,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,SAAwB;gBAClC,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAC,CAAC,CAAC;YAC/C,CAAC;YACD,KAAK,CAAC,OAAO;gBACZ,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAC,CAAC,CAAC;gBACxC,OAAO,EAAE,CAAC;YACX,CAAC;YACD,KAAK,CAAC,UAAU,CAAC,OAAO;gBACvB,UAAU,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAC,CAAC,CAAC;YACnD,CAAC;SACD,CAAC;QAEF,OAAO;YACN,IAAI;YACJ,KAAK,CAAC,KAAK;gBACV,MAAM,GAAG,IAAI,CAAC;YACf,CAAC;SACD,CAAC;IACH,CAAC;CACD"}
1
+ {"version":3,"file":"stub-transport.js","sourceRoot":"","sources":["../src/stub-transport.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,23 @@
1
1
  {
2
2
  "name": "@webhands/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
+ "description": "Core library for webhands: drives a real, persistent browser via Playwright.",
5
+ "keywords": [
6
+ "browser",
7
+ "playwright",
8
+ "automation"
9
+ ],
10
+ "license": "AGPL-3.0-or-later",
11
+ "author": "wighawag",
12
+ "homepage": "https://github.com/wighawag/webhands#readme",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/wighawag/webhands.git",
16
+ "directory": "packages/core"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/wighawag/webhands/issues"
20
+ },
4
21
  "publishConfig": {
5
22
  "access": "public"
6
23
  },
@@ -13,7 +30,9 @@
13
30
  },
14
31
  "files": [
15
32
  "dist",
16
- "src"
33
+ "src",
34
+ "README.md",
35
+ "LICENSE"
17
36
  ],
18
37
  "dependencies": {
19
38
  "playwright": "1.61.1"
@@ -2,8 +2,8 @@
2
2
  * The `cookies export` / `cookies import` verb's FILE FORMAT (PRD story 11).
3
3
  *
4
4
  * The seam already carries the transport-neutral cookie primitives:
5
- * {@link Page.cookies} reads the active context's cookies and
6
- * {@link Page.setCookies} loads cookies into it. The export/import VERB is built
5
+ * {@link WebHandsPage.cookies} reads the active context's cookies and
6
+ * {@link WebHandsPage.setCookies} loads cookies into it. The export/import VERB is built
7
7
  * ON TOP of those two methods (the forward-note: refine the existing seam,
8
8
  * do NOT add a parallel cookie path). What this module adds is only the
9
9
  * SERIALIZATION the verb needs to move a session to/from disk: how a
@@ -34,12 +34,12 @@ export const COOKIES_EXPORT_VERSION = 1 as const;
34
34
  export interface CookiesExport {
35
35
  /** Format version (see {@link COOKIES_EXPORT_VERSION}). */
36
36
  readonly version: typeof COOKIES_EXPORT_VERSION;
37
- /** The exported cookies, exactly as the seam's {@link Page.cookies} returns them. */
37
+ /** The exported cookies, exactly as the seam's {@link WebHandsPage.cookies} returns them. */
38
38
  readonly cookies: readonly Cookie[];
39
39
  }
40
40
 
41
41
  /**
42
- * Serialize the cookies read from the seam ({@link Page.cookies}) into the
42
+ * Serialize the cookies read from the seam ({@link WebHandsPage.cookies}) into the
43
43
  * export file's text. Pretty-printed JSON so a human can read/diff a backed-up
44
44
  * session. This is pure: it does NO disk I/O, so the caller (the CLI verb, a
45
45
  * test) owns WHERE the file lands — which is what lets a test keep its export
@@ -55,7 +55,7 @@ export function serializeCookies(cookies: readonly Cookie[]): string {
55
55
 
56
56
  /**
57
57
  * Parse an export file's text back into the cookies to hand to the seam's
58
- * {@link Page.setCookies} ({@link parse} is pure; the caller does the disk read
58
+ * {@link WebHandsPage.setCookies} ({@link parse} is pure; the caller does the disk read
59
59
  * and the `setCookies` call). Rejects anything that is not a recognised export
60
60
  * envelope so a corrupt or wrong-version file surfaces as a clear error rather
61
61
  * than silently importing nothing or a half-parsed list.