Skip to content

Commit 5428321

Browse files
committed
refactor(browser): replace workspaces with sessions
1 parent b56bebd commit 5428321

50 files changed

Lines changed: 1182 additions & 1308 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### ⚠ BREAKING CHANGES
6+
7+
* **browser session model** — replace the browser-facing `--workspace` model with explicit `--session <name>` on `opencli browser *`. Browser commands now require a session name, `browser bind`/`unbind` use `--session`, and bind no longer accepts `--domain`, `--path-prefix`, or `--allow-navigate-bound`. Browser primitives keep their session tab by design; the browser namespace no longer exposes `--keep-tab`. Adapter `--keep-tab` and `browserSession.reuse: 'site'` are unchanged.
8+
9+
### Internal
10+
11+
* **extension 1.0.11** — switch Browser Bridge lease routing from user-facing workspaces to explicit browser sessions.
12+
313
## [1.7.16](https://github.com/jackwener/opencli/compare/v1.7.15...v1.7.16) (2026-05-11)
414

515
Extension bumped to 1.0.10 (rename adapter-owned tab group `OpenCLI Automation``OpenCLI Adapter`). Performance and stability sweep across browser-backed adapters; new external CLI integrations (tg-cli, discord-cli, wx-cli).

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,15 @@ The agent handles all the `opencli browser` commands internally — you just des
152152

153153
Available browser commands include `open`, `state`, `click`, `type`, `fill`, `select`, `keys`, `wait`, `get`, `find`, `extract`, `frames`, `screenshot`, `scroll`, `back`, `eval`, `network`, `tab list`, `tab new`, `tab select`, `tab close`, `init`, `verify`, and `close`.
154154

155-
`opencli browser open <url>` and `opencli browser tab new [url]` both return a target ID. Use `opencli browser tab list` to inspect the target IDs of tabs that already exist, then pass `--tab <targetId>` to route a command to a specific tab. `tab new` creates a new tab without changing the default browser target; only `tab select <targetId>` promotes that tab to the default target for later untargeted `opencli browser ...` commands.
155+
`opencli browser` commands require `--session <name>`. `opencli browser --session work open <url>` and `opencli browser --session work tab new [url]` both return a target ID. Use `opencli browser --session work tab list` to inspect target IDs, then pass `--tab <targetId>` to route a command to a specific tab. `tab new` creates a new tab without changing the default browser target; only `tab select <targetId>` promotes that tab to the default target for later untargeted commands in the same session.
156156

157157
## Core Concepts
158158

159159
### `browser`: AI Agent browser control
160160

161161
`opencli browser` commands are the low-level primitives that AI Agents use to operate websites. You don't run these manually — instead, install the `opencli-adapter-author` skill into your AI agent, describe what you want in natural language, and the agent handles the browser operations.
162162

163-
For example, tell your agent: *"Help me check my Xiaohongshu notifications"* — the agent will use `opencli browser open`, `state`, `click`, etc. under the hood.
163+
For example, tell your agent: *"Help me check my Xiaohongshu notifications"* — the agent will use `opencli browser --session <name> open`, `state`, `click`, etc. under the hood.
164164

165165
### Built-in adapters: stable commands
166166

@@ -174,7 +174,7 @@ When the site you need is not yet covered, use the `opencli-adapter-author` skil
174174
2. Discover the right endpoint — network inspection, initial state, bundle search, token trace, or interceptor fallback.
175175
3. Decide the auth strategy — `PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`.
176176
4. Decode response fields and design output columns.
177-
5. `opencli browser analyze <url>` for one-shot recon, then `opencli browser init <site>/<name>` → write adapter → `opencli browser verify <site>/<name>`.
177+
5. `opencli browser --session recon analyze <url>` for one-shot recon, then `opencli browser --session recon init <site>/<name>` → write adapter → `opencli browser --session recon verify <site>/<name>`.
178178
6. Persist site knowledge to `~/.opencli/sites/<site>/` so the next adapter for the same site is faster.
179179

