Skip to content

模块 86: Web Cowork 日常任务协作系统 (web-cowork)

版本: v5.0.3.0 状态: 🔄 实施中 日期: 2026-04-13

一、背景与目标

1.1 问题陈述

普通用户在日常工作和生活中频繁遇到以下类型的问题:

场景类别典型问题当前解决方式痛点
文档处理Word 转 PDF、合并文档、格式修复手动操作 Office、找在线工具散乱、隐私风险
音视频处理视频压缩、提取音频、剪辑片段、格式转换下载各种工具、学 ffmpeg 命令门槛高、耗时
数据分析Excel 统计、CSV 趋势图、数据清洗手写公式、学 Python非技术用户无法完成
信息检索多源调研、竞品分析、技术选型手动搜索+整理耗时、遗漏
图片处理批量压缩、加水印、格式转换、OCR 文字提取Photoshop/在线工具批量操作繁琐
代码辅助生成脚本、调试报错、自动化任务复制粘贴到 ChatGPT无法执行、无上下文
系统运维磁盘清理、进程管理、日志分析手动命令行危险操作多、记不住命令
文件管理批量重命名、整理归档、查找重复资源管理器一个个改效率极低
网络工具API 调试、网页抓取、下载管理Postman/curl/浏览器工具分散
学习辅助文档翻译、知识总结、论文分析复制到翻译器上下文断裂

核心洞察: 这些问题的共同特征是 —— 用户知道要做什么,但不知道怎么做或嫌麻烦。而一个有工具访问权限的 AI Agent 恰好能补上这个缺口:用户用自然语言描述需求,Agent 实时生成代码并执行完成任务。

1.2 设计目标

  1. 一个 Web 入口覆盖日常 80% 问题 — 用户打开浏览器即可使用,无需安装额外软件
  2. 自然语言驱动 — 用户不需要知道 ffmpeg、pandoc、Python,只需描述需求
  3. 实时数据 + 大模型 — Agent 能抓取网页、调用 API 获取实时信息,结合 LLM 分析后给出方案
  4. Code Agent 实时生成代码执行 — 不是预置脚本,而是 Agent 根据具体需求动态生成 Python/Node/Shell 脚本并执行
  5. 流水线式多步协作 — 复杂任务自动分解为多步,每步独立 Agent 执行,步间传递结构化结果
  6. 安全可控 — 所有操作在本机执行,敏感操作需确认,文件不上传第三方

1.3 与现有系统的关系

现有系统                           新增系统
┌─────────────┐                  ┌──────────────────────┐
│ /chat 页面   │                  │ /cowork 页面          │
│ 通用 AI 对话  │                  │ 任务模板 + 对话 + 执行  │
│ 单轮问答为主  │                  │ 多步流水线为主         │
└──────┬──────┘                  └──────────┬───────────┘
       │                                    │
       └──────────┬─────────────────────────┘

        ┌──────────────────┐
        │ WebSocket Server  │  ← 共用,新增 cowork-task 消息类型
        │ (ws-server.js)    │
        └────────┬─────────┘

        ┌──────────────────┐
        │ Agent Core       │  ← 零改动复用
        │ (agent-core.js)  │
        │ 13 工具 + 138 技能 │
        └──────────────────┘

二、用户场景全覆盖清单

2.1 十大场景分类与 Agent 执行路径

场景 1: 文档处理

用户输入: "把 report.docx 转成 PDF"
         "合并 chapter1.md 和 chapter2.md 为一个文档"
         "把这个 Excel 导出为带图表的 PDF 报告"

Agent 执行路径 (开源工具优先):

  路径 A — cli-anything 已注册 (最优):
  ① list_skills → 发现 cli-anything-pandoc 已注册
  ② run_skill cli-anything-pandoc "convert report.docx to PDF"
     → cli-anything 自动翻译为: pandoc report.docx -o report.pdf --pdf-engine=xelatex
  ③ verify → run_shell: ls -la report.pdf

  路径 B — cli-anything 未注册,工具已安装:
  ① run_shell: pandoc --version → OK
  ② run_shell: pandoc report.docx -o report.pdf
  ③ 尝试注册: run_shell: chainlesschain cli-anything register pandoc --force
  ④ verify → 确认文件存在

  路径 C — 工具未安装 (自动安装):
  ① run_shell: pandoc --version → 失败
  ② run_shell: winget install JohnMacFarlane.Pandoc --accept-package-agreements --accept-source-agreements
  ③ run_shell: pandoc --version → OK
  ④ run_shell: pandoc report.docx -o report.pdf
  ⑤ 后台注册: chainlesschain cli-anything register pandoc

  路径 D — winget 也没有 (Python 降级):
  ① run_code(python): pip install python-docx pdfkit → 用 Python 库实现

开源工具: pandoc, LibreOffice (soffice), Ghostscript (gs), wkhtmltopdf
Python 降级: python-docx, pdfkit, fpdf2, openpyxl

场景 2: 音视频处理

用户输入: "把 meeting.mp4 提取音频"
         "压缩这个视频到 50MB 以内"
         "把 podcast.mp3 从 10:30 到 25:00 剪一段"
         "合并 intro.mp4 和 main.mp4"

Agent 执行路径 (开源工具优先):

  路径 A — cli-anything 已注册 (最优):
  ① list_skills → 发现 cli-anything-ffmpeg 已注册
  ② run_skill cli-anything-ffmpeg "extract audio from meeting.mp4 as mp3 192kbps"
     → cli-anything 自动翻译为正确的 ffmpeg 命令
     → 用户不需要知道 -vn -acodec libmp3lame -ab 192k 这些参数
  ③ verify → run_shell: ffprobe output.mp3

  路径 B — 直接调用 ffmpeg:
  ① run_shell: ffprobe -v quiet -print_format json -show_format input.mp4
     (先分析源文件)
  ② run_shell: ffmpeg -i meeting.mp4 -vn -acodec libmp3lame audio.mp3
     (Agent 根据分析结果构造命令)
  ③ verify → ffprobe output.mp3

  路径 C — ffmpeg 未安装 (自动安装):
  ① run_shell: winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements
  ② 验证 → ffmpeg -version → OK
  ③ 执行转换 → 同路径 B

  路径 D — Python 降级:
  ① run_code(python): pip install moviepy pydub → 用 Python 库实现

开源工具: FFmpeg, SoX, yt-dlp
Python 降级: moviepy, pydub, ffmpeg-python

场景 3: 数据分析

用户输入: "分析 sales.csv 的月度趋势,生成图表"
         "清洗这个 Excel,去重并修复格式"
         "比较这两个 CSV 文件的差异"

Agent 执行路径:
  ① read-sample → read_file: sales.csv (前 20 行,理解数据结构)
  ② analyze     → run_code(python): 动态生成 pandas 脚本
     ```python
     import pandas as pd
     import matplotlib.pyplot as plt
     df = pd.read_csv('sales.csv')
     df['month'] = pd.to_datetime(df['date']).dt.to_period('M')
     monthly = df.groupby('month')['amount'].sum()
     monthly.plot(kind='bar', figsize=(12, 6))
     plt.savefig('trend.png', dpi=150, bbox_inches='tight')
     print(monthly.to_string())
     ```
  ③ report      → write_file: 生成分析报告 markdown

依赖工具: Python + pandas + matplotlib
Agent 工具: run_code, read_file, write_file
关键能力: Agent 先看数据再写代码,不是套模板

场景 4: 信息检索与实时数据

用户输入: "帮我调研 2024 年主流 AI Agent 框架的对比"
         "查一下今天的汇率,人民币兑美元"
         "搜索这个 npm 包的最新版本和 changelog"

Agent 执行路径:
  ① fetch       → run_skill(browser-automation): fetchPage(url) 抓取网页
                   或 run_code(node): fetch('https://api.exchangerate-api.com/...')
  ② parse       → run_code(python/node): 解析 HTML/JSON,提取关键数据
  ③ analyze     → LLM 对抓取到的原始数据进行分析、对比、总结
  ④ report      → write_file: 生成结构化调研报告

Agent 工具: run_skill(browser-automation), run_code, write_file
关键能力: 实时数据 + LLM 分析 = 有时效性的智能报告

场景 5: 图片处理

用户输入: "把 photos/ 下所有图片压缩到 500KB 以内"
         "给这些图片加公司 logo 水印"
         "识别这张图上的文字 (OCR)"

