Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ Web Cap is a local-first browser automation toolkit for agents. It lets agents i

Agents interact with Web Cap through the `web-cap` CLI. The CLI manages the required local runtime automatically, so users do not need a separate startup command.

## Quick Use

1. Install the Web Cap skill with the `skills` CLI:

```bash
npx skills add edgestorage/web-cap
```

2. Install the Web Cap browser extension:

- Open the latest GitHub Release.
- Download the Chrome extension zip asset, named like `*chrome*.zip`.
- Open `chrome://extensions` in Chrome.
- Enable Developer mode.
- Drag the downloaded zip file into the extensions page.

## Features

- Browser extension runtime for real Chrome/Firefox tabs.
Expand Down Expand Up @@ -80,7 +96,7 @@ The browser extension connects to the local runtime and executes commands agains
- pnpm 9.x
- A Chromium-based browser or Firefox for extension development

## Quick Start
## Development Quick Start

Install dependencies:

Expand Down Expand Up @@ -110,12 +126,6 @@ pnpm cli script-search "inspect page" --type read --site generic-web
pnpm cli script-get builtin.page.inspect
```

Install the Web Cap agent skill with the `skills` CLI:

```bash
npx skills add edgestorage/web-cap --skill web-cap -a codex
```

A typical agent flow is:

1. Use `script-search` to find a reusable script.
Expand Down
24 changes: 17 additions & 7 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ Web Cap 是一个本地优先的浏览器自动化工具,面向 agent 使用

Agent 通过 `web-cap` CLI 使用 Web Cap。CLI 会自动管理所需的本地运行时,用户不需要额外的启动命令。

## 快速使用

1. 通过 `skills` CLI 安装 Web Cap skill:

```bash
npx skills add edgestorage/web-cap
```

2. 安装 Web Cap 浏览器扩展:

- 打开最新的 GitHub Release。
- 下载 Chrome 扩展 zip 产物,文件名类似 `*chrome*.zip`。
- 在 Chrome 中打开 `chrome://extensions`。
- 开启开发者模式。
- 将下载的 zip 文件拖到扩展程序页面中。

## 功能特性

- 面向真实 Chrome/Firefox 标签页的浏览器扩展运行时。
Expand Down Expand Up @@ -80,7 +96,7 @@ Browser extension
- pnpm 9.x
- 用于扩展开发的 Chromium 系浏览器或 Firefox

## 快速开始
## 开发快速开始

安装依赖:

Expand Down Expand Up @@ -110,12 +126,6 @@ pnpm cli script-search "inspect page" --type read --site generic-web
pnpm cli script-get builtin.page.inspect
```

通过 `skills` CLI 安装 Web Cap agent skill:

```bash
npx skills add edgestorage/web-cap --skill web-cap -a codex
```

典型 agent 流程是:

1. 用 `script-search` 查找可复用脚本。
Expand Down
2 changes: 2 additions & 0 deletions extension/runtime/click-routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ function scriptUsesManagedClick(code: string): boolean {
}

return (
/\bpage\s*\.\s*mouse\b/.test(code) ||
/\.\s*dragTo\s*\(/.test(code) ||
/\.\s*click\s*\(/.test(code) ||
/new\s+MouseEvent\s*\(/.test(code) ||
/dispatchEvent\s*\(\s*new\s+MouseEvent/.test(code)
Expand Down
4 changes: 4 additions & 0 deletions extension/runtime/debugger-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export class DebuggerScriptExecutor {
await this.managedInputBridgeFactory.createManagedKeyboardBridge(target, executionScope);
const windowBridge =
await this.managedInputBridgeFactory.createManagedWindowBridge(target, executionScope);
const browserBridge =
await this.managedInputBridgeFactory.createManagedBrowserBridge(target, executionScope);
let evaluation: DebuggerEvaluateResult;
try {
evaluation = await this.client.sendCommand<DebuggerEvaluateResult>(target, 'Runtime.evaluate', {
Expand All @@ -59,13 +61,15 @@ export class DebuggerScriptExecutor {
managedKeyboardBridgeFunctionName: keyboardBridge.bridgeFunctionName,
managedWindowBridgeFunctionName: windowBridge.bridgeFunctionName,
managedTimerBridgeFunctionName: timerBridge.bridgeFunctionName,
managedBrowserBridgeFunctionName: browserBridge.bridgeFunctionName,
}),
awaitPromise: true,
returnByValue: true,
userGesture: true,
allowUnsafeEvalBlockedByCSP: true,
});
} finally {
await browserBridge.dispose();
await timerBridge.dispose();
await windowBridge.dispose();
await keyboardBridge.dispose();
Expand Down
7 changes: 7 additions & 0 deletions extension/runtime/execution-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface ScriptExecutionExpressionOptions {
managedKeyboardBridgeFunctionName?: string;
managedWindowBridgeFunctionName?: string;
managedTimerBridgeFunctionName?: string;
managedBrowserBridgeFunctionName?: string;
}

export function scriptToFunctionExpression(code: string): string {
Expand Down Expand Up @@ -323,6 +324,10 @@ export function buildScriptExecutionExpression(
options.managedTimerBridgeFunctionName === undefined
? null
: String(options.managedTimerBridgeFunctionName);
const managedBrowserBridgeFunctionName =
options.managedBrowserBridgeFunctionName === undefined
? null
: String(options.managedBrowserBridgeFunctionName);
const scripts = new Map<string, ScriptDefinition>();
for (const item of scriptRegistry) {
scripts.set(item.id, item);
Expand All @@ -345,6 +350,7 @@ export function buildScriptExecutionExpression(
const managedKeyboardBridgeFunctionName = ${JSON.stringify(managedKeyboardBridgeFunctionName)};
const managedWindowBridgeFunctionName = ${JSON.stringify(managedWindowBridgeFunctionName)};
const managedTimerBridgeFunctionName = ${JSON.stringify(managedTimerBridgeFunctionName)};
const managedBrowserBridgeFunctionName = ${JSON.stringify(managedBrowserBridgeFunctionName)};
const timerBridge = managedTimerBridgeFunctionName ? globalThis[managedTimerBridgeFunctionName] : null;
const nativeSetTimeout = globalThis.setTimeout.bind(globalThis);
const nativeClearTimeout = globalThis.clearTimeout.bind(globalThis);
Expand Down Expand Up @@ -400,6 +406,7 @@ export function buildScriptExecutionExpression(
managedKeyboardBridgeFunctionName,
managedWindowBridgeFunctionName,
managedTimerBridgeFunctionName,
managedBrowserBridgeFunctionName,
scriptFactories,
});
})()
Expand Down
Loading
Loading