abelworkflow 1.2.4 → 1.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 +26 -25
- package/extensions/gpt-responses-compat.ts +1 -1
- package/lib/cli/main.mjs +18 -86
- package/lib/cli/pi.mjs +43 -0
- package/lib/cli/prompts.mjs +3 -3
- package/lib/installer/assets.mjs +35 -31
- package/lib/installer/install.mjs +29 -9
- package/lib/installer/links.mjs +97 -84
- package/lib/paths.mjs +0 -2
- package/lib/providers/claude.mjs +14 -3
- package/lib/providers/codex.mjs +14 -9
- package/lib/providers/pi.mjs +61 -68
- package/lib/providers/skills.mjs +22 -22
- package/lib/providers/url.mjs +32 -1
- package/lib/templates/codex/agents/default.toml +16 -54
- package/lib/templates/codex/agents/explorer.toml +25 -52
- package/lib/templates/codex/agents/planner.toml +23 -77
- package/lib/templates/codex/agents/reviewer.toml +16 -62
- package/lib/templates/codex/agents/worker.toml +30 -64
- package/lib/templates/codex/config-base.toml +0 -6
- package/lib/templates/{workflow/gitignore.template → gitignore.template} +0 -3
- package/lib/tools/cli-installer.mjs +40 -12
- package/package.json +13 -18
- package/lib/templates/workflow/AGENTS.md +0 -50
- package/lib/templates/workflow/commands/abel-design.md +0 -175
- package/lib/templates/workflow/commands/abel-diagnose.md +0 -63
- package/lib/templates/workflow/commands/abel-implement.md +0 -170
- package/lib/templates/workflow/commands/abel-init.md +0 -25
- package/skills/dev-browser/SKILL.md +0 -281
- package/skills/dev-browser/dist/scripts/start.d.ts +0 -1
- package/skills/dev-browser/dist/scripts/start.js +0 -90
- package/skills/dev-browser/dist/src/client.d.ts +0 -92
- package/skills/dev-browser/dist/src/client.js +0 -310
- package/skills/dev-browser/dist/src/entrypoint.d.ts +0 -29
- package/skills/dev-browser/dist/src/entrypoint.js +0 -113
- package/skills/dev-browser/dist/src/index.d.ts +0 -3
- package/skills/dev-browser/dist/src/index.js +0 -1
- package/skills/dev-browser/dist/src/page-api.d.ts +0 -24
- package/skills/dev-browser/dist/src/page-api.js +0 -103
- package/skills/dev-browser/dist/src/relay.d.ts +0 -26
- package/skills/dev-browser/dist/src/relay.js +0 -567
- package/skills/dev-browser/dist/src/runtime.d.ts +0 -34
- package/skills/dev-browser/dist/src/runtime.js +0 -44
- package/skills/dev-browser/dist/src/snapshot/browser-script.d.ts +0 -22
- package/skills/dev-browser/dist/src/snapshot/browser-script.js +0 -868
- package/skills/dev-browser/dist/src/snapshot/index.d.ts +0 -13
- package/skills/dev-browser/dist/src/snapshot/index.js +0 -13
- package/skills/dev-browser/dist/src/snapshot/inject.d.ts +0 -12
- package/skills/dev-browser/dist/src/snapshot/inject.js +0 -12
- package/skills/dev-browser/dist/src/standalone.d.ts +0 -31
- package/skills/dev-browser/dist/src/standalone.js +0 -173
- package/skills/dev-browser/dist/src/startup.d.ts +0 -46
- package/skills/dev-browser/dist/src/startup.js +0 -77
- package/skills/dev-browser/dist/src/target-registry.d.ts +0 -28
- package/skills/dev-browser/dist/src/target-registry.js +0 -134
- package/skills/dev-browser/dist/src/types.d.ts +0 -26
- package/skills/dev-browser/dist/src/types.js +0 -1
- package/skills/dev-browser/package-lock.json +0 -1545
- package/skills/dev-browser/package.json +0 -35
- package/skills/dev-browser/references/scraping.md +0 -144
- package/skills/git-commit/SKILL.md +0 -124
- package/skills/time/SKILL.md +0 -119
- package/skills/time/scripts/time_cli.py +0 -143
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dev-browser
|
|
3
|
-
description: Browser automation with page state shared while the server process runs. Use when users ask to navigate websites, fill forms, take screenshots, extract web data, test web apps, or automate browser workflows. Trigger phrases include "go to [url]", "click on", "fill out the form", "take a screenshot", "scrape", "automate", "test the website", "log into", or any browser interaction request.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Dev Browser Skill
|
|
7
|
-
|
|
8
|
-
Browser automation that maintains page state across script executions while the server process runs. Write small, focused scripts to accomplish tasks incrementally.
|
|
9
|
-
|
|
10
|
-
## Choosing Your Approach
|
|
11
|
-
|
|
12
|
-
- **Local/source-available sites**: Read the source code first to write selectors directly
|
|
13
|
-
- **Unknown page layouts**: Use `getAISnapshot()` to discover elements and `selectSnapshotRef()` to interact with them
|
|
14
|
-
- **Visual feedback**: Take screenshots to see what the user sees
|
|
15
|
-
|
|
16
|
-
## Setup
|
|
17
|
-
|
|
18
|
-
Two supported startup modes are available on **Linux** and **native Windows**. Run the following commands from the installed `dev-browser` skill directory. Bash, Git Bash, and WSL are not required.
|
|
19
|
-
|
|
20
|
-
Startup never installs packages or browsers and treats the skill directory as read-only. If a preflight reports missing dependencies, run its explicit setup command yourself. Typical setup commands from the installed skill directory are:
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
npm ci --omit=dev
|
|
24
|
-
node "node_modules/playwright/cli.js" install chromium
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
The Playwright command is required only for standalone mode. Startup does not download Chromium automatically.
|
|
28
|
-
|
|
29
|
-
### Standalone Mode (Default)
|
|
30
|
-
|
|
31
|
-
Launches a new Chromium browser for fresh automation sessions.
|
|
32
|
-
|
|
33
|
-
```text
|
|
34
|
-
node dist/scripts/start.js standalone
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Add `--headless` if needed:
|
|
38
|
-
|
|
39
|
-
```text
|
|
40
|
-
node dist/scripts/start.js standalone --headless
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Wait for the stable readiness line `Ready` before running scripts.
|
|
44
|
-
|
|
45
|
-
### Extension Mode
|
|
46
|
-
|
|
47
|
-
Connects to the user's existing Chrome browser. Use this when:
|
|
48
|
-
|
|
49
|
-
- The user is already logged into sites and wants you to do things behind an authed experience that isn't local dev.
|
|
50
|
-
- The user asks you to use the extension.
|
|
51
|
-
|
|
52
|
-
Start the relay server with:
|
|
53
|
-
|
|
54
|
-
```text
|
|
55
|
-
node dist/scripts/start.js extension
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Wait for `Waiting for extension to connect...`. Once the browser extension attaches, the relay logs `Extension connected`.
|
|
59
|
-
|
|
60
|
-
If the extension hasn't connected yet, tell the user to launch and activate it. Download link: https://github.com/SawyerHood/dev-browser/releases
|
|
61
|
-
|
|
62
|
-
## Support Matrix
|
|
63
|
-
|
|
64
|
-
| Mode | Linux | Native Windows | Readiness signal | Notes |
|
|
65
|
-
|------|-------|----------------|------------------|-------|
|
|
66
|
-
| standalone mode | Supported | Supported | `Ready` | Uses a process-owned temporary Chromium profile and cleans it on exit |
|
|
67
|
-
| extension mode | Supported | Supported | `Waiting for extension to connect...` then `Extension connected` | Requires the external browser extension to attach |
|
|
68
|
-
|
|
69
|
-
## Verification Checklist
|
|
70
|
-
|
|
71
|
-
- Start `standalone mode` with `node dist/scripts/start.js standalone`
|
|
72
|
-
- Observe the readiness line `Ready`
|
|
73
|
-
- Connect with `connect()` and create a named page
|
|
74
|
-
- Start `extension mode` with `node dist/scripts/start.js extension`
|
|
75
|
-
- Observe `Waiting for extension to connect...`
|
|
76
|
-
- Attach the browser extension and confirm `Extension connected`
|
|
77
|
-
|
|
78
|
-
## Known Differences
|
|
79
|
-
|
|
80
|
-
- `standalone mode` owns a temporary Chromium profile only for the server process lifetime and cleans it on exit.
|
|
81
|
-
- `extension mode` depends on the external browser extension and the user's existing Chrome session.
|
|
82
|
-
- Extension mode rejects viewport requests with HTTP 400; viewport sizing is supported only in standalone mode.
|
|
83
|
-
- In `extension mode`, relay readiness means the server is waiting for the extension; it does not imply browser control is available until `Extension connected` appears.
|
|
84
|
-
- `standalone mode` is the default path for deterministic local automation; `extension mode` is for working inside an already-authenticated browser.
|
|
85
|
-
|
|
86
|
-
## Server Boundary
|
|
87
|
-
|
|
88
|
-
- Both server modes and their direct APIs accept only loopback hosts: `localhost`, IPv4 loopback addresses in `127.0.0.0/8`, and `::1` (bracketed IPv6 is accepted in CLI input).
|
|
89
|
-
- Wildcard, LAN, and other hosts are rejected. This loopback-only binding is the primary access boundary.
|
|
90
|
-
- Origin checks are defense-in-depth, not authentication.
|
|
91
|
-
|
|
92
|
-
- State-changing `/pages` requests accept only originless JSON clients; browser-origin and non-JSON mutations are rejected before backend calls.
|
|
93
|
-
- `/cdp` accepts only originless WebSocket clients, which is the normal behavior of the Node client. Browser pages always send an `Origin` and are rejected.
|
|
94
|
-
- `/extension` accepts originless protocol clients and valid `chrome-extension://` origins. HTTP(S), `null`, malformed, and other origins are rejected.
|
|
95
|
-
- Rejected sockets close with WebSocket policy code `1008` before they can own a client ID, replace the extension, or route buffered messages.
|
|
96
|
-
|
|
97
|
-
## Non-goal Environments
|
|
98
|
-
|
|
99
|
-
- `WSL` and `Git Bash` are not part of the supported Windows path for this skill.
|
|
100
|
-
- Native Windows support means PowerShell / Command Prompt can use the documented entrypoints directly.
|
|
101
|
-
- If a user runs inside WSL or Git Bash, treat that as a separate environment rather than the official Windows support contract.
|
|
102
|
-
|
|
103
|
-
## Writing Scripts
|
|
104
|
-
|
|
105
|
-
Treat the installed `dev-browser` skill directory as read-only. Store scripts and artifacts in the OS temporary directory or task workspace, never inside the skill directory, and delete files you created when the task ends.
|
|
106
|
-
|
|
107
|
-
External scripts cannot use package self-resolution, so pass the installed skill directory as the first argument and import its compiled client by file URL. Example:
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
import { tmpdir } from "node:os";
|
|
111
|
-
import { join } from "node:path";
|
|
112
|
-
import { pathToFileURL } from "node:url";
|
|
113
|
-
|
|
114
|
-
const skillDir = process.argv[2];
|
|
115
|
-
if (!skillDir) throw new Error("Pass the installed dev-browser skill directory");
|
|
116
|
-
const { connect, waitForPageLoad } = await import(
|
|
117
|
-
pathToFileURL(join(skillDir, "dist", "src", "client.js")).href
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const client = await connect();
|
|
121
|
-
const page = await client.page("example", { viewport: { width: 1920, height: 1080 } });
|
|
122
|
-
|
|
123
|
-
await page.goto("https://example.com");
|
|
124
|
-
await waitForPageLoad(page);
|
|
125
|
-
const screenshotPath = join(tmpdir(), "dev-browser-screenshot.png");
|
|
126
|
-
await page.screenshot({ path: screenshotPath });
|
|
127
|
-
|
|
128
|
-
console.log({ title: await page.title(), url: page.url(), screenshotPath });
|
|
129
|
-
await client.disconnect();
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
This invocation works in Linux shells, PowerShell, and Command Prompt when the two paths are quoted:
|
|
133
|
-
|
|
134
|
-
```text
|
|
135
|
-
node "PATH_TO_SCRIPT.mjs" "PATH_TO_INSTALLED_DEV_BROWSER"
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Key Principles
|
|
139
|
-
|
|
140
|
-
1. **Small scripts**: Each script does ONE thing (navigate, click, fill, check)
|
|
141
|
-
2. **Evaluate state**: Log/return state at the end to decide next steps
|
|
142
|
-
3. **Descriptive page names**: Use `"checkout"`, `"login"`, not `"main"`
|
|
143
|
-
4. **Disconnect to exit**: `await client.disconnect()` - pages persist while the server process runs
|
|
144
|
-
5. **Plain JS in evaluate**: `page.evaluate()` runs in browser - no TypeScript syntax
|
|
145
|
-
|
|
146
|
-
## Workflow Loop
|
|
147
|
-
|
|
148
|
-
Follow this pattern for complex tasks:
|
|
149
|
-
|
|
150
|
-
1. **Write a script** to perform one action
|
|
151
|
-
2. **Run it** and observe the output
|
|
152
|
-
3. **Evaluate** - did it work? What's the current state?
|
|
153
|
-
4. **Decide** - is the task complete or do we need another script?
|
|
154
|
-
5. **Repeat** until task is done
|
|
155
|
-
|
|
156
|
-
### No TypeScript in Browser Context
|
|
157
|
-
|
|
158
|
-
Code passed to `page.evaluate()` runs in the browser, which doesn't understand TypeScript:
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
// ✅ Correct: plain JavaScript
|
|
162
|
-
const text = await page.evaluate(() => {
|
|
163
|
-
return document.body.innerText;
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// ❌ Wrong: TypeScript syntax will fail at runtime
|
|
167
|
-
const text = await page.evaluate(() => {
|
|
168
|
-
const el: HTMLElement = document.body; // Type annotation breaks in browser!
|
|
169
|
-
return el.innerText;
|
|
170
|
-
});
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## Scraping Data
|
|
174
|
-
|
|
175
|
-
For scraping large datasets, intercept and replay network requests rather than scrolling the DOM. See [references/scraping.md](references/scraping.md) for the complete guide covering request capture, schema discovery, and paginated API replay.
|
|
176
|
-
|
|
177
|
-
## Client API
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
const client = await connect();
|
|
181
|
-
|
|
182
|
-
// Get or create named page (viewport only applies to new pages)
|
|
183
|
-
const page = await client.page("name");
|
|
184
|
-
const pageWithSize = await client.page("name", { viewport: { width: 1920, height: 1080 } });
|
|
185
|
-
|
|
186
|
-
const pages = await client.list(); // List all page names
|
|
187
|
-
await client.close("name"); // Close a page
|
|
188
|
-
await client.disconnect(); // Disconnect (pages persist while the server runs)
|
|
189
|
-
|
|
190
|
-
// ARIA Snapshot methods
|
|
191
|
-
const snapshot = await client.getAISnapshot("name"); // Get accessibility tree
|
|
192
|
-
const element = await client.selectSnapshotRef("name", "e5"); // Get element by ref
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
The `page` object is a standard Playwright Page.
|
|
196
|
-
|
|
197
|
-
## Waiting
|
|
198
|
-
|
|
199
|
-
```javascript
|
|
200
|
-
await waitForPageLoad(page); // After navigation
|
|
201
|
-
await page.waitForSelector(".results"); // For specific elements
|
|
202
|
-
await page.waitForURL("**/success"); // For specific URL
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## Inspecting Page State
|
|
206
|
-
|
|
207
|
-
### Screenshots
|
|
208
|
-
|
|
209
|
-
```javascript
|
|
210
|
-
import { tmpdir } from "node:os";
|
|
211
|
-
import { join } from "node:path";
|
|
212
|
-
|
|
213
|
-
const screenshotPath = join(tmpdir(), "dev-browser-screenshot.png");
|
|
214
|
-
const fullScreenshotPath = join(tmpdir(), "dev-browser-full.png");
|
|
215
|
-
await page.screenshot({ path: screenshotPath });
|
|
216
|
-
await page.screenshot({ path: fullScreenshotPath, fullPage: true });
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Inspect the files, then remove them no later than task completion.
|
|
220
|
-
|
|
221
|
-
### ARIA Snapshot (Element Discovery)
|
|
222
|
-
|
|
223
|
-
Use `getAISnapshot()` to discover page elements. Returns YAML-formatted accessibility tree:
|
|
224
|
-
|
|
225
|
-
```yaml
|
|
226
|
-
- banner:
|
|
227
|
-
- link "Hacker News" [ref=e1]
|
|
228
|
-
- navigation:
|
|
229
|
-
- link "new" [ref=e2]
|
|
230
|
-
- main:
|
|
231
|
-
- list:
|
|
232
|
-
- listitem:
|
|
233
|
-
- link "Article Title" [ref=e8]
|
|
234
|
-
- link "328 comments" [ref=e9]
|
|
235
|
-
- contentinfo:
|
|
236
|
-
- textbox [ref=e10]
|
|
237
|
-
- /placeholder: "Search"
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
**Interpreting refs:**
|
|
241
|
-
|
|
242
|
-
- `[ref=eN]` - Element reference for interaction (visible, clickable elements only)
|
|
243
|
-
- `[checked]`, `[disabled]`, `[expanded]` - Element states
|
|
244
|
-
- `[level=N]` - Heading level
|
|
245
|
-
- `/url:`, `/placeholder:` - Element properties
|
|
246
|
-
|
|
247
|
-
**Interacting with refs:**
|
|
248
|
-
|
|
249
|
-
```typescript
|
|
250
|
-
const snapshot = await client.getAISnapshot("hackernews");
|
|
251
|
-
console.log(snapshot); // Find the ref you need
|
|
252
|
-
|
|
253
|
-
const element = await client.selectSnapshotRef("hackernews", "e2");
|
|
254
|
-
await element.click();
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## Error Recovery
|
|
258
|
-
|
|
259
|
-
Page state persists after failures while the server process runs. Reuse the external script pattern above from the OS temporary directory or task workspace:
|
|
260
|
-
|
|
261
|
-
```javascript
|
|
262
|
-
const client = await connect();
|
|
263
|
-
const page = await client.page("hackernews");
|
|
264
|
-
|
|
265
|
-
const debugScreenshotPath = join(tmpdir(), "dev-browser-debug.png");
|
|
266
|
-
await page.screenshot({ path: debugScreenshotPath });
|
|
267
|
-
console.log({
|
|
268
|
-
url: page.url(),
|
|
269
|
-
title: await page.title(),
|
|
270
|
-
bodyText: await page.textContent("body").then((t) => t?.slice(0, 200)),
|
|
271
|
-
debugScreenshotPath,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
await client.disconnect();
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Run it with the same cross-platform invocation and delete the debug script and screenshot when finished:
|
|
278
|
-
|
|
279
|
-
```text
|
|
280
|
-
node "PATH_TO_DEBUG_SCRIPT.mjs" "PATH_TO_INSTALLED_DEV_BROWSER"
|
|
281
|
-
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { formatHttpUrl, parseEntrypointArgs, resolveHostForProbe } from "../src/entrypoint.js";
|
|
5
|
-
import { assertRuntimeDependenciesAvailable, getInvalidRuntimeDependencies, getLockedRuntimeDependencies, isPlaywrightChromiumInstalled, isTcpPortInUse, resolveSkillDirFromEntrypoint, } from "../src/runtime.js";
|
|
6
|
-
import { assertPlaywrightChromiumAvailable, preflightStandaloneStartup, runEntrypoint, } from "../src/startup.js";
|
|
7
|
-
const skillDir = resolveSkillDirFromEntrypoint(import.meta.url);
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
async function main() {
|
|
10
|
-
const args = parseEntrypointArgs(process.argv.slice(2));
|
|
11
|
-
await ensureSkillDependencies();
|
|
12
|
-
await runEntrypoint(args, {
|
|
13
|
-
serveStandalone: async (options) => {
|
|
14
|
-
const { serve } = await import("../src/index.js");
|
|
15
|
-
return serve(options);
|
|
16
|
-
},
|
|
17
|
-
serveExtension: async (options) => {
|
|
18
|
-
const { serveRelay } = await import("../src/relay.js");
|
|
19
|
-
return serveRelay(options);
|
|
20
|
-
},
|
|
21
|
-
registerShutdown,
|
|
22
|
-
keepAlive: () => new Promise(() => { }),
|
|
23
|
-
log: (line) => console.log(line),
|
|
24
|
-
ensureBrowser: async () => {
|
|
25
|
-
const { registry } = require("playwright-core/lib/server/registry/index");
|
|
26
|
-
await assertPlaywrightChromiumAvailable({
|
|
27
|
-
isInstalled: () => isPlaywrightChromiumInstalled({
|
|
28
|
-
headless: args.headless,
|
|
29
|
-
findExecutable: (name) => registry.findExecutable(name),
|
|
30
|
-
exists: existsSync,
|
|
31
|
-
}),
|
|
32
|
-
});
|
|
33
|
-
},
|
|
34
|
-
preflightStandalone: () => preflightStandaloneStartup(args, {
|
|
35
|
-
checkServer: async (host, port) => {
|
|
36
|
-
try {
|
|
37
|
-
const response = await fetch(formatHttpUrl(resolveHostForProbe(host), port), {
|
|
38
|
-
signal: AbortSignal.timeout(1000),
|
|
39
|
-
});
|
|
40
|
-
if (!response.ok) {
|
|
41
|
-
return { ok: false };
|
|
42
|
-
}
|
|
43
|
-
const info = (await response.json());
|
|
44
|
-
return { ok: true, info };
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return { ok: false };
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
isPortInUse: isTcpPortInUse,
|
|
51
|
-
log: (line) => console.log(line),
|
|
52
|
-
}),
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
async function ensureSkillDependencies() {
|
|
56
|
-
const packageLock = JSON.parse(readFileSync(join(skillDir, "package-lock.json"), "utf8"));
|
|
57
|
-
const invalidDependencies = getInvalidRuntimeDependencies({
|
|
58
|
-
skillDir,
|
|
59
|
-
lockedDependencies: getLockedRuntimeDependencies(packageLock),
|
|
60
|
-
readPackageVersion: (path) => {
|
|
61
|
-
try {
|
|
62
|
-
const installed = JSON.parse(readFileSync(path, "utf8"));
|
|
63
|
-
return typeof installed.version === "string" ? installed.version : undefined;
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
assertRuntimeDependenciesAvailable({
|
|
71
|
-
invalidDependencies,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
function registerShutdown(stop) {
|
|
75
|
-
let shutdownPromise;
|
|
76
|
-
const shutdown = () => {
|
|
77
|
-
shutdownPromise ??= (async () => {
|
|
78
|
-
await stop();
|
|
79
|
-
process.exit(0);
|
|
80
|
-
})();
|
|
81
|
-
return shutdownPromise;
|
|
82
|
-
};
|
|
83
|
-
process.on("SIGINT", shutdown);
|
|
84
|
-
process.on("SIGTERM", shutdown);
|
|
85
|
-
process.on("SIGHUP", shutdown);
|
|
86
|
-
}
|
|
87
|
-
main().catch((error) => {
|
|
88
|
-
console.error("Failed to start dev-browser:", error);
|
|
89
|
-
process.exit(1);
|
|
90
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { type ElementHandle, type Page } from "playwright";
|
|
2
|
-
import type { ViewportSize } from "./types.js";
|
|
3
|
-
/**
|
|
4
|
-
* Options for waiting for page load
|
|
5
|
-
*/
|
|
6
|
-
export interface WaitForPageLoadOptions {
|
|
7
|
-
/** Maximum time to wait in ms (default: 10000) */
|
|
8
|
-
timeout?: number;
|
|
9
|
-
/** How often to check page state in ms (default: 50) */
|
|
10
|
-
pollInterval?: number;
|
|
11
|
-
/** Minimum time to wait even if page appears ready in ms (default: 100) */
|
|
12
|
-
minimumWait?: number;
|
|
13
|
-
/** Wait for network to be idle (no pending requests) (default: true) */
|
|
14
|
-
waitForNetworkIdle?: boolean;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Result of waiting for page load
|
|
18
|
-
*/
|
|
19
|
-
export interface WaitForPageLoadResult {
|
|
20
|
-
/** Whether the page is considered loaded */
|
|
21
|
-
success: boolean;
|
|
22
|
-
/** Document ready state when finished */
|
|
23
|
-
readyState: string;
|
|
24
|
-
/** Number of pending network requests when finished */
|
|
25
|
-
pendingRequests: number;
|
|
26
|
-
/** Time spent waiting in ms */
|
|
27
|
-
waitTimeMs: number;
|
|
28
|
-
/** Whether timeout was reached */
|
|
29
|
-
timedOut: boolean;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Wait for a page to finish loading using document.readyState and Playwright request events.
|
|
33
|
-
*
|
|
34
|
-
* Uses browser-use's approach of:
|
|
35
|
-
* - Checking document.readyState for 'complete'
|
|
36
|
-
* - Monitoring pending network requests via Playwright
|
|
37
|
-
* - Filtering out ads, tracking, and non-critical resources
|
|
38
|
-
* - Graceful timeout handling (continues even if timeout reached)
|
|
39
|
-
*/
|
|
40
|
-
export declare function waitForPageLoad(page: Page, options?: WaitForPageLoadOptions): Promise<WaitForPageLoadResult>;
|
|
41
|
-
/** Server mode information */
|
|
42
|
-
export interface ServerInfo {
|
|
43
|
-
wsEndpoint: string;
|
|
44
|
-
mode: "standalone" | "extension";
|
|
45
|
-
extensionConnected?: boolean;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Options for creating or getting a page
|
|
49
|
-
*/
|
|
50
|
-
export interface PageOptions {
|
|
51
|
-
/** Viewport size for new pages */
|
|
52
|
-
viewport?: ViewportSize;
|
|
53
|
-
}
|
|
54
|
-
export interface DevBrowserClient {
|
|
55
|
-
page: (name: string, options?: PageOptions) => Promise<Page>;
|
|
56
|
-
list: () => Promise<string[]>;
|
|
57
|
-
close: (name: string) => Promise<void>;
|
|
58
|
-
disconnect: () => Promise<void>;
|
|
59
|
-
/**
|
|
60
|
-
* Get AI-friendly ARIA snapshot for a page.
|
|
61
|
-
* Returns YAML format with refs like [ref=e1], [ref=e2].
|
|
62
|
-
* Refs are stored on window.__devBrowserRefs for cross-connection persistence.
|
|
63
|
-
*/
|
|
64
|
-
getAISnapshot: (name: string) => Promise<string>;
|
|
65
|
-
/**
|
|
66
|
-
* Get an element handle by its ref from the last getAISnapshot call.
|
|
67
|
-
* Refs persist across Playwright connections.
|
|
68
|
-
*/
|
|
69
|
-
selectSnapshotRef: (name: string, ref: string) => Promise<ElementHandle | null>;
|
|
70
|
-
/**
|
|
71
|
-
* Get server information including mode and extension connection status.
|
|
72
|
-
*/
|
|
73
|
-
getServerInfo: () => Promise<ServerInfo>;
|
|
74
|
-
}
|
|
75
|
-
interface TargetLookupSession {
|
|
76
|
-
send(method: "Target.getTargetInfo"): Promise<{
|
|
77
|
-
targetInfo: {
|
|
78
|
-
targetId: string;
|
|
79
|
-
};
|
|
80
|
-
}>;
|
|
81
|
-
detach(): Promise<void>;
|
|
82
|
-
}
|
|
83
|
-
interface TargetLookupContext<TPage> {
|
|
84
|
-
pages(): TPage[];
|
|
85
|
-
newCDPSession(page: TPage): Promise<TargetLookupSession>;
|
|
86
|
-
}
|
|
87
|
-
interface TargetLookupBrowser<TPage> {
|
|
88
|
-
contexts(): Array<TargetLookupContext<TPage>>;
|
|
89
|
-
}
|
|
90
|
-
export declare function findPageByTargetId<TPage>(browser: TargetLookupBrowser<TPage>, targetId: string): Promise<TPage | null>;
|
|
91
|
-
export declare function connect(serverUrl?: string): Promise<DevBrowserClient>;
|
|
92
|
-
export {};
|