teamshare-bridge 0.26.13 → 0.26.15

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 (48) hide show
  1. package/dist/cli/commands/research.js +10 -2
  2. package/dist/cli/commands/research.js.map +1 -1
  3. package/dist/cli/commands/run.js +0 -21
  4. package/dist/cli/commands/run.js.map +1 -1
  5. package/dist/lib/browser/batch.d.ts +77 -1
  6. package/dist/lib/browser/batch.js +151 -3
  7. package/dist/lib/browser/batch.js.map +1 -1
  8. package/dist/lib/browser/cdp.d.ts +61 -2
  9. package/dist/lib/browser/cdp.js +235 -14
  10. package/dist/lib/browser/cdp.js.map +1 -1
  11. package/dist/lib/browser/index.d.ts +2 -2
  12. package/dist/lib/browser/index.js +4 -1
  13. package/dist/lib/browser/index.js.map +1 -1
  14. package/dist/lib/browser/login.d.ts +20 -2
  15. package/dist/lib/browser/login.js +125 -88
  16. package/dist/lib/browser/login.js.map +1 -1
  17. package/dist/lib/browser/network-log.d.ts +31 -0
  18. package/dist/lib/browser/network-log.js +94 -12
  19. package/dist/lib/browser/network-log.js.map +1 -1
  20. package/dist/lib/browser/page-context.d.ts +62 -1
  21. package/dist/lib/browser/page-context.js +284 -1
  22. package/dist/lib/browser/page-context.js.map +1 -1
  23. package/dist/lib/browser/refs.d.ts +104 -0
  24. package/dist/lib/browser/refs.js +430 -0
  25. package/dist/lib/browser/refs.js.map +1 -0
  26. package/dist/lib/browser/session.d.ts +188 -7
  27. package/dist/lib/browser/session.js +537 -8
  28. package/dist/lib/browser/session.js.map +1 -1
  29. package/dist/lib/git/git-finalize.js +17 -2
  30. package/dist/lib/git/git-finalize.js.map +1 -1
  31. package/dist/lib/harness/harness-adapter.d.ts +2 -5
  32. package/dist/lib/harness/harness-adapter.js.map +1 -1
  33. package/dist/lib/harness/opencode-control.d.ts +73 -0
  34. package/dist/lib/harness/opencode-control.js +318 -0
  35. package/dist/lib/harness/opencode-control.js.map +1 -1
  36. package/dist/lib/harness/opencode-outcome.d.ts +16 -2
  37. package/dist/lib/harness/opencode-outcome.js +36 -7
  38. package/dist/lib/harness/opencode-outcome.js.map +1 -1
  39. package/dist/lib/harness/spawn.js +112 -48
  40. package/dist/lib/harness/spawn.js.map +1 -1
  41. package/dist/lib/orchestrator/handlers/browser.js +472 -27
  42. package/dist/lib/orchestrator/handlers/browser.js.map +1 -1
  43. package/dist/lib/tools/browser-tool.js +24 -3
  44. package/dist/lib/tools/browser-tool.js.map +1 -1
  45. package/dist/lib/workspace/repo-lock.d.ts +5 -1
  46. package/dist/lib/workspace/repo-lock.js +5 -3
  47. package/dist/lib/workspace/repo-lock.js.map +1 -1
  48. package/package.json +1 -1
@@ -1,9 +1,10 @@
1
1
  import type { CdpPage, ElementInfo, PageInfo, PageText, PageLink } from './cdp';
2
- import { type NetworkEntry, type ConsoleEntry } from './network-log';
2
+ import { type NetworkEntry, type ConsoleEntry, type WebSocketFrame, type NetworkLogStatus } from './network-log';
3
3
  import { type ReadStagedResult, type FillExcelResult } from './xlsx-template';
