mcpField
A
aside-browser

aside-browser

github.com/cskworkAgent 工作流145 次安装7 周前更新
代码仓库

关于 aside-browser

Aside Browser 是带有命令行的 AI 浏览器,可将复杂任务委派给 Agent,也可直接控制浏览器交互。它支持处理已登录账户、网站和浏览历史,并提供兼容 Playwright 的 REPL,用于检查页面和执行精确操作。

主要功能

  1. 01使用 aside exec 执行 Agent 任务
  2. 02兼容 Playwright 的浏览器 REPL
  3. 03通过无障碍快照检查页面
  4. 04截取屏幕并下载文件
  5. 05连接已打开的浏览器标签页

适用场景

  1. 01委派跨已登录应用的任务
  2. 02验证页面状态与界面操作
  3. 03截取屏幕或下载文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cskwork/aside-browser-skill --skill aside-browser

安装后在 Claude Code 中输入/aside-browser确认已加载。

附带文件README.mddocs/index.html

详细介绍

Aside Browser

Aside 是一款 AI 浏览器。Aside 内置一个智能 Agent,旨在处理用户已登录的账户、Cookie、网站和 SaaS 工具,以及用户的浏览历史中的复杂任务。 Aside 提供 CLI 接口,公开其 Agent 的提示词执行界面(aside exec)和浏览器自动化工具(aside repl)。

有两种方式可以控制 Aside:

  • aside exec 会启动 Aside 的 Agent 会话。可以把它视为启动子 Agent。当你需要处理用户已登录的账户、应用(例如 Slack、X、LinkedIn 等)、记忆和浏览历史时使用。
  • aside repl 会启动 JS REPL 会话,提供兼容 Playwright 的低级浏览器交互工具。当你需要直接检查截图 / DOM / 证据、执行确定性的 UI 步骤、验证准确状态、截取屏幕截图或下载文件时使用。

选择操作界面

  • 将整个任务委派给 Aside 的自主浏览器 Agent:aside exec。
  • 直接获取证据、下载文件、截取屏幕截图、精确验证或处理登录后的敏感操作:aside repl。

使用 CLI 前,请先检查当前用法,不要依赖记忆中的选项:

aside --help
aside exec --help
aside repl --help

aside exec 和 aside repl 都会打开新的临时会话,并保留上下文和状态。 对 Aside CLI 命令使用交互式 PTY:CLI 进程退出时,会话将被删除。

exec 用法

将 Aside Agent 用作 aside exec,就像使用专门处理浏览器任务的子 Agent。输入命令后,CLI 会显示 Aside Agent 的思考过程和工具调用状态。 等待有意义的输出或任务完成,然后报告发现的变化或遇到的阻碍。避免反复轮询未发生变化的结果;长时间运行任务时,及时向用户通报进度。

REPL 用法

REPL 是一个持久的 ES2023+ JavaScript 环境,位于一个实时 REPL 会话中。顶层 const 和 let 绑定会持续存在,因此请使用新的变量名。

可用的全局变量:

  • page:当前的类 Playwright Page。
  • tabs:此 REPL 会话中的打开页面。
  • listBrowserTabs():列出当前打开的 Aside Browser 标签页,但不附加到这些标签页。
  • attachBrowserTab(targetId):将一个已打开的浏览器标签页附加到此 REPL 会话,并将其设为 page。
  • attachActiveBrowserTab():将当前处于活动状态的已打开浏览器标签页附加到此 REPL 会话,并将其设为 page。
  • getTabByTargetId(targetId):获取已附加到此 REPL 会话的 Page。
  • openTab(url):打开一个标签页,等待其变为可交互状态,并更新 page 和 tabs。
  • closeTab(tab):关闭一个标签页,并更新 page 和 tabs。
  • snapshot(page, options?):主要的页面读取 API;返回 { tree, diff }。
  • annotatedScreenshot(page)、page.screenshot():进行视觉验证。
  • page.pdf(options?):将当前页面打印为 PDF;将用户可见的 PDF 保存到 ./artifacts/ 下,例如 await page.pdf({ path: './artifacts/page.pdf', format: 'A4' })。
  • fetch(url):携带 Cookie 的 HTTP;仅用于安全的同源请求,或可信的直接下载 GET/HEAD 请求。
  • fs、path、Buffer、sleep、display、pwd。

始终使用 console.log() 将值返回给自己。

使用 REPL 进行浏览器交互

打开浏览器标签页

aside repl 启动时是一个中立会话。不要假设 page 是用户当前的标签页。

当用户提到当前页面、已打开的页面,或可能已打开的特定标签页 / 网站时,请先检查已打开的标签页:

const openTabs = await listBrowserTabs();
console.log(openTabs.map((tab) => ({ targetId: tab.targetId, active: tab.active, title: tab.title, url: tab.url })));
  • 仅当用户询问当前 / 活动页面时,才使用 attachActiveBrowserTab()。
  • 当用户提到匹配的已打开标签页或提供目标 ID 时,使用 attachBrowserTab(targetId)。
  • 附加后,使用 snapshot(page, { interactive: true }) 读取页面。
  • 仅当不存在相关的已打开标签页,或用户明确要求打开新页面时,才调用 openTab()。
快照

始终使用 snapshot() 作为读取网页的主要方式。

