@volter-ai-dev/supercode-browser-playwright 0.1.1 → 0.2.1

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 CHANGED
@@ -58,7 +58,8 @@ Both carry the same envelope, `{protocol, id, token, call}` in and
58
58
 
59
59
  - **TCP** is the wire the harness speaks (`crates/harness/src/browser.rs`): one
60
60
  newline-terminated JSON request per connection, one JSON response, then the
61
- provider closes. The provider listens on `127.0.0.1` and writes an owner-only
61
+ provider closes. A provider waiting for the person may first write
62
+ `{protocol, id, pending}` lines; each extends the harness's wait to 120 s. The provider listens on `127.0.0.1` and writes an owner-only
62
63
  discovery record (file `0600`, directory `0700`) to
63
64
  `<providers dir>/browser/playwright.cdp.<port>.json`, scoped to the
64
65
  canonical workspace, and removes it on stop.
@@ -129,15 +130,48 @@ Two entry points use no Node API:
129
130
  `@volter/almostcdp/playwright`, and answers the operations against an
130
131
  AlmostCDP surface with no Node process.
131
132
 
132
- A host's `actionGuard(action)` is asked before each locator action (`click`,
133
- `fill`, `press`, `hover`, `focus`, `check`, `uncheck`, `select`, `drag`) with
134
- the action's `Locator` and value, and before each `browser.script` with
135
- `{action: "script", source, args}`; throwing a `BrowserActionRefusal` answers
136
- the call with its code, such as `APPROVAL_REQUIRED`. A script's own locator
137
- calls are the real `page`'s and are not asked again, so a host that guards
138
- locator actions guards scripts as a whole.
133
+ A host's `actionGuard(action)` is asked before every action that can change the
134
+ page or send it input, and before each `browser.script` (`{action: "script", source,
135
+ args}`); throwing a `BrowserActionRefusal` answers the call with its code, such as
136
+ `APPROVAL_REQUIRED`. Reading (status, snapshot, query, wait, box) is not asked;
137
+ `hover` is asked like any element action, and moving the mouse is not.
138
+
139
+ - Element actions (`click`, `fill`, `press`, `hover`, `focus`, `check`, `uncheck`,
140
+ `select`) carry a `target` described from the browser side. The locator is
141
+ resolved once (waiting up to 5 s) and the action runs on that same element
142
+ handle. The handle must be in the page's main frame and must be one of the
143
+ elements found at its box in an isolated world (a one-off marker attribute on
144
+ the handle confirms it); each is described over CDP (`DOM.describeNode` for tag
145
+ and attributes, `Accessibility.getPartialAXTree` for role, name and ancestors,
146
+ plus its form membership and, when unnamed, its own text). An element in a
147
+ `<label>` brings the control the label forwards to. A locator that resolves in
148
+ another frame, to a frame, or to a box more than eight elements share is refused.
149
+ A `select` carries the chosen options' labels and values.
150
+ - A locator `press` focuses its element and is refused unless focus is then on or
151
+ inside it; a press without a locator is described from the focused element and
152
+ refused inside a frame or a closed shadow root.
153
+ - Raw pointer input (`browser.mouse` click/down/up, `browser.wheel`,
154
+ `browser.drag`) carries `pointer: true` and the element at the point as best
155
+ known (`target.unidentified` says why when it cannot be told); a drag carries
156
+ both points and the element at the drop point. The mouse is moved to the point
157
+ before every down, up and wheel. After a locator action the position is that
158
+ element's box centre, or unknown, and a press then needs coordinates.
159
+ - `back`, `forward`, `reload` and `scroll` are page actions (`{action, url}`).
160
+ - Just before any input is dispatched, the executor confirms the page's main frame
161
+ still holds the document the action was checked on (its `loaderId` and URL) with
162
+ no navigation requested or loading (a navigation counts as settled once its
163
+ document commits, it moves within the document, loading stops, as for a 204
164
+ answer, or it becomes a download), then calls the host's `beforeInput({url})`;
165
+ a change refuses the action with `STALE_PAGE` and nothing is sent. A pointer
166
+ action on a locator first waits for its element in a trial run, so the
167
+ confirmation comes as late as it can.
168
+
169
+ A script gets the page through a membrane. When the script ends or its time runs
170
+ out, every later call through it throws, and the routes, exposed bindings and
171
+ functions, init scripts and listeners it installed are removed.
139
172
 
140
173
  A host's `snapshotExclude` is a CSS selector for its own elements in the page
141
174
  (an overlay, a launcher): `browser.snapshot` leaves out the nodes of every
142
- element it matches, found by their aria refs, and a node left empty by that.
143
- The page is not changed, so assistive technology still reads those elements.
175
+ element it matches, found by their aria refs, and a node left empty by that,
176
+ and a coordinate action that lands on one is refused with `UNSUPPORTED`. The
177
+ page is not changed, so assistive technology still reads those elements.
@@ -4,7 +4,8 @@
4
4
  * over CDP. No Node API is used, so the executor also runs in a browser realm
5
5
  * with a browser build of playwright-core (`@volter/almostcdp/playwright`).
6
6
  */
7
- import { type Locator, type Page } from "playwright-core";
7
+ import { type Page } from "playwright-core";
8
+ import { type GuardedTarget } from "./guard.js";
8
9
  import { type BrowserOperationErrorCode, type BrowserOperationResult } from "./protocol.js";
9
10
  /** The implementation this provider reports; the pinned playwright-core. */
10
11
  export declare const PLAYWRIGHT_IMPLEMENTATION = "playwright-core 1.63.0";
