waygraph 0.16.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/browser.d.ts +2 -0
- package/dist/cli/commands/browser.js +109 -0
- package/dist/cli/commands/pilot.d.ts +2 -0
- package/dist/cli/commands/pilot.js +102 -0
- package/dist/cli/commands/session-ops.d.ts +3 -0
- package/dist/cli/commands/session-ops.js +257 -0
- package/dist/cli/commands/session.js +20 -461
- package/dist/cli/usage.d.ts +1 -1
- package/dist/demo/narration/demo-pace.d.ts +1 -1
- package/dist/demo/narration/device.d.ts +2 -2
- package/dist/demo/narration/merge.d.ts +4 -2
- package/dist/demo/narration/merge.js +2 -6
- package/dist/demo/narration/narration.d.ts +8 -8
- package/dist/demo/narration/todo-dock.d.ts +5 -5
- package/dist/demo/overlay/cursor.d.ts +9 -2
- package/dist/demo/overlay/cursor.js +1 -1
- package/dist/demo/overlay/device-stage.d.ts +15 -2
- package/dist/demo/overlay/inpage/banner.d.ts +2 -1
- package/dist/demo/overlay/inpage/banner.js +3 -3
- package/dist/demo/overlay/inpage/caption.d.ts +1 -1
- package/dist/demo/overlay/inpage/core.d.ts +2 -1
- package/dist/demo/overlay/inpage/core.js +1 -1
- package/dist/demo/overlay/inpage/device-chip.d.ts +1 -1
- package/dist/demo/overlay/inpage/device-chip.js +6 -6
- package/dist/demo/overlay/inpage/network.d.ts +3 -2
- package/dist/demo/overlay/inpage/network.js +1 -12
- package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -1
- package/dist/demo/overlay/inpage/panel-chrome.js +1 -1
- package/dist/demo/overlay/inpage/stamp.d.ts +1 -1
- package/dist/demo/overlay/inpage/stamp.js +1 -1
- package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -1
- package/dist/demo/overlay/inpage/swipe-zoom.js +1 -1
- package/dist/demo/overlay/inpage/todos.d.ts +2 -1
- package/dist/demo/overlay/inpage/todos.js +1 -2
- package/dist/demo/overlay/network-capture.d.ts +2 -2
- package/dist/demo/overlay/network-capture.js +1 -1
- package/dist/demo/overlay/overlay-stage.d.ts +19 -11
- package/dist/demo/overlay/overlay.d.ts +2 -2
- package/dist/demo/overlay/rings.d.ts +38 -10
- package/dist/demo/overlay/rings.js +21 -47
- package/dist/demo/stepper/after.js +9 -19
- package/dist/demo/stepper/banner-log.d.ts +4 -6
- package/dist/demo/stepper/banner-log.js +3 -1
- package/dist/demo/stepper/before.js +3 -3
- package/dist/demo/stepper/demo-log.d.ts +26 -9
- package/dist/demo/stepper/demo-log.js +9 -26
- package/dist/demo/stepper/interaction-patch.d.ts +3 -2
- package/dist/demo/stepper/interaction-patch.js +19 -19
- package/dist/demo/stepper/panel-after.d.ts +17 -0
- package/dist/demo/stepper/panel-after.js +166 -0
- package/dist/demo/stepper/panel-before.d.ts +12 -0
- package/dist/demo/stepper/panel-before.js +241 -0
- package/dist/demo/stepper/slides.d.ts +13 -1
- package/dist/demo/stepper/slides.js +3 -3
- package/dist/demo/stepper/step-panels.d.ts +57 -9
- package/dist/demo/stepper/step-panels.js +10 -427
- package/dist/demo/stepper/stepper.js +1 -1
- package/dist/demo/stepper/teardown.d.ts +4 -5
- package/dist/demo/stepper/teardown.js +4 -5
- package/dist/demo/stepper/todo-advance.d.ts +3 -2
- package/dist/demo/stepper/todo-advance.js +2 -2
- package/dist/demo/stepper/view.d.ts +4 -14
- package/dist/demo/types.d.ts +69 -1
- package/dist/engine/block/action-page.d.ts +53 -0
- package/dist/engine/block/action-page.js +1 -0
- package/dist/engine/block/block.d.ts +24 -79
- package/dist/engine/block/block.js +2 -77
- package/dist/engine/block/branch.d.ts +17 -0
- package/dist/engine/block/branch.js +40 -0
- package/dist/engine/block/dialog.d.ts +13 -0
- package/dist/engine/block/dialog.js +37 -0
- package/dist/engine/flow/map-branch.d.ts +9 -0
- package/dist/engine/flow/map-branch.js +57 -0
- package/dist/engine/flow/map-builder.d.ts +7 -22
- package/dist/engine/flow/map-builder.js +6 -145
- package/dist/engine/flow/map-steps.d.ts +30 -0
- package/dist/engine/flow/map-steps.js +87 -0
- package/dist/engine/trait/trait.js +1 -1
- package/dist/index.d.ts +13 -9
- package/dist/index.js +7 -5
- package/dist/live/auto/auto.d.ts +3 -15
- package/dist/live/auto/auto.js +10 -420
- package/dist/live/auto/explore.d.ts +2 -2
- package/dist/live/auto/mem.d.ts +11 -0
- package/dist/live/auto/mem.js +85 -0
- package/dist/live/auto/menu.d.ts +30 -0
- package/dist/live/auto/menu.js +335 -0
- package/dist/live/auto-session/auto-session.d.ts +23 -103
- package/dist/live/auto-session/auto-session.js +100 -370
- package/dist/live/auto-session/console.d.ts +4 -0
- package/dist/live/auto-session/console.js +41 -0
- package/dist/live/auto-session/files.d.ts +44 -0
- package/dist/live/auto-session/files.js +145 -0
- package/dist/live/auto-session/helpers.d.ts +5 -2
- package/dist/live/auto-session/helpers.js +17 -0
- package/dist/live/auto-session/inspect.d.ts +4 -0
- package/dist/live/auto-session/inspect.js +75 -0
- package/dist/live/auto-session/ipc.d.ts +3 -22
- package/dist/live/auto-session/ipc.js +7 -147
- package/dist/live/auto-session/open-browser.d.ts +6 -0
- package/dist/live/auto-session/open-browser.js +47 -0
- package/dist/live/pilot/pilot.d.ts +1 -1
- package/dist/live/pilot/pilot.js +2 -1
- package/dist/live/traverse/traverse.js +6 -200
- package/dist/live/traverse/worker.d.ts +37 -0
- package/dist/live/traverse/worker.js +200 -0
- package/package.json +5 -1
|
@@ -1,5 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { StubPhaseResult } from "../../engine/stub/stub.js";
|
|
2
|
+
import type { TodoDockState } from "../../engine/stub/todos.js";
|
|
3
|
+
import type { DeviceState } from "../../engine/stub/viewport.js";
|
|
4
|
+
/** What a HIGHLIGHT log line shows: a ring as painted (no selector for a narrated caption). Logged, not checked. */
|
|
5
|
+
type LoggedHighlight = {
|
|
6
|
+
selector?: string | null | undefined;
|
|
7
|
+
label?: string | undefined;
|
|
8
|
+
tone?: string | undefined;
|
|
9
|
+
color?: string | undefined;
|
|
10
|
+
focus?: boolean | undefined;
|
|
11
|
+
zoom?: number | undefined;
|
|
12
|
+
zoomOut?: boolean | undefined;
|
|
13
|
+
gesture?: string | undefined;
|
|
14
|
+
weight?: string | undefined;
|
|
15
|
+
size?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
export declare function demoPaceKind(pace: unknown): string;
|
|
18
|
+
export declare function paceSpeakFields(pace: unknown, baseAutoplayMs: number | undefined): {
|
|
3
19
|
pace: import("../../index.js").DemoPace;
|
|
4
20
|
paceBadge: string;
|
|
5
21
|
paceLabel: string;
|
|
@@ -19,13 +35,14 @@ export declare const ANSI: {
|
|
|
19
35
|
magenta: string;
|
|
20
36
|
white: string;
|
|
21
37
|
};
|
|
22
|
-
export declare function ansiPaint(code:
|
|
23
|
-
export declare function demoLog(msg:
|
|
38
|
+
export declare function ansiPaint(code: string, text: unknown): string;
|
|
39
|
+
export declare function demoLog(msg: string): void;
|
|
24
40
|
/** Fixture catch-all: how it was called + value. */
|
|
25
|
-
export declare function demoFixture(kind:
|
|
41
|
+
export declare function demoFixture(kind: string, call: string, value?: unknown): void;
|
|
26
42
|
/** Highlight trigger line: PURPLE · Cart items - Product landed in cart */
|
|
27
|
-
export declare function demoHighlight(h:
|
|
28
|
-
export declare function logStubPhaseFixtures(phaseName:
|
|
43
|
+
export declare function demoHighlight(h: LoggedHighlight | null | undefined, extra?: string): void;
|
|
44
|
+
export declare function logStubPhaseFixtures(phaseName: string, phase: StubPhaseResult | null | undefined): void;
|
|
29
45
|
/** Full todo dump for agents (every group/item id + flags). */
|
|
30
|
-
export declare function logTodoDockFull(dock:
|
|
31
|
-
export declare function summarizeDevice(d:
|
|
46
|
+
export declare function logTodoDockFull(dock: TodoDockState | null | undefined, tag?: string): void;
|
|
47
|
+
export declare function summarizeDevice(d: DeviceState | null | undefined): string;
|
|
48
|
+
export {};
|
|
@@ -14,7 +14,7 @@ export function demoPaceKind(pace) {
|
|
|
14
14
|
}
|
|
15
15
|
export function paceSpeakFields(pace, baseAutoplayMs) {
|
|
16
16
|
const p = normalizeDemoPace(pace);
|
|
17
|
-
const base = Number.isFinite(baseAutoplayMs) && baseAutoplayMs > 0 ? baseAutoplayMs : 1800;
|
|
17
|
+
const base = baseAutoplayMs !== undefined && Number.isFinite(baseAutoplayMs) && baseAutoplayMs > 0 ? baseAutoplayMs : 1800;
|
|
18
18
|
return {
|
|
19
19
|
pace: p,
|
|
20
20
|
paceBadge: formatDemoPaceBadge(p, base),
|
|
@@ -207,12 +207,10 @@ export function logStubPhaseFixtures(phaseName, phase) {
|
|
|
207
207
|
}
|
|
208
208
|
: phase.todoSync);
|
|
209
209
|
}
|
|
210
|
-
|
|
211
|
-
for (let i = 0; i < rings.length; i++) {
|
|
212
|
-
const h = rings[i];
|
|
210
|
+
phase.highlights.forEach((h, i) => {
|
|
213
211
|
demoFixture(tag, "ctx.ring/highlights[" + i + "]", {
|
|
214
212
|
selector: h.selector,
|
|
215
|
-
label: h.label
|
|
213
|
+
label: h.label,
|
|
216
214
|
detail: h.detail,
|
|
217
215
|
tone: h.tone || "planned",
|
|
218
216
|
color: h.color,
|
|
@@ -222,10 +220,7 @@ export function logStubPhaseFixtures(phaseName, phase) {
|
|
|
222
220
|
gesture: h.gesture,
|
|
223
221
|
duration: h.duration,
|
|
224
222
|
});
|
|
225
|
-
}
|
|
226
|
-
if (phase.slides && phase.slides.length) {
|
|
227
|
-
demoFixture(tag, "ctx.slides(...)", { n: phase.slides.length });
|
|
228
|
-
}
|
|
223
|
+
});
|
|
229
224
|
}
|
|
230
225
|
function summarizeTodoDock(dock) {
|
|
231
226
|
if (!dock)
|
|
@@ -267,8 +262,7 @@ export function logTodoDockFull(dock, tag) {
|
|
|
267
262
|
demoLog(prefix + " (no groups)");
|
|
268
263
|
return;
|
|
269
264
|
}
|
|
270
|
-
|
|
271
|
-
const g = groups[gi];
|
|
265
|
+
groups.forEach((g, gi) => {
|
|
272
266
|
const gLabel = "group[" +
|
|
273
267
|
gi +
|
|
274
268
|
"]" +
|
|
@@ -276,22 +270,11 @@ export function logTodoDockFull(dock, tag) {
|
|
|
276
270
|
(g.title ? ' title="' + String(g.title).slice(0, 40) + '"' : "") +
|
|
277
271
|
(g.style ? " style=" + g.style : "");
|
|
278
272
|
demoLog(prefix + " " + gLabel);
|
|
279
|
-
|
|
280
|
-
for (let ti = 0; ti < items.length; ti++) {
|
|
281
|
-
const t = items[ti];
|
|
273
|
+
(g.items || []).forEach((t, ti) => {
|
|
282
274
|
const mark = t.done ? "done" : t.current ? "CURRENT" : "pending";
|
|
283
|
-
demoLog(prefix +
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"] " +
|
|
287
|
-
mark +
|
|
288
|
-
(t.id ? " id=" + t.id : "") +
|
|
289
|
-
' text="' +
|
|
290
|
-
String(t.text || "").slice(0, 80) +
|
|
291
|
-
'"' +
|
|
292
|
-
(t.detail ? ' detail="' + String(t.detail).slice(0, 40) + '"' : ""));
|
|
293
|
-
}
|
|
294
|
-
}
|
|
275
|
+
demoLog(prefix + " [" + ti + "] " + mark + (t.id ? " id=" + t.id : "") + ' text="' + String(t.text || "").slice(0, 80) + '"');
|
|
276
|
+
});
|
|
277
|
+
});
|
|
295
278
|
}
|
|
296
279
|
export function summarizeDevice(d) {
|
|
297
280
|
if (!d)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { WgPage } from "../types.js";
|
|
1
|
+
import type { StepperRefs, WgPage } from "../types.js";
|
|
2
|
+
import type { Pacing } from "./pacing.js";
|
|
2
3
|
import type { MemPage } from "../../engine/mem/mem.js";
|
|
3
|
-
export declare function instrumentInteractionHighlighting(page: WgPage, mem: MemPage, slowMo: number, pacing:
|
|
4
|
+
export declare function instrumentInteractionHighlighting(page: WgPage, mem: MemPage, slowMo: number, pacing: Pacing, stubBeforeRef: StepperRefs["stubBefore"], todoDockRef: StepperRefs["todoDock"], deviceRef: StepperRefs["device"]): void;
|
|
@@ -70,7 +70,7 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
70
70
|
const memTrack = { lastKeyName: null, at: 0 };
|
|
71
71
|
const originalGet = mem.get.bind(mem);
|
|
72
72
|
mem.get = (key) => {
|
|
73
|
-
memTrack.lastKeyName = key
|
|
73
|
+
memTrack.lastKeyName = key.name;
|
|
74
74
|
memTrack.at = Date.now();
|
|
75
75
|
return originalGet(key);
|
|
76
76
|
};
|
|
@@ -126,22 +126,22 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
126
126
|
await applyHighlightZoom(page, stub.selector, stub.zoom, stub.zoomOut);
|
|
127
127
|
}
|
|
128
128
|
demoHighlight({
|
|
129
|
-
selector: stub
|
|
129
|
+
selector: stub?.selector,
|
|
130
130
|
label: cap.label,
|
|
131
|
-
tone: cap.tone || (stub
|
|
132
|
-
color: stub
|
|
133
|
-
focus: !!(stub
|
|
134
|
-
zoom: stub
|
|
135
|
-
zoomOut: stub
|
|
136
|
-
gesture: stub
|
|
131
|
+
tone: cap.tone || (stub?.tone) || "planned",
|
|
132
|
+
color: stub?.color,
|
|
133
|
+
focus: !!(stub?.focus),
|
|
134
|
+
zoom: stub?.zoom,
|
|
135
|
+
zoomOut: stub?.zoomOut,
|
|
136
|
+
gesture: stub?.gesture,
|
|
137
137
|
weight: cap.weight,
|
|
138
138
|
size: cap.size,
|
|
139
139
|
}, "fill");
|
|
140
140
|
await showRing(page, box, cap.label, cap.tone, {
|
|
141
141
|
size: cap.size,
|
|
142
142
|
weight: cap.weight,
|
|
143
|
-
selector: stub
|
|
144
|
-
focus: !!(stub
|
|
143
|
+
selector: stub?.selector,
|
|
144
|
+
focus: !!(stub?.focus),
|
|
145
145
|
});
|
|
146
146
|
await dwellMatchedStub(page, locator, stubs, pacing);
|
|
147
147
|
await new Promise((res) => setTimeout(res, skipTheater() ? 0 : 200));
|
|
@@ -218,22 +218,22 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
218
218
|
await applyHighlightZoom(page, stub.selector, stub.zoom, stub.zoomOut);
|
|
219
219
|
}
|
|
220
220
|
demoHighlight({
|
|
221
|
-
selector: stub
|
|
221
|
+
selector: stub?.selector,
|
|
222
222
|
label: cap.label,
|
|
223
|
-
tone: cap.tone || (stub
|
|
224
|
-
color: stub
|
|
225
|
-
focus: !!(stub
|
|
226
|
-
zoom: stub
|
|
227
|
-
zoomOut: stub
|
|
228
|
-
gesture: stub
|
|
223
|
+
tone: cap.tone || (stub?.tone) || "planned",
|
|
224
|
+
color: stub?.color,
|
|
225
|
+
focus: !!(stub?.focus),
|
|
226
|
+
zoom: stub?.zoom,
|
|
227
|
+
zoomOut: stub?.zoomOut,
|
|
228
|
+
gesture: stub?.gesture,
|
|
229
229
|
weight: cap.weight,
|
|
230
230
|
size: cap.size,
|
|
231
231
|
}, "click");
|
|
232
232
|
await showRing(page, box, cap.label, cap.tone, {
|
|
233
233
|
size: cap.size,
|
|
234
234
|
weight: cap.weight,
|
|
235
|
-
selector: stub
|
|
236
|
-
focus: !!(stub
|
|
235
|
+
selector: stub?.selector,
|
|
236
|
+
focus: !!(stub?.focus),
|
|
237
237
|
});
|
|
238
238
|
await dwellMatchedStub(page, locator, stubs, pacing);
|
|
239
239
|
// "pop for a few seconds" - the user's own phrase, matching the
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Checkpoint } from "../../engine/checkpoint/checkpoint.js";
|
|
2
|
+
import type { DemoPace } from "../../engine/stub/pace.js";
|
|
3
|
+
import type { ResolvedHighlight } from "../../engine/stub/ring.js";
|
|
4
|
+
import type { TodoDockState } from "../../engine/stub/todos.js";
|
|
5
|
+
import type { Ref, WgPage } from "../types.js";
|
|
6
|
+
import { type PanelTodos, type StepPanelInfo } from "./step-panels.js";
|
|
7
|
+
/** The panel after a step: the Checkpoint it resolved to, the rings to cycle, and whether it was the last step. */
|
|
8
|
+
export interface AfterPanelInfo extends StepPanelInfo, PanelTodos {
|
|
9
|
+
result: Checkpoint<string>;
|
|
10
|
+
resultTag: string;
|
|
11
|
+
highlights: readonly ResolvedHighlight[];
|
|
12
|
+
gatesFast?: boolean | undefined;
|
|
13
|
+
isLast: boolean;
|
|
14
|
+
pace?: DemoPace | undefined;
|
|
15
|
+
todoDockRef?: Ref<TodoDockState | undefined> | undefined;
|
|
16
|
+
}
|
|
17
|
+
export declare function renderAfterStep(page: WgPage, info: AfterPanelInfo): Promise<void>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// The demo panel after a step: what it resolved to (pretty / JSON), its rings, and the Next gate.
|
|
2
|
+
import { ignorePageGone } from "../../engine/page-gone.js";
|
|
3
|
+
import { installOverlay } from "../overlay/overlay.js";
|
|
4
|
+
import { cycleHighlightRings } from "../overlay/rings.js";
|
|
5
|
+
import { miniStepLabel } from "./step-panels.js";
|
|
6
|
+
export async function renderAfterStep(page, info) {
|
|
7
|
+
await installOverlay(page, info.title, info.bannerUi, info.caption, info.networkTabVisible);
|
|
8
|
+
// Clear any tracker from a previous highlight before cycling through this
|
|
9
|
+
// step's own.
|
|
10
|
+
await page
|
|
11
|
+
.evaluate(() => {
|
|
12
|
+
if (window.__wgRingTrack) {
|
|
13
|
+
window.removeEventListener("resize", window.__wgRingTrack);
|
|
14
|
+
window.removeEventListener("scroll", window.__wgRingTrack, true);
|
|
15
|
+
window.__wgRingTrack = null;
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
.catch(ignorePageGone);
|
|
19
|
+
const highlights = info.highlights || [];
|
|
20
|
+
const gatesFast = !!info.gatesFast;
|
|
21
|
+
// Cycle through EVERY declared/recovered highlight in order, each shown
|
|
22
|
+
// long enough to actually register - "it highlights something [...] then
|
|
23
|
+
// it highlights something [else] and next," not just the first one.
|
|
24
|
+
// duration / fastMode on stubAfter (or flow fixtures) override the default
|
|
25
|
+
// 900ms / 200ms holds when set.
|
|
26
|
+
await cycleHighlightRings(page, highlights, gatesFast, {
|
|
27
|
+
pace: info.pace,
|
|
28
|
+
stepLabel: miniStepLabel(info),
|
|
29
|
+
todoDock: info.todoDock,
|
|
30
|
+
todos: info.todos,
|
|
31
|
+
todoSync: info.todoSync,
|
|
32
|
+
todoDockRef: info.todoDockRef,
|
|
33
|
+
// stubAfter already authored progress - do not re-index by ring 0..n
|
|
34
|
+
advanceTodos: false,
|
|
35
|
+
});
|
|
36
|
+
// After-ring advances may have moved the dock - surface latest for caller.
|
|
37
|
+
if (info.todoDockRef && info.todoDockRef.current) {
|
|
38
|
+
info.todoDock = info.todoDockRef.current;
|
|
39
|
+
}
|
|
40
|
+
const afterPayload = { ...info, stepLabel: miniStepLabel(info) };
|
|
41
|
+
await page
|
|
42
|
+
.evaluate((info) => {
|
|
43
|
+
// Reused in place - see renderBeforeStep's own comment on this.
|
|
44
|
+
let panel = __wgById("wg-panel");
|
|
45
|
+
const isNewPanel = !panel;
|
|
46
|
+
if (!panel) {
|
|
47
|
+
panel = document.createElement("div");
|
|
48
|
+
panel.id = "wg-panel";
|
|
49
|
+
}
|
|
50
|
+
const pct = Math.round(((info.index + 1) / info.total) * 100);
|
|
51
|
+
const heading = info.isLast
|
|
52
|
+
? "End of chain - " + info.total + " / " + info.total + " blocks covered - " + info.blockName + " done"
|
|
53
|
+
: "Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName + " done";
|
|
54
|
+
const buttonLabel = info.isLast ? "Finish" : "Next \u25B6";
|
|
55
|
+
const modulesClass = info.stepperMode === "full" ? "wg-modules-full" : "wg-modules-carousel";
|
|
56
|
+
const modules = info.allNames.map((name, idx) => {
|
|
57
|
+
const cls = idx <= info.moduleIndex ? "wg-mod-done" : "wg-mod-upcoming";
|
|
58
|
+
const desc = info.allDescriptions && info.allDescriptions[idx];
|
|
59
|
+
return __wgEl("span", { class: "wg-mod " + cls, title: desc || undefined }, String(name));
|
|
60
|
+
});
|
|
61
|
+
// QA-friendly by default ("LoginSuccess" -> "Login Success") - raw
|
|
62
|
+
// JSON is one click away for whoever actually wants __state.
|
|
63
|
+
const stateTag = info.result && info.result.__state ? info.result.__state : "";
|
|
64
|
+
const prettyText = stateTag
|
|
65
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
66
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2") || info.resultTag;
|
|
67
|
+
const pretty = window.__wgPretty !== false;
|
|
68
|
+
let autoNow = false;
|
|
69
|
+
try {
|
|
70
|
+
autoNow = localStorage.getItem("wg-autoplay") === "1";
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
/* private mode / blocked storage - defaults to manual */
|
|
74
|
+
}
|
|
75
|
+
const autoplay = __wgEl("input", { id: "wg-autoplay-cb", attrs: { type: "checkbox" } });
|
|
76
|
+
autoplay.checked = autoNow;
|
|
77
|
+
const episodes = info.allEpisodes && info.allEpisodes.length > 0
|
|
78
|
+
? __wgEl("div", { id: "wg-episodes" }, info.allEpisodes.map((e) => {
|
|
79
|
+
const cls = e.episodeNumber < (info.episodeNumber ?? 0) ? "wg-ep-done"
|
|
80
|
+
: e.episodeNumber === info.episodeNumber ? "wg-ep-current"
|
|
81
|
+
: "wg-ep-upcoming";
|
|
82
|
+
return __wgEl("span", { class: "wg-ep-tab " + cls }, "Episode " + e.episodeNumber + ": " + (e.episodeTitle || ""));
|
|
83
|
+
}))
|
|
84
|
+
: null;
|
|
85
|
+
const pace = info.paceBadge || info.paceLabel
|
|
86
|
+
? __wgEl("div", { class: "wg-pace", data: { paceKind: info.paceKind || "normal" } }, __wgEl("span", { class: "wg-pace-badge" }, info.paceBadge || "1x"), __wgEl("span", null, info.paceLabel || ""))
|
|
87
|
+
: null;
|
|
88
|
+
// Todos float in #wg-todo-dock via __wgSyncTodos, never in the panel.
|
|
89
|
+
__wgSet(panel, __wgEl("div", { id: "wg-progress" }, __wgEl("div", { id: "wg-progress-bar", style: "width:" + pct + "%" })), episodes, pace, __wgEl("div", { id: "wg-modules", class: modulesClass }, modules), __wgEl("h3", null, heading), __wgEl("div", { class: "wg-toggle" }, __wgEl("button", { class: "wg-toggle-btn" + (pretty ? " wg-active" : ""), data: { mode: "pretty" } }, "Pretty"), __wgEl("button", { class: "wg-toggle-btn" + (pretty ? "" : " wg-active"), data: { mode: "json" } }, "JSON")), __wgEl("div", { class: "wg-result wg-result-pretty", style: "display:" + (pretty ? "block" : "none") }, String(prettyText)), __wgEl("div", { class: "wg-result wg-result-json", style: "display:" + (pretty ? "none" : "block") }, String(info.resultTag)), __wgEl("div", { class: "wg-autoplay-row" }, __wgEl("label", null, autoplay, " Auto-advance")), __wgEl("div", { id: "wg-gate-manual", style: autoNow ? "display:none" : "" }, __wgEl("button", { id: "wg-run" }, buttonLabel)), __wgEl("div", { id: "wg-gate-auto", class: "wg-auto", style: autoNow ? "" : "display:none" }, "Auto-advancing..."));
|
|
90
|
+
if (isNewPanel) {
|
|
91
|
+
__wgAdd(panel);
|
|
92
|
+
requestAnimationFrame(() => panel.classList.add("wg-in"));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
panel.classList.add("wg-in");
|
|
96
|
+
}
|
|
97
|
+
if (window.__wgWirePanelChrome) {
|
|
98
|
+
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
99
|
+
stepLabel: info.stepLabel || "",
|
|
100
|
+
forceCollapsed: info.forceCollapsed === true ? true : undefined,
|
|
101
|
+
fastForward: !!info.fastForward,
|
|
102
|
+
isApi: !!info.isApi,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (window.__wgSyncTodos) {
|
|
106
|
+
const sync = info.todoSync || (info.todos && info.todos.length ? "set" : "keep");
|
|
107
|
+
// Prefer dock-only payload. Passing list:[] with a dock used to clear
|
|
108
|
+
// marks a frame later (empty-list clear path).
|
|
109
|
+
if (sync === "keep" && !info.todoDock) {
|
|
110
|
+
/* leave floating dock alone */
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const payload = {
|
|
114
|
+
sync: sync,
|
|
115
|
+
dock: info.todoDock || null,
|
|
116
|
+
pos: info.todoPos || null,
|
|
117
|
+
todoId: info.todoId || (info.todoDock && info.todoDock.id) || null,
|
|
118
|
+
};
|
|
119
|
+
if (!info.todoDock && info.todos && info.todos.length) {
|
|
120
|
+
payload.list = info.todos;
|
|
121
|
+
}
|
|
122
|
+
window.__wgSyncTodos(payload);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (window.__wgStampModal) {
|
|
126
|
+
window.__wgStampModal(panel, "panel", {
|
|
127
|
+
phase: "after",
|
|
128
|
+
step: info.index + 1,
|
|
129
|
+
total: info.total,
|
|
130
|
+
block: info.blockName || "",
|
|
131
|
+
ready: true,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
panel.querySelectorAll(".wg-toggle-btn").forEach((btn) => {
|
|
135
|
+
btn.addEventListener("click", () => {
|
|
136
|
+
const wantPretty = btn.getAttribute("data-mode") === "pretty";
|
|
137
|
+
window.__wgPretty = wantPretty;
|
|
138
|
+
panel.querySelectorAll(".wg-toggle-btn").forEach((b) => b.classList.remove("wg-active"));
|
|
139
|
+
btn.classList.add("wg-active");
|
|
140
|
+
panel.querySelector(".wg-result-pretty").style.display = wantPretty ? "block" : "none";
|
|
141
|
+
panel.querySelector(".wg-result-json").style.display = wantPretty ? "none" : "block";
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
const runBtn = __wgById("wg-run");
|
|
145
|
+
if (runBtn)
|
|
146
|
+
runBtn.addEventListener("click", () => window.__wgNext({}));
|
|
147
|
+
const cb = __wgById("wg-autoplay-cb");
|
|
148
|
+
if (cb) {
|
|
149
|
+
cb.addEventListener("change", () => {
|
|
150
|
+
try {
|
|
151
|
+
localStorage.setItem("wg-autoplay", cb.checked ? "1" : "0");
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
/* private mode / blocked storage - toggle still works this page */
|
|
155
|
+
}
|
|
156
|
+
const manual = __wgById("wg-gate-manual");
|
|
157
|
+
const auto = __wgById("wg-gate-auto");
|
|
158
|
+
if (manual)
|
|
159
|
+
manual.style.display = cb.checked ? "none" : "";
|
|
160
|
+
if (auto)
|
|
161
|
+
auto.style.display = cb.checked ? "" : "none";
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}, afterPayload)
|
|
165
|
+
.catch(ignorePageGone);
|
|
166
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WgPage } from "../types.js";
|
|
2
|
+
import { type PanelTodos, type StepPanelInfo } from "./step-panels.js";
|
|
3
|
+
/** The panel before a step: its description, the mem it reads (editable), and whether its episode just began. */
|
|
4
|
+
export interface BeforePanelInfo extends StepPanelInfo, PanelTodos {
|
|
5
|
+
description: string;
|
|
6
|
+
keys: readonly {
|
|
7
|
+
name: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}[];
|
|
10
|
+
justEnteredEpisode: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function renderBeforeStep(page: WgPage, info: BeforePanelInfo): Promise<void>;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// The demo panel before a step: episode and step chips, pace, the mem it reads (editable), and the Run gate.
|
|
2
|
+
import { envFlag, envString } from "../../engine/env.js";
|
|
3
|
+
import { ignorePageGone, ignoreTimeout } from "../../engine/page-gone.js";
|
|
4
|
+
import { installOverlay } from "../overlay/overlay.js";
|
|
5
|
+
import { miniStepLabel } from "./step-panels.js";
|
|
6
|
+
export async function renderBeforeStep(page, info) {
|
|
7
|
+
await installOverlay(page, info.title, info.bannerUi, info.caption, info.networkTabVisible);
|
|
8
|
+
// A ring left highlighting the PREVIOUS step's element (and its live
|
|
9
|
+
// resize/scroll tracker) shouldn't linger once a new step's own panel is
|
|
10
|
+
// up - only relevant when a Block's act() doesn't navigate away, since a
|
|
11
|
+
// real navigation already wipes document.documentElement's children.
|
|
12
|
+
await page
|
|
13
|
+
.evaluate(() => {
|
|
14
|
+
if (window.__wgRingTrack) {
|
|
15
|
+
window.removeEventListener("resize", window.__wgRingTrack);
|
|
16
|
+
window.removeEventListener("scroll", window.__wgRingTrack, true);
|
|
17
|
+
window.__wgRingTrack = null;
|
|
18
|
+
}
|
|
19
|
+
if (window.__wgHideRing)
|
|
20
|
+
window.__wgHideRing();
|
|
21
|
+
if (window.__wgHideCursor)
|
|
22
|
+
window.__wgHideCursor();
|
|
23
|
+
})
|
|
24
|
+
.catch(ignorePageGone);
|
|
25
|
+
// miniStepLabel / todosHtmlFromInfo are Node-only — browser evaluate has no closure.
|
|
26
|
+
const payload = { ...info, stepLabel: miniStepLabel(info) };
|
|
27
|
+
await page
|
|
28
|
+
.evaluate((info) => {
|
|
29
|
+
// Reused in place, not removed + recreated, every step - the old
|
|
30
|
+
// remove()-then-fade-back-in cycle was a real flash on every single
|
|
31
|
+
// transition (the user: "the appear and disappear... hurts eyes and
|
|
32
|
+
// dizzy"). Updating one persistent element's content has nothing to
|
|
33
|
+
// flash - it only ever fades in ONCE, the first time this page
|
|
34
|
+
// genuinely has no panel yet (a real navigation wiped the whole
|
|
35
|
+
// document, or this is the very first step).
|
|
36
|
+
let panel = __wgById("wg-panel");
|
|
37
|
+
const isNewPanel = !panel;
|
|
38
|
+
if (!panel) {
|
|
39
|
+
panel = document.createElement("div");
|
|
40
|
+
panel.id = "wg-panel";
|
|
41
|
+
}
|
|
42
|
+
const pct = Math.round((info.index / info.total) * 100);
|
|
43
|
+
// A real tab bar, not a single text line - every episode this chain
|
|
44
|
+
// touches, the current one reading as active (the user: "if episode 1 is
|
|
45
|
+
// active, the episode 2 tab is inactive"). Absent entirely for an ad
|
|
46
|
+
// hoc block chain with no named Flows.
|
|
47
|
+
const episodes = info.allEpisodes && info.allEpisodes.length > 0
|
|
48
|
+
? __wgEl("div", { id: "wg-episodes" }, info.allEpisodes.map((e) => {
|
|
49
|
+
const cls = e.episodeNumber < (info.episodeNumber ?? 0) ? "wg-ep-done"
|
|
50
|
+
: e.episodeNumber === info.episodeNumber ? "wg-ep-current"
|
|
51
|
+
: "wg-ep-upcoming";
|
|
52
|
+
// The gentle one-time glow only plays on the tab actually
|
|
53
|
+
// being entered right now, not on every render of it.
|
|
54
|
+
const enteredCls = info.justEnteredEpisode && e.episodeNumber === info.episodeNumber
|
|
55
|
+
? " wg-ep-entered"
|
|
56
|
+
: "";
|
|
57
|
+
return __wgEl("span", { class: "wg-ep-tab " + cls + enteredCls }, "Episode " + e.episodeNumber + ": " + (e.episodeTitle || ""));
|
|
58
|
+
}))
|
|
59
|
+
: null;
|
|
60
|
+
// Scoped to THIS episode's own blocks (info.allNames is already the
|
|
61
|
+
// episode-local subset the caller computed) - moduleIndex is this
|
|
62
|
+
// step's position WITHIN that subset, not the whole chain's index -
|
|
63
|
+
// "in episode 2 it shows 2nd to the last... it should start from the
|
|
64
|
+
// first block" (the user).
|
|
65
|
+
const modulesClass = info.stepperMode === "full" ? "wg-modules-full" : "wg-modules-carousel";
|
|
66
|
+
const modules = info.allNames.map((name, idx) => {
|
|
67
|
+
const cls = idx < info.moduleIndex ? "wg-mod-done" : idx === info.moduleIndex ? "wg-mod-current" : "wg-mod-upcoming";
|
|
68
|
+
const desc = info.allDescriptions && info.allDescriptions[idx];
|
|
69
|
+
return __wgEl("span", { class: "wg-mod " + cls, title: desc || undefined }, String(name));
|
|
70
|
+
});
|
|
71
|
+
const pace = info.paceBadge || info.paceLabel
|
|
72
|
+
? __wgEl("div", { class: "wg-pace", data: { paceKind: info.paceKind || "normal" } }, __wgEl("span", { class: "wg-pace-badge" }, info.paceBadge || "1x"), __wgEl("span", null, info.paceLabel || ""))
|
|
73
|
+
: null;
|
|
74
|
+
const keys = info.keys.length === 0
|
|
75
|
+
? [__wgEl("div", { class: "wg-key" }, "(no MemKeys required)")]
|
|
76
|
+
: info.keys.map((k) => {
|
|
77
|
+
const field = __wgEl("textarea", { data: { key: k.name }, attrs: { rows: 2 } });
|
|
78
|
+
field.value = k.value;
|
|
79
|
+
return __wgEl("div", { class: "wg-key" }, __wgEl("label", null, k.name), field, __wgEl("div", { class: "wg-key-pretty", data: { prettyFor: k.name } }));
|
|
80
|
+
});
|
|
81
|
+
let autoNow = false;
|
|
82
|
+
try {
|
|
83
|
+
autoNow = localStorage.getItem("wg-autoplay") === "1";
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
/* private mode / blocked storage - defaults to manual */
|
|
87
|
+
}
|
|
88
|
+
const autoplay = __wgEl("input", { id: "wg-autoplay-cb", attrs: { type: "checkbox" } });
|
|
89
|
+
autoplay.checked = autoNow;
|
|
90
|
+
// Todos render into floating #wg-todo-dock via __wgSyncTodos - never
|
|
91
|
+
// inside .wg-body (would vanish under --mini / Hide collapse).
|
|
92
|
+
__wgSet(panel, __wgEl("div", { id: "wg-progress" }, __wgEl("div", { id: "wg-progress-bar", style: "width:" + pct + "%" })), episodes, pace, __wgEl("div", { id: "wg-modules", class: modulesClass }, modules), __wgEl("h3", null, "Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName), info.description ? __wgEl("div", { class: "wg-narration" }, info.description) : null, keys, __wgEl("div", { class: "wg-autoplay-row" }, __wgEl("label", null, autoplay, " Auto-advance")), __wgEl("div", { id: "wg-gate-manual", style: autoNow ? "display:none" : "" }, __wgEl("button", { id: "wg-run" }, "Run this step \u25B6")), __wgEl("div", { id: "wg-gate-auto", class: "wg-auto", style: autoNow ? "" : "display:none" }, "Auto-advancing..."));
|
|
93
|
+
if (isNewPanel) {
|
|
94
|
+
__wgAdd(panel);
|
|
95
|
+
requestAnimationFrame(() => panel.classList.add("wg-in"));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
panel.classList.add("wg-in");
|
|
99
|
+
}
|
|
100
|
+
if (window.__wgWirePanelChrome) {
|
|
101
|
+
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
102
|
+
stepLabel: info.stepLabel || "",
|
|
103
|
+
forceCollapsed: info.forceCollapsed === true ? true : undefined,
|
|
104
|
+
fastForward: !!info.fastForward,
|
|
105
|
+
isApi: !!info.isApi,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (window.__wgSyncTodos) {
|
|
109
|
+
const sync = info.todoSync || (info.todos && info.todos.length ? "set" : "keep");
|
|
110
|
+
// Prefer dock-only payload. Passing list:[] with a dock used to clear
|
|
111
|
+
// marks a frame later (empty-list clear path).
|
|
112
|
+
if (sync === "keep" && !info.todoDock) {
|
|
113
|
+
/* leave floating dock alone */
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const payload = {
|
|
117
|
+
sync: sync,
|
|
118
|
+
dock: info.todoDock || null,
|
|
119
|
+
pos: info.todoPos || null,
|
|
120
|
+
todoId: info.todoId || (info.todoDock && info.todoDock.id) || null,
|
|
121
|
+
};
|
|
122
|
+
if (!info.todoDock && info.todos && info.todos.length) {
|
|
123
|
+
payload.list = info.todos;
|
|
124
|
+
}
|
|
125
|
+
window.__wgSyncTodos(payload);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (window.__wgStampModal) {
|
|
129
|
+
window.__wgStampModal(panel, "panel", {
|
|
130
|
+
phase: "before",
|
|
131
|
+
step: info.index + 1,
|
|
132
|
+
total: info.total,
|
|
133
|
+
block: info.blockName || "",
|
|
134
|
+
ready: true,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// Live, human-readable preview of what a MemKey's raw JSON will
|
|
138
|
+
// actually write - object fields become "Field: value" lines
|
|
139
|
+
// (camelCase split the same way state tags already are); a
|
|
140
|
+
// non-object payload (a plain string/number/array) is shown as-is.
|
|
141
|
+
// Hidden entirely in JSON mode - shares the SAME global toggle the
|
|
142
|
+
// result display's own Pretty/JSON buttons already set, not a
|
|
143
|
+
// second, separate preference.
|
|
144
|
+
const prettyMemValue = (raw) => {
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = JSON.parse(raw);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return [__wgEl("em", null, "(invalid JSON)")];
|
|
151
|
+
}
|
|
152
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
153
|
+
return [JSON.stringify(parsed)];
|
|
154
|
+
}
|
|
155
|
+
return Object.entries(parsed).map(([field, value]) => {
|
|
156
|
+
const label = field.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
157
|
+
return __wgEl("div", { class: "wg-key-pretty-row" }, __wgEl("span", { class: "wg-key-pretty-label" }, label + ":"), " " + String(value));
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
const applyKeyPretty = () => {
|
|
161
|
+
const prettyOn = window.__wgPretty !== false;
|
|
162
|
+
panel.querySelectorAll("textarea[data-key]").forEach((ta) => {
|
|
163
|
+
const previewEl = ta.parentElement?.querySelector(".wg-key-pretty");
|
|
164
|
+
if (!previewEl)
|
|
165
|
+
return;
|
|
166
|
+
previewEl.style.display = prettyOn ? "" : "none";
|
|
167
|
+
if (prettyOn)
|
|
168
|
+
__wgSet(previewEl, prettyMemValue(ta.value));
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
applyKeyPretty();
|
|
172
|
+
panel.querySelectorAll("textarea[data-key]").forEach((ta) => {
|
|
173
|
+
ta.addEventListener("input", applyKeyPretty);
|
|
174
|
+
});
|
|
175
|
+
const runBtn = __wgById("wg-run");
|
|
176
|
+
if (runBtn) {
|
|
177
|
+
runBtn.addEventListener("click", () => {
|
|
178
|
+
const edits = {};
|
|
179
|
+
panel.querySelectorAll("textarea[data-key]").forEach((el) => {
|
|
180
|
+
edits[el.getAttribute("data-key") ?? ""] = el.value;
|
|
181
|
+
});
|
|
182
|
+
window.__wgNext(edits);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// Live toggle - flips localStorage immediately so an in-flight gate()
|
|
186
|
+
// poll (on the Node side) picks it up within its next poll slice,
|
|
187
|
+
// without needing this whole panel to re-render. A manual click
|
|
188
|
+
// still always wins over an active autoplay wait, whichever the
|
|
189
|
+
// checkbox says - this is the "hybrid" control: autoplay is a
|
|
190
|
+
// default, not a lockout.
|
|
191
|
+
const cb = __wgById("wg-autoplay-cb");
|
|
192
|
+
if (cb) {
|
|
193
|
+
cb.addEventListener("change", () => {
|
|
194
|
+
try {
|
|
195
|
+
localStorage.setItem("wg-autoplay", cb.checked ? "1" : "0");
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
/* private mode / blocked storage - toggle still works this page */
|
|
199
|
+
}
|
|
200
|
+
const manual = __wgById("wg-gate-manual");
|
|
201
|
+
const auto = __wgById("wg-gate-auto");
|
|
202
|
+
if (manual)
|
|
203
|
+
manual.style.display = cb.checked ? "none" : "";
|
|
204
|
+
if (auto)
|
|
205
|
+
auto.style.display = cb.checked ? "" : "none";
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}, payload)
|
|
209
|
+
.catch(ignorePageGone);
|
|
210
|
+
if (envString("WAYGRAPH_PROVE_SHOT") || envFlag("WAYGRAPH_PROVE_EXIT")) {
|
|
211
|
+
// Default: prove once on first painted panel. PROVE_EVERY=1 re-checks
|
|
212
|
+
// every step (noisy; useful when hunting a mid-chain blank).
|
|
213
|
+
const proveEvery = envFlag("WAYGRAPH_PROVE_EVERY");
|
|
214
|
+
const already = globalThis.__wgProveDone;
|
|
215
|
+
if (!already || proveEvery || envFlag("WAYGRAPH_PROVE_EXIT")) {
|
|
216
|
+
await page.waitForTimeout(500).catch(ignoreTimeout);
|
|
217
|
+
const shot = envString("WAYGRAPH_PROVE_SHOT");
|
|
218
|
+
if (shot)
|
|
219
|
+
await page.screenshot({ path: shot }).catch(ignorePageGone);
|
|
220
|
+
const ok = await page
|
|
221
|
+
.evaluate(() => {
|
|
222
|
+
const beacons = typeof window.__wgOverlayBeacon === "function" ? window.__wgOverlayBeacon() : [];
|
|
223
|
+
const panel = beacons.find((b) => b.modal === "panel" && b.ready && b.visible);
|
|
224
|
+
const textOk = panel && panel.textLen >= 12;
|
|
225
|
+
const opacityOk = panel && Number(panel.opacity) > 0.5;
|
|
226
|
+
return {
|
|
227
|
+
ok: !!(panel && textOk && opacityOk),
|
|
228
|
+
beacons,
|
|
229
|
+
hasRun: !!__wgById("wg-run"),
|
|
230
|
+
readyAttr: __wgById("wg-panel")?.getAttribute("data-wg-ready") || null,
|
|
231
|
+
};
|
|
232
|
+
})
|
|
233
|
+
.catch((e) => ({ ok: false, reason: String(e instanceof Error ? e.message : e) }));
|
|
234
|
+
console.error("WAYGRAPH_PROVE " + JSON.stringify(ok));
|
|
235
|
+
globalThis.__wgProveDone = true;
|
|
236
|
+
if (envFlag("WAYGRAPH_PROVE_EXIT")) {
|
|
237
|
+
process.exit(ok && ok.ok ? 0 : 2);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|