4
- import { type LoginResult, type PerformLoginOptions } from './login';
5
- import { type NativeDialogState, type PageSnapshot, type WaitForKind } from './page-context';
4
+ import { type LoginResult, type PerformLoginOptions, type TypeResult } from './login';
5
+ import { type NativeDialogState, type PagePaginationState, type PageSnapshot, type WaitForKind } from './page-context';
6
6
  import { type PageEvent } from './page-events';
7
+ import { type RefElement } from './refs';
7
8
  /**
8
9
  * Persistent Chrome profile for the AUTO-ANSWER browser (research reads,
9
10
  * `browse --auto-answer`, the web-auto-answer tool).
@@ -55,6 +56,16 @@ export interface BrowserSessionOptions {
55
56
  * `type()` keeps throwing `LOGIN_BLOCKED` for a credential field.
56
57
  */
57
58
  allowCredentials?: boolean;
59
+ /**
60
+ * OPT-IN (default false): QA VISION mode (2026-10).
61
+ *
62
+ * When on, every mutating action result carries an inline screenshot (the
63
+ * bridge handler captures it) and `snapshot({refs:true})` can hand back an
64
+ * accessibility-style ref list. Only a QA run turns it on
65
+ * (`browser_open({ qaVision: true })`, instructed by the QA brief), so the
66
+ * interactive browser and the auto-answer path are unchanged.
67
+ */
68
+ qaVision?: boolean;
58
69
  }
