[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80304":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":37,"readmeContent":38,"aiSummary":39,"trendingCount":15,"starSnapshotCount":15,"syncStatus":40,"lastSyncTime":41,"discoverSource":42},80304,"WebDroid-Agent","yeahhe365\u002FWebDroid-Agent","yeahhe365","Browser-based Android phone agent using WebADB\u002FWebUSB and OpenAI-compatible vision models","https:\u002F\u002Fwebadb-autoglm.pages.dev\u002F",null,"TypeScript",91,17,71,0,3,13,19,11,58.17,"MIT License",false,"main",true,[26,27,28,29,30,31,32,33,34,35,36],"adb","android","android-automation","autoglm","openai-compatible","phone-agent","react","vision-language-model","vite","webadb","webusb","2026-06-12 04:01:27","\u003Cp align=\"center\">\n  \u003Cimg src=\".\u002Fpublic\u002Fwebdroid-agent-logo-128.png\" alt=\"WebDroid Agent logo\" width=\"96\" \u002F>\n\u003C\u002Fp>\n\n# WebDroid Agent\n\n\u003Cp align=\"center\">\n  \u003Ca href=\".\u002FREADME.md\">中文\u003C\u002Fa> | \u003Ca href=\".\u002FREADME.en-US.md\">English\u003C\u002Fa>\n\u003C\u002Fp>\n\n![React](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FReact-19-61DAFB?logo=react&logoColor=111)\n![TypeScript](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FTypeScript-6-3178C6?logo=typescript&logoColor=white)\n![Vite](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FVite-8-646CFF?logo=vite&logoColor=white)\n![WebUSB](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FWebUSB-Android_ADB-34A853?logo=googlechrome&logoColor=white)\n![Cloudflare Pages](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FCloudflare_Pages-online-F38020?logo=cloudflare&logoColor=white)\n\nWebDroid Agent 是一个以浏览器为核心的 Android 手机 Agent 实验项目。静态部署时它完全在前端运行；Docker 部署时会额外启用一个本地 Node API 代理，让模型请求通过容器转发而不是从浏览器直接跨域请求。它在浏览器中通过 WebUSB\u002FWebADB 连接 Android 设备，截取手机屏幕并发送给 OpenAI 兼容的视觉模型，再把模型返回的受控动作解析、校验并通过 ADB 执行。\n\n项目目标不是替代人工长期托管手机，而是提供一个可以在本地浏览器中快速验证「视觉模型 + 手机控制」链路的实验环境。\n\n[历史在线地址（Pages 旧域名）](https:\u002F\u002Fwebadb-autoglm.pages.dev\u002F) · [英文版](.\u002FREADME.en-US.md) · [Tango \u002F WebADB](https:\u002F\u002Fgithub.com\u002Fyume-chan\u002Fya-webadb)\n\n```text\nChromium WebUSB -> Tango\u002FWebADB -> Android ADB\n静态部署: 浏览器 fetch -> OpenAI 兼容 \u002Fv1\u002Fchat\u002Fcompletions -> 视觉模型\nDocker: 浏览器 fetch -> 同源本地代理 -> OpenAI 兼容 \u002Fv1\u002Fchat\u002Fcompletions -> 视觉模型\n```\n\n## 目录\n\n- [核心能力](#核心能力)\n- [适合谁使用](#适合谁使用)\n- [项目状态](#项目状态)\n- [工作流程](#工作流程)\n- [环境要求](#环境要求)\n- [快速开始](#快速开始)\n- [配置说明](#配置说明)\n- [Docker 部署](#docker-部署)\n- [模型动作协议](#模型动作协议)\n- [mobilerun 兼容](#mobilerun-兼容)\n- [Open-AutoGLM 兼容](#open-autoglm-兼容)\n- [设备控制细节](#设备控制细节)\n- [安全边界](#安全边界)\n- [项目结构](#项目结构)\n- [验证](#验证)\n- [路线图](#路线图)\n- [贡献说明](#贡献说明)\n- [部署到 Cloudflare Pages](#部署到-cloudflare-pages)\n- [License](#license)\n- [相关项目和社区](#相关项目和社区)\n\n## 核心能力\n\n- 静态部署纯前端运行，适合本地实验、Cloudflare Pages 等静态站点部署。\n- Docker 部署内置同源本地 API 代理，可避免模型服务浏览器 CORS 限制。\n- 通过 WebADB 在浏览器中连接已开启 USB 调试的 Android 设备。\n- 截取手机屏幕，并把截图、当前 App、设备状态、完整已安装应用列表和历史步骤发送给视觉模型。\n- 可显式选择 `webdroid_json`、`open_autoglm_function` 或 `mobilerun_xml` 动作协议。\n- 使用 canonical JSON 提示词和动作格式，并保留 Open-AutoGLM、mobilerun 风格动作输出的解析兼容。\n- 自动解析、规范化并校验模型返回的下一步动作。\n- 通过 ADB 执行启动应用、点击、滑动、输入文本、返回、Home、长按、双击、等待等操作，支持模型显式配置等待时间。\n- 支持输入前清空文本、动作后固定等待、瞬时模型 API 错误\u002F模型空回复重试和非敏感执行失败的有限自动恢复。\n- 支持可编辑 App Cards、本地 Custom Tools，以及只向模型暴露 ID\u002F标签的安全 Secret 输入。\n- 发送聊天消息后默认自动执行，也保留单步计划等高级调试能力。\n- 支持敏感动作确认、完全无限制模式、最大步数限制、停止运行，以及高级区中的上下文重置和运行日志导出。\n- 页面配置持久化到本机浏览器 `localStorage`，Agent thread\u002Fturn 历史持久化到 IndexedDB。\n\n## 适合谁使用\n\n适合用于：\n\n- 验证 OpenAI 兼容视觉模型是否能理解真实手机界面。\n- 调试手机 Agent 的动作协议、坐标映射和自动执行流程。\n- 研究 Open-AutoGLM、mobilerun 风格动作和更通用 JSON 动作之间的兼容层。\n- 在本地安全环境中做 Android UI 自动化原型实验。\n- 想快速体验 WebUSB + ADB + 多模态模型闭环的开发者。\n\n不建议用于：\n\n- 支付、下单、删除、授权、账号设置等高风险流程。\n- 登录、验证码、密码输入等需要人工明确介入的流程。\n- 需要后台服务、长期稳定托管或多设备调度的生产场景。\n\n## 项目状态\n\n当前项目处于实验可用阶段，核心链路已经打通：\n\n- 浏览器端连接 Android 设备并获取截图。\n- 调用 OpenAI 兼容视觉模型生成下一步动作。\n- 解析 canonical JSON、Open-AutoGLM 和 mobilerun 风格动作。\n- 执行常见 ADB 控制指令并记录运行日志。\n- 支持聊天驱动的自动执行、人工确认、停止、上下文恢复和基础失败恢复。\n\n仍建议把它当作本地实验工具使用。真实设备、模型能力、浏览器权限、CORS 配置和 Android ROM 差异都会影响效果。\n\n## 工作流程\n\n1. 在 Chromium 系浏览器中打开应用。\n2. 连接开启 USB 调试的 Android 设备，并在手机上授权 ADB 调试。\n3. 填写 OpenAI 兼容接口的 `Base URL`、`API Key` 和 `Model`。\n4. 在右侧聊天区输入自然语言指令，例如「打开设置并进入 Wi-Fi 页面」。\n5. 发送后应用截屏并请求模型返回一个动作。\n6. 前端解析、校验动作，并自动执行安全动作；敏感动作默认仍会请求确认。\n7. 如果非敏感动作执行失败，失败反馈会进入下一轮上下文，模型最多获得少量自动恢复机会。\n8. 重复执行，直到模型返回 `done`、请求 `take_over`、达到最大步数或用户停止；开启完全无限制模式时不会因 `take_over` 停止。\n\n## 环境要求\n\n- 支持 WebUSB 的 Chromium 系浏览器，例如 Chrome 或 Edge。\n- 已开启 USB 调试的 Android 设备。\n- 可传输数据的 USB 数据线。\n- OpenAI 兼容的 `\u002Fv1\u002Fchat\u002Fcompletions` API。\n- 支持 `image_url` 输入的视觉模型。\n- 静态部署时，API 服务需要允许浏览器跨域请求，也就是正确配置 CORS；Docker 部署可通过同源本地代理规避这项要求。\n- 页面需要运行在 `localhost` 或 HTTPS 环境下，WebUSB 才能正常工作。\n\n## 快速开始\n\n```bash\nnpm install\nnpm run dev\n```\n\n然后用 Chrome 或 Edge 打开 Vite 输出的本地地址。\n\n常用命令：\n\n```bash\nnpm test\nnpm run lint\nnpm run build\nnpm run preview\n```\n\n## 配置说明\n\n应用会把以下配置保存在当前浏览器的 `localStorage` 中：\n\n- `Base URL`：OpenAI 兼容接口地址，默认 `https:\u002F\u002Fapi.openai.com\u002Fv1`。\n- `API Key`：模型接口密钥。\n- `Model`：模型名称，默认 `gpt-5.5`。\n- `Thinking depth`：GPT-5.5 等推理模型的 `reasoning_effort`，可使用服务默认值，或选择 `none`、`minimal`、`low`、`medium`、`high`、`xhigh`。\n- `Action protocol`：模型动作协议，可选 `webdroid_json`、`open_autoglm_function`、`mobilerun_xml`。\n- `Max steps`：自动执行的最大步数，默认 `50`。\n- `Confirm sensitive actions`：敏感点击是否需要人工确认，默认开启。\n- `完全无限制模式`：绕过本地安全策略和敏感确认，模型也会被提示不要请求人工接管。\n- `Stream responses`：是否启用流式响应，默认关闭。\n- `Use ADB Keyboard for text`：是否优先使用 ADB Keyboard 输入文本，默认关闭。\n- `Action settle`、`Double tap interval`、`Keyboard step`：动作执行后的等待和输入节奏参数。\n- `App Cards`：按包名编辑的应用上下文卡片，默认内置 Chrome、Gmail、Settings。\n- `Secrets`：本地 Secret 列表，模型只看到 `id` 和 `label`，执行时通过 `type_secret` 在本机解析真实值。\n- `Custom Tools`：本地工具定义，模型只看到工具名和描述，执行结果在本地返回给下一轮上下文。\n\nAPI Key 只保存在浏览器本地。请只在可信设备和本地实验环境中使用。Docker 部署时，浏览器会把模型请求发送到同源的本地代理接口，再由容器内 Node 服务请求模型 API，以绕过浏览器 CORS 限制。\n\n## Docker 部署\n\nDocker 镜像会构建同一个前端应用，并额外启用一个本地 Node 服务：\n\n- 浏览器访问容器页面，WebUSB\u002FWebADB 仍然在浏览器中工作。\n- 前端请求同源 `\u002Fapi\u002Fopenai\u002Fchat\u002Fcompletions`。\n- 容器内 Node 服务读取请求里的 `Base URL`、`API Key` 和 OpenAI-compatible payload，再转发到模型 API。\n- Cloudflare Pages 不使用这个 Node 服务，也不会设置代理构建变量，仍然是静态前端和浏览器直连模型 API。\n\n构建并运行：\n\n```bash\nnpm run docker:build\ndocker run --rm -p 8080:8080 webdroid-agent\n```\n\n然后用 Chrome 或 Edge 打开：\n\n```text\nhttp:\u002F\u002Flocalhost:8080\u002F\n```\n\n如果使用仓库内的 Docker Compose 配置：\n\n```bash\ndocker compose up -d --build\n```\n\n则打开：\n\n```text\nhttp:\u002F\u002Flocalhost:8083\u002F\n```\n\nDocker 运行时不需要把 API Key 写进环境变量；继续在页面里的模型配置中填写。请不要把这个容器代理直接暴露到不可信公网，因为它会转发浏览器提交的任意 OpenAI-compatible `Base URL`。\n\n## 模型动作协议\n\n推荐让模型只返回一个 JSON 对象，不要包含 Markdown 或解释性文本：\n\n```json\n{ \"action\": \"tap\", \"x\": 540, \"y\": 1280, \"reason\": \"点击搜索框\" }\n```\n\ncanonical JSON 推荐使用的标准动作：\n\n| 动作 | 说明 |\n| --- | --- |\n| `launch` | 启动应用，可传常见应用名或包名 |\n| `tap` | 点击屏幕坐标 |\n| `swipe` | 从一个坐标滑动到另一个坐标 |\n| `input_text` | 输入文本；`clear:true` 会先清空当前焦点文本框 |\n| `type_secret` | 输入本地 Secret；模型只传 `secretId`，不会看到真实值 |\n| `open_url` | 使用 Android `ACTION_VIEW` 打开网页 URL 或 App deep link |\n| `set_clipboard` | 设置 WebDroid 剪贴板文本，并尽力同步到设备剪贴板 |\n| `paste` | 将 WebDroid 剪贴板文本粘贴\u002F输入到当前焦点 |\n| `custom_tool` | 调用本地配置的 Custom Tool |\n| `key` | 发送 Android 按键，如 `BACK`、`HOME`、`ENTER` |\n| `back` | 返回 |\n| `home` | 回到桌面 |\n| `long_press` | 长按坐标 |\n| `double_tap` | 双击坐标 |\n| `wait` | 等待一段时间，推荐使用 `duration` 秒数 |\n| `take_over` | 请求人工接管 |\n| `note` | 记录观察，不执行设备动作 |\n| `done` | 任务完成 |\n\n示例：\n\n```json\n{ \"action\": \"launch\", \"app\": \"Settings\", \"reason\": \"打开系统设置\" }\n```\n\n```json\n{ \"action\": \"swipe\", \"fromX\": 540, \"fromY\": 1700, \"toX\": 540, \"toY\": 500, \"durationMs\": 400, \"reason\": \"向下滚动列表\" }\n```\n\n```json\n{ \"action\": \"take_over\", \"message\": \"需要用户输入验证码\" }\n```\n\n```json\n{ \"action\": \"type_secret\", \"secretId\": \"gmail_password\", \"clear\": true, \"reason\": \"输入已配置的本地密码\" }\n```\n\n```json\n{ \"action\": \"open_url\", \"url\": \"https:\u002F\u002Fexample.com\u002Fsearch?q=webdroid\", \"reason\": \"直接打开目标网页\" }\n```\n\n遗留兼容层仍能接收 `interact` 和 `call_api`，但它们不是推荐给模型使用的真实执行动作：`interact` 会转成 `take_over`，`call_api` 会转成带有“不支持二次 API 调用”说明的 `take_over`。\n\n## mobilerun 兼容\n\n解析器也接受常见 mobilerun 风格动作，并映射到 WebDroid 的真实执行动作：\n\n| mobilerun 风格 | WebDroid 执行动作 |\n| --- | --- |\n| `click_at` \u002F `tap_at` | `tap` |\n| `click_area` \u002F `tap_area` | 点击区域中心点 |\n| `long_press_at` | `long_press` |\n| `type_text` \u002F `type_text_direct` | `input_text` |\n| `type_secret` | `type_secret` |\n| `custom_tool` | `custom_tool` |\n| `system_button` \u002F `press_button` | `key` |\n| `open_app` \u002F `open_bundle_id` | `launch` |\n| `remember` | `note` |\n| `complete` | `done` |\n\n`swipe` 也兼容 `coordinate`、`coordinate2` 和 `duration` 秒数。mobilerun 风格的 `coordinate`、`point`、`position`、`click_area` 坐标都按截图像素处理；只有 Open-AutoGLM 的 `element` 继续按 `0-1000` 相对坐标处理。\n\n## Open-AutoGLM 兼容\n\n解析器也兼容 Open-AutoGLM 风格的动作名称和载荷，包括：\n\n- `Launch`\n- `Tap`，支持 `element: [x, y]` 相对坐标\n- `Type`\n- `Swipe`\n- `Back`\n- `Home`\n- `Long Press`\n- `Double Tap`\n- `Wait`\n- `Take_over`\n- `Interact`，会转成 `take_over`\n- `Note`\n- `Call_API`，会转成带“不支持二次 API 调用”说明的 `take_over`\n- `type_secret(secret_id=\"...\")`\n- `custom_tool(tool=\"...\")`\n\n也支持类似下面的函数式输出：\n\n```text\ndo(action=\"Launch\", app=\"京东\")\n```\n\nOpen-AutoGLM 风格坐标使用 `0-1000` 的相对坐标空间；canonical JSON 默认使用截图像素坐标。应用会在执行前把坐标映射回设备原生坐标。\n\n## 设备控制细节\n\n- 启动应用：优先匹配设备已安装应用列表，也支持内置常见 App 名称映射或直接传 Android 包名。\n- 点击\u002F滑动：执行前会校验坐标是否在屏幕范围内。\n- 界面结构：每步会尽力通过 `uiautomator dump --compressed` 读取当前控件树，把可见文本、描述、资源 ID、可点击状态和 bounds 注入模型上下文。\n- 打开 URL：使用 Android `am start -a android.intent.action.VIEW -d \u003Curl>`，支持网页和设备上已注册的 deep link。\n- 长按：使用 Android `input swipe x y x y duration` 命令模拟。\n- 双击：连续发送两次 `tap`，中间带可配置延迟。\n- 文本输入：简单 ASCII 文本使用 Android `input text`。\n- 清空后输入、中文和复杂字符：使用 ADB Keyboard 或 AutoGLM Keyboard 广播模式输入。\n- 剪贴板：`set_clipboard` 会保存一份本地 WebDroid 剪贴板并尝试调用 `cmd clipboard set`；`paste` 优先用本地剪贴板通过当前输入通道写入焦点框。\n- ADB Keyboard 模式要求设备上已安装并启用 `com.android.adbkeyboard\u002F.AdbIME`；设备面板提供安装和启用入口。\n- 每个设备动作执行后会按 `Action settle` 配置等待，避免动画或页面加载期间过早进入下一步。\n\n## 安全边界\n\n项目会尽量在前端执行前做约束和确认：\n\n- 模型输出必须能解析为受支持动作。\n- 坐标会进行屏幕范围校验。\n- 文本输入会限制长度并拒绝控制字符。\n- `type_secret` 只从模型接收本地 Secret ID，真实 Secret 值不会进入模型请求或日志摘要。\n- 自动执行有最大步数限制。\n- 用户可以随时停止运行。\n- 敏感点击可要求人工确认；开启完全无限制模式时会跳过这些确认。\n- `take_over`、`note`、`done` 不会直接操作设备；遗留 `interact` 和 `call_api` 会转成人工接管。\n\n仍然建议避免让 Agent 操作账号登录、支付、下单、删除、授权、验证码、隐私页面等高风险流程。默认情况下模型返回 `take_over` 时，自动执行会停止并等待人工接管；开启完全无限制模式后不会因接管请求停止。\n\n## 项目结构\n\n```text\nsrc\u002F\n  adapters\u002F\n    adbKeyboard.ts            # ADB Keyboard 安装、检测和编码工具\n    appPackages.ts            # 常见 App 名称和包名映射\n    deviceCommands.ts         # 设备命令兼容导出口\n    deviceParsers.ts          # dumpsys 和截图二进制解析\n    deviceRetry.ts            # 设备读取重试和延迟工具\n    deviceTiming.ts           # 设备执行时序默认值\n    deviceTypes.ts            # 设备后端共享类型和错误\n    inputCommands.ts          # ADB 输入命令构建\n    installedApps.ts          # 已安装应用解析、搜索和显示名\n    sensitiveActions.ts       # 敏感动作确认\n    screenshotPreprocess.ts   # 截图预处理\n    stayAwakeCommands.ts      # ADB 连接期间保持唤醒命令\n    webAdbBackend.ts          # WebADB\u002FWebUSB 实现\n  components\u002F\n    AgentStepCard.tsx         # Agent 步骤卡片\n    AppTopbar.tsx             # 顶栏品牌和状态\n    ChatHistorySidebar.tsx    # 历史会话侧栏\n    ChatPanel.tsx             # 聊天记录和输入区外壳\n    ConfigRail.tsx            # 收起状态下的配置快捷栏\n    ConfigSidebar.tsx         # 设备和模型配置侧栏编排\n    ConversationPanel.tsx     # 聊天、历史会话和待执行动作\n    DeviceOptionsSection.tsx  # 设备输入、确认和时序选项\n    DevicePanel.tsx           # 设备连接和执行设置面板\n    DirectCommandsSection.tsx # 直接 ADB 动作面板\n    InstalledAppsSection.tsx  # 已安装应用搜索和启动\n    LazyDetails.tsx           # 延迟渲染的折叠区域\n    MarkdownContent.tsx       # 聊天消息 Markdown 渲染\n    ModelPanel.tsx            # 模型配置面板\n    PendingActionCard.tsx     # 待执行动作确认卡片\n    PhoneStage.tsx            # 手机截图和动作覆盖层\n    RunLog.tsx                # 运行日志\n    ScreenshotLightbox.tsx    # 截图预览弹窗\n    SettingsDialog.tsx        # 应用设置、仓库信息和可编辑资源\n    TutorialPanel.tsx         # 顶部栏展开的快速上手教程\n  hooks\u002F\n    useAgentRunController.ts        # Agent 自动运行和待执行动作控制\n    useAgentSessionHistory.ts       # 会话恢复、保存和历史列表状态\n    useBusyTask.ts                  # 运行中任务和错误状态管理\n    useConfigTargetScroll.ts        # 配置侧栏目标定位\n    useDeviceBackendPreferences.ts  # 设备后端偏好同步\n    useDeviceController.ts          # 设备连接、截图和直接动作控制\n    useDocumentPreferences.ts       # 文档主题和语言属性同步\n    useLatestValue.ts               # 异步回调读取最新值的 ref\n    usePersistedSettings.ts         # 设置变更持久化\n    useRepositoryStats.ts           # 设置弹窗中的 GitHub 仓库统计加载\n    useRunLog.ts                    # 运行日志状态管理\n    useStorageEstimate.ts           # 本地存储容量估算\n  lib\u002F\n    actionDefaults.ts         # 常用截图动作默认值\n    actionParser.ts           # 动作解析、规范化和校验\n    actionPreview.ts          # 动作预览文案格式化\n    actionProtocol.ts         # 显式动作协议枚举\n    actionSafetyPolicy.ts     # 本地动作安全策略\n    actionTypes.ts            # 动作类型和校验错误定义\n    actions.ts                # 动作模块兼容导出口\n    agentResources.ts         # App 外的本地 Secret 和 Custom Tool 资源\n    agent.ts                  # Agent 循环调度\n    agentThread.ts            # 持久化 Agent thread\u002Fturn\u002Fevent 模型\n    appCards.ts               # 可编辑应用上下文卡片\n    appCopy.ts                # 界面文案聚合和语言解析\n    appCopy.en-US.ts          # 英文界面文案\n    appCopy.zh-CN.ts          # 中文界面文案\n    busyTask.ts               # 页面运行中任务标识\n    contextBuilder.ts         # 本轮模型上下文构建和压缩\n    deviceDoctor.ts           # 设备和模型配置诊断\n    deviceState.ts            # 设备状态展示格式化\n    interactionStream.ts      # 聊天消息和 Agent 步骤合并展示\n    openAiClient.ts           # OpenAI 兼容网络客户端\n    openAiErrors.ts           # OpenAI 客户端错误类型\n    openAiPayload.ts          # OpenAI 兼容请求体构造\n    openAiResponse.ts         # OpenAI 兼容响应读取和错误格式化\n    openAiRuntimeConfig.ts    # OpenAI 请求运行时配置\n    openAiTypes.ts            # OpenAI 客户端和消息类型\n    promptContextFormatting.ts # 模型上下文格式化工具\n    prompts.ts                # 提示词和动作规则\n    repository.ts             # 仓库链接和 GitHub 统计解析\n    runLogEntries.ts          # 运行日志条目和截图视图格式化\n    screenshot\u002F              # 截图坐标、上下文和内存保留策略\n      coordinates.ts\n      index.ts\n      retention.ts\n    settings.ts               # 本地设置读写\n    threadStore.ts            # Agent thread 持久化存储\n    toolRegistry.ts           # Agent 动作工具注册和执行入口\n  styles\u002F                    # 按页面区域拆分的样式\n    agent-step-card.css      # Agent 步骤卡片样式\n    chat-composer.css        # 聊天输入区样式\n    chat-history.css         # 历史会话侧栏样式\n    chat-panel.css           # 聊天面板样式\n    compact-section.css      # 折叠工具区样式\n    config-panel.css         # 设备和模型配置面板样式\n    config-rail.css          # 收起配置栏样式\n    controls.css             # 表单、按钮和通用控件样式\n    conversation-panel.css   # 会话面板外壳和待执行动作样式\n    device-doctor.css        # 设备诊断结果样式\n    device-options.css       # 设备执行选项样式\n    device-panel.css         # 设备连接区样式\n    direct-commands.css      # 直接命令面板样式\n    index.css                # 全局样式入口\n    installed-apps.css       # 已安装应用列表样式\n    layout.css               # 页面布局和面板外框\n    markdown-content.css     # Markdown 内容样式\n    model-panel.css          # 模型配置区样式\n    phone-stage.css          # 手机预览和动作覆盖层样式\n    responsive.css           # 响应式布局调整\n    run-log.css              # 运行日志样式\n    screenshot-lightbox.css  # 截图预览弹窗样式\n    settings-dialog.css      # 设置弹窗样式\n    theme.css                # 主题变量和基础 reset\n    tutorial-panel.css       # 教程面板样式\n  App.tsx                     # 页面状态、业务流程和组件编排\n  main.tsx                    # React 入口和全局样式加载\nserver\u002F\n  index.js                    # Docker 中的静态文件和 API 代理服务\n  openAiProxy.js              # OpenAI 兼容接口本地代理\n```\n\n## 验证\n\n```bash\nnpm test\nnpm run lint\nnpm run build\n```\n\n当前测试主要覆盖：\n\n- 动作解析和动作安全校验。\n- OpenAI 兼容请求体构造、响应解析和网络客户端错误处理。\n- Agent 单步和连续执行流程。\n- 失败反馈、瞬时模型 API 错误\u002F模型空回复重试和有限自动恢复。\n- 设置持久化和兼容迁移。\n- Agent thread\u002Fturn 持久化。\n- 已安装应用解析、匹配和完整上下文注入。\n- 截图坐标映射。\n- 运行日志、截图预览和主界面布局组件。\n\n真实设备控制仍需要连接 Android 设备进行手动验证。\n\n## 路线图\n\n- [x] 浏览器中通过 WebADB 连接 Android 设备。\n- [x] 截图并发送给 OpenAI 兼容视觉模型。\n- [x] 支持 canonical JSON 动作协议。\n- [x] 显式支持 `webdroid_json`、`open_autoglm_function`、`mobilerun_xml` 三种动作协议。\n- [x] 支持可编辑 App Cards、本地 Custom Tools 和安全 Secret 输入。\n- [x] 支持自动执行、单步执行和敏感动作确认。\n- [x] 支持运行日志和截图查看。\n- [x] 支持已安装应用列表、文本清空输入、可配置等待和基础失败恢复。\n- [ ] 补充更完整的真实设备验证矩阵。\n- [ ] 增加更多模型提供商配置示例。\n- [ ] 增强更系统的失败分类、动作重试和任务暂停恢复体验。\n- [ ] 提供更系统的安全策略和风险分级。\n\n## 贡献说明\n\n欢迎围绕以下方向提交 issue 或 pull request：\n\n- 新设备、新浏览器或新模型的兼容性反馈。\n- 动作解析、坐标映射、ADB 执行稳定性改进。\n- Open-AutoGLM 或其他手机 Agent 协议兼容。\n- 文档、示例任务、故障排查和安全建议补充。\n- UI 可用性、日志可读性和本地实验体验优化。\n\n提交改动前建议先运行：\n\n```bash\nnpm test\nnpm run lint\nnpm run build\n```\n\n## 部署到 Cloudflare Pages\n\n项目已创建在 Cloudflare Pages：\n\n- 历史在线地址（Pages 旧域名）：https:\u002F\u002Fwebadb-autoglm.pages.dev\u002F\n- 部署方式：GitHub 绑定自动部署\n\n重新部署：\n\n```bash\ngit push origin main\n```\n\n也可以本地先验证构建：\n\n```bash\nnpm run build\n```\n\nCloudflare Pages 使用普通 `npm run build`，不要设置 `VITE_OPENAI_PROXY_URL`。这样线上静态站点会继续由浏览器直接请求你填写的 OpenAI 兼容 API，不依赖 Docker 的本地 Node 代理。\n\n## License\n\n本项目基于 [MIT License](.\u002FLICENSE) 开源。你可以自由使用、复制、修改、分发和二次开发本项目代码，但需要保留原始版权声明和许可证文本。\n\n项目依赖的第三方库仍遵循各自的开源许可证，请在分发或商用前自行确认依赖合规性。\n\n## 相关项目和社区\n\n- [Tango \u002F WebADB](https:\u002F\u002Fgithub.com\u002Fyume-chan\u002Fya-webadb)：浏览器中的 ADB\u002FWebUSB 能力基础。\n- Open-AutoGLM：手机 GUI Agent 动作协议的重要参考。\n- Linux.do：活跃的中文技术社区，围绕 AI、软件开发、资源分享与前沿资讯展开讨论。\n","WebDroid Agent 是一个基于浏览器的 Android 手机代理实验项目，利用 WebADB\u002FWebUSB 和 OpenAI 兼容的视觉模型实现手机自动化控制。其核心功能包括通过浏览器连接已开启 USB 调试的 Android 设备，截取屏幕并发送给视觉模型处理，再将模型返回的动作解析并通过 ADB 执行。项目支持静态部署和 Docker 部署两种方式，前者完全在前端运行，后者则通过本地 API 代理解决跨域问题。适用于需要快速验证视觉模型与手机控制链路的场景，比如调试动作协议、研究不同风格动作兼容性或进行 Android UI 自动化原型实验。但不推荐用于涉及高风险操作如支付、登录等流程或需要长期稳定托管的生产环境。",2,"2026-06-11 04:00:15","CREATED_QUERY"]