180180
### CLI Hub and desktop adapters
@@ -199,7 +199,7 @@ OpenCLI is not only for websites. It can also:
199199
| `OPENCLI_DAEMON_PORT` | `19825` | HTTP port for the daemon-extension bridge |
200200
| `OPENCLI_PROFILE` || Browser Bridge profile alias/contextId to use when multiple Chrome profiles are connected |
201201
| `OPENCLI_WINDOW` | command default | Set to `foreground` or `background` to override Browser Bridge window placement. Browser-backed commands also accept `--window <foreground\|background>`. |
202-
| `OPENCLI_KEEP_TAB` | command default | Set to `true` or `false` to keep or release the browser tab lease after a browser-backed command. Browser-backed commands also accept `--keep-tab <true\|false>`. |
202+
| `OPENCLI_KEEP_TAB` | command default | Set to `true` or `false` to keep or release the browser tab lease after a browser-backed adapter command. Browser-backed adapter commands also accept `--keep-tab <true\|false>`. |
203203
| `OPENCLI_BROWSER_REUSE` | adapter default | Set to `none` or `site` to override adapter browser tab reuse. The `--reuse <none\|site>` flag sets this. |
204204
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | Seconds to wait for browser connection |
205205
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | Seconds to wait for a single browser command |
@@ -208,7 +208,7 @@ OpenCLI is not only for websites. It can also:
208208
| `OPENCLI_VERBOSE` | `false` | Enable verbose logging (`-v` flag also works) |
209209
| `DEBUG_SNAPSHOT` || Set to `1` for DOM snapshot debug output |
210210

211-
`opencli browser *` uses a foreground browser window and keeps its tab lease by default. Browser-backed adapters use a background automation window and release one-shot tab leases by default. Some interactive adapters default to `--reuse site`, which also keeps the site tab lease; pass `--reuse none` for a one-shot tab.
211+
`opencli browser *` requires an explicit `--session <name>`, uses a foreground browser window by default, and keeps that session's tab lease until `browser --session <name> close` or idle cleanup. Browser-backed adapters use a background adapter window and release one-shot tab leases by default. Some interactive adapters default to `--reuse site`, which keeps the site tab lease for continuity; pass `--reuse none` for a one-shot tab.
212212

213213
## Update
214214

@@ -409,10 +409,10 @@ See [Plugins Guide](./docs/guide/plugins.md) for creating your own plugin.
409409
Before writing any adapter code, read the [`opencli-adapter-author` skill](./skills/opencli-adapter-author/SKILL.md). It takes you end-to-end:
410410

411411
- Recon the site and pick a pattern (SPA / SSR / JSONP / Token / Streaming).
412-
- Discover the right endpoint via `opencli browser network`, `eval`, or the interceptor fallback.
412+
- Discover the right endpoint via `opencli browser --session <name> network`, `eval`, or the interceptor fallback.
413413
- Decide auth strategy (`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`).
414-
- Run `opencli browser analyze <url>` for one-shot recon, decode response fields, design columns, scaffold with `opencli browser init`.
415-
- Verify with `opencli browser verify <site>/<name>` before shipping.
414+
- Run `opencli browser --session recon analyze <url>` for one-shot recon, decode response fields, design columns, scaffold with `opencli browser --session recon init`.
415+
- Verify with `opencli browser --session recon verify <site>/<name>` before shipping.
416416

417417
For long-lived personal commands that should live in your own Git repo, use a local plugin instead; see [Extending OpenCLI](./docs/guide/extending-opencli.md). Quick private adapters can still live at `~/.opencli/clis/<site>/<name>.js`. Site knowledge (endpoints, field maps, fixtures) accumulates in `~/.opencli/sites/<site>/` so the next adapter for the same site starts from context instead of zero.
418418

README.zh-CN.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,15 @@ Agent 在内部自动处理所有 `opencli browser` 命令——你只需用自
136136

137137
`browser` 可用命令包括:`open``state``click``type``fill``select``keys``wait``get``find``extract``frames``screenshot``scroll``back``eval``network``tab list``tab new``tab select``tab close``init``verify``close`
138138

139-
`opencli browser open <url>``opencli browser tab new [url]` 都会返回 target ID。`opencli browser tab list` 用来查看当前已存在 tab 的 target ID,再通过 `--tab <targetId>` 把命令明确路由到某个 tab。`tab new` 只会新建 tab,不会改变默认浏览器目标;只有显式执行 `tab select <targetId>`,才会把该 tab 设为后续未指定 target 的 `opencli browser ...` 命令的默认目标
139+
`opencli browser` 命令必须显式传 `--session <name>``opencli browser --session work open <url>``opencli browser --session work tab new [url]` 都会返回 target ID。`opencli browser --session work tab list` 用来查看当前已存在 tab 的 target ID,再通过 `--tab <targetId>` 把命令明确路由到某个 tab。`tab new` 只会新建 tab,不会改变默认浏览器目标;只有显式执行 `tab select <targetId>`,才会把该 tab 设为同一 session 后续未指定 target 的默认目标
140140

141141
## 核心概念
142142

143143
### `browser`:AI Agent 的浏览器控制层
144144

145145
`opencli browser` 命令是 AI Agent 操作网站的底层原语。你不需要手动运行这些命令——把 `opencli-adapter-author` skill 安装到你的 AI Agent 中,用自然语言描述你想做的事,Agent 会自动处理浏览器操作。
146146