59
70
  export declare class BrowserSession {
60
71
  private readonly id;
@@ -68,6 +79,14 @@ export declare class BrowserSession {
68
79
  private _connected;
69
80
  /** Opt-in credential entry (see BrowserSessionOptions.allowCredentials). */
70
81
  private _allowCredentials;
82
+ /** Opt-in QA vision mode (see BrowserSessionOptions.qaVision). */
83
+ private _qaVision;
84
+ /**
85
+ * The last ref scan (2026-10). Kept so a stale ref can be explained and,
86
+ * when a unique same-role/same-name element exists in the fresh scan,
87
+ * transparently re-pointed - instead of failing with a mute miss.
88
+ */
89
+ private _lastRefs;
71
90
  /**
72
91
  * True when THIS bridge process launched the Chrome this session is attached
73
92
  * to. Only such a browser may be terminated by the bridge; one the human
@@ -108,6 +127,12 @@ export declare class BrowserSession {
108
127
  */
109
128
  setAllowCredentials(allow: boolean): void;
110
129
  get allowCredentials(): boolean;
130
+ /**
131
+ * Toggle QA vision mode (2026-10). Persists across actions, exactly like
132
+ * allowCredentials: `browser_open({ qaVision: true })` sets it once.
133
+ */
134
+ setQaVision(on: boolean): void;
135
+ get qaVision(): boolean;
111
136
  /** The native JS dialog currently blocking the page, if any. */
112
137
  get nativeDialog(): NativeDialogState | null;
113
138
  /** Last time a command actually used this session (drives idle close). */
@@ -176,13 +201,73 @@ export declare class BrowserSession {
176
201
  error?: string;
177
202
  }>;
178
203
  /**
179
- * Navigate to a URL. Returns page info after navigation.
204
+ * Current pagination state (controls, page, page size, total, rows).
205
+ * Scoped to the top dialog by the page-state script.
206
+ */
207
+ pagination(): Promise<PagePaginationState>;
208
+ /** Stable-ish signature used to prove a page actually changed. */
209
+ private paginationSignature;
210
+ private waitPaginationChange;
211
+ private clickPagination;
212
+ /** Move to the next page (or Load more) and wait for the content to change. */
213
+ nextPage(timeoutMs?: number): Promise<{
214
+ moved: boolean;
215
+ elapsedMs: number;
216
+ state: PagePaginationState;
217
+ reason?: string;
218
+ }>;
219
+ /** Move to the previous page. */
220
+ prevPage(timeoutMs?: number): Promise<{
221
+ moved: boolean;
222
+ elapsedMs: number;
223
+ state: PagePaginationState;
224
+ reason?: string;
225
+ }>;
226
+ /** Go to a numbered page; walks next if the page control is not rendered. */
227
+ gotoPage(page: number, timeoutMs?: number): Promise<{
228
+ moved: boolean;
229
+ elapsedMs: number;
230
+ state: PagePaginationState;
231
+ reason?: string;
232
+ }>;
233
+ /** Select a native page-size option (custom comboboxes use click + waitFor). */
234
+ setPageSize(size: number): Promise<{
235
+ ok: boolean;
236
+ state: PagePaginationState;
237
+ error?: string;
238
+ }>;
239
+ /**
240
+ * Read the current table (headers + rows), then walk every page and return
241
+ * the deduplicated rows. Bounded by maxPages/maxRows; stops on a repeated
242
+ * page signature, a disabled pager, or an unchanged table.
180
243
  */
244
+ collectTable(opts?: {
245
+ selector?: string;
246
+ maxPages?: number;
247
+ maxRows?: number;
248
+ pageSize?: number;
249
+ }): Promise<{
250
+ headers: string[];
251
+ rows: string[][];
252
+ rowCount: number;
253
+ pagesVisited: number;
254
+ total?: number;
255
+ complete: boolean;
256
+ duplicates: number;
257
+ truncated: boolean;
258
+ stoppedBecause: string;
259
+ }>;
181
260
  navigate(url: string): Promise<PageInfo>;
182
261
  /**
183
262
  * Capture a screenshot. Returns base64-encoded data.
184
263
  */
185
264
  screenshot(format?: 'jpeg' | 'png', quality?: number): Promise<string>;
265
+ /**
266
+ * Capture a screenshot with numbered ref labels drawn over the interactive
267
+ * elements, then remove the overlay (2026-10). One image shows the page AND
268
+ * names every target; the page is never left modified.
269
+ */
270
+ annotatedScreenshot(format?: 'jpeg' | 'png', quality?: number): Promise<string>;
186
271
  /**
187
272
  * Read the network + console evidence collected for this session (QA).
188
273
  * `onlyProblems` narrows to failures/redirects; `clear` empties the buffer
@@ -196,11 +281,99 @@ export declare class BrowserSession {
196
281
  }): Promise<{
197
282
  requests: NetworkEntry[];
198
283
  console: ConsoleEntry[];
284
+ websockets: WebSocketFrame[];
285
+ status: NetworkLogStatus;
199
286
  }>;
200
287
  /**
201
- * Click at (x, y) coordinates.
288
+ * Click at (x, y) CSS pixels. Coordinates OUTSIDE the current viewport are
289
+ * refused loudly — a screenshot pixel is not a CSS pixel (the capture is
290
+ * device-scale), so clicking one lands on the wrong element.
202
291
  */
203
292
  click(x: number, y: number): Promise<void>;
293
+ /**
294
+ * Click by reference instead of raw coordinates: an element REF (`e7`, from
295
+ * getRefs / snapshot refs:true), explicit x/y, a fresh `getElements` index,
296
+ * or a CSS selector resolved in-page. Coordinates from a screenshot image are
297
+ * NEVER accepted here — they are device-scale.
298
+ */
299
+ clickRef(ref: {
300
+ ref?: string;
301
+ x?: number;
302
+ y?: number;
303
+ elementIndex?: number;
304
+ selector?: string;
305
+ }): Promise<{
306
+ x: number;
307
+ y: number;
308
+ refreshedFrom?: string;
309
+ }>;
310
+ /**
311
+ * Fresh element-ref scan (2026-10).
312
+ *
313
+ * Returns the interactive elements of the CURRENT page as `e1 … eN` with
314
+ * role, accessible name, state and CSS-pixel centre. Includes elements
315
+ * inside portalled menus/popovers/dialogs, which is the whole point: a kebab
316
+ * menu that just opened is findable without guessing a selector.
317
+ */
318
+ getRefs(): Promise<{
319
+ at: number;
320
+ count: number;
321
+ refs: RefElement[];
322
+ lines: string[];
323
+ }>;
324
+ /**
325
+ * Resolve a ref to a clickable point. A ref whose node left the DOM is
326
+ * either re-pointed at a UNIQUE same-role/same-name element from a fresh
327
+ * scan (the common case: a re-render replaced the node), or refused with
328
+ * `REF_STALE` - never silently clicked at stale coordinates.
329
+ */
330
+ private resolveRefPoint;
331
+ /** Move the pointer to (x, y) without clicking (hover menus/tooltips). */
332
+ hover(x: number, y: number): Promise<void>;
333
+ /** Hover an element by ref (preferred) or CSS selector. */
334
+ hoverRef(ref: {
335
+ ref?: string;
336
+ selector?: string;
337
+ }): Promise<{
338
+ x: number;
339
+ y: number;
340
+ refreshedFrom?: string;
341
+ }>;
342
+ /**
343
+ * Click a ref'd element with the IN-PAGE pointer sequence instead of a CDP
344
+ * coordinate click (2026-10). This is the rescue for a control that ignores
345
+ * a normal click (the Radix lesson from the web tours: some activators only
346
+ * react to a full pointerdown/mousedown gesture). Explicit, never automatic:
347
+ * a blind second click after "nothing happened" could double-submit a form.
348
+ */
349
+ clickPointerRef(ref: string): Promise<{
350
+ x: number;
351
+ y: number;
352
+ }>;
353
+ /**
354
+ * Focus an element by ref (2026-10). Reports whether focus actually moved:
355
+ * a plain div without tabindex cannot take focus, and claiming `ok:true`
356
+ * while the active element is unchanged is how a QA step "passes" having
357
+ * done nothing.
358
+ */
359
+ focusRef(ref: string): Promise<{
360
+ ok: boolean;
361
+ alive: boolean;
362
+ tag?: string;
363
+ contentEditable?: boolean;
364
+ refreshedFrom?: string;
365
+ }>;
366
+ /**
367
+ * Close whatever menu/popover layer is open (2026-10): Escape first (Radix
368
+ * DismissableLayer), then a document-level outside pointer sequence for
369
+ * layers that ignore Escape. Reports what is left, so a "still open" menu is
370
+ * visible instead of silently swallowing the next click.
371
+ */
372
+ closePopup(): Promise<{
373
+ closed: boolean;
374
+ popoversLeft: number;
375
+ }>;
376
+ private countPopovers;
204
377
  /**
205
378
  * Type text at the current cursor position, VERIFYING it landed.
206
379
  *
@@ -208,10 +381,13 @@ export declare class BrowserSession {
208
381
  * caller opted in (`browser_open({ allowCredentials: true })`) AND passed a
209
382
  * credential for the run - the debug browser is the QA surface, the
210
383
  * auto-answer loop is a separate path that still never touches credentials.
384
+ *
385
+ * An insert the page does not reflect is refused with `TYPE_NOT_VERIFIED`
386
+ * (carrying the observed field state) — never reported as success.
211
387
  */
212
388
  type(text: string, opts?: {
213
389
  clearFirst?: boolean;
214
- }): Promise<void>;
390
+ }): Promise<TypeResult>;
215
391
  /**
216
392
  * Deterministically fill a login form (username + password) and submit.
217
393
  * Handles the common two-step email -> Continue -> password flow. Requires
@@ -368,7 +544,12 @@ export declare class BrowserSession {
368
544
  includeText?: boolean;
369
545
  maxTextChars?: number;
370
546
  maxFields?: number;
371
- }): Promise<PageSnapshot>;
547
+ /** Also return the interactive element refs (QA vision, 2026-10). */
548
+ refs?: boolean;
549
+ }): Promise<PageSnapshot & {
550
+ refs?: RefElement[];
551
+ refsText?: string[];
552
+ }>;
372
553
  /**
373
554
  * Bounded state attached to every mutating action result. Never include the
374
555
  * page text (that is what `snapshot` is for); a failure returns null so an