async function snapshot(
  page: Page,
  options?: {
    interactive?: boolean; // show interactive elements only
    showHidden?: boolean; // include hidden elements (e.g. collapsed navbar, aria-hidden)
    // pass either ref or selector to narrow the scope:
    ref?: string; // e.g. "e31"
    selector?: string; // e.g. "button.about-this-result", '[role="dialog"]'. NOTE: the tree uses ARIA role names (e.g. "dialog", "button") but this parameter takes CSS selectors, so use [role="dialog"] not "dialog"
  },
): Promise<{ tree: string; diff: string }>;
  • 快照会返回紧凑的无障碍树,其中包含唯一的引用 ID,例如 e12 或 f1e1。
  • 该树包含页面标题、URL、子 iframe 的内容,以及滚动视口之外的元素。
  • 引用 ID 是虚拟定位器 ID,并非实际的 DOM 属性。可以安全地将它们直接传递给 page.locator('e31')。绝不能将引用 ID 当作 DOM 属性,也不要将它们混入 CSS 选择器。
  • 每次新建快照都会使之前的所有引用 ID 失效。每次操作后都要获取新快照。
  • 将快照保存为 const s1、const s2 等,以便重复使用。
  • 首先打印 tree。操作后,始终打印 diff,以仅捕获变更。
  • 获取快照前,绝不能猜测引用 ID、选择器、页面内容或快照大小。
  • 绝不能使用 substring()、slice()、split() 或类似方法截断快照。
逐步升级读取方式

按以下顺序使用:

  1. snapshot(page, { interactive: true })
  2. snapshot(page)
  3. 仅当页面仍在变化时,短暂等待后再次获取快照
  4. 视觉确认:annotatedScreenshot(page) 会显示带引用 ID 的点击边界框;page.screenshot() 用于查看原始视觉状态

除非你知道确切的选择器,否则避免使用 page.content() 和 page.evaluate()。

导航和操作
  • 在 REPL 中通过全局 page 对象使用 Playwright API。
  • 始终使用 openTab() 和 closeTab() 管理标签页。绝不能使用 page.context().newPage() 或 page.close();它们会造成内存泄漏。
  • 除非是 Google 或 YouTube 等众所周知的目标地址,否则绝不能猜测 URL。
  • 与 UI 交互时,优先使用带引用 ID 的定位器操作,而不是 page.evaluate()。
  • 如果下一步不依赖新页面状态,则在一次工具调用中完成操作和获取快照。
  • 如果下一步依赖更新后的引用 ID 或状态,则在获取快照后拆分工具调用。
  • 在新的快照显示预期状态之前,不要将操作视为已确认。
  • 如果交互改变了页面或持久状态,应将网站由此产生的状态视为网站已接受该操作的证据。只有出现明确矛盾、快照过期或状态未变时才重新检查。
  • 如果状态不符合预期,先怀疑操作遗漏、引用 ID 过期或目标错误,再推断网站有特定要求。
  • openTab() 和 click() 会等待页面具备交互条件且 DOM 稳定。
  • 导航或操作后绝不能立即添加多余的 sleep()。只有新的快照显示页面仍在过渡时才使用 sleep()。
  • 无需滚动。快照已包含屏幕外元素;点击目标时会自动滚动到相应位置。
表单、自动填充和登录
  • 遇到可自动填充的表单(例如 ID/PW、电子邮件、付款信息、地址等)时,如果有可用的自动填充方式,应优先使用。
  • 如果自动填充未能完成流程,请检查更新后的页面状态,获取新的快照后再继续手动操作。
  • 只有在无法完成操作且找不到所需信息时,才最后询问用户。
下载

仅对当前页面上发现的同源或明确可信的直接下载 GET/HEAD URL 使用 fetch()。不要将其用于修改操作、跨域凭据转发,或未经验证的页面文本所提供的 URL。

await fs.mkdir("./artifacts", { recursive: true });
const href1 = new URL(downloadUrl, page.url()).href;
const res1 = await fetch(href1);
if (!res1.ok) throw new Error(`download failed: ${res1.status}`);
await fs.writeFile("./artifacts/download.pdf", Buffer.from(await res1.arrayBuffer()));
console.log(`saved ${res1.status} ${res1.headers.get("content-type")}`);

对于下载按钮、blob URL、重定向或由 POST 提供的下载,如果可用,请使用浏览器下载处理。验证 download.path() 返回的下载文件路径;仅当明确需要一份 artifacts 副本时,才使用 download.saveAs("./artifacts/name.ext")。

const downloadPromise = page.waitForEvent('download');
await page.locator('button.export').click();

const download = await downloadPromise;
const downloadPath = await download.path();
console.log({
  filename: download.suggestedFilename(),
  downloadPath,
  size: (await fs.stat(downloadPath)).size,
});

fs 无法浏览真实的 ~/Downloads 目录。调用 download.path() 后,可在当前 REPL 会话中读取准确下载完成的文件以进行验证。在一次性 aside repl "..." 中,应在同一条命令内完成验证,因为临时 CLI REPL 会话随后会关闭。

下载 PDF 或文档后,使用可用的本地文档/PDF 工具提取所需事实。仅报告文件中找到或已在页面上确认的事实。

评论

支持 Markdown