pi-lean-dimension 0.3.0 → 0.3.1
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/node_modules/pi-lean-portal/README.md +4 -6
- package/node_modules/pi-lean-portal/__tests__/browser-toggle.test.ts +7 -7
- package/node_modules/pi-lean-portal/browser-toggle.ts +5 -5
- package/node_modules/pi-lean-portal/package.json +1 -1
- package/node_modules/pi-lean-search/__tests__/web-search.test.ts +6 -6
- package/node_modules/pi-lean-search/index.ts +14 -14
- package/node_modules/pi-lean-search/package.json +1 -1
- package/package.json +3 -3
|
@@ -691,12 +691,10 @@ When creating navigation guides with `web-learn`:
|
|
|
691
691
|
|
|
692
692
|
### Security
|
|
693
693
|
|
|
694
|
-
- URLs are
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
`javascript:`, `vbscript:`
|
|
699
|
-
- Secrets in URLs are detected heuristically
|
|
694
|
+
- URLs are parsed with `new URL()` as input validation — malformed
|
|
695
|
+
URLs are rejected, but no SSRF boundary is enforced (a coding agent
|
|
696
|
+
already has filesystem and shell access, so blocking localhost or
|
|
697
|
+
private IPs would be theater)
|
|
700
698
|
- Profile state is stored with restricted file permissions (0700 dirs,
|
|
701
699
|
0600 files)
|
|
702
700
|
|
|
@@ -259,26 +259,26 @@ describe("getToggleState / getLearnState", () => {
|
|
|
259
259
|
// appendEntry persist keys
|
|
260
260
|
// ==================================================================
|
|
261
261
|
describe("persistence key split", () => {
|
|
262
|
-
it("appends toolset-state:
|
|
262
|
+
it("appends toolset-state:pi-lean-dimension.web on enable", async () => {
|
|
263
263
|
const { pi } = mockPi([]);
|
|
264
264
|
browserToggle(pi);
|
|
265
265
|
|
|
266
266
|
await captureWebHandler(pi)("on", mockCtx());
|
|
267
267
|
|
|
268
268
|
const webCalls = (pi.appendEntry as any).mock.calls.filter(
|
|
269
|
-
(c: any) => c[0] === "toolset-state:
|
|
269
|
+
(c: any) => c[0] === "toolset-state:pi-lean-dimension.web",
|
|
270
270
|
);
|
|
271
271
|
expect(webCalls.length).toBeGreaterThanOrEqual(1);
|
|
272
272
|
});
|
|
273
273
|
|
|
274
|
-
it("appends toolset-state:
|
|
274
|
+
it("appends toolset-state:pi-lean-dimension.web-learn on learn", async () => {
|
|
275
275
|
const { pi } = mockPi([]);
|
|
276
276
|
browserToggle(pi);
|
|
277
277
|
|
|
278
278
|
await captureWebHandler(pi)("learn", mockCtx());
|
|
279
279
|
|
|
280
280
|
const learnCalls = (pi.appendEntry as any).mock.calls.filter(
|
|
281
|
-
(c: any) => c[0] === "toolset-state:
|
|
281
|
+
(c: any) => c[0] === "toolset-state:pi-lean-dimension.web-learn",
|
|
282
282
|
);
|
|
283
283
|
expect(learnCalls.length).toBeGreaterThanOrEqual(1);
|
|
284
284
|
});
|
|
@@ -377,7 +377,7 @@ describe("/web focus-mode guard", () => {
|
|
|
377
377
|
// Glyph sync on external-plugin changed events
|
|
378
378
|
// ==================================================================
|
|
379
379
|
describe("external-plugin glyph sync", () => {
|
|
380
|
-
it("re-renders browser glyph off when external plugin fires
|
|
380
|
+
it("re-renders browser glyph off when external plugin fires pi-lean-dimension.web disabled", async () => {
|
|
381
381
|
const { pi, handlers, events } = mockPi();
|
|
382
382
|
browserToggle(pi);
|
|
383
383
|
|
|
@@ -391,7 +391,7 @@ describe("external-plugin glyph sync", () => {
|
|
|
391
391
|
// Clear the initial render call so we only see the external-plugin re-render.
|
|
392
392
|
vi.clearAllMocks();
|
|
393
393
|
|
|
394
|
-
// Simulate an external plugin disabling
|
|
394
|
+
// Simulate an external plugin disabling pi-lean-dimension.web — it has
|
|
395
395
|
// already removed browser tools from the active set.
|
|
396
396
|
const nonBrowser = ALL_TOOLS.map((t) => t.name).filter(
|
|
397
397
|
(n) => !BROWSER_TOOL_NAMES.has(n),
|
|
@@ -399,7 +399,7 @@ describe("external-plugin glyph sync", () => {
|
|
|
399
399
|
(pi.getActiveTools as any).mockReturnValue(nonBrowser);
|
|
400
400
|
|
|
401
401
|
events.emit(TOOLSET_EVENTS.changed, {
|
|
402
|
-
id: "
|
|
402
|
+
id: "pi-lean-dimension.web",
|
|
403
403
|
enabled: false,
|
|
404
404
|
});
|
|
405
405
|
|
|
@@ -15,7 +15,7 @@ import { readMergedSettings } from "./core/shared/settings-reader.js";
|
|
|
15
15
|
// ---- Toolset specs -----------------------------------------------
|
|
16
16
|
|
|
17
17
|
const PORTAL_WEB_SPEC: ToolsetSpec = {
|
|
18
|
-
id: "
|
|
18
|
+
id: "pi-lean-dimension.web",
|
|
19
19
|
names: new Set([
|
|
20
20
|
"web-fetch",
|
|
21
21
|
"browser-navigate",
|
|
@@ -29,15 +29,15 @@ const PORTAL_WEB_SPEC: ToolsetSpec = {
|
|
|
29
29
|
"browser-inspect",
|
|
30
30
|
"web-guide",
|
|
31
31
|
]),
|
|
32
|
-
persistKey: "toolset-state:
|
|
32
|
+
persistKey: "toolset-state:pi-lean-dimension.web",
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
const PORTAL_LEARN_SPEC: ToolsetSpec = {
|
|
36
|
-
id: "
|
|
36
|
+
id: "pi-lean-dimension.web-learn",
|
|
37
37
|
names: new Set(["web-learn"]),
|
|
38
|
-
persistKey: "toolset-state:
|
|
38
|
+
persistKey: "toolset-state:pi-lean-dimension.web-learn",
|
|
39
39
|
defaultEnabled: false,
|
|
40
|
-
requires: ["
|
|
40
|
+
requires: ["pi-lean-dimension.web"],
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
// ---- Status bar cached state (derived from library events) ------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-lean-portal",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
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",
|
|
@@ -447,15 +447,15 @@ beforeEach(() => {
|
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
// ==================================================================
|
|
450
|
-
// Toolset wiring:
|
|
450
|
+
// Toolset wiring: pi-lean-dimension.web ↔ pi-lean-dimension.search co-activation mirror
|
|
451
451
|
// ==================================================================
|
|
452
|
-
describe("
|
|
453
|
-
it("disables search
|
|
452
|
+
describe("pi-lean-dimension.web co-activation mirror", () => {
|
|
453
|
+
it("disables pi-lean-dimension.search when pi-lean-dimension.web changed fires with enabled: false", async () => {
|
|
454
454
|
const { pi, events } = mockSearchPi();
|
|
455
455
|
searchExtension(pi);
|
|
456
456
|
|
|
457
457
|
events.emit(TOOLSET_EVENTS.changed, {
|
|
458
|
-
id: "
|
|
458
|
+
id: "pi-lean-dimension.web",
|
|
459
459
|
enabled: false,
|
|
460
460
|
});
|
|
461
461
|
|
|
@@ -464,12 +464,12 @@ describe("portal.web co-activation mirror", () => {
|
|
|
464
464
|
);
|
|
465
465
|
});
|
|
466
466
|
|
|
467
|
-
it("enables search
|
|
467
|
+
it("enables pi-lean-dimension.search when pi-lean-dimension.web changed fires with enabled: true", async () => {
|
|
468
468
|
const { pi, events } = mockSearchPi([]);
|
|
469
469
|
searchExtension(pi);
|
|
470
470
|
|
|
471
471
|
events.emit(TOOLSET_EVENTS.changed, {
|
|
472
|
-
id: "
|
|
472
|
+
id: "pi-lean-dimension.web",
|
|
473
473
|
enabled: true,
|
|
474
474
|
});
|
|
475
475
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Registers the `web-search` tool and a `/searxng-status` diagnostic command.
|
|
5
5
|
* Manages the `search` status bar slot with health-colored glyphs.
|
|
6
6
|
*
|
|
7
|
-
* Owns the `search
|
|
7
|
+
* Owns the `pi-lean-dimension.search` toolset (co-activated off `pi-lean-dimension.web`):
|
|
8
8
|
* ● searxng (accent/blue) — healthy and reachable
|
|
9
9
|
* ● searxng (warning/yellow) — server up but pipeline degraded
|
|
10
10
|
* ● searxng (error/red) — unreachable
|
|
@@ -24,9 +24,9 @@ import { webSearchTool } from "./web-search-tool.js";
|
|
|
24
24
|
// ─── Toolset spec ────────────────────────────────────────────────
|
|
25
25
|
|
|
26
26
|
const SEARCH_WEB_SPEC: ToolsetSpec = {
|
|
27
|
-
id: "search
|
|
27
|
+
id: "pi-lean-dimension.search",
|
|
28
28
|
names: new Set(["web-search"]),
|
|
29
|
-
persistKey: "toolset-state:search
|
|
29
|
+
persistKey: "toolset-state:pi-lean-dimension.search",
|
|
30
30
|
defaultEnabled: true,
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -35,7 +35,7 @@ const SEARCH_WEB_SPEC: ToolsetSpec = {
|
|
|
35
35
|
/** Cached SearXNG URL (read once at startup, stable mid-session). */
|
|
36
36
|
let _searxngUrl: string | undefined;
|
|
37
37
|
|
|
38
|
-
/** Last known search
|
|
38
|
+
/** Last known pi-lean-dimension.search enabled state (updated by library events). */
|
|
39
39
|
let _lastSearchEnabled = true;
|
|
40
40
|
|
|
41
41
|
/** Last known health state: true=healthy, false=unreachable, null=unconfigured. */
|
|
@@ -128,10 +128,10 @@ function displayUrl(url: string): string {
|
|
|
128
128
|
/**
|
|
129
129
|
* Render the `search` status slot based on toolset state + health.
|
|
130
130
|
*
|
|
131
|
-
* search
|
|
132
|
-
* search
|
|
133
|
-
* search
|
|
134
|
-
* search
|
|
131
|
+
* pi-lean-dimension.search off → ○ searxng
|
|
132
|
+
* pi-lean-dimension.search on + healthy → ● searxng (accent/blue)
|
|
133
|
+
* pi-lean-dimension.search on + degraded → ● searxng (warning/yellow)
|
|
134
|
+
* pi-lean-dimension.search on + unreachable → ● searxng (error/red)
|
|
135
135
|
* unconfigured → (clear slot)
|
|
136
136
|
*/
|
|
137
137
|
function renderSearchGlyph(ctx: {
|
|
@@ -154,13 +154,13 @@ function renderSearchGlyph(ctx: {
|
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
// search
|
|
157
|
+
// pi-lean-dimension.search disabled — show off state
|
|
158
158
|
if (!_lastSearchEnabled) {
|
|
159
159
|
safeSetStatus("○ searxng");
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
// search
|
|
163
|
+
// pi-lean-dimension.search enabled — show health-colored glyph
|
|
164
164
|
if (!_lastHealth) {
|
|
165
165
|
safeSetStatus(ctx.ui.theme.fg("error", "●") + " searxng");
|
|
166
166
|
return;
|
|
@@ -193,15 +193,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
193
193
|
// ── Register the web-search tool ─────────────────────────
|
|
194
194
|
pi.registerTool(webSearchTool);
|
|
195
195
|
|
|
196
|
-
// ── Define the search
|
|
196
|
+
// ── Define the pi-lean-dimension.search toolset ───────────
|
|
197
197
|
// Registers restore handler on session_start / session_tree.
|
|
198
198
|
const searchToolset = defineToolset(pi, SEARCH_WEB_SPEC);
|
|
199
199
|
|
|
200
|
-
// ── Co-activation: mirror
|
|
200
|
+
// ── Co-activation: mirror pi-lean-dimension.web changed events ─
|
|
201
201
|
// Listen on changed ONLY, not restored (§10.1).
|
|
202
202
|
pi.events.on(TOOLSET_EVENTS.changed, (data: unknown) => {
|
|
203
203
|
const event = data as ToolsetChangedEvent;
|
|
204
|
-
if (event.id === "
|
|
204
|
+
if (event.id === "pi-lean-dimension.web") {
|
|
205
205
|
if (event.enabled) {
|
|
206
206
|
searchToolset.enable(pi);
|
|
207
207
|
} else {
|
|
@@ -213,7 +213,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
213
213
|
// ── Keep cached state in sync with library events ────────
|
|
214
214
|
const syncSearchState = (data: unknown) => {
|
|
215
215
|
const event = data as ToolsetChangedEvent;
|
|
216
|
-
if (event.id === "search
|
|
216
|
+
if (event.id === "pi-lean-dimension.search") {
|
|
217
217
|
_lastSearchEnabled = event.enabled;
|
|
218
218
|
if (_lastCtx) renderSearchGlyph(_lastCtx);
|
|
219
219
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-lean-search",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Pi extension. SearXNG search tool for Pi — pairs with pi-lean-portal's /web toggle; search-only installs are valid, or add it to a portal install for the full web-tools suite.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-lean-dimension",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Pi extension. The full Pi web-tools suite in one install — interactive browsing (pi-lean-portal) plus SearXNG search (pi-lean-search), unified under a /web toggle that removes the tools from context when switched off.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"pi-lean-portal": "^0.3.
|
|
36
|
-
"pi-lean-search": "^0.3.
|
|
35
|
+
"pi-lean-portal": "^0.3.1",
|
|
36
|
+
"pi-lean-search": "^0.3.1"
|
|
37
37
|
},
|
|
38
38
|
"bundledDependencies": [
|
|
39
39
|
"pi-lean-portal",
|