diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index de4ac15c2..f8679078b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -184,7 +184,7 @@ jobs:
# 默认不启用 voice feature(包含 whisper-rs,编译很慢)
args: --target ${{ matrix.target }}
- - name: Build Tauri app (Windows)
+ - name: Build Tauri app (Windows online)
if: matrix.platform == 'windows-2022'
uses: tauri-apps/tauri-action@v0
env:
@@ -204,6 +204,33 @@ jobs:
releaseBody: ${{ env.RELEASE_BODY }}
releaseDraft: false
prerelease: false
+ # 默认推荐在线小包,安装时按需拉取 WebView2
+ releaseAssetNamePattern: "[name]_[version]_[arch]-online[setup][ext]"
+ # 默认不启用 voice feature(包含 whisper-rs,编译很慢)
+ args: --target ${{ matrix.target }} --config tauri.windows.online.conf.json
+
+ - name: Build Tauri app (Windows offline)
+ if: matrix.platform == 'windows-2022'
+ uses: tauri-apps/tauri-action@v0
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # 禁用 LTO 加速编译(正式发布可改为 thin)
+ CARGO_PROFILE_RELEASE_LTO: "off"
+ # 增加并行编译单元
+ CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 32
+ CARGO_INCREMENTAL: 0
+ SCCACHE_GHA_ENABLED: "true"
+ RUSTC_WRAPPER: sccache
+ with:
+ tauriScript: npx tauri
+ projectPath: src-tauri
+ tagName: ${{ github.event.inputs.version || github.ref_name }}
+ releaseName: "ProxyCast ${{ github.event.inputs.version || github.ref_name }}"
+ releaseBody: ${{ env.RELEASE_BODY }}
+ releaseDraft: false
+ prerelease: false
+ # 离线大包内置 WebView2 离线安装器,适用于无网环境
+ releaseAssetNamePattern: "[name]_[version]_[arch]-offline[setup][ext]"
# 默认不启用 voice feature(包含 whisper-rs,编译很慢)
args: --target ${{ matrix.target }} --config tauri.windows.conf.json
diff --git a/README.md b/README.md
index 0f08e1ca7..fd5788c24 100644
--- a/README.md
+++ b/README.md
@@ -1,112 +1,117 @@
-# ProxyCast 🚀
+# ProxyCast
-**创作类 AI Agent 平台**
+**以创作为中心的本地优先 AI Agent 交互工作台**
-一句话:把灵感、写作、出图、改稿、沉淀放进同一个工作台,让创作从“想到”直接走到“可发布”。
+一句话:用 Skills 组织经验与流程,用 MCP 接入标准能力,用 Claw 渠道把 Agent 带到飞书、Telegram 等入口,让创作、研究、执行与交付在同一个工作环境里闭合。
---
-## 👋 这是什么
+## 这是什么
-ProxyCast 是面向普通创作者的 AI Agent 平台。
-你不需要先懂复杂设置,只要带着一个想法进来,就可以在同一处完成:
+ProxyCast 是一个基于 Tauri 的桌面应用,面向创作者、内容团队与轻知识工作者。它把 Workspace、Agent、Skills、MCP、Claw 渠道和 Artifact 交付整合到同一个桌面环境里,让工作从输入需求直接走向可沉淀、可复用、可继续执行的结果。
-- 和 Agent 对话定方向
-- 生成内容与素材
-- 继续迭代修改
-- 把结果沉淀成可复用资产
+你可以在一个地方完成:
+
+- 在项目里与 Agent 协作
+- 生成和编辑文档、脚本、图文方案等产物
+- 使用浏览器、终端、MCP 和插件扩展执行空间
+- 让结果沉淀为可复用的记忆、风格和版本资产
---
-## 🧩 支持的创作主题
+## 产品核心
-你可以按创作目标选择主题,也可以跨主题组合使用。
+### 1. Workspace 是环境
-1. **通用对话**:灵感发散、问题梳理、快速头脑风暴
-2. **社媒内容**:选题、标题、正文、多平台改写
-3. **图文海报**:主视觉文案、配图方向、海报内容生成
-4. **歌词曲谱**:歌词起稿、段落续写、风格改编
-5. **知识探索**:知识点拆解、结构化总结、学习卡片
-6. **计划规划**:目标分解、执行节奏、阶段复盘
-7. **办公文档**:报告、方案、邮件、会议纪要整理
-8. **短视频**:脚本结构、分镜思路、口播文案生成
-9. **小说创作**:设定、章节推进、人物对白与续写
+- 项目、文件、会话、记忆、风格和人设围绕同一个工作区持续累积
+- 支持主题化工作台,覆盖通用对话、社媒内容、办公文档、视频、小说等场景
+
+### 2. Skills 是经验交互与流程编排
+
+- Skills 封装 prompt、references、scripts、assets 和调用规则
+- Skills 既定义如何交互,也定义任务如何推进
+- 它们是 ProxyCast 中经验复用、流程复用和领域方法沉淀的核心单元
+
+### 3. MCP 是标准能力层
+
+- 基于 MCP 接入 tools、resources、prompts 和工作边界
+- 让浏览器、文件、终端和外部服务成为 Agent 的标准化能力网络
+- 让 ProxyCast 的能力扩展建立在开放标准之上
+
+### 4. Claw 渠道是异步协作入口
+
+- 支持通过飞书、Telegram、Discord 等渠道与 Agent 持续协作
+- 支持远程触发、异步回流与渠道化交互
+- 让 Agent 不只存在于桌面窗口中
+
+### 5. Artifact 是交付物
+
+- 持续产出文档、脚本、草稿、海报方案与版本结果
+- 通过画布与工作流把过程沉淀到项目内,形成可复用的项目资产
+
+### 6. Agent Runtime 负责执行与编排
+
+- 基于 Aster Agent Runtime
+- 支持会话、流式执行、技能调用、子任务接力与长期运行
+- 底层保留多 Provider 接入、凭证池、路由与协议兼容能力
---
-## 📖 创作场景(不止一种)
+## 适合谁
-### 场景 1:社媒日更
-
-- 场景:每天都要稳定发内容,但选题和表达容易重复。
-- 动作:先让 Agent 给出 3 个方向,再选一个生成多版文案与配图思路。
-- 结果:当天可直接发布,同时保留素材供后续复用。
-
-### 场景 2:短视频起号
-
-- 场景:有想法但脚本总是“有点散”。
-- 动作:用主题工作流先拆结构,再生成口播稿和镜头节奏。
-- 结果:从模糊创意变成可拍摄脚本,沟通成本显著降低。
-
-### 场景 3:小说连载
-
-- 场景:长期连载容易设定冲突、节奏断档。
-- 动作:在同一项目里持续积累世界观、人物设定和章节草稿。
-- 结果:剧情连贯性更强,更新更稳定。
-
-### 场景 4:活动海报与图文
-
-- 场景:活动上线前要快速产出多套视觉方向。
-- 动作:先生成文案方向,再出图并按参考图持续迭代。
-- 结果:方案选择更快,历史版本可追溯、可复用。
-
-### 场景 5:歌词创作
-
-- 场景:有旋律或主题,但歌词总卡在中段。
-- 动作:让 Agent 先给主副歌框架,再逐段续写与改写。
-- 结果:成稿速度更快,风格更统一。
-
-### 场景 6:知识内容输出
-
-- 场景:学了很多但难以整理成可分享内容。
-- 动作:把资料整理成结构化要点,再输出为卡片或长文。
-- 结果:输入和输出形成闭环,知识更容易长期积累。
-
-### 场景 7:计划执行
-
-- 场景:目标很大,但每天不知道先做什么。
-- 动作:把目标拆成周计划与日任务,并按进度复盘调整。
-- 结果:执行路径清晰,可持续推进。
-
-### 场景 8:办公写作
-
-- 场景:报告、邮件、方案反复改,耗时高。
-- 动作:先生成初稿,再按受众快速改成不同版本。
-- 结果:沟通更顺,交付更快。
+- 内容创作者
+- 品牌与运营团队
+- 研究与知识整理型工作者
+- 需要本地优先、结果可追溯的小团队
---
-## 🎨 3 步开始创作
+## 典型场景
-1. **选主题**:按目标进入对应创作主题
-2. **给输入**:一句需求、一个方向或一份素材都可以
-3. **持续迭代**:边聊边改边沉淀,最终得到可发布结果
+### 场景 1:内容创作闭环
+
+- 从选题、研究、写作、改稿到最终成稿
+- Skills 驱动任务推进,对话、版本和风格资产持续沉淀在项目中
+
+### 场景 2:研究整理
+
+- 从网页资料、笔记、素材到提纲、报告和长文输出
+- 通过 Skills 与 MCP 把零散信息整理成结构化交付物
+
+### 场景 3:渠道化协作
+
+- 通过飞书、Telegram、Discord 等 Claw 渠道接收结果、触发任务、继续协作
+- 让 Agent 进入真实使用的消息入口,而不只停留在桌面端
+
+### 场景 4:浏览器与标准能力执行
+
+- 在同一个 Agent 会话里接入浏览器、文件、终端和外部服务
+- 让 MCP 成为标准能力层,而不是零散工具调用
+
+### 场景 5:批量与长期运行
+
+- 针对多条素材、模板或重复流程批量执行
+- 结合心跳、调度与渠道回流形成长期可运行的 Agent 流程
---
-## ❤️ 为什么好用
+## 如何工作
-- **一个地方完成全流程**:从想法到成品不用来回切工具
-- **结果自动沉淀**:历史对话、素材、版本都可回看
-- **越用越顺手**:每个项目都有自己的上下文记忆
+ProxyCast 的核心工作方式是:
+
+1. 在 Workspace 内组织项目、素材、记忆和风格
+2. 用 Skills 定义经验交互与流程推进
+3. 通过 MCP 接入标准化外部能力
+4. 通过 Claw 渠道把协作延伸到飞书、Telegram、Discord 等入口
+5. 让结果沉淀为文档、脚本、版本和后续任务输入
---
-## 🚀 快速开始
+## 快速开始
### 安装
@@ -121,27 +126,18 @@ brew install --cask proxycast
从 [Releases](https://github.com/aiclientproxy/proxycast/releases) 下载对应平台安装包。
-- Windows 用户优先下载 `ProxyCast_*_x64-setup.exe`(NSIS 安装器)
-- 该安装器已内置 WebView2 Offline Installer,弱网/离线环境成功率更高
+- Windows 用户默认优先下载 `ProxyCast_*_x64-online-setup.exe`(NSIS 在线安装器,体积更小)
+- 如果处于离线、内网或受限网络环境,请改用 `ProxyCast_*_x64-offline-setup.exe`
- 如被 SmartScreen 拦截,属于未签名或签名信誉不足的 Windows 常见提示,不代表安装包必然损坏
---
-## 🧭 适合谁
+## 文档与开发
-- 自媒体创作者
-- 短视频团队
-- 小说与剧情创作者
-- 运营与品牌内容团队
-- 需要长期沉淀创作资产的个人与小团队
-
----
-
-## 📚 文档与开发(可选)
-
-如果你是开发者,可查看:
+如果你是开发者,可查看以下文档:
- 项目文档:`docs/aiprompts/`
+- 官网定位 PRD:`docs/PRD/website-positioning-prd.md`
- Agent 指南:`AGENTS.md`
开发命令:
@@ -157,11 +153,11 @@ npm run tauri build
---
-## 📄 开源协议
+## 开源协议
[GNU General Public License v3 (GPLv3)](https://www.gnu.org/licenses/gpl-3.0)
-## ⚠️ 免责声明
+## 免责声明
本项目仅供学习研究使用,用户需自行承担使用风险。
本项目不直接提供 AI 模型服务,模型能力由第三方提供商提供。
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 704269f10..e121f503a 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,46 +1,52 @@
-## ProxyCast v0.87.0
+## ProxyCast v0.88.0
### ✨ 新功能
-- **浏览器协助运行时**:新增 `browser-runtime` crate、Tauri 命令与调试页,支持在 Agent 会话内拉起浏览器协助能力
-- **Browser Assist 产物渲染**:新增 Browser Assist Artifact 渲染器,可在 General 会话中直接承接浏览器协助状态与操作
-- **画布工作台布局**:新增 `CanvasWorkbenchLayout`,支持预览 / 文件 / 差异 / 工作台联动,以及分栏与堆叠两种布局模式
-- **技能显式选择器**:新增 `SkillSelector` 与相关 harness skill 聚合逻辑,提升技能发现、点选与触发体验
-- **新任务入口模式**:新增 `new-task` 入口、空状态页与会话恢复控制,梳理 Claw / 新任务两类进入路径
+- **自动化任务中心**:新增 `automation` 命令、服务、DAO 与设置页,支持定时任务、计划预览、健康检查、运行历史,以及 `Agent 对话任务 / 浏览器会话任务` 两种执行形态
+- **浏览器资料与环境预设**:新增 Browser Profile / Browser Environment Preset 管理,支持托管浏览器与附着当前 Chrome 两种资料模式,并可直接复用于浏览器运行时
+- **浏览器现有会话接管**:补齐 existing session attach、页签切换、桥接状态同步与 Browser Runtime 工作区协同链路
+- **Agent Chat 决策与空状态升级**:新增 `DecisionPanel`、空状态 Hero / Quick Actions、A2UI 预览卡、线程分组与消息轮次分组,强化新任务入口与浏览器协助预热
### 🔧 优化与重构
-- **General Chat 主流程重构**:重写 Agent Chat 页的大量 General 场景逻辑,统一画布、Artifact、Workbench 与浏览器协助状态
-- **Webview / Browser Runtime 协调增强**:扩展 `webview_cmd`、窗口服务与前端 API,补齐浏览器运行时会话、窗口与控制链路
-- **Settings v2 大规模重排**:重构外观、快捷键、频道、Chrome Relay、环境、安全性能、账户统计等设置页
-- **项目与记忆工作区升级**:重构内容列表、内容编辑器、项目选择器及多类 Memory 面板,统一信息架构与交互密度
-- **导航与侧栏收敛**:调整应用侧栏、任务侧栏、资源与工作区导航,移除部分旧页面与冗余入口
+- **执行系统收敛**:移除旧 `batch` 页面/API 与 `heartbeat` 命令/设置入口,统一收口到 `automation` 与 `execution tracker`
+- **OpenClaw 工作台重做**:重排安装、配置、运行、Dashboard 与进度页,补强 Windows 环境检测、修复引导与诊断复制
+- **Settings v2 持续整理**:合并媒体服务设置,重构 Chrome Relay、Execution Tracker、About、Appearance 等页面,统一导航与信息架构
+- **资源与创作工作台更新**:重构资源页、图像生成、视频画布、项目选择器与多处内容创作界面,提升工作区一致性
### 🐛 修复
-- **前端 Hooks 依赖修复**:补齐 `useCallback` 依赖,消除 `npm run lint` 中的 `react-hooks/exhaustive-deps` 警告
-- **Rust Clippy 清理**:移除浏览器运行时客户端中的冗余类型转换,保持 `cargo clippy` 输出干净
-- **日志测试并发污染修复**:将日志诊断测试切到独立临时目录,避免并行测试互相删除 `raw_response` 工件
-- **Workspace 错误态兜底**:补强任务侧栏与相关页面的 workspace 异常显示与恢复路径
+- **插件兼容与更新提示补强**:插件管理页新增 Windows 主程序升级入口和最低版本提示,降低插件与主程序版本错配的排障成本
+- **Browser Runtime / DevBridge 稳定性提升**:补齐浏览器会话启动参数、流诊断、桥接 mock 与状态同步,减少运行时偏差
+- **Provider 配置读写修复**:完善 API Key Provider 的 `api_version`、`project` 等配置项读写与表单校验
+- **Windows 启动与安装诊断改进**:补充安装说明、常见问题与构建文档,降低受限网络与依赖缺失场景下的排障摩擦
+
+### ⚠️ 兼容性调整
+
+- 旧 `Batch` / `Heartbeat` 相关前端入口与后端命令已下线;既有流程请迁移到新的 `Automation` 设置页与统一执行记录
### 🧪 测试
-- 新增 Browser Assist、Canvas Workbench、Skill Selector、General Resource Sync、Harness Skills 等前端测试
-- 补充项目页、设置页、统计页、内存面板等多处 UI / 交互测试
+- 新增 Automation、Browser Profile / Environment Preset、Existing Session Attach、Agent Chat 分组与插件版本提示等测试覆盖
+- 补充 Browser Runtime、OpenClaw、Execution Tracker、Chrome Relay 与多处设置页交互测试
- 发布前已执行:`cargo fmt --all`、`cargo test`、`cargo clippy`、`npm run lint`
### 📝 文档
-- 补充 Agent Chat / Components 文档说明
-- 新增 `docs/research/` 研究资料目录
-- 更新发布流程相关说明,覆盖 headless Tauri 配置版本同步
+- 更新 README、架构概览、安装、故障排查、构建与运维文档
+- 补充 NextBrowser 相关研究资料与浏览器自动化设计记录
### 🛠️ 开发体验
-- **版本一致性检查增强**:`check-app-version-consistency.mjs` 现覆盖 `tauri.conf.headless.json`
-- **Release Workflow 补强**:GitHub Release 工作流现同步标准与 headless 两份 Tauri 配置版本
-- **跨端发布一致性提升**:统一 `package.json`、Cargo workspace、Tauri 配置与 release notes 的版本入口
+- **Windows 发布流程增强**:Release Workflow 现同时产出在线 / 离线两个 Windows 安装包
+- **版本源保持一致**:统一 `package.json`、Cargo workspace、两份 Tauri 配置与 `RELEASE_NOTES.md` 的发布版本入口
+
+### 📦 Windows 下载说明
+
+- `ProxyCast_*_x64-online-setup.exe`:默认推荐,体积更小,安装时按需下载 WebView2
+- `ProxyCast_*_x64-offline-setup.exe`:适用于离线、内网或受限网络环境
+- 如果在线安装失败,请改用离线安装包
---
-**完整变更**: v0.86.0...v0.87.0
+**完整变更**: v0.87.0...v0.88.0
diff --git a/docs/aiprompts/overview.md b/docs/aiprompts/overview.md
index b6a355a01..115decca7 100644
--- a/docs/aiprompts/overview.md
+++ b/docs/aiprompts/overview.md
@@ -2,7 +2,25 @@
## 概述
-ProxyCast 是一个 Tauri 桌面应用,作为 LLM API 代理网关,支持多 Provider 凭证池管理、协议转换、流量监控等功能。
+ProxyCast 是一个以创作为中心的本地优先 AI Agent 交互工作台,基于 Tauri 桌面应用构建,面向创作者、内容团队与轻知识工作者。系统由 Workspace、Skills 编排层、MCP 标准能力层、Claw 渠道层、Artifact 交付层与多模型接入能力共同组成。
+
+可以把它理解为三层结构:
+
+1. **产品层**:Workspace、主题工作台、Agent 对话、Skills、Artifact/Canvas、记忆与风格
+2. **能力层**:MCP、浏览器运行时、终端、插件、批量/心跳、Claw 渠道
+3. **基础设施层**:Aster Agent、Provider 凭证池、协议兼容、路由、服务器、数据库与监控
+
+其中,Provider 接入、协议兼容与运行时服务共同构成底层能力底座。
+
+同时,术语上应与当前 Agent 生态保持一致:
+
+- **Sessions**:长期会话与协作上下文
+- **Handoffs**:任务接力与多阶段编排
+- **Guardrails**:权限边界、审批与调用限制
+- **Tracing**:时间线、步骤与调用轨迹可观测
+- **MCP**:tools / resources / prompts / roots 的标准能力接入
+
+在 ProxyCast 中,Skills 处于比 MCP 更贴近产品的一层:它不是底层原语,而是将领域经验、交互方式和执行流程打包后的编排单元。
## 项目结构
@@ -26,51 +44,106 @@ proxycast/
└── docs/ # 文档
```
-## 核心模块
+## 架构分层
-### 后端 (src-tauri/src/)
+### 产品层
| 模块 | 说明 |
|------|------|
+| `workspace/` | 工作区与项目边界,承载文件、会话与配置上下文 |
+| `components/agent/` | Agent 对话主入口,负责会话、流式事件与交互 |
+| `components/content-creator/` | 主题化创作工作台与画布联动 |
+| `skills/` | 技能加载、标准校验与经验编排能力 |
+| `lib/artifact/` | Artifact 解析、状态与轻量渲染器 |
+| `memory / style / personas` | 项目记忆、风格策略与人设沉淀 |
+
+### 能力层
+
+| 模块 | 说明 |
+|------|------|
+| `src/features/browser-runtime/` | 浏览器协助运行时与调试工作区 |
+| `src-tauri/src/terminal/` | 内置终端与 PTY 会话 |
+| `src-tauri/src/services/heartbeat_service/` | 异步调度、周期任务与投递 |
+| `src-tauri/src/plugin/` | 插件系统 |
+| `src-tauri/src/services/mcp_service.rs` | MCP 服务器与工具管理 |
+| `src-tauri/src/commands/gateway_channel_cmd.rs` | Telegram / Feishu / Discord Claw 渠道运行时 |
+| `src-tauri/src/commands/telegram_remote_cmd.rs` | Telegram 远程触发入口 |
+
+### 基础设施层
+
+| 模块 | 说明 |
+|------|------|
+| `src-tauri/src/agent/` | Aster Agent 集成、会话、工具注册与流式桥接 |
| `providers/` | LLM Provider 认证和 API 实现 |
| `services/` | 业务服务层 |
-| `converter/` | 协议转换 (OpenAI ↔ CW/Claude) |
+| `converter/` | 协议转换与兼容层 |
| `server/` | HTTP API 服务器 |
| `credential/` | 凭证池管理 |
| `flow_monitor/` | 流量监控 |
-| `terminal/` | 内置终端 |
+| `database/` | 数据持久化与 DAO |
-### 前端 (src/)
+## 核心模块视图
+
+### 后端(`src-tauri/src/`)
| 模块 | 说明 |
|------|------|
-| `components/` | React 组件 |
+| `agent/` | Aster Agent 运行时桥接与会话管理 |
+| `skills/` | Skills 标准集成、动态加载与执行回调 |
+| `providers/` | 多 Provider 认证与请求发送 |
+| `services/` | 心跳、OpenClaw、浏览器窗口、MCP 等业务服务 |
+| `converter/` | 协议兼容与转换 |
+| `server/` | HTTP Server 与 REST 能力 |
+| `terminal/` | 终端与 PTY |
+| `plugin/` | 插件加载与运行时 |
+| `voice/` | 语音输入输出与 ASR 流程 |
+
+### 前端(`src/`)
+
+| 模块 | 说明 |
+|------|------|
+| `components/` | 主 UI 组件与主题工作台 |
+| `features/` | 浏览器运行时等较独立特性域 |
| `hooks/` | 业务逻辑 Hooks |
-| `lib/` | 工具函数和 API 封装 |
-| `pages/` | 页面组件 |
+| `lib/api/` | Tauri API 与运行时封装 |
+| `lib/artifact/` | Artifact 状态与解析 |
+| `pages/` | 独立窗口与页面入口 |
## 数据流
```
┌─────────────────────────────────────────────────────────────────┐
-│ 客户端请求 (Cursor/Continue) │
+│ 用户请求(工作台 / 对话 / Skills / 飞书 / Telegram) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
-│ HTTP Server │
+│ Workspace / Project / Memory Layer │
+│ 项目路径、工作区配置、主题、记忆、人设、风格、产物上下文 │
+└─────────┬───────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ Skills / Orchestration Layer │
+│ 经验规则、references、scripts、流程推进、任务接力与阶段切换 │
+└─────────┬───────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ Agent Runtime │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
-│ │ OpenAI API │ │ Claude API │ │ Flow Monitor │ │
-│ │ 兼容端点 │ │ 兼容端点 │ │ (请求拦截) │ │
+│ │ Aster Agent │ │ Session │ │ Stream / Action │ │
+│ │ 执行 │ │ 状态 │ │ Request │ │
│ └──────┬──────┘ └──────┬──────┘ └───────────┬─────────────┘ │
└─────────┼────────────────┼─────────────────────┼────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
-│ Router / Processor │
+│ Execution Surface │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
-│ │ 模型路由 │ │ 协议转换 │ │ 弹性策略 │ │
-│ │ (规则匹配) │ │ (Converter) │ │ (重试/超时) │ │
+│ │ MCP Tools / │ │ Browser / │ │ Claw Channels / │ │
+│ │ Resources / │ │ Terminal / │ │ Heartbeat / Plugins │ │
+│ │ Prompts │ │ Files │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ └───────────┬─────────────┘ │
└─────────┼────────────────┼─────────────────────┼────────────────┘
│ │ │
@@ -89,50 +162,73 @@ proxycast/
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Kiro │ │ Gemini │ │ Claude │ │ OpenAI │ ... │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ Artifact / Canvas Layer │
+│ 文档、脚本、海报、版本链、画布状态、导出结果与任务沉淀 │
└─────────────────────────────────────────────────────────────────┘
```
## 关键特性
-### 1. 多 Provider 支持
-- OAuth: Kiro, Gemini, Qwen, Claude, Antigravity
-- API Key: OpenAI, Claude, 自定义
+### 1. Workspace 驱动
+- Workspace 既是文件边界,也是 context 边界和配置边界
+- 项目、会话、记忆、风格和 Artifact 围绕同一工作区组织
-### 2. 凭证池管理
-- 多凭证轮询负载均衡
-- 自动健康检查和剔除
-- Token 自动刷新
+### 2. Skills 驱动
+- Skills 是经验交互、流程编排与领域方法沉淀的核心单元
+- Skills 可封装 prompt、references、scripts、assets 与调用规则
+- Agent 运行时可动态加载、自动发现与调用 Skills
-### 3. 协议转换
-- OpenAI ↔ CodeWhisperer
-- OpenAI ↔ Claude
-- OpenAI ↔ Antigravity
+### 3. MCP 标准能力层
+- 基于 MCP 管理 tools、resources、prompts 与读取边界
+- 为 Agent 提供标准化能力发现、调用与上下文共享方式
-### 4. 流量监控
-- 请求/响应拦截
-- Token 统计
-- 历史查询
+### 4. Claw 渠道协作
+- 支持 Telegram / Feishu / Discord 等渠道运行时
+- 支持远程触发、异步协作、消息回流与外部入口接入
+
+### 5. Agent Runtime
+- 基于 Aster Agent,支持会话、流式事件、工具调用与多模型配置
+- 支持任务接力、会话持续化、步骤可观测与长期运行
+
+### 6. Artifact First
+- 输出不止是聊天文本,还包括文档、草稿、脚本、版本链与画布产物
+- `write_file`、画布联动与主题工作流负责把过程沉淀成交付物
+
+### 7. 多 Provider 与兼容层
+- OAuth 与 API Key Provider 并存
+- 凭证池、模型路由、协议兼容与 HTTP Server 作为底层支撑
+
+### 8. 本地优先与可扩展
+- 桌面应用、本地工作区、插件与外部工具扩展
+- 允许在不改变产品主形态的前提下向更多执行环境延展
## 文档索引
-### 核心系统
+### 产品与工作台
+- [workspace.md](workspace.md) - Workspace 边界与工作区设计
+- [content-creator.md](content-creator.md) - 主题化创作工作台
+- [../../src-tauri/src/skills/README.md](../../src-tauri/src/skills/README.md) - Skills 标准与集成
+- [terminal.md](terminal.md) - 终端能力
+- [mcp.md](mcp.md) - MCP 服务器
+- [plugins.md](plugins.md) - 插件系统
+- [aster-integration.md](aster-integration.md) - Agent Runtime 集成
+
+### 基础设施
- [providers.md](providers.md) - Provider 系统
- [credential-pool.md](credential-pool.md) - 凭证池管理
- [converter.md](converter.md) - 协议转换
- [server.md](server.md) - HTTP 服务器
-### 前端模块
+### 前端与公共模块
- [components.md](components.md) - 组件系统
- [hooks.md](hooks.md) - React Hooks
- [lib.md](lib.md) - 工具库
-### 功能模块
-- [flow-monitor.md](flow-monitor.md) - 流量监控
-- [terminal.md](terminal.md) - 内置终端
-- [mcp.md](mcp.md) - MCP 服务器
-- [plugins.md](plugins.md) - 插件系统
-
-### 配置与服务
+### 配置、服务与数据
- [commands.md](commands.md) - Tauri 命令
- [services.md](services.md) - 业务服务
- [database.md](database.md) - 数据库层
diff --git a/docs/content/01.introduction/2.installation.md b/docs/content/01.introduction/2.installation.md
index 3e0356cd0..3397a9f96 100644
--- a/docs/content/01.introduction/2.installation.md
+++ b/docs/content/01.introduction/2.installation.md
@@ -16,16 +16,17 @@ navigation:
## 下载
-从 GitHub Releases/Tags 下载最新版本安装包:
+从 GitHub Releases 下载最新版本安装包:
-[下载 ProxyCast](https://github.com/aiclientproxy/proxycast/tags)
+[下载 ProxyCast](https://github.com/aiclientproxy/proxycast/releases)
### 安装包
| 平台 | 文件名 | 说明 |
|------|--------|------|
| macOS | `ProxyCast_x.x.x_aarch64.dmg` | Apple Silicon Mac |
-| Windows | `ProxyCast_x.x.x_x64-setup.exe` | Windows 64位 |
+| Windows | `ProxyCast_x.x.x_x64-online-setup.exe` | 默认推荐,体积更小,安装时按需下载 WebView2 |
+| Windows | `ProxyCast_x.x.x_x64-offline-setup.exe` | 离线、内网或受限网络环境使用 |
## macOS 安装
@@ -40,11 +41,15 @@ navigation:
## Windows 安装
-1. 下载 `.exe` 安装程序
+1. 优先下载 `ProxyCast_x.x.x_x64-online-setup.exe`
2. 双击运行安装程序
3. 按照安装向导完成安装
4. 从开始菜单启动 ProxyCast
+::alert{type="info"}
+如果设备处于离线、内网或受限网络环境,请改用 `ProxyCast_x.x.x_x64-offline-setup.exe`。
+::
+
## 验证安装
启动 ProxyCast 后,你应该看到:
diff --git a/docs/content/05.troubleshooting/1.common-issues.md b/docs/content/05.troubleshooting/1.common-issues.md
index f7cfa805d..410c441a2 100644
--- a/docs/content/05.troubleshooting/1.common-issues.md
+++ b/docs/content/05.troubleshooting/1.common-issues.md
@@ -107,10 +107,11 @@ navigation:
### 处理建议
-1. 优先重新下载安装 `ProxyCast_*_x64-setup.exe`
+1. 优先重新下载安装 `ProxyCast_*_x64-online-setup.exe`
2. 确认 `%APPDATA%\proxycast\` 与 `%USERPROFILE%\.proxycast\` 可写
3. 如被 SmartScreen 拦截,确认来源可信后再继续
-4. 如有条件,运行一键收集脚本后再反馈
+4. 如果处于离线、内网或受限网络环境,改用 `ProxyCast_*_x64-offline-setup.exe`
+5. 如有条件,运行一键收集脚本后再反馈
详见 [Windows 启动与安装问题](/troubleshooting/windows-startup-issues)。
diff --git a/docs/content/05.troubleshooting/4.windows-startup-issues.md b/docs/content/05.troubleshooting/4.windows-startup-issues.md
index 0ac14a942..af6cbff0a 100644
--- a/docs/content/05.troubleshooting/4.windows-startup-issues.md
+++ b/docs/content/05.troubleshooting/4.windows-startup-issues.md
@@ -20,7 +20,7 @@ navigation:
推荐优先使用:
-- `ProxyCast_*_x64-setup.exe`
+- `ProxyCast_*_x64-online-setup.exe`
不建议优先分发:
@@ -29,8 +29,8 @@ navigation:
原因:
-- `setup.exe` 会一并处理 WebView2 Offline Installer
-- 在弱网、离线或新系统环境下成功率更高
+- 在线安装包体积更小,适合大多数 Windows 10/11 用户
+- 如果处于离线、内网或受限网络环境,请改用 `ProxyCast_*_x64-offline-setup.exe`
## 常见症状与处理
@@ -40,14 +40,14 @@ navigation:
1. 确认下载来源可信
2. 如果被 SmartScreen 拦截,点击“更多信息”后再确认是否继续
-3. 重新运行 `setup.exe` 覆盖安装
+3. 重新运行 Windows setup 安装包覆盖安装
4. 安装后从开始菜单再次启动
### 启动后白屏
处理建议:
-1. 优先重装 `setup.exe`,补齐 WebView2 Runtime
+1. 优先重装 Windows setup 安装包,补齐 WebView2 Runtime
2. 检查系统是否禁用了 Edge WebView2 Runtime
3. 再确认本地目录是否可写
@@ -56,7 +56,7 @@ navigation:
处理建议:
1. 不要先手动找旧版运行时
-2. 先重新运行 `setup.exe`
+2. 先重新运行 Windows setup 安装包
3. 如仍失败,再单独检查 WebView2 Runtime 是否安装完整
## 目录权限检查
diff --git a/docs/content/06.development/3.building.md b/docs/content/06.development/3.building.md
index fa4992755..4734d7e73 100644
--- a/docs/content/06.development/3.building.md
+++ b/docs/content/06.development/3.building.md
@@ -50,7 +50,7 @@ xcode-select --install
**Windows:**
- 安装 Visual Studio Build Tools
-- 安装 WebView2(开发模式必需;对外分发时建议使用带离线 WebView2 的 NSIS 安装器)
+- 安装 WebView2(开发模式必需;对外分发时默认推荐在线小包,离线或受限网络环境再提供离线大包)
**Linux:**
@@ -141,11 +141,14 @@ pnpm tauri build --target universal-apple-darwin
#### Windows 构建
```bash
-# 构建 64 位 Windows 安装包(NSIS setup.exe,内置离线 WebView2 安装器)
+# 构建 64 位 Windows 在线安装包(推荐,体积更小,安装时按需下载 WebView2)
+pnpm tauri build --target x86_64-pc-windows-msvc --config src-tauri/tauri.windows.online.conf.json
+
+# 构建 64 位 Windows 离线安装包(体积更大,内置离线 WebView2 安装器)
pnpm tauri build --target x86_64-pc-windows-msvc --config src-tauri/tauri.windows.conf.json
```
-> 建议对外分发 `-setup.exe`,不要把默认 `.msi` 作为首选下载项。
+> 建议默认对外分发在线小包;只有内网、离线或受限网络环境,再提供离线大包。
#### Linux 构建
diff --git a/docs/content/06.development/4.operations.md b/docs/content/06.development/4.operations.md
index 01df37d30..5f0e3b2df 100644
--- a/docs/content/06.development/4.operations.md
+++ b/docs/content/06.development/4.operations.md
@@ -42,8 +42,8 @@ navigation:
## Windows 启动失败排查
-- 优先确认用户安装的是 `ProxyCast_*_x64-setup.exe`,不要默认分发便携包或旧的 `.msi`
-- 首次启动若提示缺少运行时,优先重新运行 `setup.exe`,它会一并安装 WebView2 Offline Installer
+- 优先确认用户安装的是 `ProxyCast_*_x64-online-setup.exe`;离线、内网或受限网络环境再提供 `ProxyCast_*_x64-offline-setup.exe`
+- 首次启动若提示缺少运行时,优先重新运行 Windows setup 安装包;如果在线安装失败,再切换到 offline 安装包
- 检查 `%APPDATA%\proxycast\` 与 `%USERPROFILE%\.proxycast\` 是否可写;数据库、日志与部分运行时状态依赖这两个目录
- 收集 `%USERPROFILE%\.proxycast\logs\` 与 `%USERPROFILE%\.proxycast\request_logs\` 作为一线排障材料
- 若前端出现 Windows 启动自检提示,按提示项优先检查目录权限、数据库可访问性、WebView2 与 Shell 可用性
diff --git a/docs/research/nextbrowser-features-analysis.md b/docs/research/nextbrowser-features-analysis.md
index 788419984..b07a0c5c3 100644
--- a/docs/research/nextbrowser-features-analysis.md
+++ b/docs/research/nextbrowser-features-analysis.md
@@ -1608,3 +1608,474 @@ Proxycast 已经具备了 CDP 基础设施,采用**渐进式增强**策略:
- ✅ Screencast 优先,Screenshot fallback
- ✅ 单 page target 先行,多 tab 后续
- ✅ 高层 action API,原始 CDP 仅调试用
+
+---
+
+## 九、基于当前代码库的差距复盘(截至 2026-03-15)
+
+> 本节用于校正文档前文的“规划态”描述,按当前仓库真实实现判断 Proxycast 已做到什么、还缺什么,以及后续应如何按基础设施优先推进。
+
+### 9.1 当前已经具备的能力底座
+
+#### A. 实时画面与 CDP 会话底座:已具备,可继续加固
+- 已有 `BrowserRuntimeManager`、`CdpSessionState`、事件缓冲区、人工接管状态机:
+ - `src-tauri/crates/browser-runtime/src/manager.rs`
+ - `src-tauri/crates/browser-runtime/src/types.rs`
+- 已支持 `Page.startScreencast`,失败时自动回退到 `Page.captureScreenshot` 轮询:
+ - `src-tauri/crates/browser-runtime/src/manager.rs`
+- 已暴露 Tauri 命令与前端调试页:
+ - `src-tauri/src/commands/browser_runtime_cmd.rs`
+ - `src-tauri/src/commands/webview_cmd.rs`
+ - `src/features/browser-runtime/BrowserRuntimeWorkspace.tsx`
+ - `src/features/browser-runtime/BrowserRuntimeDebugPanel.tsx`
+
+#### B. 浏览器 Profile 隔离:已具备基础,但还不是产品级“个人资料”
+- 已支持按 `profile_key` 启动独立 Chrome 用户目录,天然保留 cookies / localStorage / 登录态:
+ - `src-tauri/src/commands/webview_cmd.rs`
+- 已支持列出和关闭运行中的 Profile 会话:
+ - `get_chrome_profile_sessions`
+ - `close_chrome_profile_session`
+- 现状问题:
+ - 只有“运行中的 Chrome profile 目录”概念,没有“可管理的 Profile 实体”概念
+ - 没有名称、标签、站点、最后使用时间、描述、导入/导出、锁定策略、加密策略
+ - 没有“保存当前登录为资料”的明确工作流
+
+#### C. 调度引擎:已具备通用能力,但不是浏览器任务编排
+- 已有调度器、轮询执行器、Cron/At/Every 调度计算与健康治理:
+ - `src-tauri/crates/scheduler/src/*`
+ - `src-tauri/src/app/scheduler_service.rs`
+ - `src-tauri/src/services/heartbeat_service/*`
+ - `src-tauri/src/commands/heartbeat_cmd.rs`
+- 现状问题:
+ - 当前主要服务于 Heartbeat/通用任务,不是浏览器自动化任务模板
+ - 缺少“任务绑定哪个 browser profile / 环境预设 / 输出 schema / 人工检查点”的模型
+
+#### D. 浏览器动作与输出:已具备最小可用能力
+- 已支持 `navigate / click / type / scroll / read_page / read_console_messages / read_network_requests`
+- 已有统一的 `browser_execute_action` 多后端编排:
+ - `src-tauri/src/commands/webview_cmd.rs`
+ - `src-tauri/crates/browser-runtime/src/action.rs`
+- 现状问题:
+ - 输出仍偏底层:`markdown / page_info / console / network event`
+ - 没有任务级结构化输出合同,例如 `json schema / table / csv / fields mapping`
+
+### 9.2 与截图功能的差距矩阵
+
+| 功能 | 当前状态 | 结论 |
+|------|----------|------|
+| 实时画面 | 已有 CDP 帧流、回退截图、调试页、人工接管 | 已做基础版,需稳定化和产品化 |
+| 个人资料(已保存的登录信息) | 已有独立 Chrome profile 目录和会话复用 | 部分完成,缺产品级资料管理 |
+| 计划任务 | 已有通用调度器、Heartbeat、Cron 校验 | 部分完成,缺浏览器任务模型与 UI |
+| 输入和输出 | 已有页面信息、控制台、网络事件、动作执行结果 | 部分完成,缺结构化 I/O 层 |
+| 位置定制 | 未见浏览器级代理、地理位置、时区、语言、UA、指纹预设 | 未实现 |
+| 证书 | 未见浏览器级客户端证书/站点证书选择与存储模型 | 未实现 |
+| 自动验证码求解器 | 仅支持人工接管,没有 solver 抽象与供应商接入 | 未实现 |
+| 连接 | 现有 `connection_cmd` 是终端/SSH/WSL 连接,不是外部业务连接器 | 未实现截图语义下的连接器 |
+
+### 9.3 架构判断:先不要直接堆功能页
+
+如果现在直接开始补“位置定制 / 计划任务 / 连接 / 输入和输出”这些页面,仓库会出现新的平行概念:
+- 一套运行中 session 概念
+- 一套 Chrome profile 目录概念
+- 一套 Heartbeat 任务概念
+- 一套未来的浏览器任务概念
+
+这会导致三类问题:
+- 状态源分裂:Profile、Session、Task、Connector 各自一套 id 和生命周期
+- 配置不可复用:位置定制、登录资料、任务调度之间无法组合
+- 上层功能失去稳定锚点:定时任务、验证码、人机接管都需要先有稳定的会话装配模型
+
+因此正确顺序不是“按截图逐个做页面”,而是先补一层浏览器控制面(control plane)。
+
+### 9.4 建议新增的统一域模型
+
+#### 1. Browser Profile
+表示一个“可复用的登录资料容器”,而不是当前仅存在的目录。
+
+建议字段:
+- `id`
+- `key`
+- `name`
+- `description`
+- `site_scope`
+- `storage_mode`:`persistent | ephemeral`
+- `profile_dir`
+- `last_used_at`
+- `created_at`
+- `updated_at`
+- `archived_at`
+
+#### 2. Browser Environment Preset
+承载“位置定制”能力,后续任务和 Profile 都引用它。
+
+建议字段:
+- `id`
+- `name`
+- `proxy_type`
+- `proxy_server`
+- `proxy_auth_ref`
+- `country`
+- `region`
+- `city`
+- `timezone_id`
+- `locale`
+- `accept_language`
+- `geolocation_lat`
+- `geolocation_lng`
+- `geolocation_accuracy_m`
+- `user_agent`
+- `viewport_width`
+- `viewport_height`
+- `device_scale_factor`
+- `platform`
+
+#### 3. Browser Task Template
+承载“计划任务”的可执行定义,复用现有 scheduler,而不是另起炉灶。
+
+建议字段:
+- `id`
+- `name`
+- `entry_url`
+- `profile_id`
+- `environment_preset_id`
+- `schedule_kind`
+- `schedule_payload`
+- `steps`
+- `requires_human_checkpoint`
+- `output_schema`
+- `output_destination`
+- `enabled`
+
+#### 4. Browser Connector
+承载“连接”能力,目标是把结果投递到外部系统,而不是终端连接。
+
+建议字段:
+- `id`
+- `type`:`google_sheets | gmail | webhook | drive | notion | ...`
+- `name`
+- `auth_kind`
+- `secret_ref`
+- `config_json`
+- `status`
+- `last_checked_at`
+
+#### 5. Browser Certificate Asset
+承载浏览器证书与站点绑定。
+
+建议字段:
+- `id`
+- `name`
+- `cert_kind`:`client_tls | custom_ca`
+- `file_ref`
+- `passphrase_ref`
+- `host_patterns`
+- `created_at`
+
+### 9.5 推荐实施优先级
+
+#### P0. 收口现有浏览器控制面(最高优先级)
+目标:把“运行时会话”变成后续一切能力的稳定底座。
+
+本阶段做什么:
+- 把当前 `profile_key` 升级为数据库中的 `Browser Profile` 实体
+- 给运行时 session 增加 `profile_id / environment_preset_id / task_id` 关联位
+- 把 `open_chrome_profile_window` 的启动参数抽象成 `LaunchBrowserSessionRequest`
+- 保持现有 `cdp_direct / extension_bridge / aster_compat` 编排不变,只收口输入模型
+- 给浏览器会话增加稳定审计日志:谁启动、带什么环境、来自哪个任务
+
+本阶段不做什么:
+- 不先做 CAPTCHA
+- 不先做连接器 UI
+- 不先做证书上传页
+
+原因:
+- 没有统一控制面,上层功能都会变成一次性参数拼装,后续很难维护
+
+#### P1. 个人资料产品化(高优先级)
+目标:让“保存的登录”从目录能力升级为可管理资产。
+
+本阶段做什么:
+- 新增 Profile 列表、创建、重命名、归档、删除、最近使用
+- 支持“从当前运行会话保存为资料”
+- 支持“打开资料并进入人工登录”
+- 支持资料与站点作用域绑定
+- 支持资料锁定策略和敏感信息隔离说明
+
+验收标准:
+- 用户可以明确看到哪些登录资料存在
+- 用户可以复用而不是记 `profile_key`
+- Agent 可以按 `profile_id` 复用资料
+
+#### P2. 位置定制(高优先级)
+目标:让 Profile 可以在不同地区/设备语境中稳定复用。
+
+本阶段做什么:
+- 浏览器启动参数支持 `--proxy-server`
+- CDP 注入 `Emulation.setGeolocationOverride`
+- CDP 注入 `Emulation.setTimezoneOverride`
+- CDP 注入 `Emulation.setUserAgentOverride`
+- 前端提供 Environment Preset 编辑页
+- Profile 与 Preset 解耦,可自由组合
+
+关键原则:
+- 位置定制必须是独立 Preset,不能直接塞进 Profile
+- 否则同一个登录资料无法复用到多个国家/城市场景
+
+### 9.6 当前已落地的基础层(截至 2026-03-15)
+
+#### 已完成
+- `P1 Browser Profile` 已完成第一版资产化:
+ - 已有 `browser_profiles` 表、DAO、Service、Tauri 命令、前端资料管理 UI
+ - 运行时会话仍以 `profile_key` 驱动,但新需求已经收口到 `Browser Profile` 实体
+- `P2 Browser Environment Preset` 已完成第一版基础落地:
+ - 已有 `browser_environment_presets` 表、DAO、Service、Tauri 命令、前端预设管理 UI
+ - 浏览器工作台支持“资料 + 环境预设”组合启动
+ - 启动链已支持:
+ - Chrome 启动参数 `--proxy-server`
+ - CDP 注入 `Emulation.setGeolocationOverride`
+ - CDP 注入 `Emulation.setTimezoneOverride`
+ - CDP 注入 `Emulation.setUserAgentOverride`
+ - CDP 注入 `Emulation.setLocaleOverride`
+ - CDP 注入 `Emulation.setDeviceMetricsOverride`
+ - 运行时 `session` 已增加 `environment_preset_id / environment_preset_name` 关联位
+- 浏览器运行时统一审计已接入基础层:
+ - 启动链与动作链统一写入同一浏览器运行时审计缓冲区
+ - `launch` 审计已覆盖 `profile/profile_id`、环境预设、`session_id/target_id`、URL、复用状态、窗口打开方式、流模式、浏览器来源、CDP 端口
+ - 调试面板高级区可以直接查看最近启动与动作审计
+- 浏览器启动请求已完成第一轮收口:
+ - 新增统一 `LaunchBrowserSessionRequest`
+ - `profile_id` 与 `profile_key` 启动都收口到同一 session 启动边界
+ - `BrowserProfileManager`、浏览器工作台恢复链、Chrome Relay、Agent Chat 浏览器协助都已切到统一启动请求
+
+#### 当前限制
+- 代理属于浏览器启动参数;若资料对应的 Chrome 进程已在运行,切换代理前必须先关闭该资料会话
+- Locale override 依赖目标 Chrome 版本;若方法不存在,当前实现按 best-effort 处理并保留日志告警
+- 当前 Environment Preset 只覆盖运行时真正可落地的字段:
+ - `proxy_server`
+ - `timezone_id`
+ - `locale`
+ - `accept_language`
+ - `geolocation_*`
+ - `user_agent`
+ - `platform`
+ - `viewport_*`
+ - `device_scale_factor`
+- 尚未实现:
+ - 地区标签字段的产品化筛选与统计
+ - 证书资产
+ - CAPTCHA solver
+ - 任务模板与 connector 组合编排
+
+#### 当前事实源分类
+- `current`
+ - `browser_profiles`
+ - `browser_environment_presets`
+ - `launch_browser_session + LaunchBrowserSessionRequest`
+ - `automation_job.payload.browser_session + Automation executor`
+ - `browser_profile_cmd`
+ - `browser_environment_cmd`
+ - `BrowserRuntimeAuditRecord` 统一浏览器运行时审计模型
+ - `BrowserProfileManager`
+ - `BrowserEnvironmentPresetManager`
+ - `BrowserRuntimeDebugPanel` 中的最近启动/动作审计面板
+- `compat`
+ - 旧的裸 `profile_key` / Chrome 目录启动链仍保留,但只允许委托到新控制面,不再承载新功能
+ - `launch_browser_runtime_assist`
+ - `launch_browser_profile_runtime_assist_cmd`
+ - `get_browser_action_audit_logs` 命名暂保留,但返回值已升级为统一运行时审计记录
+
+#### P3. 浏览器计划任务(中高优先级)
+目标:复用现有 scheduler/heartbeat 底座,做真正的浏览器自动化任务。
+
+当前进展(第一刀已落地):
+- 不新增平行调度系统,先把浏览器任务收口为 `automation_jobs.payload.browser_session`
+- 调度执行时直接复用 `launch_browser_session`
+- profile / environment preset 在保存任务时就做存在性校验
+- 执行历史继续写现有 `ExecutionTracker`
+- 自动化详情页已直接嵌入现有 `BrowserRuntimeDebugPanel`,复用 `waiting_for_human / human_controlling / live` 状态机处理人工接管
+- 浏览器任务不再在启动成功后立即记为 `success`;现在会保持 `agent_runs=running`,并通过 `session_id -> automation_jobs / agent_runs` 回写 `waiting_for_human / human_controlling / agent_resuming`
+- 人工点击“恢复给 Agent”后,会在原链路内把自动化任务收口为成功并恢复下一次调度,不新增 `browser_task_runs` 一类旁路表
+- 自动化详情页、运行历史和风险任务面板开始直接消费 `agent_runs.metadata.human_reason`,等待人工/人工接管/恢复中的原因不再只藏在实时面板里
+- 自动化主列表开始直显 `当前阻塞 / 最近异常` 摘要,值守时无需进入详情页也能判断浏览器任务卡在什么环节
+- `delivery_json` 已扩成最小输出投递配置,支持 `output_format=text|json`
+- `delivery_json` 已继续扩展为最小输出契约,新增 `output_schema`
+- 当前 `output_schema` 第一版支持:
+ - `text`
+ - `json`
+ - `table`
+ - `csv`
+ - `links`
+- 第一批输出目标先落 `webhook / local_file`;`webhook` 会携带结构化 `output_data`,`local_file` 用于最小闭环落盘,`telegram` 继续只作为兼容通知通道
+- `telegram` 现在明确固定为文本提醒,不承诺结构化 output schema;结构化下游集成只允许继续收敛到 `webhook / local_file`
+- `automation_jobs` 已补最小 `last_delivery_json`,最近一次投递结果继续收敛在任务主记录里,不新增投递历史旁路表
+- 自动化详情页开始直接展示:
+ - 输出契约
+ - 最近一次投递结果
+- `best_effort=false` 的语义已收口为真实失败:
+ - 输出投递失败会把本次 job 最终状态记为 `error`
+ - 最近一次运行 metadata 会携带 `delivery` 摘要,运行历史与详情页不再各写一套投递状态
+
+本阶段做什么:
+- 第一阶段:继续基于 `automation_jobs` 承载浏览器任务模板
+- 调度执行时自动装配:`automation job -> profile -> environment preset -> browser session`
+- 支持一次性、周期性、cron
+- 支持“需要人工介入”的挂起态,与当前 `waiting_for_human / human_controlling` 状态机打通
+- 执行历史统一写入现有执行追踪体系
+
+原因:
+- 没有 P1/P2,任务就不可复现
+- 定时任务是对稳定会话装配能力的消费方,不应先于底座实现
+
+#### P4. 输入和输出 + 连接器(中优先级)
+目标:让浏览器任务结果可被下游系统稳定消费。
+
+本阶段做什么:
+- 定义 `output_schema`
+- 支持输出类型:`text / json / table / csv / links`
+- 支持输出目标:`download / local_file / webhook / connector`
+- 引入 Browser Connector 抽象
+- 第一批只做 `webhook` 和 `google_sheets`
+
+建议顺序:
+1. 先做结构化输出 schema
+2. 再做 connector 适配器
+
+当前进展(第三刀已落地):
+- `delivery_json` 已同时承载:
+ - `output_schema`
+ - `output_format`
+- `output_schema` 负责表达语义契约,`output_format` 只负责投递编码
+- `webhook` 当前会稳定输出:
+ - `output_schema`
+ - `output_format`
+ - `output_data`
+- `local_file` 当前支持:
+ - text 模式按 schema 渲染
+ - json 模式落结构化 payload
+- `automation_jobs.last_delivery_json` 已承载最近一次投递结果,历史开关关闭时仍可直接在任务详情中观察
+- `agent_runs.metadata.delivery` 已补投递摘要,运行历史和详情页共用同一份运行态事实
+
+当前进展(第四刀已落地):
+- 不新增 `browser_connectors` 表,也不引入独立 connector runtime
+- 第一个真正 connector 已继续收敛到现有 `delivery` 边界:
+ - `channel=google_sheets`
+ - 继续使用 `automation_jobs.delivery_json`
+ - 继续把最近一次投递结果写回 `automation_jobs.last_delivery_json`
+- `google_sheets` 当前采用最小 service account 直连模式:
+ - 目标串使用 `spreadsheet_id=...;sheet=...;credentials_file=...`
+ - 可选 `include_header=true`
+ - 可选 `value_input_option=RAW|USER_ENTERED`
+- 输出语义继续复用现有 `output_schema`:
+ - `table/csv` 直接按行追加
+ - `links` 追加为链接记录
+ - `text/json` 追加为单行摘要/JSON 记录
+- `telegram` 仍维持 `compat` 文本通知;结构化下游集成只允许继续收敛到 `webhook / local_file / google_sheets`
+
+当前进展(第五刀已落地):
+- delivery 幂等与重试语义继续收敛在同一条事实源:
+ - `automation_service::delivery`
+ - `automation_jobs.last_delivery_json`
+ - `agent_runs.metadata.delivery`
+- 新增稳定 `delivery_attempt_id`:
+ - 有 `run_id` 时直接复用 `dlv-{run_id}`
+ - 无 history/run_id 时按 `job_id + started_at + execution_retry_count` 生成稳定哈希键
+- `webhook` 当前会输出并透传:
+ - payload 字段 `delivery_attempt_id`
+ - 请求头 `Idempotency-Key`
+ - 请求头 `X-Proxycast-Delivery-Attempt-Id`
+- `google_sheets` 当前会在每一行前置:
+ - `delivery_attempt_id`
+ - `run_id`
+ - `job_id`
+ - `execution_retry_count`
+- 网络型输出目标当前采用最小内建重试:
+ - `webhook`
+ - `google_sheets`
+ - 默认最多 3 次,保留同一个 `delivery_attempt_id`
+- `last_delivery_json` 与运行历史 metadata 当前会继续记录:
+ - `delivery_attempt_id`
+ - `run_id`
+ - `execution_retry_count`
+ - `delivery_attempts`
+
+下一刀不应继续堆通知通道,应该优先补:
+- 输出目标的能力边界说明
+- 连接器失败重试与幂等策略
+
+原因:
+- 没有统一输出 schema,连接器会各自解析页面结果,后续无法维护
+
+#### P5. 证书(中低优先级)
+目标:支持企业站点、银行类或需要 mTLS 的场景。
+
+本阶段做什么:
+- 先只支持 `client_tls` 证书资产管理
+- 支持证书与 host pattern 绑定
+- 启动浏览器时注入证书选择策略或使用平台能力完成匹配
+
+为什么不是更早:
+- 这是企业纵深能力,不是大多数浏览器任务的基础阻塞项
+
+#### P6. 自动验证码求解器(低优先级)
+目标:减少人工介入,但不破坏当前可用的人机协同链路。
+
+本阶段做什么:
+- 先定义 `CaptchaSolver` 抽象
+- 再接第三方供应商
+- 最后支持策略:自动求解失败后回退人工接管
+
+为什么最后做:
+- 当前已有人工接管 + 实时画面,可满足可用性底线
+- CAPTCHA 成本高、供应商不稳定、风控强,不应先于 Profile/Preset/Task/I-O
+
+### 9.6 建议的数据库与模块落点
+
+建议新增表:
+- `browser_profiles`
+- `browser_environment_presets`
+- `browser_profile_bindings`
+- `browser_task_templates`
+- `browser_task_runs`
+- `browser_connectors`
+- `browser_certificate_assets`
+
+建议新增模块:
+- `src-tauri/src/browser_control/`
+ - `profile_service.rs`
+ - `environment_preset_service.rs`
+ - `task_template_service.rs`
+ - `connector_service.rs`
+ - `certificate_service.rs`
+
+建议保持不动的模块:
+- `src-tauri/crates/browser-runtime/`
+ - 继续只做运行时与 CDP 交互
+- `src-tauri/src/commands/webview_cmd.rs`
+ - 继续做命令入口,但逐步改为调用新 service
+- `src-tauri/src/app/scheduler_service.rs`
+ - 继续复用,不重新发明调度器
+
+### 9.7 结论
+
+从代码现状看,Proxycast 并不是“还没有浏览器底座”,而是已经跨过了最难的第一步:
+- 已有实时画面
+- 已有 CDP 会话
+- 已有人工接管
+- 已有独立 Chrome profile
+- 已有通用调度器
+
+真正缺的是中间那层“浏览器控制面产品模型”:
+- Profile 还是目录,不是资产
+- 调度器还是通用任务,不是浏览器任务
+- 输出还是原始事件,不是结构化结果
+- 连接还是终端连接,不是业务连接器
+
+所以后续路线必须是:
+1. 先收口控制面
+2. 再做个人资料
+3. 再做位置定制
+4. 再做浏览器定时任务
+5. 再做输入和输出与连接器
+6. 最后补证书与自动验证码
+
+这条路线最符合当前仓库状态,也最符合 KISS / YAGNI / DRY:先把已有底座变成稳定平台,再让上层功能自然长出来。
diff --git a/extensions/proxycast-chrome/README.md b/extensions/proxycast-chrome/README.md
index 85e521068..279671fd1 100644
--- a/extensions/proxycast-chrome/README.md
+++ b/extensions/proxycast-chrome/README.md
@@ -6,7 +6,7 @@
- Observer 通道自动连接:`/proxycast-chrome-observer/Proxycast_Key=...`
- 页面信息上报:标题、URL、Markdown
-- 远程指令执行:`open_url` / `click` / `type` / `scroll` / `switch_tab` / `go_back` 等
+- 远程指令执行:`open_url` / `click` / `type` / `scroll` / `switch_tab` / `list_tabs` / `go_back` 等
- 弹窗配置:`serverUrl`、`bridgeKey`、`profileKey`、监控开关、手动抓取
## 安装
diff --git a/extensions/proxycast-chrome/background.js b/extensions/proxycast-chrome/background.js
index 12e37461f..cbf117cfb 100644
--- a/extensions/proxycast-chrome/background.js
+++ b/extensions/proxycast-chrome/background.js
@@ -235,6 +235,11 @@ async function executeRemoteCommand(commandData) {
return;
}
+ if (command === "list_tabs") {
+ await handleListTabs(commandData);
+ return;
+ }
+
const tabId = await resolveTargetTabId();
if (!tabId) {
sendCommandResult({
@@ -389,6 +394,41 @@ async function handleSwitchTab(commandData, waitForPageInfo) {
}
}
+async function handleListTabs(commandData) {
+ const requestId = commandData.requestId;
+ const sourceClientId = commandData.sourceClientId;
+
+ try {
+ const tabs = await chrome.tabs.query({ currentWindow: true });
+ const normalizedTabs = tabs
+ .filter((tab) => Number.isInteger(tab.id) && Number.isInteger(tab.index))
+ .map((tab) => ({
+ id: tab.id,
+ index: tab.index,
+ active: tab.active === true,
+ title: tab.title || "",
+ url: tab.url || "",
+ }));
+
+ sendCommandResult({
+ requestId,
+ sourceClientId,
+ status: "success",
+ message: `已读取 ${normalizedTabs.length} 个标签页`,
+ data: {
+ tabs: normalizedTabs,
+ },
+ });
+ } catch (error) {
+ sendCommandResult({
+ requestId,
+ sourceClientId,
+ status: "error",
+ error: error?.message || String(error),
+ });
+ }
+}
+
function sendCommandResult(data) {
sendObserverMessage({
type: "command_result",
diff --git a/package.json b/package.json
index 064ce98fa..12b0b469b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "proxycast",
"private": true,
- "version": "0.87.0",
+ "version": "0.88.0",
"type": "module",
"engines": {
"node": ">=22.0.0"
diff --git a/scripts/report-legacy-surfaces.mjs b/scripts/report-legacy-surfaces.mjs
index 26448cd71..e70a7a909 100644
--- a/scripts/report-legacy-surfaces.mjs
+++ b/scripts/report-legacy-surfaces.mjs
@@ -70,6 +70,27 @@ const importSurfaceMonitors = [
targets: ["src/lib/api/agentCompat.ts"],
allowedPaths: [],
},
+ {
+ id: "heartbeat-api-gateway",
+ classification: "deprecated",
+ description: "旧 heartbeat 前端 API 入口",
+ targets: ["src/lib/api/heartbeat.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "heartbeat-settings-page-entry",
+ classification: "deprecated",
+ description: "旧 heartbeat 设置页入口",
+ targets: ["src/components/settings-v2/system/heartbeat/index.tsx"],
+ allowedPaths: [],
+ },
+ {
+ id: "assistant-settings-page-entry",
+ classification: "deprecated",
+ description: "旧助理服务设置页入口",
+ targets: ["src/components/settings-v2/agent/assistant/index.tsx"],
+ allowedPaths: [],
+ },
];
const commandSurfaceMonitors = [
@@ -117,6 +138,50 @@ const commandSurfaceMonitors = [
],
allowedPaths: [],
},
+ {
+ id: "heartbeat-legacy-commands",
+ classification: "deprecated",
+ description: "旧 heartbeat 命令前端边界",
+ commands: [
+ "get_heartbeat_config",
+ "update_heartbeat_config",
+ "get_heartbeat_status",
+ "get_heartbeat_tasks",
+ "add_heartbeat_task",
+ "delete_heartbeat_task",
+ "update_heartbeat_task",
+ "get_heartbeat_history",
+ "get_heartbeat_execution_detail",
+ "get_heartbeat_task_health",
+ "deliver_heartbeat_task_health_alerts",
+ "trigger_heartbeat_now",
+ "get_task_templates",
+ "apply_task_template",
+ "generate_content_creator_tasks",
+ "preview_heartbeat_schedule",
+ "validate_heartbeat_schedule",
+ ],
+ allowedPaths: [],
+ },
+];
+
+const frontendTextSurfaceMonitors = [
+ {
+ id: "frontend-assistant-settings-surfaces",
+ classification: "deprecated",
+ description: "前端助理服务设置页与配置面回流",
+ patterns: [
+ "SettingsTabs.Assistant",
+ "settings.tab.assistant",
+ "AssistantSettings",
+ "AssistantConfig",
+ "default_assistant_id",
+ "custom_assistants",
+ "show_suggestions",
+ "auto_select",
+ ],
+ allowedPaths: [],
+ },
];
const rustTextSurfaceMonitors = [
@@ -237,6 +302,38 @@ const rustTextSurfaceMonitors = [
],
allowedPaths: [],
},
+ {
+ id: "rust-heartbeat-business-surfaces",
+ classification: "deprecated",
+ description: "Rust 业务层 heartbeat 旧实现回流",
+ patterns: [
+ "crate::services::heartbeat_service::",
+ "services::heartbeat_service::",
+ "HeartbeatServiceState",
+ "heartbeat_service_adapter",
+ "proxycast_core::database::dao::heartbeat",
+ "heartbeat_tool",
+ "RunSource::Heartbeat",
+ "source = 'heartbeat'",
+ "source: \"heartbeat\".to_string()",
+ ],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-assistant-config-surfaces",
+ classification: "deprecated",
+ description: "Rust 助理服务配置面回流",
+ patterns: [
+ "AssistantConfig",
+ "AssistantProfile",
+ "default_assistant_id",
+ "custom_assistants",
+ "show_suggestions",
+ "auto_select",
+ ],
+ includePathPrefixes: ["src-tauri/crates/core/src/config", "src-tauri/src/config"],
+ allowedPaths: [],
+ },
{
id: "rust-migration-setting-key-leak",
classification: "deprecated",
@@ -935,6 +1032,8 @@ function printTextCountReport(result) {
}
const { runtimeSources, testSources } = collectSources();
+const { runtimeSources: frontendRuntimeTextSources, testSources: frontendTestTextSources } =
+ collectTextSources(sourceRoots, sourceExtensions);
const { runtimeSources: rustRuntimeSources, testSources: rustTestSources } =
collectTextSources(rustSourceRoots, rustSourceExtensions);
const importResults = importSurfaceMonitors.map((monitor) =>
@@ -943,6 +1042,9 @@ const importResults = importSurfaceMonitors.map((monitor) =>
const commandResults = commandSurfaceMonitors.map((monitor) =>
evaluateCommandMonitor(monitor, runtimeSources, testSources),
);
+const frontendTextResults = frontendTextSurfaceMonitors.map((monitor) =>
+ evaluateTextMonitor(monitor, frontendRuntimeTextSources, frontendTestTextSources),
+);
const rustTextResults = rustTextSurfaceMonitors.map((monitor) =>
evaluateTextMonitor(monitor, rustRuntimeSources, rustTestSources),
);
@@ -963,6 +1065,9 @@ const violations = [
...commandResults.flatMap((result) =>
result.violations.map((item) => `${result.id} -> ${item}`),
),
+ ...frontendTextResults.flatMap((result) =>
+ result.violations.map((item) => `${result.id} -> ${item}`),
+ ),
...rustTextResults.flatMap((result) =>
result.violations.map((item) => `${result.id} -> ${item}`),
),
@@ -984,6 +1089,12 @@ for (const result of commandResults) {
printCommandReport(result);
}
+console.log("");
+console.log("## 前端护栏");
+for (const result of frontendTextResults) {
+ printTextReport(result);
+}
+
console.log("");
console.log("## Rust 护栏");
for (const result of rustTextResults) {
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index fba0905cf..967c5a2d1 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -6982,7 +6982,7 @@ dependencies = [
[[package]]
name = "proxycast"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"anyhow",
"arboard",
@@ -7008,13 +7008,13 @@ dependencies = [
"hex",
"if-addrs",
"indexmap 2.13.0",
+ "jsonwebtoken",
"md5",
"mouse_position",
"notify 6.1.1",
"objc",
"once_cell",
"open",
- "openssl",
"parking_lot",
"portable-pty",
"proptest",
@@ -7085,7 +7085,7 @@ dependencies = [
[[package]]
name = "proxycast-agent"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"aster-core",
"async-trait",
@@ -7110,7 +7110,7 @@ dependencies = [
[[package]]
name = "proxycast-browser-runtime"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"chrono",
"futures",
@@ -7127,7 +7127,7 @@ dependencies = [
[[package]]
name = "proxycast-config"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"async-trait",
"parking_lot",
@@ -7143,7 +7143,7 @@ dependencies = [
[[package]]
name = "proxycast-core"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"aster-models",
"async-trait",
@@ -7183,7 +7183,7 @@ dependencies = [
[[package]]
name = "proxycast-credential"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"axum 0.7.9",
"base64 0.22.1",
@@ -7218,7 +7218,7 @@ dependencies = [
[[package]]
name = "proxycast-gateway"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"axum 0.7.9",
"chrono",
@@ -7239,7 +7239,7 @@ dependencies = [
[[package]]
name = "proxycast-infra"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"chrono",
"dashmap 5.5.3",
@@ -7259,7 +7259,7 @@ dependencies = [
[[package]]
name = "proxycast-mcp"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"async-trait",
"dirs 5.0.1",
@@ -7291,7 +7291,7 @@ dependencies = [
[[package]]
name = "proxycast-processor"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"async-trait",
"parking_lot",
@@ -7310,7 +7310,7 @@ dependencies = [
[[package]]
name = "proxycast-providers"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"anyhow",
"async-stream",
@@ -7364,7 +7364,7 @@ dependencies = [
[[package]]
name = "proxycast-server"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"aster-core",
"async-stream",
@@ -7409,7 +7409,7 @@ dependencies = [
[[package]]
name = "proxycast-server-utils"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"axum 0.7.9",
"futures",
@@ -7424,7 +7424,7 @@ dependencies = [
[[package]]
name = "proxycast-services"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"anyhow",
"aster-core",
@@ -7466,7 +7466,7 @@ dependencies = [
[[package]]
name = "proxycast-skills"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"async-trait",
"dirs 5.0.1",
@@ -7484,7 +7484,7 @@ dependencies = [
[[package]]
name = "proxycast-terminal"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"async-trait",
"base64 0.22.1",
@@ -7511,7 +7511,7 @@ dependencies = [
[[package]]
name = "proxycast-websocket"
-version = "0.87.0"
+version = "0.88.0"
dependencies = [
"axum 0.7.9",
"chrono",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 8f22e6c33..c91cdbd3f 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"
[workspace.package]
-version = "0.87.0"
+version = "0.88.0"
edition = "2021"
authors = ["coso"]
repository = "https://github.com/aiclientproxy/proxycast"
@@ -78,6 +78,7 @@ cron = "0.15"
dirs = "5"
regex = "1"
md5 = "0.7"
+jsonwebtoken = "9.3.1"
urlencoding = "2"
subtle = "2.5"
flate2 = "1"
@@ -113,8 +114,7 @@ rustls-pemfile = "2"
portable-pty = "0.8"
# SSH
-ssh2 = "0.9"
-openssl = { version = "0.10", features = ["vendored"] }
+ssh2 = { version = "0.9", features = ["vendored-openssl"] }
# 系统交互
mouse_position = "0.1.4"
@@ -191,7 +191,7 @@ version = "2.4"
[package]
name = "proxycast"
-version = "0.87.0"
+version = "0.88.0"
description = "AI API Proxy Desktop App"
authors = ["you"]
edition = "2021"
@@ -283,6 +283,7 @@ cron.workspace = true
dirs.workspace = true
regex.workspace = true
md5.workspace = true
+jsonwebtoken.workspace = true
urlencoding.workspace = true
subtle.workspace = true
flate2.workspace = true
@@ -314,7 +315,6 @@ portable-pty.workspace = true
# SSH
ssh2.workspace = true
-openssl.workspace = true
# 系统交互
mouse_position.workspace = true
diff --git a/src-tauri/crates/agent/src/tools/heartbeat_tool.rs b/src-tauri/crates/agent/src/tools/heartbeat_tool.rs
deleted file mode 100644
index a97f84649..000000000
--- a/src-tauri/crates/agent/src/tools/heartbeat_tool.rs
+++ /dev/null
@@ -1,763 +0,0 @@
-//! Heartbeat Tool
-//!
-//! 为 Aster Agent 提供心跳任务管理能力,允许 AI 通过工具调用管理心跳系统。
-
-use aster::tools::{Tool, ToolContext, ToolError, ToolResult};
-use async_trait::async_trait;
-use serde::{Deserialize, Serialize};
-use serde_json::{json, Value};
-use std::path::PathBuf;
-use std::sync::Arc;
-use thiserror::Error;
-
-/// Heartbeat 工具错误类型
-#[derive(Debug, Error)]
-pub enum HeartbeatToolError {
- #[error("服务未初始化")]
- ServiceNotInitialized,
-
- #[error("参数错误: {0}")]
- InvalidParams(String),
-
- #[error("执行失败: {0}")]
- ExecutionFailed(String),
-
- #[error("IO 错误: {0}")]
- IoError(String),
-}
-
-/// 心跳任务预览
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct HeartbeatTaskPreview {
- pub description: String,
- pub priority: Option,
- pub timeout_secs: Option,
- pub once: bool,
- pub model: Option,
-}
-
-/// 心跳执行记录
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct HeartbeatExecutionRecord {
- pub id: i64,
- pub task_description: String,
- pub status: String,
- pub started_at: String,
- pub completed_at: Option,
- pub duration_ms: Option,
- pub output: Option,
- pub retry_count: u32,
-}
-
-/// 心跳状态
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct HeartbeatStatus {
- pub running: bool,
- pub last_run: Option,
- pub next_run: Option,
- pub last_task_count: usize,
- pub total_executions: u64,
- pub schedule_description: Option,
-}
-
-/// 心跳周期结果
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct HeartbeatCycleResult {
- pub task_count: usize,
- pub success_count: usize,
- pub failed_count: usize,
- pub timeout_count: usize,
-}
-
-/// Heartbeat 服务抽象 trait
-///
-/// 这样可以在测试时 mock,也可以避免直接依赖 Tauri 类型
-#[async_trait]
-pub trait HeartbeatService: Send + Sync {
- /// 获取心跳状态
- fn get_status(&self) -> Result;
-
- /// 获取应用数据目录
- fn get_app_data_dir(&self) -> Result;
-
- /// 预览任务列表
- fn preview_tasks(&self) -> Result, HeartbeatToolError>;
-
- /// 添加任务
- fn add_task(
- &self,
- description: String,
- priority: Option,
- timeout_secs: Option,
- once: Option,
- model: Option,
- ) -> Result<(), HeartbeatToolError>;
-
- /// 删除任务
- fn delete_task(&self, index: usize) -> Result<(), HeartbeatToolError>;
-
- /// 更新任务
- fn update_task(
- &self,
- index: usize,
- description: String,
- priority: Option,
- timeout_secs: Option,
- once: Option,
- model: Option,
- ) -> Result<(), HeartbeatToolError>;
-
- /// 获取执行历史
- fn get_history(
- &self,
- limit: usize,
- ) -> Result, HeartbeatToolError>;
-
- /// 获取执行详情
- fn get_execution_detail(
- &self,
- id: i64,
- ) -> Result