pi-lean-dimension 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/node_modules/pi-lean-portal/AGENTS.md +1 -1
- package/node_modules/pi-lean-portal/README.md +28 -18
- package/node_modules/pi-lean-portal/__tests__/plugin-config-browser.test.ts +28 -0
- package/node_modules/pi-lean-portal/backends/playwright-base/playwright-plugin.ts +237 -181
- package/node_modules/pi-lean-portal/backends/python-adapter.ts +7 -2
- package/node_modules/pi-lean-portal/contributed/CHOOSING.md +1 -1
- package/node_modules/pi-lean-portal/contributed/README.md +1 -1
- package/node_modules/pi-lean-portal/core/guides.ts +1 -2
- package/node_modules/pi-lean-portal/core/plugin-config.ts +27 -3
- package/node_modules/pi-lean-portal/core/router.ts +2 -1
- package/node_modules/pi-lean-portal/core/shared/storage-state.ts +6 -2
- package/node_modules/pi-lean-portal/package.json +1 -1
- package/node_modules/pi-lean-search/__tests__/web-search.test.ts +241 -1
- package/node_modules/pi-lean-search/package.json +1 -1
- package/node_modules/pi-lean-search/web-search-tool.ts +222 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ search via SearXNG — all toggled from a single `/web` command. When the toggle
|
|
|
8
8
|
is off, the tools are removed from the agent's context entirely, so web browsing
|
|
9
9
|
doesn't consume tokens or attention on sessions that aren't doing web work.
|
|
10
10
|
The same surfaces are user-extensible: author navigation guides that resurface
|
|
11
|
-
by domain, or drop in a stealth browser backend like [Camoufox](https://github.com/
|
|
11
|
+
by domain, or drop in a stealth browser backend like [Camoufox](https://github.com/daijro/camoufox)
|
|
12
12
|
when a site blocks the shipped Chromium/Firefox.
|
|
13
13
|
|
|
14
14
|
## Quick start (recommended)
|
|
@@ -100,7 +100,7 @@ When search is installed, two independent glyphs appear:
|
|
|
100
100
|
Beyond the `/web` toggle, two surfaces are user-driven rather than hardcoded:
|
|
101
101
|
|
|
102
102
|
- **Navigation guides** — `web-learn` saves site-specific playbooks that auto-match by domain and resurface in later sessions.
|
|
103
|
-
- **Custom browser backends** — if a site blocks the shipped Chromium/Firefox, drop a `bridge.py` subclass into `~/.pi/agent/pi-lean-portal/user-backends/` and drive a patched engine like [Camoufox](https://github.com/
|
|
103
|
+
- **Custom browser backends** — if a site blocks the shipped Chromium/Firefox, drop a `bridge.py` subclass into `~/.pi/agent/pi-lean-portal/user-backends/` and drive a patched engine like [Camoufox](https://github.com/daijro/camoufox) yourself. A quirks schema declares how the engine diverges from base Playwright, and `launch` options flow from `settings.json` to the subprocess at runtime. This is user-authored, user-audited code that the extension never auto-downloads — and as far as we're aware, no other Pi web plugin lets you run a browser backend you wrote yourself. Most installs never need it; the [portal README](packages/pi-lean-portal/README.md#stealth--custom-browser-backends) and [`contributed/README.md`](packages/pi-lean-portal/contributed/README.md) cover the full flow when you do.
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
@@ -199,7 +199,7 @@ All tool calls dispatch through the router. Key responsibilities:
|
|
|
199
199
|
- **Atomic writes + concurrency safety** (`storage-state.ts`): `saveStorageState()` writes to a temp file then renames atomically, preventing half-write races. Concurrent writers merge at the cookie level (`name+domain+path` key) and localStorage level (`origin+name` key), so two agents sharing a named profile don't clobber each other's data.
|
|
200
200
|
- **Session profiles** (`profile="session"`) are scoped to one pi conversation, stored under `_session-<piSessionId>`. Default profile is now `"session"` (changed from `"none"`), so conversations persist state automatically.
|
|
201
201
|
- **Named profiles** (`profile="shopping"`, `profile="work"`) are shared across conversations and agents.
|
|
202
|
-
- **Conversation-scoped default profile** set via `/web profile
|
|
202
|
+
- **Conversation-scoped default profile** set via `/web profile <name>` (or `/web profile none` / `/web profile session`), survives `/reload`/`/resume`.
|
|
203
203
|
- **Cookie operations** (`getCookies`, `addCookies`, `clearCookies`) delegate to the browser plugin's Playwright `context.cookies()` / `context.clearCookies()`.
|
|
204
204
|
|
|
205
205
|
## Known Constraints & Debt
|
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
> domain. A `/web` toggle removes the tools from the agent's context when
|
|
7
7
|
> switched off, so web browsing doesn't consume tokens on sessions that aren't
|
|
8
8
|
> doing web work. If a site blocks the shipped browsers, drop in your own
|
|
9
|
-
> backend (e.g. [Camoufox](https://github.com/
|
|
10
|
-
> we're aware, no other Pi web plugin lets you run a browser backend you wrote
|
|
11
|
-
> yourself.
|
|
9
|
+
> backend (e.g. [Camoufox](https://github.com/daijro/camoufox)).
|
|
12
10
|
>
|
|
13
11
|
> Part of the [pi-lean-dimension](https://github.com/coreyryanhanson/pi-lean-dimension)
|
|
14
12
|
> web-tools suite. For SearXNG search support, install
|
|
@@ -42,7 +40,7 @@ npx playwright install chromium firefox
|
|
|
42
40
|
|
|
43
41
|
Once loaded, you'll see a notification like:
|
|
44
42
|
|
|
45
|
-
> 🌐 Browser extension loaded (plugins: chromium, firefox)
|
|
43
|
+
> 🌐 Browser extension loaded (plugins: chromium, firefox). Try: web-fetch for static pages or browser-navigate for interactive browsing.
|
|
46
44
|
|
|
47
45
|
The browser tools are **enabled by default**. You can:
|
|
48
46
|
|
|
@@ -70,7 +68,7 @@ Beyond the toggle, two surfaces are user-extensible rather than hardcoded:
|
|
|
70
68
|
[Navigation Guides](#navigation-guides-web-guide--web-learn).
|
|
71
69
|
- **Custom browser backends** — if a site blocks the shipped Chromium/Firefox,
|
|
72
70
|
drop a `bridge.py` subclass into `~/.pi/agent/pi-lean-portal/user-backends/`
|
|
73
|
-
and drive a patched engine like [Camoufox](https://github.com/
|
|
71
|
+
and drive a patched engine like [Camoufox](https://github.com/daijro/camoufox)
|
|
74
72
|
yourself. The full flow lives in [Backend Architecture](#backend-architecture)
|
|
75
73
|
and [`contributed/README.md`](./contributed/README.md).
|
|
76
74
|
|
|
@@ -122,7 +120,8 @@ which defaults to `true`).
|
|
|
122
120
|
**Auto-captured screenshots:** `browser-navigate` and `browser-snapshot` automatically
|
|
123
121
|
capture a screenshot to a temp file (`/tmp/pi-lean-portal/screenshot-<taskId>.jpg`).
|
|
124
122
|
Use the `read` tool to visually inspect the page when the accessibility tree isn't enough.
|
|
125
|
-
|
|
123
|
+
Screenshots capture the 1280×720 viewport (not full-page) — the same viewport the
|
|
124
|
+
browser uses for navigation.
|
|
126
125
|
|
|
127
126
|
### 1. `browser-navigate` — Visit a Page
|
|
128
127
|
|
|
@@ -201,7 +200,7 @@ Navigates back in browser history. Returns the previous page's snapshot.
|
|
|
201
200
|
browser-press key="Enter"
|
|
202
201
|
```
|
|
203
202
|
|
|
204
|
-
Useful keys: `Enter`, `Tab`, `Escape`, `ArrowDown`, `ArrowUp`,
|
|
203
|
+
Useful keys: `Enter`, `Tab`, `Escape`, `ArrowDown`, `ArrowUp`, `Backspace`.
|
|
205
204
|
|
|
206
205
|
### 8. `browser-console` — Read Console / Run JS
|
|
207
206
|
|
|
@@ -306,12 +305,13 @@ Shows everything about the browser runtime in one notification:
|
|
|
306
305
|
🌐 Browser tools: ✅ on | 📖 Learn mode: ❌ off
|
|
307
306
|
────────────────────────────────────────
|
|
308
307
|
Status: idle
|
|
309
|
-
Plugins: chromium
|
|
308
|
+
Plugins: chromium, firefox, chromium-py (disabled), firefox-py (disabled)
|
|
309
|
+
Use web-fetch for stateless HTTP fetches.
|
|
310
310
|
Active sessions: 1
|
|
311
311
|
PW [chromium] https://example.com — Example Domain [profile: session]
|
|
312
|
-
Profiles:
|
|
313
|
-
|
|
314
|
-
|
|
312
|
+
Profiles: 1 on disk (named)
|
|
313
|
+
shopping (0.3 KB) ← active
|
|
314
|
+
Session profiles: 1 (manage with /web profile)
|
|
315
315
|
```
|
|
316
316
|
|
|
317
317
|
Covers:
|
|
@@ -320,7 +320,9 @@ Covers:
|
|
|
320
320
|
- **Backend health** — idle, busy, or error state
|
|
321
321
|
- **All registered plugins** — enabled/disabled status
|
|
322
322
|
- **Active sessions** — current URL, title, profile name per session
|
|
323
|
-
- **Profiles on disk** — state size and which
|
|
323
|
+
- **Profiles on disk** — named profiles with state size and which is
|
|
324
|
+
currently active; session profiles are collapsed into a single count line
|
|
325
|
+
(inspect individually with `/web profile list`)
|
|
324
326
|
|
|
325
327
|
When `pi-lean-search` is also installed, the status bar shows two independent
|
|
326
328
|
glyphs: `● idle` (browser state) and `● searxng` (search health/state).
|
|
@@ -614,8 +616,9 @@ Size threshold for profile state warnings (default: 10 MB):
|
|
|
614
616
|
### Working with `@e` Element References
|
|
615
617
|
|
|
616
618
|
- `@e1`, `@e2`, etc. are assigned based on the accessibility tree order
|
|
617
|
-
-
|
|
618
|
-
|
|
619
|
+
- `browser-click`/`type`/`scroll` already return a fresh snapshot and cache
|
|
620
|
+
the full tree to disk — no separate `browser-snapshot` needed unless you
|
|
621
|
+
want the uncompacted tree (`full=true`) or a screenshot
|
|
619
622
|
- `browser-inspect` is cheaper than `browser-snapshot full=true` for finding
|
|
620
623
|
specific elements
|
|
621
624
|
|
|
@@ -623,8 +626,9 @@ Size threshold for profile state warnings (default: 10 MB):
|
|
|
623
626
|
|
|
624
627
|
- Snapshots are automatically compacted to ~2500 characters
|
|
625
628
|
- Very large pages (>8000 chars) preserve the top ~2000 chars
|
|
626
|
-
- The **full tree is cached to disk** at `/tmp/pi-lean-portal/snapshot-*.txt`
|
|
627
|
-
|
|
629
|
+
- The **full tree is cached to disk** at `/tmp/pi-lean-portal/snapshot-*.txt`
|
|
630
|
+
when it would otherwise be truncated — use `read` on the cache file with
|
|
631
|
+
offset/limit to retrieve the complete tree
|
|
628
632
|
- `browser-inspect text=true query="keyword"` finds specific content without
|
|
629
633
|
loading the full tree
|
|
630
634
|
|
|
@@ -636,8 +640,14 @@ When a page triggers anti-automation:
|
|
|
636
640
|
2. The **bot-detection guide** footer appears with strategies available via `web-guide`
|
|
637
641
|
3. If very few elements are detected (<5), the navigation is treated as
|
|
638
642
|
a hard failure — the agent won't try to interact with a challenge page
|
|
639
|
-
4.
|
|
640
|
-
|
|
643
|
+
4. Retry with a stealth backend — the `browser-navigate` `strategy`
|
|
644
|
+
parameter lists registered backend names; a stealth backend (e.g.
|
|
645
|
+
`strategy="camoufox"`) can pass challenges the default `chromium`/
|
|
646
|
+
`firefox` triggers. Only names listed in the `strategy` description
|
|
647
|
+
are valid — there is no `"stealth"` alias
|
|
648
|
+
5. Try `web-fetch` on the same URL — it skips JS execution, so it can
|
|
649
|
+
retrieve raw HTML on pages that block the interactive browser via
|
|
650
|
+
client-side fingerprinting (it won't help against server-side WAFs)
|
|
641
651
|
|
|
642
652
|
### Guide Creation Discipline
|
|
643
653
|
|
|
@@ -92,6 +92,34 @@ describe("loadFullConfig().browser", () => {
|
|
|
92
92
|
mockGlobalSettings({ unrelated: true });
|
|
93
93
|
const config = loadFullConfig().browser;
|
|
94
94
|
expect(config.defaultProfile).toBe("session");
|
|
95
|
+
expect(config.maxStorageStateSize).toBe(10 * 1024 * 1024);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ── maxStorageStateSize ────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
describe("maxStorageStateSize", () => {
|
|
101
|
+
it("accepts a positive number", () => {
|
|
102
|
+
mockGlobalSettings({ maxStorageStateSize: 5 * 1024 * 1024 });
|
|
103
|
+
expect(loadFullConfig().browser.maxStorageStateSize).toBe(
|
|
104
|
+
5 * 1024 * 1024,
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("floors fractional values", () => {
|
|
109
|
+
mockGlobalSettings({ maxStorageStateSize: 5.9 * 1024 * 1024 });
|
|
110
|
+
expect(loadFullConfig().browser.maxStorageStateSize).toBe(
|
|
111
|
+
Math.floor(5.9 * 1024 * 1024),
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("rejects zero / negative / non-finite and falls back to default", () => {
|
|
116
|
+
for (const bad of [0, -1, Infinity, NaN, "big", null]) {
|
|
117
|
+
mockGlobalSettings({ maxStorageStateSize: bad });
|
|
118
|
+
expect(loadFullConfig().browser.maxStorageStateSize).toBe(
|
|
119
|
+
10 * 1024 * 1024,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
95
123
|
});
|
|
96
124
|
|
|
97
125
|
// ── defaultProfile ─────────────────────────────────────────
|