cairn-engine 0.1.0 → 0.3.0
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 +11 -0
- package/dist/adapters/drivers/chrome.d.ts +27 -2
- package/dist/adapters/drivers/chrome.js +154 -32
- package/dist/adapters/drivers/chrome.js.map +1 -1
- package/dist/adapters/drivers/fake.d.ts +12 -0
- package/dist/adapters/drivers/fake.js +31 -6
- package/dist/adapters/drivers/fake.js.map +1 -1
- package/dist/adapters/drivers/self-heal.d.ts +6 -0
- package/dist/adapters/drivers/self-heal.js +35 -4
- package/dist/adapters/drivers/self-heal.js.map +1 -1
- package/dist/adapters/llm/anthropic.d.ts +6 -0
- package/dist/adapters/llm/anthropic.js +52 -21
- package/dist/adapters/llm/anthropic.js.map +1 -1
- package/dist/core/discover.d.ts +5 -1
- package/dist/core/discover.js +68 -31
- package/dist/core/discover.js.map +1 -1
- package/dist/core/pipeline.d.ts +12 -2
- package/dist/core/pipeline.js +25 -1
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/ports.d.ts +10 -0
- package/dist/core/types.d.ts +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +7 -1
- package/dist/run.js +2 -2
- package/dist/run.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,17 @@ const { result } = await runScenario(scenario, { heal: true });
|
|
|
28
28
|
if (!result.verdict.passed) process.exit(1);
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
Building a UI on top? The engine exposes the seams; you bring the UI:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
await runScenario(scenario, {
|
|
36
|
+
signal: controller.signal, // a Stop button
|
|
37
|
+
screenshots: true, // capture a PNG per step
|
|
38
|
+
onStep: (e) => render(e.index, e.step, e.ok, e.screenshot), // live timeline
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
31
42
|
No API key needed if you have **Claude Code** installed (cairn shells out to it); set
|
|
32
43
|
`ANTHROPIC_API_KEY` to use the Anthropic API instead.
|
|
33
44
|
|
|
@@ -3,18 +3,37 @@ import type { ConsoleMessage, Evidence, NetworkRequest, PageElement, SettleOptio
|
|
|
3
3
|
export interface ChromeDriverOptions {
|
|
4
4
|
command?: string;
|
|
5
5
|
args?: string[];
|
|
6
|
+
/** Per-MCP-call timeout (ms). A hung tool call rejects instead of wedging the run. Default 30s. */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
/** Timeout for the initial browser launch/connect (ms). Default 60s (first run may download). */
|
|
9
|
+
connectTimeoutMs?: number;
|
|
6
10
|
}
|
|
7
11
|
export declare class ChromeDevToolsDriver implements Driver {
|
|
8
12
|
private readonly opts;
|
|
9
13
|
private client?;
|
|
10
14
|
private transport?;
|
|
11
15
|
private initialUrl?;
|
|
16
|
+
private snapshotCache?;
|
|
17
|
+
private readonly seenPages;
|
|
12
18
|
constructor(opts?: ChromeDriverOptions);
|
|
19
|
+
private trackPages;
|
|
20
|
+
/** If the last action opened a new tab, switch to it — else later actions silently hit the wrong page. */
|
|
21
|
+
private followNewTab;
|
|
22
|
+
/** Reject after `ms` if `p` hasn't settled — so a hung MCP/subprocess never wedges the caller. */
|
|
23
|
+
private withTimeout;
|
|
13
24
|
private ensureConnected;
|
|
14
25
|
private call;
|
|
15
26
|
goto(url: string): Promise<void>;
|
|
16
27
|
click(target: Target): Promise<void>;
|
|
28
|
+
doubleClick(target: Target): Promise<void>;
|
|
29
|
+
hover(target: Target): Promise<void>;
|
|
17
30
|
type(target: Target, text: string): Promise<void>;
|
|
31
|
+
select(target: Target, value: string): Promise<void>;
|
|
32
|
+
pressKey(key: string): Promise<void>;
|
|
33
|
+
scroll(direction?: "down" | "up"): Promise<void>;
|
|
34
|
+
screenshot(): Promise<string | undefined>;
|
|
35
|
+
/** Cache the page snapshot so resolve + the discover loop don't both re-fetch it; actions invalidate it. */
|
|
36
|
+
private getSnapshot;
|
|
18
37
|
snapshot(): Promise<PageElement[]>;
|
|
19
38
|
settle(options?: SettleOptions): Promise<void>;
|
|
20
39
|
observe(): Promise<Evidence>;
|
|
@@ -23,15 +42,21 @@ export declare class ChromeDevToolsDriver implements Driver {
|
|
|
23
42
|
}
|
|
24
43
|
/** `uid=1_3 link "Learn more" …` → {role:"link", name:"Learn more"} for named rows. */
|
|
25
44
|
export declare function parseElements(snapshot: string): PageElement[];
|
|
26
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a uid by accessible name. Prefers an exact (case-insensitive) match over a
|
|
47
|
+
* substring one, so "Cart" picks the button "Cart" rather than the first "Add to Cart".
|
|
48
|
+
* Only the role-adjacent quoted name counts — a bare `url="…"` is never matched as a name.
|
|
49
|
+
*/
|
|
27
50
|
export declare function findUidByName(snapshot: string, text: string): string | undefined;
|
|
28
51
|
/** `reqid=5 GET https://… [200]` → NetworkRequest[]. */
|
|
29
52
|
export declare function parseNetwork(text: string): NetworkRequest[];
|
|
30
|
-
/**
|
|
53
|
+
/** `msgid=1 [error] message (1 args)` → {type:"error", text:"message"}. */
|
|
31
54
|
export declare function parseConsole(text: string): ConsoleMessage[];
|
|
32
55
|
/** Canonicalize a url for comparison: drop a trailing slash and the hash. */
|
|
33
56
|
export declare function normalizeUrl(u: string): string;
|
|
34
57
|
/** True only if the page genuinely moved — not just a trailing-slash difference. */
|
|
35
58
|
export declare function isNavigation(initialUrl: string | undefined, finalUrl: string): boolean;
|
|
59
|
+
/** `4: Example Domain (…) [selected]` → page ids [4]. Ids are stable, increasing numbers. */
|
|
60
|
+
export declare function parsePageIds(text: string): number[];
|
|
36
61
|
/** `2: Example Domain (https://example.com/) [selected]` → the selected page's url. */
|
|
37
62
|
export declare function parseSelectedUrl(text: string): string | undefined;
|
|
@@ -8,17 +8,60 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
8
8
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
9
9
|
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
10
10
|
const MCP_COMMAND = "npx";
|
|
11
|
+
// Pinned to the tested 1.3.x line: the parsers below depend on chrome-devtools-mcp's text
|
|
12
|
+
// format, so an unbounded `@latest` could break them silently. Override via ChromeDriverOptions.
|
|
11
13
|
// `--isolated` gives the harness its own ephemeral browser, so a standalone `cairn run`
|
|
12
14
|
// never collides with another chrome-devtools-mcp using the default profile.
|
|
13
|
-
const MCP_ARGS = ["-y", "chrome-devtools-mcp
|
|
15
|
+
const MCP_ARGS = ["-y", "chrome-devtools-mcp@~1.3.0", "--isolated"];
|
|
14
16
|
export class ChromeDevToolsDriver {
|
|
15
17
|
opts;
|
|
16
18
|
client;
|
|
17
19
|
transport;
|
|
18
20
|
initialUrl;
|
|
21
|
+
snapshotCache; // raw take_snapshot text, valid until the next action mutates the page
|
|
22
|
+
seenPages = new Set();
|
|
19
23
|
constructor(opts = {}) {
|
|
20
24
|
this.opts = opts;
|
|
21
25
|
}
|
|
26
|
+
async trackPages() {
|
|
27
|
+
try {
|
|
28
|
+
parsePageIds(await this.call("list_pages")).forEach((id) => this.seenPages.add(id));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
/* best-effort */
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** If the last action opened a new tab, switch to it — else later actions silently hit the wrong page. */
|
|
35
|
+
async followNewTab() {
|
|
36
|
+
try {
|
|
37
|
+
const ids = parsePageIds(await this.call("list_pages"));
|
|
38
|
+
const fresh = ids.filter((id) => !this.seenPages.has(id));
|
|
39
|
+
ids.forEach((id) => this.seenPages.add(id));
|
|
40
|
+
if (fresh.length) {
|
|
41
|
+
await this.call("select_page", { pageId: Math.max(...fresh) });
|
|
42
|
+
this.snapshotCache = undefined; // different tab → different DOM
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
/* best-effort */
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Reject after `ms` if `p` hasn't settled — so a hung MCP/subprocess never wedges the caller. */
|
|
50
|
+
async withTimeout(p, ms, label) {
|
|
51
|
+
let timer;
|
|
52
|
+
try {
|
|
53
|
+
return await Promise.race([
|
|
54
|
+
p,
|
|
55
|
+
new Promise((_, reject) => {
|
|
56
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
57
|
+
}),
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
if (timer)
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
22
65
|
async ensureConnected() {
|
|
23
66
|
if (this.client)
|
|
24
67
|
return this.client;
|
|
@@ -27,14 +70,27 @@ export class ChromeDevToolsDriver {
|
|
|
27
70
|
command: this.opts.command ?? MCP_COMMAND,
|
|
28
71
|
args: this.opts.args ?? MCP_ARGS,
|
|
29
72
|
});
|
|
30
|
-
|
|
73
|
+
// If the subprocess dies mid-run, drop the dead client so the next call reconnects.
|
|
74
|
+
transport.onclose = () => {
|
|
75
|
+
if (this.client === client) {
|
|
76
|
+
this.client = undefined;
|
|
77
|
+
this.transport = undefined;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
try {
|
|
81
|
+
await this.withTimeout(client.connect(transport), this.opts.connectTimeoutMs ?? 60_000, "chrome-devtools-mcp connect");
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
await transport.close().catch(() => { }); // don't orphan the spawned subprocess
|
|
85
|
+
throw new Error(`failed to start chrome-devtools-mcp: ${err instanceof Error ? err.message : String(err)}`);
|
|
86
|
+
}
|
|
31
87
|
this.client = client;
|
|
32
88
|
this.transport = transport;
|
|
33
89
|
return client;
|
|
34
90
|
}
|
|
35
91
|
async call(name, args = {}) {
|
|
36
92
|
const client = await this.ensureConnected();
|
|
37
|
-
const res = (await client.callTool({ name, arguments: args }));
|
|
93
|
+
const res = (await this.withTimeout(client.callTool({ name, arguments: args }), this.opts.timeoutMs ?? 30_000, `MCP ${name}`));
|
|
38
94
|
const text = (res.content ?? [])
|
|
39
95
|
.filter((c) => c.type === "text" && typeof c.text === "string")
|
|
40
96
|
.map((c) => c.text)
|
|
@@ -46,18 +102,64 @@ export class ChromeDevToolsDriver {
|
|
|
46
102
|
async goto(url) {
|
|
47
103
|
if (this.initialUrl === undefined)
|
|
48
104
|
this.initialUrl = url;
|
|
49
|
-
|
|
105
|
+
// accept beforeunload so leaving a dirty form/page doesn't hang on a dialog.
|
|
106
|
+
await this.call("navigate_page", { type: "url", url, handleBeforeUnload: "accept" });
|
|
107
|
+
this.snapshotCache = undefined;
|
|
108
|
+
await this.trackPages();
|
|
50
109
|
}
|
|
51
110
|
async click(target) {
|
|
52
|
-
|
|
53
|
-
|
|
111
|
+
await this.call("click", { uid: await this.resolveUid(target) });
|
|
112
|
+
this.snapshotCache = undefined;
|
|
113
|
+
await this.followNewTab();
|
|
114
|
+
}
|
|
115
|
+
async doubleClick(target) {
|
|
116
|
+
await this.call("click", { uid: await this.resolveUid(target), dblClick: true });
|
|
117
|
+
this.snapshotCache = undefined;
|
|
118
|
+
await this.followNewTab();
|
|
119
|
+
}
|
|
120
|
+
async hover(target) {
|
|
121
|
+
await this.call("hover", { uid: await this.resolveUid(target) });
|
|
122
|
+
this.snapshotCache = undefined;
|
|
54
123
|
}
|
|
55
124
|
async type(target, text) {
|
|
56
|
-
|
|
57
|
-
|
|
125
|
+
await this.call("fill", { uid: await this.resolveUid(target), value: text });
|
|
126
|
+
this.snapshotCache = undefined;
|
|
127
|
+
}
|
|
128
|
+
async select(target, value) {
|
|
129
|
+
// chrome-devtools-mcp's `fill` selects an option when the element is a <select>.
|
|
130
|
+
await this.call("fill", { uid: await this.resolveUid(target), value });
|
|
131
|
+
this.snapshotCache = undefined;
|
|
132
|
+
}
|
|
133
|
+
async pressKey(key) {
|
|
134
|
+
await this.call("press_key", { key });
|
|
135
|
+
this.snapshotCache = undefined;
|
|
136
|
+
}
|
|
137
|
+
async scroll(direction = "down") {
|
|
138
|
+
const sign = direction === "up" ? "-" : "";
|
|
139
|
+
await this.call("evaluate_script", {
|
|
140
|
+
function: `() => { window.scrollBy(0, ${sign}window.innerHeight * 0.9); }`,
|
|
141
|
+
});
|
|
142
|
+
this.snapshotCache = undefined;
|
|
143
|
+
}
|
|
144
|
+
async screenshot() {
|
|
145
|
+
try {
|
|
146
|
+
const client = await this.ensureConnected();
|
|
147
|
+
const res = (await this.withTimeout(client.callTool({ name: "take_screenshot", arguments: { format: "png" } }), this.opts.timeoutMs ?? 30_000, "MCP take_screenshot"));
|
|
148
|
+
const img = (res.content ?? []).find((c) => c.type === "image" && typeof c.data === "string");
|
|
149
|
+
return img?.data ? `data:${img.mimeType ?? "image/png"};base64,${img.data}` : undefined;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return undefined; // screenshots are best-effort; never fail a run
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Cache the page snapshot so resolve + the discover loop don't both re-fetch it; actions invalidate it. */
|
|
156
|
+
async getSnapshot() {
|
|
157
|
+
if (this.snapshotCache === undefined)
|
|
158
|
+
this.snapshotCache = await this.call("take_snapshot");
|
|
159
|
+
return this.snapshotCache;
|
|
58
160
|
}
|
|
59
161
|
async snapshot() {
|
|
60
|
-
return parseElements(await this.
|
|
162
|
+
return parseElements(await this.getSnapshot());
|
|
61
163
|
}
|
|
62
164
|
async settle(options = {}) {
|
|
63
165
|
// Chrome defers low-priority resources (favicon, web fonts) past the usual 500ms
|
|
@@ -66,18 +168,22 @@ export class ChromeDevToolsDriver {
|
|
|
66
168
|
const idleMs = options.idleMs ?? 1_000;
|
|
67
169
|
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
68
170
|
const pollMs = options.pollMs ?? 250;
|
|
171
|
+
// Tolerate a trickle of background traffic (analytics beacons, polling, websockets) so
|
|
172
|
+
// those sites reach "idle" instead of always burning the full timeout; a real load
|
|
173
|
+
// burst (>1 new request in the window) still resets the wait.
|
|
174
|
+
const tolerance = 1;
|
|
69
175
|
const deadline = Date.now() + timeoutMs;
|
|
70
|
-
let
|
|
71
|
-
let
|
|
176
|
+
let windowStart = Date.now();
|
|
177
|
+
let windowBase = -1;
|
|
72
178
|
try {
|
|
73
179
|
while (Date.now() < deadline) {
|
|
74
180
|
const count = parseNetwork(await this.call("list_network_requests")).length;
|
|
75
|
-
if (count
|
|
76
|
-
|
|
77
|
-
|
|
181
|
+
if (windowBase < 0 || count - windowBase > tolerance) {
|
|
182
|
+
windowBase = count;
|
|
183
|
+
windowStart = Date.now();
|
|
78
184
|
}
|
|
79
|
-
else if (Date.now() -
|
|
80
|
-
return; //
|
|
185
|
+
else if (Date.now() - windowStart >= idleMs) {
|
|
186
|
+
return; // at most a trickle over idleMs — treat as network-idle
|
|
81
187
|
}
|
|
82
188
|
await delay(pollMs);
|
|
83
189
|
}
|
|
@@ -101,9 +207,13 @@ export class ChromeDevToolsDriver {
|
|
|
101
207
|
};
|
|
102
208
|
}
|
|
103
209
|
async close() {
|
|
104
|
-
|
|
105
|
-
|
|
210
|
+
const client = this.client;
|
|
211
|
+
const transport = this.transport;
|
|
212
|
+
this.client = undefined; // clear first so onclose treats this as an intentional close
|
|
106
213
|
this.transport = undefined;
|
|
214
|
+
this.seenPages.clear();
|
|
215
|
+
await client?.close().catch(() => { });
|
|
216
|
+
await transport?.close().catch(() => { }); // also kill the subprocess on partial/abnormal state
|
|
107
217
|
}
|
|
108
218
|
async resolveUid(target) {
|
|
109
219
|
if (target.selector) {
|
|
@@ -111,7 +221,7 @@ export class ChromeDevToolsDriver {
|
|
|
111
221
|
}
|
|
112
222
|
if (!target.text)
|
|
113
223
|
throw new Error("target needs a `text` to resolve an element");
|
|
114
|
-
const uid = findUidByName(await this.
|
|
224
|
+
const uid = findUidByName(await this.getSnapshot(), target.text);
|
|
115
225
|
if (!uid)
|
|
116
226
|
throw new Error(`no element with accessible name matching "${target.text}"`);
|
|
117
227
|
return uid;
|
|
@@ -128,19 +238,21 @@ export function parseElements(snapshot) {
|
|
|
128
238
|
}
|
|
129
239
|
return out;
|
|
130
240
|
}
|
|
131
|
-
/**
|
|
241
|
+
/**
|
|
242
|
+
* Resolve a uid by accessible name. Prefers an exact (case-insensitive) match over a
|
|
243
|
+
* substring one, so "Cart" picks the button "Cart" rather than the first "Add to Cart".
|
|
244
|
+
* Only the role-adjacent quoted name counts — a bare `url="…"` is never matched as a name.
|
|
245
|
+
*/
|
|
132
246
|
export function findUidByName(snapshot, text) {
|
|
133
|
-
const needle = text.toLowerCase();
|
|
247
|
+
const needle = text.trim().toLowerCase();
|
|
248
|
+
const rows = [];
|
|
134
249
|
for (const line of snapshot.split("\n")) {
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
const nameMatch = line.match(/"([^"]*)"/);
|
|
139
|
-
if (nameMatch && nameMatch[1].toLowerCase().includes(needle)) {
|
|
140
|
-
return uidMatch[1];
|
|
141
|
-
}
|
|
250
|
+
const m = line.match(/uid=(\S+)\s+\w+\s+"([^"]*)"/);
|
|
251
|
+
if (m && m[2].trim())
|
|
252
|
+
rows.push({ uid: m[1], name: m[2] });
|
|
142
253
|
}
|
|
143
|
-
return
|
|
254
|
+
return (rows.find((r) => r.name.toLowerCase() === needle)?.uid ??
|
|
255
|
+
rows.find((r) => r.name.toLowerCase().includes(needle))?.uid);
|
|
144
256
|
}
|
|
145
257
|
/** `reqid=5 GET https://… [200]` → NetworkRequest[]. */
|
|
146
258
|
export function parseNetwork(text) {
|
|
@@ -152,13 +264,13 @@ export function parseNetwork(text) {
|
|
|
152
264
|
}
|
|
153
265
|
return out;
|
|
154
266
|
}
|
|
155
|
-
/**
|
|
267
|
+
/** `msgid=1 [error] message (1 args)` → {type:"error", text:"message"}. */
|
|
156
268
|
export function parseConsole(text) {
|
|
157
269
|
const out = [];
|
|
158
270
|
for (const line of text.split("\n")) {
|
|
159
|
-
const m = line.match(
|
|
271
|
+
const m = line.match(/^msgid=\d+\s+\[(\w+)\]\s+(.*)$/);
|
|
160
272
|
if (m)
|
|
161
|
-
out.push({ type: m[1].toLowerCase(), text: m[2].trim() });
|
|
273
|
+
out.push({ type: m[1].toLowerCase(), text: m[2].replace(/\s*\(\d+ args?\)\s*$/, "").trim() });
|
|
162
274
|
}
|
|
163
275
|
return out;
|
|
164
276
|
}
|
|
@@ -178,6 +290,16 @@ export function isNavigation(initialUrl, finalUrl) {
|
|
|
178
290
|
return true;
|
|
179
291
|
return normalizeUrl(initialUrl) !== normalizeUrl(finalUrl);
|
|
180
292
|
}
|
|
293
|
+
/** `4: Example Domain (…) [selected]` → page ids [4]. Ids are stable, increasing numbers. */
|
|
294
|
+
export function parsePageIds(text) {
|
|
295
|
+
const ids = [];
|
|
296
|
+
for (const line of text.split("\n")) {
|
|
297
|
+
const m = line.match(/^\s*(\d+):/);
|
|
298
|
+
if (m)
|
|
299
|
+
ids.push(Number(m[1]));
|
|
300
|
+
}
|
|
301
|
+
return ids;
|
|
302
|
+
}
|
|
181
303
|
/** `2: Example Domain (https://example.com/) [selected]` → the selected page's url. */
|
|
182
304
|
export function parseSelectedUrl(text) {
|
|
183
305
|
for (const line of text.split("\n")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../src/adapters/drivers/chrome.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../src/adapters/drivers/chrome.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import type { Evidence, PageElement, Target } from "../../core/types.js";
|
|
|
4
4
|
export interface FakeScript {
|
|
5
5
|
evidence: Evidence;
|
|
6
6
|
elements?: PageElement[];
|
|
7
|
+
screenshot?: string;
|
|
7
8
|
/** Targets (by text) that should throw when acted on, to simulate a broken step. */
|
|
8
9
|
failOn?: string[];
|
|
9
10
|
}
|
|
@@ -13,10 +14,21 @@ export declare class FakeDriver implements Driver {
|
|
|
13
14
|
settled: boolean;
|
|
14
15
|
readonly visited: string[];
|
|
15
16
|
readonly clicked: Target[];
|
|
17
|
+
readonly hovered: Target[];
|
|
18
|
+
readonly keys: string[];
|
|
19
|
+
readonly scrolls: string[];
|
|
16
20
|
constructor(script: FakeScript);
|
|
21
|
+
/** Throws if the target is in `failOn`, simulating an unresolvable element. */
|
|
22
|
+
private resolve;
|
|
17
23
|
goto(url: string): Promise<void>;
|
|
18
24
|
click(target: Target): Promise<void>;
|
|
25
|
+
doubleClick(target: Target): Promise<void>;
|
|
26
|
+
hover(target: Target): Promise<void>;
|
|
19
27
|
type(target: Target, _text: string): Promise<void>;
|
|
28
|
+
select(target: Target, _value: string): Promise<void>;
|
|
29
|
+
pressKey(key: string): Promise<void>;
|
|
30
|
+
scroll(direction?: "down" | "up"): Promise<void>;
|
|
31
|
+
screenshot(): Promise<string | undefined>;
|
|
20
32
|
snapshot(): Promise<PageElement[]>;
|
|
21
33
|
settle(): Promise<void>;
|
|
22
34
|
observe(): Promise<Evidence>;
|
|
@@ -4,22 +4,47 @@ export class FakeDriver {
|
|
|
4
4
|
settled = false;
|
|
5
5
|
visited = [];
|
|
6
6
|
clicked = [];
|
|
7
|
+
hovered = [];
|
|
8
|
+
keys = [];
|
|
9
|
+
scrolls = [];
|
|
7
10
|
constructor(script) {
|
|
8
11
|
this.script = script;
|
|
9
12
|
}
|
|
13
|
+
/** Throws if the target is in `failOn`, simulating an unresolvable element. */
|
|
14
|
+
resolve(target) {
|
|
15
|
+
if (target.text && this.script.failOn?.includes(target.text)) {
|
|
16
|
+
throw new Error(`element not found: ${target.text}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
10
19
|
async goto(url) {
|
|
11
20
|
this.visited.push(url);
|
|
12
21
|
}
|
|
13
22
|
async click(target) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
this.resolve(target);
|
|
24
|
+
this.clicked.push(target);
|
|
25
|
+
}
|
|
26
|
+
async doubleClick(target) {
|
|
27
|
+
this.resolve(target);
|
|
17
28
|
this.clicked.push(target);
|
|
18
29
|
}
|
|
30
|
+
async hover(target) {
|
|
31
|
+
this.resolve(target);
|
|
32
|
+
this.hovered.push(target);
|
|
33
|
+
}
|
|
19
34
|
async type(target, _text) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
this.resolve(target);
|
|
36
|
+
}
|
|
37
|
+
async select(target, _value) {
|
|
38
|
+
this.resolve(target);
|
|
39
|
+
}
|
|
40
|
+
async pressKey(key) {
|
|
41
|
+
this.keys.push(key);
|
|
42
|
+
}
|
|
43
|
+
async scroll(direction = "down") {
|
|
44
|
+
this.scrolls.push(direction);
|
|
45
|
+
}
|
|
46
|
+
async screenshot() {
|
|
47
|
+
return this.script.screenshot;
|
|
23
48
|
}
|
|
24
49
|
async snapshot() {
|
|
25
50
|
return this.script.elements ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake.js","sourceRoot":"","sources":["../../../src/adapters/drivers/fake.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fake.js","sourceRoot":"","sources":["../../../src/adapters/drivers/fake.ts"],"names":[],"mappings":"AAYA,MAAM,OAAO,UAAU;IASQ;IAR7B,MAAM,GAAG,KAAK,CAAC;IACf,OAAO,GAAG,KAAK,CAAC;IACP,OAAO,GAAa,EAAE,CAAC;IACvB,OAAO,GAAa,EAAE,CAAC;IACvB,OAAO,GAAa,EAAE,CAAC;IACvB,IAAI,GAAa,EAAE,CAAC;IACpB,OAAO,GAAa,EAAE,CAAC;IAEhC,YAA6B,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;IAAG,CAAC;IAEnD,+EAA+E;IACvE,OAAO,CAAC,MAAc;QAC5B,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,KAAa;QACtC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,YAA2B,MAAM;QAC5C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -25,7 +25,13 @@ export declare class SelfHealingDriver implements Driver {
|
|
|
25
25
|
constructor(inner: Driver, llm: LlmClient, opts?: SelfHealOptions);
|
|
26
26
|
goto(url: string): Promise<void>;
|
|
27
27
|
click(target: Target): Promise<void>;
|
|
28
|
+
doubleClick(target: Target): Promise<void>;
|
|
29
|
+
hover(target: Target): Promise<void>;
|
|
28
30
|
type(target: Target, text: string): Promise<void>;
|
|
31
|
+
select(target: Target, value: string): Promise<void>;
|
|
32
|
+
pressKey(key: string): Promise<void>;
|
|
33
|
+
scroll(direction?: "down" | "up"): Promise<void>;
|
|
34
|
+
screenshot(): Promise<string | undefined>;
|
|
29
35
|
snapshot(): Promise<PageElement[]>;
|
|
30
36
|
settle(options?: SettleOptions): Promise<void>;
|
|
31
37
|
observe(): Promise<Evidence>;
|
|
@@ -46,8 +46,23 @@ export class SelfHealingDriver {
|
|
|
46
46
|
await this.inner.click(target);
|
|
47
47
|
}
|
|
48
48
|
catch (err) {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
await this.inner.click({ text: await this.heal(target, err) });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async doubleClick(target) {
|
|
53
|
+
try {
|
|
54
|
+
await this.inner.doubleClick(target);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
await this.inner.doubleClick({ text: await this.heal(target, err) });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async hover(target) {
|
|
61
|
+
try {
|
|
62
|
+
await this.inner.hover(target);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
await this.inner.hover({ text: await this.heal(target, err) });
|
|
51
66
|
}
|
|
52
67
|
}
|
|
53
68
|
async type(target, text) {
|
|
@@ -55,10 +70,26 @@ export class SelfHealingDriver {
|
|
|
55
70
|
await this.inner.type(target, text);
|
|
56
71
|
}
|
|
57
72
|
catch (err) {
|
|
58
|
-
|
|
59
|
-
await this.inner.type({ text: healed }, text);
|
|
73
|
+
await this.inner.type({ text: await this.heal(target, err) }, text);
|
|
60
74
|
}
|
|
61
75
|
}
|
|
76
|
+
async select(target, value) {
|
|
77
|
+
try {
|
|
78
|
+
await this.inner.select(target, value);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
await this.inner.select({ text: await this.heal(target, err) }, value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
pressKey(key) {
|
|
85
|
+
return this.inner.pressKey(key);
|
|
86
|
+
}
|
|
87
|
+
scroll(direction) {
|
|
88
|
+
return this.inner.scroll(direction);
|
|
89
|
+
}
|
|
90
|
+
screenshot() {
|
|
91
|
+
return this.inner.screenshot();
|
|
92
|
+
}
|
|
62
93
|
snapshot() {
|
|
63
94
|
return this.inner.snapshot();
|
|
64
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self-heal.js","sourceRoot":"","sources":["../../../src/adapters/drivers/self-heal.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,GACf,wFAAwF;IACxF,wFAAwF;IACxF,mFAAmF;IACnF,8FAA8F;IAC9F,mBAAmB,CAAC;AAEtB,SAAS,UAAU,CAAC,MAAc,EAAE,QAAuB;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,WAAW,CAAC;IAC3D,MAAM,IAAI,GAAG,QAAQ;SAClB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;SACrC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO;QACL,oBAAoB,IAAI,EAAE;QAC1B,EAAE;QACF,+BAA+B;QAC/B,IAAI,IAAI,QAAQ;QAChB,EAAE;QACF,oEAAoE;KACrE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC7E,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAChG,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAuB,CAAC;IACtE,OAAO,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,MAAM,OAAO,iBAAiB;IAKT;IACA;IALV,KAAK,GAAW,EAAE,CAAC;IACX,QAAQ,CAAS;IAElC,YACmB,KAAa,EACb,GAAc,EAC/B,OAAwB,EAAE;QAFT,UAAK,GAAL,KAAK,CAAQ;QACb,QAAG,GAAH,GAAG,CAAW;QAG/B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"self-heal.js","sourceRoot":"","sources":["../../../src/adapters/drivers/self-heal.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,12 +7,18 @@ export interface AnthropicOptions {
|
|
|
7
7
|
apiKey?: string;
|
|
8
8
|
model?: string;
|
|
9
9
|
baseUrl?: string;
|
|
10
|
+
/** Per-request timeout (ms). Default 60s — a stalled connection rejects instead of hanging. */
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
/** Retries on transient errors (429 / 5xx). Default 2. */
|
|
13
|
+
maxRetries?: number;
|
|
10
14
|
}
|
|
11
15
|
export declare class AnthropicLlmClient implements LlmClient {
|
|
12
16
|
readonly id: string;
|
|
13
17
|
private readonly apiKey;
|
|
14
18
|
private readonly model;
|
|
15
19
|
private readonly baseUrl;
|
|
20
|
+
private readonly timeoutMs;
|
|
21
|
+
private readonly maxRetries;
|
|
16
22
|
constructor(opts?: AnthropicOptions);
|
|
17
23
|
complete(prompt: string, opts?: CompleteOptions): Promise<string>;
|
|
18
24
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
1
2
|
export class AnthropicLlmClient {
|
|
2
3
|
id;
|
|
3
4
|
apiKey;
|
|
4
5
|
model;
|
|
5
6
|
baseUrl;
|
|
7
|
+
timeoutMs;
|
|
8
|
+
maxRetries;
|
|
6
9
|
constructor(opts = {}) {
|
|
7
10
|
const apiKey = opts.apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
8
11
|
if (!apiKey)
|
|
@@ -10,32 +13,60 @@ export class AnthropicLlmClient {
|
|
|
10
13
|
this.apiKey = apiKey;
|
|
11
14
|
this.model = opts.model ?? "claude-sonnet-4-6";
|
|
12
15
|
this.baseUrl = opts.baseUrl ?? "https://api.anthropic.com";
|
|
16
|
+
this.timeoutMs = opts.timeoutMs ?? 60_000;
|
|
17
|
+
this.maxRetries = opts.maxRetries ?? 2;
|
|
13
18
|
this.id = `anthropic:${this.model}`;
|
|
14
19
|
}
|
|
15
20
|
async complete(prompt, opts = {}) {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"anthropic-version": "2023-06-01",
|
|
22
|
-
},
|
|
23
|
-
body: JSON.stringify({
|
|
24
|
-
model: this.model,
|
|
25
|
-
max_tokens: opts.maxTokens ?? 1024,
|
|
26
|
-
...(opts.system ? { system: opts.system } : {}),
|
|
27
|
-
messages: [{ role: "user", content: prompt }],
|
|
28
|
-
}),
|
|
21
|
+
const body = JSON.stringify({
|
|
22
|
+
model: this.model,
|
|
23
|
+
max_tokens: opts.maxTokens ?? 1024,
|
|
24
|
+
...(opts.system ? { system: opts.system } : {}),
|
|
25
|
+
messages: [{ role: "user", content: prompt }],
|
|
29
26
|
});
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
for (let attempt = 0;; attempt++) {
|
|
28
|
+
const controller = new AbortController();
|
|
29
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
30
|
+
try {
|
|
31
|
+
const res = await fetch(`${this.baseUrl}/v1/messages`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: {
|
|
34
|
+
"content-type": "application/json",
|
|
35
|
+
"x-api-key": this.apiKey,
|
|
36
|
+
"anthropic-version": "2023-06-01",
|
|
37
|
+
},
|
|
38
|
+
body,
|
|
39
|
+
signal: controller.signal,
|
|
40
|
+
});
|
|
41
|
+
if (res.ok) {
|
|
42
|
+
const data = (await res.json());
|
|
43
|
+
return (data.content ?? [])
|
|
44
|
+
.filter((c) => c.type === "text" && typeof c.text === "string")
|
|
45
|
+
.map((c) => c.text)
|
|
46
|
+
.join("")
|
|
47
|
+
.trim();
|
|
48
|
+
}
|
|
49
|
+
// Back off on transient errors (rate limit / overloaded / server), else fail.
|
|
50
|
+
if ((res.status === 429 || res.status >= 500) && attempt < this.maxRetries) {
|
|
51
|
+
await delay(500 * 2 ** attempt);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Anthropic API ${res.status}: ${await res.text()}`);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
const aborted = err instanceof Error && err.name === "AbortError";
|
|
58
|
+
if (aborted && attempt >= this.maxRetries)
|
|
59
|
+
throw new Error(`Anthropic request timed out after ${this.timeoutMs}ms`);
|
|
60
|
+
if (aborted) {
|
|
61
|
+
await delay(500 * 2 ** attempt);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
clearTimeout(timer);
|
|
68
|
+
}
|
|
32
69
|
}
|
|
33
|
-
const data = (await res.json());
|
|
34
|
-
return (data.content ?? [])
|
|
35
|
-
.filter((c) => c.type === "text" && typeof c.text === "string")
|
|
36
|
-
.map((c) => c.text)
|
|
37
|
-
.join("")
|
|
38
|
-
.trim();
|
|
39
70
|
}
|
|
40
71
|
}
|
|
41
72
|
//# sourceMappingURL=anthropic.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/adapters/llm/anthropic.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/adapters/llm/anthropic.ts"],"names":[],"mappings":"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"}
|
package/dist/core/discover.d.ts
CHANGED
|
@@ -11,11 +11,15 @@ export interface DiscoverOptions {
|
|
|
11
11
|
baseUrl?: string;
|
|
12
12
|
maxSteps?: number;
|
|
13
13
|
onStep?: (decision: Decision, step?: Step) => void;
|
|
14
|
+
/** Abort discovery between steps (a host's Stop button). */
|
|
15
|
+
signal?: AbortSignal;
|
|
14
16
|
}
|
|
15
17
|
export interface Decision {
|
|
16
|
-
action: "click" | "type" | "goto" | "done";
|
|
18
|
+
action: "click" | "doubleClick" | "hover" | "type" | "select" | "pressKey" | "scroll" | "goto" | "done";
|
|
17
19
|
text?: string;
|
|
18
20
|
value?: string;
|
|
21
|
+
key?: string;
|
|
22
|
+
direction?: "down" | "up";
|
|
19
23
|
url?: string;
|
|
20
24
|
reason?: string;
|
|
21
25
|
assertions?: Assertion[];
|
package/dist/core/discover.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
const SYSTEM = "You are a QA agent driving a web browser to satisfy a natural-language intent. " +
|
|
2
2
|
"At each turn you see the page's interactive elements and the actions taken so far. " +
|
|
3
3
|
"Respond with ONE next action as strict JSON, no prose, no code fences. " +
|
|
4
|
-
|
|
5
|
-
'
|
|
6
|
-
'
|
|
7
|
-
'{"
|
|
8
|
-
|
|
4
|
+
"Actions: " +
|
|
5
|
+
'{"action":"click","text":"<element>"} · {"action":"doubleClick","text":"<element>"} · ' +
|
|
6
|
+
'{"action":"hover","text":"<element>"} (reveals flyout/dropdown menus) · ' +
|
|
7
|
+
'{"action":"type","text":"<element>","value":"<text>"} · {"action":"select","text":"<element>","value":"<option>"} · ' +
|
|
8
|
+
'{"action":"pressKey","key":"Enter|Escape|Tab|..."} · {"action":"scroll","direction":"down|up"} (load lazy content) · ' +
|
|
9
|
+
'{"action":"goto","url":"<url>"} · {"action":"done"}. ' +
|
|
10
|
+
'Always add "reason":"<short>". Use the exact element name shown. To open a menu before clicking a hidden item, hover it first. ' +
|
|
11
|
+
'Use "done" when the intent is achieved (or impossible); with "done" you may include "assertions": an array of ' +
|
|
12
|
+
'{"kind":"navigated"} | {"kind":"no-failed-requests"} | {"kind":"no-console-errors"} | {"kind":"request-status","urlIncludes":"...","status":200}.';
|
|
13
|
+
function buildPrompt(intent, elements, steps, failures) {
|
|
9
14
|
const els = elements
|
|
10
15
|
.slice(0, 60)
|
|
11
16
|
.map((e) => `- [${e.role}] ${e.name}`)
|
|
@@ -16,6 +21,9 @@ function buildPrompt(intent, elements, steps) {
|
|
|
16
21
|
return [
|
|
17
22
|
`Intent: ${intent}`,
|
|
18
23
|
``,
|
|
24
|
+
...(failures.length
|
|
25
|
+
? [`These actions ALREADY FAILED — do NOT repeat them, choose a different element or approach:`, ...failures.map((f) => `- ${f}`), ``]
|
|
26
|
+
: []),
|
|
19
27
|
`Actions taken so far:`,
|
|
20
28
|
history,
|
|
21
29
|
``,
|
|
@@ -45,47 +53,76 @@ function sanitizeAssertions(input) {
|
|
|
45
53
|
const valid = (input ?? []).filter((a) => a && KNOWN_KINDS.has(a.kind));
|
|
46
54
|
return valid.length ? valid : [{ kind: "no-failed-requests" }];
|
|
47
55
|
}
|
|
56
|
+
/** Execute a non-`done` decision and return the Step it produced. Throws if it fails. */
|
|
57
|
+
async function applyDecision(driver, decision) {
|
|
58
|
+
const needText = () => {
|
|
59
|
+
if (!decision.text)
|
|
60
|
+
throw new Error(`${decision.action} decision missing "text"`);
|
|
61
|
+
return decision.text;
|
|
62
|
+
};
|
|
63
|
+
switch (decision.action) {
|
|
64
|
+
case "click":
|
|
65
|
+
await driver.click({ text: needText() });
|
|
66
|
+
return { kind: "click", target: { text: needText() } };
|
|
67
|
+
case "doubleClick":
|
|
68
|
+
await driver.doubleClick({ text: needText() });
|
|
69
|
+
return { kind: "doubleClick", target: { text: needText() } };
|
|
70
|
+
case "hover":
|
|
71
|
+
await driver.hover({ text: needText() });
|
|
72
|
+
return { kind: "hover", target: { text: needText() } };
|
|
73
|
+
case "type":
|
|
74
|
+
await driver.type({ text: needText() }, decision.value ?? "");
|
|
75
|
+
return { kind: "type", target: { text: needText() }, text: decision.value ?? "" };
|
|
76
|
+
case "select":
|
|
77
|
+
await driver.select({ text: needText() }, decision.value ?? "");
|
|
78
|
+
return { kind: "select", target: { text: needText() }, value: decision.value ?? "" };
|
|
79
|
+
case "pressKey":
|
|
80
|
+
if (!decision.key)
|
|
81
|
+
throw new Error('pressKey decision missing "key"');
|
|
82
|
+
await driver.pressKey(decision.key);
|
|
83
|
+
return { kind: "pressKey", key: decision.key };
|
|
84
|
+
case "scroll":
|
|
85
|
+
await driver.scroll(decision.direction);
|
|
86
|
+
return { kind: "scroll", direction: decision.direction };
|
|
87
|
+
case "goto":
|
|
88
|
+
if (!decision.url)
|
|
89
|
+
throw new Error('goto decision missing "url"');
|
|
90
|
+
await driver.goto(decision.url);
|
|
91
|
+
return { kind: "goto", url: decision.url };
|
|
92
|
+
default:
|
|
93
|
+
throw new Error(`unknown action: ${decision.action}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
48
96
|
export async function discover(intent, opts) {
|
|
49
|
-
const { driver, llm, baseUrl, maxSteps = 8, onStep } = opts;
|
|
97
|
+
const { driver, llm, baseUrl, maxSteps = 8, onStep, signal } = opts;
|
|
50
98
|
const steps = [];
|
|
51
99
|
if (baseUrl) {
|
|
52
100
|
await driver.goto(baseUrl);
|
|
53
101
|
steps.push({ kind: "goto", url: baseUrl });
|
|
54
102
|
}
|
|
103
|
+
// Remember what already failed so the LLM stops retrying dead ends (real sites have
|
|
104
|
+
// hover menus, overlays, maintenance pages). ADAPT is the point of the loop (invariant #3).
|
|
105
|
+
const failures = [];
|
|
55
106
|
for (let i = 0; i < maxSteps; i++) {
|
|
107
|
+
signal?.throwIfAborted();
|
|
56
108
|
await driver.settle();
|
|
57
109
|
const elements = await driver.snapshot();
|
|
58
|
-
const reply = await llm.complete(buildPrompt(intent, elements, steps), { system: SYSTEM });
|
|
110
|
+
const reply = await llm.complete(buildPrompt(intent, elements, steps, failures), { system: SYSTEM });
|
|
59
111
|
const decision = parseDecision(reply);
|
|
60
112
|
if (decision.action === "done") {
|
|
61
113
|
onStep?.(decision);
|
|
62
114
|
return { name: intent, steps, assertions: sanitizeAssertions(decision.assertions) };
|
|
63
115
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!decision.text)
|
|
74
|
-
throw new Error('type decision missing "text"');
|
|
75
|
-
await driver.type({ text: decision.text }, decision.value ?? "");
|
|
76
|
-
step = { kind: "type", target: { text: decision.text }, text: decision.value ?? "" };
|
|
77
|
-
break;
|
|
78
|
-
case "goto":
|
|
79
|
-
if (!decision.url)
|
|
80
|
-
throw new Error('goto decision missing "url"');
|
|
81
|
-
await driver.goto(decision.url);
|
|
82
|
-
step = { kind: "goto", url: decision.url };
|
|
83
|
-
break;
|
|
84
|
-
default:
|
|
85
|
-
throw new Error(`unknown action: ${decision.action}`);
|
|
116
|
+
try {
|
|
117
|
+
const step = await applyDecision(driver, decision);
|
|
118
|
+
steps.push(step);
|
|
119
|
+
onStep?.(decision, step);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const what = `${decision.action}${decision.text ? ` "${decision.text}"` : decision.url ? ` ${decision.url}` : ""}`;
|
|
123
|
+
failures.push(`${what} — ${err instanceof Error ? err.message : String(err)}`);
|
|
124
|
+
onStep?.(decision);
|
|
86
125
|
}
|
|
87
|
-
steps.push(step);
|
|
88
|
-
onStep?.(decision, step);
|
|
89
126
|
}
|
|
90
127
|
// Safety cap reached without an explicit "done".
|
|
91
128
|
return { name: intent, steps, assertions: [{ kind: "no-failed-requests" }] };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/core/discover.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/core/discover.ts"],"names":[],"mappings":"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"}
|
package/dist/core/pipeline.d.ts
CHANGED
|
@@ -4,5 +4,15 @@
|
|
|
4
4
|
* runs (invariant #4).
|
|
5
5
|
*/
|
|
6
6
|
import type { Harness } from "./ports.js";
|
|
7
|
-
import type { Result } from "./types.js";
|
|
8
|
-
|
|
7
|
+
import type { Result, StepProgress } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Seams a host (CLI, desktop app, CI) plugs into — the engine emits/accepts, the host
|
|
10
|
+
* decides what to do. `onStep` for a live timeline, `captureScreenshots` for visual
|
|
11
|
+
* replay, `signal` for a Stop button. None of these put UI in the engine.
|
|
12
|
+
*/
|
|
13
|
+
export interface RunHarnessOptions {
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
onStep?: (progress: StepProgress) => void;
|
|
16
|
+
captureScreenshots?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function runHarness(harness: Harness, task: string, opts?: RunHarnessOptions): Promise<Result>;
|
package/dist/core/pipeline.js
CHANGED
|
@@ -7,9 +7,28 @@ async function executeStep(driver, step) {
|
|
|
7
7
|
case "click":
|
|
8
8
|
await driver.click(step.target);
|
|
9
9
|
break;
|
|
10
|
+
case "doubleClick":
|
|
11
|
+
await driver.doubleClick(step.target);
|
|
12
|
+
break;
|
|
13
|
+
case "hover":
|
|
14
|
+
await driver.hover(step.target);
|
|
15
|
+
break;
|
|
10
16
|
case "type":
|
|
11
17
|
await driver.type(step.target, step.text);
|
|
12
18
|
break;
|
|
19
|
+
case "select":
|
|
20
|
+
await driver.select(step.target, step.value);
|
|
21
|
+
break;
|
|
22
|
+
case "pressKey":
|
|
23
|
+
await driver.pressKey(step.key);
|
|
24
|
+
break;
|
|
25
|
+
case "scroll":
|
|
26
|
+
await driver.scroll(step.direction);
|
|
27
|
+
break;
|
|
28
|
+
default: {
|
|
29
|
+
const unhandled = step;
|
|
30
|
+
throw new Error(`unhandled step kind: ${JSON.stringify(unhandled)}`);
|
|
31
|
+
}
|
|
13
32
|
}
|
|
14
33
|
return { step, ok: true };
|
|
15
34
|
}
|
|
@@ -17,7 +36,7 @@ async function executeStep(driver, step) {
|
|
|
17
36
|
return { step, ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
18
37
|
}
|
|
19
38
|
}
|
|
20
|
-
export async function runHarness(harness, task) {
|
|
39
|
+
export async function runHarness(harness, task, opts = {}) {
|
|
21
40
|
const { context, planner, driver, critic, reporter } = harness;
|
|
22
41
|
const ctx = await context.provide(task);
|
|
23
42
|
const scenario = await planner.plan(ctx);
|
|
@@ -25,8 +44,13 @@ export async function runHarness(harness, task) {
|
|
|
25
44
|
const actions = [];
|
|
26
45
|
try {
|
|
27
46
|
for (const step of scenario.steps) {
|
|
47
|
+
opts.signal?.throwIfAborted(); // cooperative cancellation between steps (host owns Stop)
|
|
28
48
|
const result = await executeStep(driver, step);
|
|
29
49
|
actions.push(result);
|
|
50
|
+
if (opts.onStep) {
|
|
51
|
+
const screenshot = opts.captureScreenshots ? await driver.screenshot().catch(() => undefined) : undefined;
|
|
52
|
+
opts.onStep({ index: actions.length - 1, step, ok: result.ok, error: result.error, screenshot });
|
|
53
|
+
}
|
|
30
54
|
if (!result.ok)
|
|
31
55
|
break;
|
|
32
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"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"}
|
package/dist/core/ports.d.ts
CHANGED
|
@@ -15,7 +15,17 @@ export interface Planner {
|
|
|
15
15
|
export interface Driver {
|
|
16
16
|
goto(url: string): Promise<void>;
|
|
17
17
|
click(target: Target): Promise<void>;
|
|
18
|
+
doubleClick(target: Target): Promise<void>;
|
|
19
|
+
hover(target: Target): Promise<void>;
|
|
18
20
|
type(target: Target, text: string): Promise<void>;
|
|
21
|
+
/** Choose an option in a `<select>` dropdown. */
|
|
22
|
+
select(target: Target, value: string): Promise<void>;
|
|
23
|
+
/** Press a key or combo (e.g. "Enter", "Escape", "Control+a"). */
|
|
24
|
+
pressKey(key: string): Promise<void>;
|
|
25
|
+
/** Scroll the page to reveal lazy/below-the-fold content. */
|
|
26
|
+
scroll(direction?: "down" | "up"): Promise<void>;
|
|
27
|
+
/** Capture the current page as a data URL (for visual replay); undefined if unavailable. */
|
|
28
|
+
screenshot(): Promise<string | undefined>;
|
|
19
29
|
snapshot(): Promise<PageElement[]>;
|
|
20
30
|
/** Execute-stage auto-wait for network idle (design §3). Best-effort, time-bounded, never throws. */
|
|
21
31
|
settle(options?: SettleOptions): Promise<void>;
|
package/dist/core/types.d.ts
CHANGED
|
@@ -10,10 +10,26 @@ export type Step = {
|
|
|
10
10
|
} | {
|
|
11
11
|
kind: "click";
|
|
12
12
|
target: Target;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "doubleClick";
|
|
15
|
+
target: Target;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "hover";
|
|
18
|
+
target: Target;
|
|
13
19
|
} | {
|
|
14
20
|
kind: "type";
|
|
15
21
|
target: Target;
|
|
16
22
|
text: string;
|
|
23
|
+
} | {
|
|
24
|
+
kind: "select";
|
|
25
|
+
target: Target;
|
|
26
|
+
value: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "pressKey";
|
|
29
|
+
key: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: "scroll";
|
|
32
|
+
direction?: "down" | "up";
|
|
17
33
|
};
|
|
18
34
|
/** Locate an element by intent, not a driver handle: `text` = accessible name, `selector` = CSS fallback. */
|
|
19
35
|
export interface Target {
|
|
@@ -49,6 +65,15 @@ export interface PageElement {
|
|
|
49
65
|
role: string;
|
|
50
66
|
name: string;
|
|
51
67
|
}
|
|
68
|
+
/** Emitted per executed step so a consumer (e.g. a desktop timeline) can render live progress. */
|
|
69
|
+
export interface StepProgress {
|
|
70
|
+
index: number;
|
|
71
|
+
step: Step;
|
|
72
|
+
ok: boolean;
|
|
73
|
+
error?: string;
|
|
74
|
+
/** A screenshot data URL, present only when screenshot capture is enabled. */
|
|
75
|
+
screenshot?: string;
|
|
76
|
+
}
|
|
52
77
|
export interface SettleOptions {
|
|
53
78
|
idleMs?: number;
|
|
54
79
|
timeoutMs?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export * from "./core/types.js";
|
|
3
3
|
export * from "./core/ports.js";
|
|
4
4
|
export { runHarness } from "./core/pipeline.js";
|
|
5
|
+
export type { RunHarnessOptions } from "./core/pipeline.js";
|
|
5
6
|
export { runScenario, needsLlmCritic, applyHeals } from "./run.js";
|
|
6
7
|
export type { RunScenarioOptions, RunScenarioResult } from "./run.js";
|
|
7
8
|
export { InlineContextProvider } from "./adapters/context/inline.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/run.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ContextProvider, Critic, Driver, LlmClient, Reporter } from "./core/ports.js";
|
|
2
2
|
import type { Heal } from "./adapters/drivers/self-heal.js";
|
|
3
|
-
import type { Result, Scenario } from "./core/types.js";
|
|
3
|
+
import type { Result, Scenario, StepProgress } from "./core/types.js";
|
|
4
4
|
export interface RunScenarioOptions {
|
|
5
5
|
driver?: Driver;
|
|
6
6
|
/** Default: LlmCritic if the scenario has `expect`, else AssertionCritic. */
|
|
@@ -11,6 +11,12 @@ export interface RunScenarioOptions {
|
|
|
11
11
|
/** Wrap the driver so broken steps are repaired by the LLM and retried. */
|
|
12
12
|
heal?: boolean;
|
|
13
13
|
model?: string;
|
|
14
|
+
/** Abort the run between steps (a host's Stop button). */
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
/** Per-step progress, for a live timeline. */
|
|
17
|
+
onStep?: (progress: StepProgress) => void;
|
|
18
|
+
/** Capture a screenshot after each step (attached to onStep / a host's visual replay). */
|
|
19
|
+
screenshots?: boolean;
|
|
14
20
|
}
|
|
15
21
|
export interface RunScenarioResult {
|
|
16
22
|
result: Result;
|
package/dist/run.js
CHANGED
|
@@ -23,7 +23,7 @@ export function applyHeals(scenario, heals) {
|
|
|
23
23
|
return {
|
|
24
24
|
...scenario,
|
|
25
25
|
steps: scenario.steps.map((step) => {
|
|
26
|
-
if (
|
|
26
|
+
if ("target" in step && step.target.text) {
|
|
27
27
|
const healed = byOriginal.get(step.target.text);
|
|
28
28
|
if (healed)
|
|
29
29
|
return { ...step, target: { ...step.target, text: healed } };
|
|
@@ -46,7 +46,7 @@ export async function runScenario(scenario, opts = {}) {
|
|
|
46
46
|
driver,
|
|
47
47
|
critic,
|
|
48
48
|
reporter: opts.reporter ?? new ConsoleReporter(),
|
|
49
|
-
}, scenario.name);
|
|
49
|
+
}, scenario.name, { signal: opts.signal, onStep: opts.onStep, captureScreenshots: opts.screenshots });
|
|
50
50
|
const heals = healer?.heals ?? [];
|
|
51
51
|
return { result, heals, healedScenario: heals.length ? applyHeals(scenario, heals) : undefined };
|
|
52
52
|
}
|
package/dist/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|