arise-browser 0.1.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 (148) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +247 -0
  3. package/deploy/neko/CONTEXT.md +37 -0
  4. package/deploy/neko/arise-browser.service +13 -0
  5. package/deploy/neko/neko.yaml +12 -0
  6. package/deploy/neko/openbox.xml +763 -0
  7. package/deploy/neko/policies.json +28 -0
  8. package/deploy/neko/pulseaudio.pa +16 -0
  9. package/deploy/neko/setup.sh +308 -0
  10. package/deploy/neko/xorg.conf +118 -0
  11. package/dist/bin/arise-browser.d.ts +26 -0
  12. package/dist/bin/arise-browser.d.ts.map +1 -0
  13. package/dist/bin/arise-browser.js +224 -0
  14. package/dist/bin/arise-browser.js.map +1 -0
  15. package/dist/src/browser/action-executor.d.ts +98 -0
  16. package/dist/src/browser/action-executor.d.ts.map +1 -0
  17. package/dist/src/browser/action-executor.js +2726 -0
  18. package/dist/src/browser/action-executor.js.map +1 -0
  19. package/dist/src/browser/behavior-recorder.d.ts +61 -0
  20. package/dist/src/browser/behavior-recorder.d.ts.map +1 -0
  21. package/dist/src/browser/behavior-recorder.js +442 -0
  22. package/dist/src/browser/behavior-recorder.js.map +1 -0
  23. package/dist/src/browser/browser-session.d.ts +202 -0
  24. package/dist/src/browser/browser-session.d.ts.map +1 -0
  25. package/dist/src/browser/browser-session.js +1647 -0
  26. package/dist/src/browser/browser-session.js.map +1 -0
  27. package/dist/src/browser/config.d.ts +43 -0
  28. package/dist/src/browser/config.d.ts.map +1 -0
  29. package/dist/src/browser/config.js +59 -0
  30. package/dist/src/browser/config.js.map +1 -0
  31. package/dist/src/browser/page-snapshot.d.ts +38 -0
  32. package/dist/src/browser/page-snapshot.d.ts.map +1 -0
  33. package/dist/src/browser/page-snapshot.js +241 -0
  34. package/dist/src/browser/page-snapshot.js.map +1 -0
  35. package/dist/src/browser/scripts/behavior_tracker.js +424 -0
  36. package/dist/src/browser/scripts/unified_analyzer.js +1576 -0
  37. package/dist/src/index.d.ts +15 -0
  38. package/dist/src/index.d.ts.map +1 -0
  39. package/dist/src/index.js +15 -0
  40. package/dist/src/index.js.map +1 -0
  41. package/dist/src/lock.d.ts +11 -0
  42. package/dist/src/lock.d.ts.map +1 -0
  43. package/dist/src/lock.js +47 -0
  44. package/dist/src/lock.js.map +1 -0
  45. package/dist/src/logger.d.ts +17 -0
  46. package/dist/src/logger.d.ts.map +1 -0
  47. package/dist/src/logger.js +29 -0
  48. package/dist/src/logger.js.map +1 -0
  49. package/dist/src/server/middleware/auth.d.ts +6 -0
  50. package/dist/src/server/middleware/auth.d.ts.map +1 -0
  51. package/dist/src/server/middleware/auth.js +24 -0
  52. package/dist/src/server/middleware/auth.js.map +1 -0
  53. package/dist/src/server/route-utils.d.ts +15 -0
  54. package/dist/src/server/route-utils.d.ts.map +1 -0
  55. package/dist/src/server/route-utils.js +33 -0
  56. package/dist/src/server/route-utils.js.map +1 -0
  57. package/dist/src/server/routes/action.d.ts +5 -0
  58. package/dist/src/server/routes/action.d.ts.map +1 -0
  59. package/dist/src/server/routes/action.js +69 -0
  60. package/dist/src/server/routes/action.js.map +1 -0
  61. package/dist/src/server/routes/actions.d.ts +3 -0
  62. package/dist/src/server/routes/actions.d.ts.map +1 -0
  63. package/dist/src/server/routes/actions.js +53 -0
  64. package/dist/src/server/routes/actions.js.map +1 -0
  65. package/dist/src/server/routes/cookies.d.ts +3 -0
  66. package/dist/src/server/routes/cookies.d.ts.map +1 -0
  67. package/dist/src/server/routes/cookies.js +27 -0
  68. package/dist/src/server/routes/cookies.js.map +1 -0
  69. package/dist/src/server/routes/download.d.ts +3 -0
  70. package/dist/src/server/routes/download.d.ts.map +1 -0
  71. package/dist/src/server/routes/download.js +35 -0
  72. package/dist/src/server/routes/download.js.map +1 -0
  73. package/dist/src/server/routes/evaluate.d.ts +3 -0
  74. package/dist/src/server/routes/evaluate.d.ts.map +1 -0
  75. package/dist/src/server/routes/evaluate.js +27 -0
  76. package/dist/src/server/routes/evaluate.js.map +1 -0
  77. package/dist/src/server/routes/health.d.ts +3 -0
  78. package/dist/src/server/routes/health.d.ts.map +1 -0
  79. package/dist/src/server/routes/health.js +11 -0
  80. package/dist/src/server/routes/health.js.map +1 -0
  81. package/dist/src/server/routes/navigate.d.ts +3 -0
  82. package/dist/src/server/routes/navigate.d.ts.map +1 -0
  83. package/dist/src/server/routes/navigate.js +36 -0
  84. package/dist/src/server/routes/navigate.js.map +1 -0
  85. package/dist/src/server/routes/page-model.d.ts +3 -0
  86. package/dist/src/server/routes/page-model.d.ts.map +1 -0
  87. package/dist/src/server/routes/page-model.js +22 -0
  88. package/dist/src/server/routes/page-model.js.map +1 -0
  89. package/dist/src/server/routes/pdf.d.ts +3 -0
  90. package/dist/src/server/routes/pdf.d.ts.map +1 -0
  91. package/dist/src/server/routes/pdf.js +20 -0
  92. package/dist/src/server/routes/pdf.js.map +1 -0
  93. package/dist/src/server/routes/recording.d.ts +5 -0
  94. package/dist/src/server/routes/recording.d.ts.map +1 -0
  95. package/dist/src/server/routes/recording.js +217 -0
  96. package/dist/src/server/routes/recording.js.map +1 -0
  97. package/dist/src/server/routes/screenshot.d.ts +3 -0
  98. package/dist/src/server/routes/screenshot.d.ts.map +1 -0
  99. package/dist/src/server/routes/screenshot.js +32 -0
  100. package/dist/src/server/routes/screenshot.js.map +1 -0
  101. package/dist/src/server/routes/snapshot.d.ts +3 -0
  102. package/dist/src/server/routes/snapshot.d.ts.map +1 -0
  103. package/dist/src/server/routes/snapshot.js +454 -0
  104. package/dist/src/server/routes/snapshot.js.map +1 -0
  105. package/dist/src/server/routes/tab-lock.d.ts +3 -0
  106. package/dist/src/server/routes/tab-lock.d.ts.map +1 -0
  107. package/dist/src/server/routes/tab-lock.js +30 -0
  108. package/dist/src/server/routes/tab-lock.js.map +1 -0
  109. package/dist/src/server/routes/tab.d.ts +3 -0
  110. package/dist/src/server/routes/tab.d.ts.map +1 -0
  111. package/dist/src/server/routes/tab.js +47 -0
  112. package/dist/src/server/routes/tab.js.map +1 -0
  113. package/dist/src/server/routes/tabs.d.ts +3 -0
  114. package/dist/src/server/routes/tabs.d.ts.map +1 -0
  115. package/dist/src/server/routes/tabs.js +13 -0
  116. package/dist/src/server/routes/tabs.js.map +1 -0
  117. package/dist/src/server/routes/text.d.ts +3 -0
  118. package/dist/src/server/routes/text.d.ts.map +1 -0
  119. package/dist/src/server/routes/text.js +20 -0
  120. package/dist/src/server/routes/text.js.map +1 -0
  121. package/dist/src/server/routes/upload.d.ts +3 -0
  122. package/dist/src/server/routes/upload.d.ts.map +1 -0
  123. package/dist/src/server/routes/upload.js +38 -0
  124. package/dist/src/server/routes/upload.js.map +1 -0
  125. package/dist/src/server/server.d.ts +7 -0
  126. package/dist/src/server/server.d.ts.map +1 -0
  127. package/dist/src/server/server.js +69 -0
  128. package/dist/src/server/server.js.map +1 -0
  129. package/dist/src/types/index.d.ts +125 -0
  130. package/dist/src/types/index.d.ts.map +1 -0
  131. package/dist/src/types/index.js +5 -0
  132. package/dist/src/types/index.js.map +1 -0
  133. package/dist/src/virtual-display/manager.d.ts +37 -0
  134. package/dist/src/virtual-display/manager.d.ts.map +1 -0
  135. package/dist/src/virtual-display/manager.js +229 -0
  136. package/dist/src/virtual-display/manager.js.map +1 -0
  137. package/dist/src/virtual-display/process-runner.d.ts +43 -0
  138. package/dist/src/virtual-display/process-runner.d.ts.map +1 -0
  139. package/dist/src/virtual-display/process-runner.js +174 -0
  140. package/dist/src/virtual-display/process-runner.js.map +1 -0
  141. package/dist/tsconfig.tsbuildinfo +1 -0
  142. package/package.json +57 -0
  143. package/plugin/openclaw.plugin.json +148 -0
  144. package/skill/arise-browser/SKILL.md +275 -0
  145. package/skill/arise-browser/TRUST.md +42 -0
  146. package/skill/arise-browser/references/api.md +198 -0
  147. package/src/browser/scripts/behavior_tracker.js +424 -0
  148. package/src/browser/scripts/unified_analyzer.js +1576 -0
