waygraph 0.16.0 → 0.16.2

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 (143) hide show
  1. package/dist/cli/commands/browser.d.ts +2 -0
  2. package/dist/cli/commands/browser.js +109 -0
  3. package/dist/cli/commands/codemod-stubs.js +90 -2
  4. package/dist/cli/commands/pilot.d.ts +2 -0
  5. package/dist/cli/commands/pilot.js +102 -0
  6. package/dist/cli/commands/session-ops.d.ts +3 -0
  7. package/dist/cli/commands/session-ops.js +257 -0
  8. package/dist/cli/commands/session.js +20 -461
  9. package/dist/cli/run-chain.js +2 -2
  10. package/dist/cli/usage.d.ts +1 -1
  11. package/dist/cli/util.js +1 -1
  12. package/dist/demo/narration/demo-pace.d.ts +2 -2
  13. package/dist/demo/narration/demo-pace.js +1 -1
  14. package/dist/demo/narration/device.d.ts +2 -2
  15. package/dist/demo/narration/merge.d.ts +5 -3
  16. package/dist/demo/narration/merge.js +3 -7
  17. package/dist/demo/narration/narration.d.ts +9 -13
  18. package/dist/demo/narration/narration.js +5 -17
  19. package/dist/demo/narration/stub-ctx.js +3 -3
  20. package/dist/demo/narration/todo-dock.d.ts +5 -5
  21. package/dist/demo/overlay/cursor.d.ts +9 -2
  22. package/dist/demo/overlay/cursor.js +1 -1
  23. package/dist/demo/overlay/device-stage.d.ts +15 -2
  24. package/dist/demo/overlay/inpage/banner.d.ts +2 -1
  25. package/dist/demo/overlay/inpage/banner.js +3 -3
  26. package/dist/demo/overlay/inpage/caption.d.ts +1 -1
  27. package/dist/demo/overlay/inpage/core.d.ts +2 -1
  28. package/dist/demo/overlay/inpage/core.js +1 -7
  29. package/dist/demo/overlay/inpage/device-chip.d.ts +1 -1
  30. package/dist/demo/overlay/inpage/device-chip.js +6 -6
  31. package/dist/demo/overlay/inpage/network.d.ts +3 -2
  32. package/dist/demo/overlay/inpage/network.js +1 -12
  33. package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -1
  34. package/dist/demo/overlay/inpage/panel-chrome.js +1 -1
  35. package/dist/demo/overlay/inpage/stamp.d.ts +1 -1
  36. package/dist/demo/overlay/inpage/stamp.js +1 -1
  37. package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -1
  38. package/dist/demo/overlay/inpage/swipe-zoom.js +1 -1
  39. package/dist/demo/overlay/inpage/todos.d.ts +2 -1
  40. package/dist/demo/overlay/inpage/todos.js +1 -2
  41. package/dist/demo/overlay/network-capture.d.ts +2 -2
  42. package/dist/demo/overlay/network-capture.js +1 -1
  43. package/dist/demo/overlay/overlay-css.js +1 -55
  44. package/dist/demo/overlay/overlay-stage.d.ts +19 -11
  45. package/dist/demo/overlay/overlay.d.ts +2 -2
  46. package/dist/demo/overlay/overlay.js +3 -2
  47. package/dist/demo/overlay/rings.d.ts +38 -18
  48. package/dist/demo/overlay/rings.js +21 -62
  49. package/dist/demo/overlay/ui/overlay.css +40 -0
  50. package/dist/demo/stepper/after.js +11 -34
  51. package/dist/demo/stepper/banner-log.d.ts +4 -6
  52. package/dist/demo/stepper/banner-log.js +3 -1
  53. package/dist/demo/stepper/before.js +6 -4
  54. package/dist/demo/stepper/demo-log.d.ts +26 -9
  55. package/dist/demo/stepper/demo-log.js +10 -27
  56. package/dist/demo/stepper/interaction-patch.d.ts +3 -2
  57. package/dist/demo/stepper/interaction-patch.js +22 -34
  58. package/dist/demo/stepper/panel-after.d.ts +17 -0
  59. package/dist/demo/stepper/panel-after.js +166 -0
  60. package/dist/demo/stepper/panel-before.d.ts +12 -0
  61. package/dist/demo/stepper/panel-before.js +241 -0
  62. package/dist/demo/stepper/slides.d.ts +16 -1
  63. package/dist/demo/stepper/slides.js +21 -5
  64. package/dist/demo/stepper/step-panels.d.ts +57 -9
  65. package/dist/demo/stepper/step-panels.js +10 -427
  66. package/dist/demo/stepper/stepper.js +1 -1
  67. package/dist/demo/stepper/teardown.d.ts +4 -5
  68. package/dist/demo/stepper/teardown.js +4 -6
  69. package/dist/demo/stepper/todo-advance.d.ts +3 -2
  70. package/dist/demo/stepper/todo-advance.js +2 -2
  71. package/dist/demo/stepper/view.d.ts +4 -14
  72. package/dist/demo/types.d.ts +69 -1
  73. package/dist/demo/verbose-log.js +1 -1
  74. package/dist/engine/block/action-page.d.ts +53 -0
  75. package/dist/engine/block/action-page.js +1 -0
  76. package/dist/engine/block/block.d.ts +24 -90
  77. package/dist/engine/block/block.js +2 -77
  78. package/dist/engine/block/branch.d.ts +17 -0
  79. package/dist/engine/block/branch.js +40 -0
  80. package/dist/engine/block/dialog.d.ts +13 -0
  81. package/dist/engine/block/dialog.js +37 -0
  82. package/dist/engine/block/kinds/method.d.ts +0 -2
  83. package/dist/engine/block/kinds/method.js +0 -1
  84. package/dist/engine/block/kinds/nav.js +1 -1
  85. package/dist/engine/flow/map-branch.d.ts +9 -0
  86. package/dist/engine/flow/map-branch.js +57 -0
  87. package/dist/engine/flow/map-builder.d.ts +7 -22
  88. package/dist/engine/flow/map-builder.js +6 -145
  89. package/dist/engine/flow/map-steps.d.ts +30 -0
  90. package/dist/engine/flow/map-steps.js +87 -0
  91. package/dist/engine/run/run.d.ts +1 -19
  92. package/dist/engine/run/run.js +0 -88
  93. package/dist/engine/stub/ring.d.ts +2 -4
  94. package/dist/engine/stub/ring.js +1 -0
  95. package/dist/engine/stub/stub.d.ts +16 -8
  96. package/dist/engine/trait/trait.js +1 -1
  97. package/dist/index.d.ts +15 -12
  98. package/dist/index.js +9 -7
  99. package/dist/live/auto/auto.d.ts +3 -15
  100. package/dist/live/auto/auto.js +10 -420
  101. package/dist/live/auto/explore.d.ts +2 -2
  102. package/dist/live/auto/mem.d.ts +11 -0
  103. package/dist/live/auto/mem.js +85 -0
  104. package/dist/live/auto/menu.d.ts +30 -0
  105. package/dist/live/auto/menu.js +335 -0
  106. package/dist/live/auto-session/auto-session.d.ts +23 -103
  107. package/dist/live/auto-session/auto-session.js +100 -370
  108. package/dist/live/auto-session/console.d.ts +4 -0
  109. package/dist/live/auto-session/console.js +41 -0
  110. package/dist/live/auto-session/files.d.ts +44 -0
  111. package/dist/live/auto-session/files.js +145 -0
  112. package/dist/live/auto-session/helpers.d.ts +5 -2
  113. package/dist/live/auto-session/helpers.js +17 -0
  114. package/dist/live/auto-session/inspect.d.ts +4 -0
  115. package/dist/live/auto-session/inspect.js +75 -0
  116. package/dist/live/auto-session/ipc.d.ts +3 -22
  117. package/dist/live/auto-session/ipc.js +7 -147
  118. package/dist/live/auto-session/open-browser.d.ts +6 -0
  119. package/dist/live/auto-session/open-browser.js +47 -0
  120. package/dist/live/pilot/pilot.d.ts +1 -1
  121. package/dist/live/pilot/pilot.js +2 -1
  122. package/dist/live/traverse/traverse.js +6 -200
  123. package/dist/live/traverse/worker.d.ts +37 -0
  124. package/dist/live/traverse/worker.js +200 -0
  125. package/dist/runner/plan/find.js +2 -2
  126. package/dist/runner/plan/plan.js +1 -1
  127. package/dist/runner/plan/seed-mem.js +5 -5
  128. package/dist/runner/plan/spec.js +1 -1
  129. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +2 -34
  130. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +2 -1
  131. package/examples/saucedemo/src/flows/checkout.flow.ts +2 -1
  132. package/examples/saucedemo/src/flows/shop.flow.ts +2 -1
  133. package/examples/saucedemo/src/stubs/device-showcase.ts +37 -43
  134. package/examples/saucedemo/src/stubs/finish-order.ts +38 -0
  135. package/package.json +5 -1
  136. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +2 -34
  137. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +2 -1
  138. package/templates/quickstart/src/flows/checkout.flow.ts +2 -1
  139. package/templates/quickstart/src/flows/shop.flow.ts +2 -1
  140. package/templates/quickstart/src/stubs/device-showcase.ts +37 -43
  141. package/templates/quickstart/src/stubs/finish-order.ts +38 -0
  142. package/templates/scaffold/src/flows/home/hello.flow.ts +3 -0
  143. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +1 -9
