pi-browser-harness 0.12.0 → 0.14.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 (102) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +132 -0
  3. package/package.json +15 -7
  4. package/skills/pi-browser-harness/SKILL.md +89 -2
  5. package/src/cdp/commands.ts +205 -14
  6. package/src/cdp/console-buffer.ts +37 -23
  7. package/src/cdp/discovery.ts +57 -25
  8. package/src/cdp/events.ts +9 -3
  9. package/src/cdp/network-buffer.ts +38 -32
  10. package/src/cdp/ownership.ts +22 -4
  11. package/src/cdp/record-store.ts +2 -2
  12. package/src/cdp/session.ts +358 -216
  13. package/src/cdp/target-factory.ts +34 -15
  14. package/src/cdp/types.ts +17 -1
  15. package/src/client.ts +127 -54
  16. package/src/daemon/bridge.ts +110 -349
  17. package/src/daemon/connection.ts +323 -0
  18. package/src/daemon/index.ts +77 -48
  19. package/src/daemon/lines.ts +40 -0
  20. package/src/daemon/main.ts +12 -0
  21. package/src/daemon/protocol.ts +55 -25
  22. package/src/daemon/server.ts +100 -63
  23. package/src/daemon/socket.ts +10 -0
  24. package/src/daemon/spawn.ts +21 -22
  25. package/src/daemon/transport.ts +80 -49
  26. package/src/domains/ax-tree.ts +27 -8
  27. package/src/domains/cdp-call.ts +14 -7
  28. package/src/domains/click.ts +2 -2
  29. package/src/domains/concurrency.ts +50 -0
  30. package/src/domains/console.ts +20 -64
  31. package/src/domains/drag.ts +26 -28
  32. package/src/domains/element-call.ts +102 -68
  33. package/src/domains/files.ts +13 -9
  34. package/src/domains/form-batch.ts +13 -10
  35. package/src/domains/form.ts +78 -107
  36. package/src/domains/headers.ts +2 -2
  37. package/src/domains/history.ts +4 -4
  38. package/src/domains/io.ts +35 -0
  39. package/src/domains/isolated-tab.ts +6 -12
  40. package/src/domains/js.ts +67 -46
  41. package/src/domains/keyboard.ts +14 -11
  42. package/src/domains/navigate.ts +102 -66
  43. package/src/domains/network.ts +55 -95
  44. package/src/domains/page/fill.page.ts +139 -0
  45. package/src/domains/page/form.page.ts +61 -0
  46. package/src/domains/page/inject.ts +37 -0
  47. package/src/domains/page/keyboard.page.ts +16 -0
  48. package/src/domains/page/live-value.page.ts +10 -0
  49. package/src/domains/page/read-page.page.ts +51 -0
  50. package/src/domains/page/recipe.page.ts +82 -0
  51. package/src/domains/page/serp.page.ts +42 -0
  52. package/src/domains/page.ts +18 -51
  53. package/src/domains/poll.ts +42 -0
  54. package/src/domains/readpage/read-page.ts +48 -53
  55. package/src/domains/ref-resolve.ts +43 -29
  56. package/src/domains/ref-signature.ts +11 -0
  57. package/src/domains/render.ts +12 -23
  58. package/src/domains/screenshot-capture.ts +4 -2
  59. package/src/domains/screenshot.ts +13 -10
  60. package/src/domains/scroll.ts +4 -4
  61. package/src/domains/search/google-serp.ts +78 -8
  62. package/src/domains/search/redirect-resolver.ts +41 -0
  63. package/src/domains/search/web-search.ts +103 -40
  64. package/src/domains/snapshot.ts +81 -78
  65. package/src/domains/tab-resolve.ts +36 -0
  66. package/src/domains/tabs.ts +18 -69
  67. package/src/domains/target.ts +1 -1
  68. package/src/index.ts +101 -33
  69. package/src/profile/bind.ts +45 -14
  70. package/src/profile/browser-process.ts +50 -12
  71. package/src/profile/command.ts +20 -12
  72. package/src/profile/launch.ts +13 -9
  73. package/src/profile/list.ts +9 -13
  74. package/src/profile/store.ts +2 -1
  75. package/src/prompt.ts +34 -8
  76. package/src/recipes/command.ts +96 -0
  77. package/src/recipes/compile.ts +198 -0
  78. package/src/recipes/find.ts +49 -0
  79. package/src/recipes/journal.ts +125 -0
  80. package/src/recipes/recipe.ts +215 -0
  81. package/src/recipes/recordable.ts +359 -0
  82. package/src/recipes/replay.ts +354 -0
  83. package/src/recipes/run-tool.ts +132 -0
  84. package/src/recipes/save-tool.ts +247 -0
  85. package/src/recipes/store.ts +103 -0
  86. package/src/recipes/trust.ts +172 -0
  87. package/src/registry.ts +69 -4
  88. package/src/schemas/parse.ts +2 -2
  89. package/src/setup.ts +28 -19
  90. package/src/state.ts +2 -1
  91. package/src/util/debug.ts +7 -1
  92. package/src/util/guards.ts +3 -0
  93. package/src/util/js-source.ts +28 -0
  94. package/src/util/mutex.ts +1 -1
  95. package/src/util/paths.ts +3 -2
  96. package/src/util/result.ts +8 -0
  97. package/src/util/sharp-shim.ts +18 -11
  98. package/src/util/sleep.ts +18 -0
  99. package/src/util/tool.ts +185 -114
  100. package/src/util/truncate.ts +1 -1
  101. package/tsconfig.json +2 -1
  102. package/src/domains/fill-engine.ts +0 -80