Agent 执行路径 (开源工具优先):

  路径 A — cli-anything 已注册:
  ① list_skills → 发现 cli-anything-magick
  ② run_skill cli-anything-magick "batch compress all png in photos/ to under 500KB"
     → cli-anything 翻译为: magick mogrify -resize '500000@>' -quality 85 photos/*.png
  ③ OCR 场景:
     run_skill cli-anything-tesseract "recognize text in screenshot.png output as txt"
     → 翻译为: tesseract screenshot.png output -l chi_sim+eng

  路径 B — 直接调用工具:
  ① run_shell: magick --version / tesseract --version
  ② 批量压缩: run_shell: magick mogrify -quality 85 -resize 800x photos/*.png
  ③ OCR: run_shell: tesseract image.png output -l chi_sim

  路径 C — Python 降级:
  ① run_code(python): 用 Pillow 批量处理
     from PIL import Image
     for f in glob.glob('photos/*.png'):
         img = Image.open(f)
         img.save(f'compressed/{os.path.basename(f)}', optimize=True, quality=85)
  ② OCR: run_code(python): pip install pytesseract → pytesseract.image_to_string(img)

开源工具: ImageMagick, Tesseract OCR, OptiPNG, ExifTool
Python 降级: Pillow, pytesseract, img2pdf

场景 6: 代码辅助

用户输入: "写一个 Python 脚本批量重命名文件"
         "这段代码报错了帮我看看" + 粘贴代码
         "生成一个 Express REST API 的脚手架"

Agent 执行路径:
  ① understand  → LLM 理解需求 / read_file 读取报错代码
  ② generate    → LLM 生成代码方案
  ③ execute     → run_code: 实际运行验证(可选)
  ④ iterate     → 如果报错,Agent 自动读错误信息、修复、重试

Agent 工具: run_code, write_file, edit_file, run_shell
关键能力: 不只是生成代码,还能执行并自动调试

场景 7: 系统运维

用户输入: "查看磁盘使用情况,找出最大的 10 个文件"
         "分析最近的系统日志,有没有异常"
         "帮我清理 node_modules 和临时文件"

Agent 执行路径:
  ① gather      → run_shell: du -sh / df -h / wmic diskdrive get size
  ② analyze     → run_code(python): 解析输出,排序,生成报告
  ③ suggest     → LLM 给出清理建议(不直接执行危险操作)
  ④ execute     → 用户确认后 run_shell 执行清理(需 approval)

Agent 工具: run_shell, run_code
安全: 删除/清理操作走 approval flow,Agent 不自行删文件

场景 8: 文件管理

用户输入: "把 downloads/ 按文件类型分类整理"
         "批量把文件名中的空格替换成下划线"
         "找出这个文件夹里的重复文件"

Agent 执行路径:
  ① scan        → list_dir + search_files: 扫描目标目录
  ② plan        → LLM 生成整理/重命名方案并展示给用户
  ③ execute     → run_code(python): 执行文件操作
     ```python
     import os, shutil
     for f in os.listdir('downloads'):
         ext = os.path.splitext(f)[1].lower()
         category = {'images': ['.jpg','.png'], 'docs': ['.pdf','.docx'], ...}
         dest = next((k for k,v in category.items() if ext in v), 'other')
         os.makedirs(f'downloads/{dest}', exist_ok=True)
         shutil.move(f'downloads/{f}', f'downloads/{dest}/{f}')
     ```
  ④ report      → 返回操作统计

Agent 工具: run_code, list_dir, search_files

场景 9: 网络工具

用户输入: "帮我测一下这个 API 接口能不能通"
         "抓取这个网页的所有图片链接"
         "下载这个 URL 的内容并保存"

Agent 执行路径:
  ① fetch       → run_code(node):
     ```javascript
     const res = await fetch('https://api.example.com/health');
     console.log({ status: res.status, headers: Object.fromEntries(res.headers) });
     console.log(await res.json());
     ```
  ② analyze     → LLM 解读 API 响应,给出诊断
  ③ save        → write_file: 保存结果到文件

Agent 工具: run_code, run_skill(browser-automation), write_file

场景 10: 学习辅助

用户输入: "翻译这篇英文 PDF 的摘要"
         "帮我总结这个长文档的要点"
         "解释这段代码的工作原理"

Agent 执行路径:
  ① read        → read_file: 读取文档内容
                   或 run_code(python): 解析 PDF
     ```python
     import PyPDF2
     reader = PyPDF2.PdfReader('paper.pdf')
     text = '\n'.join(page.extract_text() for page in reader.pages[:5])
     print(text)
     ```
  ② process     → LLM 翻译/总结/解释
  ③ output      → write_file: 保存翻译/总结结果

Agent 工具: run_code, read_file, write_file

2.2 实时数据获取能力矩阵

数据类型获取方式Agent 工具示例
网页内容browser-automation skillrun_skill新闻、文档、竞品页面
REST APINode.js fetch / Python requestsrun_code汇率、天气、股票行情
本地文件直接读取read_fileCSV、日志、配置文件
系统信息Shell 命令run_shell磁盘、进程、网络状态
Git 仓库git 命令git 工具commit 历史、diff、blame
npm/pip 包包管理器 CLIrun_shell版本、依赖、changelog
数据库sqlite3/psql CLIrun_shell查询、导出、统计

三、系统架构

3.1 整体架构

┌─────────────────── Web Browser ────────────────────────────┐
│                                                             │
│  /cowork 页面 (Cowork.vue)                                   │
│  ┌──────────────┬───────────────────────────────────────┐   │
│  │              │                                       │   │
│  │  任务模板面板  │         对话 + 实时执行面板             │   │
│  │              │                                       │   │
│  │ ┌──────────┐ │  ┌─────────────────────────────────┐  │   │
│  │ │ 文档处理  │ │  │  用户: "把 video.mp4 转成 mp3"  │  │   │
│  │ │ 音视频   │ │  │                                 │  │   │
│  │ │ 数据分析  │ │  │  ┌── Step 1: 环境检查 ────────┐ │  │   │
│  │ │ 信息检索  │ │  │  │ run_shell: ffmpeg -version │ │  │   │
│  │ │ 图片处理  │ │  │  │ ✅ ffmpeg 6.1 已安装       │ │  │   │
│  │ │ 代码辅助  │ │  │  └──────────────────────────┘ │  │   │
│  │ │ 系统运维  │ │  │                                 │  │   │
│  │ │ 文件管理  │ │  │  ┌── Step 2: 执行转换 ────────┐ │  │   │
│  │ │ 网络工具  │ │  │  │ run_shell: ffmpeg -i ...   │ │  │   │
│  │ │ 学习辅助  │ │  │  │ ✅ 输出: audio.mp3 (5.2MB) │ │  │   │
│  │ │ 自由提问  │ │  │  └──────────────────────────┘ │  │   │
│  │ └──────────┘ │  │                                 │  │   │
│  │              │  │  📁 结果: audio.mp3 [下载]       │  │   │
│  │  📂 文件拖拽区 │  └─────────────────────────────────┘  │   │
│  │              │                                       │   │
│  └──────────────┴───────────────────────────────────────┘   │
│                                                             │
└──────────────────────── WebSocket ──────────────────────────┘

                    ┌─────────┴─────────┐
                    ▼                   ▼
             cowork-task           session-message
             (模板模式)             (自由模式)
                    │                   │
                    ▼                   ▼
          ┌──────────────┐    ┌──────────────┐
          │ CoworkRunner  │    │ Agent Session │
          │ 流水线控制器    │    │ 单次长对话     │
          └──────┬───────┘    └──────────────┘

      ┌──────────┼──────────┐
      ▼          ▼          ▼
  SubAgent   SubAgent   SubAgent
  (Step 1)   (Step 2)   (Step 3)
      │          │          │
      ▼          ▼          ▼
  agentLoop  agentLoop  agentLoop
  (13 工具)   (13 工具)   (13 工具)

3.2 核心组件

新增文件:
packages/cli/src/lib/cowork-task-runner.js       # 流水线控制器 (~300行)
packages/cli/src/lib/cowork-task-templates.js     # 任务模板定义 (~400行)
packages/web-panel/src/views/Cowork.vue           # Web 主页面 (~400行)
packages/web-panel/src/stores/cowork.js           # 前端状态管理 (~200行)

修改文件:
packages/web-panel/src/router/index.js            # 新增 /cowork 路由
packages/web-panel/src/components/AppLayout.vue   # 侧边栏加入 Cowork 入口
packages/cli/src/gateways/ws/action-protocol.js   # 新增 cowork-task 消息处理

3.3 数据流

用户操作                    前端                    WebSocket                后端
  │                         │                         │                      │
  ├─ 选择模板 ──────────────→│                         │                      │
  ├─ 输入需求 ──────────────→│                         │                      │
  ├─ (可选)拖入文件 ────────→│                         │                      │
  │                         │                         │                      │
  │                         ├─ cowork-task ──────────→│                      │
  │                         │  {template, message,    │                      │
  │                         │   files, cwd}           │── CoworkRunner ─────→│
  │                         │                         │                      │
  │                         │←── step-started ────────│←── SubAgent(step1) ──│
  │ 看到 Step 1 开始       ←│                         │      agentLoop()     │
  │                         │←── tool-executing ──────│←── run_shell(...)  ──│
  │ 看到工具在执行         ←│                         │                      │
  │                         │←── tool-result ─────────│←── result ──────────│
  │ 看到工具结果           ←│                         │                      │
  │                         │←── step-completed ──────│←── summary ─────────│
  │ 看到 Step 1 完成       ←│                         │                      │
  │                         │                         │                      │
  │                         │←── step-started ────────│←── SubAgent(step2) ──│
  │ 看到 Step 2 开始       ←│                         │      agentLoop()     │
  │                         │  ... (重复)              │                      │
  │                         │                         │                      │
  │                         │←── pipeline-complete ───│                      │
  │ 看到最终结果+下载链接  ←│                         │                      │

四、核心实现

4.1 任务模板 (cowork-task-templates.js)

任务模板不是硬编码脚本,而是 给 Agent 的领域知识注入。Agent 仍然有完整的工具集和自主决策能力,模板只约束"该做什么"和"做完检查什么"。

javascript
/**
 * Cowork Task Templates
 *
 * 每个模板定义:
 * - id: 唯一标识
 * - name: 显示名称
 * - icon: Ant Design icon 名
 * - category: 分类
 * - description: 一句话描述
 * - examples: 示例输入列表 (帮用户理解能做什么)
 * - steps: 流水线步骤定义
 *   - step: 步骤标识
 *   - prompt(ctx): 生成 Agent prompt 的函数
 *   - validate(result): 从 Agent 返回中提取结构化数据
 *   - maxIterations: Agent 最大循环次数
 *   - tools: 工具白名单 (null = 全部)
 * - systemPromptExtension: 注入到 Agent system prompt 的领域知识
 * - acceptsFiles: 是否接受文件输入
 * - fileTypes: 接受的文件类型
 */

