waygraph 0.16.1 → 0.16.4
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 +12 -0
- package/dist/analysis/practices-check.d.ts +1 -1
- package/dist/analysis/practices-check.js +36 -0
- package/dist/beta.d.ts +6 -0
- package/dist/beta.js +5 -0
- package/dist/cli/commands/codemod-flows.js +2 -2
- package/dist/cli/commands/codemod-stubs.js +132 -2
- package/dist/cli/commands/pilot.js +3 -16
- package/dist/cli/commands/session-ops.js +26 -1
- package/dist/cli/flags.d.ts +1 -1
- package/dist/cli/flags.js +1 -1
- package/dist/cli/run-chain.js +2 -2
- package/dist/cli/usage.js +6 -0
- package/dist/cli/util.js +1 -1
- package/dist/demo/narration/demo-pace.d.ts +1 -1
- package/dist/demo/narration/demo-pace.js +1 -1
- package/dist/demo/narration/merge.d.ts +1 -1
- package/dist/demo/narration/merge.js +1 -1
- package/dist/demo/narration/narration.d.ts +2 -6
- package/dist/demo/narration/narration.js +5 -17
- package/dist/demo/narration/stub-ctx.js +126 -124
- package/dist/demo/overlay/cursor.js +1 -1
- package/dist/demo/overlay/inpage/banner.js +5 -0
- package/dist/demo/overlay/inpage/core.js +1 -6
- package/dist/demo/overlay/inpage/network.js +1 -1
- package/dist/demo/overlay/inpage/todos.js +0 -15
- package/dist/demo/overlay/network-capture.js +2 -2
- package/dist/demo/overlay/overlay-css.js +19 -76
- package/dist/demo/overlay/overlay-stage.js +1 -1
- package/dist/demo/overlay/overlay.js +3 -2
- package/dist/demo/overlay/phase-fixtures.js +5 -5
- package/dist/demo/overlay/pilot/shell.js +7 -5
- package/dist/demo/overlay/rings.d.ts +0 -8
- package/dist/demo/overlay/rings.js +0 -15
- package/dist/demo/overlay/ui/components/ring.js +2 -2
- package/dist/demo/overlay/ui/overlay.css +136 -33
- package/dist/demo/overlay/ui/shadow.js +69 -2
- package/dist/demo/stepper/after.js +4 -17
- package/dist/demo/stepper/before.js +3 -1
- package/dist/demo/stepper/demo-log.js +8 -8
- package/dist/demo/stepper/interaction-patch.js +3 -15
- package/dist/demo/stepper/panel-after.js +1 -1
- package/dist/demo/stepper/slides.d.ts +3 -0
- package/dist/demo/stepper/slides.js +18 -2
- package/dist/demo/stepper/stepper.js +1 -1
- package/dist/demo/stepper/teardown.js +0 -1
- package/dist/demo/verbose-log.js +1 -1
- package/dist/engine/block/block.d.ts +1 -12
- package/dist/engine/block/kind.d.ts +3 -0
- package/dist/engine/block/kind.js +11 -0
- package/dist/engine/block/kinds/method.d.ts +0 -2
- package/dist/engine/block/kinds/method.js +0 -1
- package/dist/engine/block/kinds/nav.js +1 -1
- package/dist/engine/errors.d.ts +12 -0
- package/dist/engine/errors.js +12 -0
- package/dist/engine/read/read-block.d.ts +61 -0
- package/dist/engine/read/read-block.js +94 -0
- package/dist/engine/read/read-key.d.ts +32 -0
- package/dist/engine/read/read-key.js +34 -0
- package/dist/engine/read/read-page.d.ts +19 -0
- package/dist/engine/read/read-page.js +50 -0
- package/dist/engine/read/readers.d.ts +82 -0
- package/dist/engine/read/readers.js +43 -0
- package/dist/engine/read/run-read.d.ts +17 -0
- package/dist/engine/read/run-read.js +156 -0
- package/dist/engine/run/connect.js +3 -2
- package/dist/engine/run/events.d.ts +28 -10
- package/dist/engine/run/events.js +52 -38
- package/dist/engine/run/run.d.ts +1 -19
- package/dist/engine/run/run.js +21 -97
- package/dist/engine/stub/ring.d.ts +2 -4
- package/dist/engine/stub/ring.js +1 -0
- package/dist/engine/stub/stub.d.ts +38 -25
- package/dist/index.d.ts +9 -7
- package/dist/index.js +11 -6
- package/dist/live/auto/auto.js +2 -3
- package/dist/live/auto/menu.js +3 -2
- package/dist/live/auto-session/auto-session.d.ts +9 -2
- package/dist/live/auto-session/auto-session.js +23 -20
- package/dist/live/auto-session/feed.d.ts +16 -0
- package/dist/live/auto-session/feed.js +71 -0
- package/dist/live/auto-session/helpers.d.ts +7 -0
- package/dist/live/auto-session/helpers.js +9 -0
- package/dist/live/auto-session/ipc.d.ts +15 -47
- package/dist/live/auto-session/ipc.js +34 -4
- package/dist/live/auto-session/protocol.d.ts +127 -0
- package/dist/live/auto-session/protocol.js +6 -0
- package/dist/live/auto-session/read.d.ts +25 -0
- package/dist/live/auto-session/read.js +50 -0
- package/dist/live/traverse/worker.d.ts +1 -0
- package/dist/live/traverse/worker.js +6 -1
- package/dist/manifest/manifest.d.ts +22 -2
- package/dist/manifest/manifest.js +27 -1
- package/dist/manifest/project.d.ts +10 -1
- package/dist/manifest/project.js +9 -12
- package/dist/manifest/read-blocks.d.ts +2 -0
- package/dist/manifest/read-blocks.js +23 -0
- package/dist/manifest/scan.d.ts +3 -2
- package/dist/manifest/scan.js +8 -4
- package/dist/runner/plan/find.js +2 -2
- package/dist/runner/plan/plan.js +1 -1
- package/dist/runner/plan/seed-mem.js +5 -5
- package/dist/runner/plan/spec.js +1 -1
- package/dist/runner/runner.d.ts +0 -1
- package/dist/runner/runner.js +6 -6
- package/dist/runtime/full-launch.d.ts +2 -1
- package/dist/runtime/full-launch.js +29 -27
- package/dist/runtime/run-log.d.ts +2 -0
- package/dist/runtime/run-log.js +13 -6
- package/examples/saucedemo/README.md +2 -2
- package/examples/saucedemo/src/blocks/SITE-MAP.md +3 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/cart.read.block.ts +26 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +2 -34
- package/examples/saucedemo/src/blocks/saucedemo-web/header.read.block.ts +25 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.read.block.ts +28 -0
- package/examples/saucedemo/src/flows/api-demo.flow.ts +1 -1
- package/examples/saucedemo/src/flows/cart-bulk.flow.ts +1 -1
- package/examples/saucedemo/src/flows/cart-continue.flow.ts +1 -1
- package/examples/saucedemo/src/flows/catalog-logout.flow.ts +1 -1
- package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +3 -2
- package/examples/saucedemo/src/flows/checkout.flow.ts +13 -12
- package/examples/saucedemo/src/flows/login.flow.ts +1 -1
- package/examples/saucedemo/src/flows/shop.flow.ts +3 -2
- package/examples/saucedemo/src/flows/stub-on-error.flow.ts +1 -1
- package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +1 -1
- package/examples/saucedemo/src/states/checkout.reads.ts +9 -0
- package/examples/saucedemo/src/stubs/device-showcase.ts +70 -76
- package/examples/saucedemo/src/stubs/finish-order.ts +38 -0
- package/examples/saucedemo/src/stubs/login.ts +5 -5
- package/package.json +5 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +2 -34
- package/templates/quickstart/src/flows/api-demo.flow.ts +1 -1
- package/templates/quickstart/src/flows/cart-bulk.flow.ts +1 -1
- package/templates/quickstart/src/flows/cart-continue.flow.ts +1 -1
- package/templates/quickstart/src/flows/catalog-logout.flow.ts +1 -1
- package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +3 -2
- package/templates/quickstart/src/flows/checkout.flow.ts +13 -12
- package/templates/quickstart/src/flows/login.flow.ts +1 -1
- package/templates/quickstart/src/flows/shop.flow.ts +3 -2
- package/templates/quickstart/src/flows/stub-on-error.flow.ts +1 -1
- package/templates/quickstart/src/flows/viewer-blocked.flow.ts +1 -1
- package/templates/quickstart/src/stubs/device-showcase.ts +70 -76
- package/templates/quickstart/src/stubs/finish-order.ts +38 -0
- package/templates/quickstart/src/stubs/login.ts +5 -5
- package/templates/scaffold/src/flows/(external)/hoppscotch/auth.flow.ts +1 -1
- package/templates/scaffold/src/flows/(external)/hoppscotch/get.flow.ts +1 -1
- package/templates/scaffold/src/flows/(external)/hoppscotch/post.flow.ts +1 -1
- package/templates/scaffold/src/flows/(user-stories)/email-verification.flow.ts +4 -4
- package/templates/scaffold/src/flows/README.md +1 -1
- package/templates/scaffold/src/flows/home/cart.flow.ts +7 -7
- package/templates/scaffold/src/flows/home/hello.flow.ts +10 -7
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +1 -9
- package/templates/skills/waygraph-convention.skill.md +10 -2
- package/templates/skills/waygraph-pilot.skill.md +7 -0
|
@@ -2,7 +2,7 @@ import type { Checkpoint } from "../checkpoint/checkpoint.js";
|
|
|
2
2
|
import type { MemPage } from "../mem/mem.js";
|
|
3
3
|
import type { TodoDockState, TodoDockUiOpts, TodoListStyle, WaygraphTodoGroupInput, WaygraphTodoInput, WaygraphTodoItem, WaygraphTodosOpts } from "./todos.js";
|
|
4
4
|
import type { DeviceOrientation, DevicePreset, DeviceState, DeviceViewport } from "./viewport.js";
|
|
5
|
-
import type { HighlightStubPhase, ResolvedHighlight, WaygraphHighlightStub } from "./ring.js";
|
|
5
|
+
import type { HighlightStubPhase, ResolvedHighlight, WaygraphHighlightStub, WaygraphSlide } from "./ring.js";
|
|
6
6
|
/** Where the top banner sits. */
|
|
7
7
|
export type BannerPos = "left" | "center" | "right";
|
|
8
8
|
/** Banner UX, mirrors {@link TodoDockUiOpts}: pass `false` fields to opt out for this phase. */
|
|
@@ -22,7 +22,7 @@ export type StubPhaseFixtures = {
|
|
|
22
22
|
todos?: readonly WaygraphTodoInput[];
|
|
23
23
|
/** Which todo is current (0-based). Rows before = done, after = pending. */
|
|
24
24
|
todoIndex?: number;
|
|
25
|
-
/** Heading above a single {@link
|
|
25
|
+
/** Heading above a single {@link StubUi.todos} list. */
|
|
26
26
|
todoTitle?: string;
|
|
27
27
|
/**
|
|
28
28
|
* Stable dock id (`data-wg-todo-id`) for external redirect asserts
|
|
@@ -85,17 +85,15 @@ export type StubPhaseFixtures = {
|
|
|
85
85
|
*
|
|
86
86
|
* @example
|
|
87
87
|
* LoginBlock.stubBefore((ctx) => {
|
|
88
|
-
* ctx.todos("sign-in", ["Enter email", "Enter password", "Click Sign in"], { index: 0 });
|
|
89
|
-
* ctx.zoom(1.35);
|
|
90
|
-
* ctx.
|
|
91
|
-
*
|
|
92
|
-
* submit: { selector: "#login-button", label: "Sign in" },
|
|
93
|
-
* });
|
|
88
|
+
* ctx.ui.todos("sign-in", ["Enter email", "Enter password", "Click Sign in"], { index: 0 });
|
|
89
|
+
* ctx.ui.zoom(1.35);
|
|
90
|
+
* ctx.ui.ring("email", { selector: "#email", label: "Email" });
|
|
91
|
+
* ctx.ui.ring("submit", { selector: "#login-button", label: "Sign in" });
|
|
94
92
|
* })
|
|
95
93
|
* // Sequential plan: bump todoIndex in a later phase / a later Block's stubBefore
|
|
96
94
|
* .stubAfter((ctx) => {
|
|
97
|
-
* ctx.todoIndex(2);
|
|
98
|
-
* ctx.ring("inventory", { selector: ".inventory_list", label: "Landed" });
|
|
95
|
+
* ctx.ui.todoIndex(2);
|
|
96
|
+
* ctx.ui.ring("inventory", { selector: ".inventory_list", label: "Landed" });
|
|
99
97
|
* });
|
|
100
98
|
*/
|
|
101
99
|
export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
|
|
@@ -109,19 +107,22 @@ export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
|
|
|
109
107
|
readonly out: Out | undefined;
|
|
110
108
|
/** Present on stubOnError when the step threw. */
|
|
111
109
|
readonly error: unknown | undefined;
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
/** Everything a stub paints in the demo: rings, todos, title, caption, device, zoom, network tab, slides. */
|
|
111
|
+
readonly ui: StubUi;
|
|
112
|
+
};
|
|
113
|
+
/** The demo UI a stub paints through: `ctx.ui.ring(...)`, `ctx.ui.todos(...)`, ... */
|
|
114
|
+
export type StubUi = {
|
|
115
|
+
/** Paints one named ring this phase; the same id again replaces it. */
|
|
115
116
|
ring(id: string, stub: WaygraphHighlightStub): void;
|
|
116
117
|
/**
|
|
117
|
-
* Floating checklist: `ctx.todos("login", ["Enter email", "Enter password"], { title: "Sign in", index: 0 })`.
|
|
118
|
+
* Floating checklist: `ctx.ui.todos("login", ["Enter email", "Enter password"], { title: "Sign in", index: 0 })`.
|
|
118
119
|
* The id is the dock's `data-wg-todo-id` (stable through redirects). One dock at a time (setting todos replaces it);
|
|
119
120
|
* pass `{ parallel: true }` to keep docks with other ids. An empty list hides the dock.
|
|
120
121
|
*/
|
|
121
122
|
todos(id: string, items: readonly WaygraphTodoInput[], opts?: WaygraphTodosOpts): void;
|
|
122
123
|
/** Moves the current dock's current item (sequential plans: a later step bumps it). */
|
|
123
124
|
todoIndex(n: number): void;
|
|
124
|
-
/** Several titled lists in one dock (e.g. Functional Requirements / Scenarios / ACs), with the same id and options as {@link
|
|
125
|
+
/** Several titled lists in one dock (e.g. Functional Requirements / Scenarios / ACs), with the same id and options as {@link StubUi.todos}. */
|
|
125
126
|
todoGroups(id: string, groups: readonly WaygraphTodoGroupInput[], opts?: Omit<WaygraphTodosOpts, "index">): void;
|
|
126
127
|
/**
|
|
127
128
|
* Hide the floating todo dock. Omit todos on a later block = **keep** the
|
|
@@ -131,7 +132,7 @@ export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
|
|
|
131
132
|
/**
|
|
132
133
|
* Viewport / device fixture (0.13+). `mobile` | `tablet` | `desktop`.
|
|
133
134
|
* Omit on later blocks = **keep** (same persist as todos). Use
|
|
134
|
-
* {@link
|
|
135
|
+
* {@link StubUi.hideDevice} or `device("desktop")` to return to desktop.
|
|
135
136
|
*/
|
|
136
137
|
device(preset: DevicePreset | DeviceState): void;
|
|
137
138
|
/** Explicit CSS-pixel viewport (implies mobile-ish unless desktop-sized). */
|
|
@@ -162,24 +163,33 @@ export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
|
|
|
162
163
|
titlePos(side: BannerPos): void;
|
|
163
164
|
/**
|
|
164
165
|
* Banner UX: `{ collision: false }` keeps it put even over a ring; `{ hidden: true }` hides it.
|
|
165
|
-
* @example ctx.bannerUi({ collision: false });
|
|
166
|
+
* @example ctx.ui.bannerUi({ collision: false });
|
|
166
167
|
*/
|
|
167
168
|
bannerUi(opts: BannerUiOpts): void;
|
|
168
169
|
/**
|
|
169
170
|
* Bottom narration caption - a white rounded card (black text, shadow), bottom-centered above
|
|
170
|
-
* the step pill; distinct from {@link
|
|
171
|
-
* on change. Pass `""` (or call {@link
|
|
172
|
-
* @example ctx.caption("Click Add to cart to continue");
|
|
171
|
+
* the step pill; distinct from {@link StubUi.title}, which is the top banner card. Fades in/out
|
|
172
|
+
* on change. Pass `""` (or call {@link StubUi.hideCaption}) to clear.
|
|
173
|
+
* @example ctx.ui.caption("Click Add to cart to continue");
|
|
173
174
|
*/
|
|
174
175
|
caption(text: string): void;
|
|
175
176
|
/** Clears the caption (fades it out). */
|
|
176
177
|
hideCaption(): void;
|
|
178
|
+
/**
|
|
179
|
+
* Multi-step "yap" captions with Next between each, for explaining a longer process. In `stubBefore` they play
|
|
180
|
+
* before the step runs, in `stubAfter` after it lands; a slide with a `selector` rings it while it is up.
|
|
181
|
+
* @example ctx.ui.slides([
|
|
182
|
+
* { caption: "Checkout is three screens", tag: "YAP" },
|
|
183
|
+
* { caption: "Overview confirms totals", selector: ".summary_info", duration: true },
|
|
184
|
+
* ]);
|
|
185
|
+
*/
|
|
186
|
+
slides(slides: readonly WaygraphSlide[]): void;
|
|
177
187
|
/** Shorthand for `bannerUi({ hidden: true })`. */
|
|
178
188
|
hideBanner(): void;
|
|
179
189
|
/**
|
|
180
190
|
* Shows the network-tab overlay (Postman-style inspector of real page traffic + defineApiBlock
|
|
181
191
|
* calls) - capture always runs in the background; this just reveals the panel. Hidden by default.
|
|
182
|
-
* @example ctx.showNetworkTab();
|
|
192
|
+
* @example ctx.ui.showNetworkTab();
|
|
183
193
|
*/
|
|
184
194
|
showNetworkTab(): void;
|
|
185
195
|
/** Hides the network-tab overlay (capture keeps running - only the panel disappears). */
|
|
@@ -188,7 +198,7 @@ export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
|
|
|
188
198
|
* Todo-dock UX: compact fold, collision flip, dim-behind-ring.
|
|
189
199
|
* Defaults are smart-on; pass false fields to opt out for this phase.
|
|
190
200
|
* @example
|
|
191
|
-
* ctx.todoDockUi({ compact: false }); // always show the full list
|
|
201
|
+
* ctx.ui.todoDockUi({ compact: false }); // always show the full list
|
|
192
202
|
*/
|
|
193
203
|
todoDockUi(opts: TodoDockUiOpts): void;
|
|
194
204
|
};
|
|
@@ -208,7 +218,7 @@ export type StubPhaseResult = {
|
|
|
208
218
|
* - `keep` - author omitted todos; demo must leave previous dock alone
|
|
209
219
|
*/
|
|
210
220
|
todoSync?: "set" | "clear" | "keep";
|
|
211
|
-
/** Todo-dock UX for this phase (when author called {@link
|
|
221
|
+
/** Todo-dock UX for this phase (when author called {@link StubUi.todoDockUi}). */
|
|
212
222
|
todoDockUi?: TodoDockUiOpts;
|
|
213
223
|
/** Resolved device after this phase (undefined when keep with no prior). */
|
|
214
224
|
device?: DeviceState;
|
|
@@ -226,6 +236,8 @@ export type StubPhaseResult = {
|
|
|
226
236
|
bannerUi?: BannerUiOpts;
|
|
227
237
|
caption?: string;
|
|
228
238
|
networkTabVisible?: boolean;
|
|
239
|
+
/** Slides to play in this phase ({@link StubUi.slides}); empty when the stub set none. */
|
|
240
|
+
slides: WaygraphSlide[];
|
|
229
241
|
todoPos?: "left" | "right";
|
|
230
242
|
/** When true, keep other docks (multi-todo). Default false = replace. */
|
|
231
243
|
todoParallel?: boolean;
|
|
@@ -249,9 +261,9 @@ export type StubBagState = {
|
|
|
249
261
|
/** Author asked to reset to desktop. */
|
|
250
262
|
hideDevice?: boolean | undefined;
|
|
251
263
|
device?: DeviceState | undefined;
|
|
252
|
-
/** Touch override when set via ctx.touch() alone or with device. */
|
|
264
|
+
/** Touch override when set via ctx.ui.touch() alone or with device. */
|
|
253
265
|
touchOverride?: boolean | undefined;
|
|
254
|
-
/** Orientation override when set via ctx.orientation / landscape / portrait. */
|
|
266
|
+
/** Orientation override when set via ctx.ui.orientation / landscape / portrait. */
|
|
255
267
|
orientationOverride?: DeviceOrientation | undefined;
|
|
256
268
|
zoom?: number | undefined;
|
|
257
269
|
zoomOut?: boolean | undefined;
|
|
@@ -260,6 +272,7 @@ export type StubBagState = {
|
|
|
260
272
|
bannerUi?: BannerUiOpts | undefined;
|
|
261
273
|
caption?: string | undefined;
|
|
262
274
|
networkTabVisible?: boolean | undefined;
|
|
275
|
+
slides?: readonly WaygraphSlide[] | undefined;
|
|
263
276
|
todoPos?: "left" | "right" | undefined;
|
|
264
277
|
/** Author patched todo-dock UX this phase. */
|
|
265
278
|
todoDockUi?: TodoDockUiOpts | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import "./runtime/full-launch.js";
|
|
2
|
-
import "./runtime/run-log.js";
|
|
3
1
|
export type { Checkpoint, Start } from "./engine/checkpoint/checkpoint.js";
|
|
4
2
|
export type { Instruction, Block, DefinedBlock, SomeBlock, SomeDefinedBlock } from "./engine/block/block.js";
|
|
5
3
|
export type { WaygraphInstanceOption } from "./engine/block/action-page.js";
|
|
@@ -11,7 +9,7 @@ export { css, byText, byRole } from "./engine/trait/selector.js";
|
|
|
11
9
|
export { WaygraphError, WAYGRAPH_ERRORS } from "./engine/errors.js";
|
|
12
10
|
export type { WaygraphErrorCode } from "./engine/errors.js";
|
|
13
11
|
export { Trait, urlMatches, textEquals, visible, disabled, enabled, frameVisible, frameTextEquals, frameContainsText } from "./engine/trait/trait.js";
|
|
14
|
-
export { runGraph, spawnTab,
|
|
12
|
+
export { runGraph, spawnTab, preflight, defineLayout } from "./engine/run/run.js";
|
|
15
13
|
export { Engine, map } from "./engine/engine.js";
|
|
16
14
|
export { branch } from "./engine/block/branch.js";
|
|
17
15
|
export { withVerify, modVerify, modVerifyAll, defineBlock } from "./engine/block/block.js";
|
|
@@ -29,7 +27,7 @@ export type { BranchEntry, BranchRunResult, RunBranchRegressionOptions } from ".
|
|
|
29
27
|
export type { ApiBlockOptions, ApiCallResult } from "./engine/block/kinds/api.js";
|
|
30
28
|
export type { MapStepOpts } from "./engine/flow/map-steps.js";
|
|
31
29
|
export type { MapFlowOpts } from "./engine/flow/map-builder.js";
|
|
32
|
-
export { resolveHighlightSlots,
|
|
30
|
+
export { resolveHighlightSlots, runStubPhase, hasAuthoredStubAfter, hasAuthoredStubOnError } from "./demo/narration/narration.js";
|
|
33
31
|
export { resolveFixtureDwellMs, normalizeDemoPace, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT } from "./demo/narration/demo-pace.js";
|
|
34
32
|
export { formatHighlightCaption, applyHighlightStyleDefaults, toneIconPrefix } from "./demo/narration/style.js";
|
|
35
33
|
export { normalizeHighlightTone, normalizeHighlightSize, normalizeHighlightWeight } from "./engine/stub/ring.js";
|
|
@@ -55,7 +53,7 @@ export { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./ana
|
|
|
55
53
|
export { buildManifest } from "./manifest/manifest.js";
|
|
56
54
|
export { onRunEvent } from "./engine/run/events.js";
|
|
57
55
|
export type { RunEvent } from "./engine/run/events.js";
|
|
58
|
-
export type { Manifest, ManifestBlock, ManifestFlow } from "./manifest/manifest.js";
|
|
56
|
+
export type { Manifest, ManifestBlock, ManifestFlow, ManifestReadBlock } from "./manifest/manifest.js";
|
|
59
57
|
export type { WaygraphGraph, WaygraphNode, WaygraphEdge, SkippedBlock, OrphanBlock } from "./analysis/graph.js";
|
|
60
58
|
export { isFileSelectToken, parseBlocksSelect, matchBlocksSelect, globToRegExp } from "./manifest/select.js";
|
|
61
59
|
export type { BlocksSelect, BlocksSelectKind } from "./manifest/select.js";
|
|
@@ -67,6 +65,10 @@ export type { TraverseCoverageReport } from "./live/traverse/coverage.js";
|
|
|
67
65
|
export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL, readWgOverlayBeacon, readWgOverlayBeaconInPage, assertWgOverlayReady } from "./demo/overlay/beacon.js";
|
|
68
66
|
export type { WgModalKind, WgBeaconRow } from "./demo/overlay/beacon.js";
|
|
69
67
|
export { AutoSession } from "./live/auto-session/auto-session.js";
|
|
68
|
+
export { SESSION_OPS, SESSION_PROTOCOL_VERSION } from "./live/auto-session/protocol.js";
|
|
69
|
+
export type { SessionRequest, SessionResponse, SessionStreamMessage, HelloResponse } from "./live/auto-session/protocol.js";
|
|
70
|
+
export { subscribeSession } from "./live/auto-session/feed.js";
|
|
71
|
+
export { requestSession } from "./live/auto-session/ipc.js";
|
|
70
72
|
export { stubFilePath } from "./live/auto-session/helpers.js";
|
|
71
73
|
export type { AutoSessionInit, SessionSnapshot, SessionSnapshotEdge, SessionSnapshotSection, ApplyPickResult, ApplyPathResult, TraceStep, ConsoleLogEntry, StorageSnapshot, ServiceWorkerRegistrationInfo, CookieInfo, StubFileKind } from "./live/auto-session/helpers.js";
|
|
72
74
|
export { pilotStart } from "./live/pilot/pilot.js";
|
|
@@ -79,12 +81,12 @@ export { resolveExtension, KNOWN_EXTENSIONS } from "./runtime/extensions.js";
|
|
|
79
81
|
export type { ExtensionSpec } from "./engine/config.js";
|
|
80
82
|
export type { WebServerConfig } from "./runtime/webserver.js";
|
|
81
83
|
export type { MapStart } from "./engine/engine.js";
|
|
82
|
-
export type { WaygraphSlidesOrFn } from "./engine/stub/ring.js";
|
|
83
84
|
export type { ConnectLayout } from "./engine/run/connect.js";
|
|
84
85
|
export type { EffectExtras } from "./engine/block/kinds/effect.js";
|
|
85
86
|
export type { BlockBase, RoutedBlockBase } from "./engine/checkpoint/route.js";
|
|
86
87
|
export type { RunEventListener } from "./engine/run/events.js";
|
|
87
|
-
export type {
|
|
88
|
+
export type { ScanOptions } from "./manifest/project.js";
|
|
89
|
+
export type { BlockKind } from "./engine/block/kind.js";
|
|
88
90
|
export type { DomSnapshot, InspectDomOptions, InspectDomResult } from "./live/auto-session/helpers.js";
|
|
89
91
|
export type { BrowserStartInit } from "./live/auto-session/start.js";
|
|
90
92
|
export type { PilotFixtureRing, PilotHighlightFixtures } from "./demo/overlay/pilot/fixtures.js";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import "./runtime/
|
|
3
|
-
//
|
|
4
|
-
|
|
1
|
+
import { installFullLaunch } from "./runtime/full-launch.js";
|
|
2
|
+
import { installRunLog } from "./runtime/run-log.js";
|
|
3
|
+
// The package entry wires the runtime in, explicitly: how an Engine launches its own browser (config, Chromium path,
|
|
4
|
+
// extensions), and the run log (.waygraph/runs) the CLI turns on. No module switches itself on by being imported.
|
|
5
|
+
installFullLaunch();
|
|
6
|
+
installRunLog();
|
|
5
7
|
export { connect } from "./engine/run/connect.js";
|
|
6
8
|
export { checkpoint } from "./engine/checkpoint/checkpoint.js";
|
|
7
9
|
export { MemKey, MemPage, key, keyGroup } from "./engine/mem/mem.js";
|
|
@@ -9,7 +11,7 @@ export { registerMemStub, seedMemStub, getMemStub } from "./engine/mem/mem-stub.
|
|
|
9
11
|
export { css, byText, byRole } from "./engine/trait/selector.js";
|
|
10
12
|
export { WaygraphError, WAYGRAPH_ERRORS } from "./engine/errors.js";
|
|
11
13
|
export { Trait, urlMatches, textEquals, visible, disabled, enabled, frameVisible, frameTextEquals, frameContainsText } from "./engine/trait/trait.js";
|
|
12
|
-
export { runGraph, spawnTab,
|
|
14
|
+
export { runGraph, spawnTab, preflight, defineLayout } from "./engine/run/run.js";
|
|
13
15
|
export { Engine, map } from "./engine/engine.js";
|
|
14
16
|
export { branch } from "./engine/block/branch.js";
|
|
15
17
|
export { withVerify, modVerify, modVerifyAll, defineBlock } from "./engine/block/block.js";
|
|
@@ -23,7 +25,7 @@ export { locate } from "./engine/locate.js";
|
|
|
23
25
|
export { composeBlock, fastForwardComposeBlock, isFastForwardBlock } from "./engine/block/compose.js";
|
|
24
26
|
export { MapBuilder } from "./engine/flow/map-builder.js";
|
|
25
27
|
export { branchRoutes, collectBranchFlows, runBranchRegression } from "./engine/flow/branch-regression.js";
|
|
26
|
-
export { resolveHighlightSlots,
|
|
28
|
+
export { resolveHighlightSlots, runStubPhase, hasAuthoredStubAfter, hasAuthoredStubOnError } from "./demo/narration/narration.js";
|
|
27
29
|
export { resolveFixtureDwellMs, normalizeDemoPace, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT } from "./demo/narration/demo-pace.js";
|
|
28
30
|
export { formatHighlightCaption, applyHighlightStyleDefaults, toneIconPrefix } from "./demo/narration/style.js";
|
|
29
31
|
export { normalizeHighlightTone, normalizeHighlightSize, normalizeHighlightWeight } from "./engine/stub/ring.js";
|
|
@@ -39,6 +41,9 @@ export { runTraverse } from "./live/traverse/traverse.js";
|
|
|
39
41
|
export { buildCoverageReport, collectGraphEdgeKeys, defaultCoverageOutPath, formatCoverageLine, normalizeHitKey, parseMinEdgeCoverage, writeCoverageReport } from "./live/traverse/coverage.js";
|
|
40
42
|
export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL, readWgOverlayBeacon, readWgOverlayBeaconInPage, assertWgOverlayReady } from "./demo/overlay/beacon.js";
|
|
41
43
|
export { AutoSession } from "./live/auto-session/auto-session.js";
|
|
44
|
+
export { SESSION_OPS, SESSION_PROTOCOL_VERSION } from "./live/auto-session/protocol.js";
|
|
45
|
+
export { subscribeSession } from "./live/auto-session/feed.js";
|
|
46
|
+
export { requestSession } from "./live/auto-session/ipc.js";
|
|
42
47
|
export { stubFilePath } from "./live/auto-session/helpers.js";
|
|
43
48
|
export { pilotStart } from "./live/pilot/pilot.js";
|
|
44
49
|
export { defineConfig, resolveBaseUrl } from "./runtime/waygraph-config.js";
|
package/dist/live/auto/auto.js
CHANGED
|
@@ -61,8 +61,6 @@ export async function runOneBlock(engine, entry, context, page, mem, headful) {
|
|
|
61
61
|
await page.evaluate("delete window.__wgPendingNavClickLabel").catch(ignorePageGone);
|
|
62
62
|
return result;
|
|
63
63
|
}
|
|
64
|
-
/** Shown in the headful panel after each Block run. */
|
|
65
|
-
let lastRunNote = null;
|
|
66
64
|
/**
|
|
67
65
|
* Interactive waygraph auto: locate current Checkpoint, list runnable Blocks, pick one, repeat.
|
|
68
66
|
*/
|
|
@@ -70,7 +68,8 @@ export async function runAutoExplore(projectDir, options = {}) {
|
|
|
70
68
|
await withWebServer(projectDir, () => runAutoExploreCore(projectDir, options));
|
|
71
69
|
}
|
|
72
70
|
async function runAutoExploreCore(projectDir, options = {}) {
|
|
73
|
-
|
|
71
|
+
/** Shown in the headful panel after each Block run. */
|
|
72
|
+
let lastRunNote = null;
|
|
74
73
|
const cli = options.cli === true;
|
|
75
74
|
const baseURL = options.baseURL ?? (await resolveBaseUrl(projectDir)) ?? envString("WAYGRAPH_BASE_URL");
|
|
76
75
|
const startUrl = options.startUrl ?? baseURL;
|
package/dist/live/auto/menu.js
CHANGED
|
@@ -27,8 +27,9 @@ export async function setAutoPanelRunning(page, label) {
|
|
|
27
27
|
}, label)
|
|
28
28
|
.catch(ignorePageGone);
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
// In the bottom-center slot of the overlay layout (demo/overlay/ui/css/layout.css), like the demo's step panel.
|
|
31
|
+
export const PANEL_CSS = "#wg-auto-panel{z-index:var(--wg-z-top);" +
|
|
32
|
+
"width:min(92vw,720px);overflow-y:auto;box-sizing:border-box;" +
|
|
32
33
|
"background:rgba(20,10,40,.94);color:#fff;border-radius:14px;padding:16px 20px;" +
|
|
33
34
|
"font:14px/1.4 system-ui,sans-serif;box-shadow:0 12px 30px rgba(0,0,0,.35);}" +
|
|
34
35
|
"#wg-auto-panel h3{margin:0 0 10px;font-size:16px;}" +
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PilotHighlightFixtures } from "../../demo/overlay/pilot/fixtures.js";
|
|
2
2
|
import type { ApplyPathResult, ApplyPickResult, AutoSessionInit, ConsoleLogEntry, InspectDomOptions, InspectDomResult, SessionSnapshot, StorageSnapshot, StubFileKind, TraceStep } from "./helpers.js";
|
|
3
|
+
import { type SessionRead } from "./read.js";
|
|
3
4
|
/**
|
|
4
5
|
* A live session driven over IPC (`browser start`, `pilot start`): the same graph, library, mem and browser as
|
|
5
6
|
* `waygraph auto`, moved one call at a time (`applyPick`, `applyPath`, the raw actions) instead of a menu loop.
|
|
@@ -17,12 +18,12 @@ export declare class AutoSession {
|
|
|
17
18
|
private page;
|
|
18
19
|
private readonly startUrl;
|
|
19
20
|
private readonly sessionId;
|
|
21
|
+
private readonly knownInteractionSelectors;
|
|
22
|
+
private readonly headless;
|
|
20
23
|
private here;
|
|
21
24
|
private lastRunNote;
|
|
22
25
|
private readonly trace;
|
|
23
26
|
private readonly consoleLog;
|
|
24
|
-
private readonly knownInteractionSelectors;
|
|
25
|
-
private readonly headless;
|
|
26
27
|
private lastOverlayInfo;
|
|
27
28
|
private constructor();
|
|
28
29
|
static start(init: AutoSessionInit): Promise<AutoSession>;
|
|
@@ -43,8 +44,14 @@ export declare class AutoSession {
|
|
|
43
44
|
* Deduped per page load so repeated status/send calls stay quiet.
|
|
44
45
|
*/
|
|
45
46
|
private warnUnmappedInteractions;
|
|
47
|
+
/** The Checkpoint the session is at, if known. */
|
|
48
|
+
get where(): string | null;
|
|
46
49
|
/** Pure getter - no Block runs, no mem/page mutation. */
|
|
47
50
|
currentSnapshot(): Promise<SessionSnapshot>;
|
|
51
|
+
/** The menu as a snapshot, with what the page shows (Read Blocks) when any covers it. */
|
|
52
|
+
private snapshotOf;
|
|
53
|
+
/** Pure getter - what the page shows, from the project's Read Blocks (beta). */
|
|
54
|
+
read(path?: string): Promise<SessionRead>;
|
|
48
55
|
/**
|
|
49
56
|
* Pure getter - reads the live page's structure at the requested fidelity.
|
|
50
57
|
* No Block runs, no mem/page mutation. `selector` scopes either mode to one
|
|
@@ -3,7 +3,7 @@ import { findBlockPathDetailed } from "../../analysis/graph.js";
|
|
|
3
3
|
import { runStubPhase } from "../../demo/narration/narration.js";
|
|
4
4
|
import { describeOverlayFixtures, phaseToOverlayFixtures } from "../../demo/overlay/phase-fixtures.js";
|
|
5
5
|
import { showPilotFixtures } from "../../demo/overlay/pilot/fixtures.js";
|
|
6
|
-
import { showPilotActivity
|
|
6
|
+
import { showPilotActivity } from "../../demo/overlay/pilot/shell.js";
|
|
7
7
|
import { keepOverlayOnNavigation } from "../../demo/overlay/reattach.js";
|
|
8
8
|
import { verboseLog } from "../../demo/verbose-log.js";
|
|
9
9
|
import { Engine } from "../../engine/engine.js";
|
|
@@ -15,17 +15,10 @@ import { buildExploreContext, buildExploreMenu } from "../auto/explore.js";
|
|
|
15
15
|
import { ensureMem, seedDefaultMem } from "../auto/mem.js";
|
|
16
16
|
import { updatePilotOverlay } from "../pilot/panel.js";
|
|
17
17
|
import { recordPageConsole } from "./console.js";
|
|
18
|
-
import { CONSOLE_LOG_MAX_ENTRIES, TRACE_MAX_STEPS, buildSessionSnapshot, describeHighlight, parsePick, stubFilePath, stubPhaseHasContent } from "./helpers.js";
|
|
18
|
+
import { CONSOLE_LOG_MAX_ENTRIES, TRACE_MAX_STEPS, buildSessionSnapshot, describeHighlight, parsePick, rawTarget, stubFilePath, stubPhaseHasContent } from "./helpers.js";
|
|
19
19
|
import { inspectDom, inspectStorage } from "./inspect.js";
|
|
20
20
|
import { openSessionBrowser } from "./open-browser.js";
|
|
21
|
-
|
|
22
|
-
async function rawTarget(page, selector, label) {
|
|
23
|
-
const locator = page.locator(selector).first();
|
|
24
|
-
if ((await locator.count()) === 0)
|
|
25
|
-
return `no element matches selector "${selector}"`;
|
|
26
|
-
await showPilotVision(page, selector, label);
|
|
27
|
-
return locator;
|
|
28
|
-
}
|
|
21
|
+
import { readSession, snapshotRead } from "./read.js";
|
|
29
22
|
/**
|
|
30
23
|
* A live session driven over IPC (`browser start`, `pilot start`): the same graph, library, mem and browser as
|
|
31
24
|
* `waygraph auto`, moved one call at a time (`applyPick`, `applyPath`, the raw actions) instead of a menu loop.
|
|
@@ -43,12 +36,12 @@ export class AutoSession {
|
|
|
43
36
|
page;
|
|
44
37
|
startUrl;
|
|
45
38
|
sessionId;
|
|
39
|
+
knownInteractionSelectors;
|
|
40
|
+
headless;
|
|
46
41
|
here = null;
|
|
47
42
|
lastRunNote = null;
|
|
48
43
|
trace = [];
|
|
49
44
|
consoleLog = [];
|
|
50
|
-
knownInteractionSelectors;
|
|
51
|
-
headless;
|
|
52
45
|
lastOverlayInfo = null;
|
|
53
46
|
constructor(projectDir, inject, blocksSelect, graph, library, mem, engine, closeBrowser, context, page, startUrl, sessionId, knownInteractionSelectors, headless) {
|
|
54
47
|
this.projectDir = projectDir;
|
|
@@ -118,7 +111,7 @@ export class AutoSession {
|
|
|
118
111
|
// watching sees the state an API caller just got back, not a frame behind.
|
|
119
112
|
this.lastOverlayInfo = {
|
|
120
113
|
sessionId: this.sessionId,
|
|
121
|
-
snapshot:
|
|
114
|
+
snapshot: await this.snapshotOf(menu),
|
|
122
115
|
graph: this.graph,
|
|
123
116
|
};
|
|
124
117
|
await updatePilotOverlay(this.page, this.lastOverlayInfo);
|
|
@@ -163,10 +156,20 @@ export class AutoSession {
|
|
|
163
156
|
};
|
|
164
157
|
await this.page.evaluate(unmappedInteractionsPageScript, payload).catch(ignorePageGone);
|
|
165
158
|
}
|
|
159
|
+
/** The Checkpoint the session is at, if known. */
|
|
160
|
+
get where() { return this.here; }
|
|
166
161
|
/** Pure getter - no Block runs, no mem/page mutation. */
|
|
167
162
|
async currentSnapshot() {
|
|
168
|
-
|
|
169
|
-
|
|
163
|
+
return this.snapshotOf(await this.currentMenu());
|
|
164
|
+
}
|
|
165
|
+
/** The menu as a snapshot, with what the page shows (Read Blocks) when any covers it. */
|
|
166
|
+
async snapshotOf(menu) {
|
|
167
|
+
return { ...buildSessionSnapshot(menu, this.library.byName, this.here, this.lastRunNote), ...(await snapshotRead(this.page, this.mem, this.here)) };
|
|
168
|
+
}
|
|
169
|
+
/** Pure getter - what the page shows, from the project's Read Blocks (beta). */
|
|
170
|
+
async read(path) {
|
|
171
|
+
this.page = await ensureLivePage(this.context, this.page, this.startUrl);
|
|
172
|
+
return readSession(this.page, this.mem, this.here, path);
|
|
170
173
|
}
|
|
171
174
|
/**
|
|
172
175
|
* Pure getter - reads the live page's structure at the requested fidelity.
|
|
@@ -238,7 +241,7 @@ export class AutoSession {
|
|
|
238
241
|
const nextMenu = await this.currentMenu();
|
|
239
242
|
return {
|
|
240
243
|
ok: true,
|
|
241
|
-
snapshot:
|
|
244
|
+
snapshot: await this.snapshotOf(nextMenu),
|
|
242
245
|
quit: false,
|
|
243
246
|
};
|
|
244
247
|
}
|
|
@@ -251,7 +254,7 @@ export class AutoSession {
|
|
|
251
254
|
if (pick.type === "quit") {
|
|
252
255
|
return {
|
|
253
256
|
ok: true,
|
|
254
|
-
snapshot:
|
|
257
|
+
snapshot: await this.snapshotOf(menu),
|
|
255
258
|
quit: true,
|
|
256
259
|
};
|
|
257
260
|
}
|
|
@@ -292,7 +295,7 @@ export class AutoSession {
|
|
|
292
295
|
this.lastRunNote = `resync -> ${this.here ?? "Unknown"}`;
|
|
293
296
|
return {
|
|
294
297
|
ok: true,
|
|
295
|
-
snapshot:
|
|
298
|
+
snapshot: await this.snapshotOf(menu),
|
|
296
299
|
quit: false,
|
|
297
300
|
};
|
|
298
301
|
}
|
|
@@ -363,7 +366,7 @@ export class AutoSession {
|
|
|
363
366
|
this.lastRunNote = `${what} -> ${this.here ?? "Unknown"}`;
|
|
364
367
|
return {
|
|
365
368
|
ok: true,
|
|
366
|
-
snapshot:
|
|
369
|
+
snapshot: await this.snapshotOf(menu),
|
|
367
370
|
quit: false,
|
|
368
371
|
};
|
|
369
372
|
}
|
|
@@ -390,7 +393,7 @@ export class AutoSession {
|
|
|
390
393
|
ok: true,
|
|
391
394
|
painted,
|
|
392
395
|
missing,
|
|
393
|
-
snapshot:
|
|
396
|
+
snapshot: await this.snapshotOf(menu),
|
|
394
397
|
};
|
|
395
398
|
}
|
|
396
399
|
catch (err) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Socket } from "node:net";
|
|
2
|
+
import type { SessionStreamMessage } from "./protocol.js";
|
|
3
|
+
/** The server side: subscribed sockets, fed every run event in this process until `close`. */
|
|
4
|
+
export declare function createFeed(): {
|
|
5
|
+
add(sock: Socket): void;
|
|
6
|
+
send(message: SessionStreamMessage): void;
|
|
7
|
+
close(): void;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The client side: subscribes to a running session and calls `onMessage` for each line until `close()` (or the session
|
|
11
|
+
* ends). Rejects when the session is unknown or does not answer the subscribe.
|
|
12
|
+
*/
|
|
13
|
+
export declare function subscribeSession(projectDir: string, sessionId: string, onMessage: (message: SessionStreamMessage) => void, timeoutMs?: number): Promise<{
|
|
14
|
+
close(): void;
|
|
15
|
+
closed: Promise<void>;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// A session's live feed (`subscribe`): every run event in the session (steps, reads) and the snapshot after each change,
|
|
2
|
+
// as JSON lines to every subscribed socket. Waygraph UI watches a session through it; `pilot watch <id>` prints it.
|
|
3
|
+
import { connect } from "node:net";
|
|
4
|
+
import { onRunEvent } from "../../engine/run/events.js";
|
|
5
|
+
import { resolveSessionMeta } from "./files.js";
|
|
6
|
+
import { SESSION_PROTOCOL_VERSION } from "./protocol.js";
|
|
7
|
+
/** The server side: subscribed sockets, fed every run event in this process until `close`. */
|
|
8
|
+
export function createFeed() {
|
|
9
|
+
const subscribers = new Set();
|
|
10
|
+
const send = (message) => {
|
|
11
|
+
const line = JSON.stringify(message) + "\n";
|
|
12
|
+
for (const sock of subscribers)
|
|
13
|
+
if (!sock.destroyed)
|
|
14
|
+
sock.write(line);
|
|
15
|
+
};
|
|
16
|
+
const off = onRunEvent((event) => send({ type: "event", event }));
|
|
17
|
+
return {
|
|
18
|
+
add(sock) {
|
|
19
|
+
subscribers.add(sock);
|
|
20
|
+
sock.on("close", () => subscribers.delete(sock));
|
|
21
|
+
sock.write(JSON.stringify({ ok: true, protocol: SESSION_PROTOCOL_VERSION }) + "\n");
|
|
22
|
+
},
|
|
23
|
+
send,
|
|
24
|
+
close() {
|
|
25
|
+
off();
|
|
26
|
+
for (const sock of subscribers)
|
|
27
|
+
sock.end();
|
|
28
|
+
subscribers.clear();
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The client side: subscribes to a running session and calls `onMessage` for each line until `close()` (or the session
|
|
34
|
+
* ends). Rejects when the session is unknown or does not answer the subscribe.
|
|
35
|
+
*/
|
|
36
|
+
export function subscribeSession(projectDir, sessionId, onMessage, timeoutMs = 15_000) {
|
|
37
|
+
const meta = resolveSessionMeta(sessionId, projectDir);
|
|
38
|
+
if (!meta)
|
|
39
|
+
return Promise.reject(new Error(`no such session "${sessionId}" - \`waygraph pilot sessions\` lists live ids`));
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
const sock = connect(meta.socketPath);
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
sock.destroy();
|
|
44
|
+
reject(new Error(`session "${sessionId}" did not answer subscribe within ${timeoutMs}ms`));
|
|
45
|
+
}, timeoutMs);
|
|
46
|
+
const closed = new Promise((done) => sock.on("close", () => done()));
|
|
47
|
+
let buf = "";
|
|
48
|
+
let acked = false;
|
|
49
|
+
sock.on("connect", () => sock.write(JSON.stringify({ op: "subscribe" }) + "\n"));
|
|
50
|
+
sock.on("error", (err) => {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
if (!acked)
|
|
53
|
+
reject(err);
|
|
54
|
+
});
|
|
55
|
+
sock.on("data", (chunk) => {
|
|
56
|
+
buf += chunk.toString("utf-8");
|
|
57
|
+
let nl;
|
|
58
|
+
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
59
|
+
const line = buf.slice(0, nl);
|
|
60
|
+
buf = buf.slice(nl + 1);
|
|
61
|
+
if (!acked) {
|
|
62
|
+
acked = true;
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
resolve({ close: () => sock.end(), closed });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
onMessage(JSON.parse(line));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Locator, Page } from "@playwright/test";
|
|
1
2
|
import type { PilotHighlightFixtures } from "../../demo/overlay/pilot/fixtures.js";
|
|
2
3
|
import type { StubPhaseResult } from "../../engine/stub/stub.js";
|
|
3
4
|
import type { BlockEntry } from "../../manifest/project.js";
|
|
@@ -27,6 +28,10 @@ export interface SessionSnapshot {
|
|
|
27
28
|
/** True when there are no runnable moves from `here` right now. */
|
|
28
29
|
done: boolean;
|
|
29
30
|
lastRunNote: string | null;
|
|
31
|
+
/** What the page shows, from the project's Read Blocks (beta); absent when none covers this page. */
|
|
32
|
+
read?: Record<string, unknown>;
|
|
33
|
+
missing?: string[];
|
|
34
|
+
readNotes?: Record<string, string>;
|
|
30
35
|
}
|
|
31
36
|
/** Plain, JSON-serializable view of a menu - no Block/MemKey/class references. */
|
|
32
37
|
export declare function buildSessionSnapshot(menu: ExploreMenu, library: Map<string, BlockEntry>, here: string | null, lastRunNote: string | null): SessionSnapshot;
|
|
@@ -214,4 +219,6 @@ export interface StorageSnapshot {
|
|
|
214
219
|
}
|
|
215
220
|
/** What a highlight call paints, in a few words, for the session's activity line. */
|
|
216
221
|
export declare function describeHighlight(fixtures: PilotHighlightFixtures): string;
|
|
222
|
+
/** The first element `selector` matches, ringed with the pilot's vision ring; or why there is none. */
|
|
223
|
+
export declare function rawTarget(page: Page, selector: string, label: string): Promise<Locator | string>;
|
|
217
224
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// The session's shared shapes and pure helpers: snapshots, picks, trace / console entries, DOM walking, stub files.
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { showPilotVision } from "../../demo/overlay/pilot/shell.js";
|
|
4
5
|
/** True when a stub-phase result actually carries authored content worth keeping. */
|
|
5
6
|
export function stubPhaseHasContent(r) {
|
|
6
7
|
return (Object.keys(r.highlights).length > 0 ||
|
|
@@ -163,3 +164,11 @@ export function describeHighlight(fixtures) {
|
|
|
163
164
|
.filter(Boolean)
|
|
164
165
|
.join(", ") || "fixtures");
|
|
165
166
|
}
|
|
167
|
+
/** The first element `selector` matches, ringed with the pilot's vision ring; or why there is none. */
|
|
168
|
+
export async function rawTarget(page, selector, label) {
|
|
169
|
+
const locator = page.locator(selector).first();
|
|
170
|
+
if ((await locator.count()) === 0)
|
|
171
|
+
return `no element matches selector "${selector}"`;
|
|
172
|
+
await showPilotVision(page, selector, label);
|
|
173
|
+
return locator;
|
|
174
|
+
}
|