关于 aside-browser
Aside Browser 是带有命令行的 AI 浏览器,可将复杂任务委派给 Agent,也可直接控制浏览器交互。它支持处理已登录账户、网站和浏览历史,并提供兼容 Playwright 的 REPL,用于检查页面和执行精确操作。
主要功能
- 01使用 aside exec 执行 Agent 任务
- 02兼容 Playwright 的浏览器 REPL
- 03通过无障碍快照检查页面
- 04截取屏幕并下载文件
- 05连接已打开的浏览器标签页
适用场景
- 01委派跨已登录应用的任务
- 02验证页面状态与界面操作
- 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:当前的类 PlaywrightPage。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()或类似方法截断快照。
逐步升级读取方式
按以下顺序使用:
snapshot(page, { interactive: true })snapshot(page)- 仅当页面仍在变化时,短暂等待后再次获取快照
- 视觉确认:
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 工具提取所需事实。仅报告文件中找到或已在页面上确认的事实。