@@ -8,7 +8,8 @@ export type OwnershipRegistry = {
8
8
  harnessWindow(): string | undefined;
9
9
  setHarnessWindowId(windowId: number | undefined): void;
10
10
  harnessWindowId(): number | undefined;
11
- onChange(cb: () => void): void;
11
+ // Subscribe; the returned function unsubscribes. Several subscribers may be registered at once.
12
+ onChange(cb: () => void): () => void;
12
13
  };
13
14
 
14
15
  export const createOwnershipRegistry = (
@@ -21,10 +22,11 @@ export const createOwnershipRegistry = (
21
22
  const owned = new Set<string>(initial?.ownedTargetIds ?? []);
22
23
  let harnessWindow: string | undefined = initial?.harnessWindowTargetId;
23
24
  let harnessWindowId: number | undefined = initial?.harnessWindowId;
24
- let listener: (() => void) | null = null;
25
+ const listeners = new Set<() => void>();
25
26
 
26
27
  const notify = (): void => {
27
- if (listener) listener();
28
+ // Snapshot so a listener that unsubscribes (or subscribes) mid-notify does not disturb the iteration.
29
+ for (const cb of [...listeners]) cb();
28
30
  };
29
31
 
30
32
  return {
@@ -67,7 +69,23 @@ export const createOwnershipRegistry = (
67
69
  return harnessWindowId;
68
70
  },
69
71
  onChange(cb) {
70
- listener = cb;
72
+ listeners.add(cb);
73
+ return () => {
74
+ listeners.delete(cb);
75
+ };
71
76
  },
72
77
  };
73
78
  };
79
+
80
+ // Drops owned targets (and the harness window) that no longer exist in the browser. Returns the owned ids that survived.
81
+ export const reconcileOwnership = (
82
+ ownership: OwnershipRegistry,
83
+ liveTargetIds: ReadonlySet<string>,
84
+ ): ReadonlyArray<string> => {
85
+ const owned = ownership.list();
86
+ const survivors = owned.filter((id) => liveTargetIds.has(id));
87
+ if (survivors.length !== owned.length) ownership.replaceAll(survivors);
88
+ const hw = ownership.harnessWindow();
89
+ if (hw !== undefined && !liveTargetIds.has(hw)) ownership.setHarnessWindow(undefined);
90
+ return survivors;
91
+ };
@@ -1,5 +1,5 @@
1
1
  export type DrainPage<T> = {
2
- readonly records: T[];
2
+ readonly records: ReadonlyArray<T>;
3
3
  readonly total: number;
4
4
  readonly bufferOverflowed: boolean;
5
5
  };
@@ -10,7 +10,7 @@ export type RecordStore<K, T> = {
10
10
  delete(key: K): void;
11
11
  values(): IterableIterator<T>;
12
12
  // Takes the overflow flag as it pages, so each drain reports only the loss since the previous one.
13
- page(matched: T[], limit: number | undefined): DrainPage<T>;
13
+ page(matched: ReadonlyArray<T>, limit: number | undefined): DrainPage<T>;
14
14
  clear(): void;
15
15
  };
16
16