@@ -3,7 +3,7 @@ import { applyDefaultZoom, applyDefaultZoomOut, readStubRaw, resolvePhaseMap } f
3
3
  import { buildTodoDock, normalizeTodoStyle, normalizeTodos } from "./todo-dock.js";
4
4
  import { resolveDeviceState } from "./device.js";
5
5
  /**
6
- * Run an open stub lifecycle (preferred) or resolve a static slot map.
6
+ * Runs a Block's stub for one phase and returns what it painted.
7
7
  * Returns rings + episode fixtures (todos / todoIndex / zoom).
8
8
  *
9
9
  * @example
@@ -27,6 +27,9 @@ export async function runStubPhase(block, phase, opts) {
27
27
  throw new Error(`${block.name}: its ${phase} stub threw: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
28
28
  }
29
29
  }
30
+ if (phase === "stubOnError" && bag.slides?.length) {
31
+ throw new Error(`${block.name}: its stubOnError stub set slides; slides play before or after a step (stubBefore / stubAfter), not on its failure`);
32
+ }
30
33
  let highlights = applyDefaultZoom(resolvePhaseMap(bag.highlights), bag.zoom);
31
34
  highlights = applyDefaultZoomOut(highlights, bag.zoomOut);
32
35
  const todoDock = bag.hideTodos
@@ -95,6 +98,7 @@ export async function runStubPhase(block, phase, opts) {
95
98
  // Boolean, not string - "" isn't a state here, so a plain undefined-check (like zoom/title)
96
99
  // is enough; false is real ("author called hideNetworkTab()") and must still be forwarded.
97
100
  ...(bag.networkTabVisible !== undefined ? { networkTabVisible: bag.networkTabVisible } : {}),
101
+ slides: [...(bag.slides ?? [])],
98
102
  ...(bag.todoPos !== undefined ? { todoPos: bag.todoPos } : {}),
99
103
  ...(bag.todoDockUi !== undefined ? { todoDockUi: bag.todoDockUi } : {}),
100
104
  ...(bag.todoParallel === true ? { todoParallel: true } : {}),
@@ -118,22 +122,6 @@ export function resolveHighlightSlots(block, phase, opts) {
118
122
  }
119
123
  return applyDefaultZoom(resolvePhaseMap(bag.highlights), bag.zoom);
120
124
  }
121
- /** Resolve multi-step yap slides from `instruction.slides` (function form allowed). */
122
- export function resolveSlides(block, opts) {
123
- const instr = block.instruction;
124
- let raw = instr.slides;
125
- if (typeof raw === "function") {
126
- try {
127
- raw = raw(opts?.out ?? { __state: "" });
128
- }
129
- catch {
130
- raw = [];
131
- }
132
- }
133
- if (!Array.isArray(raw))
134
- return [];
135
- return raw.filter((s) => s && typeof s.caption === "string" && s.caption.length > 0);
136
- }
137
125
  function stubPhaseLooksAuthored(block, phase) {
138
126
  return readStubRaw(block, phase) !== undefined;
139
127
  }