export const TASK_TEMPLATES = {
  "doc-convert": {
    id: "doc-convert",
    name: "文档格式转换",
    icon: "FileTextOutlined",
    category: "document",
    description: "Word、Markdown、HTML、PDF 之间的格式互转",
    examples: [
      "把 report.docx 转成 PDF",
      "把 README.md 转成带样式的 HTML",
      "合并 chapter1.md 和 chapter2.md 为一个 PDF",
    ],
    acceptsFiles: true,
    fileTypes: [".docx", ".md", ".html", ".txt", ".pdf", ".xlsx", ".pptx"],
    systemPromptExtension: `你是文档格式转换专家。
工具优先级: pandoc > soffice (LibreOffice) > wkhtmltopdf > Python。
转换前先检查工具可用性。如果工具未安装,自动安装:
- pandoc: winget install JohnMacFarlane.Pandoc --accept-package-agreements --accept-source-agreements
- LibreOffice: winget install TheDocumentFoundation.LibreOffice --accept-package-agreements --accept-source-agreements
- 安装后验证: pandoc --version / soffice --version
- 如果 winget 不可用,尝试 choco install pandoc -y
- 所有安装工具都不可用时,使用 Python 替代方案 (python-docx, pdfkit)
转换后确认文件存在且大小合理。
如果目标格式是 PDF 且源是 Markdown,用 pandoc 加 --pdf-engine=xelatex 以支持中文。
如果 pandoc 不可用,尝试 Markdown → HTML → soffice → PDF 的降级路径。`,
    steps: [
      {
        step: "check-env",
        maxIterations: 3,
        prompt: (ctx) => `检查以下工具的可用性: pandoc, soffice, wkhtmltopdf, python。
只返回 JSON 格式: {"pandoc":"版本号或false","soffice":"版本号或false","wkhtmltopdf":"版本号或false","python":"版本号或false"}`,
      },
      {
        step: "convert",
        maxIterations: 8,
        prompt: (ctx) => `用户需求: ${ctx.userMessage}
${ctx.files?.length ? `输入文件: ${ctx.files.join(", ")}` : ""}
可用工具: ${JSON.stringify(ctx.steps?.["check-env"] || {})}
请执行转换,完成后确认输出文件路径和大小。`,
      },
      {
        step: "verify",
        maxIterations: 3,
        prompt: (ctx) => `验证转换结果: ${ctx.steps?.convert?.outputFile || "上一步产出的文件"}
检查: 1. 文件存在 2. 大小合理(>0) 3. 可以正常打开
返回验证结论。`,
      },
    ],
  },

  "media-process": {
    id: "media-process",
    name: "音视频处理",
    icon: "PlayCircleOutlined",
    category: "media",
    description: "视频压缩、音频提取、格式转换、剪辑",
    examples: [
      "把 meeting.mp4 提取音频保存为 mp3",
      "压缩 video.mp4 到 50MB 以内",
      "剪辑 podcast.mp3 从 10:30 到 25:00",
      "把 video.avi 转成 mp4 (H.264)",
    ],
    acceptsFiles: true,
    fileTypes: [".mp4", ".avi", ".mkv", ".mov", ".mp3", ".wav", ".flac", ".aac", ".webm"],
    systemPromptExtension: `你是音视频处理专家,精通 ffmpeg/ffprobe。
如果 ffmpeg 未安装,自动安装:
- Windows: winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements
- 备选: choco install ffmpeg -y
- 安装后验证: ffmpeg -version
处理前先用 ffprobe 分析源文件(编码、分辨率、码率、时长)。
根据分析结果智能选择编码参数,而非使用固定参数。
压缩视频时优先用 -crf 控制质量,如果有目标大小限制则计算合适的码率。
剪辑使用 -ss 和 -to 参数,优先用 copy 编码避免重新编码。`,
    steps: [
      {
        step: "check-env",
        maxIterations: 3,
        prompt: (ctx) => `检查 ffmpeg 和 ffprobe 是否可用,返回版本号。
JSON 格式: {"ffmpeg":"版本或false","ffprobe":"版本或false"}`,
      },
      {
        step: "analyze",
        maxIterations: 5,
        prompt: (ctx) => `用 ffprobe 分析输入文件: ${ctx.files?.[0] || "用户指定的文件"}
输出关键信息: 格式、编码、分辨率、码率、时长、大小。`,
      },
      {
        step: "process",
        maxIterations: 10,
        prompt: (ctx) => `用户需求: ${ctx.userMessage}
文件分析: ${JSON.stringify(ctx.steps?.analyze || {})}
执行处理,完成后确认输出文件路径和大小。
如果处理失败,分析错误原因并尝试替代方案。`,
      },
    ],
  },

  "data-analysis": {
    id: "data-analysis",
    name: "数据分析",
    icon: "BarChartOutlined",
    category: "data",
    description: "CSV/Excel 分析、统计、可视化图表生成",
    examples: [
      "分析 sales.csv 的月度趋势,生成图表",
      "清洗这个 Excel,去重并修复日期格式",
      "比较 2023.csv 和 2024.csv 的差异",
      "统计 log.csv 中各错误类型的出现频率",
    ],
    acceptsFiles: true,
    fileTypes: [".csv", ".xlsx", ".xls", ".tsv", ".json"],
    systemPromptExtension: `你是数据分析专家,精通 Python pandas/matplotlib/seaborn。
分析前先 read_file 查看数据样本(前 10-20 行),理解列名、数据类型、缺失值情况。
根据数据特征选择合适的分析方法和可视化类型。
图表必须: 有标题、轴标签、适当的颜色;中文用 matplotlib 的 SimHei 或 Arial Unicode MS 字体。
如果 pandas 未安装,先用 run_code 的 auto-install 功能安装。`,
    steps: [
      {
        step: "inspect",
        maxIterations: 5,
        prompt: (ctx) => `读取数据文件 ${ctx.files?.[0] || "用户指定的文件"} 的前 20 行。
分析: 列名、数据类型、行数、缺失值情况。返回数据概况。`,
      },
      {
        step: "analyze",
        maxIterations: 12,
        prompt: (ctx) => `用户需求: ${ctx.userMessage}
数据概况: ${JSON.stringify(ctx.steps?.inspect || {})}
用 Python (pandas + matplotlib) 执行分析并生成图表。
图表保存为 PNG 文件。分析结论写入 markdown 报告。`,
      },
    ],
  },

  "web-research": {
    id: "web-research",
    name: "信息检索与调研",
    icon: "SearchOutlined",
    category: "research",
    description: "网页抓取、API 调用、多源信息汇总",
    examples: [
      "调研 2024 年主流 AI Agent 框架对比",
      "查询今天的美元兑人民币汇率",
      "搜索这个 npm 包的最新版本信息",
      "抓取这个网页的主要内容并翻译成中文",
    ],
    acceptsFiles: false,
    systemPromptExtension: `你是信息检索与分析专家。
获取实时数据的方式:
1. 网页抓取: 用 run_skill browser-automation 的 fetchPage 功能
2. REST API: 用 run_code(node) 调用 fetch 请求公开 API
3. CLI 工具: 用 run_shell 调用 curl
抓取到原始数据后,用 LLM 能力进行分析、对比、总结。
输出结构化的调研报告(markdown 格式),包含数据来源和时间。`,
    steps: [
      {
        step: "gather",
        maxIterations: 10,
        prompt: (ctx) => `用户需求: ${ctx.userMessage}
请从网络获取相关信息。使用以下方式:
- 公开 API: 用 run_code 调用 fetch
- 网页: 用 run_skill browser-automation fetchPage
收集尽可能全面的原始数据。`,
      },
      {
        step: "analyze-report",
        maxIterations: 8,
        prompt: (ctx) => `基于收集到的原始数据:
${JSON.stringify(ctx.steps?.gather || {})}
生成结构化分析报告(markdown),包含:
1. 摘要结论 2. 详细对比/分析 3. 数据来源与时间
保存为 report.md 文件。`,
      },
    ],
  },

  "image-process": {
    id: "image-process",
    name: "图片处理",
    icon: "PictureOutlined",
    category: "media",
    description: "批量压缩、格式转换、加水印、OCR 文字识别",
    examples: [
      "把 photos/ 下所有图片压缩到 500KB 以内",
      "给这些图片加水印文字 'CONFIDENTIAL'",
      "把所有 PNG 转成 WebP 格式",
      "识别这张图上的文字",
    ],
    acceptsFiles: true,
    fileTypes: [".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp", ".tiff", ".svg"],
    systemPromptExtension: `你是图片处理专家。
工具优先级: Python Pillow > ImageMagick (magick/convert)。
OCR: 优先用 Python pytesseract (需 Tesseract 引擎)。
批量操作时先处理 1 张确认效果,再批量执行。
输出统计: 处理数量、成功/失败数、原始总大小→处理后总大小。`,
    steps: [
      {
        step: "check-env",
        maxIterations: 3,
        prompt: (ctx) => `检查图片处理工具: Python Pillow, ImageMagick, Tesseract (OCR)。
JSON: {"pillow":"版本或false","imagemagick":"版本或false","tesseract":"版本或false"}`,
      },
      {
        step: "process",
        maxIterations: 12,
        prompt: (ctx) => `用户需求: ${ctx.userMessage}
${ctx.files?.length ? `输入文件: ${ctx.files.join(", ")}` : ""}
可用工具: ${JSON.stringify(ctx.steps?.["check-env"] || {})}
执行处理。批量操作先试 1 张,成功后批量执行。
完成后报告统计数据。`,
      },
    ],
  },

  "code-helper": {
    id: "code-helper",
    name: "代码辅助",
    icon: "CodeOutlined",
    category: "development",
    description: "生成脚本、调试代码、自动化任务",
    examples: [
      "写一个批量重命名文件的 Python 脚本",
      "这段代码报错了帮我看看: ...",
      "生成一个 cron 表达式解析器",
      "写个自动化脚本定时备份数据库",
    ],
    acceptsFiles: true,
    fileTypes: [".py", ".js", ".ts", ".sh", ".bat", ".ps1"],
    systemPromptExtension: `你是编程助手,擅长 Python/Node.js/Shell 脚本。
不只是生成代码 — 用 run_code 实际执行验证,确保代码能跑。
如果执行报错,自动分析错误、修复代码、重试。
生成的脚本保存到文件,方便用户后续使用。`,
    steps: null, // 无固定流水线,走单次 Agent 长对话
  },

  "system-admin": {
    id: "system-admin",
    name: "系统运维",
    icon: "DesktopOutlined",
    category: "system",
    description: "磁盘分析、进程管理、日志分析、环境检查",
    examples: [
      "查看磁盘使用情况,找出最大的 10 个文件夹",
      "分析最近的系统日志有没有异常",
      "检查 Node.js/Python/Java 开发环境版本",
      "列出占用端口的进程",
    ],
    acceptsFiles: false,
    systemPromptExtension: `你是系统运维专家。
当前系统: Windows (检测方式: os.platform())。
使用 PowerShell/cmd 命令获取系统信息。
危险操作(删除文件、杀进程、修改配置)必须先列出影响范围,等用户确认。
绝对不要执行 rm -rf、format、del /f /s 等破坏性命令。`,
    steps: null,
  },

  "file-organize": {
    id: "file-organize",
    name: "文件整理",
    icon: "FolderOpenOutlined",
    category: "file",
    description: "批量重命名、分类整理、查找重复、归档压缩",
    examples: [
      "把 downloads/ 按文件类型分类整理",
      "批量重命名: 把空格替换为下划线",
      "找出这个文件夹里的重复文件",
      "把项目打包为 zip 并排除 node_modules",
    ],
    acceptsFiles: false,
    systemPromptExtension: `你是文件管理专家。
操作前先 list_dir 查看目录结构,确认操作范围。
重命名/移动操作先生成预览列表(旧名→新名),让用户确认后再执行。
永远不要直接删除文件,改为移动到回收站或临时目录。`,
    steps: null,
  },

  "network-tools": {
    id: "network-tools",
    name: "网络工具",
    icon: "GlobalOutlined",
    category: "network",
    description: "API 调试、网页抓取、网络诊断",
    examples: [
      "测试一下 https://api.example.com/health 能不能通",
      "抓取这个网页上的所有图片链接",
      "ping 一下 google.com 看网络延迟",
      "用 curl 发一个 POST 请求到这个接口",
    ],
    acceptsFiles: false,
    systemPromptExtension: `你是网络工具专家。
API 调试: 用 run_code(node) 的 fetch 或 run_shell 的 curl。
网页抓取: 优先用 run_skill browser-automation。
网络诊断: ping, tracert, nslookup, netstat。
展示完整的请求/响应信息: status, headers, body。`,
    steps: null,
  },

  "learning-assist": {
    id: "learning-assist",
    name: "学习辅助",
    icon: "ReadOutlined",
    category: "learning",
    description: "文档翻译、内容总结、知识提取、论文分析",
    examples: [
      "翻译这篇 PDF 的摘要和结论",
      "总结这个长文档的关键要点",
      "解释这段代码的工作原理",
      "把这个技术文档转成通俗易懂的说明",
    ],
    acceptsFiles: true,
    fileTypes: [".pdf", ".md", ".txt", ".docx", ".html"],
    systemPromptExtension: `你是学习辅助专家。
读取文档: PDF 用 run_code(python) + PyPDF2/pdfminer 提取文本。
对于长文档,分段处理: 先提取目录/结构,再逐段翻译/总结。
翻译保持专业术语的准确性,必要时保留原文术语。
输出格式: markdown,便于阅读和后续编辑。`,
    steps: [
      {
        step: "extract",
        maxIterations: 8,
        prompt: (ctx) => `读取文档内容: ${ctx.files?.[0] || "用户指定的文件"}
如果是 PDF,用 Python 提取文本。如果是其他格式,直接 read_file。
返回文档结构概况(标题、章节、总字数)和前 2000 字内容。`,
      },
      {
        step: "process",
        maxIterations: 10,
        prompt: (ctx) => `用户需求: ${ctx.userMessage}
文档内容: ${ctx.steps?.extract?.summary || "见上一步"}
执行翻译/总结/分析,保存结果到 markdown 文件。`,
      },
    ],
  },
};

// 分类索引
export const TEMPLATE_CATEGORIES = [
  { key: "document", label: "文档处理", icon: "FileTextOutlined" },
  { key: "media",    label: "音视频/图片", icon: "PlayCircleOutlined" },
  { key: "data",     label: "数据分析", icon: "BarChartOutlined" },
  { key: "research", label: "信息检索", icon: "SearchOutlined" },
  { key: "development", label: "代码辅助", icon: "CodeOutlined" },
  { key: "system",   label: "系统运维", icon: "DesktopOutlined" },
  { key: "file",     label: "文件管理", icon: "FolderOpenOutlined" },
  { key: "network",  label: "网络工具", icon: "GlobalOutlined" },
  { key: "learning", label: "学习辅助", icon: "ReadOutlined" },
];

4.2 流水线控制器 (cowork-task-runner.js)

javascript
/**
 * CoworkTaskRunner — 循环调用 Code Agent 完成多步任务
 *
 * 核心思路:
 * - 有模板的任务 → 按模板定义的步骤序列,逐步创建独立 SubAgentContext 执行
 * - 无模板/自由提问 → 退化为单次 Agent Session(等同 /chat 的 Agent 模式)
 *
 * 每步之间:
 * - validate() 从 Agent 返回中提取结构化数据
 * - 下一步的 prompt(ctx) 拿到上一步的结构化结果
 * - 失败可重试单步,不影响已完成步骤
 *
 * 所有事件通过 async generator yield 出去,前端实时展示。
 */

import { SubAgentContext } from "./sub-agent-context.js";
import { TASK_TEMPLATES } from "./cowork-task-templates.js";

