feat(browser): 新增 browser cookies 子命令,导出当前页 Cookie(含 HttpOnly)#1583
Open
riba2534 wants to merge 4 commits into
Open
feat(browser): 新增 browser cookies 子命令,导出当前页 Cookie(含 HttpOnly)#1583riba2534 wants to merge 4 commits into
browser cookies 子命令,导出当前页 Cookie(含 HttpOnly)#1583riba2534 wants to merge 4 commits into
Conversation
a0d085b to
4993395
Compare
Expose `page.getCookies()` as a top-level browser subcommand so agents
and adapters can read live browser cookies — including HttpOnly ones —
without depending on `playwright-cli cookie-list` or hand-rolled CDP
plumbing.
opencli browser <session> cookies [--domain <d>] [--url <u>]
Returns `{cookies, count}` where each cookie carries the full set of
fields the underlying transport exposes (name, value, domain, path,
secure, httpOnly, sameSite, expirationDate, session, plus CDP-only
size/priority/sourceScheme/sourcePort/sameParty/partitionKey).
CDP `Network.getCookies` reports the expiry as `expires`; the chrome
cookies extension API calls the same field `expirationDate`. We
normalize CDP records to the chrome.cookies shape so consumers don't
have to branch on transport. Session cookies (CDP `expires` <= 0)
omit `expirationDate` and surface `session: true` instead.
Why this exists: a recurring agent pattern is to log into a site once
in Chrome and then drive an external HTTP client (Python httpx, curl,
etc.) using the resulting session — typically for internal RPCs that
don't have a public API but do honor the web client's cookies. The
in-page `document.cookie` path can't see the session/SSO cookies that
make this work because they're HttpOnly. Both transports already in
opencli (CDP and the Chrome extension) can read HttpOnly cookies; this
PR just wires that capability through the CLI.
4993395 to
ef00e0d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这个 PR 解决了什么问题
OpenCLI 内部其实已经实现了完整的 cookie 读取能力——
page.getCookies()在 CDP(src/browser/cdp.ts)和 Chrome Extension(src/browser/page.ts)两个 transport 上都能拿到 cookie,包括 HttpOnly cookie。但这个能力今天没有暴露成 CLI 子命令,唯一的调用点是browser analyze内部用来给 site detection 取 cookie 名字(src/cli.ts:1186)。外部使用者(agent / 适配器作者 / 一次性脚本)想拿当前浏览器登录态的 cookie 时,要么去 fork 一份 daemon 协议自己调,要么换成 `playwright-cli cookie-list` 之类的外部依赖。本 PR 就是把已有的内核能力开出一条最薄的 CLI 通道。
命令形态
```bash
opencli browser cookies [--domain ] [--url ] [--tab ]
```
返回 JSON envelope:
```json
{
"cookies": [
{
"name": "session",
"value": "abc...",
"domain": ".larkoffice.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "None",
"expirationDate": 1781234567,
"session": false,
"size": 64,
"priority": "Medium",
"sourceScheme": "Secure",
"sourcePort": 443
}
],
"count": 1
}
```
这个能力的价值
最直接的应用场景是让 agent 复用已登录的浏览器 session 去驱动外部 HTTP 客户端。一个典型例子:
走 `opencli browser eval "document.cookie"` 不行——`document.cookie` 拿不到 HttpOnly cookie,而几乎所有正经站点的 session/SSO cookie 都是 HttpOnly(这是 OWASP 的安全最低线)。本 PR 的子命令绕开 `document.cookie` 限制,直接走 CDP `Network.getCookies` / chrome.cookies API,把这些登录态 cookie 完整导出。
落到具体使用模式:
```bash
1. 用户已在 Chrome 登录某站点,agent 把当前 tab 绑到 opencli session
opencli browser my bind
2. 一行拿到登录 cookie,喂给任何 HTTP 工具
opencli browser my cookies --domain example.com \
| jq -r '.cookies[] | "\(.name)=\(.value)"' \
| paste -sd '; ' - \
| xargs -I{} curl -H "Cookie: {}" https://example.com/api/...
或者 Python:
opencli browser my cookies --url https://example.com/api/foo > cookies.json
python -c "import json, httpx; jar = httpx.Cookies(); [jar.set(c['name'], c['value'], domain=c['domain'], path=c.get('path','/')) for c in json.load(open('cookies.json'))['cookies']]; print(httpx.get('https://example.com/api/foo', cookies=jar).text)"
```
这个模式之前依赖 `playwright-cli cookie-list`,但需要额外装 Playwright + MCP Bridge 扩展,且其输出格式 `name=value (domain: x, path: y)` 字段比 OpenCLI 这个新命令少(没有 secure / httpOnly / sameSite / expirationDate 等)。本 PR 让 OpenCLI 自身就具备这一能力,对已经在用 OpenCLI 的 agent 工作流是无依赖收益。
实现要点
src/types.ts— 扩展 `BrowserCookie` 类型,增加可选字段:`sameSite / session / size / priority / sourceScheme / sourcePort / hostOnly / storeId / sameParty / partitionKey`。纯加法、向后兼容。src/browser/cdp.ts— 把 `Network.getCookies` 的字段全部映射到 `BrowserCookie`,并把 CDP 字段名 `expires` 归一化为 `expirationDate`,与 chrome.cookies API 风格一致。这修复了一个早就存在的隐性不一致:CDP 路径之前从未真正返回过 `expirationDate`(因为 raw 字段叫 `expires`),但类型签名声明它会返回。Session cookies(`expires <= 0`)省略 `expirationDate`、并设 `session: true`。src/cli.ts— 在 `browser frames` 后面加 `browser cookies` 子命令,复用 `browserAction` 错误处理 wrapper 和 `addBrowserTabOption`。空字符串过滤值不下传,避免 CDP 把 `domain=""` 当字面量匹配返回零结果。src/browser/page.ts— Extension 实现没改,因为 `chrome.cookies.getAll` 原生返回的就是 `expirationDate` 风格,透传即可。测试
```
Test Files 363 passed (363)
Tests 3636 passed | 1 skipped (3637)
```
新增 5 个测试:
无 breaking change:
文档
`skills/opencli-browser/SKILL.md` 的 Inspect 命令表里加了 `browser cookies` 行,说明使用场景、过滤选项、HttpOnly 能力,以及和 `document.cookie` / `playwright-cli cookie-list` 的差异。
兼容性 / 风险