@predicatelabs/sdk 0.99.9

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 (302) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +252 -0
  3. package/dist/actions.d.ts +185 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +1120 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/agent-runtime.d.ts +352 -0
  8. package/dist/agent-runtime.d.ts.map +1 -0
  9. package/dist/agent-runtime.js +1170 -0
  10. package/dist/agent-runtime.js.map +1 -0
  11. package/dist/agent.d.ts +164 -0
  12. package/dist/agent.d.ts.map +1 -0
  13. package/dist/agent.js +408 -0
  14. package/dist/agent.js.map +1 -0
  15. package/dist/asserts/expect.d.ts +159 -0
  16. package/dist/asserts/expect.d.ts.map +1 -0
  17. package/dist/asserts/expect.js +547 -0
  18. package/dist/asserts/expect.js.map +1 -0
  19. package/dist/asserts/index.d.ts +58 -0
  20. package/dist/asserts/index.d.ts.map +1 -0
  21. package/dist/asserts/index.js +70 -0
  22. package/dist/asserts/index.js.map +1 -0
  23. package/dist/asserts/query.d.ts +199 -0
  24. package/dist/asserts/query.d.ts.map +1 -0
  25. package/dist/asserts/query.js +288 -0
  26. package/dist/asserts/query.js.map +1 -0
  27. package/dist/backends/actions.d.ts +119 -0
  28. package/dist/backends/actions.d.ts.map +1 -0
  29. package/dist/backends/actions.js +291 -0
  30. package/dist/backends/actions.js.map +1 -0
  31. package/dist/backends/browser-use-adapter.d.ts +131 -0
  32. package/dist/backends/browser-use-adapter.d.ts.map +1 -0
  33. package/dist/backends/browser-use-adapter.js +219 -0
  34. package/dist/backends/browser-use-adapter.js.map +1 -0
  35. package/dist/backends/cdp-backend.d.ts +66 -0
  36. package/dist/backends/cdp-backend.d.ts.map +1 -0
  37. package/dist/backends/cdp-backend.js +273 -0
  38. package/dist/backends/cdp-backend.js.map +1 -0
  39. package/dist/backends/index.d.ts +80 -0
  40. package/dist/backends/index.d.ts.map +1 -0
  41. package/dist/backends/index.js +101 -0
  42. package/dist/backends/index.js.map +1 -0
  43. package/dist/backends/protocol.d.ts +156 -0
  44. package/dist/backends/protocol.d.ts.map +1 -0
  45. package/dist/backends/protocol.js +16 -0
  46. package/dist/backends/protocol.js.map +1 -0
  47. package/dist/backends/sentience-context.d.ts +143 -0
  48. package/dist/backends/sentience-context.d.ts.map +1 -0
  49. package/dist/backends/sentience-context.js +359 -0
  50. package/dist/backends/sentience-context.js.map +1 -0
  51. package/dist/backends/snapshot.d.ts +188 -0
  52. package/dist/backends/snapshot.d.ts.map +1 -0
  53. package/dist/backends/snapshot.js +360 -0
  54. package/dist/backends/snapshot.js.map +1 -0
  55. package/dist/browser.d.ts +154 -0
  56. package/dist/browser.d.ts.map +1 -0
  57. package/dist/browser.js +920 -0
  58. package/dist/browser.js.map +1 -0
  59. package/dist/canonicalization.d.ts +126 -0
  60. package/dist/canonicalization.d.ts.map +1 -0
  61. package/dist/canonicalization.js +161 -0
  62. package/dist/canonicalization.js.map +1 -0
  63. package/dist/captcha/strategies.d.ts +12 -0
  64. package/dist/captcha/strategies.d.ts.map +1 -0
  65. package/dist/captcha/strategies.js +43 -0
  66. package/dist/captcha/strategies.js.map +1 -0
  67. package/dist/captcha/types.d.ts +45 -0
  68. package/dist/captcha/types.d.ts.map +1 -0
  69. package/dist/captcha/types.js +12 -0
  70. package/dist/captcha/types.js.map +1 -0
  71. package/dist/cli.d.ts +5 -0
  72. package/dist/cli.d.ts.map +1 -0
  73. package/dist/cli.js +422 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/conversational-agent.d.ts +123 -0
  76. package/dist/conversational-agent.d.ts.map +1 -0
  77. package/dist/conversational-agent.js +341 -0
  78. package/dist/conversational-agent.js.map +1 -0
  79. package/dist/cursor-policy.d.ts +41 -0
  80. package/dist/cursor-policy.d.ts.map +1 -0
  81. package/dist/cursor-policy.js +81 -0
  82. package/dist/cursor-policy.js.map +1 -0
  83. package/dist/debugger.d.ts +28 -0
  84. package/dist/debugger.d.ts.map +1 -0
  85. package/dist/debugger.js +107 -0
  86. package/dist/debugger.js.map +1 -0
  87. package/dist/expect.d.ts +16 -0
  88. package/dist/expect.d.ts.map +1 -0
  89. package/dist/expect.js +67 -0
  90. package/dist/expect.js.map +1 -0
  91. package/dist/failure-artifacts.d.ts +95 -0
  92. package/dist/failure-artifacts.d.ts.map +1 -0
  93. package/dist/failure-artifacts.js +805 -0
  94. package/dist/failure-artifacts.js.map +1 -0
  95. package/dist/generator.d.ts +16 -0
  96. package/dist/generator.d.ts.map +1 -0
  97. package/dist/generator.js +205 -0
  98. package/dist/generator.js.map +1 -0
  99. package/dist/index.d.ts +37 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +160 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/inspector.d.ts +13 -0
  104. package/dist/inspector.d.ts.map +1 -0
  105. package/dist/inspector.js +153 -0
  106. package/dist/inspector.js.map +1 -0
  107. package/dist/llm-provider.d.ts +144 -0
  108. package/dist/llm-provider.d.ts.map +1 -0
  109. package/dist/llm-provider.js +460 -0
  110. package/dist/llm-provider.js.map +1 -0
  111. package/dist/ordinal.d.ts +90 -0
  112. package/dist/ordinal.d.ts.map +1 -0
  113. package/dist/ordinal.js +249 -0
  114. package/dist/ordinal.js.map +1 -0
  115. package/dist/overlay.d.ts +63 -0
  116. package/dist/overlay.d.ts.map +1 -0
  117. package/dist/overlay.js +102 -0
  118. package/dist/overlay.js.map +1 -0
  119. package/dist/protocols/browser-protocol.d.ts +79 -0
  120. package/dist/protocols/browser-protocol.d.ts.map +1 -0
  121. package/dist/protocols/browser-protocol.js +9 -0
  122. package/dist/protocols/browser-protocol.js.map +1 -0
  123. package/dist/query.d.ts +66 -0
  124. package/dist/query.d.ts.map +1 -0
  125. package/dist/query.js +482 -0
  126. package/dist/query.js.map +1 -0
  127. package/dist/read.d.ts +47 -0
  128. package/dist/read.d.ts.map +1 -0
  129. package/dist/read.js +128 -0
  130. package/dist/read.js.map +1 -0
  131. package/dist/recorder.d.ts +44 -0
  132. package/dist/recorder.d.ts.map +1 -0
  133. package/dist/recorder.js +262 -0
  134. package/dist/recorder.js.map +1 -0
  135. package/dist/runtime-agent.d.ts +72 -0
  136. package/dist/runtime-agent.d.ts.map +1 -0
  137. package/dist/runtime-agent.js +357 -0
  138. package/dist/runtime-agent.js.map +1 -0
  139. package/dist/screenshot.d.ts +17 -0
  140. package/dist/screenshot.d.ts.map +1 -0
  141. package/dist/screenshot.js +40 -0
  142. package/dist/screenshot.js.map +1 -0
  143. package/dist/snapshot-diff.d.ts +23 -0
  144. package/dist/snapshot-diff.d.ts.map +1 -0
  145. package/dist/snapshot-diff.js +119 -0
  146. package/dist/snapshot-diff.js.map +1 -0
  147. package/dist/snapshot.d.ts +47 -0
  148. package/dist/snapshot.d.ts.map +1 -0
  149. package/dist/snapshot.js +358 -0
  150. package/dist/snapshot.js.map +1 -0
  151. package/dist/textSearch.d.ts +64 -0
  152. package/dist/textSearch.d.ts.map +1 -0
  153. package/dist/textSearch.js +113 -0
  154. package/dist/textSearch.js.map +1 -0
  155. package/dist/tools/context.d.ts +18 -0
  156. package/dist/tools/context.d.ts.map +1 -0
  157. package/dist/tools/context.js +40 -0
  158. package/dist/tools/context.js.map +1 -0
  159. package/dist/tools/defaults.d.ts +5 -0
  160. package/dist/tools/defaults.d.ts.map +1 -0
  161. package/dist/tools/defaults.js +368 -0
  162. package/dist/tools/defaults.js.map +1 -0
  163. package/dist/tools/filesystem.d.ts +12 -0
  164. package/dist/tools/filesystem.d.ts.map +1 -0
  165. package/dist/tools/filesystem.js +137 -0
  166. package/dist/tools/filesystem.js.map +1 -0
  167. package/dist/tools/index.d.ts +5 -0
  168. package/dist/tools/index.d.ts.map +1 -0
  169. package/dist/tools/index.js +15 -0
  170. package/dist/tools/index.js.map +1 -0
  171. package/dist/tools/registry.d.ts +38 -0
  172. package/dist/tools/registry.d.ts.map +1 -0
  173. package/dist/tools/registry.js +100 -0
  174. package/dist/tools/registry.js.map +1 -0
  175. package/dist/tracing/cloud-sink.d.ts +189 -0
  176. package/dist/tracing/cloud-sink.d.ts.map +1 -0
  177. package/dist/tracing/cloud-sink.js +1067 -0
  178. package/dist/tracing/cloud-sink.js.map +1 -0
  179. package/dist/tracing/index-schema.d.ts +231 -0
  180. package/dist/tracing/index-schema.d.ts.map +1 -0
  181. package/dist/tracing/index-schema.js +235 -0
  182. package/dist/tracing/index-schema.js.map +1 -0
  183. package/dist/tracing/index.d.ts +12 -0
  184. package/dist/tracing/index.d.ts.map +1 -0
  185. package/dist/tracing/index.js +28 -0
  186. package/dist/tracing/index.js.map +1 -0
  187. package/dist/tracing/indexer.d.ts +20 -0
  188. package/dist/tracing/indexer.d.ts.map +1 -0
  189. package/dist/tracing/indexer.js +347 -0
  190. package/dist/tracing/indexer.js.map +1 -0
  191. package/dist/tracing/jsonl-sink.d.ts +51 -0
  192. package/dist/tracing/jsonl-sink.d.ts.map +1 -0
  193. package/dist/tracing/jsonl-sink.js +329 -0
  194. package/dist/tracing/jsonl-sink.js.map +1 -0
  195. package/dist/tracing/sink.d.ts +25 -0
  196. package/dist/tracing/sink.d.ts.map +1 -0
  197. package/dist/tracing/sink.js +15 -0
  198. package/dist/tracing/sink.js.map +1 -0
  199. package/dist/tracing/tracer-factory.d.ts +102 -0
  200. package/dist/tracing/tracer-factory.d.ts.map +1 -0
  201. package/dist/tracing/tracer-factory.js +375 -0
  202. package/dist/tracing/tracer-factory.js.map +1 -0
  203. package/dist/tracing/tracer.d.ts +140 -0
  204. package/dist/tracing/tracer.d.ts.map +1 -0
  205. package/dist/tracing/tracer.js +336 -0
  206. package/dist/tracing/tracer.js.map +1 -0
  207. package/dist/tracing/types.d.ts +203 -0
  208. package/dist/tracing/types.d.ts.map +1 -0
  209. package/dist/tracing/types.js +8 -0
  210. package/dist/tracing/types.js.map +1 -0
  211. package/dist/types.d.ts +422 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +6 -0
  214. package/dist/types.js.map +1 -0
  215. package/dist/utils/action-executor.d.ts +25 -0
  216. package/dist/utils/action-executor.d.ts.map +1 -0
  217. package/dist/utils/action-executor.js +121 -0
  218. package/dist/utils/action-executor.js.map +1 -0
  219. package/dist/utils/browser-evaluator.d.ts +76 -0
  220. package/dist/utils/browser-evaluator.d.ts.map +1 -0
  221. package/dist/utils/browser-evaluator.js +130 -0
  222. package/dist/utils/browser-evaluator.js.map +1 -0
  223. package/dist/utils/browser.d.ts +30 -0
  224. package/dist/utils/browser.d.ts.map +1 -0
  225. package/dist/utils/browser.js +75 -0
  226. package/dist/utils/browser.js.map +1 -0
  227. package/dist/utils/element-filter.d.ts +76 -0
  228. package/dist/utils/element-filter.d.ts.map +1 -0
  229. package/dist/utils/element-filter.js +195 -0
  230. package/dist/utils/element-filter.js.map +1 -0
  231. package/dist/utils/grid-utils.d.ts +37 -0
  232. package/dist/utils/grid-utils.d.ts.map +1 -0
  233. package/dist/utils/grid-utils.js +283 -0
  234. package/dist/utils/grid-utils.js.map +1 -0
  235. package/dist/utils/llm-interaction-handler.d.ts +41 -0
  236. package/dist/utils/llm-interaction-handler.d.ts.map +1 -0
  237. package/dist/utils/llm-interaction-handler.js +171 -0
  238. package/dist/utils/llm-interaction-handler.js.map +1 -0
  239. package/dist/utils/llm-response-builder.d.ts +56 -0
  240. package/dist/utils/llm-response-builder.d.ts.map +1 -0
  241. package/dist/utils/llm-response-builder.js +130 -0
  242. package/dist/utils/llm-response-builder.js.map +1 -0
  243. package/dist/utils/selector-utils.d.ts +12 -0
  244. package/dist/utils/selector-utils.d.ts.map +1 -0
  245. package/dist/utils/selector-utils.js +32 -0
  246. package/dist/utils/selector-utils.js.map +1 -0
  247. package/dist/utils/snapshot-event-builder.d.ts +28 -0
  248. package/dist/utils/snapshot-event-builder.d.ts.map +1 -0
  249. package/dist/utils/snapshot-event-builder.js +88 -0
  250. package/dist/utils/snapshot-event-builder.js.map +1 -0
  251. package/dist/utils/snapshot-processor.d.ts +27 -0
  252. package/dist/utils/snapshot-processor.d.ts.map +1 -0
  253. package/dist/utils/snapshot-processor.js +47 -0
  254. package/dist/utils/snapshot-processor.js.map +1 -0
  255. package/dist/utils/trace-event-builder.d.ts +122 -0
  256. package/dist/utils/trace-event-builder.d.ts.map +1 -0
  257. package/dist/utils/trace-event-builder.js +365 -0
  258. package/dist/utils/trace-event-builder.js.map +1 -0
  259. package/dist/utils/trace-file-manager.d.ts +70 -0
  260. package/dist/utils/trace-file-manager.d.ts.map +1 -0
  261. package/dist/utils/trace-file-manager.js +194 -0
  262. package/dist/utils/trace-file-manager.js.map +1 -0
  263. package/dist/utils/zod.d.ts +5 -0
  264. package/dist/utils/zod.d.ts.map +1 -0
  265. package/dist/utils/zod.js +80 -0
  266. package/dist/utils/zod.js.map +1 -0
  267. package/dist/utils.d.ts +8 -0
  268. package/dist/utils.d.ts.map +1 -0
  269. package/dist/utils.js +13 -0
  270. package/dist/utils.js.map +1 -0
  271. package/dist/verification.d.ts +194 -0
  272. package/dist/verification.d.ts.map +1 -0
  273. package/dist/verification.js +530 -0
  274. package/dist/verification.js.map +1 -0
  275. package/dist/vision-executor.d.ts +18 -0
  276. package/dist/vision-executor.d.ts.map +1 -0
  277. package/dist/vision-executor.js +60 -0
  278. package/dist/vision-executor.js.map +1 -0
  279. package/dist/visual-agent.d.ts +120 -0
  280. package/dist/visual-agent.d.ts.map +1 -0
  281. package/dist/visual-agent.js +796 -0
  282. package/dist/visual-agent.js.map +1 -0
  283. package/dist/wait.d.ts +35 -0
  284. package/dist/wait.d.ts.map +1 -0
  285. package/dist/wait.js +76 -0
  286. package/dist/wait.js.map +1 -0
  287. package/package.json +94 -0
  288. package/spec/README.md +72 -0
  289. package/spec/SNAPSHOT_V1.md +208 -0
  290. package/spec/sdk-types.md +259 -0
  291. package/spec/snapshot.schema.json +148 -0
  292. package/src/extension/background.js +104 -0
  293. package/src/extension/content.js +162 -0
  294. package/src/extension/injected_api.js +1399 -0
  295. package/src/extension/manifest.json +36 -0
  296. package/src/extension/pkg/README.md +1340 -0
  297. package/src/extension/pkg/package.json +15 -0
  298. package/src/extension/pkg/sentience_core.d.ts +51 -0
  299. package/src/extension/pkg/sentience_core.js +371 -0
  300. package/src/extension/pkg/sentience_core_bg.wasm +0 -0
  301. package/src/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
  302. package/src/extension/release.json +116 -0
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ # License
2
+
3
+ This project is dual-licensed under your choice of either:
4
+
5
+ * **MIT License** ([LICENSE-MIT](./LICENSE-MIT))
6
+ * **Apache License 2.0** ([LICENSE-APACHE](./LICENSE-APACHE))
7
+
8
+ ## Choosing a License
9
+
10
+ You may use this software under the terms of either license, at your option.
11
+
12
+ ### MIT License
13
+ The MIT License is a permissive license that is short and to the point. It lets people do almost anything they want with your project, like making and distributing closed source versions.
14
+
15
+ ### Apache License 2.0
16
+ The Apache License 2.0 is also a permissive license, similar to MIT, but it also provides an express grant of patent rights from contributors to users.
17
+
18
+ ## Contribution
19
+
20
+ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you shall be dual-licensed as above, without any additional terms or conditions.
21
+
22
+ ---
23
+
24
+ Copyright (c) 2025 Sentience Contributors
package/README.md ADDED
@@ -0,0 +1,252 @@
1
+ # Predicate TypeScript SDK
2
+
3
+ > **A verification & control layer for AI agents that operate browsers**
4
+
5
+ Predicate is built for **AI agent developers** who already use Playwright / CDP / LangGraph and care about **flakiness, cost, determinism, evals, and debugging**.
6
+
7
+ Often described as _Jest for Browser AI Agents_ - but applied to end-to-end agent runs (not unit tests).
8
+
9
+ The core loop is:
10
+
11
+ > **Agent → Snapshot → Action → Verification → Artifact**
12
+
13
+ ## What Predicate is
14
+
15
+ - A **verification-first runtime** (`AgentRuntime`) for browser agents
16
+ - Treats the browser as an adapter (Playwright / CDP); **`AgentRuntime` is the product**
17
+ - A **controlled perception** layer (semantic snapshots; pruning/limits; lowers token usage by filtering noise from what models see)
18
+ - A **debugging layer** (structured traces + failure artifacts)
19
+ - Enables **local LLM small models (3B-7B)** for browser automation (privacy, compliance, and cost control)
20
+ - Keeps vision models **optional** (use as a fallback when DOM/snapshot structure falls short, e.g. `<canvas>`)
21
+
22
+ ## What Predicate is not
23
+
24
+ - Not a browser driver
25
+ - Not a Playwright replacement
26
+ - Not a vision-first agent framework
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ npm install @predicatelabs/sdk
32
+ npx playwright install chromium
33
+ ```
34
+
35
+ ## Naming migration (Predicate rebrand)
36
+
37
+ Use the new `Predicate*` class names for all new code:
38
+
39
+ - `PredicateBrowser`
40
+ - `PredicateAgent`
41
+ - `PredicateVisualAgent`
42
+ - `PredicateDebugger`
43
+ - `backends.PredicateContext`
44
+
45
+ ## Conceptual example (why this exists)
46
+
47
+ - Steps are **gated by verifiable UI assertions**
48
+ - If progress can’t be proven, the run **fails with evidence**
49
+ - This is how you make runs **reproducible** and **debuggable**, and how you run evals reliably
50
+
51
+ ## Quickstart: a verification-first loop
52
+
53
+ ```ts
54
+ import { PredicateBrowser, AgentRuntime } from '@predicatelabs/sdk';
55
+ import { JsonlTraceSink, Tracer } from '@predicatelabs/sdk';
56
+ import { exists, urlContains } from '@predicatelabs/sdk';
57
+ import type { Page } from 'playwright';
58
+
59
+ async function main(): Promise<void> {
60
+ const tracer = new Tracer('demo', new JsonlTraceSink('trace.jsonl'));
61
+
62
+ const browser = new PredicateBrowser();
63
+ await browser.start();
64
+ const page = browser.getPage();
65
+ if (!page) throw new Error('no page');
66
+
67
+ await page.goto('https://example.com');
68
+
69
+ // AgentRuntime needs a snapshot provider; PredicateBrowser.snapshot() does not depend on Page,
70
+ // so we wrap it to fit the runtime interface.
71
+ const runtime = new AgentRuntime(
72
+ { snapshot: async (_page: Page, options?: Record<string, any>) => browser.snapshot(options) },
73
+ page,
74
+ tracer
75
+ );
76
+
77
+ runtime.beginStep('Verify homepage');
78
+ await runtime.snapshot({ limit: 60 });
79
+
80
+ runtime.assert(urlContains('example.com'), 'on_domain', true);
81
+ runtime.assert(exists('role=heading'), 'has_heading');
82
+
83
+ runtime.assertDone(exists("text~'Example'"), 'task_complete');
84
+
85
+ await browser.close();
86
+ }
87
+
88
+ void main();
89
+ ```
90
+
91
+ ## PredicateDebugger: attach to your existing agent framework (sidecar mode)
92
+
93
+ If you already have an agent loop (LangGraph, custom planner/executor), keep it and attach Predicate as a **verifier + trace layer**.
94
+
95
+ Key idea: your agent still executes actions — Predicate **snapshots and verifies outcomes**.
96
+
97
+ ```ts
98
+ import type { Page } from 'playwright';
99
+ import { PredicateDebugger, Tracer, JsonlTraceSink, exists, urlContains } from '@predicatelabs/sdk';
100
+
101
+ async function runExistingAgent(page: Page): Promise<void> {
102
+ const tracer = new Tracer('run-123', new JsonlTraceSink('trace.jsonl'));
103
+ const dbg = PredicateDebugger.attach(page, tracer);
104
+
105
+ await dbg.step('agent_step: navigate + verify', async () => {
106
+ // 1) Let your framework do whatever it does
107
+ await yourAgent.step();
108
+
109
+ // 2) Snapshot what the agent produced
110
+ await dbg.snapshot({ limit: 60 });
111
+
112
+ // 3) Verify outcomes (with bounded retries)
113
+ await dbg
114
+ .check(urlContains('example.com'), 'on_domain', true)
115
+ .eventually({ timeoutMs: 10_000 });
116
+ await dbg.check(exists('role=heading'), 'has_heading').eventually({ timeoutMs: 10_000 });
117
+ });
118
+ }
119
+ ```
120
+
121
+ ## SDK-driven full loop (snapshots + actions)
122
+
123
+ If you want Predicate to drive the loop end-to-end, you can use the SDK primitives directly: take a snapshot, select elements, act, then verify.
124
+
125
+ ```ts
126
+ import { PredicateBrowser, snapshot, find, typeText, click, waitFor } from '@predicatelabs/sdk';
127
+
128
+ async function loginExample(): Promise<void> {
129
+ const browser = new PredicateBrowser();
130
+ await browser.start();
131
+ const page = browser.getPage();
132
+ if (!page) throw new Error('no page');
133
+
134
+ await page.goto('https://example.com/login');
135
+
136
+ const snap = await snapshot(browser);
137
+ const email = find(snap, "role=textbox text~'email'");
138
+ const password = find(snap, "role=textbox text~'password'");
139
+ const submit = find(snap, "role=button text~'sign in'");
140
+ if (!email || !password || !submit) throw new Error('login form not found');
141
+
142
+ await typeText(browser, email.id, 'user@example.com');
143
+ await typeText(browser, password.id, 'password123');
144
+ await click(browser, submit.id);
145
+
146
+ const ok = await waitFor(browser, "role=heading text~'Dashboard'", 10_000);
147
+ if (!ok.found) throw new Error('login failed');
148
+
149
+ await browser.close();
150
+ }
151
+ ```
152
+
153
+ ## Capabilities (lifecycle guarantees)
154
+
155
+ ### Controlled perception
156
+
157
+ - **Semantic snapshots** instead of raw DOM dumps
158
+ - **Pruning knobs** via `SnapshotOptions` (limit/filter)
159
+ - Snapshot diagnostics that help decide when “structure is insufficient”
160
+
161
+ ### Constrained action space
162
+
163
+ - Action primitives operate on **stable IDs / rects** derived from snapshots
164
+ - Optional helpers for ordinality (“click the 3rd result”)
165
+
166
+ ### Verified progress
167
+
168
+ - Predicates like `exists(...)`, `urlMatches(...)`, `isEnabled(...)`, `valueEquals(...)`
169
+ - Fluent assertion DSL via `expect(...)`
170
+ - Retrying verification via `runtime.check(...).eventually(...)`
171
+
172
+ ### Explained failure
173
+
174
+ - JSONL trace events (`Tracer` + `JsonlTraceSink`)
175
+ - Optional failure artifact bundles (snapshots, diagnostics, step timelines, frames/clip)
176
+ - Deterministic failure semantics: when required assertions can’t be proven, the run fails with artifacts you can replay
177
+
178
+ ### Framework interoperability
179
+
180
+ - Bring your own LLM and orchestration (LangGraph, custom loops)
181
+ - Register explicit LLM-callable tools with `ToolRegistry`
182
+
183
+ ## ToolRegistry (LLM-callable tools)
184
+
185
+ ```ts
186
+ import { ToolRegistry, registerDefaultTools } from '@predicatelabs/sdk';
187
+
188
+ const registry = new ToolRegistry();
189
+ registerDefaultTools(registry);
190
+ const toolsForLLM = registry.llmTools();
191
+ ```
192
+
193
+ ## Permissions (avoid Chrome permission bubbles)
194
+
195
+ Chrome permission prompts are outside the DOM and can be invisible to snapshots. Prefer setting a policy **before navigation**.
196
+
197
+ ```ts
198
+ import { PredicateBrowser } from '@predicatelabs/sdk';
199
+ import type { PermissionPolicy } from '@predicatelabs/sdk';
200
+
201
+ const policy: PermissionPolicy = {
202
+ default: 'clear',
203
+ autoGrant: ['geolocation'],
204
+ geolocation: { latitude: 37.77, longitude: -122.41, accuracy: 50 },
205
+ origin: 'https://example.com',
206
+ };
207
+
208
+ // `permissionPolicy` is the last constructor argument; pass `keepAlive` right before it.
209
+ const browser = new PredicateBrowser(
210
+ undefined,
211
+ undefined,
212
+ undefined,
213
+ undefined,
214
+ undefined,
215
+ undefined,
216
+ undefined,
217
+ undefined,
218
+ undefined,
219
+ undefined,
220
+ undefined,
221
+ undefined,
222
+ false,
223
+ policy
224
+ );
225
+ await browser.start();
226
+ ```
227
+
228
+ If your backend supports it, you can also use ToolRegistry permission tools (`grant_permissions`, `clear_permissions`, `set_geolocation`) mid-run.
229
+
230
+ ## Downloads (verification predicate)
231
+
232
+ ```ts
233
+ import { downloadCompleted } from '@predicatelabs/sdk';
234
+
235
+ runtime.assert(downloadCompleted('report.csv'), 'download_ok', true);
236
+ ```
237
+
238
+ ## Debugging (fast)
239
+
240
+ - **Manual driver CLI**:
241
+
242
+ ```bash
243
+ npx predicate driver --url https://example.com
244
+ ```
245
+
246
+ - **Verification + artifacts + debugging with time-travel traces (Predicate Studio demo)**:
247
+
248
+ <video src="https://github.com/user-attachments/assets/7ffde43b-1074-4d70-bb83-2eb8d0469307" controls muted playsinline></video>
249
+
250
+ If the video tag doesn’t render in your GitHub README view, use this link: [`sentience-studio-demo.mp4`](https://github.com/user-attachments/assets/7ffde43b-1074-4d70-bb83-2eb8d0469307)
251
+
252
+ - **Predicate SDK Documentation**: https://predicatelabs.dev/docs
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Actions v1 - click, type, press
3
+ */
4
+ import { IBrowser } from './protocols/browser-protocol';
5
+ import { ActionResult, BBox } from './types';
6
+ import { SnapshotOptions } from './snapshot';
7
+ import { CursorPolicy } from './cursor-policy';
8
+ export interface ClickRect {
9
+ x: number;
10
+ y: number;
11
+ w?: number;
12
+ width?: number;
13
+ h?: number;
14
+ height?: number;
15
+ }
16
+ /**
17
+ * Click an element by its ID
18
+ *
19
+ * Uses a hybrid approach: gets element bounding box from snapshot and calculates center,
20
+ * then uses Playwright's native mouse.click() for realistic event simulation.
21
+ * Falls back to JavaScript click if element not found in snapshot.
22
+ *
23
+ * @param browser - SentienceBrowser instance
24
+ * @param elementId - Element ID from snapshot
25
+ * @param useMouse - Use mouse simulation (default: true). If false, uses JavaScript click.
26
+ * @param takeSnapshot - Take snapshot after action (default: false)
27
+ * @returns ActionResult with success status, outcome, duration, and optional snapshot
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const snap = await snapshot(browser);
32
+ * const button = find(snap, 'role=button');
33
+ * if (button) {
34
+ * const result = await click(browser, button.id);
35
+ * console.log(`Click ${result.success ? 'succeeded' : 'failed'}`);
36
+ * }
37
+ * ```
38
+ */
39
+ export declare function click(browser: IBrowser, elementId: number, useMouse?: boolean, takeSnapshot?: boolean, cursorPolicy?: CursorPolicy): Promise<ActionResult>;
40
+ /**
41
+ * Type text into an input element
42
+ *
43
+ * Focuses the element first, then types the text using Playwright's keyboard simulation.
44
+ *
45
+ * @param browser - SentienceBrowser instance
46
+ * @param elementId - Element ID from snapshot (must be a text input element)
47
+ * @param text - Text to type
48
+ * @param takeSnapshot - Take snapshot after action (default: false)
49
+ * @param delayMs - Delay between keystrokes in milliseconds for human-like typing (default: 0)
50
+ * @returns ActionResult with success status, outcome, duration, and optional snapshot
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const snap = await snapshot(browser);
55
+ * const searchBox = find(snap, 'role=searchbox');
56
+ * if (searchBox) {
57
+ * // Type instantly (default behavior)
58
+ * await typeText(browser, searchBox.id, 'Hello World');
59
+ *
60
+ * // Type with human-like delay (~10ms between keystrokes)
61
+ * await typeText(browser, searchBox.id, 'Hello World', false, 10);
62
+ * }
63
+ * ```
64
+ */
65
+ export declare function typeText(browser: IBrowser, elementId: number, text: string, takeSnapshot?: boolean, delayMs?: number): Promise<ActionResult>;
66
+ /**
67
+ * Clear the value of an input/textarea element (best-effort).
68
+ */
69
+ export declare function clear(browser: IBrowser, elementId: number, takeSnapshot?: boolean): Promise<ActionResult>;
70
+ /**
71
+ * Ensure a checkbox/radio is checked (best-effort).
72
+ */
73
+ export declare function check(browser: IBrowser, elementId: number, takeSnapshot?: boolean): Promise<ActionResult>;
74
+ /**
75
+ * Ensure a checkbox/radio is unchecked (best-effort).
76
+ */
77
+ export declare function uncheck(browser: IBrowser, elementId: number, takeSnapshot?: boolean): Promise<ActionResult>;
78
+ /**
79
+ * Select an option in a <select> element by matching option value or label (best-effort).
80
+ */
81
+ export declare function selectOption(browser: IBrowser, elementId: number, option: string, takeSnapshot?: boolean): Promise<ActionResult>;
82
+ /**
83
+ * Upload a local file via an <input type="file"> element (best-effort).
84
+ */
85
+ export declare function uploadFile(browser: IBrowser, elementId: number, filePath: string, takeSnapshot?: boolean): Promise<ActionResult>;
86
+ /**
87
+ * Submit a form (best-effort) by clicking a submit control or calling requestSubmit().
88
+ */
89
+ export declare function submit(browser: IBrowser, elementId: number, takeSnapshot?: boolean): Promise<ActionResult>;
90
+ /**
91
+ * Navigate back in history (best-effort).
92
+ */
93
+ export declare function back(browser: IBrowser, takeSnapshot?: boolean): Promise<ActionResult>;
94
+ /**
95
+ * Scroll an element into view
96
+ *
97
+ * Scrolls the page so that the specified element is visible in the viewport.
98
+ * Uses the element registry to find the element and scrollIntoView() to scroll it.
99
+ *
100
+ * @param browser - SentienceBrowser instance
101
+ * @param elementId - Element ID from snapshot to scroll into view
102
+ * @param behavior - Scroll behavior: 'smooth' for animated scroll, 'instant' for immediate (default: 'smooth')
103
+ * @param block - Vertical alignment: 'start', 'center', 'end', 'nearest' (default: 'center')
104
+ * @param takeSnapshot - Take snapshot after action (default: false)
105
+ * @returns ActionResult with success status, outcome, duration, and optional snapshot
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * const snap = await snapshot(browser);
110
+ * const button = find(snap, 'role=button[name="Submit"]');
111
+ * if (button) {
112
+ * // Scroll element into view with smooth animation
113
+ * await scrollTo(browser, button.id);
114
+ *
115
+ * // Scroll instantly to top of viewport
116
+ * await scrollTo(browser, button.id, 'instant', 'start');
117
+ * }
118
+ * ```
119
+ */
120
+ export declare function scrollTo(browser: IBrowser, elementId: number, behavior?: 'smooth' | 'instant' | 'auto', block?: 'start' | 'center' | 'end' | 'nearest', takeSnapshot?: boolean): Promise<ActionResult>;
121
+ /**
122
+ * Press a keyboard key
123
+ *
124
+ * Simulates pressing a key using Playwright's keyboard API.
125
+ * Common keys: 'Enter', 'Escape', 'Tab', 'ArrowUp', 'ArrowDown', etc.
126
+ *
127
+ * @param browser - SentienceBrowser instance
128
+ * @param key - Key to press (e.g., 'Enter', 'Escape', 'Tab')
129
+ * @param takeSnapshot - Take snapshot after action (default: false)
130
+ * @returns ActionResult with success status, outcome, duration, and optional snapshot
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * // Press Enter after typing
135
+ * await typeText(browser, elementId, 'search query');
136
+ * await press(browser, 'Enter');
137
+ * ```
138
+ */
139
+ export declare function press(browser: IBrowser, key: string, takeSnapshot?: boolean): Promise<ActionResult>;
140
+ /**
141
+ * Send a sequence of key presses (e.g., "CMD+H", "CTRL+SHIFT+P").
142
+ */
143
+ export declare function sendKeys(browser: IBrowser, sequence: string, takeSnapshot?: boolean, delayMs?: number): Promise<ActionResult>;
144
+ /**
145
+ * Navigate to a search results page for the given query.
146
+ */
147
+ export declare function search(browser: IBrowser, query: string, engine?: string, takeSnapshot?: boolean, snapshotOptions?: SnapshotOptions | undefined): Promise<ActionResult>;
148
+ /**
149
+ * Click at the center of a rectangle using Playwright's native mouse simulation.
150
+ * This uses a hybrid approach: calculates center coordinates and uses mouse.click()
151
+ * for realistic event simulation (triggers hover, focus, mousedown, mouseup).
152
+ *
153
+ * @param browser - SentienceBrowser instance
154
+ * @param rect - Rectangle with x, y, w (or width), h (or height) keys, or BBox object
155
+ * @param highlight - Whether to show a red border highlight when clicking (default: true)
156
+ * @param highlightDuration - How long to show the highlight in seconds (default: 2.0)
157
+ * @param takeSnapshot - Whether to take snapshot after action
158
+ * @returns ActionResult
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * // Click using rect object
163
+ * await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 });
164
+ *
165
+ * // Click using BBox from element
166
+ * const snap = await snapshot(browser);
167
+ * const element = find(snap, "role=button");
168
+ * if (element) {
169
+ * await clickRect(browser, {
170
+ * x: element.bbox.x,
171
+ * y: element.bbox.y,
172
+ * w: element.bbox.width,
173
+ * h: element.bbox.height
174
+ * });
175
+ * }
176
+ *
177
+ * // Without highlight
178
+ * await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, false);
179
+ *
180
+ * // Custom highlight duration
181
+ * await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, true, 3.0);
182
+ * ```
183
+ */
184
+ export declare function clickRect(browser: IBrowser, rect: ClickRect | BBox, highlight?: boolean, highlightDuration?: number, takeSnapshot?: boolean, cursorPolicy?: CursorPolicy): Promise<ActionResult>;
185
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAY,IAAI,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAY,eAAe,EAAE,MAAM,YAAY,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAwB,MAAM,iBAAiB,CAAC;AAoCrE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAoED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,OAAc,EACxB,YAAY,GAAE,OAAe,EAC7B,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,YAAY,CAAC,CA2GvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,OAAe,EAC7B,OAAO,GAAE,MAAU,GAClB,OAAO,CAAC,YAAY,CAAC,CAoDvB;AAED;;GAEG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA4DvB;AAED;;GAEG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA2DvB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA2DvB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CAwEvB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA8EvB;AAED;;GAEG;AACH,wBAAsB,MAAM,CAC1B,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CAiFvB;AAED;;GAEG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,QAAQ,EACjB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CAiDvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,QAAQ,GAAG,SAAS,GAAG,MAAiB,EAClD,KAAK,GAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAoB,EACxD,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CAwDvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,QAAQ,EACjB,GAAG,EAAE,MAAM,EACX,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CAgCvB;AA4CD;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,MAAM,EAChB,YAAY,GAAE,OAAe,EAC7B,OAAO,GAAE,MAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CAqCvB;AAiBD;;GAEG;AACH,wBAAsB,MAAM,CAC1B,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAqB,EAC7B,YAAY,GAAE,OAAe,EAC7B,eAAe,GAAE,eAAe,GAAG,SAAqB,GACvD,OAAO,CAAC,YAAY,CAAC,CAwCvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,SAAS,GAAG,IAAI,EACtB,SAAS,GAAE,OAAc,EACzB,iBAAiB,GAAE,MAAY,EAC/B,YAAY,GAAE,OAAe,EAC7B,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,YAAY,CAAC,CAgGvB"}