browser-workspace 0.4.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 (108) hide show
  1. package/PRIVACY.md +21 -0
  2. package/README.md +138 -0
  3. package/SKILL.md +301 -0
  4. package/agent-workspace/agent_helpers.py +718 -0
  5. package/bin/__pycache__/browser-workspacecpython-311.pyc +0 -0
  6. package/bin/browser-workspace +75 -0
  7. package/extension/manifest.json +26 -0
  8. package/extension/service-worker.mjs +126 -0
  9. package/extension/workspace-manager.mjs +680 -0
  10. package/extension/workspace-page.mjs +7 -0
  11. package/extension/workspace.html +8 -0
  12. package/interaction-skills/connection.md +52 -0
  13. package/interaction-skills/cookies.md +3 -0
  14. package/interaction-skills/cross-origin-iframes.md +3 -0
  15. package/interaction-skills/dialogs.md +64 -0
  16. package/interaction-skills/downloads.md +3 -0
  17. package/interaction-skills/drag-and-drop.md +3 -0
  18. package/interaction-skills/dropdowns.md +3 -0
  19. package/interaction-skills/iframes.md +3 -0
  20. package/interaction-skills/network-requests.md +3 -0
  21. package/interaction-skills/print-as-pdf.md +3 -0
  22. package/interaction-skills/profile-sync.md +90 -0
  23. package/interaction-skills/screenshots.md +17 -0
  24. package/interaction-skills/scrolling.md +22 -0
  25. package/interaction-skills/shadow-dom.md +3 -0
  26. package/interaction-skills/tabs.md +73 -0
  27. package/interaction-skills/uploads.md +1 -0
  28. package/interaction-skills/viewport.md +16 -0
  29. package/licenses/browser-harness-MIT.txt +21 -0
  30. package/managed_chrome.py +244 -0
  31. package/node/admin.mjs +44 -0
  32. package/package.json +36 -0
  33. package/platform_runner.py +187 -0
  34. package/platforms/chatgpt/README.md +60 -0
  35. package/platforms/chatgpt/actions/_bootstrap_start.py +58 -0
  36. package/platforms/chatgpt/actions/_lifecycle_common.py +119 -0
  37. package/platforms/chatgpt/actions/_mcp_app.py +80 -0
  38. package/platforms/chatgpt/actions/_new_thread.py +85 -0
  39. package/platforms/chatgpt/actions/_new_turn.py +33 -0
  40. package/platforms/chatgpt/actions/_project_setup.py +353 -0
  41. package/platforms/chatgpt/actions/_readiness.py +52 -0
  42. package/platforms/chatgpt/actions/_submit_thread.py +129 -0
  43. package/platforms/chatgpt/actions/_temporary_submit.py +571 -0
  44. package/platforms/chatgpt/actions/_thread_turn.py +362 -0
  45. package/platforms/chatgpt/manifest.yaml +34 -0
  46. package/platforms/chatgpt/tests/test_contract.py +176 -0
  47. package/platforms/chrome-web-store/README.md +49 -0
  48. package/platforms/chrome-web-store/actions/_chrome_web_store.py +425 -0
  49. package/platforms/chrome-web-store/flows/check-status.md +7 -0
  50. package/platforms/chrome-web-store/flows/open-item.md +10 -0
  51. package/platforms/chrome-web-store/flows/submit-review.md +10 -0
  52. package/platforms/chrome-web-store/flows/update-listing.md +18 -0
  53. package/platforms/chrome-web-store/flows/upload-package.md +11 -0
  54. package/platforms/chrome-web-store/flows/verify-published.md +9 -0
  55. package/platforms/chrome-web-store/manifest.yaml +33 -0
  56. package/platforms/chrome-web-store/tests/test_contract.py +83 -0
  57. package/platforms/microsoft-teams/README.md +32 -0
  58. package/platforms/microsoft-teams/actions/_meeting.py +210 -0
  59. package/platforms/microsoft-teams/flows/instant-meeting.md +21 -0
  60. package/platforms/microsoft-teams/manifest.yaml +25 -0
  61. package/platforms/microsoft-teams/tests/test_contract.py +24 -0
  62. package/platforms/tiktok/README.md +10 -0
  63. package/platforms/tiktok/actions/_post.py +180 -0
  64. package/platforms/tiktok/manifest.yaml +99 -0
  65. package/platforms/wechat-channels/README.md +10 -0
  66. package/platforms/wechat-channels/actions/_common.py +163 -0
  67. package/platforms/wechat-channels/actions/_manage.py +130 -0
  68. package/platforms/wechat-channels/actions/_post.py +232 -0
  69. package/platforms/wechat-channels/manifest.yaml +118 -0
  70. package/platforms/wechat-channels/tests/test_contract.py +36 -0
  71. package/platforms/xhs/README.md +10 -0
  72. package/platforms/xhs/actions/_manage.py +355 -0
  73. package/platforms/xhs/actions/_post.py +192 -0
  74. package/platforms/xhs/manifest.yaml +98 -0
  75. package/platforms/youtube/README.md +10 -0
  76. package/platforms/youtube/actions/_post.py +100 -0
  77. package/platforms/youtube/manifest.yaml +94 -0
  78. package/pyproject.toml +29 -0
  79. package/session_client.py +97 -0
  80. package/session_daemon.py +325 -0
  81. package/src/browser_harness/__init__.py +2 -0
  82. package/src/browser_harness/__pycache__/__init__.cpython-311.pyc +0 -0
  83. package/src/browser_harness/__pycache__/_ipc.cpython-311.pyc +0 -0
  84. package/src/browser_harness/__pycache__/admin.cpython-311.pyc +0 -0
  85. package/src/browser_harness/__pycache__/auth.cpython-311.pyc +0 -0
  86. package/src/browser_harness/__pycache__/daemon.cpython-311.pyc +0 -0
  87. package/src/browser_harness/__pycache__/helpers.cpython-311.pyc +0 -0
  88. package/src/browser_harness/__pycache__/paths.cpython-311.pyc +0 -0
  89. package/src/browser_harness/__pycache__/recorder.cpython-311.pyc +0 -0
  90. package/src/browser_harness/_ipc.py +201 -0
  91. package/src/browser_harness/admin.py +1588 -0
  92. package/src/browser_harness/auth.py +546 -0
  93. package/src/browser_harness/daemon.py +894 -0
  94. package/src/browser_harness/helpers.py +668 -0
  95. package/src/browser_harness/macos.py +131 -0
  96. package/src/browser_harness/mcp_cli.py +16 -0
  97. package/src/browser_harness/paths.py +49 -0
  98. package/src/browser_harness/recorder.py +343 -0
  99. package/src/browser_harness/run.py +413 -0
  100. package/src/browser_harness/telemetry.py +308 -0
  101. package/src/browser_harness/video-template.html +970 -0
  102. package/src/browser_harness/video.py +749 -0
  103. package/src/browser_harness/video_render.py +524 -0
  104. package/src/browser_workspace.egg-info/PKG-INFO +10 -0
  105. package/src/browser_workspace.egg-info/SOURCES.txt +28 -0
  106. package/src/browser_workspace.egg-info/dependency_links.txt +1 -0
  107. package/src/browser_workspace.egg-info/requires.txt +5 -0
  108. package/src/browser_workspace.egg-info/top_level.txt +1 -0