@@ -25,9 +25,6 @@ export function createStubCtx(bag, opts) {
25
25
  mem: opts.mem,
26
26
  out: opts.out,
27
27
  error: opts.error,
28
- highlights(slots) {
29
- bag.highlights = { ...(slots || {}) };
30
- },
31
28
  ring(id, stub) {
32
29
  bag.highlights = { ...bag.highlights, [id]: stub };
33
30
  },
@@ -134,6 +131,9 @@ export function createStubCtx(bag, opts) {
134
131
  caption(text) {
135
132
  bag.caption = String(text ?? "");
136
133
  },
134
+ slides(slides) {
135
+ bag.slides = slides;
136
+ },
137
137
  hideCaption() {
138
138
  bag.caption = "";
139
139
  },
@@ -31,11 +31,11 @@ export declare function buildTodoDock(opts: {
31
31
  * - keep: author omitted todos — preserve previous dock (do not wipe)
32
32
  */
33
33
  export declare function applyTodoPhase(prev: TodoDockState | undefined, phase: {
34
- todoSync?: "set" | "clear" | "keep";
35
- todoDock?: TodoDockState;
36
- todos?: WaygraphTodoItem[];
37
- todoPos?: "left" | "right";
38
- todoId?: string;
34
+ todoSync?: "set" | "clear" | "keep" | undefined;
35
+ todoDock?: TodoDockState | undefined;
36
+ todos?: WaygraphTodoItem[] | undefined;
37
+ todoPos?: "left" | "right" | undefined;
38
+ todoId?: string | undefined;
39
39
  }): {
40
40
  dock: TodoDockState | undefined;
41
41
  sync: "set" | "clear" | "keep";
@@ -1,12 +1,19 @@
1
1
  import type { WgBox, WgPage } from "../types.js";
2
+ /** A touch swipe: which way, its caption (plus an optional hint) and how long it takes. */
3
+ export interface SwipeTrailOptions {
4
+ dir?: "left" | "right" | "up" | "down";
5
+ label?: string;
6
+ hint?: string;
7
+ ms?: number;
8
+ }
2
9
  export declare function moveCursorTo(page: WgPage, box: WgBox, ms: number): Promise<{
3
10
  x: number;
4
11
  y: number;
5
12
  }>;
6
- export declare function clickPulseAt(page: WgPage, x: any, y: any, tone: any): Promise<void>;
13
+ export declare function clickPulseAt(page: WgPage, x: number, y: number, tone?: string): Promise<void>;
7
14
  /**
8
15
  * Touch swipe trail (mobile/tablet). dir: left|right|up|down.
9
16
  * Returns after the trail animation completes.
10
17
  * Self-contained when overlay helper is not installed yet (device runs before panel).
11
18
  */
12
- export declare function playSwipeTrail(page: WgPage, opts: any): Promise<void>;
19
+ export declare function playSwipeTrail(page: WgPage, opts?: SwipeTrailOptions): Promise<void>;
@@ -135,7 +135,7 @@ export async function playSwipeTrail(page, opts) {
135
135
  hint: o.hint || "",
136
136
  ms: o.ms || 720,
137
137
  })
138
- .catch(() => 0);
138
+ .catch(ignorePageGone);
139
139
  const n = Number(waitMs) || 0;
140
140
  if (n > 0)
141
141
  await new Promise((r) => setTimeout(r, n));
@@ -1,13 +1,26 @@
1
+ import type { DeviceState } from "../../engine/stub/viewport.js";
1
2
  import type { WgPage } from "../types.js";
3
+ interface Size {
4
+ width: number;
5
+ height: number;
6
+ }
7
+ /** How a device-shell change animates: clear it, shutter out to desktop, enter in, or stay flat. */
8
+ interface DeviceStageOptions {
9
+ clear?: boolean;
10
+ shutterOut?: boolean;
11
+ enterIn?: boolean;
12
+ desktopFlat?: boolean;
13
+ }
2
14
  /**
3
15
  * Video recording locks Playwright viewport to recordVideo.size. Shrinking
4
16
  * setViewportSize to mobile/tablet letterboxes the .webm top-left. Instead keep
5
17
  * the stage size and center a device-sized #wg-device-shell inside the frame.
6
18
  */
7
- export declare function applyVideoDeviceStage(page: WgPage, target: any, stage: any, opts: any): Promise<void>;
19
+ export declare function applyVideoDeviceStage(page: WgPage, target: Size, stage: Size, opts?: DeviceStageOptions): Promise<void>;
8
20
  /**
9
21
  * Apply authored device fixture to the live page (0.13+).
10
22
  * Seamless viewport lerp + centered window + toast on set/clear.
11
23
  * With --video: keep recordVideo stage size and center a device shell in-frame.
12
24
  */
13
- export declare function applyDeviceToPage(page: WgPage, device: any, sync: any): Promise<void>;
25
+ export declare function applyDeviceToPage(page: WgPage, device: DeviceState | null | undefined, sync?: string): Promise<void>;
26
+ export {};
@@ -1 +1,2 @@
1
- export declare function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi, bannerUi, tag: bannerTag }: any): void;
1
+ import type { OverlayInstallArgs } from "../../types.js";
2
+ export declare function installBanner({ title, favicon, bannerPos, bannerUi, tag: bannerTag }: OverlayInstallArgs): void;
@@ -1,4 +1,4 @@
1
- export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi, bannerUi, tag: bannerTag }) {
1
+ export function installBanner({ title, favicon, bannerPos, bannerUi, tag: bannerTag }) {
2
2
  const POSITIONS = ["left", "center", "right"];
3
3
  const applyPos = (el, pos) => {
4
4
  el.dataset.pos = pos;
@@ -22,7 +22,7 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
22
22
  catch {
23
23
  /* ignore */
24
24
  }
25
- const startPos = saved && POSITIONS.includes(saved) ? saved : bannerPos;
25
+ const startPos = saved && POSITIONS.includes(saved) ? saved : bannerPos || "left";
26
26
  applyPos(banner, startPos);
27
27
  banner.title = "Click to move: top left / center / right";
28
28
  banner.addEventListener("click", (e) => {
@@ -155,6 +155,6 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
155
155
  iconLink.rel = "icon";
156
156
  document.head.appendChild(iconLink);
157
157
  }
158
- if (iconLink.href !== favicon)
158
+ if (favicon && iconLink.href !== favicon)
159
159
  iconLink.href = favicon;
160
160
  }
@@ -1,2 +1,2 @@
1
- export declare function showCaption(text: any): void;
1
+ export declare function showCaption(text: string): void;
2
2
  export declare function hideCaption(): void;
@@ -1 +1,2 @@
1
- export declare function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }: any): void;
1
+ import type { OverlayInstallArgs } from "../../types.js";
2
+ export declare function installCore({ envAutoplay, todoDockUi }: OverlayInstallArgs): void;
@@ -1,4 +1,4 @@
1
- export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }) {
1
+ export function installCore({ envAutoplay, todoDockUi }) {
2
2
  window.__wgTodoDockUi = todoDockUi || {
3
3
  compact: true,
4
4
  cap: 5,
@@ -275,12 +275,6 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
275
275
  pulse.classList.add("wg-pulse");
276
276
  };
277
277
  window.__wgHideRing = (opts) => {
278
- // While a narrate() call owns the ring (mid multi-step action),
279
- // the auto-highlight click/fill patches' own end-of-step hide is
280
- // a no-op - narrate() itself clears it once the WHOLE wrapped
281
- // action finishes, not just its first sub-step.
282
- if (window.__wgNarrateOwnsRing)
283
- return;
284
278
  if (window.__wgStopRingFollow)
285
279
  window.__wgStopRingFollow();
286
280
  const ring = __wgById("wg-ring");
@@ -1 +1 @@
1
- export declare function installDevice({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }: any): void;
1
+ export declare function installDevice(): void;
@@ -1,5 +1,5 @@
1
1
  // In-page (runs inside the browser via page.evaluate, must stay self-contained): the device toast and chip.
2
- export function installDevice({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }) {
2
+ export function installDevice() {
3
3
  // Device toast + chip (0.13.2+) - announce on set/clear; quiet chip on keep.
4
4
  // Payload: { sync, device?, remain?, announce? }
5
5
  window.__wgSyncDevice = (payload) => {
@@ -114,7 +114,7 @@ export function installDevice({ title, favicon, bannerPos, todoPos, envAutoplay,
114
114
  (device && device.preset === "desktop" && !device.touchMode);
115
115
  if (isDesktopClear) {
116
116
  setCursor(false);
117
- const announce = payload.announce !== false && sync !== "keep";
117
+ const announce = payload?.announce !== false && sync !== "keep";
118
118
  if (announce) {
119
119
  const vp = device && device.viewport ? device.viewport : { width: 1280, height: 720 };
120
120
  showToast("desktop", false, "Back to desktop", vp.width + "×" + vp.height + " · mouse", "landscape");
@@ -144,8 +144,8 @@ export function installDevice({ title, favicon, bannerPos, todoPos, envAutoplay,
144
144
  return;
145
145
  const preset = device.preset || "desktop";
146
146
  const touch = !!device.touchMode;
147
- const remain = payload.remain !== false && sync !== "clear";
148
- const vp = device.viewport || {};
147
+ const remain = payload?.remain !== false;
148
+ const vp = device.viewport || { width: 0, height: 0 };
149
149
  const orient = device.orientation === "landscape" || device.orientation === "portrait"
150
150
  ? device.orientation
151
151
  : vp.height > vp.width
@@ -163,8 +163,8 @@ export function installDevice({ title, favicon, bannerPos, todoPos, envAutoplay,
163
163
  document.documentElement.dataset.wgTouch = touch ? "1" : "0";
164
164
  if (window.__wgEnsureZoomBadge)
165
165
  window.__wgEnsureZoomBadge();
166
- const announce = payload.announce === true ||
167
- (payload.announce !== false && (sync === "set" || sync === "clear") && changed);
166
+ const announce = payload?.announce === true ||
167
+ (payload?.announce !== false && sync === "set" && changed);
168
168
  const size = (vp.width || "?") +
169
169
  "×" +
170
170
  (vp.height || "?") +
@@ -1,9 +1,10 @@
1
- export declare function addNetworkEntry(entry: any): void;
1
+ import type { NetworkEntry } from "../../types.js";
2
+ export declare function addNetworkEntry(entry: NetworkEntry): void;
2
3
  /**
3
4
  * Shows or hides the network-tab panel - capture keeps happening either way (addNetworkEntry
4
5
  * always builds the DOM row; this only toggles whether the panel itself is visible). Safe to call
5
6
  * before any entry exists yet - it just remembers the flag for addNetworkEntry to check later.
6
7
  */
7
- export declare function setNetworkTabVisible(visible: any): void;
8
+ export declare function setNetworkTabVisible(visible: boolean): void;
8
9
  /** Clears every captured entry and removes the panel - a fresh navigation/session starting over. */
9
10
  export declare function clearNetworkLog(): void;
@@ -1,14 +1,3 @@
1
- // In-page installer (page.evaluate target) - must stay self-contained, no module-scope closure
2
- // (page.evaluate serializes ONLY the passed function's own source, not sibling top-level
3
- // functions in this file - every helper below is nested inside addNetworkEntry itself for exactly
4
- // that reason; a row's click handler still works after addNetworkEntry returns because it's a
5
- // closure over ITS OWN invocation's nested helpers, not a reference to module scope).
6
- //
7
- // A real network-tab overlay (`#wg-network-log`): the DevTools Network panel itself can't be
8
- // embedded (it lives in browser chrome, not reachable from automation), but every entry's real
9
- // data is - this renders that, on-page: method, url, status, and (click a row) request/response
10
- // headers + bodies + a "copy as cURL" command, a Postman-style inspector for both real page
11
- // traffic (installNetworkCapture, network-capture.js) and defineApiBlock's own page.request calls.
12
1
  export function addNetworkEntry(entry) {
13
2
  // No-op outside a demo/pilot/auto run - ensureShadowRoot() (and its __wgById/__wgAdd globals)
14
3
  // is never installed for a plain `waygraph run`/Playwright test, and this must not throw there.
@@ -113,7 +102,7 @@ export function addNetworkEntry(entry) {
113
102
  row.dataset.ok = entry.ok ? "1" : "0";
114
103
  let path = entry.url;
115
104
  try {
116
- const u = new URL(entry.url);
105
+ const u = new URL(String(entry.url));
117
106
  path = u.pathname + u.search;
118
107
  }
119
108
  catch {
@@ -1 +1 @@
1
- export declare function installPanelChrome({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }: any): void;
1
+ export declare function installPanelChrome(): void;
@@ -1,5 +1,5 @@
1
1
  // In-page (runs inside the browser via page.evaluate, must stay self-contained): the step panel's Hide/Show chrome and mini Next.
2
- export function installPanelChrome({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }) {
2
+ export function installPanelChrome() {
3
3
  // Hide/Show for #wg-panel - call after every panel content refresh.
4
4
  // Collapsed = "N / M · block" + Next (when not auto). Never pass
5
5
  // forceCollapsed:false - omit so Hide/localStorage wins.
@@ -1 +1 @@
1
- export declare function installStamp({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }: any): void;
1
+ export declare function installStamp(): void;
@@ -1,5 +1,5 @@
1
1
  // In-page (runs inside the browser via page.evaluate, must stay self-contained): readiness stamps agents read to know a panel painted.
2
- export function installStamp({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }) {
2
+ export function installStamp() {
3
3
  // Blind-agent overlay beacons: every modal root gets data-wg-ui /
4
4
  // data-wg-modal / data-wg-ready so tests can fail on a blank panel.
5
5
  window.__wgStampModal = (el, kind, meta) => {
@@ -1 +1 @@
1
- export declare function installSwipeZoom({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }: any): void;
1
+ export declare function installSwipeZoom(): void;
@@ -1,5 +1,5 @@
1
1
  // In-page (runs inside the browser via page.evaluate, must stay self-contained): swipe trails and ring zoom.
2
- export function installSwipeZoom({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }) {
2
+ export function installSwipeZoom() {
3
3
  /**
4
4
  * Finger swipe trail for touch theater (orientation rotate / device change).
5
5
  * opts: { dir: 'left'|'right'|'up'|'down', label?, ms? }
@@ -1 +1,2 @@
1
- export declare function installTodos({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }: any): void;
1
+ import type { OverlayInstallArgs } from "../../types.js";
2
+ export declare function installTodos({ todoPos }: OverlayInstallArgs): void;
@@ -1,5 +1,4 @@
1
- // In-page (runs inside the browser via page.evaluate, must stay self-contained): the todo dock(s).
2
- export function installTodos({ title, favicon, bannerPos, todoPos, envAutoplay, todoDockUi }) {
1
+ export function installTodos({ todoPos }) {
3
2
  // Floating todo dock - lives outside #wg-panel so --mini / Hide never
4
3
  // hide the checklist. Click cycles left <-> right with CSS transform.
5
4
  // Authors set side via ctx.todos(id, items, { pos }); env / --todo-* fallback.
@@ -1,4 +1,4 @@
1
- import type { WgPage } from "../types.js";
1
+ import type { NetworkEntry, WgPage } from "../types.js";
2
2
  /**
3
3
  * Records one entry AND paints it live - the single place that touches page.__wgNetworkHistory,
4
4
  * so every caller (this file's own listeners, defineApiBlock) stays in sync automatically. History
@@ -7,7 +7,7 @@ import type { WgPage } from "../types.js";
7
7
  * this, the "network tab" reset to empty on every step that navigated - not what a persistent
8
8
  * Network tab is supposed to do.
9
9
  */
10
- export declare function recordNetworkEntry(page: WgPage, entry: any): Promise<void | undefined>;
10
+ export declare function recordNetworkEntry(page: WgPage, entry: NetworkEntry): Promise<void | undefined>;
11
11
  /**
12
12
  * Replays whatever history survived the last navigation back into a freshly (re)installed panel -
13
13
  * call this after ensureShadowRoot, every step, same as the rest of the overlay's own per-step
@@ -119,7 +119,7 @@ export function installNetworkCapture(page) {
119
119
  status: 0,
120
120
  ok: false,
121
121
  reqBody: request.postData() || undefined,
122
- resBody: request.failure() ? request.failure().errorText : undefined,
122
+ resBody: request.failure()?.errorText,
123
123
  });
124
124
  });
125
125
  }
@@ -1,7 +1,7 @@
1
1
  // CSS for the runner-only chrome (step panel, chips) and for the host page (device stage), next to the shared bundle in ui/css.
2
2
  import { SURFACE } from "./ui/tokens.js";
3
3
  // ---------------------------------------------------------------------------
4
- // WAYGRAPH_STEP=1 - human-verification overlay: one Block at a time, a
4
+ // The demo stepper (waygraph demo) - human-verification overlay: one Block at a time, a
5
5
  // browser-injected panel showing/editing that Block's MemKeys, a "Run this
6
6
  // step" gate, then a highlight ring over whatever its own verify Traits just
7
7
  // confirmed, then a "Next" gate before moving on. Ring CSS borrowed from
@@ -114,60 +114,6 @@ export const RUNNER_EXTRA_CSS =
114
114
  "#wg-zoom-badge .wg-zoom-ico svg{width:14px;height:14px;display:block;}" +
115
115
  "#wg-zoom-badge .wg-zoom-val{color:#c9a6ff;font-variant-numeric:tabular-nums;font-weight:800;min-width:3.2em;}" +
116
116
  "#wg-zoom-badge[data-zoomed=\"1\"]{border-color:#7C3AED;}" +
117
- // Network-tab overlay (real page traffic via network-capture.js + defineApiBlock's own
118
- // page.request calls) - bottom-left, the one corner free of the zoom HUD (bottom-right) and the
119
- // typing chip (bottom-center). Persistent (does not auto-fade) once any entry exists - this is a
120
- // real Postman/DevTools-style inspector meant to be reviewed, not a flash-and-gone toast.
121
- "#wg-network-log{position:fixed;z-index:2147483646;bottom:14px;left:14px;min-width:260px;" +
122
- "max-width:min(92vw,420px);max-height:min(60vh,420px);display:flex;flex-direction:column;" +
123
- "border-radius:10px;background:" + SURFACE + ";color:#f0e8ff;border:1px solid rgba(124,58,237,.45);" +
124
- "box-shadow:0 8px 22px rgba(0,0,0,.4);font:12px/1.4 ui-monospace,\"SF Mono\",Consolas,monospace;" +
125
- "opacity:0;transform:translateY(8px);transition:opacity .25s ease,transform .25s ease;overflow:hidden;}" +
126
- "#wg-network-log.wg-in{opacity:1;transform:translateY(0);}" +
127
- "#wg-network-log.wg-net-collapsed .wg-net-list{display:none;}" +
128
- "#wg-network-log .wg-net-header{display:flex;align-items:center;gap:6px;padding:8px 10px;" +
129
- "border-bottom:1px solid rgba(124,58,237,.25);cursor:default;flex:0 0 auto;}" +
130
- "#wg-network-log .wg-net-title{font:700 10px/1.2 system-ui,sans-serif;color:#c9a6ff;" +
131
- "letter-spacing:.06em;text-transform:uppercase;flex:1 1 auto;}" +
132
- "#wg-network-log .wg-net-count{font:700 10px/1.2 system-ui,sans-serif;color:#9CA3AF;" +
133
- "background:rgba(124,58,237,.22);border-radius:999px;padding:1px 7px;}" +
134
- "#wg-network-log .wg-net-collapse{flex:0 0 auto;width:18px;height:18px;border-radius:5px;border:none;" +
135
- "background:rgba(124,58,237,.28);color:#e8dcff;font:700 13px/1 system-ui,sans-serif;cursor:pointer;" +
136
- "pointer-events:auto;}" +
137
- "#wg-network-log .wg-net-collapse:hover{background:rgba(124,58,237,.42);}" +
138
- "#wg-network-log .wg-net-list{list-style:none;margin:0;padding:6px 8px;display:flex;" +
139
- "flex-direction:column;gap:2px;overflow-y:auto;pointer-events:auto;}" +
140
- "#wg-network-log .wg-net-row{display:flex;align-items:baseline;gap:7px;opacity:0;padding:3px 4px;" +
141
- "border-radius:5px;cursor:pointer;transform:translateX(-4px);transition:opacity .2s ease,transform .2s ease;}" +
142
- "#wg-network-log .wg-net-row:hover,#wg-network-log .wg-net-row.wg-net-open{background:rgba(124,58,237,.18);}" +
143
- "#wg-network-log .wg-net-row.wg-in{opacity:1;transform:translateX(0);}" +
144
- "#wg-network-log .wg-net-method{flex:0 0 auto;font-weight:800;font-size:10px;min-width:38px;}" +
145
- "#wg-network-log .wg-net-method-get{color:#3B82F6;}" +
146
- "#wg-network-log .wg-net-method-post{color:#22C55E;}" +
147
- "#wg-network-log .wg-net-method-put{color:#F97316;}" +
148
- "#wg-network-log .wg-net-method-delete{color:#EF4444;}" +
149
- "#wg-network-log .wg-net-method-other{color:#9CA3AF;}" +
150
- "#wg-network-log .wg-net-path{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;" +
151
- "white-space:nowrap;color:#e0e0f0;}" +
152
- "#wg-network-log .wg-net-status{flex:0 0 auto;font-weight:700;color:#22C55E;}" +
153
- "#wg-network-log .wg-net-row[data-ok=\"0\"] .wg-net-status{color:#EF4444;}" +
154
- "#wg-network-log .wg-net-ms{flex:0 0 auto;color:#9CA3AF;font-size:10px;}" +
155
- "#wg-network-log .wg-net-detail{list-style:none;background:rgba(0,0,0,.28);border-radius:6px;" +
156
- "padding:8px;margin:2px 0 6px;}" +
157
- "#wg-network-log .wg-net-detail-section{margin-bottom:8px;}" +
158
- "#wg-network-log .wg-net-detail-section:last-child{margin-bottom:0;}" +
159
- "#wg-network-log .wg-net-detail-section h4{margin:0 0 4px;font:700 9px/1.2 system-ui,sans-serif;" +
160
- "color:#9CA3AF;letter-spacing:.06em;text-transform:uppercase;}" +
161
- "#wg-network-log .wg-net-headers{width:100%;border-collapse:collapse;font-size:11px;}" +
162
- "#wg-network-log .wg-net-headers td{padding:1px 6px 1px 0;vertical-align:top;word-break:break-all;}" +
163
- "#wg-network-log .wg-net-headers td:first-child{color:#c9a6ff;white-space:nowrap;}" +
164
- "#wg-network-log .wg-net-body{margin:0;font-size:11px;white-space:pre-wrap;word-break:break-all;" +
165
- "max-height:160px;overflow-y:auto;color:#e0e0f0;}" +
166
- "#wg-network-log .wg-net-curl{color:#7dd3fc;}" +
167
- "#wg-network-log .wg-net-empty{font-size:11px;color:#6b7280;font-style:italic;}" +
168
- "#wg-network-log .wg-net-copy{margin-top:5px;padding:3px 9px;border-radius:5px;border:1px solid rgba(124,58,237,.5);" +
169
- "background:rgba(124,58,237,.22);color:#e8dcff;font:700 10px system-ui,sans-serif;cursor:pointer;}" +
170
- "#wg-network-log .wg-net-copy:hover{background:rgba(124,58,237,.38);}" +
171
117
  // Typing chip (method fills: username / password / etc.)
172
118
  "#wg-typing-badge{position:fixed;z-index:2147483646;bottom:88px;left:50%;transform:translateX(-50%);" +
173
119
  "display:flex;align-items:center;gap:8px;padding:8px 14px;" +
@@ -1,22 +1,30 @@
1
- import type { WgPage } from "../types.js";
2
- export declare function createOverlayStage(page: WgPage, { todoDockRef, deviceRef }: any): {
1
+ import type { BannerUiState, StepperRefs, WgPage } from "../types.js";
2
+ import type { StubPhaseResult } from "../../engine/stub/stub.js";
3
+ import type { TodoDockState, TodoDockUiOpts } from "../../engine/stub/todos.js";
4
+ import type { DeviceState } from "../../engine/stub/viewport.js";
5
+ export declare function createOverlayStage(page: WgPage, { todoDockRef, deviceRef }: Pick<StepperRefs, never> & {
6
+ todoDockRef: StepperRefs["todoDock"];
7
+ deviceRef: StepperRefs["device"];
8
+ }): {
3
9
  state: {
4
- lastTodoDock: any;
5
- lastDevice: any;
6
- lastBannerUi: Record<string, any>;
10
+ lastTodoDock: TodoDockState | undefined;
11
+ lastDevice: DeviceState | undefined;
12
+ lastBannerUi: BannerUiState;
7
13
  };
8
- pushTodoDockUi: (patch: any) => Promise<void>;
9
- rememberTodoDock: (dock: any, sync: any, parallel: any) => void;
10
- syncAllTodoDocks: (opts: any) => Promise<void>;
11
- applyPhase: (phase: any, { reapplyDeviceOnKeep }?: {
14
+ pushTodoDockUi: (patch: TodoDockUiOpts | undefined) => Promise<void>;
15
+ rememberTodoDock: (dock: TodoDockState | undefined, sync: "set" | "clear" | "keep", parallel: boolean) => void;
16
+ syncAllTodoDocks: (opts?: {
17
+ parallel?: boolean;
18
+ }) => Promise<void>;
19
+ applyPhase: (phase: StubPhaseResult, { reapplyDeviceOnKeep }?: {
12
20
  reapplyDeviceOnKeep?: boolean | undefined;
13
21
  }) => Promise<{
14
22
  appliedTodo: {
15
- dock: import("../../index.js").TodoDockState | undefined;
23
+ dock: TodoDockState | undefined;
16
24
  sync: "set" | "clear" | "keep";
17
25
  };
18
26
  appliedDevice: {
19
- device: import("../../index.js").DeviceState | undefined;
27
+ device: DeviceState | undefined;
20
28
  sync: "set" | "clear" | "keep";
21
29
  };
22
30
  }>;
@@ -1,4 +1,4 @@
1
- import type { WgPage } from "../types.js";
1
+ import type { BannerUiState, WgPage } from "../types.js";
2
2
  /**
3
3
  * `ui` = authored banner UX from the stub phase: { pos, collision, hidden } (all optional).
4
4
  * `caption` = bottom subtitle-bar text (ctx.caption()/ctx.hideCaption()) - `undefined` leaves it
@@ -7,4 +7,4 @@ import type { WgPage } from "../types.js";
7
7
  * `undefined` leaves it alone (default state is hidden, set the very first time restoreNetworkHistory
8
8
  * builds a panel); capture itself is unconditional and unaffected by this either way.
9
9
  */
10
- export declare function installOverlay(page: WgPage, title?: any, ui?: any, caption?: any, networkTabVisible?: any): Promise<void>;
10
+ export declare function installOverlay(page: WgPage, title?: string, ui?: BannerUiState | null, caption?: string, networkTabVisible?: boolean): Promise<void>;
@@ -25,6 +25,9 @@ import { ignorePageGone } from "../../engine/page-gone.js";
25
25
  export async function installOverlay(page, title, ui, caption, networkTabVisible) {
26
26
  // ring/cursor/banner/dock come from the ONE shared bundle every surface installs (ui/css/*.css).
27
27
  await ensureShadowRoot(page);
28
+ // Runner-only chrome (step panel, zoom/typing/device chips) - separate key, no collision. First, so nothing below
29
+ // builds chrome ahead of its CSS (an element painted unstyled for a moment, then restyled).
30
+ await page.evaluate(([css, key]) => __wgCss(css, key), [RUNNER_EXTRA_CSS, "wg-runner-css"]).catch(ignorePageGone);
28
31
  // Idempotent (guarded on page.__wgNetworkCaptureInstalled) - safe to call every step even though
29
32
  // installOverlay itself runs every step; the page.on() listeners this installs are attached to
30
33
  // the Page object, not any one document, so they already survive navigations on their own.
@@ -46,8 +49,6 @@ export async function installOverlay(page, title, ui, caption, networkTabVisible
46
49
  if (networkTabVisible !== undefined) {
47
50
  await page.evaluate(setNetworkTabVisible, networkTabVisible).catch(ignorePageGone);
48
51
  }
49
- // Runner-only chrome (step panel, zoom/typing/device chips) - separate key, no collision.
50
- await page.evaluate(([css, key]) => __wgCss(css, key), [RUNNER_EXTRA_CSS, "wg-runner-css"]).catch(ignorePageGone);
51
52
  await page.addStyleTag({ content: HOST_CSS }).catch(ignorePageGone);
52
53
  // Default top-left; override with WAYGRAPH_TITLE_POS=left|center|right.
53
54
  // Click cycles left -> center -> right (persisted in localStorage so a
@@ -1,5 +1,9 @@
1
1
  import type { WgBox, WgPage } from "../types.js";
2
2
  import type { Locator } from "@playwright/test";
3
+ import type { ResolvedHighlight } from "../../engine/stub/ring.js";
4
+ import type { DemoPace } from "../../engine/stub/pace.js";
5
+ import type { TodoDockState, WaygraphTodoItem } from "../../engine/stub/todos.js";
6
+ import type { Pacing } from "../stepper/pacing.js";
3
7
  /**
4
8
  * Scroll a locator into view for demo theater.
5
9
  * Prefer CSS smooth scroll + scrollend wait. Do NOT call Playwright's
@@ -8,26 +12,42 @@ import type { Locator } from "@playwright/test";
8
12
  * noticeable under --fast when dwell is shorter.
9
13
  * Pass opts.instant=true only for skipTheater / blitz.
10
14
  */
11
- export declare function ensureLocatorInView(locator: Locator, opts: any): Promise<void>;
12
- export declare function ensureSelectorInView(page: WgPage, selector: any, opts?: any): Promise<void>;
13
- export declare function applyHighlightZoom(page: WgPage, selector: any, zoom: any, zoomOut: any): Promise<void>;
14
- export declare function cycleHighlightRings(page: WgPage, highlights: any, gatesFast: any, opts: any): Promise<void>;
15
- export declare function showRing(page: WgPage, box: WgBox, label: any, tone: any, style: any): Promise<void>;
16
- /** 0-based stub index for Method fill/click todo advance; -1 if none. */
17
- export declare function matchStubIndexForLocator(page: WgPage, locator: Locator, stubs: any): Promise<number>;
18
- export declare function captionForLocator(page: WgPage, locator: Locator, stubs: any, fallback: any): Promise<{
19
- label: any;
15
+ export declare function ensureLocatorInView(locator: Locator, opts?: {
16
+ instant?: boolean;
17
+ }): Promise<void>;
18
+ export declare function ensureSelectorInView(page: WgPage, selector: string, opts?: {
19
+ instant?: boolean;
20
+ }): Promise<void>;
21
+ export declare function applyHighlightZoom(page: WgPage, selector: string | undefined, zoom: number | undefined, zoomOut: boolean | undefined): Promise<void>;
22
+ /** How `cycleHighlightRings` plays a step's rings: hold times, pace, and the todo dock it moves along. */
23
+ export interface CycleRingsOptions {
24
+ /** Hold for each ring when it sets none (the failure path holds longer). */
25
+ defaultHoldMs?: number;
26
+ pace?: DemoPace | undefined;
27
+ todoDock?: TodoDockState | undefined;
28
+ todos?: readonly WaygraphTodoItem[] | undefined;
29
+ todoSync?: "set" | "clear" | "keep" | undefined;
30
+ todoDockRef?: {
31
+ current: TodoDockState | undefined;
32
+ } | undefined;
33
+ /** False when the stub already set the dock's progress. */
34
+ advanceTodos?: boolean;
35
+ stepLabel?: string;
36
+ }
37
+ export declare function cycleHighlightRings(page: WgPage, highlights: readonly ResolvedHighlight[] | undefined, gatesFast: boolean, opts?: CycleRingsOptions): Promise<void>;
38
+ export declare function showRing(page: WgPage, box: WgBox, label: string, tone: string | undefined, style?: {
39
+ size?: string | undefined;
40
+ weight?: string | undefined;
41
+ selector?: string | undefined;
42
+ focus?: boolean;
43
+ }): Promise<void>;
44
+ /** The stubBefore ring a locator is, by overlapping bounding boxes: its index, or -1. For a Method's todo advance. */
45
+ export declare function matchStubIndexForLocator(page: WgPage, locator: Locator, stubs: readonly ResolvedHighlight[] | undefined): Promise<number>;
46
+ export declare function captionForLocator(page: WgPage, locator: Locator, stubs: readonly ResolvedHighlight[] | undefined, fallback: string): Promise<{
47
+ label: string;
20
48
  tone: string;
21
49
  size: string;
22
50
  weight: string;
23
51
  }>;
24
- export declare function dwellMatchedStub(page: WgPage, locator: Locator, stubs: any, pacing: any): Promise<void>;
52
+ export declare function dwellMatchedStub(page: WgPage, locator: Locator, stubs: readonly ResolvedHighlight[] | undefined, pacing: Pick<Pacing, "gatesFast" | "demoPace"> | undefined): Promise<void>;
25
53
  export declare function hideRing(page: WgPage): Promise<void>;
26
- /**
27
- * True if the engine's own narrate() (waygraph's public export, for a Block
28
- * author explicitly captioning one action) JUST positioned the ring for
29
- * THIS action, moments ago - the automatic per-fill/per-click narration
30
- * below should not immediately overwrite an author's own explicit caption
31
- * with its generic guess.
32
- */
33
- export declare function wasJustNarrated(page: WgPage): Promise<boolean>;