waygraph 0.15.44 → 0.15.46
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/analysis/coverage-gap.d.ts +1 -1
- package/dist/analysis/coverage-gap.js +1 -1
- package/dist/analysis/graph.js +1 -1
- package/dist/auto-session/helpers.d.ts +2 -2
- package/dist/auto-session/session.js +2 -2
- package/dist/cli/usage.d.ts +1 -1
- package/dist/commands/session.js +5 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/pilot-overlay/fixtures.js +20 -45
- package/dist/pilot-overlay/shell.js +7 -1
- package/dist/runner/inpage/core.d.ts +4 -0
- package/dist/runner/inpage/core.js +76 -53
- package/dist/runner/rings.js +49 -0
- package/dist/session/auto-explore-run.d.ts +37 -0
- package/dist/session/auto-explore-run.js +670 -0
- package/dist/session/auto-explore.d.ts +57 -0
- package/dist/session/auto-explore.js +376 -0
- package/dist/session/auto-session-ipc.d.ts +150 -0
- package/dist/session/auto-session-ipc.js +499 -0
- package/dist/session/block-inject.d.ts +21 -0
- package/dist/session/block-inject.js +97 -0
- package/dist/session/browser.d.ts +15 -0
- package/dist/session/browser.js +29 -0
- package/dist/session/overlay-beacon.d.ts +44 -0
- package/dist/session/overlay-beacon.js +85 -0
- package/dist/session/pilot.d.ts +54 -0
- package/dist/session/pilot.js +80 -0
- package/dist/traverse/run.js +2 -2
- package/dist/ui/components/ring.d.ts +0 -2
- package/dist/ui/components/ring.js +4 -19
- package/dist/ui/overlay.css +39 -65
- package/examples/saucedemo/.waygraph-auto/00b0c55c.log +22 -0
- package/examples/saucedemo/.waygraph-auto/00e5d037.log +5 -0
- package/examples/saucedemo/.waygraph-auto/015be8f6.log +6 -0
- package/examples/saucedemo/.waygraph-auto/026e188e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/05d76fc3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/07845ed1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0c19e232.log +5 -0
- package/examples/saucedemo/.waygraph-auto/1122c13c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/20e91af6.log +5 -0
- package/examples/saucedemo/.waygraph-auto/222d1d09.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2b9b56fc.log +20 -0
- package/examples/saucedemo/.waygraph-auto/2e6bc35e.log +6 -0
- package/examples/saucedemo/.waygraph-auto/30a5c848.log +20 -0
- package/examples/saucedemo/.waygraph-auto/33a50dc0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3a208bb8.log +20 -0
- package/examples/saucedemo/.waygraph-auto/3e3c0f3b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/432d09e3.log +22 -0
- package/examples/saucedemo/.waygraph-auto/47247959.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4cebc228.log +20 -0
- package/examples/saucedemo/.waygraph-auto/625e7f65.log +5 -0
- package/examples/saucedemo/.waygraph-auto/756fd326.log +20 -0
- package/examples/saucedemo/.waygraph-auto/78043767.log +20 -0
- package/examples/saucedemo/.waygraph-auto/7e8a6b62.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7fdd47ee.log +2 -0
- package/examples/saucedemo/.waygraph-auto/8be93021.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8e12e34f.log +22 -0
- package/examples/saucedemo/.waygraph-auto/976394cd.log +20 -0
- package/examples/saucedemo/.waygraph-auto/9d827954.log +20 -0
- package/examples/saucedemo/.waygraph-auto/a4f8d355.log +20 -0
- package/examples/saucedemo/.waygraph-auto/aa7323f8.log +20 -0
- package/examples/saucedemo/.waygraph-auto/ad0bfad9.log +5 -0
- package/examples/saucedemo/.waygraph-auto/af2fae12.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b0752c49.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b14811d7.log +6 -0
- package/examples/saucedemo/.waygraph-auto/c8987b67.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c9d76e32.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cc989184.log +20 -0
- package/examples/saucedemo/.waygraph-auto/de8cb83d.log +6 -0
- package/examples/saucedemo/.waygraph-auto/e5127c03.log +22 -0
- package/package.json +1 -1
- package/templates/agents/waygraph-author.agent.md +24 -51
- package/templates/agents/waygraph-planner.agent.md +12 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BlockEntry } from "../auto-explore.js";
|
|
1
|
+
import type { BlockEntry } from "../session/auto-explore.js";
|
|
2
2
|
/** Collect selector strings from NavClick blocks and Block/*Sel source files. */
|
|
3
3
|
export declare function collectKnownInteractionSelectors(projectDir: string, library: {
|
|
4
4
|
navBlocks: BlockEntry[];
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
-
import { exploreRoots } from "../block-inject.js";
|
|
8
|
+
import { exploreRoots } from "../session/block-inject.js";
|
|
9
9
|
const SELECTOR_LITERAL = /(?:locator|visible|click|fill|press|selector|getByRole)\(\s*['"`]([^'"`]+)['"`]/g;
|
|
10
10
|
const HASH_ID = /#([a-zA-Z][\w-]*)/g;
|
|
11
11
|
const DATA_TEST = /\[data-test(?:-id)?(?:=["'`][^"'`]+["'`])?\]/g;
|
package/dist/analysis/graph.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { join, dirname, relative, resolve } from "node:path";
|
|
3
3
|
import { matchBlocksSelect, } from "../blocks-select.js";
|
|
4
|
-
import { exploreRoots, injectTaggedFile } from "../block-inject.js";
|
|
4
|
+
import { exploreRoots, injectTaggedFile } from "../session/block-inject.js";
|
|
5
5
|
/**
|
|
6
6
|
* Renders a `WaygraphGraph` as Mermaid `stateDiagram-v2` text - paste
|
|
7
7
|
* straight into a `.md` file's ```mermaid fence or a live editor. `"*"`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StubPhaseResult } from "../highlights.js";
|
|
2
|
-
import type { BlockEntry, ExploreMenu } from "../auto-explore.js";
|
|
3
|
-
import type { PickResult } from "../auto-explore-run.js";
|
|
2
|
+
import type { BlockEntry, ExploreMenu } from "../session/auto-explore.js";
|
|
3
|
+
import type { PickResult } from "../session/auto-explore-run.js";
|
|
4
4
|
/** True when a stub-phase result actually carries authored content worth keeping. */
|
|
5
5
|
export declare function stubPhaseHasContent(r: StubPhaseResult): boolean;
|
|
6
6
|
export interface SessionSnapshotEdge {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Split out of the former 1,078-line auto-session.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
2
|
import { CONSOLE_LOG_MAX_ENTRIES, FULL_MODE_DEFAULT_DEPTH, FULL_MODE_MAX_NODES, FULL_MODE_MAX_TEXT_LENGTH, TRACE_MAX_STEPS, buildSessionSnapshot, parsePick, stubFilePath, stubPhaseHasContent, walkFullDom } from "./helpers.js";
|
|
3
3
|
import { instrumentPilotActions, installPersistentPilotOverlay, showPilotActivity, showPilotFixtures, showPilotVision, phaseToOverlayFixtures, describeOverlayFixtures, updatePilotOverlay } from "../pilot-overlay.js";
|
|
4
|
-
import { buildExploreContext, buildExploreMenu } from "../auto-explore.js";
|
|
4
|
+
import { buildExploreContext, buildExploreMenu } from "../session/auto-explore.js";
|
|
5
5
|
import { MemPage } from "../mem-page.js";
|
|
6
6
|
import { Engine } from "../engine.js";
|
|
7
|
-
import { detectHere, ensureLivePage, ensureMem, resolveBaseUrl, runOneBlock, seedDefaultMem } from "../auto-explore-run.js";
|
|
7
|
+
import { detectHere, ensureLivePage, ensureMem, resolveBaseUrl, runOneBlock, seedDefaultMem } from "../session/auto-explore-run.js";
|
|
8
8
|
import { collectKnownInteractionSelectors, unmappedInteractionsPageScript } from "../analysis/coverage-gap.js";
|
|
9
9
|
import { runStubPhase } from "../highlights.js";
|
|
10
10
|
import { verboseLog } from "../verbose-log.js";
|
package/dist/cli/usage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionMeta } from "../browser.js";
|
|
1
|
+
import type { SessionMeta } from "../session/browser.js";
|
|
2
2
|
export declare function printBrowserUsage(): void;
|
|
3
3
|
export declare function printBrowserSessionsList(sessions: SessionMeta[], projectDir: string): void;
|
|
4
4
|
export declare function usage(): void;
|
package/dist/commands/session.js
CHANGED
|
@@ -4,14 +4,14 @@ import { applyRunFlags, looksLikeFlowFileRef, parseRunFlags, resolveBaseUrl } fr
|
|
|
4
4
|
import { runChain } from "../cli/run-chain.js";
|
|
5
5
|
import { runChainAuto } from "./check.js";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
|
-
import { browserStart, listBrowserSessions, stopAllBrowserSessions, stopBrowserSession } from "../browser.js";
|
|
7
|
+
import { browserStart, listBrowserSessions, stopAllBrowserSessions, stopBrowserSession } from "../session/browser.js";
|
|
8
8
|
import { existsSync, statSync } from "node:fs";
|
|
9
|
-
import { resolveInjectRoots } from "../block-inject.js";
|
|
10
|
-
import { requestSession, resolveSessionMeta, runAttachLoop, runAutoServeCommand, spawnDetachedSession } from "../auto-session-ipc.js";
|
|
11
|
-
import { pilotAttach, pilotStart } from "../pilot.js";
|
|
9
|
+
import { resolveInjectRoots } from "../session/block-inject.js";
|
|
10
|
+
import { requestSession, resolveSessionMeta, runAttachLoop, runAutoServeCommand, spawnDetachedSession } from "../session/auto-session-ipc.js";
|
|
11
|
+
import { pilotAttach, pilotStart } from "../session/pilot.js";
|
|
12
12
|
import { parseHighlightShorthand } from "../highlights/shorthand.js";
|
|
13
13
|
import { isFileSelectToken, parseBlocksSelect } from "../blocks-select.js";
|
|
14
|
-
import { runAutoExplore } from "../auto-explore-run.js";
|
|
14
|
+
import { runAutoExplore } from "../session/auto-explore-run.js";
|
|
15
15
|
import { discoverGraph, findOrphanBlocks, toMermaid } from "../analysis/graph.js";
|
|
16
16
|
export async function sessionCase(args, command) {
|
|
17
17
|
if (command === "browser") {
|
package/dist/index.d.ts
CHANGED
|
@@ -21,9 +21,9 @@ export { runTraverse } from "./traverse/run.js";
|
|
|
21
21
|
export type { TraverseOptions, TraverseSessionMode, TraverseWorkerResult, } from "./traverse/run.js";
|
|
22
22
|
export { buildCoverageReport, collectGraphEdgeKeys, defaultCoverageOutPath, formatCoverageLine, normalizeHitKey, parseMinEdgeCoverage, writeCoverageReport, } from "./traverse/coverage.js";
|
|
23
23
|
export type { TraverseCoverageReport } from "./traverse/coverage.js";
|
|
24
|
-
export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL, readWgOverlayBeacon, readWgOverlayBeaconInPage, assertWgOverlayReady, } from "./overlay-beacon.js";
|
|
25
|
-
export type { WgModalKind, WgBeaconRow } from "./overlay-beacon.js";
|
|
24
|
+
export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL, readWgOverlayBeacon, readWgOverlayBeaconInPage, assertWgOverlayReady, } from "./session/overlay-beacon.js";
|
|
25
|
+
export type { WgModalKind, WgBeaconRow } from "./session/overlay-beacon.js";
|
|
26
26
|
export { AutoSession, stubFilePath } from "./auto-session.js";
|
|
27
27
|
export type { AutoSessionInit, SessionSnapshot, SessionSnapshotEdge, SessionSnapshotSection, ApplyPickResult, ApplyPathResult, TraceStep, ConsoleLogEntry, StorageSnapshot, ServiceWorkerRegistrationInfo, CookieInfo, StubFileKind, } from "./auto-session.js";
|
|
28
|
-
export { pilotStart } from "./pilot.js";
|
|
29
|
-
export type { PilotStartResult } from "./pilot.js";
|
|
28
|
+
export { pilotStart } from "./session/pilot.js";
|
|
29
|
+
export type { PilotStartResult } from "./session/pilot.js";
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,6 @@ export { isFileSelectToken, parseBlocksSelect, matchBlocksSelect, globToRegExp,
|
|
|
11
11
|
export { EdgeLeaseCoordinator } from "./traverse/lease.js";
|
|
12
12
|
export { runTraverse } from "./traverse/run.js";
|
|
13
13
|
export { buildCoverageReport, collectGraphEdgeKeys, defaultCoverageOutPath, formatCoverageLine, normalizeHitKey, parseMinEdgeCoverage, writeCoverageReport, } from "./traverse/coverage.js";
|
|
14
|
-
export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL, readWgOverlayBeacon, readWgOverlayBeaconInPage, assertWgOverlayReady, } from "./overlay-beacon.js";
|
|
14
|
+
export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL, readWgOverlayBeacon, readWgOverlayBeaconInPage, assertWgOverlayReady, } from "./session/overlay-beacon.js";
|
|
15
15
|
export { AutoSession, stubFilePath } from "./auto-session.js";
|
|
16
|
-
export { pilotStart } from "./pilot.js";
|
|
16
|
+
export { pilotStart } from "./session/pilot.js";
|
|
@@ -188,7 +188,7 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
188
188
|
};
|
|
189
189
|
w.__wgPilotFxZoomOutOnHide = zoomOut;
|
|
190
190
|
const clearFx = () => {
|
|
191
|
-
__wgQA("
|
|
191
|
+
__wgQA('[id^="wg-fx-ring-"]').forEach((el) => el.remove());
|
|
192
192
|
__wgById("wg-pilot-fx-todos")?.remove();
|
|
193
193
|
clearFocus();
|
|
194
194
|
if (w.__wgPilotFxZoomOutOnHide !== false || clearAll)
|
|
@@ -205,59 +205,34 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
205
205
|
const missing = [];
|
|
206
206
|
let painted = 0;
|
|
207
207
|
let focusBox = null;
|
|
208
|
-
|
|
208
|
+
// Paint through the SAME shared ring primitive the demo/auto singleton ring uses
|
|
209
|
+
// (window.__wgPaintRingAt, installed by runner/inpage/core.js's installCore - see
|
|
210
|
+
// ensureInstalled) - one ring implementation, not a separate DOM-building copy here.
|
|
211
|
+
rings.forEach((ring, i) => {
|
|
209
212
|
const el = document.querySelector(ring.selector);
|
|
210
213
|
if (!el) {
|
|
211
214
|
missing.push(ring.selector);
|
|
212
|
-
|
|
215
|
+
return;
|
|
213
216
|
}
|
|
214
217
|
const rect = el.getBoundingClientRect();
|
|
215
218
|
if (rect.width === 0 && rect.height === 0) {
|
|
216
219
|
missing.push(ring.selector);
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
const pad = ring.size === "sm" ? 3 : ring.size === "lg" ? 10 : 6;
|
|
220
|
-
const ringEl = document.createElement("div");
|
|
221
|
-
ringEl.className = "wg-pilot-fx-ring";
|
|
222
|
-
ringEl.dataset.tone = ring.tone;
|
|
223
|
-
ringEl.dataset.size = ring.size;
|
|
224
|
-
ringEl.style.left = `${rect.left - pad}px`;
|
|
225
|
-
ringEl.style.top = `${rect.top - pad}px`;
|
|
226
|
-
ringEl.style.width = `${Math.max(4, rect.width + pad * 2)}px`;
|
|
227
|
-
ringEl.style.height = `${Math.max(4, rect.height + pad * 2)}px`;
|
|
228
|
-
ringEl.style.opacity = "1";
|
|
229
|
-
const labelEl = document.createElement("div");
|
|
230
|
-
labelEl.className = "wg-pilot-fx-label";
|
|
231
|
-
labelEl.dataset.tone = ring.tone;
|
|
232
|
-
labelEl.dataset.size = ring.size;
|
|
233
|
-
labelEl.dataset.weight = ring.weight;
|
|
234
|
-
labelEl.textContent = ring.label;
|
|
235
|
-
labelEl.style.opacity = "1";
|
|
236
|
-
if (ring.color) {
|
|
237
|
-
labelEl.style.color = ring.color;
|
|
220
|
+
return;
|
|
238
221
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
labelTop = 6;
|
|
249
|
-
if (labelLeft + lw > window.innerWidth - 6) {
|
|
250
|
-
labelLeft = Math.max(6, window.innerWidth - 6 - lw);
|
|
222
|
+
const box = { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
|
|
223
|
+
const ringId = `wg-fx-ring-${i}`;
|
|
224
|
+
const labelId = `wg-fx-ring-${i}-label`;
|
|
225
|
+
if (window.__wgPaintRingAt) {
|
|
226
|
+
window.__wgPaintRingAt(ringId, labelId, box, ring.label, ring.tone, {
|
|
227
|
+
size: ring.size,
|
|
228
|
+
weight: ring.weight,
|
|
229
|
+
color: ring.color,
|
|
230
|
+
});
|
|
251
231
|
}
|
|
252
|
-
if (labelLeft < 6)
|
|
253
|
-
labelLeft = 6;
|
|
254
|
-
labelEl.style.left = `${labelLeft}px`;
|
|
255
|
-
labelEl.style.top = `${labelTop}px`;
|
|
256
232
|
painted += 1;
|
|
257
|
-
if (ring.focus)
|
|
258
|
-
focusBox =
|
|
259
|
-
|
|
260
|
-
}
|
|
233
|
+
if (ring.focus)
|
|
234
|
+
focusBox = box;
|
|
235
|
+
});
|
|
261
236
|
// Real TodoDockState groups (same shape/builder the demo runner uses) - a group's own
|
|
262
237
|
// style (sequential/checklist/bullets) and its own done/current flags drive rendering here,
|
|
263
238
|
// not a re-derived index over a flattened string list.
|
|
@@ -324,7 +299,7 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
324
299
|
}
|
|
325
300
|
// Collision flip: if a painted ring intersects the dock, flip side once.
|
|
326
301
|
if (dockEl && todoUi.collision !== false && painted > 0) {
|
|
327
|
-
const firstRing = __wgQ("
|
|
302
|
+
const firstRing = __wgQ('[id^="wg-fx-ring-"]:not([id$="-label"])');
|
|
328
303
|
if (firstRing) {
|
|
329
304
|
const rr = firstRing.getBoundingClientRect();
|
|
330
305
|
const dr = dockEl.getBoundingClientRect();
|
|
@@ -62,7 +62,8 @@ const OVERLAY_CSS = `
|
|
|
62
62
|
opacity: 0; transform: translateY(4px); transition: opacity 0.15s, transform 0.15s;
|
|
63
63
|
}
|
|
64
64
|
#wg-pilot-activity.wg-pilot-toast-show { opacity: 1; transform: translateY(0); }
|
|
65
|
-
/* Agent fixture rings (.wg-
|
|
65
|
+
/* Agent fixture rings (painted via the shared .wg-ring-el primitive, see ui/css/ring.css and
|
|
66
|
+
runner/inpage/core.js's __wgPaintRingAt), #wg-pilot-fx-todos, #wg-ring/#wg-ring-label and
|
|
66
67
|
#wg-banner all come from the ONE shared bundle ensureShadowRoot installs (ui/css/*.css) - not
|
|
67
68
|
redefined here. */
|
|
68
69
|
/* Spotlight (demo focus:true) - dim page, cutout around target. */
|
|
@@ -149,6 +150,11 @@ export async function installPersistentPilotOverlay(context) {
|
|
|
149
150
|
export async function ensureInstalled(page) {
|
|
150
151
|
await ensureShadowRoot(page);
|
|
151
152
|
await page.evaluate(installPilotOverlayShell, OVERLAY_CSS).catch(() => { });
|
|
153
|
+
// The shared ring primitive (__wgEnsureRingEl/__wgPaintRingAt) - so Pilot's fixture rings paint
|
|
154
|
+
// through the SAME implementation the demo/auto singleton ring uses (see ui/css/ring.css / this
|
|
155
|
+
// file's own header comment on redundancy), not a separate DOM-building copy.
|
|
156
|
+
const { installCore } = await import("../runner/inpage/core.js");
|
|
157
|
+
await page.evaluate(installCore, {}).catch(() => { });
|
|
152
158
|
// Device toast/chip CSS (runner/overlay-css.js's RUNNER_EXTRA_CSS) - same rules the demo runner
|
|
153
159
|
// uses, reused here (not re-authored) so a device fixture looks identical on Pilot.
|
|
154
160
|
const { RUNNER_EXTRA_CSS } = await import("../runner/overlay-css.js");
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** In-page installer (page.evaluate target) - see core.js's own header. Installs the shared ring
|
|
2
|
+
* primitive (__wgEnsureRingEl/__wgPaintRingAt/__wgHideRingAt), cursor, click-pulse, focus veil,
|
|
3
|
+
* and the #wg-ring singleton every surface's "current action" ring uses. */
|
|
4
|
+
export function installCore(args: Record<string, unknown>): void;
|
|
@@ -19,65 +19,37 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
|
|
|
19
19
|
} catch {
|
|
20
20
|
/* private mode / blocked storage - falls back to manual gating */
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
if (!__wgById("wg-cursor")) {
|
|
33
|
-
const cursor = document.createElement("div");
|
|
34
|
-
cursor.id = "wg-cursor";
|
|
35
|
-
// Dark fill + white stroke, same as help-center-clip-engine's own
|
|
36
|
-
// #clip-cursor - visible against any page background, light or
|
|
37
|
-
// dark, unlike a plain solid-white shape.
|
|
38
|
-
cursor.innerHTML =
|
|
39
|
-
"<svg viewBox='0 0 32 32' width='24' height='24'>" +
|
|
40
|
-
"<path fill='#0C0C1A' stroke='#fff' stroke-width='1.4' stroke-linejoin='round' " +
|
|
41
|
-
"d='M6 3.5l1.4 22.5 5.8-5.4 4.2 9.4 3.6-1.6-4.2-9.2H26z'/></svg>";
|
|
42
|
-
__wgAdd(cursor);
|
|
43
|
-
}
|
|
44
|
-
if (!__wgById("wg-click-pulse")) {
|
|
45
|
-
const pulse = document.createElement("div");
|
|
46
|
-
pulse.id = "wg-click-pulse";
|
|
47
|
-
__wgAdd(pulse);
|
|
48
|
-
}
|
|
49
|
-
window.__wgMoveCursorTo = (x, y, ms, instant) => {
|
|
50
|
-
const cursor = __wgById("wg-cursor");
|
|
51
|
-
if (!cursor) return;
|
|
52
|
-
cursor.style.setProperty("--wg-cursor-ms", (ms || 600) + "ms");
|
|
53
|
-
if (instant) {
|
|
54
|
-
const prev = cursor.style.transition;
|
|
55
|
-
cursor.style.transition = "none";
|
|
56
|
-
cursor.style.transform = "translate(" + x + "px," + y + "px)";
|
|
57
|
-
void cursor.offsetWidth;
|
|
58
|
-
cursor.style.transition = prev || "";
|
|
59
|
-
} else {
|
|
60
|
-
cursor.style.transform = "translate(" + x + "px," + y + "px)";
|
|
22
|
+
// The one shared ring primitive (ui/css/ring.css) - #wg-ring/#wg-ring-label is just this
|
|
23
|
+
// surface's OWN ring instance, found by id like any other (see __wgEnsureRingEl below).
|
|
24
|
+
window.__wgEnsureRingEl = (ringId, labelId) => {
|
|
25
|
+
let ring = __wgById(ringId);
|
|
26
|
+
if (!ring) {
|
|
27
|
+
ring = document.createElement("div");
|
|
28
|
+
ring.id = ringId;
|
|
29
|
+
ring.className = "wg-ring-el";
|
|
30
|
+
__wgAdd(ring);
|
|
61
31
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
32
|
+
let label = __wgById(labelId);
|
|
33
|
+
if (!label) {
|
|
34
|
+
label = document.createElement("div");
|
|
35
|
+
label.id = labelId;
|
|
36
|
+
label.className = "wg-ring-el-label";
|
|
37
|
+
__wgAdd(label);
|
|
38
|
+
}
|
|
39
|
+
return [ring, label];
|
|
67
40
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const ringLabel =
|
|
71
|
-
if (!
|
|
41
|
+
/** Bare positioning only - no collision/follow/focus-veil (those are #wg-ring's own extras, see __wgPositionRing). */
|
|
42
|
+
window.__wgPaintRingAt = (ringId, labelId, box, label, tone, style) => {
|
|
43
|
+
const [ring, ringLabel] = window.__wgEnsureRingEl(ringId, labelId);
|
|
44
|
+
if (!box) return null;
|
|
72
45
|
const raw = (tone || "planned") + "";
|
|
73
46
|
const t =
|
|
74
|
-
raw === "auto" || raw === "info" || raw === "warning" || raw === "danger" || raw === "success"
|
|
47
|
+
raw === "auto" || raw === "info" || raw === "warning" || raw === "danger" || raw === "success" || raw === "orange"
|
|
75
48
|
? raw
|
|
76
49
|
: "planned";
|
|
77
50
|
const st = style && typeof style === "object" ? style : {};
|
|
78
51
|
const sizeRaw = (st.size || "md") + "";
|
|
79
|
-
const size =
|
|
80
|
-
sizeRaw === "sm" || sizeRaw === "lg" ? sizeRaw : "md";
|
|
52
|
+
const size = sizeRaw === "sm" || sizeRaw === "lg" ? sizeRaw : "md";
|
|
81
53
|
const weightRaw = (st.weight || "normal") + "";
|
|
82
54
|
const weight = weightRaw === "bold" ? "bold" : "normal";
|
|
83
55
|
ring.dataset.tone = t;
|
|
@@ -85,12 +57,12 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
|
|
|
85
57
|
ring.dataset.size = size;
|
|
86
58
|
ringLabel.dataset.size = size;
|
|
87
59
|
ringLabel.dataset.weight = weight;
|
|
60
|
+
if (st.color) ringLabel.style.color = st.color;
|
|
61
|
+
else ringLabel.style.removeProperty("color");
|
|
88
62
|
const pad = size === "sm" ? 3 : size === "lg" ? 10 : 6;
|
|
89
63
|
const margin = 6;
|
|
90
64
|
const vw = window.innerWidth;
|
|
91
65
|
const vh = window.innerHeight;
|
|
92
|
-
// Pin ring EXACTLY to the element - never clamp the ring away from
|
|
93
|
-
// the target (that looked "strapped on" the viewport).
|
|
94
66
|
const left = box.x - pad;
|
|
95
67
|
const top = box.y - pad;
|
|
96
68
|
const width = Math.max(4, box.width + pad * 2);
|
|
@@ -112,6 +84,57 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
|
|
|
112
84
|
if (labelLeft < margin) labelLeft = margin;
|
|
113
85
|
ringLabel.style.left = labelLeft + "px";
|
|
114
86
|
ringLabel.style.top = labelTop + "px";
|
|
87
|
+
return [ring, ringLabel];
|
|
88
|
+
};
|
|
89
|
+
window.__wgHideRingAt = (ringId, labelId) => {
|
|
90
|
+
const ring = __wgById(ringId);
|
|
91
|
+
const label = __wgById(labelId);
|
|
92
|
+
if (ring) ring.style.opacity = "0";
|
|
93
|
+
if (label) label.style.opacity = "0";
|
|
94
|
+
};
|
|
95
|
+
window.__wgEnsureRingEl("wg-ring", "wg-ring-label");
|
|
96
|
+
if (!__wgById("wg-cursor")) {
|
|
97
|
+
const cursor = document.createElement("div");
|
|
98
|
+
cursor.id = "wg-cursor";
|
|
99
|
+
// Dark fill + white stroke, same as help-center-clip-engine's own
|
|
100
|
+
// #clip-cursor - visible against any page background, light or
|
|
101
|
+
// dark, unlike a plain solid-white shape.
|
|
102
|
+
cursor.innerHTML =
|
|
103
|
+
"<svg viewBox='0 0 32 32' width='24' height='24'>" +
|
|
104
|
+
"<path fill='#0C0C1A' stroke='#fff' stroke-width='1.4' stroke-linejoin='round' " +
|
|
105
|
+
"d='M6 3.5l1.4 22.5 5.8-5.4 4.2 9.4 3.6-1.6-4.2-9.2H26z'/></svg>";
|
|
106
|
+
__wgAdd(cursor);
|
|
107
|
+
}
|
|
108
|
+
if (!__wgById("wg-click-pulse")) {
|
|
109
|
+
const pulse = document.createElement("div");
|
|
110
|
+
pulse.id = "wg-click-pulse";
|
|
111
|
+
__wgAdd(pulse);
|
|
112
|
+
}
|
|
113
|
+
window.__wgMoveCursorTo = (x, y, ms, instant) => {
|
|
114
|
+
const cursor = __wgById("wg-cursor");
|
|
115
|
+
if (!cursor) return;
|
|
116
|
+
cursor.style.setProperty("--wg-cursor-ms", (ms || 600) + "ms");
|
|
117
|
+
if (instant) {
|
|
118
|
+
const prev = cursor.style.transition;
|
|
119
|
+
cursor.style.transition = "none";
|
|
120
|
+
cursor.style.transform = "translate(" + x + "px," + y + "px)";
|
|
121
|
+
void cursor.offsetWidth;
|
|
122
|
+
cursor.style.transition = prev || "";
|
|
123
|
+
} else {
|
|
124
|
+
cursor.style.transform = "translate(" + x + "px," + y + "px)";
|
|
125
|
+
}
|
|
126
|
+
cursor.style.opacity = "1";
|
|
127
|
+
};
|
|
128
|
+
window.__wgHideCursor = () => {
|
|
129
|
+
const cursor = __wgById("wg-cursor");
|
|
130
|
+
if (cursor) cursor.style.opacity = "0";
|
|
131
|
+
};
|
|
132
|
+
// #wg-ring's own extras on top of the shared __wgPaintRingAt primitive: todo/banner
|
|
133
|
+
// collision avoidance only makes sense for the ONE "current action" ring, not Pilot's
|
|
134
|
+
// several independent fixture rings - kept here, not pushed down into the shared painter.
|
|
135
|
+
window.__wgPositionRing = (box, label, tone, style) => {
|
|
136
|
+
if (!box) return;
|
|
137
|
+
window.__wgPaintRingAt("wg-ring", "wg-ring-label", box, label, tone, style);
|
|
115
138
|
if (window.__wgTodosSetBehind) window.__wgTodosSetBehind(true);
|
|
116
139
|
if (window.__wgTodosAvoidRingCollision) window.__wgTodosAvoidRingCollision(box);
|
|
117
140
|
if (window.__wgBannerAvoidRing) window.__wgBannerAvoidRing(box);
|
package/dist/runner/rings.js
CHANGED
|
@@ -363,6 +363,55 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Paint a NAMED ring instance (ui/css/ring.css's shared `.wg-ring-el`/`.wg-ring-el-label`) at a
|
|
368
|
+
* known viewport box - the primitive both the demo/auto singleton (`showRing`, always "wg-ring")
|
|
369
|
+
* and Pilot's several simultaneous fixture rings (their own ids) paint through, so there is one
|
|
370
|
+
* ring-rendering implementation, not two. No collision/follow/focus - those are `#wg-ring`'s own
|
|
371
|
+
* extras (see `showRing`/`inpage/core.js`'s `__wgPositionRing`), meaningless for an independent
|
|
372
|
+
* fixture ring that isn't "the current action."
|
|
373
|
+
*/
|
|
374
|
+
export async function showRingAt(page, ringId, labelId, box, label, tone, style) {
|
|
375
|
+
const size = normalizeHighlightSize(style && style.size);
|
|
376
|
+
const weight = normalizeHighlightWeight(style && style.weight);
|
|
377
|
+
const color = style && style.color ? String(style.color) : "";
|
|
378
|
+
await page
|
|
379
|
+
.evaluate(
|
|
380
|
+
({ ringId, labelId, box, label, tone, size, weight, color }) => {
|
|
381
|
+
if (window.__wgPaintRingAt) {
|
|
382
|
+
window.__wgPaintRingAt(ringId, labelId, box, label, tone, { size, weight, color });
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
{ ringId, labelId, box, label, tone: tone || "planned", size, weight, color },
|
|
386
|
+
)
|
|
387
|
+
.catch(() => {});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/** Hide (not remove) a named ring instance painted via {@link showRingAt}. */
|
|
391
|
+
export async function hideRingAt(page, ringId, labelId) {
|
|
392
|
+
await page
|
|
393
|
+
.evaluate(
|
|
394
|
+
({ ringId, labelId }) => {
|
|
395
|
+
if (window.__wgHideRingAt) window.__wgHideRingAt(ringId, labelId);
|
|
396
|
+
},
|
|
397
|
+
{ ringId, labelId },
|
|
398
|
+
)
|
|
399
|
+
.catch(() => {});
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** Remove a named ring instance entirely (Pilot's fixture rings are short-lived, not reused). */
|
|
403
|
+
export async function removeRingAt(page, ringId, labelId) {
|
|
404
|
+
await page
|
|
405
|
+
.evaluate(
|
|
406
|
+
({ ringId, labelId }) => {
|
|
407
|
+
__wgById(ringId)?.remove();
|
|
408
|
+
__wgById(labelId)?.remove();
|
|
409
|
+
},
|
|
410
|
+
{ ringId, labelId },
|
|
411
|
+
)
|
|
412
|
+
.catch(() => {});
|
|
413
|
+
}
|
|
414
|
+
|
|
366
415
|
export async function showRing(page, box, label, tone, style) {
|
|
367
416
|
const size = normalizeHighlightSize(style && style.size);
|
|
368
417
|
const weight = normalizeHighlightWeight(style && style.weight);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Page, BrowserContext } from "@playwright/test";
|
|
2
|
+
import { Engine } from "../engine.js";
|
|
3
|
+
import { MemPage } from "../mem-page.js";
|
|
4
|
+
import { type BlockEntry } from "./auto-explore.js";
|
|
5
|
+
import type { Checkpoint } from "../types.js";
|
|
6
|
+
export interface AutoExploreOptions {
|
|
7
|
+
/** Terminal menu (browser still runs for act()). Default false = headful picker panel. */
|
|
8
|
+
cli?: boolean;
|
|
9
|
+
baseURL?: string;
|
|
10
|
+
/** Initial URL when the page is blank (defaults to baseURL). */
|
|
11
|
+
startUrl?: string;
|
|
12
|
+
/** Phase C: glob / regex / bare `--blocks` file select for discovery. */
|
|
13
|
+
blocksSelect?: import("../blocks-select.js").BlocksSelect;
|
|
14
|
+
}
|
|
15
|
+
export declare function resolveBaseUrl(projectDir: string): string | undefined;
|
|
16
|
+
export declare function detectHere(page: Page, navBlocks: BlockEntry[]): Promise<string | null>;
|
|
17
|
+
export declare function ensureLivePage(context: BrowserContext, page: Page, startUrl: string | undefined): Promise<Page>;
|
|
18
|
+
/**
|
|
19
|
+
* Saucedemo-only defaults. Exact key names only — never substring `"login"`.
|
|
20
|
+
* A consumer's own `key<string>("login-email")` must stay unset here, or it
|
|
21
|
+
* silently gets a saucedemo credentials object instead of its own default.
|
|
22
|
+
*/
|
|
23
|
+
export declare function defaultMemValueForKey(keyName: string): unknown | undefined;
|
|
24
|
+
/** Pre-seed known demo keys (saucedemo creds) so headful/cli do not stop for mem forms. */
|
|
25
|
+
export declare function seedDefaultMem(library: Map<string, BlockEntry>, mem: MemPage): void;
|
|
26
|
+
export declare function ensureMem(entry: BlockEntry, mem: MemPage, cli: boolean): Promise<void>;
|
|
27
|
+
export declare function runOneBlock(engine: Engine, entry: BlockEntry, context: BrowserContext, page: Page, mem: MemPage, headful: boolean): Promise<Checkpoint<string>>;
|
|
28
|
+
export type PickResult = {
|
|
29
|
+
type: "pick";
|
|
30
|
+
index: number;
|
|
31
|
+
} | {
|
|
32
|
+
type: "quit";
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Interactive waygraph auto: locate current Checkpoint, list runnable Blocks, pick one, repeat.
|
|
36
|
+
*/
|
|
37
|
+
export declare function runAutoExplore(projectDir: string, options?: AutoExploreOptions): Promise<void>;
|