fix(web-access): use governed external browser open tool (#97)

## 中文

### 变更
- 将 web-access 升级到 v3.4.3,并声明 `BrowserExternalOpen`
- 外部浏览器的简单打开/导航固定为 `BrowserExternalProbe` → `BrowserExternalOpen`
- 仅把点击、动态取文、提取等高级交互交给隔离 Playwright
- 同步中英文 Skill、状态表、决策树和 CDP reference

### 验证
- `python scripts/i18n/validate-i18n.py`
- `python scripts/i18n/translate.py --check skills/web-access`
- `python -m unittest scripts/i18n/test_validate_i18n.py`
- `git diff --check`

## English

### Changes
- Bump web-access to v3.4.3 and expose `BrowserExternalOpen`
- Route simple external-browser open/navigation through
`BrowserExternalProbe` → `BrowserExternalOpen`
- Reserve isolated Playwright for advanced click, dynamic-read, and
extraction workflows
- Keep the English/Chinese skill, status table, decision tree, and CDP
reference aligned

### Verification
- `python scripts/i18n/validate-i18n.py`
- `python scripts/i18n/translate.py --check skills/web-access`
- `python -m unittest scripts/i18n/test_validate_i18n.py`
- `git diff --check`
This commit is contained in:
2026-08-29 07:53:59 -04:00
committed by GitHub
parent 7026cc72ed
commit 3059468526
4 changed files with 59 additions and 21 deletions

View File

@@ -15,7 +15,7 @@ description: >-
新闻、网址、URL、找一下、搜一下、查一下、小红书、B站、微博、飞书、Twitter、 新闻、网址、URL、找一下、搜一下、查一下、小红书、B站、微博、飞书、Twitter、
推特、X、知乎、公众号、已登录、登录状态。 推特、X、知乎、公众号、已登录、登录状态。
license: Complete terms in LICENSE.txt license: Complete terms in LICENSE.txt
version: 3.4.2 version: 3.4.3
type: procedural type: procedural
risk_level: low risk_level: low
status: enabled status: enabled
@@ -32,6 +32,7 @@ provides:
tools: tools:
- BrowserManage - BrowserManage
- BrowserExternalProbe - BrowserExternalProbe
- BrowserExternalOpen
- BrowserSnapshot - BrowserSnapshot
- BrowserAct - BrowserAct
- BrowserScript - BrowserScript
@@ -54,14 +55,14 @@ metadata:
short_desc: 联网搜索、网页抓取、内置受管浏览器登录态访问与取文、研究调研工作流 short_desc: 联网搜索、网页抓取、内置受管浏览器登录态访问与取文、研究调研工作流
description: 联网访问工具包——搜索公开页面、Jina 优化抓取、内置受管浏览器完成登录态访问与取文,以及用户点名时接管他自己的 Chrome/Edge/Chromium。 description: 联网访问工具包——搜索公开页面、Jina 优化抓取、内置受管浏览器完成登录态访问与取文,以及用户点名时接管他自己的 Chrome/Edge/Chromium。
body: ./SKILL.zh-CN.md body: ./SKILL.zh-CN.md
source_hash: sha256:b12669d544fe2c7e source_hash: sha256:78082a20359f730f
translated_by: human translated_by: human
en-US: en-US:
name: Web Access name: Web Access
short_desc: Web search, page fetching, logged-in access via the governed built-in browser, research workflows short_desc: Web search, page fetching, logged-in access via the governed built-in browser, research workflows
description: A web-access toolkit — search public pages, fetch heavy pages via Jina Reader, reach and read logged-in sites through the governed built-in browser, and drive the user's named Chrome/Edge/Chromium over CDP on request. description: A web-access toolkit — search public pages, fetch heavy pages via Jina Reader, reach and read logged-in sites through the governed built-in browser, and drive the user's named Chrome/Edge/Chromium over CDP on request.
body: ./SKILL.md body: ./SKILL.md
source_hash: sha256:b12669d544fe2c7e source_hash: sha256:78082a20359f730f
translated_by: human translated_by: human
market: market:
icon: >- icon: >-
@@ -102,18 +103,19 @@ web-access is a **procedural skill** that provides four complementary layers of
- **L2** (Jina Reader): JS-rendered heavy pages, saving tokens by default - **L2** (Jina Reader): JS-rendered heavy pages, saving tokens by default
- **L3** (governed built-in browser, capability surface completed in v3.0): reach, *interact with*, and **read** logged-in / interactive sites — isolated BrowserSpace per task, zero Python dependency, every action carries a signed receipt. Bulk text extraction (`page.extract-text`), discriminated waits (`page.wait`), and code mode (`BrowserScript`) all close the loop inside this layer - **L3** (governed built-in browser, capability surface completed in v3.0): reach, *interact with*, and **read** logged-in / interactive sites — isolated BrowserSpace per task, zero Python dependency, every action carries a signed receipt. Bulk text extraction (`page.extract-text`), discriminated waits (`page.wait`), and code mode (`BrowserScript`) all close the loop inside this layer
- **L3-external** (the user's named Chrome/Edge/Chromium, attached via CDP + Python Playwright): **take this route only when the user names their own browser or explicitly accepts it after you explain why**its isolated DesireCore profile login state, its visible window, and the user's ability to take over at any moment - **L3-external** (the user's named Chrome/Edge/Chromium, opened through governed CDP tools and attached via isolated Python Playwright only for advanced interaction): **take this route only when the user names their own browser or explicitly accepts it after you explain why**the login state the user established manually in the DesireCore-isolated external profile, the visible window, and the user's ability to take over at any moment
A note of history on L3-external: v3.0 deleted it outright, on the grounds that "every technical reason it existed for (no bulk text channel, evaluate unusable, screenshots must activate-serialize) is now covered by the built-in browser". That technical judgement was correct — **as a fallback for when the built-in browser isn't enough, it genuinely isn't needed any more**. But the deletion took with it a completely different use case: the user wanting *their own* browser. That has nothing to do with capability, and the built-in browser cannot stand in for it, so v3.2 restores it as a peer option **triggered by user intent**. Note it is no longer a fallback; see "Two browsers — pick by user intent" below. A note of history on L3-external: v3.0 deleted it outright, on the grounds that "every technical reason it existed for (no bulk text channel, evaluate unusable, screenshots must activate-serialize) is now covered by the built-in browser". That technical judgement was correct — **as a fallback for when the built-in browser isn't enough, it genuinely isn't needed any more**. But the deletion took with it a completely different use case: the user wanting *their own* browser. That has nothing to do with capability, and the built-in browser cannot stand in for it, so v3.2 restores it as a peer option **triggered by user intent**. Note it is no longer a fallback; see "Two browsers — pick by user intent" below.
### v3.0: governed built-in browser (default-hidden, exposed only after Skill activation) ### v3.0: governed built-in browser (default-hidden, exposed only after Skill activation)
When you call `Skill('web-access')`, the following tools are injected into the current session. The `Browser*` tools drive the built-in browser; `BrowserExternalProbe` only inspects external-browser prerequisites: When you call `Skill('web-access')`, the following tools are injected into the current session. Most `Browser*` tools drive the built-in browser; `BrowserExternalProbe` and `BrowserExternalOpen` are the explicitly named external-browser exceptions:
| Tool | Purpose | | Tool | Purpose |
|------|---------| |------|---------|
| BrowserManage | Create/destroy isolated BrowserSpace, start sessions, manage tabs | | BrowserManage | Create/destroy isolated BrowserSpace, start sessions, manage tabs |
| BrowserExternalProbe | Read-only check for installed Chrome/Edge/Chromium and loopback CDP readiness; never launches or reads a profile | | BrowserExternalProbe | Read-only check for installed Chrome/Edge/Chromium and loopback CDP readiness; never launches or reads a profile |
| BrowserExternalOpen | After `BrowserExternalProbe` returns `ready` in the same runtime session, visibly open one HTTP(S) URL in the exact external browser; no shell, Python, or Playwright |
| BrowserSnapshot | `semantic` / `text` / `accessibility` / `visual` snapshots — the primary way to read a page | | BrowserSnapshot | `semantic` / `text` / `accessibility` / `visual` snapshots — the primary way to read a page |
| BrowserAct | One governed action per call: navigate, input, extract text, wait, element ops, screenshot, … | | BrowserAct | One governed action per call: navigate, input, extract text, wait, element ops, screenshot, … |
| BrowserScript | **Code mode**: one async JS script issues browser commands back-to-back, eliminating per-action round trips (trust level equals Bash) | | BrowserScript | **Code mode**: one async JS script issues browser commands back-to-back, eliminating per-action round trips (trust level equals Bash) |
@@ -168,7 +170,7 @@ Handle the structured result exactly:
| status | Required response | | status | Required response |
|---|---| |---|---|
| `ready` | Continue with Playwright `connect_over_cdp`; name the detected external browser honestly. For `any`, the already-ready endpoint is the prepared choice even if other products are installed | | `ready` | For a simple open/navigation, call `BrowserExternalOpen` with the returned exact browser id and port. For advanced click/read/extract interaction, continue with isolated Playwright `connect_over_cdp`. Name the detected external browser honestly. For `any`, the already-ready endpoint is the prepared choice even if other products are installed |
| `browser_not_installed` | Say the requested browser was not detected. If `alternatives` is non-empty, ask whether the user wants one of them; **never switch automatically** | | `browser_not_installed` | Say the requested browser was not detected. If `alternatives` is non-empty, ask whether the user wants one of them; **never switch automatically** |
| `debug_port_closed` | Show the returned `launchCommand`, ask the user to launch it and log in manually, then wait and probe again | | `debug_port_closed` | Show the returned `launchCommand`, ask the user to launch it and log in manually, then wait and probe again |
| `browser_choice_required` | No endpoint is ready and multiple external browsers are installed. List id/name only and ask which one the user wants; probe that exact choice next | | `browser_choice_required` | No endpoint is ready and multiple external browsers are installed. List id/name only and ask which one the user wants; probe that exact choice next |
@@ -180,7 +182,7 @@ Handle the structured result exactly:
1. The user logs in manually to the sites they need. 1. The user logs in manually to the sites they need.
2. That external browser window stays open. 2. That external browser window stays open.
3. Call `BrowserExternalProbe` again. Only `ready` authorizes the CDP attach attempt. 3. Call `BrowserExternalProbe` again. Only `ready` authorizes `BrowserExternalOpen` or an advanced CDP attach attempt.
Do not replace this probe with `curl`: a refused connection cannot distinguish “browser not installed” Do not replace this probe with `curl`: a refused connection cannot distinguish “browser not installed”
from “browser installed but debugging disabled”, and a random HTTP service must not be accepted as CDP. from “browser installed but debugging disabled”, and a random HTTP service must not be accepted as CDP.
@@ -188,9 +190,21 @@ from “browser installed but debugging disabled”, and a random HTTP service m
⚠️ When attached over CDP, **never call `browser.close()`** — that would close the user's own external browser. ⚠️ When attached over CDP, **never call `browser.close()`** — that would close the user's own external browser.
Only close the page you opened. Full recipes in [references/cdp-browser.md](references/cdp-browser.md). Only close the page you opened. Full recipes in [references/cdp-browser.md](references/cdp-browser.md).
### Simple external open/navigation: use the dedicated tool
When the user's requested action is only to open or navigate to an HTTP(S) URL in their named external browser:
1. Call `BrowserExternalProbe` and require `ready`.
2. In the same runtime session, call `BrowserExternalOpen` with `browser: detectedBrowser.id`, the exact probe `port`, and the URL.
3. Do not call Bash, PowerShell, Python, pip, or Playwright for this simple action.
The ready grant is short-lived, one-time, and bound to the exact browser and port. The host revalidates
`Browser.getVersion` on the same CDP WebSocket before creating the target. If open reports a closed,
invalid, or mismatched endpoint, call the probe again and follow its status guidance; do not retry with shell.
### Platform-safe Playwright execution ### Platform-safe Playwright execution
After a `ready` probe, identify the current OS **before** creating or running an attach script: Only for advanced interaction after a `ready` probe, identify the current OS **before** creating or running an attach script:
1. **Create or select the DesireCore-owned isolated venv first.** Do not probe a global interpreter 1. **Create or select the DesireCore-owned isolated venv first.** Do not probe a global interpreter
for Playwright. A system/bootstrap Python may only run `-m venv` when the venv does not exist. for Playwright. A system/bootstrap Python may only run `-m venv` when the venv does not exist.
@@ -217,7 +231,9 @@ User intent
├─ **Any request that names "my own / my machine's / external Chrome/Edge/Chromium"** ├─ **Any request that names "my own / my machine's / external Chrome/Edge/Chromium"**
│ └─→ L3-external first, whether the verb is search/read/open/click: │ └─→ L3-external first, whether the verb is search/read/open/click:
│ BrowserExternalProbe(exact requested browser), then connect_over_cdp() only on `ready` │ BrowserExternalProbe(exact requested browser), then only on `ready`:
│ simple open/navigation → BrowserExternalOpen(exact detected browser + port + URL)
│ advanced search/read/click/extract → isolated Playwright connect_over_cdp()
│ Otherwise follow the status guidance and wait; never route to WebSearch/WebFetch/Jina/built-in browser │ Otherwise follow the status guidance and wait; never route to WebSearch/WebFetch/Jina/built-in browser
├─ "Local browser" without saying built-in or external ├─ "Local browser" without saying built-in or external
@@ -262,7 +278,7 @@ DesireCore can drive **two** browsers. They are peer options:
| | L3 built-in governed browser | L3-external — the user's own browser | | | L3 built-in governed browser | L3-external — the user's own browser |
|---|---|---| |---|---|---|
| What it is | A browser instance inside the app (the `Browser*` tools) | The user-named Chrome/Edge/Chromium on their machine, attached via CDP + Python Playwright | | What it is | A browser instance inside the app (the governed built-in browser tools) | The user-named Chrome/Edge/Chromium on their machine, opened through governed CDP tools and attached via isolated Python Playwright only for advanced interaction |
| Login state | Isolated; needs `browser.import.*` granted by the Host before `BrowserImport` can pull cookies | **Literally the user's own session** — nothing to import | | Login state | Isolated; needs `browser.import.*` granted by the Host before `BrowserImport` can pull cookies | **Literally the user's own session** — nothing to import |
| Can the user see it | Agent tabs are offscreen by default; must be presented to the workbench | **It's their own window** — visible throughout, theirs to take over | | Can the user see it | Agent tabs are offscreen by default; must be presented to the workbench | **It's their own window** — visible throughout, theirs to take over |
| Prerequisite | None | `BrowserExternalProbe` must report `ready`; otherwise follow its exact status guidance | | Prerequisite | None | `BrowserExternalProbe` must report `ready`; otherwise follow its exact status guidance |
@@ -301,7 +317,7 @@ When what they asked for and what you're giving differ, the wording has to make
| L1 | Public, static | `WebFetch` | Low | | L1 | Public, static | `WebFetch` | Low |
| L2 | JS-heavy, long articles, token savings | `Bash curl r.jina.ai` | **Lowest** (Markdown pre-cleaned) | | L2 | JS-heavy, long articles, token savings | `Bash curl r.jina.ai` | **Lowest** (Markdown pre-cleaned) |
| **L3** | **Login-gated navigation, interaction & extraction (PRIMARY)** | **built-in browser (BrowserManage / BrowserAct / BrowserSnapshot / BrowserScript)** | Medium | | **L3** | **Login-gated navigation, interaction & extraction (PRIMARY)** | **built-in browser (BrowserManage / BrowserAct / BrowserSnapshot / BrowserScript)** | Medium |
| L3-external | **User named their own browser**, or explicitly accepted this route after you explained why it is needed | `BrowserExternalProbe` → platform-native shell (`PowerShell` on Windows) + DesireCore isolated venv + Playwright `connect_over_cdp` (see references/cdp-browser.md) | Medium | | L3-external | **User named their own browser**, or explicitly accepted this route after you explained why it is needed | Simple open/navigation: `BrowserExternalProbe``BrowserExternalOpen`; advanced interaction: ready probe → platform-native shell (`PowerShell` on Windows) + DesireCore isolated venv + Playwright `connect_over_cdp` (see references/cdp-browser.md) | Medium |
**Default priority**: L1 for simple public pages → L2 for heavy → **L3 for login-gated (body text and in-site API data included)**. **Default priority**: L1 for simple public pages → L2 for heavy → **L3 for login-gated (body text and in-site API data included)**.

View File

@@ -16,18 +16,19 @@ web-access 是一个**流程型技能Procedural Skill**,提供四层互
- **L2**Jina ReaderJS 渲染的重页面,默认节省 Token - **L2**Jina ReaderJS 渲染的重页面,默认节省 Token
- **L3**内置受管浏览器v3.0 能力面补全):到达、操作并**读取**登录态/交互站点——每个任务独立 BrowserSpace 隔离、零 Python 依赖、每次动作都有可审计回执。批量取文(`page.extract-text`)、判别式等待(`page.wait`)、代码模式(`BrowserScript`)都在本层内闭环 - **L3**内置受管浏览器v3.0 能力面补全):到达、操作并**读取**登录态/交互站点——每个任务独立 BrowserSpace 隔离、零 Python 依赖、每次动作都有可审计回执。批量取文(`page.extract-text`)、判别式等待(`page.wait`)、代码模式(`BrowserScript`)都在本层内闭环
- **L3-external**(用户点名的 Chrome/Edge/Chromium,经 CDP + Python Playwright 接管):**仅在用户点名,或 Agent 解释原因后用户明确同意时走这条**——DesireCore 隔离外部 Profile 中由用户手工登录形成的状态、可见窗口,以及用户随时接管的能力 - **L3-external**(用户点名的 Chrome/Edge/Chromium;简单打开由受治理 CDP 工具完成,只有高级交互才经隔离 Python Playwright 接管):**仅在用户点名,或 Agent 解释原因后用户明确同意时走这条**——DesireCore 隔离外部 Profile 中由用户手工登录形成的状态、可见窗口,以及用户随时接管的能力
关于 L3-external 的一段历史v3.0 曾把它整个删掉理由是「它存在的每一条技术理由无批量取文通道、evaluate 不可用、截图必须串行 activate都已被内置浏览器覆盖」。那个技术判断没错**作为「内置浏览器不够用时的兜底」它确实不再需要**。但删除时顺带丢掉了一个完全不同的用例:用户想用**他自己那个**浏览器。这跟能力够不够无关,内置浏览器替代不了,所以 v3.2 把它作为一条**由用户意图触发**的平级选择恢复回来——注意它不再是 fallback判据见下方「两个浏览器按用户意图选」。 关于 L3-external 的一段历史v3.0 曾把它整个删掉理由是「它存在的每一条技术理由无批量取文通道、evaluate 不可用、截图必须串行 activate都已被内置浏览器覆盖」。那个技术判断没错**作为「内置浏览器不够用时的兜底」它确实不再需要**。但删除时顺带丢掉了一个完全不同的用例:用户想用**他自己那个**浏览器。这跟能力够不够无关,内置浏览器替代不了,所以 v3.2 把它作为一条**由用户意图触发**的平级选择恢复回来——注意它不再是 fallback判据见下方「两个浏览器按用户意图选」。
### v3.0:内置受管浏览器(默认隐藏,激活后才暴露) ### v3.0:内置受管浏览器(默认隐藏,激活后才暴露)
调用 `Skill('web-access')` 加载本技能时会注入以下工具。`Browser*` 工具驱动内置浏览器;`BrowserExternalProbe` 只检查外部浏览器前置条件 调用 `Skill('web-access')` 加载本技能时会注入以下工具。大多数 `Browser*` 工具驱动内置浏览器;`BrowserExternalProbe` `BrowserExternalOpen` 是名称明确的外部浏览器例外
| 工具 | 用途 | | 工具 | 用途 |
|------|------| |------|------|
| BrowserManage | 建/销隔离 BrowserSpace、启动会话、管理标签页 | | BrowserManage | 建/销隔离 BrowserSpace、启动会话、管理标签页 |
| BrowserExternalProbe | 只读检查 Chrome/Edge/Chromium 安装与 loopback CDP 就绪状态;绝不启动浏览器或读取 Profile | | BrowserExternalProbe | 只读检查 Chrome/Edge/Chromium 安装与 loopback CDP 就绪状态;绝不启动浏览器或读取 Profile |
| BrowserExternalOpen | 同一 session 的 probe 返回 `ready` 后,在精确外部浏览器中可见打开一个 HTTP(S) URL不使用 shell、Python 或 Playwright |
| BrowserSnapshot | `semantic` / `text` / `accessibility` / `visual` 四种快照——读页面的主通道 | | BrowserSnapshot | `semantic` / `text` / `accessibility` / `visual` 四种快照——读页面的主通道 |
| BrowserAct | 一次调用一个受管动作:导航、输入、取文、等待、元素操作、截图…… | | BrowserAct | 一次调用一个受管动作:导航、输入、取文、等待、元素操作、截图…… |
| BrowserScript | **代码模式**:一段异步 JS 连续下发浏览器命令,消除逐动作往返(信任级别等同 Bash | | BrowserScript | **代码模式**:一段异步 JS 连续下发浏览器命令,消除逐动作往返(信任级别等同 Bash |
@@ -82,7 +83,7 @@ If any fetch fails, explicitly tell the user which URL failed and which fallback
| status | 必须采取的动作 | | status | 必须采取的动作 |
|---|---| |---|---|
| `ready` | 才能继续 Playwright `connect_over_cdp`,并如实说出检测到的外部浏览器;`any` 已有 ready 端口时,即使还安装了其他产品,也以该端口作为用户已准备的选择 | | `ready` | 简单打开/导航调用 `BrowserExternalOpen`,参数使用返回的精确浏览器 id 与端口;点击、读取、提取等高级交互才继续隔离 Playwright `connect_over_cdp`如实说出检测到的外部浏览器;`any` 已有 ready 端口时,即使还安装了其他产品,也以该端口作为用户已准备的选择 |
| `browser_not_installed` | 明确说未检测到用户点名的浏览器;若有 `alternatives`,询问是否改用其中之一,**绝不自动替换** | | `browser_not_installed` | 明确说未检测到用户点名的浏览器;若有 `alternatives`,询问是否改用其中之一,**绝不自动替换** |
| `debug_port_closed` | 展示返回的 `launchCommand`,请用户启动并手工登录,然后等待并重新 probe | | `debug_port_closed` | 展示返回的 `launchCommand`,请用户启动并手工登录,然后等待并重新 probe |
| `browser_choice_required` | 没有 ready 端口且检测到多个外部浏览器;只列 id/name 并询问用户选哪个,再 probe 精确选择 | | `browser_choice_required` | 没有 ready 端口且检测到多个外部浏览器;只列 id/name 并询问用户选哪个,再 probe 精确选择 |
@@ -94,7 +95,7 @@ If any fetch fails, explicitly tell the user which URL failed and which fallback
1. 用户在该外部浏览器里手工登录所需站点。 1. 用户在该外部浏览器里手工登录所需站点。
2. 外部浏览器窗口保持打开。 2. 外部浏览器窗口保持打开。
3. 再调用一次 `BrowserExternalProbe`;只有 `ready` 才允许尝试 CDP attach。 3. 再调用一次 `BrowserExternalProbe`;只有 `ready` 才允许调用 `BrowserExternalOpen` 或尝试高级 CDP attach。
不得用 `curl` 替代本探测:连接拒绝无法区分「未安装浏览器」与「已安装但没开调试」,普通 HTTP 服务也不能冒充 CDP。 不得用 `curl` 替代本探测:连接拒绝无法区分「未安装浏览器」与「已安装但没开调试」,普通 HTTP 服务也不能冒充 CDP。
@@ -103,9 +104,21 @@ If any fetch fails, explicitly tell the user which URL failed and which fallback
⚠️ 用 CDP attach 时**绝不能调 `browser.close()`**,那会关掉用户自己的外部浏览器;只关你开的 page。 ⚠️ 用 CDP attach 时**绝不能调 `browser.close()`**,那会关掉用户自己的外部浏览器;只关你开的 page。
完整配方见 [references/cdp-browser.md](references/cdp-browser.md)。 完整配方见 [references/cdp-browser.md](references/cdp-browser.md)。
### 简单外部打开/导航:使用专用工具
当用户只要求在点名的外部浏览器中打开或导航到一个 HTTP(S) URL
1. 调用 `BrowserExternalProbe`,且必须得到 `ready`
2. 在同一 runtime session 调用 `BrowserExternalOpen`,传入 `browser: detectedBrowser.id`、probe 的精确 `port` 与 URL。
3. 这个简单动作不得调用 Bash、PowerShell、Python、pip 或 Playwright。
ready grant 有短时、一次性、精确 browser+port 绑定。宿主会在同一 CDP WebSocket 上重新验证
`Browser.getVersion`,匹配后才创建标签页。如果 open 报告端口关闭、无效或产品不匹配,重新 probe
并按结构化状态处理;不得改用 shell 重试。
### 按平台安全执行 Playwright ### 按平台安全执行 Playwright
probe 返回 `ready` 后,创建或执行 attach 脚本前**必须先确认当前操作系统** 仅在 probe 返回 `ready`需要高级交互时,创建或执行 attach 脚本前**必须先确认当前操作系统**
1. **必须先创建或选择 DesireCore 拥有的隔离 venv**,不得先用全局解释器探测 Playwright。venv 不存在时,系统/引导 Python 只能用于执行 `-m venv` 1. **必须先创建或选择 DesireCore 拥有的隔离 venv**,不得先用全局解释器探测 Playwright。venv 不存在时,系统/引导 Python 只能用于执行 `-m venv`
2. 此后 import、固定版本安装、重新 import 与 attach 全部只能调用 venv 解释器;严禁裸 `python`、裸 `pip``pip --user`、全局安装或 `playwright install`。依赖缺失与浏览器 ready 是两件事:明确报告缺失,暂不 attach。 2. 此后 import、固定版本安装、重新 import 与 attach 全部只能调用 venv 解释器;严禁裸 `python`、裸 `pip``pip --user`、全局安装或 `playwright install`。依赖缺失与浏览器 ready 是两件事:明确报告缺失,暂不 attach。
@@ -124,7 +137,9 @@ User intent
├─ **任何点名「我自己的 / 我本机的 / 外部 Chrome、Edge、Chromium」的请求** ├─ **任何点名「我自己的 / 我本机的 / 外部 Chrome、Edge、Chromium」的请求**
│ └─→ 不论动词是搜索、读取、打开还是点击,都优先走 L3-external │ └─→ 不论动词是搜索、读取、打开还是点击,都优先走 L3-external
│ BrowserExternalProbe精确点名产品仅 `ready` 后 connect_over_cdp() │ BrowserExternalProbe精确点名产品仅 `ready` 后
│ 简单打开/导航 → BrowserExternalOpen精确 detected browser + port + URL
│ 高级搜索/读取/点击/提取 → 隔离 Playwright connect_over_cdp()
│ 否则按状态提示并等待;绝不能改走 WebSearch、WebFetch、Jina 或内置浏览器 │ 否则按状态提示并等待;绝不能改走 WebSearch、WebFetch、Jina 或内置浏览器
├─ 只说「本地浏览器」,没有说明内置还是外部 ├─ 只说「本地浏览器」,没有说明内置还是外部
@@ -169,7 +184,7 @@ DesireCore 能驱动**两个**浏览器,它们是平级的选项:
| | L3 内置受管浏览器 | L3-external 用户自己的浏览器 | | | L3 内置受管浏览器 | L3-external 用户自己的浏览器 |
|---|---|---| |---|---|---|
| 是什么 | 应用内的浏览器实例(`Browser*` 工具 | 用户点名的 Chrome/Edge/Chromium,经 CDP + Python Playwright 接管 | | 是什么 | 应用内的浏览器实例(内置受管浏览器工具) | 用户点名的 Chrome/Edge/Chromium;简单打开走受治理 CDP 工具,高级交互才经隔离 Python Playwright 接管 |
| 登录态 | 独立隔离;需 Host 授予 `browser.import.*` 才能用 `BrowserImport` 导 Cookie | **就是用户本人的登录态**,无需导入 | | 登录态 | 独立隔离;需 Host 授予 `browser.import.*` 才能用 `BrowserImport` 导 Cookie | **就是用户本人的登录态**,无需导入 |
| 用户能看到吗 | Agent 开的标签页默认离屏,需展示到工作台 | **就在用户自己的窗口里**,他能全程看着、随时接管 | | 用户能看到吗 | Agent 开的标签页默认离屏,需展示到工作台 | **就在用户自己的窗口里**,他能全程看着、随时接管 |
| 前置条件 | 无 | `BrowserExternalProbe` 必须返回 `ready`;否则严格按结构化状态处理 | | 前置条件 | 无 | `BrowserExternalProbe` 必须返回 `ready`;否则严格按结构化状态处理 |
@@ -204,7 +219,7 @@ DesireCore 能驱动**两个**浏览器,它们是平级的选项:
| L1 | Public, static | `WebFetch` | Low | | L1 | Public, static | `WebFetch` | Low |
| L2 | JS-heavy, long articles, token savings | `Bash curl r.jina.ai` | **Lowest** (Markdown pre-cleaned) | | L2 | JS-heavy, long articles, token savings | `Bash curl r.jina.ai` | **Lowest** (Markdown pre-cleaned) |
| **L3** | **登录态导航、交互与取文 (PRIMARY)** | **内置受管浏览器BrowserManage / BrowserAct / BrowserSnapshot / BrowserScript** | Medium | | **L3** | **登录态导航、交互与取文 (PRIMARY)** | **内置受管浏览器BrowserManage / BrowserAct / BrowserSnapshot / BrowserScript** | Medium |
| L3-external | **用户点名要用他自己的浏览器**,或 Agent 解释原因后用户明确同意改走此路径 | `BrowserExternalProbe` → 平台原生 shellWindows 必须 PowerShell+ DesireCore 隔离 venv + Playwright `connect_over_cdp`(见 references/cdp-browser.md | Medium | | L3-external | **用户点名要用他自己的浏览器**,或 Agent 解释原因后用户明确同意改走此路径 | 简单打开/导航:`BrowserExternalProbe` `BrowserExternalOpen`高级交互ready probe → 平台原生 shellWindows 必须 PowerShell+ DesireCore 隔离 venv + Playwright `connect_over_cdp`(见 references/cdp-browser.md | Medium |
**Default priority**: L1 for simple public pages → L2 for heavy → **L3 for login-gated含正文与站内接口取数** **Default priority**: L1 for simple public pages → L2 for heavy → **L3 for login-gated含正文与站内接口取数**

View File

@@ -1,5 +1,10 @@
# 内置受管浏览器工具速查L3 # 内置受管浏览器工具速查L3
> **范围**:本文只描述 DesireCore **内置**受管浏览器,所以 v10.0.98+ 是本层基础能力的最低版本,
> 不是整个 web-access v3.4.3 的兼容门槛。用户点名自己的外部 Chrome/Edge/Chromium 时需要
> 客户端 v10.0.128+;简单打开走 `BrowserExternalProbe → BrowserExternalOpen`,高级 CDP/Playwright
> 交互见 [cdp-browser.md](cdp-browser.md)。不要把本文的 BrowserManage/Act 路线用于冒充外部浏览器。
>
> v2.1 起本层从「cdp-proxy 驱动用户自己的 Chrome」改为「DesireCore 内置受管浏览器」v3.0 补全能力面(批量取文 / 元素操作 / 等待 / 代码模式)并移除 Python Playwright 回落。 > v2.1 起本层从「cdp-proxy 驱动用户自己的 Chrome」改为「DesireCore 内置受管浏览器」v3.0 补全能力面(批量取文 / 元素操作 / 等待 / 代码模式)并移除 Python Playwright 回落。
> 每个任务跑在独立 BrowserSpace 里Cookie / Storage / 缓存互不串扰),每个动作都经过 > 每个任务跑在独立 BrowserSpace 里Cookie / Storage / 缓存互不串扰),每个动作都经过
> Capability → Grant → Lease → Origin → Host fencing 校验并留下可审计回执。 > Capability → Grant → Lease → Origin → Host fencing 校验并留下可审计回执。

View File

@@ -2,7 +2,9 @@
Detailed recipes for accessing sites through the user-approved external Chromium browser, via Chrome DevTools Protocol (CDP) + Python Playwright. Detailed recipes for accessing sites through the user-approved external Chromium browser, via Chrome DevTools Protocol (CDP) + Python Playwright.
**Precondition**: `BrowserExternalProbe` has returned `ready` for the exact browser the user requested, that browser is running with its DesireCore-isolated profile, and the user has manually logged in to the target sites. Never infer readiness from a failed/successful `curl`; see the main SKILL.md status table. **Scope**: this manual is only for advanced external-browser interaction such as clicking, reading dynamic content, extraction, or form work. A simple open/navigation must use `BrowserExternalProbe``BrowserExternalOpen` and must not invoke shell, Python, pip, or Playwright.
**Precondition for advanced interaction**: `BrowserExternalProbe` has returned `ready` for the exact browser the user requested, that browser is running with its DesireCore-isolated profile, and the user has manually logged in to the target sites. Never infer readiness from a failed/successful `curl`; see the main SKILL.md status table.
The probe distinguishes these cases before Playwright is involved: The probe distinguishes these cases before Playwright is involved:
@@ -13,7 +15,7 @@ The probe distinguishes these cases before Playwright is involved:
- a non-CDP service owns the port (`invalid_cdp_endpoint`) - a non-CDP service owns the port (`invalid_cdp_endpoint`)
- desktop host cannot be inspected (`host_unavailable`) - desktop host cannot be inspected (`host_unavailable`)
Only `ready` permits `connect_over_cdp`. An alternative browser is a suggestion requiring user approval, never an automatic fallback. Only `ready` permits `BrowserExternalOpen` or advanced `connect_over_cdp`. An alternative browser is a suggestion requiring user approval, never an automatic fallback.
--- ---