export async function* runCoworkPipeline(templateId, userContext, options = {}) {
  const template = TASK_TEMPLATES[templateId];

  // ── 无模板 或 模板无固定流水线 → 单次 Agent 长对话 ─────────────
  if (!template || !template.steps) {
    yield* runSingleAgentMode(template, userContext, options);
    return;
  }

  // ── 流水线模式 → 逐步 SubAgent 执行 ───────────────────────────
  const stepResults = {};
  const ctx = {
    userMessage: userContext.message,
    files: userContext.files || [],
    steps: stepResults,
  };

  yield {
    type: "pipeline-started",
    templateId,
    templateName: template.name,
    totalSteps: template.steps.length,
  };

  for (let i = 0; i < template.steps.length; i++) {
    const stepDef = template.steps[i];
    const stepPrompt = stepDef.prompt({ ...ctx, steps: stepResults });
    const fullPrompt = template.systemPromptExtension
      ? `${template.systemPromptExtension}\n\n---\n\n${stepPrompt}`
      : stepPrompt;

    yield {
      type: "step-started",
      step: stepDef.step,
      index: i,
      total: template.steps.length,
      prompt: stepPrompt,
    };

    const subCtx = SubAgentContext.create({
      role: `cowork-${templateId}-${stepDef.step}`,
      task: fullPrompt,
      maxIterations: stepDef.maxIterations || 8,
      cwd: options.cwd || process.cwd(),
      allowedTools: stepDef.tools || null,
    });

    try {
      const result = await subCtx.run(fullPrompt);

      // 转发 sub-agent 内部的工具调用事件(如果需要实时展示)
      yield {
        type: "step-completed",
        step: stepDef.step,
        index: i,
        summary: result.summary,
        toolsUsed: result.toolsUsed,
        iterationCount: result.iterationCount,
        artifacts: result.artifacts,
      };

      // 提取结构化数据供下一步使用
      if (stepDef.validate) {
        try {
          stepResults[stepDef.step] = stepDef.validate(result);
        } catch (_e) {
          stepResults[stepDef.step] = { summary: result.summary };
        }
      } else {
        stepResults[stepDef.step] = { summary: result.summary };
      }
    } catch (err) {
      yield {
        type: "step-failed",
        step: stepDef.step,
        index: i,
        error: err.message,
      };
      // 可选: 重试逻辑
      break;
    }
  }

  yield {
    type: "pipeline-complete",
    templateId,
    results: stepResults,
  };
}

/**
 * 单次 Agent 长对话模式(无流水线)
 */
async function* runSingleAgentMode(template, userContext, options) {
  const systemExtension = template?.systemPromptExtension || "";
  const fileContext = userContext.files?.length
    ? `\n\n[用户提供的文件: ${userContext.files.join(", ")}]`
    : "";
  const prompt = userContext.message + fileContext;

  const subCtx = SubAgentContext.create({
    role: template ? `cowork-${template.id}` : "cowork-free",
    task: systemExtension
      ? `${systemExtension}\n\n---\n\n用户需求: ${prompt}`
      : prompt,
    maxIterations: 20, // 自由模式给更多迭代空间
    cwd: options.cwd || process.cwd(),
  });

  yield { type: "agent-started", templateId: template?.id || "free" };

  try {
    const result = await subCtx.run(
      systemExtension
        ? `${systemExtension}\n\n---\n\n用户需求: ${prompt}`
        : prompt
    );

    yield {
      type: "agent-completed",
      summary: result.summary,
      toolsUsed: result.toolsUsed,
      iterationCount: result.iterationCount,
      artifacts: result.artifacts,
    };
  } catch (err) {
    yield { type: "agent-failed", error: err.message };
  }
}

4.3 WebSocket 协议扩展

新增消息类型 cowork-task,在 action-protocol.js 中处理:

javascript
// action-protocol.js — handleCoworkTask

async function handleCoworkTask(ws, msg, context) {
  const { runCoworkPipeline } = await import("../../lib/cowork-task-runner.js");

  const userContext = {
    message: msg.message || msg.content || "",
    files: msg.files || [],
  };

  const options = {
    cwd: msg.cwd || context.cwd || process.cwd(),
  };

  const gen = runCoworkPipeline(msg.template || null, userContext, options);

  for await (const event of gen) {
    _send(ws, {
      ...event,
      requestId: msg.id || msg.requestId,
      sessionId: msg.sessionId || null,
    });
  }
}

五、Web 前端实现

5.1 路由注册

javascript
// router/index.js — 新增
{ path: 'cowork', name: 'Cowork', component: () => import('../views/Cowork.vue') },

5.2 侧边栏入口

在 AppLayout.vue 的 "概 览" 分组中,AI 对话下方新增:

html
<a-menu-item key="cowork">
  <template #icon><RocketOutlined /></template>
  日常协作
</a-menu-item>

5.3 页面结构 (Cowork.vue)

┌─────────────────────────────────────────────────────────┐
│ Cowork.vue                                              │
│                                                         │
│ ┌─── 左侧 (280px) ───┐ ┌─── 右侧 (flex:1) ──────────┐ │
│ │                     │ │                              │ │
│ │  任务模板卡片列表     │ │  空状态 / 执行面板           │ │
│ │                     │ │                              │ │
│ │  ┌───────────────┐  │ │  ┌──────────────────────┐   │ │
│ │  │ 📄 文档处理    │  │ │  │ Step 1: 环境检查      │   │ │
│ │  │ 格式转换/合并  │  │ │  │ ✅ ffmpeg 6.1        │   │ │
│ │  └───────────────┘  │ │  └──────────────────────┘   │ │
│ │  ┌───────────────┐  │ │  ┌──────────────────────┐   │ │
│ │  │ 🎬 音视频处理  │  │ │  │ Step 2: 执行转换      │   │ │
│ │  │ 压缩/提取/剪辑│  │ │  │ 🔧 run_shell: ffmpeg  │   │ │
│ │  └───────────────┘  │ │  │ ✅ output.mp3 (5MB)   │   │ │
│ │  ...                │ │  └──────────────────────┘   │ │
│ │                     │ │                              │ │
│ │  ┌───────────────┐  │ │  ┌──────────────────────┐   │ │
│ │  │ ⚡ 自由提问    │  │ │  │ 最终结果              │   │ │
│ │  │ 任意任务      │  │ │  │ 📁 audio.mp3 [下载]   │   │ │
│ │  └───────────────┘  │ │  └──────────────────────┘   │ │
│ │                     │ │                              │ │
│ │  📂 拖拽文件到此处  │ │  ┌──────────────────────┐   │ │
│ │                     │ │  │ 💬 输入框 + 发送按钮   │   │ │
│ └─────────────────────┘ │  └──────────────────────┘   │ │
│                         └──────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

5.4 前端状态管理 (cowork.js store)

javascript
// stores/cowork.js
import { defineStore } from 'pinia'
import { ref, reactive, computed } from 'vue'
import { useWsStore } from './ws.js'

export const useCoworkStore = defineStore('cowork', () => {
  // 当前选中的模板
  const selectedTemplate = ref(null)
  // 上传/拖入的文件路径
  const files = ref([])
  // 执行状态
  const isRunning = ref(false)
  // 流水线步骤状态
  const steps = ref([])    // [{ step, status, summary, tools, ... }]
  // 对话消息 (自由模式)
  const messages = ref([])
  // 最终结果
  const result = ref(null)

  function selectTemplate(template) {
    selectedTemplate.value = template
    reset()
  }

  function reset() {
    steps.value = []
    messages.value = []
    result.value = null
    isRunning.value = false
  }

  async function execute(message) {
    const ws = useWsStore()
    isRunning.value = true
    messages.value.push({ role: 'user', content: message })

    // 注册事件处理
    const unsubscribe = ws.onMessage((msg) => {
      handleCoworkEvent(msg)
    })

    ws.send({
      type: 'cowork-task',
      template: selectedTemplate.value?.id || null,
      message,
      files: files.value,
      cwd: window.__CC_CONFIG__?.projectRoot || null,
    })

    // unsubscribe 在 pipeline-complete/agent-completed 时调用
  }

  function handleCoworkEvent(msg) {
    switch (msg.type) {
      case 'pipeline-started':
        steps.value = []
        break
      case 'step-started':
        steps.value.push({
          step: msg.step,
          index: msg.index,
          status: 'running',
          summary: null,
        })
        break
      case 'step-completed':
        const step = steps.value.find(s => s.step === msg.step)
        if (step) {
          step.status = 'done'
          step.summary = msg.summary
          step.toolsUsed = msg.toolsUsed
        }
        break
      case 'step-failed':
        const failedStep = steps.value.find(s => s.step === msg.step)
        if (failedStep) {
          failedStep.status = 'failed'
          failedStep.error = msg.error
        }
        break
      case 'pipeline-complete':
        result.value = msg.results
        isRunning.value = false
        break
      case 'agent-started':
        break
      case 'agent-completed':
        messages.value.push({ role: 'assistant', content: msg.summary })
        result.value = { summary: msg.summary, artifacts: msg.artifacts }
        isRunning.value = false
        break
      case 'agent-failed':
        messages.value.push({ role: 'assistant', content: `Error: ${msg.error}` })
        isRunning.value = false
        break
      // 透传 tool-executing / tool-result 事件
      case 'tool-executing':
        steps.value[steps.value.length - 1]?.tools?.push(msg.tool)
        break
    }
  }

  return {
    selectedTemplate, files, isRunning, steps, messages, result,
    selectTemplate, reset, execute,
  }
})

六、CLI-Anything 开源工具集成

6.1 核心理念:开源工具优先