@@ -0,0 +1,275 @@
1
+ ---
2
+ name: arise-browser
3
+ description: >
4
+ Control a headless or headed Chromium browser via AriseBrowser's HTTP API. Use for web automation,
5
+ scraping, form filling, navigation, and multi-tab workflows. AriseBrowser exposes a YAML accessibility
6
+ tree with persistent refs (WeakMap + aria-ref + signature), multi-strategy click fallbacks, and
7
+ behavior recording with Learn protocol export — built for AI agents that need reliable browser control.
8
+ Use when the task involves: browsing websites, filling forms, clicking buttons, extracting
9
+ page text, taking screenshots, recording workflows, or any browser-based automation.
10
+ Supports virtual display mode on Linux servers — runs a real headed Chrome with Xvfb + Neko WebRTC
11
+ streaming, allowing users to watch and interact with the AI-controlled browser in real time.
12
+ homepage: https://github.com/AriseOS/arise-browser
13
+ metadata:
14
+ openclaw:
15
+ emoji: "🚀"
16
+ requires:
17
+ bins: ["npx"]
18
+ env: |
19
+ ARISE_BROWSER_TOKEN (optional, secret) - Bearer auth token
20
+ ARISE_BROWSER_PORT (optional) - HTTP port, default 9867
21
+ ARISE_BROWSER_HEADLESS (optional) - true/false, default true
22
+ ARISE_BROWSER_PROFILE (optional) - Chromium profile directory
23
+ ARISE_BROWSER_BIND (optional) - Bind address, default 127.0.0.1
24
+ ARISE_BROWSER_VIRTUAL_DISPLAY (optional) - Enable headed mode with Xvfb + Neko (Linux only)
25
+ ARISE_BROWSER_NEKO_PORT (optional) - Neko WebRTC port, default 6090
26
+ ARISE_BROWSER_NEKO_PASSWORD (optional, secret) - Neko user password, default "neko"
27
+ ARISE_BROWSER_NEKO_ADMIN_PASSWORD (optional, secret) - Neko admin password, default "admin"
28
+ ---
29
+
30
+ # AriseBrowser
31
+
32
+ Industrial-grade browser automation for AI agents. Persistent refs, multi-strategy clicks, behavior recording.
33
+
34
+ **Security Note:** AriseBrowser runs entirely locally. It does not contact external services or send telemetry. It controls a real Chromium instance — if pointed at a profile with saved logins, agents can access authenticated sites. Always use a dedicated empty profile and set ARISE_BROWSER_TOKEN when exposing the API. See [TRUST.md](TRUST.md) for the full security model.
35
+
36
+ ## Quick Start (Agent Workflow)
37
+
38
+ ```bash
39
+ # 1. Start AriseBrowser (local on :9867)
40
+ npx arise-browser &
41
+
42
+ # 2. In your agent, follow this loop:
43
+ # a) Navigate to a URL
44
+ # b) Snapshot the page (get refs like e0, e5, e12)
45
+ # c) Act on a ref (click e5, type e12 "search text")
46
+ # d) Snapshot again to see the result
47
+ # e) Repeat until done
48
+ ```
49
+
50
+ **Refs are persistent** — AriseBrowser's 3-layer ref system (WeakMap + aria-ref + signature) means refs survive across snapshots. You don't need to re-snapshot before every action.
51
+
52
+ ### Recommended Secure Setup
53
+
54
+ ```bash
55
+ ARISE_BROWSER_BIND=127.0.0.1 \
56
+ ARISE_BROWSER_TOKEN="your-strong-secret" \
57
+ ARISE_BROWSER_PROFILE=~/.arise-browser/automation-profile \
58
+ npx arise-browser &
59
+ ```
60
+
61
+ **Never expose to 0.0.0.0 without a token. Never point at your daily browser profile.**
62
+
63
+ ## Setup
64
+
65
+ ### Headless Mode (default, any platform)
66
+
67
+ ```bash
68
+ # Headless (default)
69
+ npx arise-browser &
70
+
71
+ # Headed — visible browser for debugging
72
+ npx arise-browser --no-headless &
73
+
74
+ # With auth token
75
+ ARISE_BROWSER_TOKEN="your-secret-token" npx arise-browser &
76
+
77
+ # Custom port
78
+ npx arise-browser --port 8080 &
79
+
80
+ # Connect to existing browser via CDP
81
+ npx arise-browser --cdp http://localhost:9222 &
82
+
83
+ # Persistent profile
84
+ npx arise-browser --profile ~/.arise-browser/my-profile &
85
+ ```
86
+
87
+ Default: **port 9867**, no auth required (local). Set `ARISE_BROWSER_TOKEN` for remote access.
88
+
89
+ ### Virtual Display Mode (Linux servers — headed + WebRTC streaming)
90
+
91
+ Run a real headed Chrome on a headless Linux server. Users watch and interact via Neko WebRTC UI.
92
+
93
+ ```bash
94
+ # 1. Install system dependencies (once, requires root)
95
+ # From npm package:
96
+ sudo bash $(dirname $(which arise-browser))/../lib/node_modules/arise-browser/deploy/neko/setup.sh
97
+ # Or from git clone:
98
+ # sudo bash deploy/neko/setup.sh
99
+ # Or directly from GitHub:
100
+ sudo bash <(curl -fsSL https://raw.githubusercontent.com/AriseOS/arise-browser/main/deploy/neko/setup.sh)
101
+
102
+ # 2. Start with virtual display
103
+ npx arise-browser --virtual-display --port 9867 --host 0.0.0.0 &
104
+
105
+ # 3. AI agent uses the API as usual:
106
+ curl -X POST http://localhost:9867/navigate -H 'Content-Type: application/json' -d '{"url":"https://example.com"}'
107
+
108
+ # 4. Users open Neko in a browser to watch/interact:
109
+ # http://<server-ip>:6090 (password: neko)
110
+ ```
111
+
112
+ Virtual display mode automatically:
113
+ - Starts Xvfb (virtual X11 display)
114
+ - Starts PulseAudio (virtual audio)
115
+ - Starts Openbox (window manager, maximizes Chrome)
116
+ - Launches Chrome with CDP on localhost:9222
117
+ - Starts Neko server for WebRTC streaming
118
+ - Connects arise-browser to Chrome via CDP
119
+
120
+ All processes are managed as children of arise-browser — no supervisord needed.
121
+
122
+ **Ports in virtual display mode:**
123
+
124
+ | Port | Service | Access |
125
+ |------|---------|--------|
126
+ | 9867 | arise-browser API | AI agent |
127
+ | 6090 | Neko WebRTC UI | User browser |
128
+ | 52000-52100/udp | WebRTC data | User browser |
129
+ | 9222 | Chrome CDP | localhost only |
130
+
131
+ **Virtual display options:**
132
+
133
+ ```bash
134
+ --virtual-display # Enable virtual display mode
135
+ --neko-port <port> # Neko port (default: 6090)
136
+ --neko-password <pwd> # Neko user password (default: "neko")
137
+ --neko-admin-password <pwd> # Neko admin password (default: "admin")
138
+ ```
139
+
140
+ ## Core Workflow
141
+
142
+ ### 1. Navigate
143
+
144
+ ```bash
145
+ curl -X POST http://localhost:9867/navigate \
146
+ -H "Content-Type: application/json" \
147
+ -d '{"url": "https://example.com"}'
148
+ ```
149
+
150
+ ### 2. Snapshot
151
+
152
+ ```bash
153
+ # YAML format (default, best for AI agents)
154
+ curl http://localhost:9867/snapshot
155
+
156
+ # JSON format (structured)
157
+ curl "http://localhost:9867/snapshot?format=json"
158
+
159
+ # Diff mode (only changes since last snapshot)
160
+ curl "http://localhost:9867/snapshot?diff=true"
161
+ ```
162
+
163
+ ### 3. Act
164
+
165
+ ```bash
166
+ # Click by ref
167
+ curl -X POST http://localhost:9867/action \
168
+ -H "Content-Type: application/json" \
169
+ -d '{"kind": "click", "ref": "e5"}'
170
+
171
+ # Type into field
172
+ curl -X POST http://localhost:9867/action \
173
+ -H "Content-Type: application/json" \
174
+ -d '{"kind": "type", "ref": "e12", "text": "hello world"}'
175
+
176
+ # Press key
177
+ curl -X POST http://localhost:9867/action \
178
+ -H "Content-Type: application/json" \
179
+ -d '{"kind": "press", "key": "Enter"}'
180
+
181
+ # Scroll down
182
+ curl -X POST http://localhost:9867/action \
183
+ -H "Content-Type: application/json" \
184
+ -d '{"kind": "scroll", "scrollY": 300}'
185
+
186
+ # Hover
187
+ curl -X POST http://localhost:9867/action \
188
+ -H "Content-Type: application/json" \
189
+ -d '{"kind": "hover", "ref": "e7"}'
190
+
191
+ # Select option
192
+ curl -X POST http://localhost:9867/action \
193
+ -H "Content-Type: application/json" \
194
+ -d '{"kind": "select", "ref": "e3", "value": "option1"}'
195
+ ```
196
+
197
+ ### 4. Record & Export
198
+
199
+ ```bash
200
+ # Start recording
201
+ curl -X POST http://localhost:9867/recording/start
202
+ # => {"recordingId": "session_20260303T180000"}
203
+
204
+ # ... perform actions ...
205
+
206
+ # Stop recording
207
+ curl -X POST http://localhost:9867/recording/stop \
208
+ -d '{"recordingId": "session_20260303T180000"}'
209
+
210
+ # Export as Learn protocol
211
+ curl -X POST http://localhost:9867/recording/export \
212
+ -d '{"recordingId": "session_20260303T180000", "task": "Search for AI products"}'
213
+ ```
214
+
215
+ Stopped recordings remain exportable for a limited retention window, so `stop -> export` is a supported flow.
216
+
217
+ ## API Reference
218
+
219
+ | Endpoint | Method | Description |
220
+ |----------|--------|-------------|
221
+ | `/health` | GET | Health check |
222
+ | `/tabs` | GET | List all tabs |
223
+ | `/navigate` | POST | Navigate to URL |
224
+ | `/snapshot` | GET | Accessibility tree snapshot |
225
+ | `/action` | POST | Execute single action |
226
+ | `/actions` | POST | Execute batch actions |
227
+ | `/text` | GET | Extract page text |
228
+ | `/screenshot` | GET | JPEG screenshot |
229
+ | `/pdf` | GET | PDF export |
230
+ | `/evaluate` | POST | Execute JavaScript |
231
+ | `/tab` | POST | Create/close/switch tabs |
232
+ | `/tab/lock` | POST | Lock tab (multi-agent) |
233
+ | `/tab/unlock` | POST | Unlock tab |
234
+ | `/cookies` | GET/POST | Read/write cookies |
235
+ | `/recording/start` | POST | Start recording |
236
+ | `/recording/stop` | POST | Stop recording |
237
+ | `/recording/status` | GET | Recording status |
238
+ | `/recording/export` | POST | Export Learn format |
239
+
240
+ Notes:
241
+ - Read routes support optional `tabId` where applicable.
242
+ - Write routes targeting a locked tab accept optional `owner`; mismatches return `423 Locked`.
243
+ - `/navigate` accepts optional `tabId` and `timeout` (milliseconds).
244
+
245
+ ## Why AriseBrowser over Pinchtab?
246
+
247
+ | Feature | AriseBrowser | Pinchtab |
248
+ |---------|----------|----------|
249
+ | Persistent Refs | 3-layer (WeakMap + aria-ref + signature) | Single pass |
250
+ | Click Strategy | Ctrl+Click → Force Click fallback | Single attempt |
251
+ | Select support | Full implementation | Empty stub |
252
+ | Behavior Recording | Built-in + Learn protocol export | Not available |
253
+ | Coordinate handling | Viewport-validated | Hardcoded (0,0) |
254
+ | Virtual Display | Xvfb + Neko WebRTC (headed on servers) | Not available |
255
+ | Runtime | Node.js + Playwright | Go + CDP |
256
+
257
+ ## Token Cost Guide
258
+
259
+ - Snapshot (YAML): ~500-2000 tokens depending on page complexity
260
+ - Snapshot (JSON): ~300-1500 tokens
261
+ - Action response: ~50-100 tokens
262
+ - Recording export: ~100-500 tokens per workflow
263
+
264
+ ## Pinchtab Compatibility
265
+
266
+ AriseBrowser accepts Pinchtab's `kind` field in `/action`:
267
+ - `kind: "click"` → click
268
+ - `kind: "type"` / `kind: "fill"` → type
269
+ - `kind: "press"` → press_key
270
+ - `kind: "scroll"` (with `scrollY`) → scroll
271
+ - `kind: "hover"` → hover
272
+ - `kind: "select"` → select
273
+ - `kind: "focus"` → focus
274
+
275
+ Environment variables `BRIDGE_*` are also accepted as aliases for `ARISE_BROWSER_*`.
@@ -0,0 +1,42 @@
1
+ # AriseBrowser Trust & Security Model
2
+
3
+ ## What AriseBrowser Does
4
+
5
+ AriseBrowser is a local HTTP server that controls a Chromium browser via Playwright. It:
6
+ - Listens on localhost only (127.0.0.1) by default
7
+ - Does NOT contact external services
8
+ - Does NOT send telemetry or analytics
9
+ - Does NOT store data beyond the current session
10
+
11
+ ## Security Boundaries
12
+
13
+ ### Network
14
+ - Binds to 127.0.0.1 by default (local only)
15
+ - Optional Bearer token authentication (`ARISE_BROWSER_TOKEN`)
16
+ - No TLS built-in (use reverse proxy for remote access)
17
+
18
+ ### Browser
19
+ - Uses Playwright's Chromium (not your system Chrome)
20
+ - Default: fresh profile with no saved data
21
+ - `--profile` mode: accesses saved logins, cookies, history
22
+ - Stealth headers enabled by default to avoid bot detection
23
+
24
+ ### Data
25
+ - Snapshots and actions are ephemeral (not persisted)
26
+ - Recordings are in-memory only, cleared on server restart
27
+ - No data is written to disk unless `--profile` is used
28
+
29
+ ## Recommendations
30
+
31
+ 1. **Always set `ARISE_BROWSER_TOKEN`** when the API is accessible to other processes
32
+ 2. **Never use `--profile` with your daily browser profile** — create a dedicated one
33
+ 3. **Never bind to 0.0.0.0** without token authentication
34
+ 4. **Review `/evaluate` usage** — it executes arbitrary JavaScript in the page context
35
+
36
+ ## Dependencies
37
+
38
+ - `playwright` — Browser automation (Microsoft, Apache-2.0)
39
+ - `fastify` — HTTP framework (MIT)
40
+ - `pino` — Logging (MIT)
41
+
42
+ All dependencies are widely used, well-maintained, and open source.
@@ -0,0 +1,198 @@
1
+ # AriseBrowser API Reference
2
+
3
+ Base URL: `http://localhost:9867`
4
+
5
+ ## Health
6
+
7
+ ### GET /health
8
+ Returns server status.
9
+
10
+ Response:
11
+ ```json
12
+ {"status": "ok", "connected": true, "version": "0.1.0"}
13
+ ```
14
+
15
+ ## Navigation
16
+
17
+ ### POST /navigate
18
+ Navigate to a URL.
19
+
20
+ Body:
21
+ ```json
22
+ {"url": "https://example.com", "newTab": false, "tabId": "tab-001", "timeout": 15000}
23
+ ```
24
+
25
+ Response:
26
+ ```json
27
+ {"message": "Navigated to https://example.com", "url": "https://example.com"}
28
+ ```
29
+
30
+ ## Snapshot
31
+
32
+ ### GET /snapshot
33
+ Get accessibility tree snapshot.
34
+
35
+ Query params:
36
+ - `tabId`: snapshot a specific tab without switching the global current tab
37
+ - `format`: `yaml` (default), `json`, `compact`, `text`
38
+ - `diff`: `true`/`false` — return only changes since last snapshot
39
+ - `viewportLimit`: `true`/`false` — limit to visible viewport
40
+
41
+ Response (yaml):
42
+ ```json
43
+ {"snapshot": "- Page Snapshot\n```yaml\n...\n```", "format": "yaml"}
44
+ ```
45
+
46
+ Response (json):
47
+ ```json
48
+ {"nodes": [{"ref": "e0", "role": "link", "name": "Home"}], "url": "...", "title": "...", "count": 42}
49
+ ```
50
+
51
+ ## Actions
52
+
53
+ ### POST /action
54
+ Execute a single browser action.
55
+
56
+ Body (AriseBrowser native):
57
+ ```json
58
+ {"type": "click", "ref": "e5", "tabId": "tab-001", "owner": "agent-1"}
59
+ ```
60
+
61
+ Body (Pinchtab-compatible):
62
+ ```json
63
+ {"kind": "click", "ref": "e5"}
64
+ ```
65
+
66
+ Supported kinds: `click`, `type`, `fill`, `press`, `hover`, `scroll`, `select`, `focus`
67
+
68
+ ### POST /actions
69
+ Execute multiple actions sequentially.
70
+
71
+ Body:
72
+ ```json
73
+ {"actions": [{"type": "click", "ref": "e5", "tabId": "tab-001"}], "owner": "agent-1", "stopOnError": true}
74
+ ```
75
+
76
+ ## Content
77
+
78
+ ### GET /text
79
+ Extract page text content.
80
+ Query params: `tabId` (optional)
81
+
82
+ ### GET /screenshot
83
+ Get JPEG screenshot.
84
+
85
+ Query params:
86
+ - `tabId`: specific tab (optional)
87
+ - `quality`: 1-100 (default 75)
88
+ - `raw`: `true` returns raw JPEG bytes
89
+
90
+ ### GET /pdf
91
+ Export page as PDF.
92
+ Query params: `tabId` (optional)
93
+
94
+ ### POST /evaluate
95
+ Execute JavaScript in page context.
96
+
97
+ Body:
98
+ ```json
99
+ {"expression": "document.title", "tabId": "tab-001", "owner": "agent-1"}
100
+ ```
101
+
102
+ ## Tabs
103
+
104
+ ### GET /tabs
105
+ List all open tabs.
106
+
107
+ ### POST /tab
108
+ Create, close, or switch tabs.
109
+
110
+ Body:
111
+ ```json
112
+ {"action": "create", "url": "https://example.com"}
113
+ {"action": "close", "tabId": "tab-001"}
114
+ {"action": "switch", "tabId": "tab-002"}
115
+ ```
116
+
117
+ ### POST /tab/lock
118
+ Lock a tab for exclusive use.
119
+ Locked write routes return `423 Locked` unless the same `owner` is supplied.
120
+
121
+ Body:
122
+ ```json
123
+ {"tabId": "tab-001", "owner": "agent-1", "ttlMs": 60000}
124
+ ```
125
+
126
+ ### POST /tab/unlock
127
+ Release a tab lock.
128
+
129
+ Body:
130
+ ```json
131
+ {"tabId": "tab-001", "owner": "agent-1"}
132
+ ```
133
+
134
+ ## Cookies
135
+
136
+ ### GET /cookies
137
+ Get all cookies.
138
+
139
+ ### POST /cookies
140
+ Set cookies.
141
+
142
+ Body:
143
+ ```json
144
+ {"cookies": [{"name": "session", "value": "abc123", "url": "https://example.com"}]}
145
+ ```
146
+
147
+ ## Recording
148
+
149
+ ### POST /recording/start
150
+ Start behavior recording.
151
+
152
+ Response:
153
+ ```json
154
+ {"recordingId": "session_20260303T180000"}
155
+ ```
156
+
157
+ ### POST /recording/stop
158
+ Stop recording and get operations.
159
+
160
+ Body:
161
+ ```json
162
+ {"recordingId": "session_20260303T180000"}
163
+ ```
164
+
165
+ ### GET /recording/status
166
+ Check recording status.
167
+
168
+ Query params:
169
+ - `recordingId`: specific recording (optional)
170
+
171
+ ### POST /recording/export
172
+ Export recording as Learn protocol format.
173
+ Works for active recordings and recently stopped recordings retained in memory.
174
+
175
+ Body:
176
+ ```json
177
+ {"recordingId": "session_20260303T180000", "task": "Search for AI products"}
178
+ ```
179
+
180
+ Response:
181
+ ```json
182
+ {
183
+ "type": "browser_workflow",
184
+ "task": "Search for AI products",
185
+ "success": true,
186
+ "domain": "producthunt.com",
187
+ "steps": [
188
+ {"url": "https://producthunt.com", "action": "navigate"},
189
+ {"url": "https://producthunt.com", "action": "click", "target": "Search"},
190
+ {"url": "https://producthunt.com", "action": "type", "target": "e12", "value": "AI"}
191
+ ],
192
+ "metadata": {
193
+ "duration_ms": 15000,
194
+ "page_count": 3,
195
+ "recorded_at": "2026-03-03T18:00:00Z"
196
+ }
197
+ }
198
+ ```