package/PRIVACY.md ADDED
@@ -0,0 +1,21 @@
1
+ # Browser Workspace Privacy Policy
2
+
3
+ Browser Workspace is a Chrome extension that manages named tab-group workspaces and reusable tab pools inside the user's browser.
4
+
5
+ ## Data handling
6
+
7
+ Browser Workspace does not send, sell, share, or transfer user data to the developer or to third parties.
8
+
9
+ The extension uses Chrome's local extension storage only to keep workspace configuration and local lease metadata needed to restore and manage workspaces. This information stays in the user's browser profile.
10
+
11
+ The extension may read tab identifiers, URLs, tab-group membership, navigation-target relationships, and related browser state only as needed to create, group, navigate, reuse, release, or reclaim workspace tabs. This information is processed locally and is not transmitted to an external service.
12
+
13
+ Browser Workspace does not collect personally identifiable information, authentication information, financial information, health information, personal communications, location data, website content, or user activity for external storage or analytics.
14
+
15
+ ## Remote code
16
+
17
+ Browser Workspace does not execute remote JavaScript or WebAssembly. All extension code is packaged with the extension.
18
+
19
+ ## Contact
20
+
21
+ Questions about this privacy policy may be submitted through the Browser Workspace GitHub repository.
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # Browser Workspace
2
+
3
+ Browser Workspace is a single browser automation skill and CLI built around persistent Python sessions, workspace-owned Chrome tabs, compact snapshot refs, and built-in platform workflows.
4
+
5
+ ## Public interface
6
+
7
+ The CLI has two public execution paths:
8
+
9
+ ```bash
10
+ # Known platform action: runner owns start/stop.
11
+ browser-workspace platform run PLATFORM ACTION [--config FILE] [--url URL]
12
+
13
+ # Custom browser workflow: caller owns lifecycle.
14
+ browser-workspace session start [--url URL]
15
+ browser-workspace session exec SESSION_ID <<'PY'
16
+ print(snapshot())
17
+ PY
18
+ browser-workspace session stop SESSION_ID
19
+ ```
20
+
21
+ `--workspace` is hidden from normal CLI help. Normal sessions use `Harness`; product integrations may set an explicit workspace internally when they require isolation.
22
+
23
+ `session stop` closes all tabs created/owned by that session while leaving unrelated browser tabs untouched.
24
+
25
+ ## Included layers
26
+
27
+ ```text
28
+ browser-workspace
29
+ ├── src/browser_harness/ low-level browser/CDP runtime (forked internally)
30
+ ├── agent-workspace/ Browser Workspace helper layer
31
+ ├── extension/ Chrome workspace/tab manager
32
+ ├── session_daemon.py persistent Python session service
33
+ ├── platforms/ site/domain actions + verification metadata
34
+ ├── interaction-skills/ browser interaction references
35
+ └── SKILL.md single agent-facing skill contract
36
+ ```
37
+
38
+ Agents should load only the Browser Workspace skill. `browser-harness` and `browser-platforms` are no longer separate runtime/skill dependencies.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ ./scripts/install.sh
44
+ ```
45
+
46
+ The installer creates the skill-owned `.venv` and links `browser-workspace` to `~/.local/bin` by default.
47
+
48
+ By default Browser Workspace owns exactly one machine-wide persistent, visible Chrome instance. Every session and runtime reuses that same Browser Workspace Chrome; config/runtime overrides never create another Chrome. It uses a Browser Workspace-managed user-data directory, prefers CDP port 9222, and selects the next available candidate only when starting the singleton for the first time. Users do not manage Chrome profiles or remote-debugging settings. Chrome Stable no longer permits silent `--load-extension` for local unpacked extensions, so the extension is treated as an optional workspace-grouping enhancement rather than a prerequisite for browser sessions.
49
+
50
+ `BU_CDP_URL` / `BU_CDP_WS` remain advanced overrides for callers that intentionally provide their own browser endpoint. `BROWSER_WORKSPACE_CDP_PORT` changes the preferred managed port.
51
+
52
+ The Web Store build remains available for ordinary interactive Chrome installs, but the managed runtime does not depend on it: `https://chromewebstore.google.com/detail/kgbghhigmbpefppgkocgjgnnnbhjchic`.
53
+
54
+ ## Snapshot model
55
+
56
+ `snapshot()` uses Chrome's accessibility tree to identify useful controls/content, annotates the corresponding live DOM elements with `data-ref="eN"`, and emits a compact representation. Interact using normal CSS selectors:
57
+
58
+ ```python
59
+ print(snapshot())
60
+ click('[data-ref="e2"]')
61
+ fill_input('[data-ref="e3"]', 'hello')
62
+ ```
63
+
64
+ There is no separate ref registry.
65
+
66
+ ## Upstream
67
+
68
+ The internal browser-control core is forked from `browser-use/browser-harness`. Its license is retained in `licenses/browser-harness-MIT.txt`.
69
+
70
+
71
+
72
+ ## Product-owned workspaces
73
+
74
+ Normal browser automation uses the default `Harness` workspace. Ordinary agents manage browser sessions only; they do not create, resize, or delete workspaces. Workspace lifecycle belongs to product runtimes such as Agents Relay or NeoY.
75
+
76
+ Products discover the installed Browser Workspace instance with:
77
+
78
+ ```bash
79
+ browser-workspace status
80
+ ```
81
+
82
+ The command returns machine-readable JSON including the resolved installation `root`, absolute `admin_helper` path, and daemon status. Calling `status` also ensures the existing Browser Workspace session daemon is ready; it does not create a separate service.
83
+
84
+ A Node.js product can then load the product-only helper without depending on the `browser-workspace` npm package or hardcoding an install path:
85
+
86
+ ```js
87
+ import { execFileSync } from "node:child_process";
88
+ import { pathToFileURL } from "node:url";
89
+
90
+ const status = JSON.parse(
91
+ execFileSync("browser-workspace", ["status"], { encoding: "utf8" })
92
+ );
93
+ const { ensureWorkspace, deleteWorkspace } =
94
+ await import(pathToFileURL(status.admin_helper).href);
95
+
96
+ await ensureWorkspace("Relay", 6);
97
+ // later, if the product owns and no longer needs it:
98
+ await deleteWorkspace("Relay", { force: true });
99
+ ```
100
+
101
+ `ensureWorkspace(name, size)` is idempotent: it creates a missing workspace, keeps one with the same capacity, and reconfigures an existing workspace when the requested size changes. The physical tab pool still grows lazily up to that capacity. `deleteWorkspace(name, { force })` removes the workspace through the existing daemon/extension RPC path.
102
+
103
+ There is intentionally no `browser-workspace workspace create/delete` CLI. Workspace lifecycle is a product API, not an agent command.
104
+
105
+ ### Start a session in a product-owned workspace
106
+
107
+ `--workspace` remains an internal integration option for product code:
108
+
109
+ ```bash
110
+ browser-workspace session start --workspace "Relay" --url https://example.com
111
+ ```
112
+
113
+ It is hidden from normal CLI help. Product code owns the workspace choice; platform actions remain unaware of workspace/session policy.
114
+
115
+ Recommended product lifecycle:
116
+
117
+ ```text
118
+ product startup
119
+ -> browser-workspace status
120
+ -> import status.admin_helper
121
+ -> ensureWorkspace("Relay", 6)
122
+
123
+ browser task
124
+ -> browser-workspace session start --workspace "Relay"
125
+ -> browser-workspace session exec <session_id>
126
+ -> browser-workspace session stop <session_id>
127
+ ```
128
+
129
+ ## Platform boundary
130
+
131
+ Platform action code is infrastructure-agnostic. It may use browser helpers, but it must not create/stop Browser Workspace sessions, choose workspaces, or import session/workspace infrastructure. The generic platform runner wraps actions in a default Harness session and always cleans up. Product code may execute the same action in a product-owned browser context when longer-lived isolation is required.
132
+
133
+ Each platform manifest records explicit verification status and evidence. `verified` means live-site verification; migrated code is labeled `migrated_unverified` until exercised in the current integration.
134
+
135
+
136
+ ## npx skills installation
137
+
138
+ After `npx skills add ...`, invoke `~/.agents/skills/browser-workspace/bin/browser-workspace` directly. The first session start bootstraps the skill-owned Python virtual environment automatically; running `scripts/install.sh` is optional.
package/SKILL.md ADDED
@@ -0,0 +1,301 @@
1
+ ---
2
+ name: browser-workspace
3
+ description: Control the real browser through one Browser Workspace skill and CLI, with leased tab workspaces, persistent Python sessions, compact snapshots, and built-in platform workflows.
4
+ ---
5
+
6
+ # Browser Workspace
7
+
8
+ Browser Workspace is the **only browser skill agents should load**. It includes the browser-control runtime, workspace/tab leasing, persistent Python sessions, snapshot refs, and site-specific platform workflows. Do not load or invoke a separate `browser-harness` or `browser-platforms` skill.
9
+
10
+ ## Agent contract
11
+
12
+ When installed with `npx skills`, use the CLI from the skill itself; no separate install step is required:
13
+
14
+ ```bash
15
+ BW_CLI="$HOME/.agents/skills/browser-workspace/bin/browser-workspace"
16
+ $BW_CLI status
17
+ ```
18
+
19
+ On first use, Browser Workspace bootstraps its own `.venv` automatically.
20
+
21
+ Use one of two execution paths:
22
+
23
+ ```text
24
+ known platform flow
25
+ -> $BW_CLI platform run <platform> <action> [--config FILE]
26
+ -> runner creates the browser session
27
+ -> runner executes the platform action
28
+ -> runner always stops and cleans up
29
+
30
+ custom browser workflow
31
+ -> $BW_CLI session start
32
+ -> $BW_CLI session exec <session_id>
33
+ -> $BW_CLI session stop <session_id>
34
+ ```
35
+
36
+ Do not manually create a session around a platform action unless product code intentionally owns a longer-lived browser context. There are no separate top-level `open`, `tabs`, `status`, or `screenshot` commands.
37
+
38
+ Every logical browser workflow must follow:
39
+
40
+ ```text
41
+ start
42
+ -> exec
43
+ -> exec
44
+ -> ...
45
+ finally
46
+ -> stop
47
+ ```
48
+
49
+ Rules:
50
+
51
+ - Start one session per logical browser workflow and retain its `session_id`.
52
+ - Reuse that same session for every action/observation turn.
53
+ - Always stop the session in cleanup/finally, including on failure or cancellation.
54
+ - A session owns one leased browser tab and a persistent Python namespace.
55
+ - Multiple independent workflows may use different sessions concurrently.
56
+
57
+ ## Start
58
+
59
+ Default workspace is `Harness`:
60
+
61
+ ```bash
62
+ $BW_CLI session start
63
+ ```
64
+
65
+ Normal agents do not choose or manage workspaces. `session start` defaults to `Harness`; the `--workspace` implementation option is hidden from normal CLI help. Workspace lifecycle is not exposed through the agent CLI. Product runtimes that need persistent isolation discover the product-only Node admin helper with `browser-workspace status`, then call `ensureWorkspace` / `deleteWorkspace` through that helper.
66
+
67
+ Start directly at a URL when known:
68
+
69
+ ```bash
70
+ $BW_CLI session start --url https://example.com
71
+ ```
72
+
73
+ The result is JSON containing `session_id`, `workspace`, `target_id`, the starting `url`, and `workspace_supported`.
74
+
75
+ Browser Workspace self-manages exactly one machine-wide persistent, visible Chrome instance. Every session and runtime must reuse that singleton. Runtime/config overrides must never create another Chrome. Browser Workspace owns the user-data directory and local CDP endpoint, prefers port 9222, and selects another candidate only when starting the singleton for the first time. Agents do not choose a Chrome profile or enable remote debugging. The Chrome workspace extension remains optional: Chrome Stable blocks silent local unpacked-extension loading, so sessions continue in plain-browser mode when the extension is absent; grouping/lease isolation becomes available when the extension is installed.
76
+
77
+ ## Exec
78
+
79
+ `session exec` reads Python from stdin. Helpers are already imported; do not import another browser package.
80
+
81
+ ```bash
82
+ $BW_CLI session exec <session_id> <<'PY'
83
+ print(page_info())
84
+ print(snapshot())
85
+ PY
86
+ ```
87
+
88
+ Python state persists across later calls in the same session:
89
+
90
+ ```bash
91
+ $BW_CLI session exec <session_id> <<'PY'
92
+ meeting_name = "Demo"
93
+ print(current_tab())
94
+ PY
95
+ ```
96
+
97
+ Then later:
98
+
99
+ ```bash
100
+ $BW_CLI session exec <session_id> <<'PY'
101
+ print(meeting_name)
102
+ PY
103
+ ```
104
+
105
+ A Python file may also be used with `--code-file`.
106
+
107
+ ## Stop
108
+
109
+ ```bash
110
+ $BW_CLI session stop <session_id>
111
+ ```
112
+
113
+ Stopping closes every tab owned or opened by that session—including tabs created with `new_tab()`, `bh.new_tab()`, direct `Target.createTarget`, and detected child/popup tabs—then destroys the session's Python namespace. It does not close unrelated browser tabs. Do not reuse the ID afterward.
114
+
115
+ A safe shell structure is:
116
+
117
+ ```bash
118
+ SESSION_JSON=$($BW_CLI session start)
119
+ SESSION_ID=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["session_id"])' "$SESSION_JSON")
120
+ trap '$BW_CLI session stop "$SESSION_ID" >/dev/null 2>&1 || true' EXIT
121
+
122
+ $BW_CLI session exec "$SESSION_ID" <<'PY'
123
+ print(snapshot())
124
+ PY
125
+ ```
126
+
127
+ ## Browser helpers
128
+
129
+ The session exposes the browser primitives directly, including:
130
+
131
+ ```python
132
+ page_info()
133
+ goto_url(url)
134
+ current_tab()
135
+ new_tab(url)
136
+ close_tab(...)
137
+ js(expression, target_id=None)
138
+ cdp(method, ...)
139
+ wait_for_load()
140
+ wait_for_element(...)
141
+ fill_input(selector, text)
142
+ click(selector)
143
+ capture_screenshot(...)
144
+ ```
145
+
146
+ Use the higher-level helpers first. Use raw `js(...)`/`cdp(...)` only when needed.
147
+
148
+ Interaction-specific reference material is bundled under `interaction-skills/` inside this skill.
149
+
150
+ ## Snapshot refs
151
+
152
+ `snapshot()` returns a compact accessibility-oriented view and writes each returned ref directly onto the corresponding live DOM element as `data-ref="eN"`.
153
+
154
+ Example:
155
+
156
+ ```text
157
+ - button "Calendar" [ref=e1]
158
+ - button "Meet now" [ref=e2]
159
+ - textbox "Meeting name" [ref=e3]
160
+ ```
161
+
162
+ The live DOM then contains equivalent annotations such as:
163
+
164
+ ```html
165
+ <button data-ref="e2">Meet now</button>
166
+ ```
167
+
168
+ Refs are ordinary CSS selectors. Use normal helpers:
169
+
170
+ ```python
171
+ print(snapshot())
172
+ click('[data-ref="e2"]')
173
+ fill_input('[data-ref="e3"]', 'Demo meeting')
174
+ ```
175
+
176
+ Do **not** invent `click("e2")`, `click_ref("e2")`, or an `@e2` API. After navigation or a substantial DOM update, call `snapshot()` again and use the new refs.
177
+
178
+ `snapshot(interactive_only=False)` may include named content roles in addition to interactive elements. `target_id=` may be used for target-specific inspection.
179
+
180
+ ## Workspaces
181
+
182
+ Default configuration:
183
+
184
+ ```text
185
+ BH_WORKSPACE_NAME=Harness
186
+ BH_WORKSPACE_POOL_SIZE=5
187
+ ```
188
+
189
+ When the Browser Workspace Chrome extension is installed, the pool size is the maximum concurrent capacity; tabs are created lazily. The extension owns grouping, lease/release, idle reclaim, and workspace isolation.
190
+
191
+ Without the extension, browser sessions still work using the built-in browser core. Workspace names, grouping, pool capacity, lease isolation, and idle reclaim are unavailable; tab/navigation/input/snapshot/platform helpers continue to work. `workspace_status()` reports `supported: false` instead of failing.
192
+
193
+ Available workspace helpers include:
194
+
195
+ ```python
196
+ workspace_create("Research", 5)
197
+ workspace_status()
198
+ workspace_list()
199
+ workspace_resize("Research", 6)
200
+ workspace_delete("Research")
201
+ ```
202
+
203
+ Never use URL as tab identity. Workspace ownership and leased target identity are authoritative.
204
+
205
+ ## Platform contract
206
+
207
+ Known-site knowledge is bundled under `platforms/`. A platform contains **site/domain behavior only**.
208
+
209
+ ```text
210
+ platforms/<name>/
211
+ ├── README.md site behavior and rules
212
+ ├── manifest.yaml actions + verification metadata
213
+ ├── actions/ reusable browser action code
214
+ └── flows/ optional flow documentation
215
+ ```
216
+
217
+ Platform rules:
218
+
219
+ - Platform actions may use browser helpers such as `new_tab()`, `current_tab()`, `snapshot()`, `js()`, `cdp()`, uploads, downloads, and screenshots.
220
+ - Platform actions must **not** create/stop Browser Workspace sessions, choose a workspace, call workspace-management APIs, invoke the Browser Workspace CLI, or import session/workspace infrastructure.
221
+ - Platform `README.md` and flow docs should describe site behavior, preconditions, side effects, and verification evidence—not Browser Workspace lifecycle mechanics.
222
+ - Platform actions must remain usable in either a generic runner-owned session or a product-owned browser context.
223
+ - The generic runner owns the normal lifecycle: start a default Harness session, inject browser helpers/config, execute the action, then always stop the session and close its owned tabs.
224
+ - Products that require a dedicated or persistent browser context (for example Family Tutor or Agents Relay) may execute the same platform action inside product-owned infrastructure. The platform code itself stays unchanged.
225
+ - Do not rediscover a known site's mechanics when a verified platform flow/action already exists.
226
+
227
+ Run a platform action through the generic runner:
228
+
229
+ ```bash
230
+ $BW_CLI platform run microsoft-teams meeting --config /path/to/config.json
231
+ ```
232
+
233
+ The runner output hides the raw session ID. It returns the platform/action result, optional workspace-extension warning, and cleanup evidence.
234
+
235
+ ### Platform verification contract
236
+
237
+ Every `platforms/<name>/manifest.yaml` must declare:
238
+
239
+ Platform-owned publishing facts belong in the same manifest, not in caller-specific tables. When applicable, declare `media`, `fields`, `capabilities`, `content_mapping`, and platform notes there. Callers inspect them with `browser-workspace platform profile <name>` and must not maintain a second authoritative limits/capabilities registry.
240
+
241
+ ```text
242
+ platform:
243
+ status:
244
+ last_verified:
245
+ actions:
246
+ verification:
247
+ status:
248
+ last_verified:
249
+ evidence:
250
+ ```
251
+
252
+ Verification rules:
253
+
254
+ - `verified`: exercised against the live site and supported by concrete evidence.
255
+ - `partially_verified`: some declared flows are live-verified while others remain implemented but unverified.
256
+ - `migrated_unverified`: code was migrated from a previously working adapter but has not yet been live-verified in the current Browser Workspace integration.
257
+ - Never upgrade a status merely because code compiles or contract tests pass.
258
+ - Flow-level verification in `manifest.yaml` should be more specific than the platform-wide status.
259
+ - When live behavior changes, update `last_verified`, evidence, and affected flow status in the same change.
260
+
261
+ Current bundled platforms:
262
+
263
+ ```text
264
+ platforms/chatgpt/
265
+ platforms/chrome-web-store/
266
+ platforms/microsoft-teams/
267
+ platforms/tiktok/
268
+ platforms/wechat-channels/
269
+ platforms/xhs/
270
+ platforms/youtube/
271
+ ```
272
+
273
+ Read the matching platform `README.md` and `manifest.yaml` before invoking or modifying a known flow. The platform README is documentation owned by this root Browser Workspace skill; it is not a separately loadable skill.
274
+
275
+ ## Installation
276
+
277
+ Run the bundled installer from the skill directory:
278
+
279
+ ```bash
280
+ ./scripts/install.sh
281
+ ```
282
+
283
+ It creates a Browser Workspace-owned `.venv`, installs the vendored browser runtime and dependencies, writes Browser Workspace environment configuration to `agent-workspace/.env`, and links `browser-workspace` into `~/.local/bin` by default.
284
+
285
+ There is no required separate Browser Harness installation.
286
+
287
+ The Chrome extension is recommended but not required. Without it Browser Workspace runs in plain-browser mode and `session start` provides the installation link. The public Web Store URL is:
288
+
289
+ ```text
290
+ https://chromewebstore.google.com/detail/kgbghhigmbpefppgkocgjgnnnbhjchic
291
+ ```
292
+
293
+ The extension is also bundled at `extension/` for unpacked/development installs. Default extension ID:
294
+
295
+ ```text
296
+ kgbghhigmbpefppgkocgjgnnnbhjchic
297
+ ```
298
+
299
+ ## Internal provenance
300
+
301
+ The low-level browser runtime is forked from `browser-use/browser-harness` and kept internally under `src/browser_harness/`. Browser Workspace is the public product/skill/CLI surface. Upstream licensing is preserved under `licenses/`.