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.
Files changed (104) hide show
  1. package/README.md +5 -3
  2. package/node_modules/pi-lean-host/AGENTS.md +13 -6
  3. package/node_modules/pi-lean-host/__tests__/api-learn-fetch-recipe.test.ts +282 -10
  4. package/node_modules/pi-lean-host/__tests__/api-learn-multi-file.test.ts +8 -16
  5. package/node_modules/pi-lean-host/__tests__/api-probe.test.ts +276 -279
  6. package/node_modules/pi-lean-host/__tests__/api-scaffold.test.ts +12 -33
  7. package/node_modules/pi-lean-host/__tests__/api-toggle.test.ts +14 -12
  8. package/node_modules/pi-lean-host/__tests__/bootstrap-command.test.ts +1 -7
  9. package/node_modules/pi-lean-host/__tests__/delete-command.test.ts +1 -12
  10. package/node_modules/pi-lean-host/__tests__/guide-catalog.test.ts +484 -0
  11. package/node_modules/pi-lean-host/__tests__/helpers.test.ts +0 -132
  12. package/node_modules/pi-lean-host/__tests__/oauth-command.test.ts +95 -0
  13. package/node_modules/pi-lean-host/__tests__/oauth-flow.test.ts +163 -0
  14. package/node_modules/pi-lean-host/__tests__/oauth-mint.test.ts +79 -6
  15. package/node_modules/pi-lean-host/__tests__/parse-api-guide.test.ts +4 -409
  16. package/node_modules/pi-lean-host/__tests__/response-spill.test.ts +0 -1
  17. package/node_modules/pi-lean-host/__tests__/secrets-command.test.ts +19 -35
  18. package/node_modules/pi-lean-host/__tests__/smoke.test.ts +1 -82
  19. package/node_modules/pi-lean-host/__tests__/ssrf-guard.test.ts +98 -0
  20. package/node_modules/pi-lean-host/__tests__/test-utils.ts +73 -0
  21. package/node_modules/pi-lean-host/__tests__/tools.test.ts +2 -518
  22. package/node_modules/pi-lean-host/__tests__/transport.test.ts +178 -31
  23. package/node_modules/pi-lean-host/__tests__/verify-command.test.ts +1 -8
  24. package/node_modules/pi-lean-host/__tests__/verify-stamp.test.ts +1 -4
  25. package/node_modules/pi-lean-host/api-guides/boe/local-helper.test.ts +9 -20
  26. package/node_modules/pi-lean-host/api-guides/dnb/error-envelope.test.ts +6 -18
  27. package/node_modules/pi-lean-host/api-guides/dnb/resumption-token.test.ts +6 -18
  28. package/node_modules/pi-lean-host/api-guides/frost-sensorthings/dotted-key.test.ts +6 -18
  29. package/node_modules/pi-lean-host/api-guides/github/static-key.test.ts +7 -25
  30. package/node_modules/pi-lean-host/api-guides/inaturalist/derived-id.test.ts +6 -18
  31. package/node_modules/pi-lean-host/api-guides/internet-archive/multi-recipe.test.ts +6 -26
  32. package/node_modules/pi-lean-host/api-guides/stripe/has-more.test.ts +6 -18
  33. package/node_modules/pi-lean-host/api-guides/telegram-bot/path-auth.test.ts +7 -25
  34. package/node_modules/pi-lean-host/api-guides/twitch/oauth2.test.ts +12 -47
  35. package/node_modules/pi-lean-host/api-guides/twitch-user/oauth-user.test.ts +11 -52
  36. package/node_modules/pi-lean-host/api-guides/usgs/transform.test.ts +10 -27
  37. package/node_modules/pi-lean-host/api-guides/wikidata-search/numeric-cursor.test.ts +6 -18
  38. package/node_modules/pi-lean-host/api-guides/wikimedia-action/token-bag.test.ts +9 -20
  39. package/node_modules/pi-lean-host/core/auth.ts +2 -1
  40. package/node_modules/pi-lean-host/core/helpers.ts +29 -35
  41. package/node_modules/pi-lean-host/core/oauth-command.ts +10 -8
  42. package/node_modules/pi-lean-host/core/oauth-flow.ts +20 -4
  43. package/node_modules/pi-lean-host/core/parse-api-guide.ts +3 -5
  44. package/node_modules/pi-lean-host/core/transport.ts +1 -1
  45. package/node_modules/pi-lean-host/package.json +1 -1
  46. package/node_modules/pi-lean-host/tools/api-guide.ts +18 -57
  47. package/node_modules/pi-lean-host/tools/api-learn.ts +20 -49
  48. package/node_modules/pi-lean-host/tools/api-probe.ts +17 -26
  49. package/node_modules/pi-lean-host/tools/api-scaffold.ts +20 -42
  50. package/node_modules/pi-lean-host/tools/utils.ts +69 -0
  51. package/node_modules/pi-lean-portal/AGENTS.md +4 -3
  52. package/node_modules/pi-lean-portal/README.md +9 -9
  53. package/node_modules/pi-lean-portal/__tests__/accessibility-tree.test.ts +0 -15
  54. package/node_modules/pi-lean-portal/__tests__/browser-install.test.ts +737 -0
  55. package/node_modules/pi-lean-portal/__tests__/browser-navigate.test.ts +33 -2
  56. package/node_modules/pi-lean-portal/__tests__/browser-status.test.ts +48 -25
  57. package/node_modules/pi-lean-portal/__tests__/browser-toggle-profile.test.ts +3 -9
  58. package/node_modules/pi-lean-portal/__tests__/browser-toggle.test.ts +3 -29
  59. package/node_modules/pi-lean-portal/__tests__/fetch-backend.test.ts +51 -0
  60. package/node_modules/pi-lean-portal/__tests__/helpers/__pycache__/mock-python-bridge.cpython-313-pytest-9.1.1.pyc +0 -0
  61. package/node_modules/pi-lean-portal/__tests__/helpers/__pycache__/mock-python-bridge.cpython-313.pyc +0 -0
  62. package/node_modules/pi-lean-portal/__tests__/helpers/mock-pi.ts +34 -0
  63. package/node_modules/pi-lean-portal/__tests__/helpers/mock-python-bridge.py +14 -24
  64. package/node_modules/pi-lean-portal/__tests__/plugin-registry.test.ts +0 -90
  65. package/node_modules/pi-lean-portal/__tests__/python-adapter.test.ts +32 -125
  66. package/node_modules/pi-lean-portal/__tests__/router-dispatch.test.ts +12 -170
  67. package/node_modules/pi-lean-portal/__tests__/router-session.test.ts +39 -151
  68. package/node_modules/pi-lean-portal/__tests__/web-guides.test.ts +1 -44
  69. package/node_modules/pi-lean-portal/backends/chromium/index.ts +1 -1
  70. package/node_modules/pi-lean-portal/backends/firefox/index.ts +1 -1
  71. package/node_modules/pi-lean-portal/backends/playwright-base/playwright-plugin.ts +1 -1
  72. package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/playwright_base.cpython-312.pyc +0 -0
  73. package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/playwright_base.cpython-313.pyc +0 -0
  74. package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/transport.cpython-312.pyc +0 -0
  75. package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/__pycache__/transport.cpython-313.pyc +0 -0
  76. package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/playwright_base.py +43 -57
  77. package/node_modules/pi-lean-portal/backends/python-base/pi_browser_bridge/transport.py +6 -21
  78. package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_accessibility.cpython-313-pytest-9.1.1.pyc +0 -0
  79. package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_playwright_base_quirks.cpython-313-pytest-9.1.1.pyc +0 -0
  80. package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_playwright_base_quirks.cpython-313.pyc +0 -0
  81. package/node_modules/pi-lean-portal/backends/python-base/tests/__pycache__/test_transport.cpython-313-pytest-9.1.1.pyc +0 -0
  82. package/node_modules/pi-lean-portal/backends/python-base/tests/test_playwright_base_quirks.py +157 -73
  83. package/node_modules/pi-lean-portal/backends/python-base/tests/test_transport.py +15 -41
  84. package/node_modules/pi-lean-portal/browser-install.ts +454 -0
  85. package/node_modules/pi-lean-portal/browser-status.ts +21 -0
  86. package/node_modules/pi-lean-portal/browser-toggle.ts +13 -11
  87. package/node_modules/pi-lean-portal/core/fetch-backend.ts +2 -2
  88. package/node_modules/pi-lean-portal/core/router.ts +7 -32
  89. package/node_modules/pi-lean-portal/core/shared/session-manager.ts +1 -3
  90. package/node_modules/pi-lean-portal/index.ts +1 -18
  91. package/node_modules/pi-lean-portal/package.json +2 -1
  92. package/node_modules/pi-lean-portal/tools/browser-navigate.ts +6 -2
  93. package/node_modules/pi-lean-portal/tools/utils.ts +5 -6
  94. package/node_modules/pi-lean-search/AGENTS.md +5 -3
  95. package/node_modules/pi-lean-search/__tests__/web-search.test.ts +180 -127
  96. package/node_modules/pi-lean-search/index.ts +0 -3
  97. package/node_modules/pi-lean-search/package.json +1 -1
  98. package/node_modules/pi-lean-search/web-search-tool.ts +22 -13
  99. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
  100. package/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
  101. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
  102. package/node_modules/yaml/dist/nodes/Alias.js +25 -23
  103. package/node_modules/yaml/package.json +1 -1
  104. 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, domain: string, recipe: string): void {
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", "scaff.example", mixedRecipe("scaff.example", "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", "scaff.example", mixedRecipe("scaff.example", "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", "merge.example", mixedRecipe("merge.example", "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", "ov.example", tokenRecipe("ov.example", "Ov", "getOv"));
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", "hov.example", tokenRecipe("hov.example", "Hov", "getHov"));
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
- "First",
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", "path.example", recipe);
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<string, Array<(...args: any[]) => void>>();
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(<T>(event: string, handler: (event: T, ctx: any) => void) => {
93
- if (!handlers.has(event)) handlers.set(event, []);
94
- handlers.get(event)!.push(handler as any);
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
  // ═══════════════════════════════════════════════════════════════════