pi-lean-portal 0.3.2 → 0.3.3
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 +42 -2
- package/browser-toggle.ts +98 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -118,6 +118,15 @@ The toggle state is stored in the conversation's branch history. A fresh
|
|
|
118
118
|
conversation starts with the default from `settings.json` (`browserToggle.defaultEnabled`,
|
|
119
119
|
which defaults to `true`).
|
|
120
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
|
+
|
|
121
130
|
---
|
|
122
131
|
|
|
123
132
|
## All 12 Tools
|
|
@@ -606,9 +615,12 @@ a `profile` parameter:
|
|
|
606
615
|
}
|
|
607
616
|
```
|
|
608
617
|
|
|
609
|
-
### `browserToggle.defaultEnabled`
|
|
618
|
+
### `browserToggle.defaultEnabled` *(deprecated — not yet replaced)*
|
|
610
619
|
|
|
611
|
-
Whether browser tools are enabled on fresh conversations
|
|
620
|
+
Whether browser tools are enabled on fresh conversations. **This key is still
|
|
621
|
+
read today and works as shown.** It is *scheduled* to be replaced by the
|
|
622
|
+
`pi-tool-masking` library's `toolsetDefaults` block in an upcoming release —
|
|
623
|
+
**that block is not read yet**, so keep this key until the replacement ships.
|
|
612
624
|
|
|
613
625
|
```jsonc
|
|
614
626
|
{
|
|
@@ -618,6 +630,34 @@ Whether browser tools are enabled on fresh conversations:
|
|
|
618
630
|
}
|
|
619
631
|
```
|
|
620
632
|
|
|
633
|
+
> ⚠️ **Preparing for the offload.** Settings-based toolset defaults are being
|
|
634
|
+
> offloaded to the `pi-tool-masking` library, which will read a new
|
|
635
|
+
> `toolsetDefaults` block keyed by persist key. **The new block is not read
|
|
636
|
+
> by the current release** — it's harmless to add now and will take effect
|
|
637
|
+
> automatically once the offload ships, at which point the legacy key stops
|
|
638
|
+
> being read. To pre-stage the migration, set both:
|
|
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.
|
|
660
|
+
|
|
621
661
|
### `browser.maxStorageStateSize`
|
|
622
662
|
|
|
623
663
|
Size threshold for profile state warnings (default: 10 MB):
|
package/browser-toggle.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ExtensionAPI,
|
|
3
|
-
ExtensionCommandContext,
|
|
4
3
|
ExtensionContext,
|
|
5
4
|
ThemeColor,
|
|
6
5
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -12,6 +11,25 @@ import {
|
|
|
12
11
|
import type { ToolsetSpec } from "pi-tool-masking";
|
|
13
12
|
import { readMergedSettings } from "./core/shared/settings-reader.js";
|
|
14
13
|
|
|
14
|
+
// Focus-mode guard helper. The library's published `DefaultResolutionMode`
|
|
15
|
+
// type is `"exclusion" | "inclusion"` (the allowlist mode is unpublished /
|
|
16
|
+
// ships in pi-tool-masking 1.2.0), so the string cast is load-bearing: an
|
|
17
|
+
// allowlist-capable consumer sharing the `globalThis` module state writes
|
|
18
|
+
// `"allowlist"` into it, and this consumer reads that value back at runtime
|
|
19
|
+
// even though its own bundled type doesn't name the mode. On published
|
|
20
|
+
// versions no caller ever writes `"allowlist"`, so this is a no-op for
|
|
21
|
+
// ordinary users — it only activates when an allowlist-capable
|
|
22
|
+
// pi-tool-masking consumer is in play.
|
|
23
|
+
//
|
|
24
|
+
// Cleanup at the ^1.2.0 bump: once `DefaultResolutionMode` names
|
|
25
|
+
// `"allowlist"`, drop the `as string` cast here and in pi-lean-search's
|
|
26
|
+
// co-activation mirror — the type system can then check the comparison
|
|
27
|
+
// directly and the cast becomes a suppressor of a check it should perform.
|
|
28
|
+
function isFocusHolding(): boolean {
|
|
29
|
+
const mode = getDefaultResolutionMode() as string;
|
|
30
|
+
return mode === "inclusion" || mode === "allowlist";
|
|
31
|
+
}
|
|
32
|
+
|
|
15
33
|
// ---- Toolset specs -----------------------------------------------
|
|
16
34
|
|
|
17
35
|
const PORTAL_WEB_SPEC: ToolsetSpec = {
|
|
@@ -136,10 +154,72 @@ function renderBrowserGlyph(
|
|
|
136
154
|
}
|
|
137
155
|
}
|
|
138
156
|
|
|
157
|
+
// ---- Legacy settings migration warning ---------------------------
|
|
158
|
+
//
|
|
159
|
+
// The portal currently seeds the web toolset's fresh-session default from
|
|
160
|
+
// `browserToggle.defaultEnabled` in settings.json. An upcoming pi-tool-masking
|
|
161
|
+
// release takes over settings-based toolset defaults and reads a new
|
|
162
|
+
// `toolsetDefaults` block instead. Warn users who pinned the legacy key so
|
|
163
|
+
// they can migrate before the offload lands and the legacy read is removed.
|
|
164
|
+
//
|
|
165
|
+
// ponytail: warn-only — we still honor the legacy key for backward compat
|
|
166
|
+
// until pi-tool-masking owns the settings tier; then delete this helper and
|
|
167
|
+
// the `browserToggle` read below. Ceiling: a silent default shift for users
|
|
168
|
+
// who ignore the warning; upgrade path is the pi-tool-masking bump.
|
|
169
|
+
const TOOLSET_DEFAULTS_MIGRATION_MSG =
|
|
170
|
+
"⚠️ pi-lean-portal: settings-based toolset defaults are moving to the " +
|
|
171
|
+
"pi-tool-masking library. The `browserToggle.defaultEnabled` key in your " +
|
|
172
|
+
"settings.json will stop being read in an upcoming release. It still works " +
|
|
173
|
+
"today — KEEP it until the replacement ships, and add the new " +
|
|
174
|
+
"`toolsetDefaults` block alongside it so your config is ready (the new " +
|
|
175
|
+
"block is not read yet, but is harmless now and will take effect " +
|
|
176
|
+
"automatically once the offload lands):\n\n" +
|
|
177
|
+
"{\n" +
|
|
178
|
+
' "browserToggle": { "defaultEnabled": true },\n' +
|
|
179
|
+
' "toolsetDefaults": {\n' +
|
|
180
|
+
' "toolset-state:pi-lean-dimension.web": { "enabled": true },\n' +
|
|
181
|
+
' "toolset-state:pi-lean-dimension.web-learn": { "enabled": true },\n' +
|
|
182
|
+
' "toolset-state:pi-lean-dimension.search": { "enabled": true }\n' +
|
|
183
|
+
" }\n" +
|
|
184
|
+
"}\n" +
|
|
185
|
+
"(omit a `toolsetDefaults` key to use the toolset's packaged default; the " +
|
|
186
|
+
"`search` key only applies when pi-lean-search is installed). Mirror your " +
|
|
187
|
+
"web default into `toolset-state:pi-lean-dimension.web` to silence this " +
|
|
188
|
+
"warning.";
|
|
189
|
+
|
|
190
|
+
function hasLegacyToolsetDefault(merged: Record<string, unknown>): boolean {
|
|
191
|
+
const seg = merged["browserToggle"];
|
|
192
|
+
if (!seg || typeof seg !== "object" || Array.isArray(seg)) return false;
|
|
193
|
+
return (
|
|
194
|
+
typeof (seg as Record<string, unknown>)["defaultEnabled"] === "boolean"
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// The new `toolsetDefaults` block the pi-tool-masking offload will read.
|
|
199
|
+
// When the user has already migrated the web toolset's default into it,
|
|
200
|
+
// the warning is redundant even if the legacy `browserToggle.defaultEnabled`
|
|
201
|
+
// key is still sitting on disk — suppress so a migrated settings file stays
|
|
202
|
+
// quiet. Only the web persist key gates this: it's the one the legacy key
|
|
203
|
+
// controlled, so its presence means the user acted on the migration.
|
|
204
|
+
const WEB_TOOLSET_PERSIST_KEY = "toolset-state:pi-lean-dimension.web";
|
|
205
|
+
function hasMigratedToolsetDefault(merged: Record<string, unknown>): boolean {
|
|
206
|
+
const td = merged["toolsetDefaults"];
|
|
207
|
+
if (!td || typeof td !== "object" || Array.isArray(td)) return false;
|
|
208
|
+
const entry = (td as Record<string, unknown>)[WEB_TOOLSET_PERSIST_KEY];
|
|
209
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
|
|
210
|
+
return typeof (entry as Record<string, unknown>)["enabled"] === "boolean";
|
|
211
|
+
}
|
|
212
|
+
|
|
139
213
|
// ---- Toggle initializer ------------------------------------------
|
|
140
214
|
|
|
141
215
|
export default function initBrowserToggle(pi: ExtensionAPI) {
|
|
142
216
|
const merged = readMergedSettings();
|
|
217
|
+
// Warn only when the legacy key is pinned AND the user hasn't already
|
|
218
|
+
// migrated the web default into `toolsetDefaults`. Once the migrated
|
|
219
|
+
// entry exists, pi-tool-masking will read it directly and the legacy
|
|
220
|
+
// key is dead weight — no need to nag.
|
|
221
|
+
const legacyDefaultPinned =
|
|
222
|
+
hasLegacyToolsetDefault(merged) && !hasMigratedToolsetDefault(merged);
|
|
143
223
|
const browserToggleSegment = (merged as Record<string, unknown>)[
|
|
144
224
|
"browserToggle"
|
|
145
225
|
] as Record<string, unknown> | undefined;
|
|
@@ -180,16 +260,19 @@ export default function initBrowserToggle(pi: ExtensionAPI) {
|
|
|
180
260
|
const cmd = args.trim().toLowerCase();
|
|
181
261
|
|
|
182
262
|
// Focus-mode guard (§13.2): refuse actuating subcommands while the
|
|
183
|
-
// library holds the line
|
|
184
|
-
//
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
263
|
+
// library holds the line — either inclusion mode or allowlist focus
|
|
264
|
+
// (an upstream pi-tool-masking consumer). Either way a sibling
|
|
265
|
+
// toggle must not write a focus-indistinguishable {enabled} entry.
|
|
266
|
+
// Read-only subcommands (status/profile/cookies/bare /web) stay
|
|
267
|
+
// unguarded, matching the focus controller's treatment of its own
|
|
268
|
+
// read-only commands.
|
|
269
|
+
if (["on", "off", "learn"].includes(cmd) && isFocusHolding()) {
|
|
270
|
+
const inInclusion =
|
|
271
|
+
(getDefaultResolutionMode() as string) === "inclusion";
|
|
191
272
|
ctx.ui.notify(
|
|
192
|
-
|
|
273
|
+
inInclusion
|
|
274
|
+
? "Another plugin has active inclusion mode — this toolset can't be toggled while inclusion is holding the line. Deactivate it there first."
|
|
275
|
+
: "Focus mode (allowlist) is active — this toolset can't be toggled while focus is holding the line. Exit focus there first.",
|
|
193
276
|
"warning",
|
|
194
277
|
);
|
|
195
278
|
return;
|
|
@@ -265,6 +348,11 @@ export default function initBrowserToggle(pi: ExtensionAPI) {
|
|
|
265
348
|
restoreProfile(pi, ctx);
|
|
266
349
|
_lastCtx = ctx;
|
|
267
350
|
syncCachedState();
|
|
351
|
+
// One-time-per-session migration warning when the legacy
|
|
352
|
+
// `browserToggle.defaultEnabled` pin is still on disk.
|
|
353
|
+
if (legacyDefaultPinned) {
|
|
354
|
+
ctx.ui.notify(TOOLSET_DEFAULTS_MIGRATION_MSG, "warning");
|
|
355
|
+
}
|
|
268
356
|
});
|
|
269
357
|
|
|
270
358
|
pi.on("session_tree", async (_event, ctx) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-lean-portal",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Pi extension. Interactive web browsing for Pi — a /web toggle removes the tools from context when switched off, Playwright Chromium/Firefox deliver accessibility-tree snapshots, persistent profiles, cookies, and domain-matched guides; custom/stealth backends (Camoufox) plug in when a site blocks the shipped browsers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"node-html-parser": "^6.1.0",
|
|
59
|
-
"pi-tool-masking": "^1.
|
|
59
|
+
"pi-tool-masking": "^1.1.0",
|
|
60
60
|
"playwright": "^1.60.0",
|
|
61
61
|
"turndown": "^7.2.0"
|
|
62
62
|
},
|