waygraph 0.12.6 → 0.12.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/agent-dive.d.ts +19 -0
- package/dist/agent-dive.js +162 -0
- package/dist/auto-explore-run.d.ts +5 -0
- package/dist/auto-explore-run.js +15 -5
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +152 -1
- package/dist/traverse-run.d.ts +24 -0
- package/dist/traverse-run.js +227 -0
- package/package.json +1 -1
- package/templates/agents/waygraph-author.agent.md +36 -0
- package/templates/agents/waygraph-healer.agent.md +33 -0
- package/templates/agents/waygraph-planner.agent.md +35 -0
- package/templates/scaffold/README.md +11 -8
- package/templates/scaffold/STRUCTURE.md +42 -17
- package/templates/scaffold/package.json +13 -8
- package/templates/scaffold/playwright.config.ts +15 -0
- package/templates/scaffold/scripts/fixture-server.mjs +41 -0
- package/templates/scaffold/scripts/with-fixture.mjs +69 -0
- package/templates/scaffold/src/blocks/SITE-MAP.md +5 -6
- package/templates/scaffold/src/blocks/demo-web/NAV.md +17 -8
- package/templates/scaffold/src/blocks/demo-web/demo-sel.ts +14 -0
- package/templates/scaffold/src/blocks/demo-web/home.html +65 -0
- package/templates/scaffold/src/blocks/demo-web/home.page.block.ts +29 -0
- package/templates/scaffold/src/blocks/demo-web/methods/add-item.effect.block.ts +68 -0
- package/templates/scaffold/src/blocks/demo-web/methods/assert-hello.method.block.ts +11 -12
- package/templates/scaffold/src/blocks/demo-web/methods/clear-cart.method.block.ts +26 -0
- package/templates/scaffold/src/blocks/demo-web/methods/remove-item.effect.block.ts +63 -0
- package/templates/scaffold/src/blocks/demo-web/nav-home.block.ts +5 -8
- package/templates/scaffold/src/flows/example.flow.ts +3 -4
- package/templates/scaffold/src/flows/shop.flow.ts +42 -0
- package/templates/scaffold/src/states/demo.mem-keys.ts +7 -0
- package/templates/scaffold/src/states/demo.states.ts +2 -0
- package/templates/scaffold/tests/example.spec.ts +9 -0
package/README.md
CHANGED
|
@@ -89,7 +89,8 @@ Live reference: `examples/saucedemo/src/blocks/saucedemo-web/inventory/`
|
|
|
89
89
|
|------|---------|
|
|
90
90
|
| Watch Sauce Demo step-through (temp dir only) | `npx waygraph try demo` |
|
|
91
91
|
| Interactive explore (Add/Remove/Open details from live page) | `cd examples/saucedemo && npm i && npx waygraph auto` |
|
|
92
|
-
| Scaffold a new **offline** project (green `npm test` on
|
|
92
|
+
| Scaffold a new **offline** project (green `npm test` on local fixture `:4177`) | `npx create-waygraph my-app` **or** `npx waygraph init my-app` |
|
|
93
|
+
| Install coding-agent defs for diving an app into Blocks | `npx waygraph agent-dive --loop claude` (also `opencode` / `cursor` / `vscode`) |
|
|
93
94
|
| Add waygraph to an existing repo | `npm install waygraph @playwright/test` |
|
|
94
95
|
|
|
95
96
|
**Scaffold is not hidden inside waygraph alone** - the offline starter also ships as
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type AgentDiveLoop = "claude" | "opencode" | "cursor" | "vscode";
|
|
2
|
+
export interface AgentSpec {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
tools: string[];
|
|
8
|
+
instructions: string;
|
|
9
|
+
}
|
|
10
|
+
/** Minimal YAML-ish frontmatter parser for `*.agent.md` templates. */
|
|
11
|
+
export declare function parseAgentSpec(filePath: string): AgentSpec;
|
|
12
|
+
export declare function loadAgentSpecs(): AgentSpec[];
|
|
13
|
+
export interface AgentDiveOptions {
|
|
14
|
+
loop: AgentDiveLoop;
|
|
15
|
+
projectDir: string;
|
|
16
|
+
/** Also copy raw prompts under docs/waygraph-agents/ */
|
|
17
|
+
prompts?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function runAgentDive(opts: AgentDiveOptions): void;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `waygraph agent-dive` — initialize coding-agent definitions for diving an app
|
|
3
|
+
* into waygraph Blocks (Playwright `init-agents` analogue).
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
6
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
function packageRoot() {
|
|
9
|
+
// dist/agent-dive.js -> ..
|
|
10
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
}
|
|
12
|
+
function agentsTemplateDir() {
|
|
13
|
+
return join(packageRoot(), "templates", "agents");
|
|
14
|
+
}
|
|
15
|
+
/** Minimal YAML-ish frontmatter parser for `*.agent.md` templates. */
|
|
16
|
+
export function parseAgentSpec(filePath) {
|
|
17
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
18
|
+
if (!raw.startsWith("---\n")) {
|
|
19
|
+
throw new Error(`agent-dive: missing frontmatter in ${filePath}`);
|
|
20
|
+
}
|
|
21
|
+
const end = raw.indexOf("\n---\n", 4);
|
|
22
|
+
if (end < 0)
|
|
23
|
+
throw new Error(`agent-dive: unclosed frontmatter in ${filePath}`);
|
|
24
|
+
const fm = raw.slice(4, end);
|
|
25
|
+
const body = raw.slice(end + 5).trim();
|
|
26
|
+
const meta = {};
|
|
27
|
+
let listKey = null;
|
|
28
|
+
const lists = {};
|
|
29
|
+
for (const line of fm.split("\n")) {
|
|
30
|
+
if (/^\s+-\s+/.test(line) && listKey) {
|
|
31
|
+
lists[listKey].push(line.replace(/^\s+-\s+/, "").trim());
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
listKey = null;
|
|
35
|
+
const m = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
|
|
36
|
+
if (!m)
|
|
37
|
+
continue;
|
|
38
|
+
const key = m[1];
|
|
39
|
+
const val = m[2].trim();
|
|
40
|
+
if (val === "") {
|
|
41
|
+
listKey = key;
|
|
42
|
+
lists[key] = [];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
meta[key] = val;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const name = meta.name || basename(filePath).replace(/\.agent\.md$/, "");
|
|
49
|
+
return {
|
|
50
|
+
name,
|
|
51
|
+
description: meta.description || name,
|
|
52
|
+
...(meta.model ? { model: meta.model } : {}),
|
|
53
|
+
...(meta.color ? { color: meta.color } : {}),
|
|
54
|
+
tools: lists.tools ?? [],
|
|
55
|
+
instructions: body,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function loadAgentSpecs() {
|
|
59
|
+
const dir = agentsTemplateDir();
|
|
60
|
+
if (!existsSync(dir)) {
|
|
61
|
+
throw new Error(`agent-dive: templates missing at ${dir}`);
|
|
62
|
+
}
|
|
63
|
+
return readdirSync(dir)
|
|
64
|
+
.filter((f) => f.endsWith(".agent.md"))
|
|
65
|
+
.sort()
|
|
66
|
+
.map((f) => parseAgentSpec(join(dir, f)));
|
|
67
|
+
}
|
|
68
|
+
function writeFileLogged(path, content, kind) {
|
|
69
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
70
|
+
writeFileSync(path, content.endsWith("\n") ? content : content + "\n");
|
|
71
|
+
console.log(` wrote ${path} (${kind})`);
|
|
72
|
+
}
|
|
73
|
+
function claudeAgentMd(agent) {
|
|
74
|
+
const tools = agent.tools.join(", ");
|
|
75
|
+
const lines = [
|
|
76
|
+
"---",
|
|
77
|
+
`name: ${agent.name}`,
|
|
78
|
+
`description: ${agent.description}`,
|
|
79
|
+
...(agent.model ? [`model: ${agent.model}`] : []),
|
|
80
|
+
...(agent.color ? [`color: ${agent.color}`] : []),
|
|
81
|
+
...(tools ? [`tools: ${tools}`] : []),
|
|
82
|
+
"---",
|
|
83
|
+
"",
|
|
84
|
+
agent.instructions,
|
|
85
|
+
"",
|
|
86
|
+
];
|
|
87
|
+
return lines.join("\n");
|
|
88
|
+
}
|
|
89
|
+
function opencodePromptMd(agent) {
|
|
90
|
+
return `${agent.instructions}\n`;
|
|
91
|
+
}
|
|
92
|
+
function cursorRuleMdc(agent) {
|
|
93
|
+
return `---
|
|
94
|
+
description: ${agent.description}
|
|
95
|
+
globs:
|
|
96
|
+
alwaysApply: false
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
# ${agent.name}
|
|
100
|
+
|
|
101
|
+
${agent.instructions}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
function vscodeAgentMd(agent) {
|
|
105
|
+
return claudeAgentMd(agent);
|
|
106
|
+
}
|
|
107
|
+
export function runAgentDive(opts) {
|
|
108
|
+
const agents = loadAgentSpecs();
|
|
109
|
+
const root = opts.projectDir;
|
|
110
|
+
console.log(`waygraph agent-dive (${opts.loop}) -> ${root}`);
|
|
111
|
+
console.log(` ${agents.length} agent(s) from package templates`);
|
|
112
|
+
switch (opts.loop) {
|
|
113
|
+
case "claude": {
|
|
114
|
+
const dir = join(root, ".claude", "agents");
|
|
115
|
+
mkdirSync(dir, { recursive: true });
|
|
116
|
+
for (const a of agents) {
|
|
117
|
+
writeFileLogged(join(dir, `${a.name}.md`), claudeAgentMd(a), "claude agent");
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case "opencode": {
|
|
122
|
+
const dir = join(root, ".opencode", "prompts");
|
|
123
|
+
mkdirSync(dir, { recursive: true });
|
|
124
|
+
for (const a of agents) {
|
|
125
|
+
writeFileLogged(join(dir, `${a.name}.md`), opencodePromptMd(a), "opencode prompt");
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case "cursor": {
|
|
130
|
+
const dir = join(root, ".cursor", "rules");
|
|
131
|
+
mkdirSync(dir, { recursive: true });
|
|
132
|
+
for (const a of agents) {
|
|
133
|
+
writeFileLogged(join(dir, `${a.name}.mdc`), cursorRuleMdc(a), "cursor rule");
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case "vscode": {
|
|
138
|
+
const dir = join(root, ".github", "agents");
|
|
139
|
+
mkdirSync(dir, { recursive: true });
|
|
140
|
+
for (const a of agents) {
|
|
141
|
+
writeFileLogged(join(dir, `${a.name}.md`), vscodeAgentMd(a), "vscode agent");
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
default: {
|
|
146
|
+
const _exhaustive = opts.loop;
|
|
147
|
+
throw new Error(`agent-dive: unsupported loop ${_exhaustive}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (opts.prompts) {
|
|
151
|
+
const dir = join(root, "docs", "waygraph-agents");
|
|
152
|
+
mkdirSync(dir, { recursive: true });
|
|
153
|
+
for (const a of agents) {
|
|
154
|
+
writeFileLogged(join(dir, `${a.name}.md`), `# ${a.name}\n\n${a.description}\n\n${a.instructions}\n`, "prompt copy");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
console.log("");
|
|
158
|
+
console.log("Next: point your coding agent at those files, then:");
|
|
159
|
+
console.log(" npx waygraph check .");
|
|
160
|
+
console.log(" npx waygraph auto --cli");
|
|
161
|
+
console.log(" (scaffold: npx waygraph init my-app)");
|
|
162
|
+
}
|
|
@@ -5,6 +5,11 @@ export interface AutoExploreOptions {
|
|
|
5
5
|
/** Initial URL when the page is blank (defaults to baseURL). */
|
|
6
6
|
startUrl?: string;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Saucedemo-only defaults. Exact key names only — never substring `"login"`
|
|
10
|
+
* (PIA `login-email` string must stay unset; see docs/proposals/auto-login-email-seed-bug.md).
|
|
11
|
+
*/
|
|
12
|
+
export declare function defaultMemValueForKey(keyName: string): unknown | undefined;
|
|
8
13
|
/**
|
|
9
14
|
* Interactive waygraph auto: locate current Checkpoint, list runnable Blocks, pick one, repeat.
|
|
10
15
|
*/
|
package/dist/auto-explore-run.js
CHANGED
|
@@ -77,12 +77,24 @@ function missingMemKeys(entry, mem) {
|
|
|
77
77
|
return requires.filter((k) => !mem.has(k));
|
|
78
78
|
}
|
|
79
79
|
const DEFAULT_CREDENTIALS = { username: "standard_user", password: "secret_sauce" };
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Saucedemo-only defaults. Exact key names only — never substring `"login"`
|
|
82
|
+
* (PIA `login-email` string must stay unset; see docs/proposals/auto-login-email-seed-bug.md).
|
|
83
|
+
*/
|
|
84
|
+
export function defaultMemValueForKey(keyName) {
|
|
85
|
+
if (keyName === "login-credentials" ||
|
|
86
|
+
keyName === "credentials" ||
|
|
87
|
+
keyName === "saucedemo.credentials") {
|
|
82
88
|
return DEFAULT_CREDENTIALS;
|
|
83
89
|
}
|
|
84
90
|
return undefined;
|
|
85
91
|
}
|
|
92
|
+
function defaultMemJsonPrompt(keyName) {
|
|
93
|
+
const def = defaultMemValueForKey(keyName);
|
|
94
|
+
if (def !== undefined)
|
|
95
|
+
return JSON.stringify(def);
|
|
96
|
+
return "{}";
|
|
97
|
+
}
|
|
86
98
|
function seedMemFromEnv(mem, entry) {
|
|
87
99
|
const raw = process.env.WAYGRAPH_DATA ?? process.env.WAYGRAPH_AUTO_MEM;
|
|
88
100
|
if (!raw)
|
|
@@ -129,9 +141,7 @@ async function promptMemCli(entry, mem) {
|
|
|
129
141
|
const rl = createInterface({ input, output });
|
|
130
142
|
try {
|
|
131
143
|
for (const k of missingMemKeys(entry, mem)) {
|
|
132
|
-
const def =
|
|
133
|
-
? '{"username":"standard_user","password":"secret_sauce"}'
|
|
134
|
-
: "{}";
|
|
144
|
+
const def = defaultMemJsonPrompt(k.name);
|
|
135
145
|
const line = await rl.question(` ${k.name} JSON [${def}]: `);
|
|
136
146
|
const json = line.trim() || def;
|
|
137
147
|
mem.set(k, JSON.parse(json));
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* demo Watch (step overlay); `--blocks` `--data` `--auto-next` `--fast` `--full` `--ff-expand`
|
|
8
8
|
* run Execute; `--blocks` `--data` `--non-headless` `--video`
|
|
9
9
|
*
|
|
10
|
-
* Also: list / nav / validate / check / graph / init / try
|
|
10
|
+
* Also: list / nav / validate / check / graph / init / agent-dive / traverse / try
|
|
11
11
|
* Aliases (one release): `chain` -> run/demo --blocks; `--autoplay` -> `--auto-next`
|
|
12
12
|
*
|
|
13
13
|
* "project" defaults to cwd. Flags beat WAYGRAPH_* env.
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* demo Watch (step overlay); `--blocks` `--data` `--auto-next` `--fast` `--full` `--ff-expand`
|
|
8
8
|
* run Execute; `--blocks` `--data` `--non-headless` `--video`
|
|
9
9
|
*
|
|
10
|
-
* Also: list / nav / validate / check / graph / init / try
|
|
10
|
+
* Also: list / nav / validate / check / graph / init / agent-dive / traverse / try
|
|
11
11
|
* Aliases (one release): `chain` -> run/demo --blocks; `--autoplay` -> `--auto-next`
|
|
12
12
|
*
|
|
13
13
|
* "project" defaults to cwd. Flags beat WAYGRAPH_* env.
|
|
@@ -19,6 +19,8 @@ import { fileURLToPath } from "node:url";
|
|
|
19
19
|
import { spawn } from "node:child_process";
|
|
20
20
|
import { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./graph.js";
|
|
21
21
|
import { runAutoExplore } from "./auto-explore-run.js";
|
|
22
|
+
import { runAgentDive } from "./agent-dive.js";
|
|
23
|
+
import { runTraverse } from "./traverse-run.js";
|
|
22
24
|
// ---------------------------------------------------------------------------
|
|
23
25
|
// Filesystem
|
|
24
26
|
// ---------------------------------------------------------------------------
|
|
@@ -3660,6 +3662,14 @@ Primary (less is more):
|
|
|
3660
3662
|
|
|
3661
3663
|
Also:
|
|
3662
3664
|
waygraph list | nav | validate | check | graph | init <name>
|
|
3665
|
+
waygraph traverse [project] Serial graph crawl (Phase B)
|
|
3666
|
+
--from <Checkpoint> Seed / start checkpoint
|
|
3667
|
+
--data '{...}' Mem seed
|
|
3668
|
+
--max-steps N Cap Block runs (default 50)
|
|
3669
|
+
--max-visits N Cap visits per node (default 2)
|
|
3670
|
+
--non-headless Show browser
|
|
3671
|
+
waygraph agent-dive [--loop claude|opencode|cursor|vscode] [--prompts]
|
|
3672
|
+
Initialize coding-agent defs (Playwright init-agents analogue)
|
|
3663
3673
|
waygraph try [demo|auto|auto:cli] One-shot saucedemo in a temp dir
|
|
3664
3674
|
try auto Headed browser panel (default)
|
|
3665
3675
|
try auto:cli / --cli Terminal menu instead
|
|
@@ -3756,6 +3766,147 @@ async function main() {
|
|
|
3756
3766
|
initCommand(args[1] ?? "");
|
|
3757
3767
|
break;
|
|
3758
3768
|
}
|
|
3769
|
+
case "traverse": {
|
|
3770
|
+
if (args.includes("--step") || args.includes("--auto-next") || args.includes("--autoplay")) {
|
|
3771
|
+
console.error("waygraph traverse: --step / --auto-next not supported (not a demo)");
|
|
3772
|
+
process.exit(1);
|
|
3773
|
+
}
|
|
3774
|
+
const rest = args.slice(1);
|
|
3775
|
+
let from;
|
|
3776
|
+
let data;
|
|
3777
|
+
let maxSteps;
|
|
3778
|
+
let maxVisits;
|
|
3779
|
+
let maxEdge;
|
|
3780
|
+
let headed = false;
|
|
3781
|
+
let baseUrl;
|
|
3782
|
+
let projectDir = process.cwd();
|
|
3783
|
+
for (let i = 0; i < rest.length; i++) {
|
|
3784
|
+
const a = rest[i];
|
|
3785
|
+
if (a === "--from" || a.startsWith("--from=")) {
|
|
3786
|
+
from = a.startsWith("--from=") ? a.slice(7) : rest[++i];
|
|
3787
|
+
continue;
|
|
3788
|
+
}
|
|
3789
|
+
if (a === "--data" || a.startsWith("--data=")) {
|
|
3790
|
+
data = a.startsWith("--data=") ? a.slice(7) : rest[++i];
|
|
3791
|
+
continue;
|
|
3792
|
+
}
|
|
3793
|
+
if (a === "--max-steps" || a.startsWith("--max-steps=")) {
|
|
3794
|
+
const v = a.startsWith("--max-steps=") ? a.slice(12) : rest[++i];
|
|
3795
|
+
maxSteps = Number(v);
|
|
3796
|
+
continue;
|
|
3797
|
+
}
|
|
3798
|
+
if (a === "--max-visits" || a.startsWith("--max-visits=")) {
|
|
3799
|
+
const v = a.startsWith("--max-visits=") ? a.slice(13) : rest[++i];
|
|
3800
|
+
maxVisits = Number(v);
|
|
3801
|
+
continue;
|
|
3802
|
+
}
|
|
3803
|
+
if (a === "--max-visits-per-edge" || a.startsWith("--max-visits-per-edge=")) {
|
|
3804
|
+
const v = a.startsWith("--max-visits-per-edge=")
|
|
3805
|
+
? a.slice("--max-visits-per-edge=".length)
|
|
3806
|
+
: rest[++i];
|
|
3807
|
+
maxEdge = Number(v);
|
|
3808
|
+
continue;
|
|
3809
|
+
}
|
|
3810
|
+
if (a === "--non-headless" || a === "--headed") {
|
|
3811
|
+
headed = true;
|
|
3812
|
+
continue;
|
|
3813
|
+
}
|
|
3814
|
+
if (a === "--base-url" || a.startsWith("--base-url=")) {
|
|
3815
|
+
baseUrl = a.startsWith("--base-url=") ? a.slice(11) : rest[++i];
|
|
3816
|
+
continue;
|
|
3817
|
+
}
|
|
3818
|
+
if (a === "--help" || a === "-h") {
|
|
3819
|
+
console.log(`waygraph traverse [project] [flags]
|
|
3820
|
+
|
|
3821
|
+
Serial graph crawl (RFC Phase B). Walks unused legal edges until a leaf,
|
|
3822
|
+
budget kill, or first broken edge.
|
|
3823
|
+
|
|
3824
|
+
--from <Checkpoint> start checkpoint (optional)
|
|
3825
|
+
--data '{...}' Mem seed JSON
|
|
3826
|
+
--max-steps N default 50
|
|
3827
|
+
--max-visits N per-node visit cap (default 2)
|
|
3828
|
+
--max-visits-per-edge N default 1
|
|
3829
|
+
--non-headless show browser
|
|
3830
|
+
--base-url URL
|
|
3831
|
+
|
|
3832
|
+
PASS: [Reached Leaf Node[traverse-1] at=... steps=N]
|
|
3833
|
+
FAIL: [Broke at edge[traverse-1] block=... from=... to=...]
|
|
3834
|
+
`);
|
|
3835
|
+
process.exit(0);
|
|
3836
|
+
}
|
|
3837
|
+
if (!a.startsWith("-")) {
|
|
3838
|
+
projectDir = resolve(a);
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
if (!existsSync(projectDir) || !statSync(projectDir).isDirectory()) {
|
|
3842
|
+
console.error(`waygraph traverse: no such directory: ${projectDir}`);
|
|
3843
|
+
process.exit(1);
|
|
3844
|
+
}
|
|
3845
|
+
const code = await runTraverse(projectDir, {
|
|
3846
|
+
...(from ? { from } : {}),
|
|
3847
|
+
...(data ? { data } : {}),
|
|
3848
|
+
...(maxSteps !== undefined && Number.isFinite(maxSteps) ? { maxSteps } : {}),
|
|
3849
|
+
...(maxVisits !== undefined && Number.isFinite(maxVisits)
|
|
3850
|
+
? { maxVisitsPerNode: maxVisits }
|
|
3851
|
+
: {}),
|
|
3852
|
+
...(maxEdge !== undefined && Number.isFinite(maxEdge)
|
|
3853
|
+
? { maxVisitsPerEdge: maxEdge }
|
|
3854
|
+
: {}),
|
|
3855
|
+
headed,
|
|
3856
|
+
...(baseUrl ? { baseURL: baseUrl } : {}),
|
|
3857
|
+
});
|
|
3858
|
+
process.exitCode = code;
|
|
3859
|
+
break;
|
|
3860
|
+
}
|
|
3861
|
+
case "agent-dive":
|
|
3862
|
+
case "init-agents": {
|
|
3863
|
+
// Playwright analogue: npx playwright init-agents --loop <provider>
|
|
3864
|
+
const rest = args.slice(1);
|
|
3865
|
+
let loop = "claude";
|
|
3866
|
+
let prompts = false;
|
|
3867
|
+
let projectDir = process.cwd();
|
|
3868
|
+
for (let i = 0; i < rest.length; i++) {
|
|
3869
|
+
const a = rest[i];
|
|
3870
|
+
if (a === "--prompts") {
|
|
3871
|
+
prompts = true;
|
|
3872
|
+
continue;
|
|
3873
|
+
}
|
|
3874
|
+
if (a === "--loop" || a.startsWith("--loop=")) {
|
|
3875
|
+
const v = a.startsWith("--loop=") ? a.slice("--loop=".length) : rest[++i];
|
|
3876
|
+
if (!v || !["claude", "opencode", "cursor", "vscode"].includes(v)) {
|
|
3877
|
+
console.error("waygraph agent-dive: --loop must be claude | opencode | cursor | vscode");
|
|
3878
|
+
process.exit(1);
|
|
3879
|
+
}
|
|
3880
|
+
loop = v;
|
|
3881
|
+
continue;
|
|
3882
|
+
}
|
|
3883
|
+
if (a === "--help" || a === "-h") {
|
|
3884
|
+
console.log(`waygraph agent-dive [--loop claude|opencode|cursor|vscode] [--prompts] [project]
|
|
3885
|
+
|
|
3886
|
+
Initialize coding-agent definitions for diving an app into waygraph Blocks
|
|
3887
|
+
(Playwright \`init-agents\` analogue).
|
|
3888
|
+
|
|
3889
|
+
--loop claude write .claude/agents/*.md (default)
|
|
3890
|
+
--loop opencode write .opencode/prompts/*.md
|
|
3891
|
+
--loop cursor write .cursor/rules/waygraph-*.mdc
|
|
3892
|
+
--loop vscode write .github/agents/*.md
|
|
3893
|
+
--prompts also copy docs/waygraph-agents/*.md
|
|
3894
|
+
|
|
3895
|
+
Agents shipped: waygraph-planner, waygraph-author, waygraph-healer.
|
|
3896
|
+
`);
|
|
3897
|
+
process.exit(0);
|
|
3898
|
+
}
|
|
3899
|
+
if (!a.startsWith("-")) {
|
|
3900
|
+
projectDir = resolve(a);
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
if (!existsSync(projectDir) || !statSync(projectDir).isDirectory()) {
|
|
3904
|
+
console.error(`waygraph agent-dive: no such directory: ${projectDir}`);
|
|
3905
|
+
process.exit(1);
|
|
3906
|
+
}
|
|
3907
|
+
runAgentDive({ loop, projectDir, prompts });
|
|
3908
|
+
break;
|
|
3909
|
+
}
|
|
3759
3910
|
case "chain": {
|
|
3760
3911
|
// Compat alias: chain auto A B -> auto --blocks A B; else -> run --blocks.
|
|
3761
3912
|
const flags = parseRunFlags(args.slice(1));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface TraverseOptions {
|
|
2
|
+
baseURL?: string;
|
|
3
|
+
startUrl?: string;
|
|
4
|
+
/** Seed checkpoint label (optional - otherwise detect from page / nav). */
|
|
5
|
+
from?: string;
|
|
6
|
+
/** Global Mem seed JSON (or use WAYGRAPH_DATA / WAYGRAPH_AUTO_MEM). */
|
|
7
|
+
data?: string;
|
|
8
|
+
/** Max Block runs this traverse (default 50). */
|
|
9
|
+
maxSteps?: number;
|
|
10
|
+
/** Max times a checkpoint may be visited (default 2). */
|
|
11
|
+
maxVisitsPerNode?: number;
|
|
12
|
+
/** Max times an edge key (block::instanceId) may be taken (default 1). */
|
|
13
|
+
maxVisitsPerEdge?: number;
|
|
14
|
+
/** Wall-clock budget ms (default 15m). */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
/** Show browser (default headless). */
|
|
17
|
+
headed?: boolean;
|
|
18
|
+
/** Traverse id for greppable lines (default traverse-1). */
|
|
19
|
+
traverseId?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Serial graph crawl. Prints greppable PASS/FAIL lines; non-zero exit on break.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runTraverse(projectDir: string, options?: TraverseOptions): Promise<number>;
|