147-
比如你告诉 Agent:*"帮我看看小红书的通知"*——Agent 会在底层调用 `opencli browser open``state``click` 等命令。
147+
比如你告诉 Agent:*"帮我看看小红书的通知"*——Agent 会在底层调用 `opencli browser --session <name> open``state``click` 等命令。
148148

149149
### 内置适配器:稳定命令
150150

@@ -158,7 +158,7 @@ Agent 在内部自动处理所有 `opencli browser` 命令——你只需用自
158158
2. 发现目标 endpoint——network 精读、initial state、bundle 搜索、token 溯源,或 interceptor 兜底
159159
3. 定认证策略——`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`
160160
4. 字段解码 + 设计输出列
161-
5. `opencli browser analyze <url>` 一步侦察,再 `opencli browser init <site>/<name>` → 写适配器 → `opencli browser verify <site>/<name>`
161+
5. `opencli browser --session recon analyze <url>` 一步侦察,再 `opencli browser --session recon init <site>/<name>` → 写适配器 → `opencli browser --session recon verify <site>/<name>`
162162
6. 把站点知识沉到 `~/.opencli/sites/<site>/`,下次写同站点的其他命令直接吃缓存
163163

164164
### CLI 枢纽与桌面端适配器
@@ -182,15 +182,15 @@ OpenCLI 不只是网站 CLI,还可以:
182182
|------|--------|------|
183183
| `OPENCLI_DAEMON_PORT` | `19825` | daemon-extension 通信端口 |
184184
| `OPENCLI_WINDOW` | 命令默认值 | 设为 `foreground``background` 来覆盖 Browser Bridge 窗口位置。浏览器型命令也支持 `--window <foreground\|background>` |
185-
| `OPENCLI_KEEP_TAB` | 命令默认值 | 设为 `true``false` 来控制浏览器型命令结束后是否保留 tab lease。浏览器型命令也支持 `--keep-tab <true\|false>` |
185+
| `OPENCLI_KEEP_TAB` | 命令默认值 | 设为 `true``false` 来控制浏览器型 adapter 命令结束后是否保留 tab lease。浏览器型 adapter 命令也支持 `--keep-tab <true\|false>` |
186186
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | 浏览器连接超时(秒) |
187187
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | 单个浏览器命令超时(秒) |
188188
| `OPENCLI_CDP_ENDPOINT` || Chrome DevTools Protocol 端点,用于远程浏览器或 Electron 应用 |
189189
| `OPENCLI_CDP_TARGET` || 按 URL 子串过滤 CDP target(如 `detail.1688.com`|
190190
| `OPENCLI_VERBOSE` | `false` | 启用详细日志(`-v` 也可以) |
191191
| `DEBUG_SNAPSHOT` || 设为 `1` 输出 DOM 快照调试信息 |
192192

193-
`opencli browser *` 默认使用前台窗口并保留 tab lease,直到你手动执行 `opencli browser close` 或等空闲超时。浏览器型 adapter 默认使用后台 automation 窗口并在命令结束后释放 tab lease;如果需要调试最终页面,可以传 `--window foreground --keep-tab true`
193+
`opencli browser *` 必须显式传 `--session <name>`,默认使用前台窗口,并保留该 session 的 tab lease,直到你手动执行 `opencli browser --session <name> close` 或等空闲超时。浏览器型 adapter 默认使用后台 adapter 窗口并在命令结束后释放一次性 tab lease;如果需要调试最终页面,可以传 `--window foreground --keep-tab true`
194194

195195
## 更新
196196

@@ -508,10 +508,10 @@ opencli plugin uninstall my-tool # 卸载
508508
在动代码前,先读 [`opencli-adapter-author` skill](./skills/opencli-adapter-author/SKILL.md)。它把整个流程串起来:
509509

510510
- 侦察站点,选定 pattern(SPA / SSR / JSONP / Token / Streaming)
511-
-`opencli browser network``eval`、interceptor 等找到目标 endpoint
511+
-`opencli browser --session <name> network``eval`、interceptor 等找到目标 endpoint
512512
- 定认证策略(`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`
513-
- 先用 `opencli browser analyze <url>` 一步侦察,再字段解码、设计 columns、`opencli browser init` 生成骨架
514-
- 交付前用 `opencli browser verify <site>/<name>` 验证
513+
- 先用 `opencli browser --session recon analyze <url>` 一步侦察,再字段解码、设计 columns、`opencli browser --session recon init` 生成骨架
514+
- 交付前用 `opencli browser --session recon verify <site>/<name>` 验证
515515

516516
在仓库外写的私有适配器放到 `~/.opencli/clis/<site>/<name>.js`;每个站点的 endpoint、字段映射、抓包样本会累积在 `~/.opencli/sites/<site>/`,下次写同站点的其他命令可以直接复用。
517517

cli-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15536,7 +15536,7 @@
1553615536
"aliases": [
1553715537
"select"
1553815538
],
15539-
"description": "Open one NotebookLM notebook in the automation workspace by id or URL",
15539+
"description": "Open one NotebookLM notebook in the adapter session by id or URL",
1554015540
"access": "read",
1554115541
"domain": "notebooklm.google.com",
1554215542
"strategy": "cookie",

clis/notebooklm/current.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ cli({
1717
await requireNotebooklmSession(page);
1818
const state = await getNotebooklmPageState(page);
1919
if (state.kind !== 'notebook') {
20-
throw new EmptyResultError('opencli notebooklm current', 'No NotebookLM notebook is open in the automation workspace. Run `opencli notebooklm open <notebook>` first.');
20+
throw new EmptyResultError('opencli notebooklm current', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
2121
}
2222
const current = await readCurrentNotebooklm(page);
2323
if (!current) {

clis/notebooklm/get.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ cli({
1818
await requireNotebooklmSession(page);
1919
const state = await getNotebooklmPageState(page);
2020
if (state.kind !== 'notebook') {
21-
throw new EmptyResultError('opencli notebooklm get', 'No NotebookLM notebook is open in the automation workspace. Run `opencli notebooklm open <notebook>` first.');
21+
throw new EmptyResultError('opencli notebooklm get', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
2222
}
2323
const rpcRow = await getNotebooklmDetailViaRpc(page).catch(() => null);
2424
if (rpcRow)

clis/notebooklm/history.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ cli({
1717
await requireNotebooklmSession(page);
1818
const state = await getNotebooklmPageState(page);
1919
if (state.kind !== 'notebook') {
20-
throw new EmptyResultError('opencli notebooklm history', 'No NotebookLM notebook is open in the automation workspace. Run `opencli notebooklm open <notebook>` first.');
20+
throw new EmptyResultError('opencli notebooklm history', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
2121
}
2222
const rows = await listNotebooklmHistoryViaRpc(page);
2323
return rows;

clis/notebooklm/note-list.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ cli({
1818
await requireNotebooklmSession(page);
1919
const state = await getNotebooklmPageState(page);
2020
if (state.kind !== 'notebook') {
21-
throw new EmptyResultError('opencli notebooklm note-list', 'No NotebookLM notebook is open in the automation workspace. Run `opencli notebooklm open <notebook>` first.');
21+
throw new EmptyResultError('opencli notebooklm note-list', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
2222
}
2323
const rows = await listNotebooklmNotesFromPage(page);
2424
if (rows.length > 0)

clis/notebooklm/notes-get.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ cli({
3131
await requireNotebooklmSession(page);
3232
const state = await getNotebooklmPageState(page);
3333
if (state.kind !== 'notebook') {
34-
throw new EmptyResultError('opencli notebooklm notes-get', 'No NotebookLM notebook is open in the automation workspace. Run `opencli notebooklm open <notebook>` first.');
34+
throw new EmptyResultError('opencli notebooklm notes-get', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
3535
}
3636
const query = typeof kwargs.note === 'string' ? kwargs.note : String(kwargs.note ?? '');
3737
const visible = await readNotebooklmVisibleNoteFromPage(page);

clis/notebooklm/open.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ cli({
77
name: 'open',
88
access: 'read',
99
aliases: ['select'],
10-
description: 'Open one NotebookLM notebook in the automation workspace by id or URL',
10+
description: 'Open one NotebookLM notebook in the adapter session by id or URL',
1111
domain: NOTEBOOKLM_DOMAIN,
1212
strategy: Strategy.COOKIE,
1313
browser: true,
@@ -28,7 +28,7 @@ cli({
2828
await requireNotebooklmSession(page);
2929
const state = await getNotebooklmPageState(page);
3030
if (state.kind !== 'notebook') {
31-
throw new CliError('NOTEBOOKLM_OPEN_FAILED', `NotebookLM notebook "${notebookId}" did not open in the automation workspace`, 'Run `opencli notebooklm list -f json` first and pass a valid notebook id.');
31+
throw new CliError('NOTEBOOKLM_OPEN_FAILED', `NotebookLM notebook "${notebookId}" did not open in the adapter session`, 'Run `opencli notebooklm list -f json` first and pass a valid notebook id.');
3232
}
3333
if (state.notebookId !== notebookId) {
3434
console.warn(`[notebooklm open] expected notebook "${notebookId}" but page reports "${state.notebookId}"; continuing`);

0 commit comments

Comments
 (0)