@@ -23,25 +24,56 @@ export interface PlaywrightOperationExecutorOptions {
23
24
  endpoint: string;
24
25
  /**
25
26
  * The host's policy for one action, asked before it runs: each locator
26
- * action, and each `browser.script` before its source is compiled. Throwing
27
- * a `BrowserActionRefusal` refuses the operation with that code.
27
+ * action, each coordinate action (`browser.mouse`, `browser.drag`,
28
+ * `browser.wheel`), and each `browser.script` before its source is
29
+ * compiled. An element action's target is resolved once, described from the
30
+ * browser side (see `GuardedTarget`), and the action then runs on that same
31
+ * element. A target that cannot be resolved or described refuses the
32
+ * operation without asking. Throwing a `BrowserActionRefusal` refuses the
33
+ * operation with that code.
28
34
  */
29
35
  actionGuard?: (action: PlaywrightAction) => void | Promise<void>;
30
36
  /**
31
- * A CSS selector (Playwright's, which pierces open shadow roots) for the
32
- * host's own elements: `browser.snapshot` leaves out every matching
33
- * element's nodes, and a node left with nothing by that. The page itself is
34
- * not changed, so what assistive technology reads stays the same.
37
+ * A CSS selector for the host's own elements: `browser.snapshot` leaves out
38
+ * every matching element's nodes (Playwright's selector, which pierces open
39
+ * shadow roots), and a coordinate action that lands on one is refused. The
40
+ * page itself is not changed, so what assistive technology reads stays the
41
+ * same.
35
42
  */
36
43
  snapshotExclude?: string;
44
+ /**
45
+ * The host's last check just before input is dispatched to the page, after
46
+ * the executor has confirmed the main frame still holds the checked
47
+ * document with no navigation in flight. `url` is the page URL the action
48
+ * was checked on. Throwing a `BrowserActionRefusal` refuses the action; no
49
+ * input has been sent.
50
+ */
51
+ beforeInput?: (checked: {
52
+ url: string;
53
+ }) => void | Promise<void>;
37
54
  }
38
55
  /** One action an operation is about to perform. */
39
- export type PlaywrightAction = PlaywrightLocatorAction | PlaywrightScriptAction;
40
- /** A locator action. */
41
- export interface PlaywrightLocatorAction {
42
- action: "click" | "fill" | "press" | "hover" | "focus" | "check" | "uncheck" | "select" | "drag";
43
- locator: Locator;
56
+ export type PlaywrightAction = PlaywrightElementAction | PlaywrightPageAction | PlaywrightScriptAction;
57
+ /** An action on the page as a whole: history navigation, reload, scrolling. */
58
+ export interface PlaywrightPageAction {
59
+ action: "back" | "forward" | "reload" | "scroll";
60
+ /** The page's URL when the action was asked about. */
61
+ url: string;
62
+ value?: unknown;
63
+ }
64
+ export type { GuardedNode, GuardedTarget } from "./guard.js";
65
+ /** An action that lands on an element: by locator, or at a viewport point. */
66
+ export interface PlaywrightElementAction {
67
+ action: "click" | "fill" | "press" | "hover" | "focus" | "check" | "uncheck" | "select" | "drag" | "mousedown" | "mouseup" | "wheel";
68
+ /** What the action lands on, described from the browser side. */
69
+ target: GuardedTarget;
44
70
  value?: unknown;
71
+ /**
72
+ * Raw pointer input (`browser.mouse` down/up/click, `browser.wheel`,
73
+ * `browser.drag`): the target is the element at `target.point` as best
74
+ * known, which a page can change between the look and the press.
75
+ */
76
+ pointer?: boolean;
45
77
  }
46
78
  export interface PlaywrightScriptAction {
47
79
  /** `browser.script`: the author's source, run with the real `page`. */
@@ -61,6 +93,14 @@ export declare class PlaywrightOperationExecutor {
61
93
  private readonly page;
62
94
  private readonly options;
63
95
  private readonly ready;
96
+ private readonly targets;
97
+ /**
98
+ * Where the mouse is: `page.mouse` keeps it, but does not report it. A
99
+ * locator action moves it to the element's clickable point; it is then the
100
+ * centre of that element's box as measured after the action, or unknown
101
+ * (null) when that cannot be measured, and a press needs coordinates.
102
+ */
103
+ private mouse;
64
104
  constructor(page: Page, options: PlaywrightOperationExecutorOptions);
65
105
  execute(raw: unknown): Promise<BrowserOperationResult>;
66
106
  private locator;
@@ -76,8 +116,28 @@ export declare class PlaywrightOperationExecutor {
76
116
  private inspect;
77
117
  /** Run a locator action; a failure on a locator that matches nothing is NOT_FOUND. */
78
118
  private act;
79
- /** The host's policy for an action; an element that is not there is the action's own failure. */
80
- private guard;
119
+ /**
120
+ * Resolves the locator's element once (waiting up to the action budget),
121
+ * asks the host's policy about it, and returns the handle the action must
122
+ * use, so the element guarded is the element acted on. Without a policy the
123
+ * action runs on the locator. Resolution or description failing refuses.
124
+ */
125
+ private guarded;
126
+ /** The document an action is checked on; input later goes only to it. */
127
+ private checkpoint;
128
+ /** Just before input: the same document, no navigation in flight, and the host's own last check. */
129
+ private dispatching;
130
+ /** The page-level action's guard. */
131
+ private guardPage;
132
+ /** The pointer's position for a press that names none; unknown after a locator action. */
133
+ private pointer;
134
+ /**
135
+ * Asks the host's policy about raw pointer input at a viewport point; the
136
+ * target is the element there as best known (`unidentified` when not).
137
+ */
138
+ private guardPoint;
139
+ /** A browser-side description, or the refusal that replaces the action. */
140
+ private describe;
81
141
  /** The aria refs of the elements `snapshotExclude` matches, and of their contents. */
82
142
  private excludedRefs;
83
143
  private revision;