waygraph 0.15.37 → 0.15.38

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.
@@ -72,6 +72,8 @@ export declare class AutoSession {
72
72
  * fallback when a Block's own `resolve()` doesn't set `__state` - same
73
73
  * behavior `applyPick` always had, just factored out, not changed.
74
74
  */
75
+ /** Paint + log a Block's authored waygraph overlay fixtures (same as demo does), best-effort. */
76
+ private paintStubPhase;
75
77
  private runNamedBlock;
76
78
  /** Applies exactly one pick: runs at most one Block, returns the resulting state. */
77
79
  applyPick(raw: string): Promise<ApplyPickResult>;
@@ -1,12 +1,13 @@
1
1
  // Split out of the former 1,078-line auto-session.ts (see src/ARCHITECTURE.md). Behavior unchanged.
2
2
  import { CONSOLE_LOG_MAX_ENTRIES, FULL_MODE_DEFAULT_DEPTH, FULL_MODE_MAX_NODES, FULL_MODE_MAX_TEXT_LENGTH, TRACE_MAX_STEPS, buildSessionSnapshot, parsePick, stubFilePath, stubPhaseHasContent, walkFullDom } from "./helpers.js";
3
- import { instrumentPilotActions, installPersistentPilotOverlay, showPilotActivity, showPilotFixtures, showPilotVision, updatePilotOverlay } from "../pilot-overlay.js";
3
+ import { instrumentPilotActions, installPersistentPilotOverlay, showPilotActivity, showPilotFixtures, showPilotVision, phaseToOverlayFixtures, describeOverlayFixtures, updatePilotOverlay } from "../pilot-overlay.js";
4
4
  import { buildExploreContext, buildExploreMenu } from "../auto-explore.js";
5
5
  import { MemPage } from "../mem-page.js";
6
6
  import { Engine } from "../engine.js";
7
7
  import { detectHere, ensureLivePage, ensureMem, resolveBaseUrl, runOneBlock, seedDefaultMem } from "../auto-explore-run.js";
8
8
  import { collectKnownInteractionSelectors, unmappedInteractionsPageScript } from "../coverage-gap.js";
9
9
  import { runStubPhase } from "../highlights.js";
10
+ import { verboseLog } from "../verbose-log.js";
10
11
  import { findBlockPathDetailed } from "../graph.js";
11
12
  /**
12
13
  * Non-interactive explore session: same graph/library/mem/browser setup
@@ -328,9 +329,19 @@ export class AutoSession {
328
329
  * fallback when a Block's own `resolve()` doesn't set `__state` - same
329
330
  * behavior `applyPick` always had, just factored out, not changed.
330
331
  */
332
+ /** Paint + log a Block's authored waygraph overlay fixtures (same as demo does), best-effort. */
333
+ async paintStubPhase(tag, phase, holdMs) {
334
+ if (!this.page || !stubPhaseHasContent(phase))
335
+ return;
336
+ const fixtures = phaseToOverlayFixtures(phase, holdMs);
337
+ for (const line of describeOverlayFixtures(tag, fixtures))
338
+ verboseLog("pilot", line);
339
+ await showPilotFixtures(this.page, fixtures).catch(() => { });
340
+ }
331
341
  async runNamedBlock(entry, expectedTo, instanceOption) {
332
342
  const from = this.here;
333
343
  const stubBeforeResult = await runStubPhase(entry.block, "stubBefore");
344
+ await this.paintStubPhase("stub.before", stubBeforeResult, 6000);
334
345
  const stepBase = {
335
346
  block: entry.block.name,
336
347
  from,
@@ -348,6 +359,7 @@ export class AutoSession {
348
359
  this.here = result.__state ?? expectedTo;
349
360
  this.lastRunNote = `${entry.block.name} -> ${this.here}`;
350
361
  const stubAfterResult = await runStubPhase(entry.block, "stubAfter", { out: result });
362
+ await this.paintStubPhase("stub.after", stubAfterResult, 6000);
351
363
  this.pushTrace({
352
364
  ...stepBase,
353
365
  to: this.here,
@@ -358,6 +370,7 @@ export class AutoSession {
358
370
  this.lastRunNote = `${entry.block.name} failed`;
359
371
  const message = err instanceof Error ? err.message : String(err);
360
372
  const stubOnErrorResult = await runStubPhase(entry.block, "stubOnError", { error: err });
373
+ await this.paintStubPhase("stub.error", stubOnErrorResult, 8000);
361
374
  this.pushTrace({
362
375
  ...stepBase,
363
376
  error: message,
@@ -588,6 +601,8 @@ export class AutoSession {
588
601
  // Same bottom-left activity toast as Running (Dom)/(Block) - agent narration.
589
602
  await showPilotActivity(this.page, `Highlighting: ${detail}`);
590
603
  try {
604
+ for (const line of describeOverlayFixtures("highlight", fixtures))
605
+ verboseLog("pilot", line);
591
606
  const { painted, missing } = await showPilotFixtures(this.page, fixtures);
592
607
  const menu = await this.currentMenu();
593
608
  this.lastRunNote = fixtures.clear
@@ -7,3 +7,12 @@ import type { PilotHighlightFixtures } from "./fixtures.js";
7
7
  * Not Playwright test fixtures - these describe what the waygraph overlay paints on the page under test.
8
8
  */
9
9
  export declare function overlayFixturesToPhase(f: PilotHighlightFixtures): Promise<StubPhaseResult>;
10
+ /**
11
+ * The reverse: a resolved stub phase (what `runStubPhase` returns for a Block's stubBefore/After/OnError)
12
+ * -> what the Pilot painter takes. Lets `auto/browser/pilot send` paint a Block's authored waygraph overlay
13
+ * fixtures (rings, todos, device, zoom, title/banner) the way `waygraph demo` does, instead of only recording
14
+ * them in the trace.
15
+ */
16
+ export declare function phaseToOverlayFixtures(phase: StubPhaseResult, holdMs?: number): PilotHighlightFixtures;
17
+ /** One verbose line per authored overlay fixture - same wording on every surface so a log reader (or an AI with no eyes) can tell what was painted. */
18
+ export declare function describeOverlayFixtures(tag: string, f: PilotHighlightFixtures): string[];
@@ -43,3 +43,63 @@ export async function overlayFixturesToPhase(f) {
43
43
  };
44
44
  return runStubPhase({ name: "overlay-fixtures", stubBefore: lifecycle }, "stubBefore");
45
45
  }
46
+ /**
47
+ * The reverse: a resolved stub phase (what `runStubPhase` returns for a Block's stubBefore/After/OnError)
48
+ * -> what the Pilot painter takes. Lets `auto/browser/pilot send` paint a Block's authored waygraph overlay
49
+ * fixtures (rings, todos, device, zoom, title/banner) the way `waygraph demo` does, instead of only recording
50
+ * them in the trace.
51
+ */
52
+ export function phaseToOverlayFixtures(phase, holdMs = 6000) {
53
+ const items = phase.todoDock?.groups[0]?.items ?? phase.todos;
54
+ const idx = items.findIndex((t) => t.current) >= 0 ? items.findIndex((t) => t.current) : items.findIndex((t) => !t.done);
55
+ return {
56
+ rings: phase.highlights.map((h) => ({
57
+ selector: h.selector,
58
+ label: h.label ?? "",
59
+ ...(h.detail ? { detail: h.detail } : {}),
60
+ ...(h.tag ? { tag: h.tag } : {}),
61
+ ...(h.tone ? { tone: h.tone } : {}),
62
+ ...(h.size ? { size: h.size } : {}),
63
+ ...(h.weight ? { weight: h.weight } : {}),
64
+ ...(h.color ? { color: h.color } : {}),
65
+ ...(h.zoom !== undefined ? { zoom: h.zoom } : {}),
66
+ ...(h.zoomOut !== undefined ? { zoomOut: h.zoomOut } : {}),
67
+ ...(h.focus ? { focus: true } : {}),
68
+ })),
69
+ ...(phase.todoSync === "set" && items.length
70
+ ? {
71
+ todos: items.map((t) => t.text),
72
+ todoIndex: idx < 0 ? items.length : idx,
73
+ ...(phase.todoDock?.groups[0]?.title ? { todoTitle: phase.todoDock.groups[0].title } : {}),
74
+ ...(phase.todoPos ? { todoPos: phase.todoPos } : {}),
75
+ }
76
+ : {}),
77
+ ...(phase.todoDockUi ? { todoDockUi: phase.todoDockUi } : {}),
78
+ ...(phase.deviceSync === "set" && phase.device ? { device: phase.device } : {}),
79
+ ...(phase.zoom !== undefined ? { zoom: phase.zoom } : {}),
80
+ ...(phase.zoomOut !== undefined ? { zoomOut: phase.zoomOut } : {}),
81
+ ...(phase.title ? { title: phase.title } : {}),
82
+ ...(phase.titlePos ? { titlePos: phase.titlePos } : {}),
83
+ ...(phase.bannerUi ? { bannerUi: phase.bannerUi } : {}),
84
+ holdMs,
85
+ };
86
+ }
87
+ /** One verbose line per authored overlay fixture - same wording on every surface so a log reader (or an AI with no eyes) can tell what was painted. */
88
+ export function describeOverlayFixtures(tag, f) {
89
+ const out = [];
90
+ if (f.title)
91
+ out.push(`${tag} ctx.title(${JSON.stringify(f.title)})${f.titlePos ? ` pos=${f.titlePos}` : ""}`);
92
+ if (f.bannerUi)
93
+ out.push(`${tag} ctx.bannerUi(${JSON.stringify(f.bannerUi)})`);
94
+ if (f.todos?.length)
95
+ out.push(`${tag} ctx.todos n=${f.todos.length} index=${f.todoIndex ?? 0}${f.todoPos ? ` pos=${f.todoPos}` : ""}`);
96
+ if (f.todoDockUi ?? f.todoUi)
97
+ out.push(`${tag} ctx.todoDockUi(${JSON.stringify(f.todoDockUi ?? f.todoUi)})`);
98
+ if (f.device)
99
+ out.push(`${tag} ctx.device(${typeof f.device === "string" ? f.device : f.device.preset ?? "custom"})`);
100
+ if (f.zoom)
101
+ out.push(`${tag} ctx.zoom(${f.zoom})`);
102
+ for (const r of f.rings ?? [])
103
+ out.push(`${tag} ring ${r.selector} tone=${r.tone ?? "planned"} label=${JSON.stringify(r.label)}`);
104
+ return out;
105
+ }
@@ -0,0 +1,6 @@
1
+ [21:45:47.529] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [21:45:47.529] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [21:45:47.529] waygraph pilot: stub.before ctx.device(mobile)
4
+ [21:45:47.529] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [21:45:47.529] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [21:45:47.633] waygraph pilot: stub.after ctx.todos n=6 index=1
@@ -0,0 +1,22 @@
1
+ [21:46:29.741] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [21:46:29.741] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [21:46:29.741] waygraph pilot: stub.before ctx.device(mobile)
4
+ [21:46:29.741] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [21:46:29.741] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [21:46:29.866] waygraph pilot: stub.after ctx.todos n=6 index=1
7
+ [21:46:31.935] waygraph pilot: stub.before ring #password tone=planned label="Password"
8
+ [21:46:31.998] waygraph pilot: stub.after ctx.todos n=6 index=2
9
+ [21:46:33.773] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
10
+ [21:46:33.961] waygraph pilot: stub.after ctx.title("Inventory · landscape")
11
+ [21:46:33.961] waygraph pilot: stub.after ctx.todos n=6 index=3
12
+ [21:46:33.961] waygraph pilot: stub.after ctx.device(mobile)
13
+ [21:46:33.961] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
14
+ [21:46:37.277] waygraph pilot: stub.before ctx.title("Pick a product · tablet")
15
+ [21:46:37.277] waygraph pilot: stub.before ctx.todos n=6 index=3
16
+ [21:46:37.277] waygraph pilot: stub.before ctx.device(tablet)
17
+ [21:46:37.277] waygraph pilot: stub.before ctx.zoom(1.35)
18
+ [21:46:37.277] waygraph pilot: stub.before ring div.inventory_item:has(button[data-test="add-to-cart-sauce-labs-backpack"], button[data-test="remove-sauce-labs-backpack"]) .inventory_item_name tone=info label="Sauce Labs Backpack"
19
+ [21:46:37.277] waygraph pilot: stub.before ring [data-test="add-to-cart-sauce-labs-backpack"] tone=success label="Add to cart"
20
+ [21:46:37.375] waygraph pilot: stub.after ctx.title("In the cart")
21
+ [21:46:37.376] waygraph pilot: stub.after ctx.todos n=6 index=4
22
+ [21:46:37.376] waygraph pilot: stub.after ring .shopping_cart_badge tone=success label="Cart badge"
@@ -0,0 +1,5 @@
1
+ [21:46:10.717] waygraph pilot: highlight ctx.todos n=3 index=0
2
+ [21:46:10.717] waygraph pilot: highlight ring #user-name tone=planned label="Username"
3
+ [21:46:10.717] waygraph pilot: highlight ring #password tone=info label="Password"
4
+ [21:46:12.774] waygraph pilot: highlight ring #no-such-element-waygraph tone=danger label="Gone"
5
+ [21:46:14.903] waygraph pilot: highlight ring #login-button tone=success label="Login"
@@ -0,0 +1,20 @@
1
+ [21:46:24.561] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [21:46:24.562] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [21:46:24.562] waygraph pilot: stub.before ctx.device(mobile)
4
+ [21:46:24.562] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [21:46:24.562] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [21:46:24.751] waygraph pilot: stub.after ctx.todos n=6 index=1
7
+ [21:46:25.895] waygraph pilot: stub.before ring #password tone=planned label="Password"
8
+ [21:46:25.977] waygraph pilot: stub.after ctx.todos n=6 index=2
9
+ [21:46:27.278] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
10
+ [21:46:27.476] waygraph pilot: stub.after ctx.title("Inventory · landscape")
11
+ [21:46:27.476] waygraph pilot: stub.after ctx.todos n=6 index=3
12
+ [21:46:27.476] waygraph pilot: stub.after ctx.device(mobile)
13
+ [21:46:27.476] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
14
+ [21:46:28.988] waygraph pilot: stub.before ctx.title("Open cart · landscape")
15
+ [21:46:28.988] waygraph pilot: stub.before ctx.todos n=6 index=5
16
+ [21:46:28.988] waygraph pilot: stub.before ctx.device(mobile)
17
+ [21:46:28.988] waygraph pilot: stub.before ctx.zoom(1.4)
18
+ [21:46:28.988] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
19
+ [21:46:29.115] waygraph pilot: stub.after ctx.title("Your cart · desktop")
20
+ [21:46:29.116] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"
@@ -0,0 +1,6 @@
1
+ [21:46:28.846] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [21:46:28.846] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [21:46:28.846] waygraph pilot: stub.before ctx.device(mobile)
4
+ [21:46:28.847] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [21:46:28.847] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [21:46:29.003] waygraph pilot: stub.after ctx.todos n=6 index=1
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.15.37",
3
+ "version": "0.15.38",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",