pi-lean-dimension 0.5.0 → 0.6.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 +5 -3
- package/node_modules/pi-lean-host/AGENTS.md +13 -6
- package/node_modules/pi-lean-host/__tests__/api-learn-fetch-recipe.test.ts +282 -10
- package/node_modules/pi-lean-host/__tests__/api-learn-multi-file.test.ts +8 -16
- package/node_modules/pi-lean-host/__tests__/api-probe.test.ts +276 -279
- package/node_modules/pi-lean-host/__tests__/api-scaffold.test.ts +12 -33
- package/node_modules/pi-lean-host/__tests__/api-toggle.test.ts +14 -12
- package/node_modules/pi-lean-host/__tests__/bootstrap-command.test.ts +1 -7
- package/node_modules/pi-lean-host/__tests__/delete-command.test.ts +1 -12
- package/node_modules/pi-lean-host/__tests__/guide-catalog.test.ts +484 -0
- package/node_modules/pi-lean-host/__tests__/helpers.test.ts +0 -132
- package/node_modules/pi-lean-host/__tests__/oauth-command.test.ts +95 -0
- package/node_modules/pi-lean-host/__tests__/oauth-flow.test.ts +163 -0
- package/node_modules/pi-lean-host/__tests__/oauth-mint.test.ts +79 -6
- package/node_modules/pi-lean-host/__tests__/parse-api-guide.test.ts +4 -409
- package/node_modules/pi-lean-host/__tests__/response-spill.test.ts +0 -1
- package/node_modules/pi-lean-host/__tests__/secrets-command.test.ts +19 -35
- package/node_modules/pi-lean-host/__tests__/smoke.test.ts +1 -82
- package/node_modules/pi-lean-host/__tests__/ssrf-guard.test.ts +98 -0
- package/node_modules/pi-lean-host/__tests__/test-utils.ts +73 -0
- package/node_modules/pi-lean-host/__tests__/tools.test.ts +2 -518
- package/node_modules/pi-lean-host/__tests__/transport.test.ts +178 -31
- package/node_modules/pi-lean-host/__tests__/verify-command.test.ts +1 -8
- package/node_modules/pi-lean-host/__tests__/verify-stamp.test.ts +1 -4
- package/node_modules/pi-lean-host/api-guides/boe/local-helper.test.ts +9 -20
- package/node_modules/pi-lean-host/api-guides/dnb/error-envelope.test.ts +6 -18
- package/node_modules/pi-lean-host/api-guides/dnb/resumption-token.test.ts +6 -18
- package/node_modules/pi-lean-host/api-guides/frost-sensorthings/dotted-key.test.ts +6 -18
- package/node_modules/pi-lean-host/api-guides/github/static-key.test.ts +7 -25
- package/node_modules/pi-lean-host/api-guides/inaturalist/derived-id.test.ts +6 -18
- package/node_modules/pi-lean-host/api-guides/internet-archive/multi-recipe.test.ts +6 -26
- package/node_modules/pi-lean-host/api-guides/stripe/has-more.test.ts +6 -18
- package/node_modules/pi-lean-host/api-guides/telegram-bot/path-auth.test.ts +7 -25
- package/node_modules/pi-lean-host/api-guides/twitch/oauth2.test.ts +12 -47
- package/node_modules/pi-lean-host/api-guides/twitch-user/oauth-user.test.ts +11 -52
- package/node_modules/pi-lean-host/api-guides/usgs/transform.test.ts +10 -27
- package/node_modules/pi-lean-host/api-guides/wikidata-search/numeric-cursor.test.ts +6 -18
- package/node_modules/pi-lean-host/api-guides/wikimedia-action/token-bag.test.ts +9 -20
- package/node_modules/pi-lean-host/core/auth.ts +2 -1
- package/node_modules/pi-lean-host/core/helpers.ts +29 -35
- package/node_modules/pi-lean-host/core/oauth-command.ts +10 -8
- package/node_modules/pi-lean-host/core/oauth-flow.ts +20 -4
- package/node_modules/pi-lean-host/core/parse-api-guide.ts +3 -5
- package/node_modules/pi-lean-host/core/transport.ts +1 -1
- package/node_modules/pi-lean-host/package.json +1 -1
- package/node_modules/pi-lean-host/tools/api-guide.ts +18 -57
- package/node_modules/pi-lean-host/tools/api-learn.ts +20 -49
- package/node_modules/pi-lean-host/tools/api-probe.ts +17 -26
- package/node_modules/pi-lean-host/tools/api-scaffold.ts +20 -42
- package/node_modules/pi-lean-host/tools/utils.ts +69 -0
- package/node_modules/pi-lean-portal/AGENTS.md +4 -3
- package/node_modules/pi-lean-portal/README.md +9 -9
- package/node_modules/pi-lean-portal/__tests__/accessibility-tree.test.ts +0 -15
- package/node_modules/pi-lean-portal/__tests__/browser-install.test.ts +737 -0
- package/node_modules/pi-lean-portal/__tests__/browser-navigate.test.ts +33 -2
- package/node_modules/pi-lean-portal/__tests__/browser-status.test.ts +48 -25
- package/node_modules/pi-lean-portal/__tests__/browser-toggle-profile.test.ts +3 -9
- package/node_modules/pi-lean-portal/__tests__/browser-toggle.test.ts +3 -29
- package/node_modules/pi-lean-portal/__tests__/fetch-backend.test.ts +51 -0
- package/node_modules/pi-lean-portal/__tests__/helpers/__pycache__/mock-python-bridge.cpython-313-pytest-9.1.1.pyc +0 -0
- package/node_modules/pi-lean-portal/__tests__/helpers/__pycache__/mock-python-bridge.cpython-313.pyc +0 -0
- package/node_modules/pi-lean-portal/__tests__/helpers/mock-pi.ts +34 -0
- package/node_modules/pi-lean-portal/__tests__/helpers/mock-python-bridge.py +14 -24
- package/node_modules/pi-lean-portal/__tests__/plugin-registry.test.ts +0 -90
- package/node_modules/pi-lean-portal/__tests__/python-adapter.test.ts +32 -125
- package/node_modules/pi-lean-portal/__tests__/router-dispatch.test.ts +12 -170
- package/node_modules/pi-lean-portal/__tests__/router-session.test.ts +39 -151
- package/node_modules/pi-lean-portal/__tests__/web-guides.test.ts +1 -44
- package/node_modules/pi-lean-portal/backends/chromium/index.ts +1 -1
- package/node_modules/pi-lean-portal/backends/firefox/index.ts +1 -1
- package/node_modules/pi-lean-portal/backends/playwright-base/playwright-plugin.ts +1 -1
- package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/playwright_base.cpython-312.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/playwright_base.cpython-313.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/transport.cpython-312.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/transport.cpython-313.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/playwright_base.py +43 -57
- package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/transport.py +6 -21
- package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_accessibility.cpython-313-pytest-9.1.1.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_playwright_base_quirks.cpython-313-pytest-9.1.1.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_playwright_base_quirks.cpython-313.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_transport.cpython-313-pytest-9.1.1.pyc +0 -0
- package/node_modules/pi-lean-portal/backends/python-base/tests/test_playwright_base_quirks.py +157 -73
- package/node_modules/pi-lean-portal/backends/python-base/tests/test_transport.py +15 -41
- package/node_modules/pi-lean-portal/browser-install.ts +454 -0
- package/node_modules/pi-lean-portal/browser-status.ts +21 -0
- package/node_modules/pi-lean-portal/browser-toggle.ts +13 -11
- package/node_modules/pi-lean-portal/core/fetch-backend.ts +2 -2
- package/node_modules/pi-lean-portal/core/router.ts +7 -32
- package/node_modules/pi-lean-portal/core/shared/session-manager.ts +1 -3
- package/node_modules/pi-lean-portal/index.ts +1 -18
- package/node_modules/pi-lean-portal/package.json +2 -1
- package/node_modules/pi-lean-portal/tools/browser-navigate.ts +6 -2
- package/node_modules/pi-lean-portal/tools/utils.ts +5 -6
- package/node_modules/pi-lean-search/AGENTS.md +5 -3
- package/node_modules/pi-lean-search/__tests__/web-search.test.ts +180 -127
- package/node_modules/pi-lean-search/index.ts +0 -3
- package/node_modules/pi-lean-search/package.json +1 -1
- package/node_modules/pi-lean-search/web-search-tool.ts +22 -13
- package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/yaml/dist/nodes/Alias.js +25 -23
- package/node_modules/yaml/package.json +1 -1
- package/package.json +4 -4
|
@@ -58,7 +58,7 @@ afterAll(() => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
/** Stage a guide's recipe into the guides dir (dirName = slug(shortName)). */
|
|
61
|
-
function writeGuide(shortName: string,
|
|
61
|
+
function writeGuide(shortName: string, recipe: string): void {
|
|
62
62
|
const dirName = slug(shortName);
|
|
63
63
|
mkdirSync(join(tmpGuidesDir, dirName), { recursive: true });
|
|
64
64
|
writeFileSync(join(tmpGuidesDir, dirName, "guide.md"), recipe, "utf-8");
|
|
@@ -192,7 +192,7 @@ describe("api-scaffold", () => {
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
it("neither verify nor helper → validation error, no /tmp write", async () => {
|
|
195
|
-
writeGuide("Scaff",
|
|
195
|
+
writeGuide("Scaff", mixedRecipe("scaff.example", "Scaff"));
|
|
196
196
|
const res = await callScaffold({ domain: "scaff.example" });
|
|
197
197
|
const text = contentText(res);
|
|
198
198
|
expect(res.details).toMatchObject({ error: "nothing_to_scaffold" });
|
|
@@ -202,11 +202,7 @@ describe("api-scaffold", () => {
|
|
|
202
202
|
});
|
|
203
203
|
|
|
204
204
|
it("helper: true → commented-out stub written to the staged dir", async () => {
|
|
205
|
-
writeGuide(
|
|
206
|
-
"Helper",
|
|
207
|
-
"helper.example",
|
|
208
|
-
tokenRecipe("helper.example", "Helper", "getHelper"),
|
|
209
|
-
);
|
|
205
|
+
writeGuide("Helper", tokenRecipe("helper.example", "Helper", "getHelper"));
|
|
210
206
|
const res = await callScaffold({ domain: "helper.example", helper: true });
|
|
211
207
|
const text = contentText(res);
|
|
212
208
|
expect(res.details).toMatchObject({
|
|
@@ -224,7 +220,7 @@ describe("api-scaffold", () => {
|
|
|
224
220
|
});
|
|
225
221
|
|
|
226
222
|
it("verify: true → sentinels for path token, required-no-default query, and every requiresAnyOf member; runnable op excluded", async () => {
|
|
227
|
-
writeGuide("Scaff",
|
|
223
|
+
writeGuide("Scaff", mixedRecipe("scaff.example", "Scaff"));
|
|
228
224
|
const res = await callScaffold({ domain: "scaff.example", verify: true });
|
|
229
225
|
expect(res.details).toMatchObject({
|
|
230
226
|
mode: "verify",
|
|
@@ -253,7 +249,7 @@ describe("api-scaffold", () => {
|
|
|
253
249
|
});
|
|
254
250
|
|
|
255
251
|
it("verify additive merge → existing real values preserved, new sentinels added", async () => {
|
|
256
|
-
writeGuide("Merge",
|
|
252
|
+
writeGuide("Merge", mixedRecipe("merge.example", "Merge"));
|
|
257
253
|
// Pre-seed a guides-dir verify.json with real values for two already-
|
|
258
254
|
// satisfied params; the rest are still unsatisfiable.
|
|
259
255
|
writeFileSync(
|
|
@@ -281,7 +277,6 @@ describe("api-scaffold", () => {
|
|
|
281
277
|
it("no unsatisfiable params → empty verify.json scaffold", async () => {
|
|
282
278
|
writeGuide(
|
|
283
279
|
"Runnable",
|
|
284
|
-
"runnable.example",
|
|
285
280
|
`---
|
|
286
281
|
schemaVersion: 1
|
|
287
282
|
kind: api
|
|
@@ -313,7 +308,7 @@ operations:
|
|
|
313
308
|
});
|
|
314
309
|
|
|
315
310
|
it("refuse-to-overwrite → existing staged verify.json errors, names delete-then-re-call", async () => {
|
|
316
|
-
writeGuide("Ov",
|
|
311
|
+
writeGuide("Ov", tokenRecipe("ov.example", "Ov", "getOv"));
|
|
317
312
|
// Pre-stage a verify.json (simulating a prior scaffold).
|
|
318
313
|
mkdirSync(stagedDir("ov"), { recursive: true });
|
|
319
314
|
writeFileSync(
|
|
@@ -337,7 +332,7 @@ operations:
|
|
|
337
332
|
});
|
|
338
333
|
|
|
339
334
|
it("refuse-to-overwrite also gates helper.ts", async () => {
|
|
340
|
-
writeGuide("Hov",
|
|
335
|
+
writeGuide("Hov", tokenRecipe("hov.example", "Hov", "getHov"));
|
|
341
336
|
mkdirSync(stagedDir("hov"), { recursive: true });
|
|
342
337
|
writeFileSync(join(stagedDir("hov"), "helper.ts"), "// existing\n", "utf-8");
|
|
343
338
|
const res = await callScaffold({ domain: "hov.example", helper: true });
|
|
@@ -349,11 +344,7 @@ operations:
|
|
|
349
344
|
});
|
|
350
345
|
|
|
351
346
|
it("both verify + helper true → both files written to one staged dir, dirName surfaced", async () => {
|
|
352
|
-
writeGuide(
|
|
353
|
-
"Both",
|
|
354
|
-
"both.example",
|
|
355
|
-
tokenRecipe("both.example", "Both", "getBoth"),
|
|
356
|
-
);
|
|
347
|
+
writeGuide("Both", tokenRecipe("both.example", "Both", "getBoth"));
|
|
357
348
|
const res = await callScaffold({
|
|
358
349
|
domain: "both.example",
|
|
359
350
|
verify: true,
|
|
@@ -375,16 +366,8 @@ operations:
|
|
|
375
366
|
});
|
|
376
367
|
|
|
377
368
|
it("N-guide domain → menu without selector; guide selector scaffolds the selected one", async () => {
|
|
378
|
-
writeGuide(
|
|
379
|
-
|
|
380
|
-
"multi.example",
|
|
381
|
-
tokenRecipe("multi.example", "First", "getFirst"),
|
|
382
|
-
);
|
|
383
|
-
writeGuide(
|
|
384
|
-
"Second",
|
|
385
|
-
"multi.example",
|
|
386
|
-
tokenRecipe("multi.example", "Second", "getSecond"),
|
|
387
|
-
);
|
|
369
|
+
writeGuide("First", tokenRecipe("multi.example", "First", "getFirst"));
|
|
370
|
+
writeGuide("Second", tokenRecipe("multi.example", "Second", "getSecond"));
|
|
388
371
|
|
|
389
372
|
const menu = await callScaffold({ domain: "multi.example", verify: true });
|
|
390
373
|
const menuText = contentText(menu);
|
|
@@ -411,11 +394,7 @@ operations:
|
|
|
411
394
|
});
|
|
412
395
|
|
|
413
396
|
it("malformed guides-dir verify.json → clear error, no /tmp write", async () => {
|
|
414
|
-
writeGuide(
|
|
415
|
-
"Badmerge",
|
|
416
|
-
"badmerge.example",
|
|
417
|
-
tokenRecipe("badmerge.example", "Badmerge", "getBad"),
|
|
418
|
-
);
|
|
397
|
+
writeGuide("Badmerge", tokenRecipe("badmerge.example", "Badmerge", "getBad"));
|
|
419
398
|
writeFileSync(
|
|
420
399
|
join(tmpGuidesDir, "badmerge", "verify.json"),
|
|
421
400
|
"{ not valid json",
|
|
@@ -519,7 +498,7 @@ operations:
|
|
|
519
498
|
description: item id
|
|
520
499
|
---
|
|
521
500
|
`;
|
|
522
|
-
writeGuide("PathKey",
|
|
501
|
+
writeGuide("PathKey", recipe);
|
|
523
502
|
const res = await callScaffold({ domain: "path.example", verify: true });
|
|
524
503
|
expect(res.details).toMatchObject({ mode: "verify", dirName: "pathkey" });
|
|
525
504
|
const merged = JSON.parse(
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
ExtensionContext,
|
|
14
14
|
} from "@earendil-works/pi-coding-agent";
|
|
15
15
|
import { TOOLSET_EVENTS } from "pi-tool-masking";
|
|
16
|
+
import { captureApiHandler } from "./test-utils.js";
|
|
16
17
|
import initApiToggle, {
|
|
17
18
|
getApiToggleState,
|
|
18
19
|
_getApiLearnStateForTest,
|
|
@@ -78,7 +79,10 @@ interface MockPi {
|
|
|
78
79
|
function mockPi(initialTools?: string[]): MockPi {
|
|
79
80
|
let active = initialTools ?? ALL_TOOLS.map((t) => t.name);
|
|
80
81
|
const eventEmitter = new EventEmitter();
|
|
81
|
-
const handlers = new Map<
|
|
82
|
+
const handlers = new Map<
|
|
83
|
+
string,
|
|
84
|
+
Array<(...args: any[]) => void | Promise<void>>
|
|
85
|
+
>();
|
|
82
86
|
|
|
83
87
|
const pi = {
|
|
84
88
|
getAllTools: vi.fn(() => ALL_TOOLS as any),
|
|
@@ -89,10 +93,15 @@ function mockPi(initialTools?: string[]): MockPi {
|
|
|
89
93
|
appendEntry: vi.fn(),
|
|
90
94
|
registerCommand: vi.fn(),
|
|
91
95
|
registerTool: vi.fn(),
|
|
92
|
-
on: vi.fn(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
on: vi.fn(
|
|
97
|
+
<T>(
|
|
98
|
+
event: string,
|
|
99
|
+
handler: (event: T, ctx: any) => void | Promise<void>,
|
|
100
|
+
) => {
|
|
101
|
+
if (!handlers.has(event)) handlers.set(event, []);
|
|
102
|
+
handlers.get(event)!.push(handler as any);
|
|
103
|
+
},
|
|
104
|
+
),
|
|
96
105
|
get events() {
|
|
97
106
|
return {
|
|
98
107
|
emit: (channel: string, data: unknown) => eventEmitter.emit(channel, data),
|
|
@@ -124,13 +133,6 @@ function mockCtx(overrides: Partial<ExtensionContext> = {}): any {
|
|
|
124
133
|
};
|
|
125
134
|
}
|
|
126
135
|
|
|
127
|
-
/** Capture the /api command handler from registerCommand. */
|
|
128
|
-
function captureApiHandler(
|
|
129
|
-
pi: ExtensionAPI,
|
|
130
|
-
): (args: string, ctx: any) => Promise<void> {
|
|
131
|
-
return (pi.registerCommand as any).mock.calls[0][1].handler;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
136
|
// ==================================================================
|
|
135
137
|
// Default export
|
|
136
138
|
// ==================================================================
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
writeSecret,
|
|
25
25
|
} from "../core/secrets-store.js";
|
|
26
26
|
import initApiToggle, { _resetToggleStateForTest } from "../core/api-toggle.js";
|
|
27
|
+
import { captureApiHandler } from "./test-utils.js";
|
|
27
28
|
|
|
28
29
|
// Clean globalThis registry between test files (same as api-toggle.test.ts).
|
|
29
30
|
const REGISTRY_KEY = "__piToolMaskingRegistry";
|
|
@@ -122,13 +123,6 @@ function mockCtx(overrides: Partial<ExtensionContext> = {}): any {
|
|
|
122
123
|
};
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
function captureApiHandler(pi: ExtensionAPI) {
|
|
126
|
-
return (pi.registerCommand as any).mock.calls[0][1].handler as (
|
|
127
|
-
args: string,
|
|
128
|
-
ctx: any,
|
|
129
|
-
) => Promise<void>;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
126
|
async function runBootstrap(
|
|
133
127
|
args: string,
|
|
134
128
|
initialTools?: string[],
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
_resetLoadWarningsForTest,
|
|
32
32
|
} from "../core/guide-store.js";
|
|
33
33
|
import { handleDeleteSubcommand } from "../core/delete-command.js";
|
|
34
|
+
import { mockCtx, notifyText } from "./test-utils.js";
|
|
34
35
|
|
|
35
36
|
// ═══════════════════════════════════════════════════════════════════
|
|
36
37
|
// Fixtures
|
|
@@ -76,18 +77,6 @@ function setupGuide(dirName: string, recipeText: string): void {
|
|
|
76
77
|
invalidateCache();
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
function mockCtx(overrides: Record<string, unknown> = {}): any {
|
|
80
|
-
return {
|
|
81
|
-
ui: { notify: vi.fn(), confirm: vi.fn(() => true) },
|
|
82
|
-
hasUI: true,
|
|
83
|
-
...overrides,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function notifyText(ctx: any): string {
|
|
88
|
-
return ctx.ui.notify.mock.calls.map((c: unknown[]) => c[0]).join("\n");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
80
|
// ═══════════════════════════════════════════════════════════════════
|
|
92
81
|
// Load-time warning suppression (once per process)
|
|
93
82
|
// ═══════════════════════════════════════════════════════════════════
|