pi-lean-portal 0.3.3 → 0.5.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 +159 -519
- package/backends/playwright-base/playwright-plugin.ts +40 -107
- package/backends/python-adapter.ts +40 -66
- package/backends/python-base/pi_browser_bridge/accessibility.py +30 -15
- package/backends/python-base/pi_browser_bridge/browser_data.py +34 -42
- package/backends/python-base/pi_browser_bridge/playwright_base.py +25 -30
- package/browser-cookies.ts +5 -0
- package/browser-profile.ts +7 -13
- package/browser-toggle.ts +29 -163
- package/core/fetch-backend.ts +20 -69
- package/core/guides.ts +134 -23
- package/core/plugin-api.ts +14 -26
- package/core/plugin-config.ts +38 -12
- package/core/plugin-registry.ts +7 -2
- package/core/router.ts +132 -154
- package/core/shared/accessibility-tree.ts +7 -2
- package/core/shared/bot-detection.ts +7 -7
- package/core/shared/browser-events.ts +10 -14
- package/core/shared/dom-extractor.ts +4 -18
- package/core/shared/nav-settle.ts +6 -6
- package/core/shared/session-manager.ts +8 -34
- package/core/shared/settings-reader.ts +5 -3
- package/core/shared/snapshot-cache.ts +27 -70
- package/core/shared/storage-state.ts +13 -12
- package/core/shared/temp-files.ts +73 -0
- package/index.ts +29 -48
- package/package.json +4 -6
- package/tools/browser-back.ts +8 -3
- package/tools/browser-console.ts +3 -8
- package/tools/browser-inspect.ts +15 -14
- package/tools/browser-navigate.ts +41 -24
- package/tools/browser-press.ts +7 -2
- package/tools/browser-scroll.ts +8 -3
- package/tools/browser-snapshot.ts +10 -8
- package/tools/index.ts +4 -1
- package/tools/utils.ts +17 -3
- package/tools/web-fetch.ts +12 -8
- package/core/shared/ship-manifest.ts +0 -151
- package/ship-manifest.test.ts +0 -17
package/README.md
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# pi-lean-portal User Guide
|
|
2
2
|
|
|
3
|
-
> **pi-lean-portal** gives the Pi coding agent interactive web browsing
|
|
4
|
-
>
|
|
5
|
-
> refs, persistent profiles, cookies, and navigation guides that resurface by
|
|
6
|
-
> domain. A `/web` toggle removes the tools from the agent's context when
|
|
3
|
+
> **pi-lean-portal** gives the Pi coding agent interactive web browsing via Playwright Chromium/Firefox, accessibility-tree snapshots with `@e` element
|
|
4
|
+
> refs, persistent profiles, cookies, and domain-aware navigation guides. A `/web` toggle removes the tools from the agent's context when
|
|
7
5
|
> switched off, so web browsing doesn't consume tokens on sessions that aren't
|
|
8
6
|
> doing web work. If a site blocks the shipped browsers, drop in your own
|
|
9
7
|
> backend (e.g. [Camoufox](https://github.com/daijro/camoufox)).
|
|
@@ -14,23 +12,6 @@
|
|
|
14
12
|
|
|
15
13
|
---
|
|
16
14
|
|
|
17
|
-
## Table of Contents
|
|
18
|
-
|
|
19
|
-
1. [Quick Start](#quick-start)
|
|
20
|
-
2. [Extending it](#extending-it)
|
|
21
|
-
3. [`/web` Command — Browser Toggle & Profiles](#web-command--browser-toggle--profiles)
|
|
22
|
-
4. [All 12 Tools](#all-12-tools)
|
|
23
|
-
5. [Stateless Fetching (web-fetch)](#stateless-fetching-web-fetch)
|
|
24
|
-
6. [Navigation Guides (web-guide & web-learn)](#navigation-guides-web-guide--web-learn)
|
|
25
|
-
7. [`/web status` — Detailed Runtime Status](#web-status--detailed-runtime-status)
|
|
26
|
-
8. [Profiles — Persistent Sessions](#profiles--persistent-sessions)
|
|
27
|
-
9. [Cookie Management](#cookie-management)
|
|
28
|
-
10. [Backend Architecture](#backend-architecture)
|
|
29
|
-
11. [Configuration (settings.json)](#configuration-settingsjson)
|
|
30
|
-
12. [Tips & Best Practices](#tips--best-practices)
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
15
|
## Quick Start
|
|
35
16
|
|
|
36
17
|
```bash
|
|
@@ -42,46 +23,16 @@ Once loaded, you'll see a notification like:
|
|
|
42
23
|
|
|
43
24
|
> 🌐 Browser extension loaded (plugins: chromium, firefox). Try: web-fetch for static pages or browser-navigate for interactive browsing.
|
|
44
25
|
|
|
45
|
-
The browser tools are **enabled by default
|
|
26
|
+
The browser tools are **enabled by default**: `web-fetch` for static pages,
|
|
27
|
+
`browser-navigate` (plus click/type/scroll/screenshots via `@e` refs) for
|
|
28
|
+
interactive browsing.
|
|
46
29
|
|
|
47
|
-
- **Fetch a static page**: The agent uses `web-fetch` for quick, stateless
|
|
48
|
-
content retrieval (no JavaScript, no session).
|
|
49
|
-
- **Browse interactively**: The agent uses `browser-navigate` to visit a page,
|
|
50
|
-
then clicks, types, scrolls, and screenshots using `@e1`/`@e2` element
|
|
51
|
-
references from the accessibility tree.
|
|
52
|
-
|
|
53
|
-
> **Tip:** If you only need Markdown content from a static page, `web-fetch`
|
|
54
|
-
> is faster and lighter than launching a full browser session.
|
|
55
|
-
>
|
|
56
30
|
> **Playwright browser binaries are not downloaded during `npm install`.**
|
|
57
31
|
> Run `npx playwright install chromium firefox` separately. On first
|
|
58
32
|
> `browser-navigate` without them, you'll be prompted with the exact command.
|
|
59
33
|
|
|
60
34
|
---
|
|
61
35
|
|
|
62
|
-
## Extending it
|
|
63
|
-
|
|
64
|
-
Beyond the toggle, three surfaces are extensible or shared rather than hardcoded:
|
|
65
|
-
|
|
66
|
-
- **Navigation guides** — `web-learn` saves site-specific playbooks that
|
|
67
|
-
auto-match by domain and resurface in later sessions. See
|
|
68
|
-
[Navigation Guides](#navigation-guides-web-guide--web-learn).
|
|
69
|
-
- **Custom browser backends** — if a site blocks the shipped Chromium/Firefox,
|
|
70
|
-
drop a `bridge.py` subclass into `~/.pi/agent/pi-lean-portal/user-backends/`
|
|
71
|
-
and drive a patched engine like [Camoufox](https://github.com/daijro/camoufox)
|
|
72
|
-
yourself. The full flow lives in [Backend Architecture](#backend-architecture)
|
|
73
|
-
and [`contributed/README.md`](./contributed/README.md).
|
|
74
|
-
- **Toolset toggles** — the `/web` toggle is powered by the shared
|
|
75
|
-
[`pi-tool-masking`](https://github.com/coreyryanhanson/pi-tool-masking/) peer dep,
|
|
76
|
-
which handles active-set masking, sibling-tool union math, and the
|
|
77
|
-
`TOOLSET_EVENTS` protocol that keeps the `browser`/`search` status-bar
|
|
78
|
-
glyphs in sync across extensions. It's published as a general toggle
|
|
79
|
-
mechanism — any extension that hides/shows its own tools can build on the
|
|
80
|
-
same scheme so masking and glyph events stay consistent across the whole
|
|
81
|
-
agent, rather than each toggle reinventing its own.
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
36
|
## `/web` Command — Browser Toggle & Profiles
|
|
86
37
|
|
|
87
38
|
The `/web` command controls whether web tools are visible to the AI agent,
|
|
@@ -90,202 +41,132 @@ toggles guide-saving mode, and manages browser profiles.
|
|
|
90
41
|
### Three-State Toggle
|
|
91
42
|
|
|
92
43
|
| Command | Effect |
|
|
93
|
-
|
|
94
|
-
| `/web on` | **Browsing only
|
|
95
|
-
| `/web learn` | **Browsing + guide-saving
|
|
96
|
-
| `/web off` | **All web tools hidden
|
|
44
|
+
| ------- | ------ |
|
|
45
|
+
| `/web on` | **Browsing only**: all interactive browser tools + `web-fetch` are available. `web-learn` is hidden. If `pi-lean-search` is also installed, `web-search` is enabled too. |
|
|
46
|
+
| `/web learn` | **Browsing + guide-saving**: same as `on`, plus the `web-learn` tool is available so the AI can save/update navigation guides on request. |
|
|
47
|
+
| `/web off` | **All web tools hidden**: saves ~1500–2000 tokens per turn by removing tool schemas from the prompt. `web-fetch` and `web-search` are also hidden. |
|
|
97
48
|
|
|
98
49
|
### Check Current State
|
|
99
50
|
|
|
100
51
|
| Command | Effect |
|
|
101
|
-
|
|
52
|
+
| ------- | ------ |
|
|
102
53
|
| `/web` | Show current toggle status and available sub-commands. |
|
|
103
|
-
| `/web status` | **Detailed runtime status**
|
|
104
|
-
|
|
105
|
-
### Why Toggle?
|
|
106
|
-
|
|
107
|
-
- **`/web off`**: When you're done browsing, turning tools off reduces context
|
|
108
|
-
usage and keeps the agent focused on coding.
|
|
109
|
-
- **`/web learn`**: Only enable this when you want the agent to save navigation
|
|
110
|
-
guidance for a site. The agent never calls `web-learn` unprompted — it must
|
|
111
|
-
be in learn mode.
|
|
112
|
-
- **State persists** across `/reload`, `/resume`, `/fork`, and `/tree`
|
|
113
|
-
navigation — the toggle remembers what you chose.
|
|
114
|
-
|
|
115
|
-
### Persistence
|
|
116
|
-
|
|
117
|
-
The toggle state is stored in the conversation's branch history. A fresh
|
|
118
|
-
conversation starts with the default from `settings.json` (`browserToggle.defaultEnabled`,
|
|
119
|
-
which defaults to `true`).
|
|
120
|
-
|
|
121
|
-
> ⚠️ `browserToggle.defaultEnabled` is still read today but is scheduled to be
|
|
122
|
-
> replaced by the `pi-tool-masking` library's `toolsetDefaults` block in an
|
|
123
|
-
> upcoming release — **that block is not read yet**, so keep the legacy key
|
|
124
|
-
> until the replacement ships. See
|
|
125
|
-
> [Configuration (`settings.json`)](#configuration-settingsjson) for the
|
|
126
|
-
> future shape and how to pre-add it harmlessly. A migration warning fires on
|
|
127
|
-
> session start once the legacy key is present and the web default hasn't yet
|
|
128
|
-
> been mirrored into `toolsetDefaults`.
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## All 12 Tools
|
|
133
|
-
|
|
134
|
-
`pi-lean-portal` registers 12 tools. The first 9 require a **browser session**
|
|
135
|
-
(created by `browser-navigate`). `web-fetch`, `web-guide`, and `web-learn` are stateless.
|
|
136
|
-
|
|
137
|
-
**Auto-captured screenshots:** `browser-navigate` and `browser-snapshot` automatically
|
|
138
|
-
capture a screenshot to a temp file (`/tmp/pi-lean-portal/screenshot-<taskId>.jpg`).
|
|
139
|
-
Use the `read` tool to visually inspect the page when the accessibility tree isn't enough.
|
|
140
|
-
Screenshots capture the 1280×720 viewport (not full-page) — the same viewport the
|
|
141
|
-
browser uses for navigation.
|
|
142
|
-
|
|
143
|
-
### 1. `browser-navigate` — Visit a Page
|
|
144
|
-
|
|
145
|
-
Navigates to a URL using a browser plugin (default: Chromium). Returns an
|
|
146
|
-
accessibility tree annotated with **@e1, @e2, …** element references.
|
|
147
|
-
|
|
148
|
-
```text
|
|
149
|
-
Title: Example Domain
|
|
150
|
-
URL: https://example.com
|
|
151
|
-
Backend: chromium
|
|
152
|
-
Interactive elements: 3
|
|
153
|
-
|
|
154
|
-
link "More information..." [@e1]
|
|
155
|
-
→ https://www.iana.org/domains/example
|
|
156
|
-
…
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
**Parameters:**
|
|
160
|
-
|
|
161
|
-
- `url` — the target URL
|
|
162
|
-
- `strategy` (optional) — `"auto"` (default) or a plugin name like `"chromium"` or `"firefox"`
|
|
163
|
-
- `timeout` (optional) — seconds, default 30, max 120
|
|
164
|
-
- `profile` (optional) — `"none"`, `"session"`, or a named profile (see
|
|
165
|
-
[Profiles](#profiles--persistent-sessions))
|
|
166
|
-
|
|
167
|
-
**Output includes:**
|
|
168
|
-
|
|
169
|
-
- Page title, URL, backend name, element count
|
|
170
|
-
- Profile info when using profiles
|
|
171
|
-
- Bot detection warning when applicable
|
|
172
|
-
- Screenshot file path for visual inspection
|
|
173
|
-
- Guide footer appended when relevant guides apply
|
|
174
|
-
|
|
175
|
-
### 2. `browser-snapshot` — Refresh the Accessibility Tree
|
|
176
|
-
|
|
177
|
-
Returns the current page's accessibility tree with up-to-date `@e` refs. Also
|
|
178
|
-
captures a screenshot to a temp file (path in output). Use after clicking, typing,
|
|
179
|
-
or scrolling to get fresh element references.
|
|
180
|
-
|
|
181
|
-
- `full=true` — returns the complete tree (by default it's compacted to
|
|
182
|
-
~2500 characters for LLM efficiency)
|
|
183
|
-
|
|
184
|
-
### 3. `browser-click` — Click an Element
|
|
54
|
+
| `/web status` | **Detailed runtime status** including toggle state, plugin health, active sessions, and profiles on disk. |
|
|
185
55
|
|
|
186
56
|
```text
|
|
187
|
-
|
|
57
|
+
🌐 Browser tools: ✅ on | 📖 Learn mode: ❌ off
|
|
58
|
+
────────────────────────────────────────
|
|
59
|
+
Status: idle
|
|
60
|
+
Plugins: chromium, firefox, chromium-py (disabled), firefox-py (disabled)
|
|
61
|
+
Use web-fetch for stateless HTTP fetches.
|
|
62
|
+
Active sessions: 1
|
|
63
|
+
PW [chromium] https://example.com — Example Domain [profile: session]
|
|
64
|
+
Profiles: 1 on disk (named)
|
|
65
|
+
shopping (0.3 KB) ← active
|
|
66
|
+
Session profiles: 1 (manage with /web profile)
|
|
188
67
|
```
|
|
189
68
|
|
|
190
|
-
|
|
191
|
-
of the page after the click.
|
|
192
|
-
|
|
193
|
-
### 4. `browser-type` — Type Into a Field
|
|
194
|
-
|
|
195
|
-
```text
|
|
196
|
-
browser-type ref="@e3" text="hello world"
|
|
197
|
-
```
|
|
69
|
+
### Persistence
|
|
198
70
|
|
|
199
|
-
|
|
200
|
-
|
|
71
|
+
Toggle state persists across `/reload`, `/resume`, `/fork`, and `/tree` — it's
|
|
72
|
+
stored in the conversation's branch history. Fresh conversations start from
|
|
73
|
+
the `toolsetDefaults` block in `settings.json`
|
|
74
|
+
([Configuration](#configuration-settingsjson)).
|
|
201
75
|
|
|
202
|
-
|
|
76
|
+
---
|
|
203
77
|
|
|
204
|
-
|
|
205
|
-
browser-scroll direction="down"
|
|
206
|
-
```
|
|
78
|
+
## Profiles — Persistent Sessions
|
|
207
79
|
|
|
208
|
-
|
|
80
|
+
Profiles let the AI agent maintain persistent browser state (cookies,
|
|
81
|
+
localStorage) across calls, conversations, and even across different subagents.
|
|
209
82
|
|
|
210
|
-
###
|
|
83
|
+
### Profile Modes
|
|
211
84
|
|
|
212
|
-
|
|
85
|
+
| Mode | `browser-navigate profile=` | Behavior |
|
|
86
|
+
| ---- | --------------------------- | -------- |
|
|
87
|
+
| None | `"none"` | Clean slate every time (no cookies or state) |
|
|
88
|
+
| Session | `"session"` (default) | Persists state for the current conversation; survives `/reload` and `/resume` |
|
|
89
|
+
| Named | `"shopping"`, `"work"`, etc. | Shared across conversations and subagents, similar to browser tabs sharing a profile |
|
|
213
90
|
|
|
214
|
-
###
|
|
91
|
+
### Managing Profiles with `/web profile`
|
|
215
92
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
93
|
+
| Sub-command | Effect |
|
|
94
|
+
| ----------- | ------ |
|
|
95
|
+
| `/web profile list` | List all profiles on disk with their state size |
|
|
96
|
+
| `/web profile create shopping` | Create a new named profile |
|
|
97
|
+
| `/web profile session` | Set conversation-scoped default to session mode |
|
|
98
|
+
| `/web profile none` | Reset default to ephemeral (no persistence) |
|
|
99
|
+
| `/web profile shopping` | Switch default profile to an existing named profile |
|
|
100
|
+
| `/web profile clear shopping` | Delete the saved state for a profile (keeps the directory) |
|
|
101
|
+
| `/web profile clear-all --confirm` | Clear ALL profile states |
|
|
102
|
+
| `/web profile prune --confirm` | Remove stale session profiles for ended conversations |
|
|
219
103
|
|
|
220
|
-
|
|
104
|
+
> **How it works:** Profile state is stored at
|
|
105
|
+
> `~/.pi/agent/pi-lean-portal/browser-state/<profile-name>/storage-state.json`.
|
|
106
|
+
> Session-scoped profiles are auto-cleaned when the pi conversation ends.
|
|
221
107
|
|
|
222
|
-
|
|
108
|
+
---
|
|
223
109
|
|
|
224
|
-
|
|
110
|
+
## Cookie Management
|
|
225
111
|
|
|
226
|
-
|
|
227
|
-
|-------|--------|
|
|
228
|
-
| `browser-console expression="document.title"` | Evaluates JS and returns the result |
|
|
229
|
-
| `browser-console` (no params) | Returns captured console messages (log, warn, error, info) |
|
|
230
|
-
| `browser-console clear=true` | Clears the captured console log |
|
|
112
|
+
The `/web cookies` command lets you inspect and clear session cookies:
|
|
231
113
|
|
|
232
|
-
|
|
114
|
+
| Sub-command | Effect |
|
|
115
|
+
| ----------- | ------ |
|
|
116
|
+
| `/web cookies list` | List all cookies in the current session (name, value, domain, expiry, flags) |
|
|
117
|
+
| `/web cookies clear --confirm` | Clear ALL cookies for the current session |
|
|
233
118
|
|
|
234
|
-
|
|
235
|
-
|
|
119
|
+
> Cookies are saved as part of profile state. When you switch profiles,
|
|
120
|
+
> the cookies from the old profile are preserved and the new profile's
|
|
121
|
+
> cookies are loaded.
|
|
236
122
|
|
|
237
|
-
|
|
238
|
-
|-----------|---------|--------|
|
|
239
|
-
| `role` | `"link,button"` | Filter by ARIA role(s) |
|
|
240
|
-
| `name` | `"Submit"` | Filter by accessible name (case-insensitive) |
|
|
241
|
-
| `ref` | `"e5"` | Look up a specific `@e` ref |
|
|
242
|
-
| `subtree` | `"dialog"` | Scope to elements inside a container |
|
|
243
|
-
| `text` | `true` | Run DOM text extractor with `@e` annotations |
|
|
244
|
-
| `maxChars` | `500` | Limit output length; `0` for full content |
|
|
245
|
-
| `query` | `"pricing"` | Keyword filter (only active with `text=true`) |
|
|
123
|
+
---
|
|
246
124
|
|
|
247
|
-
|
|
248
|
-
> dialogs without loading the full tree.
|
|
125
|
+
## All 12 Tools
|
|
249
126
|
|
|
250
|
-
|
|
127
|
+
`pi-lean-portal` registers 12 tools. Three are **stateless**; the rest require
|
|
128
|
+
a **browser session** (created by `browser-navigate`).
|
|
251
129
|
|
|
252
|
-
|
|
130
|
+
| Tool | What it does | State |
|
|
131
|
+
| ---- | ------------ | ----- |
|
|
132
|
+
| `web-fetch` | Fetch a URL → Markdown, no browser session | stateless |
|
|
133
|
+
| `web-guide` / `web-learn` | Read / save navigation guides (learn mode via `/web learn`) | stateless |
|
|
134
|
+
| `browser-navigate` | Open a page → accessibility tree with `@e` element refs | session |
|
|
135
|
+
| `browser-snapshot` | Refresh the tree (`full=true` returns the uncompacted tree) | session |
|
|
136
|
+
| `browser-click` / `browser-type` / `browser-scroll` / `browser-back` / `browser-press` | Interact via `@e` refs (click, type, scroll, history, keyboard) | session |
|
|
137
|
+
| `browser-console` | Read captured console messages; also evaluates JS in the page | session |
|
|
138
|
+
| `browser-inspect` | Targeted element/text queries without loading a full snapshot | session |
|
|
253
139
|
|
|
254
|
-
|
|
255
|
-
HTML to Markdown. It does **not** create a browser session.
|
|
140
|
+
### Automatic Artifacts
|
|
256
141
|
|
|
257
|
-
|
|
142
|
+
Session tools save their full output to disk so the agent never needs a second call:
|
|
258
143
|
|
|
259
|
-
-
|
|
260
|
-
-
|
|
261
|
-
- When the interactive browser is blocked by bot detection — `web-fetch`
|
|
262
|
-
sometimes succeeds where the browser triggers a challenge
|
|
144
|
+
- **Screenshots**: `browser-navigate` and `browser-snapshot` auto-capture a viewport-sized (1280×720) JPEG to `/tmp/pi-lean-portal/screenshot-<taskId>.jpg`[^1].
|
|
145
|
+
- **Full Snapshots**: Any snapshot compacted for size is cached in full at `/tmp/pi-lean-portal/snapshot-*.txt` (last 2 per task).
|
|
263
146
|
|
|
264
|
-
|
|
147
|
+
Both file paths are surfaced as hints in the tool output, which the agent can follow up with the `read` tool.
|
|
265
148
|
|
|
266
|
-
|
|
267
|
-
- Larger content is spilled to a temp file in `/tmp/pi-lean-portal/` — the agent can `read` the file with offset/limit for specific sections. This cache ensures that the agent can access the full page content even when it exceeds the LLM's immediate context window.
|
|
268
|
-
- Bot detection and JS-only shells are detected heuristically
|
|
149
|
+
[^1]: Not full-page.
|
|
269
150
|
|
|
270
151
|
---
|
|
271
152
|
|
|
272
|
-
## Navigation Guides
|
|
153
|
+
## Navigation Guides
|
|
273
154
|
|
|
274
155
|
### Built-in Pattern Guides
|
|
275
156
|
|
|
276
157
|
`pi-lean-portal` ships with four built-in pattern guides that appear in the guide footer when relevant:
|
|
277
158
|
|
|
278
159
|
| Guide | Trigger | What It Covers |
|
|
279
|
-
|
|
280
|
-
| `bot-detection` |
|
|
281
|
-
| `cookie-consent` |
|
|
160
|
+
| ----- | ------- | -------------- |
|
|
161
|
+
| `bot-detection` | Bot blocking detected (`botDetected`) | Cloudflare, challenge pages, what NOT to do |
|
|
162
|
+
| `cookie-consent` | Dialog detected (`dialogDetected`) | Accept/Reject buttons, Escape key, verification |
|
|
282
163
|
| `pagination` | On-demand | Next buttons, infinite scroll, pages |
|
|
283
164
|
| `search` | On-demand | Search boxes, comboboxes, result lists |
|
|
284
165
|
|
|
285
166
|
### Overriding Built-in Guides
|
|
286
167
|
|
|
287
168
|
A same-named `.md` file in `~/.pi/agent/pi-lean-portal/web-guides/` (e.g.
|
|
288
|
-
`bot-detection.md`) **shadows the builtin entirely
|
|
169
|
+
`bot-detection.md`) **shadows the builtin entirely**; the whole guide is
|
|
289
170
|
replaced, not field-merged. To keep a pattern guide firing, include
|
|
290
171
|
`trigger.signal: botDetected` (or `dialogDetected`) in the frontmatter;
|
|
291
172
|
omitting it disables the trigger.
|
|
@@ -304,133 +185,41 @@ Site guides and pattern guides live in **disjoint namespaces** — a site guide
|
|
|
304
185
|
for `www.botdetection.com` does not collide with the `bot-detection` pattern
|
|
305
186
|
guide; both fire when applicable.
|
|
306
187
|
|
|
307
|
-
###
|
|
308
|
-
|
|
309
|
-
```text
|
|
310
|
-
web-guide → lists all available guides
|
|
311
|
-
web-guide guide="cookie-consent" → shows guidance text
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
The output includes the guide's last updated date and source (`builtin` or
|
|
315
|
-
`user`).
|
|
316
|
-
|
|
317
|
-
### Creating Your Own Site Guides (`web-learn`)
|
|
318
|
-
|
|
319
|
-
When the agent is in **learn mode** (`/web learn`), it can save or update
|
|
320
|
-
navigation guidance for specific sites using `web-learn`.
|
|
321
|
-
|
|
322
|
-
```text
|
|
323
|
-
web-learn domain="reddit.com" content="…guidance text…"
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
This creates a `.md` file with YAML frontmatter in `~/.pi/agent/pi-lean-portal/web-guides/`.
|
|
327
|
-
The guide becomes available immediately via `web-guide` and appears in the guide footer on
|
|
328
|
-
future navigations to that domain.
|
|
329
|
-
|
|
330
|
-
**Learn mode is off by default** — the agent never saves guides unprompted.
|
|
331
|
-
You must explicitly enable it with `/web learn`.
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
## `/web status` — Detailed Runtime Status
|
|
336
|
-
|
|
337
|
-
```text
|
|
338
|
-
/web status
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
Shows everything about the browser runtime in one notification:
|
|
342
|
-
|
|
343
|
-
```text
|
|
344
|
-
🌐 Browser tools: ✅ on | 📖 Learn mode: ❌ off
|
|
345
|
-
────────────────────────────────────────
|
|
346
|
-
Status: idle
|
|
347
|
-
Plugins: chromium, firefox, chromium-py (disabled), firefox-py (disabled)
|
|
348
|
-
Use web-fetch for stateless HTTP fetches.
|
|
349
|
-
Active sessions: 1
|
|
350
|
-
PW [chromium] https://example.com — Example Domain [profile: session]
|
|
351
|
-
Profiles: 1 on disk (named)
|
|
352
|
-
shopping (0.3 KB) ← active
|
|
353
|
-
Session profiles: 1 (manage with /web profile)
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
Covers:
|
|
357
|
-
|
|
358
|
-
- **Toggle state** — whether browser/learn tools are active in the agent's context
|
|
359
|
-
- **Backend health** — idle, busy, or error state
|
|
360
|
-
- **All registered plugins** — enabled/disabled status
|
|
361
|
-
- **Active sessions** — current URL, title, profile name per session
|
|
362
|
-
- **Profiles on disk** — named profiles with state size and which is
|
|
363
|
-
currently active; session profiles are collapsed into a single count line
|
|
364
|
-
(inspect individually with `/web profile list`)
|
|
365
|
-
|
|
366
|
-
When `pi-lean-search` is also installed, the status bar shows two independent
|
|
367
|
-
glyphs: `● idle` (browser state) and `● searxng` (search health/state).
|
|
368
|
-
|
|
369
|
-
---
|
|
370
|
-
|
|
371
|
-
## Profiles — Persistent Sessions
|
|
372
|
-
|
|
373
|
-
Profiles let the AI agent maintain persistent browser state (cookies,
|
|
374
|
-
localStorage) across calls, conversations, and even across different subagents.
|
|
375
|
-
|
|
376
|
-
### Profile Modes
|
|
377
|
-
|
|
378
|
-
| Mode | `browser-navigate profile=` | Behavior |
|
|
379
|
-
|------|-----------------------------|----------|
|
|
380
|
-
| None | `"none"` | Clean slate every time — no cookies, no state |
|
|
381
|
-
| Session | `"session"` (default) | Persists state for the current conversation; survives `/reload` and `/resume` |
|
|
382
|
-
| Named | `"shopping"`, `"work"`, etc. | Shared across conversations and subagents — like browser tabs sharing a profile |
|
|
383
|
-
|
|
384
|
-
### Managing Profiles with `/web profile`
|
|
385
|
-
|
|
386
|
-
All profile management happens through the `/web profile` command:
|
|
387
|
-
|
|
388
|
-
| Sub-command | Effect |
|
|
389
|
-
|-------------|--------|
|
|
390
|
-
| `/web profile list` | List all profiles on disk with their state size |
|
|
391
|
-
| `/web profile create shopping` | Create a new named profile |
|
|
392
|
-
| `/web profile session` | Set conversation-scoped default to session mode |
|
|
393
|
-
| `/web profile none` | Reset default to ephemeral (no persistence) |
|
|
394
|
-
| `/web profile shopping` | Switch default profile to an existing named profile |
|
|
395
|
-
| `/web profile clear shopping` | Delete the saved state for a profile (keeps the directory) |
|
|
396
|
-
| `/web profile clear-all --confirm` | Clear ALL profile states |
|
|
397
|
-
| `/web profile prune --confirm` | Remove stale session profiles for ended conversations |
|
|
398
|
-
|
|
399
|
-
> **How it works:** Profile state is stored at
|
|
400
|
-
> `~/.pi/agent/pi-lean-portal/browser-state/<profile-name>/storage-state.json`.
|
|
401
|
-
> Session-scoped profiles use names like `_session-<piSessionId>` and are
|
|
402
|
-
> auto-cleaned when the pi conversation ends.
|
|
188
|
+
### Domain Matching
|
|
403
189
|
|
|
404
|
-
|
|
190
|
+
A guide's declared domain matches the **exact hostname or any subdomain of
|
|
191
|
+
it**. Declaring `reddit.com` covers `www.reddit.com`, `old.reddit.com`, and
|
|
192
|
+
any other subdomain, so a guide saved once resurfaces across a site's URL
|
|
193
|
+
variations. This is what makes guides cheap to author: you rarely need more
|
|
194
|
+
than the apex domain. A domain may match multiple guides (a web guide plus
|
|
195
|
+
one or more API guides) — all matching guides surface together, sorted
|
|
196
|
+
host-first (API guides before web guides).
|
|
405
197
|
|
|
406
|
-
|
|
198
|
+
### API guides from `pi-lean-host` (co-install)
|
|
407
199
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
> cookies are loaded.
|
|
200
|
+
When `pi-lean-host` is installed alongside portal and `/api` is on, its
|
|
201
|
+
user-authored API guides also **surface in the navigate footer** alongside
|
|
202
|
+
your web guides using the same reactive mechanism, with no extra setup. API guides sort
|
|
203
|
+
first (API access is cheaper than browsing) but both always appear, so a
|
|
204
|
+
partial-coverage API keeps its web guide for the gaps the API doesn't cover.
|
|
205
|
+
The footer routes API guides to `api-guide({domain, guide})` rather than
|
|
206
|
+
`web-guide`. See the
|
|
207
|
+
[host README](https://github.com/coreyryanhanson/pi-lean-dimension/blob/main/packages/pi-lean-host/README.md#co-installing-with-pi-lean-portal)
|
|
208
|
+
for the host side of the contract.
|
|
418
209
|
|
|
419
210
|
---
|
|
420
211
|
|
|
421
212
|
## Backend Architecture
|
|
422
213
|
|
|
423
214
|
`pi-lean-portal` uses a **plugin-based architecture**. The core framework is
|
|
424
|
-
backend-agnostic
|
|
215
|
+
backend-agnostic; plugins implement a standard `BrowserPlugin` interface,
|
|
425
216
|
and the router dispatches tool calls to the right plugin based on a
|
|
426
217
|
`strategy` parameter.
|
|
427
218
|
|
|
428
219
|
### Four Shipped Backends
|
|
429
220
|
|
|
430
|
-
The extension ships with **four browser backends** out of the box:
|
|
431
|
-
|
|
432
221
|
| Backend | Engine | Type | Default |
|
|
433
|
-
|
|
222
|
+
| ------- | ------ | ---- | ------- |
|
|
434
223
|
| `chromium` | Chromium | Node/Playwright | **Enabled** (auto strategy) |
|
|
435
224
|
| `firefox` | Firefox | Node/Playwright | **Enabled** |
|
|
436
225
|
| `chromium-py` | Chromium | Python/Playwright | Disabled |
|
|
@@ -440,134 +229,43 @@ The extension ships with **four browser backends** out of the box:
|
|
|
440
229
|
> `firefox` backend. For the Python parity backends, install Playwright
|
|
441
230
|
> inside `backends/python-base/.venv`.
|
|
442
231
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
capability advertisement:
|
|
448
|
-
|
|
449
|
-
| Capability | Chromium / Firefox (Node) | `-py` backends (Python) |
|
|
450
|
-
|------------|--------------------------|------------------------|
|
|
451
|
-
| Full-page screenshots | ✅ | ✅ |
|
|
452
|
-
| Console message capture | ✅ | ✅ |
|
|
453
|
-
| JavaScript evaluation | ✅ | ✅ |
|
|
454
|
-
| Bot detection | ✅ | ✅ |
|
|
455
|
-
| Dialog auto-dismissal | ✅ | ✅ |
|
|
456
|
-
| AbortSignal support | ✅ | Advertised, silently ignored |
|
|
232
|
+
All four shipped backends support screenshots (viewport-sized, not
|
|
233
|
+
full-page), console capture, JS evaluation, bot detection, and dialog
|
|
234
|
+
auto-dismissal. The one divergence:
|
|
235
|
+
`AbortSignal` is advertised but silently ignored on the Python `-py` backends.
|
|
457
236
|
|
|
458
|
-
> The `-py`
|
|
459
|
-
>
|
|
460
|
-
>
|
|
461
|
-
> section below). Keep `chromium-py` as a reference when reading the
|
|
462
|
-
> bridge code.
|
|
237
|
+
> The `-py` backends are disabled by default, as they ship as parity references
|
|
238
|
+
> for the Python bridge contract and as templates for authoring your own
|
|
239
|
+
> Python-based backends.
|
|
463
240
|
|
|
464
241
|
### How Plugin Selection Works
|
|
465
242
|
|
|
466
|
-
- The **order** of plugins in the config array determines priority
|
|
243
|
+
- The **order** of plugins in the config array determines priority; the
|
|
467
244
|
first enabled plugin is the "auto" default (typically Chromium).
|
|
468
245
|
- The **AI agent explicitly selects** which backend to use via the
|
|
469
246
|
`strategy` parameter in `browser-navigate`:
|
|
470
247
|
- `strategy="auto"` → uses the first enabled plugin (typically Chromium)
|
|
471
248
|
- `strategy="firefox"` → uses the Firefox Node backend
|
|
472
249
|
- `strategy="chromium-py"` → uses the Python Chromium backend
|
|
473
|
-
- **No automatic fallbacks** and **no mid-session transitions
|
|
250
|
+
- **No automatic fallbacks** and **no mid-session transitions**. If a
|
|
474
251
|
plugin fails, the agent decides what to do next.
|
|
475
|
-
- The extension auto-detects whether a plugin is Node-based (`index.ts`)
|
|
476
|
-
or Python-based (`bridge.py`) by inspecting the directory.
|
|
477
252
|
|
|
478
253
|
### Stealth & Custom Browser Backends
|
|
479
254
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
[`contributed/
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
`~/.pi/agent/pi-lean-portal/user-backends/<name>-py/bridge.py` (the
|
|
495
|
-
`-py` suffix mirrors the shipped `chromium-py` / `firefox-py`). This is
|
|
496
|
-
a separate tree from the package's own `backends/` directory, which is
|
|
497
|
-
not edited after install — exactly so custom backends survive updates.
|
|
498
|
-
2. **Create a venv and fetch the engine binary** (e.g.
|
|
499
|
-
`python -m camoufox fetch`). The shared `pi_browser_bridge` library is
|
|
500
|
-
injected onto `PYTHONPATH` automatically at spawn time, so you do not
|
|
501
|
-
need to `pip install` it.
|
|
502
|
-
3. **Register it in `browser.plugins`** with an **absolute** `pythonPath`
|
|
503
|
-
and a `launch` object whose keys are forwarded to the bridge.
|
|
504
|
-
4. **Verify with `/web status`** and a `browser-navigate`.
|
|
505
|
-
|
|
506
|
-
The shipped **Camoufox template** at
|
|
507
|
-
[`contributed/camoufox-py/bridge.py`](./contributed/camoufox-py/bridge.py)
|
|
508
|
-
is a worked example — copy it as a starting point. The full install flow,
|
|
509
|
-
the quirks schema reference, and the security model (user-backends are
|
|
510
|
-
**trusted user code** — never auto-downloaded, no plugin marketplace) live
|
|
511
|
-
in [`contributed/README.md`](./contributed/README.md). The decision doc at
|
|
512
|
-
[`contributed/CHOOSING.md`](./contributed/CHOOSING.md) covers when to use
|
|
513
|
-
a stealth backend at all and the two lifecycle patterns for implementing
|
|
514
|
-
your own.
|
|
515
|
-
|
|
516
|
-
#### Writing your own backend (high level)
|
|
517
|
-
|
|
518
|
-
A custom Python backend is a subclass of `PlaywrightBridge`
|
|
519
|
-
(`backends/python-base/pi_browser_bridge/playwright_base.py`) that sets
|
|
520
|
-
the **quirks flags** its engine needs as class attributes and overrides
|
|
521
|
-
the launch hook matching how the engine owns Playwright. The flags
|
|
522
|
-
(`_fingerprint_managed_context`, `_eval_prefix`, `_scroll_via_wheel`,
|
|
523
|
-
`_skip_default_viewport`, `_skip_networkidle`, `_wrap_mw_eval_in_eval`)
|
|
524
|
-
all default off, so a subclass that sets none of them is bit-identical to
|
|
525
|
-
the shipped `chromium-py` / `firefox-py`. The full table with effects is
|
|
526
|
-
in [`contributed/README.md`](./contributed/README.md#quirks-schema-reference).
|
|
527
|
-
|
|
528
|
-
Node-based custom backends follow the same shape via the
|
|
529
|
-
`PlaywrightPluginBase` class — the auto-detection in `plugin-loading`
|
|
530
|
-
picks up `index.ts` (Node) or `bridge.py` (Python) entry points from the
|
|
531
|
-
user-backends directory.
|
|
532
|
-
|
|
533
|
-
#### Tests are auto-discovered
|
|
534
|
-
|
|
535
|
-
You usually do **not** need to write your own tests. The contributed
|
|
536
|
-
runner at `__tests__/run-contributed-suites.test.ts` discovers every
|
|
537
|
-
backend under `user-backends/*-py/`, loads config from the test-local
|
|
538
|
-
`settings.json`, and runs the shared contract + persistence + parity +
|
|
539
|
-
quirks-introspection suites against it — forwarding your configured
|
|
540
|
-
`launch` options. Opt in with `CONTRIB_RUN=1`:
|
|
541
|
-
|
|
542
|
-
```bash
|
|
543
|
-
npm run setup:miniwob # one-time: clone MiniWoB++ content
|
|
544
|
-
CONTRIB_RUN=1 npx vitest run packages/pi-lean-portal/__tests__/run-contributed-suites.test.ts
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
A custom backend's config entry looks like:
|
|
548
|
-
|
|
549
|
-
```jsonc
|
|
550
|
-
{
|
|
551
|
-
"browser": {
|
|
552
|
-
"plugins": [
|
|
553
|
-
{ "name": "chromium", "dir": "chromium", "enabled": true, "config": {} },
|
|
554
|
-
{ "name": "firefox", "dir": "firefox", "enabled": true, "config": {} },
|
|
555
|
-
{ "name": "camoufox-py", "dir": "camoufox-py", "enabled": true, "config": {
|
|
556
|
-
"pythonPath": "/home/me/.pi/agent/pi-lean-portal/user-backends/camoufox-py/.venv/bin/python",
|
|
557
|
-
"launch": { "headless": true, "os": "windows", "humanize": true }
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
]
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
`pythonPath` must be **absolute**; `dir` resolves against the user-backends
|
|
566
|
-
root (multi-root discovery: package `backends/` → `USER_BACKENDS_DIR` →
|
|
567
|
-
absolute). `launch` keys are forwarded to the bridge as
|
|
568
|
-
`plugin_config.launch` via the `browser.init` RPC. Stealth backends are
|
|
569
|
-
never in the default fallback list — a fresh install with no
|
|
570
|
-
`browser.plugins` loads only the four shipped backends.
|
|
255
|
+
Stealth engines like **Camoufox** are intentionally **left to users** to
|
|
256
|
+
author: drop a `bridge.py` into
|
|
257
|
+
`~/.pi/agent/pi-lean-portal/user-backends/<name>-py/` — a separate tree
|
|
258
|
+
from the package's `backends/` directory (never edited after install,
|
|
259
|
+
so custom backends survive updates) and never in the default fallback list.
|
|
260
|
+
Register one in `browser.plugins` with an **absolute** `pythonPath` (see
|
|
261
|
+
[Configuration](#configuration-settingsjson)).
|
|
262
|
+
|
|
263
|
+
The full install flow, the quirks schema, and the worked Camoufox template
|
|
264
|
+
live in
|
|
265
|
+
[`contributed/README.md`](https://github.com/coreyryanhanson/pi-lean-dimension/blob/main/packages/pi-lean-portal/contributed/README.md);
|
|
266
|
+
[`contributed/CHOOSING.md`](https://github.com/coreyryanhanson/pi-lean-dimension/blob/main/packages/pi-lean-portal/contributed/CHOOSING.md)
|
|
267
|
+
covers when to reach for one at all (most users never need one).
|
|
268
|
+
Node-based custom backends follow the same shape via `PlaywrightPluginBase`.
|
|
571
269
|
|
|
572
270
|
---
|
|
573
271
|
|
|
@@ -587,7 +285,7 @@ Controls which browser backends are loaded. Entries are processed in order
|
|
|
587
285
|
"plugins": [
|
|
588
286
|
{
|
|
589
287
|
"name": "chromium", // Required: unique plugin identifier
|
|
590
|
-
"dir": "chromium", // Required: directory
|
|
288
|
+
"dir": "chromium", // Required: backend directory
|
|
591
289
|
"enabled": true, // Optional, defaults to true
|
|
592
290
|
"config": {} // Optional, passed to the plugin's init()
|
|
593
291
|
}
|
|
@@ -596,11 +294,9 @@ Controls which browser backends are loaded. Entries are processed in order
|
|
|
596
294
|
}
|
|
597
295
|
```
|
|
598
296
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
shown for `camoufox-py` in the [Stealth & Custom Browser Backends](#stealth--custom-browser-backends)
|
|
603
|
-
section above is the reference for a user-authored Python backend).
|
|
297
|
+
A user-installed stealth backend additionally puts an **absolute** `pythonPath`
|
|
298
|
+
and a `launch` object into `config` — see
|
|
299
|
+
[`contributed/README.md`](https://github.com/coreyryanhanson/pi-lean-dimension/blob/main/packages/pi-lean-portal/contributed/README.md#6-register-in-settingsjson).
|
|
604
300
|
|
|
605
301
|
### `browser.defaultProfile`
|
|
606
302
|
|
|
@@ -615,48 +311,28 @@ a `profile` parameter:
|
|
|
615
311
|
}
|
|
616
312
|
```
|
|
617
313
|
|
|
618
|
-
### `
|
|
314
|
+
### `toolsetDefaults`
|
|
619
315
|
|
|
620
|
-
Whether browser tools are enabled on fresh conversations.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
**that block is not read yet**, so keep this key until the replacement ships.
|
|
316
|
+
Whether browser tools are enabled on fresh conversations. Read by the
|
|
317
|
+
`pi-tool-masking` library at restore time, between the chat-branch tier and
|
|
318
|
+
the toolset's packaged default:
|
|
624
319
|
|
|
625
320
|
```jsonc
|
|
626
321
|
{
|
|
627
|
-
"
|
|
628
|
-
"
|
|
322
|
+
"toolsetDefaults": {
|
|
323
|
+
"toolset-state:pi-lean-dimension.web": { "enabled": true },
|
|
324
|
+
"toolset-state:pi-lean-dimension.web-learn": { "enabled": false },
|
|
325
|
+
"toolset-state:pi-lean-dimension.search": { "enabled": true }
|
|
629
326
|
}
|
|
630
327
|
}
|
|
631
328
|
```
|
|
632
329
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
>
|
|
640
|
-
> ```jsonc
|
|
641
|
-
> {
|
|
642
|
-
> "browserToggle": { "defaultEnabled": true },
|
|
643
|
-
> "toolsetDefaults": {
|
|
644
|
-
> "toolset-state:pi-lean-dimension.web": { "enabled": true },
|
|
645
|
-
> "toolset-state:pi-lean-dimension.web-learn": { "enabled": false },
|
|
646
|
-
> "toolset-state:pi-lean-dimension.search": { "enabled": true }
|
|
647
|
-
> }
|
|
648
|
-
> }
|
|
649
|
-
> ```
|
|
650
|
-
>
|
|
651
|
-
> - Keys are the toolsets' `persistKey` values (`toolset-state:<id>`).
|
|
652
|
-
> - Omit a `toolsetDefaults` key to use the toolset's packaged default (`web`
|
|
653
|
-
> and `search` default `true`; `web-learn` defaults `false`).
|
|
654
|
-
> - The `search` key only applies when `pi-lean-search` is installed.
|
|
655
|
-
>
|
|
656
|
-
> Once the offload ships and the legacy read is removed, delete the
|
|
657
|
-
> `browserToggle` block. Until then, a migration warning fires on session
|
|
658
|
-
> start when the legacy key is present and the web default hasn't yet been
|
|
659
|
-
> mirrored into `toolsetDefaults`; mirroring it suppresses the warning.
|
|
330
|
+
- Keys are the toolsets' `persistKey` values (`toolset-state:<id>`).
|
|
331
|
+
- Omit a `toolsetDefaults` key to use the toolset's packaged default (`web`
|
|
332
|
+
and `search` default `true`; `web-learn` defaults `false`).
|
|
333
|
+
- The `search` key only applies when `pi-lean-search` is installed.
|
|
334
|
+
- Pins do not apply in spawned subagent children (see pi-tool-masking
|
|
335
|
+
1.3.0's `piToolMasking.childPolicy` for the opt-out).
|
|
660
336
|
|
|
661
337
|
### `browser.maxStorageStateSize`
|
|
662
338
|
|
|
@@ -677,61 +353,30 @@ Size threshold for profile state warnings (default: 10 MB):
|
|
|
677
353
|
### When to use `web-fetch` vs `browser-navigate`
|
|
678
354
|
|
|
679
355
|
| Use `web-fetch` | Use `browser-navigate` |
|
|
680
|
-
|
|
356
|
+
| --------------- | ---------------------- |
|
|
681
357
|
| Static content, docs, READMEs | Interactive pages, JS-heavy SPAs |
|
|
682
358
|
| Quick lookups, no session needed | Form filling, clicking, authentication |
|
|
683
|
-
|
|
|
684
|
-
| Content you want as clean Markdown | Pages where you need the accessibility tree |
|
|
685
|
-
|
|
686
|
-
### Working with `@e` Element References
|
|
687
|
-
|
|
688
|
-
- `@e1`, `@e2`, etc. are assigned based on the accessibility tree order
|
|
689
|
-
- `browser-click`/`type`/`scroll` already return a fresh snapshot and cache
|
|
690
|
-
the full tree to disk — no separate `browser-snapshot` needed unless you
|
|
691
|
-
want the uncompacted tree (`full=true`) or a screenshot
|
|
692
|
-
- `browser-inspect` is cheaper than `browser-snapshot full=true` for finding
|
|
693
|
-
specific elements
|
|
359
|
+
| Content you want as clean Markdown | Visual inspection (auto-captured screenshots), pages where you need the accessibility tree |
|
|
694
360
|
|
|
695
|
-
###
|
|
361
|
+
### Working with `@e` Element References & Large Pages
|
|
696
362
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
offset/limit to retrieve the complete tree
|
|
702
|
-
- `browser-inspect text=true query="keyword"` finds specific content without
|
|
703
|
-
loading the full tree
|
|
363
|
+
The agent interacts via `@e1`, `@e2` refs from the accessibility tree —
|
|
364
|
+
no CSS selectors or XPath. Snapshots are auto-compacted to ~2500 chars;
|
|
365
|
+
full trees and screenshots spill to `/tmp/pi-lean-portal/` (paths are
|
|
366
|
+
surfaced in tool output).
|
|
704
367
|
|
|
705
368
|
### Bot Detection
|
|
706
369
|
|
|
707
|
-
When a page triggers anti-automation
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
4. Retry with a stealth backend — the `browser-navigate` `strategy`
|
|
714
|
-
parameter lists registered backend names; a stealth backend (e.g.
|
|
715
|
-
`strategy="camoufox"`) can pass challenges the default `chromium`/
|
|
716
|
-
`firefox` triggers. Only names listed in the `strategy` description
|
|
717
|
-
are valid — there is no `"stealth"` alias
|
|
718
|
-
5. Try `web-fetch` on the same URL — it skips JS execution, so it can
|
|
719
|
-
retrieve raw HTML on pages that block the interactive browser via
|
|
720
|
-
client-side fingerprinting (it won't help against server-side WAFs)
|
|
721
|
-
|
|
722
|
-
### Guide Creation Discipline
|
|
723
|
-
|
|
724
|
-
When creating navigation guides with `web-learn`:
|
|
725
|
-
|
|
726
|
-
- Keep guidance **concise** (≤800 chars recommended)
|
|
727
|
-
- Focus on: page structure, consent dialogs, known quirks, and useful
|
|
728
|
-
selector patterns
|
|
729
|
-
- Include domains so the guide appears in the footer on future navigations
|
|
730
|
-
- No runtime enforcement on guide length, but brevity helps the LLM
|
|
370
|
+
When a page triggers anti-automation, the agent sees a warning plus a
|
|
371
|
+
bot-detection guide footer, and challenge pages with <5 visible elements
|
|
372
|
+
fail hard rather than being interacted with. If a site consistently blocks
|
|
373
|
+
the shipped Chromium/Firefox, that's the trigger to install a stealth
|
|
374
|
+
backend (see [Stealth & Custom Browser Backends](#stealth--custom-browser-backends)) —
|
|
375
|
+
not something to configure up front.
|
|
731
376
|
|
|
732
377
|
### Security
|
|
733
378
|
|
|
734
|
-
- URLs are parsed with `new URL()` as input validation
|
|
379
|
+
- URLs are parsed with `new URL()` as input validation. Malformed
|
|
735
380
|
URLs are rejected, but no SSRF boundary is enforced (a coding agent
|
|
736
381
|
already has filesystem and shell access, so blocking localhost or
|
|
737
382
|
private IPs would be theater)
|
|
@@ -740,9 +385,4 @@ When creating navigation guides with `web-learn`:
|
|
|
740
385
|
|
|
741
386
|
---
|
|
742
387
|
|
|
743
|
-
> `pi-lean-portal` is part of the
|
|
744
|
-
> [pi-lean-dimension](https://github.com/coreyryanhanson/pi-lean-dimension)
|
|
745
|
-
> web-tools suite. For questions, issues, or feature requests, check the
|
|
746
|
-
> project's documentation or open an issue.
|
|
747
|
-
>
|
|
748
388
|
> License: AGPL-3.0-only
|