waygraph 0.15.3 → 0.15.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/dist/auto-session-ipc.d.ts +14 -0
- package/dist/auto-session-ipc.js +4 -0
- package/dist/auto-session.d.ts +15 -0
- package/dist/auto-session.js +34 -1
- package/dist/cli.js +37 -1
- package/dist/pilot-overlay.d.ts +42 -0
- package/dist/pilot-overlay.js +148 -0
- package/examples/saucedemo/.waygraph-auto/1d266123.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2c7e8edd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/49edc885.log +4 -0
- package/examples/saucedemo/.waygraph-auto/79600ead.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d2c6ed66.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ddcb4212.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ebc2ebdb.log +0 -0
- package/package.json +1 -1
- package/templates/skills/waygraph-blind-pilot.skill.md +2 -1
- package/templates/skills/waygraph-pilot.skill.md +17 -0
- package/examples/saucedemo/.waygraph-auto/0b1f5b26.json +0 -8
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { AutoSession, type AutoSessionInit, type SessionSnapshot, type InspectDomOptions, type DomSnapshot, type TraceStep, type ApplyPathResult, type ConsoleLogEntry, type StorageSnapshot, type StubFileKind } from "./auto-session.js";
|
|
2
|
+
import type { PilotHighlightFixtures } from "./pilot-overlay.js";
|
|
3
|
+
export type { PilotHighlightFixtures, PilotFixtureRing } from "./pilot-overlay.js";
|
|
2
4
|
export interface SessionMeta {
|
|
3
5
|
sessionId: string;
|
|
4
6
|
socketPath: string;
|
|
@@ -43,6 +45,15 @@ export type StorageResponse = ({
|
|
|
43
45
|
error: string;
|
|
44
46
|
};
|
|
45
47
|
export type ReachResponse = ApplyPathResult;
|
|
48
|
+
export type HighlightResponse = {
|
|
49
|
+
ok: true;
|
|
50
|
+
painted: number;
|
|
51
|
+
missing: string[];
|
|
52
|
+
snapshot: SessionSnapshot;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
error: string;
|
|
56
|
+
};
|
|
46
57
|
/**
|
|
47
58
|
* Client-side: sends one request to a running session and returns its
|
|
48
59
|
* response. Reports a stale/unreachable session as an error within
|
|
@@ -94,6 +105,9 @@ export declare function requestSession(projectDir: string, sessionId: string, re
|
|
|
94
105
|
op: "reach";
|
|
95
106
|
checkpoint: string;
|
|
96
107
|
}, timeoutMs?: number): Promise<ReachResponse>;
|
|
108
|
+
export declare function requestSession(projectDir: string, sessionId: string, request: {
|
|
109
|
+
op: "highlight";
|
|
110
|
+
} & PilotHighlightFixtures, timeoutMs?: number): Promise<HighlightResponse>;
|
|
97
111
|
/**
|
|
98
112
|
* Server-side: runs `session` behind a unix socket at
|
|
99
113
|
* `.waygraph-auto/<sessionId>.sock`, writing session metadata only once the
|
package/dist/auto-session-ipc.js
CHANGED
|
@@ -235,6 +235,10 @@ export async function serveSession(session, projectDir, sessionId, headless = tr
|
|
|
235
235
|
else if (request.op === "resync") {
|
|
236
236
|
response = await session.resync();
|
|
237
237
|
}
|
|
238
|
+
else if (request.op === "highlight") {
|
|
239
|
+
const { op: _op, ...fixtures } = request;
|
|
240
|
+
response = await session.applyHighlight(fixtures);
|
|
241
|
+
}
|
|
238
242
|
else {
|
|
239
243
|
response = { ok: false, error: `unknown op "${request.op}"` };
|
|
240
244
|
}
|
package/dist/auto-session.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type BlockEntry, type ExploreMenu } from "./auto-explore.js";
|
|
2
2
|
import { type PickResult } from "./auto-explore-run.js";
|
|
3
3
|
import { type StubPhaseResult } from "./highlights.js";
|
|
4
|
+
import type { PilotHighlightFixtures } from "./pilot-overlay.js";
|
|
4
5
|
export interface SessionSnapshotEdge {
|
|
5
6
|
/** 1-based, matching the numbers a human/agent picks by (same as printCliMenu). */
|
|
6
7
|
index: number;
|
|
@@ -299,6 +300,20 @@ export declare class AutoSession {
|
|
|
299
300
|
rawUpload(selector: string, stub: StubFileKind | {
|
|
300
301
|
filePath: string;
|
|
301
302
|
}): Promise<ApplyPickResult>;
|
|
303
|
+
/**
|
|
304
|
+
* Agent-sent highlight fixtures (rings + optional todos) on the live page -
|
|
305
|
+
* the Pilot equivalent of Block `stubBefore` narration in `waygraph demo`.
|
|
306
|
+
* Does not run a Block; paint-only. Missing selectors are reported, not fatal.
|
|
307
|
+
*/
|
|
308
|
+
applyHighlight(fixtures: PilotHighlightFixtures): Promise<{
|
|
309
|
+
ok: true;
|
|
310
|
+
painted: number;
|
|
311
|
+
missing: string[];
|
|
312
|
+
snapshot: SessionSnapshot;
|
|
313
|
+
} | {
|
|
314
|
+
ok: false;
|
|
315
|
+
error: string;
|
|
316
|
+
}>;
|
|
302
317
|
/**
|
|
303
318
|
* Runs a whole multi-step route to `targetCheckpoint` in one call, instead
|
|
304
319
|
* of an agent hand-picking one index at a time across many separate
|
package/dist/auto-session.js
CHANGED
|
@@ -5,7 +5,7 @@ import { buildExploreContext, buildExploreMenu, } from "./auto-explore.js";
|
|
|
5
5
|
import { ensureLivePage, detectHere, seedDefaultMem, ensureMem, runOneBlock, resolveBaseUrl, } from "./auto-explore-run.js";
|
|
6
6
|
import { runStubPhase } from "./highlights.js";
|
|
7
7
|
import { findBlockPathDetailed } from "./graph.js";
|
|
8
|
-
import { updatePilotOverlay, showPilotActivity, showPilotVision } from "./pilot-overlay.js";
|
|
8
|
+
import { updatePilotOverlay, showPilotActivity, showPilotVision, showPilotFixtures } from "./pilot-overlay.js";
|
|
9
9
|
/** True when a stub-phase result actually carries authored content worth keeping. */
|
|
10
10
|
function stubPhaseHasContent(r) {
|
|
11
11
|
return (Object.keys(r.highlights).length > 0 ||
|
|
@@ -670,6 +670,39 @@ export class AutoSession {
|
|
|
670
670
|
quit: false,
|
|
671
671
|
};
|
|
672
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Agent-sent highlight fixtures (rings + optional todos) on the live page -
|
|
675
|
+
* the Pilot equivalent of Block `stubBefore` narration in `waygraph demo`.
|
|
676
|
+
* Does not run a Block; paint-only. Missing selectors are reported, not fatal.
|
|
677
|
+
*/
|
|
678
|
+
async applyHighlight(fixtures) {
|
|
679
|
+
this.page = await ensureLivePage(this.context, this.page, this.startUrl);
|
|
680
|
+
const label = fixtures.clear === true
|
|
681
|
+
? "clear fixtures"
|
|
682
|
+
: `${fixtures.rings?.length ?? 0} ring(s)` +
|
|
683
|
+
(fixtures.todos?.length ? `, ${fixtures.todos.length} todo(s)` : "");
|
|
684
|
+
await showPilotActivity(this.page, `Highlight: ${label}`);
|
|
685
|
+
try {
|
|
686
|
+
const { painted, missing } = await showPilotFixtures(this.page, fixtures);
|
|
687
|
+
const menu = await this.currentMenu();
|
|
688
|
+
this.lastRunNote = fixtures.clear
|
|
689
|
+
? "highlight cleared"
|
|
690
|
+
: `highlight painted ${painted}` +
|
|
691
|
+
(missing.length ? ` (missing: ${missing.join(", ")})` : "");
|
|
692
|
+
return {
|
|
693
|
+
ok: true,
|
|
694
|
+
painted,
|
|
695
|
+
missing,
|
|
696
|
+
snapshot: buildSessionSnapshot(menu, this.library.byName, this.here, this.lastRunNote),
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
catch (err) {
|
|
700
|
+
return {
|
|
701
|
+
ok: false,
|
|
702
|
+
error: `highlight failed - ${err instanceof Error ? err.message : String(err)}`,
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
}
|
|
673
706
|
/**
|
|
674
707
|
* Runs a whole multi-step route to `targetCheckpoint` in one call, instead
|
|
675
708
|
* of an agent hand-picking one index at a time across many separate
|
package/dist/cli.js
CHANGED
|
@@ -7006,6 +7006,13 @@ Primary (less is more):
|
|
|
7006
7006
|
--non-headless session someone is co-driving);
|
|
7007
7007
|
send/reach never do this on their own, since they
|
|
7008
7008
|
only re-detect when the position is already unknown
|
|
7009
|
+
waygraph auto highlight <sessionId> '<json>'
|
|
7010
|
+
Paint agent highlight fixtures on the live page
|
|
7011
|
+
(rings + optional todos). Same visual language as
|
|
7012
|
+
Block stubBefore in demo. JSON: rings[{selector,
|
|
7013
|
+
label,tone?,size?,weight?}], todos[], todoIndex?,
|
|
7014
|
+
todoTitle?, holdMs? (0=until next), clear:true.
|
|
7015
|
+
Missing selectors listed in response, not fatal.
|
|
7009
7016
|
waygraph pilot start Bootstrap for an agent: starts a --detach session
|
|
7010
7017
|
(same as auto --cli --detach) AND reads back the
|
|
7011
7018
|
whole project's Block graph (same as waygraph
|
|
@@ -7468,7 +7475,8 @@ Agents shipped: waygraph-planner, waygraph-author, waygraph-healer.
|
|
|
7468
7475
|
args[1] === "goto" ||
|
|
7469
7476
|
args[1] === "reload" ||
|
|
7470
7477
|
args[1] === "reach" ||
|
|
7471
|
-
args[1] === "resync"
|
|
7478
|
+
args[1] === "resync" ||
|
|
7479
|
+
args[1] === "highlight")) {
|
|
7472
7480
|
const sub = args[1];
|
|
7473
7481
|
const sessionId = args[2];
|
|
7474
7482
|
if (!sessionId) {
|
|
@@ -7670,6 +7678,34 @@ Agents shipped: waygraph-planner, waygraph-author, waygraph-healer.
|
|
|
7670
7678
|
process.exitCode = 1;
|
|
7671
7679
|
break;
|
|
7672
7680
|
}
|
|
7681
|
+
if (sub === "highlight") {
|
|
7682
|
+
const raw = args[3];
|
|
7683
|
+
if (raw === undefined) {
|
|
7684
|
+
console.error('waygraph auto highlight: usage: waygraph auto highlight <sessionId> \'{"rings":[{"selector":"#x","label":"X"}]}\'');
|
|
7685
|
+
process.exit(1);
|
|
7686
|
+
}
|
|
7687
|
+
let fixtures;
|
|
7688
|
+
try {
|
|
7689
|
+
fixtures = JSON.parse(raw);
|
|
7690
|
+
}
|
|
7691
|
+
catch {
|
|
7692
|
+
console.error("waygraph auto highlight: body must be valid JSON");
|
|
7693
|
+
process.exit(1);
|
|
7694
|
+
}
|
|
7695
|
+
if (fixtures.op !== undefined && fixtures.op !== "highlight") {
|
|
7696
|
+
console.error('waygraph auto highlight: do not set "op" (or set it to "highlight")');
|
|
7697
|
+
process.exit(1);
|
|
7698
|
+
}
|
|
7699
|
+
const { op: _ignore, ...rest } = fixtures;
|
|
7700
|
+
const res = await requestSession(proj, sessionId, {
|
|
7701
|
+
op: "highlight",
|
|
7702
|
+
...rest,
|
|
7703
|
+
});
|
|
7704
|
+
console.log(JSON.stringify(res));
|
|
7705
|
+
if (!res.ok)
|
|
7706
|
+
process.exitCode = 1;
|
|
7707
|
+
break;
|
|
7708
|
+
}
|
|
7673
7709
|
const res = await requestSession(proj, sessionId, { op: "status" });
|
|
7674
7710
|
console.log(JSON.stringify(res));
|
|
7675
7711
|
if (!res.ok)
|
package/dist/pilot-overlay.d.ts
CHANGED
|
@@ -52,8 +52,50 @@ export declare function showPilotActivity(page: Page, text: string): Promise<voi
|
|
|
52
52
|
* raw click/type/upload IS a real Playwright-driven action (`auto` was
|
|
53
53
|
* always documented as meaning exactly that), while a pure `auto dom` read
|
|
54
54
|
* touches nothing, so it gets its own "orange" tone instead.
|
|
55
|
+
*
|
|
56
|
+
* For agent-authored multi-ring / todo narration, use {@link showPilotFixtures}
|
|
57
|
+
* (`auto highlight`) instead - this vision ring is one-shot inspect feedback.
|
|
55
58
|
*/
|
|
56
59
|
export declare function showPilotVision(page: Page, selector: string, label: string, tone?: HighlightTone): Promise<void>;
|
|
60
|
+
/** One ring the Pilot agent wants painted (same fields as demo stub rings). */
|
|
61
|
+
export type PilotFixtureRing = {
|
|
62
|
+
selector: string;
|
|
63
|
+
label: string;
|
|
64
|
+
tone?: HighlightTone;
|
|
65
|
+
size?: "sm" | "md" | "lg";
|
|
66
|
+
weight?: "normal" | "bold";
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Agent-sent highlight fixtures for a live Pilot / auto session.
|
|
70
|
+
* Painted by {@link showPilotFixtures}; driven via IPC `op: "highlight"`.
|
|
71
|
+
*/
|
|
72
|
+
export type PilotHighlightFixtures = {
|
|
73
|
+
/** Replace current fixture rings with these (empty + no todos = clear). */
|
|
74
|
+
rings?: readonly PilotFixtureRing[];
|
|
75
|
+
/** Optional floating todo list (demo-dock language, simplified). */
|
|
76
|
+
todos?: readonly string[];
|
|
77
|
+
/** 0-based index of the "current" todo row (others before it = done). */
|
|
78
|
+
todoIndex?: number;
|
|
79
|
+
/** Optional title above the todo list. */
|
|
80
|
+
todoTitle?: string;
|
|
81
|
+
/**
|
|
82
|
+
* How long fixtures stay visible (ms). `0` = until the next highlight /
|
|
83
|
+
* clear. Default `12000`. Vision rings (`showPilotVision`) stay separate.
|
|
84
|
+
*/
|
|
85
|
+
holdMs?: number;
|
|
86
|
+
/** Drop every agent fixture ring/todo immediately. */
|
|
87
|
+
clear?: boolean;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Paint (or clear) agent-authored highlight fixtures on the live page.
|
|
91
|
+
* Multi-ring + optional todo strip - what Block `stubBefore` does in
|
|
92
|
+
* `waygraph demo`, available to the Pilot agent without going through demo.
|
|
93
|
+
* Does not import `cli.ts` (see file header).
|
|
94
|
+
*/
|
|
95
|
+
export declare function showPilotFixtures(page: Page, fixtures: PilotHighlightFixtures): Promise<{
|
|
96
|
+
painted: number;
|
|
97
|
+
missing: string[];
|
|
98
|
+
}>;
|
|
57
99
|
/** Minimal shape needed to render the graph tree - matches WaygraphGraph. */
|
|
58
100
|
export interface PilotOverlayGraph {
|
|
59
101
|
nodes: readonly {
|
package/dist/pilot-overlay.js
CHANGED
|
@@ -60,6 +60,44 @@ const OVERLAY_CSS = `
|
|
|
60
60
|
opacity: 0; transform: translateY(4px); transition: opacity 0.15s, transform 0.15s;
|
|
61
61
|
}
|
|
62
62
|
#wg-pilot-activity.wg-pilot-toast-show { opacity: 1; transform: translateY(0); }
|
|
63
|
+
/* Agent-sent fixture rings share tone/size CSS with #wg-ring (demo language). */
|
|
64
|
+
.wg-pilot-fx-ring{position:fixed;z-index:2147483645;pointer-events:none;opacity:0;
|
|
65
|
+
border:3px solid #7C3AED;border-radius:10px;box-sizing:border-box;
|
|
66
|
+
transition:opacity .12s ease,left .12s,top .12s,width .12s,height .12s;}
|
|
67
|
+
.wg-pilot-fx-ring[data-tone=planned]{border-color:#7C3AED;box-shadow:0 0 0 4px rgba(124,58,237,.16);}
|
|
68
|
+
.wg-pilot-fx-ring[data-tone=auto]{border-color:#9CA3AF;box-shadow:0 0 0 4px rgba(156,163,175,.28);}
|
|
69
|
+
.wg-pilot-fx-ring[data-tone=info]{border-color:#3B82F6;box-shadow:0 0 0 4px rgba(59,130,246,.22);}
|
|
70
|
+
.wg-pilot-fx-ring[data-tone=warning]{border-color:#EAB308;box-shadow:0 0 0 4px rgba(234,179,8,.22);}
|
|
71
|
+
.wg-pilot-fx-ring[data-tone=danger]{border-color:#EF4444;box-shadow:0 0 0 4px rgba(239,68,68,.22);}
|
|
72
|
+
.wg-pilot-fx-ring[data-tone=success]{border-color:#22C55E;box-shadow:0 0 0 4px rgba(34,197,94,.22);}
|
|
73
|
+
.wg-pilot-fx-ring[data-tone=orange]{border-color:#F97316;box-shadow:0 0 0 4px rgba(249,115,22,.22);}
|
|
74
|
+
.wg-pilot-fx-label{position:fixed;z-index:2147483645;pointer-events:none;opacity:0;
|
|
75
|
+
font:600 12px/1.3 ui-sans-serif,system-ui,sans-serif;padding:5px 9px;border-radius:6px;
|
|
76
|
+
max-width:min(360px,80vw);box-shadow:0 2px 8px rgba(0,0,0,.25);white-space:nowrap;
|
|
77
|
+
overflow:hidden;text-overflow:ellipsis;transition:opacity .12s ease;}
|
|
78
|
+
.wg-pilot-fx-label[data-tone=planned]{background:#7C3AED;color:#fff;}
|
|
79
|
+
.wg-pilot-fx-label[data-tone=auto]{background:#6B7280;color:#fff;}
|
|
80
|
+
.wg-pilot-fx-label[data-tone=info]{background:#2563EB;color:#fff;}
|
|
81
|
+
.wg-pilot-fx-label[data-tone=warning]{background:#EAB308;color:#1c1917;}
|
|
82
|
+
.wg-pilot-fx-label[data-tone=danger]{background:#DC2626;color:#fff;}
|
|
83
|
+
.wg-pilot-fx-label[data-tone=success]{background:#16A34A;color:#fff;}
|
|
84
|
+
.wg-pilot-fx-label[data-tone=orange]{background:#EA580C;color:#fff;}
|
|
85
|
+
.wg-pilot-fx-ring[data-size=sm]{border-width:1.5px;border-radius:8px;}
|
|
86
|
+
.wg-pilot-fx-ring[data-size=lg]{border-width:4px;border-radius:12px;}
|
|
87
|
+
.wg-pilot-fx-label[data-size=sm]{font-size:10px;padding:4px 7px;}
|
|
88
|
+
.wg-pilot-fx-label[data-size=lg]{font-size:16px;padding:8px 14px;}
|
|
89
|
+
.wg-pilot-fx-label[data-weight=bold]{font-weight:800;}
|
|
90
|
+
#wg-pilot-fx-todos{
|
|
91
|
+
position:fixed;z-index:2147483645;top:72px;left:14px;max-width:280px;
|
|
92
|
+
font:12px/1.4 ui-sans-serif,system-ui,sans-serif;color:#fff;
|
|
93
|
+
background:rgba(20,10,40,.94);border-radius:10px;padding:10px 12px;
|
|
94
|
+
box-shadow:0 2px 10px rgba(0,0,0,.3);pointer-events:none;
|
|
95
|
+
}
|
|
96
|
+
#wg-pilot-fx-todos .wg-pilot-fx-todo-title{font-weight:700;color:#c9a6ff;margin-bottom:6px;}
|
|
97
|
+
#wg-pilot-fx-todos ol{margin:0;padding-left:18px;}
|
|
98
|
+
#wg-pilot-fx-todos li{margin:3px 0;color:#ddd;}
|
|
99
|
+
#wg-pilot-fx-todos li.wg-pilot-fx-todo-done{color:#888;text-decoration:line-through;}
|
|
100
|
+
#wg-pilot-fx-todos li.wg-pilot-fx-todo-now{color:#fff;font-weight:700;}
|
|
63
101
|
` + WAYGRAPH_RING_CSS;
|
|
64
102
|
/** Idempotent - safe to call before every update, matching narrate mode's own precedent. */
|
|
65
103
|
async function ensureInstalled(page) {
|
|
@@ -159,6 +197,9 @@ export async function showPilotActivity(page, text) {
|
|
|
159
197
|
* raw click/type/upload IS a real Playwright-driven action (`auto` was
|
|
160
198
|
* always documented as meaning exactly that), while a pure `auto dom` read
|
|
161
199
|
* touches nothing, so it gets its own "orange" tone instead.
|
|
200
|
+
*
|
|
201
|
+
* For agent-authored multi-ring / todo narration, use {@link showPilotFixtures}
|
|
202
|
+
* (`auto highlight`) instead - this vision ring is one-shot inspect feedback.
|
|
162
203
|
*/
|
|
163
204
|
export async function showPilotVision(page, selector, label, tone = "auto") {
|
|
164
205
|
await ensureInstalled(page);
|
|
@@ -211,6 +252,113 @@ export async function showPilotVision(page, selector, label, tone = "auto") {
|
|
|
211
252
|
}, { selector, label, tone })
|
|
212
253
|
.catch(() => { });
|
|
213
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Paint (or clear) agent-authored highlight fixtures on the live page.
|
|
257
|
+
* Multi-ring + optional todo strip - what Block `stubBefore` does in
|
|
258
|
+
* `waygraph demo`, available to the Pilot agent without going through demo.
|
|
259
|
+
* Does not import `cli.ts` (see file header).
|
|
260
|
+
*/
|
|
261
|
+
export async function showPilotFixtures(page, fixtures) {
|
|
262
|
+
await ensureInstalled(page);
|
|
263
|
+
const holdMs = fixtures.clear === true
|
|
264
|
+
? 0
|
|
265
|
+
: fixtures.holdMs === undefined
|
|
266
|
+
? 12_000
|
|
267
|
+
: Math.max(0, fixtures.holdMs);
|
|
268
|
+
const rings = fixtures.clear ? [] : (fixtures.rings ?? []);
|
|
269
|
+
const todos = fixtures.clear ? [] : (fixtures.todos ?? []);
|
|
270
|
+
const todoIndex = fixtures.todoIndex ?? 0;
|
|
271
|
+
const todoTitle = fixtures.todoTitle ?? "Plan";
|
|
272
|
+
return page
|
|
273
|
+
.evaluate(({ rings, todos, todoIndex, todoTitle, holdMs }) => {
|
|
274
|
+
const w = window;
|
|
275
|
+
if (w.__wgPilotFxHideTimer)
|
|
276
|
+
clearTimeout(w.__wgPilotFxHideTimer);
|
|
277
|
+
const clearFx = () => {
|
|
278
|
+
document.querySelectorAll(".wg-pilot-fx-ring, .wg-pilot-fx-label").forEach((el) => el.remove());
|
|
279
|
+
document.getElementById("wg-pilot-fx-todos")?.remove();
|
|
280
|
+
};
|
|
281
|
+
w.__wgPilotFxClear = clearFx;
|
|
282
|
+
clearFx();
|
|
283
|
+
const missing = [];
|
|
284
|
+
let painted = 0;
|
|
285
|
+
for (const ring of rings) {
|
|
286
|
+
const el = document.querySelector(ring.selector);
|
|
287
|
+
if (!el) {
|
|
288
|
+
missing.push(ring.selector);
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
const rect = el.getBoundingClientRect();
|
|
292
|
+
if (rect.width === 0 && rect.height === 0) {
|
|
293
|
+
missing.push(ring.selector);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const tone = ring.tone || "planned";
|
|
297
|
+
const size = ring.size === "sm" || ring.size === "lg" ? ring.size : "md";
|
|
298
|
+
const weight = ring.weight === "bold" ? "bold" : "normal";
|
|
299
|
+
const pad = size === "sm" ? 3 : size === "lg" ? 10 : 6;
|
|
300
|
+
const ringEl = document.createElement("div");
|
|
301
|
+
ringEl.className = "wg-pilot-fx-ring";
|
|
302
|
+
ringEl.dataset.tone = tone;
|
|
303
|
+
ringEl.dataset.size = size;
|
|
304
|
+
ringEl.style.left = `${rect.left - pad}px`;
|
|
305
|
+
ringEl.style.top = `${rect.top - pad}px`;
|
|
306
|
+
ringEl.style.width = `${Math.max(4, rect.width + pad * 2)}px`;
|
|
307
|
+
ringEl.style.height = `${Math.max(4, rect.height + pad * 2)}px`;
|
|
308
|
+
ringEl.style.opacity = "1";
|
|
309
|
+
const labelEl = document.createElement("div");
|
|
310
|
+
labelEl.className = "wg-pilot-fx-label";
|
|
311
|
+
labelEl.dataset.tone = tone;
|
|
312
|
+
labelEl.dataset.size = size;
|
|
313
|
+
labelEl.dataset.weight = weight;
|
|
314
|
+
labelEl.textContent = ring.label;
|
|
315
|
+
labelEl.style.opacity = "1";
|
|
316
|
+
document.documentElement.appendChild(ringEl);
|
|
317
|
+
document.documentElement.appendChild(labelEl);
|
|
318
|
+
const lw = labelEl.offsetWidth;
|
|
319
|
+
const lh = labelEl.offsetHeight;
|
|
320
|
+
let labelLeft = rect.left - pad;
|
|
321
|
+
let labelTop = rect.top - pad + rect.height + pad * 2 + 8;
|
|
322
|
+
if (labelTop + lh > window.innerHeight - 6)
|
|
323
|
+
labelTop = rect.top - pad - lh - 8;
|
|
324
|
+
if (labelTop < 6)
|
|
325
|
+
labelTop = 6;
|
|
326
|
+
if (labelLeft + lw > window.innerWidth - 6) {
|
|
327
|
+
labelLeft = Math.max(6, window.innerWidth - 6 - lw);
|
|
328
|
+
}
|
|
329
|
+
if (labelLeft < 6)
|
|
330
|
+
labelLeft = 6;
|
|
331
|
+
labelEl.style.left = `${labelLeft}px`;
|
|
332
|
+
labelEl.style.top = `${labelTop}px`;
|
|
333
|
+
painted += 1;
|
|
334
|
+
}
|
|
335
|
+
if (todos.length > 0) {
|
|
336
|
+
const dock = document.createElement("div");
|
|
337
|
+
dock.id = "wg-pilot-fx-todos";
|
|
338
|
+
const title = document.createElement("div");
|
|
339
|
+
title.className = "wg-pilot-fx-todo-title";
|
|
340
|
+
title.textContent = todoTitle;
|
|
341
|
+
dock.appendChild(title);
|
|
342
|
+
const ol = document.createElement("ol");
|
|
343
|
+
todos.forEach((text, i) => {
|
|
344
|
+
const li = document.createElement("li");
|
|
345
|
+
li.textContent = text;
|
|
346
|
+
if (i < todoIndex)
|
|
347
|
+
li.className = "wg-pilot-fx-todo-done";
|
|
348
|
+
else if (i === todoIndex)
|
|
349
|
+
li.className = "wg-pilot-fx-todo-now";
|
|
350
|
+
ol.appendChild(li);
|
|
351
|
+
});
|
|
352
|
+
dock.appendChild(ol);
|
|
353
|
+
document.documentElement.appendChild(dock);
|
|
354
|
+
}
|
|
355
|
+
if (holdMs > 0 && (painted > 0 || todos.length > 0)) {
|
|
356
|
+
w.__wgPilotFxHideTimer = setTimeout(() => clearFx(), holdMs);
|
|
357
|
+
}
|
|
358
|
+
return { painted, missing };
|
|
359
|
+
}, { rings, todos, todoIndex, todoTitle, holdMs })
|
|
360
|
+
.catch(() => ({ painted: 0, missing: rings.map((r) => r.selector) }));
|
|
361
|
+
}
|
|
214
362
|
/**
|
|
215
363
|
* Refreshes the badge text and the (possibly-collapsed) panel's two tabs
|
|
216
364
|
* ("Here" - current live menu; "All nodes" - whole project graph as a
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
(node:218615) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
|
|
2
|
+
(Use `node --trace-warnings ...` to show where the warning was created)
|
|
3
|
+
(node:218615) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
|
|
4
|
+
(Use `node --trace-warnings ...` to show where the warning was created)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -25,7 +25,8 @@ permanent, reusable, typed coverage instead of leaving nothing behind.
|
|
|
25
25
|
(`(group)/<page-slug>/page.block.ts` + `nav.block.ts` + `methods/*.block.ts` + one `*.sel.ts`)
|
|
26
26
|
so the result becomes part of the Waygraph Map, not a scattered one-off file.
|
|
27
27
|
4. `auto reload <sessionId>` to pick up the newly-written Block(s) without restarting.
|
|
28
|
-
5.
|
|
28
|
+
5. Optionally narrate for a headful watcher: `auto highlight <sessionId> '{"rings":[...],"todos":[...]}'`
|
|
29
|
+
6. Run the new Block for real via `auto send` - prove it works before moving to the next
|
|
29
30
|
pattern, exactly like any other real Block.
|
|
30
31
|
6. Ask the user a clarifying question only when something genuinely can't be resolved from
|
|
31
32
|
the DOM alone (is this instance local or published? does a downstream integration exist?)
|
|
@@ -16,12 +16,29 @@ waygraph pilot start # bootstraps: {sessionId, socketPath,
|
|
|
16
16
|
waygraph auto status <sessionId> # re-read the live menu, no side effects
|
|
17
17
|
waygraph auto send <sessionId> "<pick>" # run exactly one Block (by menu index or name)
|
|
18
18
|
waygraph auto reach <sessionId> <Checkpoint> # path-find + run a whole route in one call
|
|
19
|
+
waygraph auto highlight <sessionId> '<json>' # paint rings/todos on the live page (agent fixtures)
|
|
19
20
|
```
|
|
20
21
|
|
|
21
22
|
`graph` in `pilot start`'s response is the **whole project's** Block/Checkpoint graph, not
|
|
22
23
|
just what's reachable from here - use it to plan several steps ahead before you start
|
|
23
24
|
sending picks.
|
|
24
25
|
|
|
26
|
+
## Highlight fixtures (agent-sent narration)
|
|
27
|
+
|
|
28
|
+
Block `stubBefore` / `withHighlightFixtures` only paint in `waygraph demo`. In Pilot they
|
|
29
|
+
land in `auto trace` as metadata but do **not** draw on the page. When a human is watching
|
|
30
|
+
a headful session (or you want to narrate intent before a send), paint yourself:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
waygraph auto highlight <sessionId> '{"rings":[{"selector":"#user-name","label":"Username","tone":"planned"},{"selector":"#password","label":"Password","tone":"info"}],"todos":["Fill username","Fill password","Submit"],"todoIndex":0,"holdMs":0}'
|
|
34
|
+
waygraph auto highlight <sessionId> '{"clear":true}'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- `tone`: `planned` (purple, default) | `auto` | `info` | `warning` | `danger` | `success` (pilot `orange` is for `auto dom` vision only)
|
|
38
|
+
- `holdMs`: ms to keep fixtures; `0` = until the next highlight / clear (default 12000)
|
|
39
|
+
- Missing selectors are listed in the JSON response (`missing`) - not a hard failure
|
|
40
|
+
- Does not replace `auto send` - paint, then run the real Block
|
|
41
|
+
|
|
25
42
|
## Rule 1: run real Blocks, not raw primitives
|
|
26
43
|
|
|
27
44
|
Default action is always `auto send`/`auto reach` (a real Block). `auto dom/click/type/
|