CLI-Anything (https://github.com/HKUDS/CLI-Anything) 能为任意 CLI 软件生成 Agent 原生的自然语言包装器。这意味着:

  • 用户说"提取视频音频",cli-anything-ffmpeg 自动生成正确的 ffmpeg -i video.mp4 -vn audio.mp3 命令
  • Agent 不需要记住任何 CLI 参数语法,由 cli-anything 的 LLM 层负责翻译
  • 任何有 CLI 接口的开源软件都能一键接入

开源工具优先级链

用户需求: "压缩这个视频"

优先级 1: cli-anything 已注册的工具
  └─ run_skill cli-anything-ffmpeg "compress video.mp4 to 50MB"
     (自然语言 → cli-anything 翻译 → 正确的 ffmpeg 命令)

优先级 2: 直接调用开源工具 CLI
  └─ run_shell: ffmpeg -i video.mp4 -crf 28 output.mp4
     (Agent 自己构造命令,需要了解参数)

优先级 3: Python/Node 开源库
  └─ run_code(python): from moviepy.editor import VideoFileClip; ...
     (用代码库实现,更灵活但更慢)

优先级 4: 在线 API / 告知用户
  └─ 最后手段

6.2 开源工具全景图

以下开源工具覆盖 Cowork 十大场景,均可通过 cli-anything 注册为 Agent 技能:

场景开源工具CLI 命令cli-anything 注册名用途
文档处理Pandocpandoccli-anything-pandoc万能文档格式转换
LibreOfficesofficecli-anything-sofficeOffice 文档处理
wkhtmltopdfwkhtmltopdfcli-anything-wkhtmltopdfHTML→PDF
Ghostscriptgscli-anything-gsPDF 合并/压缩/OCR
音视频FFmpegffmpegcli-anything-ffmpeg音视频全能处理
yt-dlpyt-dlpcli-anything-yt-dlp视频下载
SoXsoxcli-anything-sox音频处理/降噪
图片处理ImageMagickmagickcli-anything-magick图片编辑/转换/批处理
Tesseracttesseractcli-anything-tesseractOCR 文字识别
ExifToolexiftoolcli-anything-exiftool图片元数据管理
OptiPNGoptipngcli-anything-optipngPNG 无损压缩
数据分析csvkitcsvstatcli-anything-csvkitCSV 命令行分析
jqjqcli-anything-jqJSON 处理
SQLitesqlite3cli-anything-sqlite3轻量数据库查询
gnuplotgnuplotcli-anything-gnuplot命令行图表生成
网络工具curlcurlcli-anything-curlHTTP 请求调试
httpiehttpcli-anything-httpie更友好的 API 调试
nmapnmapcli-anything-nmap网络扫描/诊断
代码辅助Gitgit(已有 git 工具)版本控制
ripgreprgcli-anything-rg代码搜索
shellcheckshellcheckcli-anything-shellcheckShell 脚本检查
系统运维htop/btopbtopcli-anything-btop进程监控
ncduncducli-anything-ncdu磁盘分析
rclonerclonecli-anything-rclone云存储同步
文件管理7-Zip7zcli-anything-7z压缩/解压
rsyncrsynccli-anything-rsync文件同步
fdfdcli-anything-fd快速文件查找
学习辅助Popplerpdftotextcli-anything-pdftotextPDF 文本提取
translate-shelltranscli-anything-trans命令行翻译

6.3 自动发现 → 注册 → 使用 流程

┌──────────────────────────────────────────────────────────────────┐
│ Cowork Agent 执行任务前的工具准备阶段                              │
│                                                                  │
│ Step 0: 环境检查                                                  │
│                                                                  │
│   ① list_skills → 看已有哪些 cli-anything-* 技能                  │
│      已注册: [cli-anything-ffmpeg, cli-anything-pandoc, ...]      │
│                                                                  │
│   ② 判断当前任务需要哪些工具                                       │
│      任务: "压缩视频" → 需要 ffmpeg                                │
│                                                                  │
│   ③ cli-anything-ffmpeg 已注册?                                   │
│      ├─ YES → 直接 run_skill cli-anything-ffmpeg "compress ..."   │
│      └─ NO  → 进入自动安装流程                                     │
│                                                                  │
│ Step 1: 安装底层开源工具                                           │
│   run_shell: winget install Gyan.FFmpeg                           │
│   验证: run_shell: ffmpeg -version → OK                          │
│                                                                  │
│ Step 2: 安装 cli-anything (如果未安装)                             │
│   run_shell: pip install cli-anything                             │
│                                                                  │
│ Step 3: 生成 cli-anything 包装器                                  │
│   run_shell: cli-anything generate ffmpeg                         │
│   (cli-anything 为 ffmpeg 生成自然语言包装器)                      │
│                                                                  │
│ Step 4: 注册为 ChainlessChain 技能                                │
│   run_shell: chainlesschain cli-anything register ffmpeg           │
│   (生成 SKILL.md + handler.js → 4 层技能系统自动加载)              │
│                                                                  │
│ Step 5: 使用                                                      │
│   run_skill cli-anything-ffmpeg "compress video.mp4 to 50MB"      │
│   (自然语言输入 → cli-anything 翻译 → ffmpeg 执行 → 返回结果)     │
│                                                                  │
│ 整个过程对用户透明,Agent 自动完成                                  │
└──────────────────────────────────────────────────────────────────┘

6.4 已注册工具的使用优势

对比: 直接 run_shell vs cli-anything skill

方式 A: run_shell (Agent 需要知道 ffmpeg 参数)
  Agent: run_shell("ffmpeg -i video.mp4 -vn -acodec libmp3lame -ab 192k audio.mp3")
  → Agent 需要记住/推理正确的 ffmpeg 参数组合
  → 参数错了就失败,需要多轮重试

方式 B: run_skill cli-anything-ffmpeg (自然语言)
  Agent: run_skill("cli-anything-ffmpeg", "extract audio from video.mp4 as mp3")
  → cli-anything 的 LLM 层负责翻译为正确命令
  → 更高的一次成功率,更少的 token 消耗

方式 B 的好处:

  • Agent 的 prompt 更简洁(不用塞 ffmpeg 参数手册)
  • 容错性更好(cli-anything 内置纠错)
  • 可组合性更强(同样的自然语言接口适用于所有工具)

6.5 与 Cowork 模板的集成

每个 Cowork 模板的 systemPromptExtension 中优先推荐 cli-anything:

// 模板 system prompt 注入(以音视频为例):

## 工具使用优先级
1. 先 list_skills 查看是否已有 cli-anything-ffmpeg 技能
   → 如果有: run_skill cli-anything-ffmpeg "用户的自然语言描述"
2. 如果没有 cli-anything 技能但 ffmpeg 已安装
   → 直接 run_shell 调用 ffmpeg(需要自己构造参数)
3. 如果 ffmpeg 未安装
   → 先安装 ffmpeg,然后尝试安装 cli-anything 并注册
   → 如果 cli-anything 安装失败,直接 run_shell 使用 ffmpeg
4. 如果底层工具完全不可用
   → 使用 Python 库替代(如 moviepy、pydub)

6.6 批量工具预注册

首次使用 Cowork 时,Agent 可以一次性注册用户系统上已有的所有工具:

Agent 在首次 Cowork session 中:
  ① run_shell: chainlesschain cli-anything doctor --json
     → 检查 Python + cli-anything 是否安装
  
  ② run_shell: chainlesschain cli-anything scan --json
     → 发现系统已安装的所有可包装工具
     → [ffmpeg, pandoc, magick, tesseract, 7z, curl, ...]
  
  ③ 对每个发现的工具:
     run_shell: chainlesschain cli-anything register <tool> --force --json
     → 批量注册为 ChainlessChain 技能
  
  ④ 后续所有 Cowork 任务都可以直接 run_skill 调用

七、工具自动安装机制

6.1 设计原则

  • Agent 检测到缺少工具时自动安装,不中断用户流程
  • 仅在 Agent 无法完成任务或确实需要人为确认时才询问用户
  • 安装范围限于公开的包管理器(pip、npm、winget、brew、choco)
  • 安装前后自动验证工具可用性

6.2 自动安装决策树 (含 cli-anything 注册)

Agent 执行任务

  ├─ Step 0: 检查 cli-anything 已注册技能
  │   list_skills category=integration → 有无 cli-anything-<tool>?
  │   ├─ 已注册 → run_skill cli-anything-<tool> "自然语言需求" → 完成
  │   └─ 未注册 → 继续

  ├─ Step 1: 检查底层工具是否已安装
  │   run_shell: <tool> --version
  │   ├─ 已安装 → 直接用 run_shell 调用,同时后台注册 cli-anything
  │   └─ 未安装 → 自动安装

  ├─ Step 2: 自动安装底层开源工具
  │   ├─ Python 包 → run_code auto-install (无需确认)
  │   ├─ npm 包    → run_shell: npm install -g <pkg> (无需确认)
  │   ├─ 系统工具:
  │   │   ├─ Windows: winget install <id> --accept-package-agreements --accept-source-agreements
  │   │   ├─ 备选:   choco install <pkg> -y
  │   │   ├─ macOS:  brew install <pkg>
  │   │   └─ Linux:  apt-get install -y <pkg>
  │   └─ 安装后验证: <tool> --version
  │       ├─ 成功 → 继续
  │       └─ 失败 → 唯一需要告知用户的场景

  ├─ Step 3: 注册 cli-anything 包装器 (最佳实践,非阻塞)
  │   run_shell: chainlesschain cli-anything register <tool> --force --json
  │   ├─ 成功 → 后续同类任务可用 run_skill 自然语言调用
  │   └─ 失败 → 无影响,继续用 run_shell 直接调用

  └─ Step 4: 执行任务
      ├─ 优先: run_skill cli-anything-<tool> "自然语言需求"
      └─ 备选: run_shell: <tool> <Agent 构造的参数>

6.3 系统工具安装映射表

工具winget IDchoco IDbrew ID用途
ffmpegGyan.FFmpegffmpegffmpeg音视频处理
pandocJohnMacFarlane.Pandocpandocpandoc文档转换
LibreOfficeTheDocumentFoundation.LibreOfficelibreoffice-freshlibreofficeOffice 文档
TesseractUB-Mannheim.TesseractOCRtesseracttesseractOCR 识别
ImageMagickImageMagick.ImageMagickimagemagickimagemagick图片处理
wkhtmltopdfwkhtmltopdfwkhtmltopdfHTML→PDF
GraphVizGraphviz.Graphvizgraphvizgraphviz图表生成

6.4 System Prompt 注入

每个模板的 systemPromptExtension 中包含自动安装指令:

通用安装规则 (注入到所有 cowork agent 的 system prompt):

## 工具自动安装
当你发现所需的命令行工具未安装时,按以下规则自动安装:
1. Python 包: 直接用 run_code 执行,auto-install 会自动处理 pip install
2. npm 包: run_shell: npm install -g <package>
3. 系统工具 (ffmpeg/pandoc/tesseract/imagemagick/soffice):
   - Windows: 先尝试 winget install <id> --accept-package-agreements --accept-source-agreements
   - 如果 winget 不可用,尝试 choco install <pkg> -y
   - 如果都不可用,告诉用户下载链接
   - macOS: brew install <pkg>
4. 安装后立即验证: <tool> --version
5. 只有在安装失败或需要管理员权限时才告知用户

绝对不要因为工具未安装就放弃任务。先尝试安装,安装失败再寻找替代方案。
替代方案优先级: Python 库 > Node.js 库 > 在线 API > 告知用户手动安装。

6.5 run_code auto-install 已有能力

agent-core.js 中的 _executeRunCode 已实现 Python 包自动安装:

javascript
// 检测 ImportError → 自动 pip install → 重试
if (error.classification === 'import_error') {
  const missingModule = extractModuleName(error.stderr);
  await run_shell(`pip install ${missingModule}`);
  // 自动重试执行
}

Node.js 同理,通过 npm install 安装缺失模块后重试。


七、安全设计

6.1 权限分级

操作类型风险等级处理方式
读取文件内容LOW直接执行
生成/写入新文件LOW直接执行
安装 pip/npm 包MEDIUMrun_code auto-install,限制来源
执行 shell 命令MEDIUMshell-policy 过滤危险命令
删除/覆盖文件HIGH需用户 approval(WebSocket question 事件)
杀进程/改系统配置HIGH需用户 approval
网络请求外部 URLMEDIUM展示目标 URL,允许执行

6.2 已有安全机制复用

  • Shell Policy (coding-agent-shell-policy.cjs): 已有的命令黑名单过滤
  • Plan Mode: 高风险操作自动进入 approval flow
  • Hook Pipeline: PreToolUse 可拦截危险操作
  • SubAgentContext: 工具白名单 + iteration budget 限制

6.3 数据隐私

  • 所有处理在本机执行,文件不上传第三方
  • LLM 只接收文件的文本内容摘要,不接收二进制数据
  • 实时数据抓取只访问用户指定的 URL

七、实施计划

Phase 1: 核心管线 (P0, 2 天)

任务文件预计行数
任务模板定义packages/cli/src/lib/cowork-task-templates.js~400
流水线控制器packages/cli/src/lib/cowork-task-runner.js~300
WS 消息处理packages/cli/src/gateways/ws/action-protocol.js (修改)~40
Web 页面packages/web-panel/src/views/Cowork.vue~400
前端状态packages/web-panel/src/stores/cowork.js~200
路由+侧边栏router/index.js + AppLayout.vue (修改)~10

Phase 2: 增强体验 (P1, 1 天)

任务说明
文件拖拽区拖入文件获取本机路径
步骤时间线可视化展示每步的工具调用和结果
结果预览图片/PDF/CSV 在线预览 + 下载

Phase 3: 扩展能力 (P2, 1-2 天)

任务说明
HTTP 文件上传真正的文件上传到临时目录
自定义模板用户创建/编辑自己的任务模板
历史记录保存执行历史,可重放

Phase 4: 测试 (P0, 1 天)

测试类型范围
单元测试cowork-task-runner, cowork-task-templates
集成测试WS 消息 → runner → SubAgent 全链路
E2E 测试Web 页面交互 → 任务执行 → 结果展示

八、依赖工具安装指南

用户机器上需要安装以下工具才能使用对应场景(Agent 会自动检测可用性并给出安装提示):

场景必需工具安装命令 (Windows)安装命令 (macOS)
文档处理pandocwinget install pandocbrew install pandoc
文档处理LibreOfficewinget install LibreOfficebrew install --cask libreoffice
音视频ffmpegwinget install ffmpegbrew install ffmpeg
数据分析Python + pandaspip install pandas matplotlib同左
图片处理Python Pillowpip install Pillow同左
图片 OCRTesseractwinget install tesseractbrew install tesseract
网页抓取Node.js (已有)

九、与竞品的差异

维度ChatGPT / 通用聊天在线工具 (smallpdf等)Web Cowork
能否执行只能给建议只能做单一操作实际执行,产出文件
数据隐私上传到云端上传到第三方本机处理,不出境
灵活性通用但不精单一功能LLM 动态生成代码
多步任务需手动串联不支持自动流水线
实时数据有网络能力不支持网页抓取+API调用
成本付费 API部分收费本地 LLM 免费

十、历史规划 — F1–F9 详细实施计划(已全部落地 v0.46.0)

制定日期: 2026-04-14 · 完成日期: 2026-04-15 状态: ✅ 全部实现 — 详见本文末尾「2026-04-15 — Cowork Evolution v0.46.0」实施记录 依赖关系: F1(Orchestrator) 独立;F2(Debate) 独立;F3(模板市场) 依赖 EvoMap;F4(定时任务) 独立;F5(移动端) 依赖 F3;F6(MCP) 独立;F7(工作流) 依赖 F1;F8(P2P) 依赖 F3;F9(学习) 依赖历史系统 实际实施顺序: F3 → F4 → F6 → F9 → F7 → F5 → F8 → F1 → F2

📝 本节保留原规划文本作为设计溯源参考。真正的后续演进方向见「十一、未来演进」。

F1: Orchestrator 多 Agent 并行模式 — 短期 (v5.0.3.1)

目标: Cowork 任务可选择使用 Orchestrator 进行多 Agent 并行执行,适合大型调研、多文件批处理、多维分析等需要拆分子任务的场景。

架构设计:

用户 → Cowork.vue (选择"并行模式") → cowork.js store
  → WS: { type: "cowork-task", parallel: true, agents: 3 }
    → action-protocol.js: handleCoworkTask()
      → if parallel: Orchestrator.addTask() (复用现有编排器)
      → else: runCoworkTask() (现有单 Agent 路径)

实现文件与变更:

文件变更
cowork-task-templates.js每个模板增加 parallelStrategy 字段 (none/auto/always);web-researchdata-analysis 默认 auto
cowork-task-runner.js新增 runCoworkTaskParallel(opts) — 调用 Orchestrator.addTask(),透传 onProgress/signal
action-protocol.jshandleCoworkTask() 根据 message.parallel 或模板 parallelStrategy 选择执行路径
web-panel/stores/cowork.jsexecuteDirectWs() 增加 parallel 选项;监听 orchestrate:event 消息更新多 Agent 进度
web-panel/views/Cowork.vue模板卡片增加"并行模式"开关;进度区域展示多 Agent 状态面板 (agent-1: running, agent-2: done...)

WS 消息扩展:

消息类型说明
cowork:agent-progressServer → Client,单个 Agent 的进度 { agentIndex, status, tool, iteration }
cowork:subtask-doneServer → Client,子任务完成 { subtaskIndex, summary, artifacts }

关键决策:

  • 复用 Orchestrator 而非新建并行引擎 — 减少代码重复,利用已有的 AgentRouter + 重试 + CI 集成
  • 模板的 parallelStrategy: "auto" 表示由 Orchestrator 的 _decompose() 自动决定是否拆分
  • 最大并行数限制为 Math.min(message.agents || 3, 10)

测试计划: 单元 8 + 集成 4 + E2E 3 = 15 tests


F2: Cowork Debate 模式 — 短期 (v5.0.3.2)

目标: 用户提交方案/代码/文档,多个 Agent 从不同视角(性能/安全/可维护性/成本/用户体验)进行审查辩论,最终输出综合评审报告。

架构设计:

用户 → Cowork.vue (选择"方案审查"模板) → cowork.js store
  → WS: { type: "cowork-task", templateId: "debate-review", perspectives: [...] }
    → action-protocol.js → cowork-task-runner.js
      → debate-review-cli.js: startDebate({ target, perspectives })
        → N 个并行 LLM 调用 (每个视角一个)
        → 仲裁者 LLM 综合 → { reviews, verdict, verdictReason }

实现文件与变更:

文件变更
cowork-task-templates.js新增 debate-review 模板 (第 11 个),包含 5 个默认视角
cowork-task-runner.js检测 templateId === "debate-review" 时调用 startDebate() 而非 SubAgentContext
cowork/debate-review-cli.js已存在;需适配 onProgress 回调 — 每个视角完成时通知
action-protocol.jshandleCoworkTask() 透传 perspectives 参数
web-panel/stores/cowork.js解析 debate 结果结构 { reviews[], verdict } 并渲染
web-panel/views/Cowork.vue新增 Debate 结果视图 — 分栏展示各视角评审 + 最终裁定

UI 设计:

  • 审查过程中: 显示 5 个视角卡片,每个显示进度条 (0/1)
  • 审查完成: 每个视角展开/收起评审详情,顶部高亮裁定结果 (通过/有风险/建议修改)
  • 用户可自定义视角列表 (如添加"合规性"、移除"性能")

关键决策:

  • 复用 debate-review-cli.jsstartDebate() 而非重写 — 该模块已有 25 个测试验证
  • A/B Compare (ab-comparator-cli.js) 作为 debate-review 模板的子模式 — 用户选择"方案对比"时自动路由

测试计划: 单元 6 + 集成 3 + E2E 2 = 11 tests


F3: 模板市场 — 社区共享任务模板 — 短期 (v5.0.3.3)

目标: 用户可发布自定义 Cowork 模板到 EvoMap Hub,其他用户可搜索、下载、安装社区模板。

架构设计:

EvoMap Hub (远程)
  ↑ publish(template)     ↓ search/download
模板市场 UI ← cowork-template-market.js ← evomap-client.js
  ↓ install                ↓ uninstall
~/.chainlesschain/cowork/community-templates/  (本地)
  ↓ loadCommunityTemplates()
cowork-task-templates.js (合并: 内置 10 + 社区 N)

实现文件与变更:

文件变更
src/lib/cowork-template-market.js新建searchTemplates(query), downloadTemplate(id), publishTemplate(template), installTemplate(gene), uninstallTemplate(id), listInstalled()
cowork-task-templates.js新增 loadCommunityTemplates(cwd) — 扫描 ~/.chainlesschain/cowork/community-templates/*.jsongetTemplate() 合并内置 + 社区
action-protocol.js新增 handleCoworkMarket(server, id, ws, message) — search/install/publish 路由
message-dispatcher.js新增 "cowork-market" 路由
ws-server.js新增 _handleCoworkMarket() 委托
web-panel/stores/cowork.js新增 marketTemplates ref + searchMarket(query) + installFromMarket(id)
web-panel/views/Cowork.vue新增"模板市场"按钮 → 弹窗/侧边栏展示社区模板列表 (搜索 + 安装 + 评分)

模板市场 JSON 格式 (EvoMap Gene 扩展):

json
{
  "id": "community-pdf-optimizer",
  "name": "PDF 优化大师",
  "description": "批量压缩、合并、分割 PDF 文件",
  "author": "user123",
  "version": "1.0.0",
  "category": "doc-convert",
  "icon": "FilePdfOutlined",
  "examples": ["压缩 report.pdf 到 5MB 以下", "合并 3 个 PDF"],
  "systemPromptExtension": "...",
  "shellPolicyOverrides": [],
  "downloads": 1234,
  "rating": 4.5
}

关键决策:

  • 复用 EvoMapClientsearch/download/publish API — 社区模板作为 EvoMap Gene 的 category: "cowork-template" 子类
  • 本地安装路径 ~/.chainlesschain/cowork/community-templates/ — 与 JSONL 历史同级
  • 安全: 社区模板的 systemPromptExtension 不能声明 shellPolicyOverrides,仅内置模板可放行危险命令

测试计划: 单元 10 + 集成 4 + E2E 3 = 17 tests


F4: 定时任务集成 — 中期 (v5.1.1)

目标: 用户可配置 Cowork 任务定期自动执行(如每日生成代码质量报告、每周清理临时文件、定时同步数据)。

架构设计:

用户 → Cowork.vue ("定时执行"按钮) → cron 配置面板
  → WS: { type: "cowork-cron-create", schedule: "0 9 * * *", templateId, userMessage, files }
    → action-protocol.js → cowork-cron-manager.js
      → node-cron scheduler → 到时间 → runCoworkTask() → 结果写 history.jsonl
                                       → WS 通知在线用户

实现文件与变更:

文件变更
src/lib/cowork-cron-manager.js新建CronManager 类:addJob(schedule, taskConfig), removeJob(jobId), listJobs(), pauseJob(jobId), resumeJob(jobId)
cowork-task-runner.jsrunCoworkTask() 增加 source: "cron" 标识,history 记录中区分手动/定时
action-protocol.js新增 handleCoworkCronCreate/Delete/List()
message-dispatcher.js新增 "cowork-cron-create", "cowork-cron-delete", "cowork-cron-list" 路由
ws-server.js启动时 cronManager.loadPersisted() 恢复已保存的 cron 任务;新增 3 个委托方法
web-panel/stores/cowork.js新增 cronJobs ref + createCron(schedule, config) + loadCronJobs()
web-panel/views/Cowork.vue模板选择后增加"定时执行"开关 → 展开 cron 表达式选择器 (预设: 每天/每周/每月/自定义)

持久化: ~/.chainlesschain/cowork/cron-jobs.json — JSON 数组,每条包含 { id, schedule, templateId, userMessage, files, enabled, createdAt, lastRunAt }

关键决策:

  • 使用 node-cron (已有 Orchestrator 的 startCronWatch 先例) 而非系统 crontab — 跨平台
  • Cron 任务执行结果通过 cowork:cron-result WS 消息推送给在线客户端
  • 服务器关闭时 cron 任务自然停止,重启时从持久化文件恢复
  • 最短间隔限制 5 分钟,防止滥用

测试计划: 单元 8 + 集成 3 + E2E 2 = 13 tests


F5: 移动端入口 — Android App 的 Cowork 页面 — 中期 (v5.1.2)

目标: Android App 增加"日常协作"页面,通过 P2P Bridge 连接桌面端/CLI 执行 Cowork 任务。

架构设计:

Android App (Jetpack Compose)
  CoworkScreen.kt → CoworkViewModel.kt
    → P2PSkillBridge → WebSocket → CLI WS Server
      → handleCoworkTask() → SubAgentContext → 结果返回
                           ← cowork:progress / cowork:done

实现文件与变更:

目录/文件变更
android-app/feature-ai/.../cowork/ui/CoworkScreen.kt新建 — Compose UI:模板网格 + 消息输入 + 文件选择 + 进度卡片
android-app/feature-ai/.../cowork/ui/CoworkViewModel.kt新建 — StateFlow<CoworkUiState>,WebSocket 通信,任务管理
android-app/feature-ai/.../cowork/model/CoworkModels.kt新建CoworkTemplate, CoworkTask, CoworkResult data classes
android-app/feature-ai/.../cowork/service/CoworkService.kt新建 — 通过 P2PSkillBridge / 直接 WebSocket 发送 cowork-task 消息
android-app/app/.../navigation/AppNavigation.kt新增 cowork 路由
android-app/app/.../screens/MainScreen.kt底部导航增加"协作"入口

UI 设计 (Material 3):

  • 顶部: 模板横向滚动卡片 (复用后端 getTemplatesForUI() 返回的 icon/description)
  • 中间: 消息列表 (用户输入 + Agent 响应)
  • 底部: 输入栏 + 文件附件按钮 + 发送按钮
  • 进度: BottomSheet 展示当前工具执行、迭代计数、token 消耗

关键决策:

  • 模板列表通过 WS cowork-templates 消息从 CLI 后端获取 — 不在 Android 端重复定义
  • 文件路径: Android 端选择文件后上传到桌面端 ~/Downloads/cowork-upload/,然后传递路径
  • 离线支持: 模板列表本地缓存 (Room),任务执行必须在线

测试计划: ViewModel 单元 6 + Service 集成 4 = 10 tests (Kotlin)


F6: MCP 工具集成 — 中期 (v5.1.3)

目标: Cowork 任务模板可声明所需的 MCP 服务器,任务启动时自动 mount,结束后 unmount。复用已有的 Skill-Embedded MCP 模式。

架构设计:

模板定义: TASK_TEMPLATES["data-analysis"].mcpServers = [
  { name: "sqlite", command: "npx", args: ["-y", "@modelcontextprotocol/server-sqlite"] }
]

runCoworkTask() 流程:
  1. getTemplate(templateId)
  2. if template.mcpServers → mountSkillMcpServers(mcpClient, { mcpServers })
  3. SubAgentContext.create() → run()  (MCP 工具已可用)
  4. unmountSkillMcpServers(mcpClient, mountedNames)

实现文件与变更:

文件变更
cowork-task-templates.js部分模板增加 mcpServers 字段:data-analysis → sqlite-server;web-research → fetch-server;doc-convert → filesystem-server
cowork-task-runner.jsrunCoworkTask() 启动前调用 mountSkillMcpServers(),finally 块调用 unmountSkillMcpServers();通过 opts.mcpClient 获取 MCP 客户端实例
action-protocol.jshandleCoworkTask()server 获取 mcpClient 传入 runner
ws-server.js确保 mcpClient 实例可被 action-protocol 访问
getTemplatesForUI()返回 mcpServers 的服务器名列表 (不含 command/args — 安全)

社区模板 MCP 声明 (F3 联动):

json
{
  "mcpServers": [
    { "name": "github", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] }
  ]
}

关键决策:

  • 直接复用 skill-mcp.jsmountSkillMcpServers() / unmountSkillMcpServers() — 零重复代码
  • MCP 服务器安装通过 npx -y 自动下载,用户无需手动安装
  • 社区模板的 MCP 声明需要安全审核 — 仅白名单内的 MCP 服务器允许自动 mount
  • 容错: mount 失败不阻塞任务执行,降级为无 MCP 工具模式

测试计划: 单元 6 + 集成 3 + E2E 2 = 11 tests


F7: 工作流编排 — 长期 (v5.2.1)

目标: 用户可将多个 Cowork 模板串联成工作流(DAG),实现复杂的多步骤自动化流水线。支持可视化拖拽编排。

架构设计:

工作流定义 (DAG):
  Stage 1: web-research "调研竞品"
    ↓ (artifacts → Stage 2 input)
  Stage 2: data-analysis "分析数据"

  Stage 3: doc-convert "生成报告"

存储: workflow-engine.js 的 workflows 表
执行: cowork-workflow-executor.js → 逐 stage 调用 runCoworkTask()

实现文件与变更:

文件变更
src/lib/cowork-workflow-executor.js新建executeWorkflow(workflowId, db, opts): 读取 DAG → 拓扑排序 → 逐 stage 执行 runCoworkTask() → stage 间传递 artifacts
src/lib/workflow-engine.js扩展 stage type: 新增 "cowork" 类型 (已有 "action" / "approval")
action-protocol.js新增 handleCoworkWorkflow() — 创建/执行/查询工作流
message-dispatcher.js新增 "cowork-workflow" 路由
web-panel/views/CoworkWorkflow.vue新建 — 可视化 DAG 编辑器 (基于 @vue-flow/core 拖拽)
web-panel/stores/cowork.js新增 workflows ref + createWorkflow() + runWorkflow()
web-panel/router/index.js新增 /cowork/workflow 路由

可视化编辑器设计:

  • 左侧: 模板面板 (拖出节点)
  • 中间: DAG 画布 (连线表示数据流)
  • 右侧: 节点属性面板 (配置 userMessage、files、条件分支)
  • 底部: 运行按钮 + 执行日志

Stage 间数据传递:

text
{
  "stages": [
    { "id": "s1", "templateId": "web-research", "userMessage": "调研 {input.topic}", "next": ["s2"] },
    { "id": "s2", "templateId": "data-analysis", "userMessage": "分析 {s1.artifacts}", "next": ["s3"] },
    { "id": "s3", "templateId": "doc-convert", "userMessage": "生成报告 {s2.summary}", "next": [] }
  ]
}

关键决策:

  • 复用 workflow-engine.js 的 DAG 校验 (validateDAG) 和存储模型
  • Stage 类型扩展为 "cowork" — 每个 stage 本质是一次 runCoworkTask() 调用
  • {s1.artifacts} 模板变量在执行时替换为前一 stage 的实际输出
  • 可视化编辑器使用 @vue-flow/core (Vue 3 的 React Flow 等价物)
  • 并行 stage 支持: DAG 中无依赖的 stage 可并行执行 (复用 F1 的 Orchestrator)

测试计划: 单元 12 + 集成 5 + E2E 3 = 20 tests


F8: 多用户协作 — P2P 共享任务模板和执行结果 — 长期 (v5.2.2)

目标: 通过 P2P 网络,团队成员可共享 Cowork 模板、发送任务执行结果、协同编辑工作流。

架构设计:

用户 A (发送方)                    用户 B (接收方)
Cowork.vue → "分享" 按钮            收到 P2P 消息
  → p2p-manager.sendMessage()        → 解析 cowork-share 类型
    → Signal 协议加密                   → 弹窗: "用户A分享了模板/结果"
      → P2P 网络传输                      → 安装模板 / 查看结果

实现文件与变更:

文件变更
src/lib/cowork-p2p-sharing.js新建shareTemplate(peerId, template), shareResult(peerId, result), handleIncoming(message)
src/lib/p2p-manager.js新增消息类型: cowork-template-share, cowork-result-share
action-protocol.js新增 handleCoworkShare() — 封装 P2P 发送
web-panel/views/Cowork.vue任务完成后增加"分享给..."按钮 → 选择在线 Peer → 发送
web-panel/stores/cowork.js新增 sharedItems ref + shareTemplate() + shareResult()

P2P 消息格式:

json
{
  "type": "cowork-template-share",
  "from": "did:key:z6Mk...",
  "template": { "id": "custom-pdf", "name": "PDF 处理", "systemPromptExtension": "..." },
  "signature": "..."
}

关键决策:

  • 复用 Signal Protocol 端到端加密 — 模板/结果在传输中加密
  • 接收方需手动确认安装 — 防止恶意模板自动执行
  • 结果分享只传 summary + artifacts 元数据,不传完整 LLM 对话历史 (隐私)
  • DID 签名验证发送方身份

测试计划: 单元 8 + 集成 4 + E2E 2 = 14 tests


F9: 学习进化 — Agent 从历史执行中学习优化策略 — 长期 (v5.2.3)

目标: 系统自动分析 Cowork 任务历史 (history.jsonl),识别高效执行模式,自动优化模板的系统提示词和工具选择。

架构设计:

history.jsonl (执行记录)
  → cowork-learning-engine.js
    → trajectory-store.js: 记录工具链
    → reflection-engine.js: 定期分析
    → skill-improver.js: 优化提示词
      → 更新 TASK_TEMPLATES[templateId].systemPromptExtension

实现文件与变更:

文件变更
src/lib/cowork-learning-engine.js新建CoworkLearningEngine 类:analyzeHistory(limit) 读取 JSONL → 按模板分组 → 统计成功率/平均 token/工具频率;suggestOptimization(templateId) 生成提示词优化建议;applyOptimization(templateId, patch) 更新模板
cowork-task-runner.js任务完成后调用 trajectory-store.appendToolCall() 记录工具链
src/lib/learning/trajectory-store.js增加 cowork 来源类型
src/lib/learning/reflection-engine.js增加 Cowork 模板的反思维度
action-protocol.js新增 handleCoworkLearning() — 查询学习建议、应用优化
web-panel/views/Cowork.vue管理面板增加"学习洞察"标签 — 展示模板使用统计、优化建议、一键应用

学习维度:

维度指标优化方向
成功率完成 vs 失败次数失败率高的模板 → 分析失败原因 → 补充提示词
Token 效率平均 token / 每次执行token 消耗高 → 精简提示词、减少迭代
工具频率最常用的工具 Top-5常用工具优先推荐给 Agent
用户反馈重试率、取消率重试率高 → 结果质量需改善
执行时间平均耗时耗时异常 → 检查是否有死循环模式

关键决策:

  • 复用已有的 trajectory-store + reflection-engine + skill-improver 三件套
  • 优化建议需人工确认 — 不自动修改模板提示词 (防止 prompt 漂移)
  • 学习数据仅本地存储 — 不上传到 EvoMap Hub (隐私)
  • 最小样本: 每个模板至少执行 10 次后才产生有意义的分析

测试计划: 单元 10 + 集成 4 + E2E 2 = 16 tests


总览

#功能阶段版本新文件数修改文件数预估测试数
F1Orchestrator 并行短期v5.0.3.10515
F2Debate 审查短期v5.0.3.20611
F3模板市场短期v5.0.3.31617
F4定时任务中期v5.1.11513
F5移动端入口中期v5.1.24210
F6MCP 集成中期v5.1.30511
F7工作流编排长期v5.2.12420
F8P2P 协作长期v5.2.21414
F9学习进化长期v5.2.31516
合计1042127

十一、未来演进(v0.46.0 之后)

制定日期: 2026-04-15 以下为 F1–F9 全部落地之后的新方向,均为本次尚未实现的真·未来项。 完整设计: 见 87-cowork-evolution-n1-n7.md(含每个 N 项的文件级变更表、测试计划、风险与 ADR)。

N1: Workflow 可视化编辑器(Web / Desktop)— 短期

问题: 当前 cowork workflow add 要求用户手写 JSON 定义 DAG,门槛偏高;Web 面板仅能 list/run。

目标: 在 packages/web-panel 新增 /cowork/workflow 页面,基于 Vue Flow 提供节点拖拽编辑、依赖连线、占位符提示、保存即下发 WS。

主要文件:

  • packages/web-panel/src/views/WorkflowEditor.vue(新建)
  • packages/cli/src/gateways/ws/action-protocol.js — 新增 handleWorkflowSave() / handleWorkflowRun()
  • packages/cli/src/gateways/ws/message-dispatcher.js — 新增 workflow-save / workflow-run

预估: 单元 8 + 集成 5 + E2E 3 = 16 tests。


N2: Learning 反馈闭环 — 中期

问题: F9 cowork-learning.js 只做只读分析(推荐/统计/失败归因),未把洞察回灌到模板。

目标: 在 learning 子树新增 suggest + apply 命令 — 基于 summarizeFailures 生成 systemPromptExtension patch 建议,经用户确认后写回用户模板(不覆盖内置模板)。

关键约束:

  • 只产出建议,不自动改 — 与 CLAUDE.md "no auto prompt drift" 原则一致
  • 每个模板需至少 ≥10 次历史调用才生成建议
  • patch 写入 user-templates/ 层(不碰 bundled)

预估: 单元 12 + 集成 4 = 16 tests。


N3: Workflow 条件分支与循环 — 中期

问题: 当前 DAG 是「单向无环 + 全步必跑」模型,不支持「if 上游 summary 含 X 则走 B,否则走 C」「对数组每项各跑一次」。

目标: 扩展 step 定义:

json
{ "id": "branch", "when": "${step.fetch.summary} contains 'error'", "message": "..." }
{ "id": "fanout", "forEach": "${step.list.items}", "message": "process ${item}" }

实现点: cowork-workflow.jsplanBatches 增加条件跳过、substitutePlaceholders 增加表达式求值(沙箱,仅允许点访问 / contains / length)。

预估: 单元 18 + 集成 6 = 24 tests。


N4: P2P 包签名升级(可选 DID)— 中期

问题: F8 cowork-share.js 当前用 canonical-JSON + SHA-256,仅防损坏不防伪造。

目标: buildPacket({ did, privateKey }) 可选注入 Ed25519 签名(复用 packages/cli/src/lib/did.js)。读包时若签名存在则验签并附带 signer.did 给导入者信任决策使用。未签名包继续向后兼容。

预估: 单元 15 + 集成 3 = 18 tests。


N5: Cron 秒级 + 非标准别名 — 短期

问题: 当前 parseCron 仅支持 5 字段 POSIX + dow 0/7 等价。不支持 @hourly / @daily 别名与秒字段。

目标: 增加 6 字段模式(首字段为秒)+ 5 个别名快捷语法,validateCron 对应扩展。

预估: 单元 10 tests。


N6: Cowork 可观测性 — 中期

问题: 任务失败仅通过 history.jsonl 的 summary 记录;长运行无统一看板。

目标: 新增 cowork observe 子命令 — 从 history / workflow-history / schedules 聚合出仪表盘数据,--serve 启动本地 HTTP 小页面(复用 web-ui-server.js 模式)展示:

  • 近 7 日任务数 / 成功率 / 平均 token
  • Top-5 失败模板 + 最常见 summary
  • 活跃 cron 任务与下一次触发时间

预估: 单元 8 + 集成 5 + E2E 3 = 16 tests。


N7: 模板市场 EvoMap 集成 — 长期

问题: F3 模板市场是本地层,cowork template publish 仅生成 JSON,不上链/不广播。

目标: 与 packages/cli/src/commands/evomap.js 打通,publish 可选上传到用户配置的 EvoMap Hub;search --hub 拉取社区模板列表。走既有 DID/签名/声誉模型。

预估: 单元 12 + 集成 6 = 18 tests。


总览(未来演进)

#功能阶段预估测试
N1Workflow 可视化编辑器短期16
N2Learning 反馈闭环中期16
N3Workflow 条件分支 / forEach中期24
N4P2P 包签名升级 (DID)中期18
N5Cron 秒级 + 别名短期10
N6Cowork 可观测性仪表盘中期16
N7模板市场 EvoMap 集成长期18
合计118

实施记录

2026-04-13 — 初版实现

已完成模块:

文件说明
后端模板packages/cli/src/lib/cowork-task-templates.js10 任务模板 + OPEN_SOURCE_FIRST_PROMPT + 自动安装规则
后端运行器packages/cli/src/lib/cowork-task-runner.jsrunCoworkTask() → SubAgentContext.create() → run()
WS 处理器packages/cli/src/gateways/ws/action-protocol.jshandleCoworkTask() — cowork:started / cowork:done
WS 路由packages/cli/src/gateways/ws/message-dispatcher.js"cowork-task" 路由注册
WS 服务器packages/cli/src/gateways/ws/ws-server.js_handleCoworkTask() 委托
前端页面packages/web-panel/src/views/Cowork.vue模板选择 + 消息展示 + 文件拖放
前端 Storepackages/web-panel/src/stores/cowork.jsexecute() + executeDirectWs() 双通道
前端路由packages/web-panel/src/router/index.js/cowork 路由
侧边栏packages/web-panel/src/components/AppLayout.vue"日常协作"菜单项

测试覆盖:

文件测试数类型
__tests__/unit/cowork-task-templates.test.js32单元
__tests__/unit/cowork-task-runner.test.js36单元
__tests__/unit/cowork-action-protocol.test.js16单元
__tests__/unit/cowork-session-extension.test.js5单元
__tests__/integration/cowork-task-workflow.test.js17集成
__tests__/e2e/cowork-task-e2e.test.js21E2E
合计127

用户文档: docs-site/docs/chainlesschain/web-cowork.md

2026-04-13 — Bug 修复: 系统提示词泄露到用户消息

问题: Cowork 页面执行任务时,AUTO_INSTALL_PROMPT (开源工具优先规则) 被拼入用户消息 fullMessage,导致:

  1. 蓝色聊天气泡中显示大段系统提示词文本,UI 非常不友好
  2. 模板指令作为 user content 发送,而非 system prompt

修复:

文件变更
后端会话网关ws-session-gateway.jscreateSession() 支持 options.systemPromptExtension 追加到系统提示
后端协议层session-protocol.jshandleSessionCreate() 透传 message.systemPromptExtension
前端 WSws.jscreateSession() 第三参数 options.systemPromptExtension
前端 Chatchat.jscreateSession() 透传 options
前端 Coworkcowork.jsexecute() 将模板提示词通过 systemPromptExtension 注入,用户消息保持干净

新增测试: cowork-session-extension.test.js (5 tests)

2026-04-14 — 10 项优化 (v0.45.81)

#优先级优化项变更摘要
1P0XSS 修复Cowork.vue 引入 DOMPurify 对 marked 输出做 sanitize
2P3dEmoji → Icon替换 🔧 为 <ToolOutlined /> 组件
3P2cisRunning 同步cowork.js 增加 watch(chatStore.isLoading) 重置 isRunning
4P3c文件路径验证cowork-task-runner.js 在启动前校验 files 是否存在
5P3bToken 统计cowork:done 增加 tokenCount;Cowork.vue 显示统计标签
6P1a实时进度SubAgentContext 增加 onProgress 回调;action-protocol 发送 cowork:progress
7P1b任务取消AbortController + cowork-cancel WS 消息;signal 透传到 SubAgentContext
8P2a模板去重后端新增 getTemplatesForUI() + cowork-templates WS 消息;前端改为 loadTemplates()
9P3a重试机制cowork.js 增加 lastRequest ref + retry() action;错误消息显示重试按钮
10P2b任务历史JSONL 持久化到 .chainlesschain/cowork/history.jsonl;cowork-history WS API;侧边栏历史面板

新增 WS 消息类型:

消息类型方向说明
cowork:progressServer → Client实时进度事件 (tool-executing 等)
cowork:cancelledServer → Client任务已取消确认
cowork-cancelClient → Server取消运行中的 cowork 任务
cowork-templatesClient → Server请求模板列表
cowork:templatesServer → Client返回 UI 模板数组
cowork-historyClient → Server请求任务历史
cowork:historyServer → Client返回 JSONL 历史条目

测试更新:

文件新测试数总测试数
cowork-task-templates.test.js+5 (getTemplatesForUI)32
cowork-task-runner.test.js+3 (history persistence)36
cowork-action-protocol.test.js+7 (cancel, signal, trackingId, progress, tokenCount)16
cowork-task-workflow.test.js+6 (cancel, progress, templates, history, persistence, tokenCount)17
cowork-task-e2e.test.js+10 (dispatcher routes, export verification)21
合计+31122 (84 unit + 17 integration + 21 E2E)

Bug Fix 2: Agent 无法执行网络请求 (v0.45.80)

问题: Cowork 页面选择"信息检索与调研"或"网络工具"模板时,Agent 无法执行 curl/wget 等网络命令,返回 "Network download commands are blocked by the coding-agent shell policy"。

根因: coding-agent-shell-policy.cjsnetwork-download 规则将 curl/wget/Invoke-WebRequest/iwr 硬性 DENY,无论会话上下文。

修复: 引入 shellPolicyOverrides 机制 — 特定模板可声明需要放行的 shell policy rule ID,在创建 session 时透传到 agentLoop,由 evaluateShellCommandPolicy 将匹配的 DENY 规则降级为 WARN (allowed)。

文件变更
Shell Policycoding-agent-shell-policy.cjsevaluateShellCommandPolicy() 新增 options.overrideRuleIds 参数
Agent Coreagent-core.jstoolContextexecuteToolInner 传递 shellPolicyOverrides
Agent Handlerws-agent-handler.jsloopOptions 传递 session.shellPolicyOverrides
Session Gatewayws-session-gateway.jssession 对象存储 shellPolicyOverrides
Session Protocolsession-protocol.js从 WS 消息解构并透传 shellPolicyOverrides
Templates (后端)cowork-task-templates.jsweb-researchnetwork-tools 声明 shellPolicyOverrides: ["network-download"]
Templates (前端)cowork.js store对应模板声明 shellPolicyOverridesexecute() 创建 session 时传递
WS Storews.js storecreateSession() 发送 shellPolicyOverrides 字段
Task Runnercowork-task-runner.js从模板读取 overrides 传给 subAgent.run(msg, loopOptions)

安全设计: 仅 web-researchnetwork-tools 两个模板声明 override,其他模板和普通 agent 会话仍受 DENY 保护。Override 只能降级为 WARN (不能绕过 REROUTE)。

新增/更新测试: shell-policy +5, templates +4, runner +3, session-extension +2 = 14 tests


2026-04-15 — Cowork Evolution v0.46.0(9 项演进特性)

本节汇总 v0.45.81 → v0.46.0 的 9 项 Cowork 演进(F1–F9,均为 CLI 层新模块或扩展)。

新增模块概览

特性模块CLI 入口测试
F1 Orchestrator 并行cowork-task-runner.js runCoworkTaskParallelcowork (parallel 模式)既有 runner 测试
F2 Debate 多视角评审cowork-task-runner.js runCoworkDebate + cowork/debate-review-cli.jscowork debate既有 runner 测试
F3 模板市场cowork-template-marketplace.jscowork template search|install|list|remove|publish17 单元
F4 定时调度cowork-cron.js + CoworkCronSchedulercowork cron list|add|remove|enable|disable|run31 单元
F5 Android 远程技能pc-cowork-daily.md / pc-cowork-workflow.md (REMOTE skills)Android /pc-cowork-daily / /pc-cowork-workflowAndroid SkillLoader 自动加载
F6 MCP 工具挂载cowork-mcp-tools.js + cowork-task-templates.js mcpServers模板声明式既有 runner 测试 + MCP plumbing
F7 Workflow DAGcowork-workflow.jscowork workflow list|show|add <file>|remove|run <id>22 单元
F8 P2P 共享cowork-share.js (canonical-JSON + SHA-256 包)cowork share export-template|export-result|import|verify22 单元
F9 学习引擎cowork-learning.jscowork learning stats|recommend|failures13 单元

关键设计决策

  • _deps 注入:所有新模块都导出可变 _deps 对象(fs/time/runner),遵循 cli-dev.md 规范,Vitest 测试可覆盖而不依赖 vi.mock
  • ESM/ESM 循环避免cowork-workflow.jscowork-cron.js 通过 _deps.runTask 接收 runner,CLI 入口在执行前注入,避免静态 import 环。
  • 持久化统一:所有新模块统一读写 .chainlesschain/cowork/workflows/user-templates/shared-results/workflow-history.jsonlschedules.jsonlhistory.jsonl),与既有 BackgroundTaskManager JSONL 模式对齐。
  • packet 格式:F8 使用 canonical JSON + SHA-256 而非完整签名,防数据损坏而非身份伪造;未来接入 DID 签名即可升级。
  • 推荐评分:F9 用 overlap × (0.5 + successRate/2) 保证新模板有机会被推荐(最低权重 0.5),避免冷启动陷阱。

测试计数(v0.46.0 新增)

文件测试数
cowork-learning.test.js13
cowork-workflow.test.js22
cowork-share.test.js22
合计57

既有 cowork 测试(template-marketplace 17 + cron 31 + task-runner 63)全部通过,累计 168 测试。

CLI 命令总览

cowork
├── debate <file>          (F2)
├── compare <prompt>       (F2)
├── analyze <path>
├── template               (F3)
│   ├── search [query]
│   ├── install <id>
│   ├── list
│   ├── remove <id>
│   └── publish
├── cron                   (F4)
│   ├── list / add / remove / enable / disable / run
├── learning               (F9)
│   ├── stats
│   ├── recommend <message...>
│   └── failures
├── workflow               (F7)
│   ├── list / show / add <file> / remove / run <id>
├── share                  (F8)
│   ├── export-template <id> --out <file>
│   ├── export-result <taskId> --out <file>
│   ├── import <file>
│   └── verify <file>
└── status

基于 MIT 许可发布