Commit 785aa93a authored by AI-甘富林's avatar AI-甘富林

docs(projects): add douyin xhs working notes

parent 3fe456f0
# 抖音 / 小红书云端 Zip 项目可插拔改造方案
## Summary
基于当前仓库事实,这条主链路已经成立:
1. 客户端初始化时调用 POST https://spb-bp1wv2oe0hvfvi98.supabase.opentrust.net/functions/v1/openclaw-employee-config
2. 从返回的 skills[].skill.download_url 发现 zip 项目包
3. ProjectBundleService 下载、解压、物化到本地 workspace/projects/<projectId>
4. ProjectStoreService 把项目写入本地 inventory
5. 专家页按 project 展示,进入项目后再使用该项目 skills
6. ProjectExecutionRouter 在 workspace-entry / skill / chat-fallback 之间路由
当前阻塞点不是“云端 zip 能不能下发”,而是“项目包要不要满足客户端现有项目契约”。
按你给的真实抖音包事实,后续小红书同结构时,推荐方案是:
- 两个项目包都补标准 project.json
- 客户端继续沿用现有 openclaw-employee-config -> zip bundle -> project isolation 主链路
- 客户端补少量校验和 UI/展示收口,不做“扫描 skills 自动反推整项目”的大改
- 最终目标是:新电脑安装客户端,初始化成功后自动拉项目包,本地物化后即可在专家页选项目并跑起来
## Key Changes
### 1. 云端协议继续沿用现状,不改接口形态
继续使用现有接口和字段,不新加 projects[]
- 接口:/functions/v1/openclaw-employee-config
- 载荷来源:skills[]
- zip 地址:skills[i].skill.download_url
- 一个 zip 对应一个 project
- 多项目通过多个 skills[] 项表达
服务端交付要求固定为:
- 抖音包和小红书包都从这个接口下发
- 同一项目升级时,保持稳定 projectId
- zip 变更时,保证 URL、etag、lastModified、content-length 或 configVersion 至少有一项能触发客户端重拉
- 不要求服务端生成本地运行态文件,运行态仍由客户端本地维护
### 2. 项目包交付契约改为“标准 project bundle”
后续抖音、小红书 zip 都按统一项目根结构交付:
<project-root>/
project.json
AGENTS.md
SOUL.md
USER.md
README.md
skills/
cron/ # 可选
memory/ # 可选,客户端也会补
output/ # 可选
当前你给的抖音包已满足大部分条件:
- 根目录就是项目根
- 有 skills/
- 有 AGENTS.md / SOUL.md / USER.md
- 缺的是 project.json
因此项目包侧最小改造就是:
- 抖音包补 project.json
- 小红书包补 project.json
- boundSkillIds 与真实 skills/<skillId> 子目录名一致
- defaultEntry.type 固定为 "workspace-entry"
推荐项目包模板约束:
- id 稳定,抖音固定 douyin,小红书固定 xhs
- name、platform、projectType、description 填全
- entries 至少包含一条 workspace-entry
- 不把真实 token、账号密钥、长效凭证打进 zip
- 所有可变运行态统一写到 memory/,避免 bundle 更新时丢失
### 3. 客户端主链路保留,但补 4 处必要改造
#### 3.1 project-bundle.ts
这里是本次最关键的改造点。
当前事实:
- resolveBundleMetadata() 在没有 project.json 时会自动用 zip 名推导 projectId/projectName
- stageProjectDirectory() 会在物化时自动写一个 project.json
- 所以今天“缺 project.json”不会彻底拦住安装,但会把项目识别退化成“按 zip 名猜”,这不适合长期可插拔交付
改造要求:
- 安装后显式校验项目根必须存在 project.json
- 根目录模式和 projects/<id>/ 模式都支持,但都必须最终拿到标准 project.json
- project.json 缺失时:
- bundle sync 标记为 error
- startup log 记录缺失原因
- 不把该 bundle 写入 ready project
- 保留现有 shared skills/cron 物化逻辑
- 保留现有 bundle replace / rollback / preserve local state 逻辑
这样可以保证以后“所有云端项目都按一个标准接入”,而不是靠客户端猜。
#### 3.2 project-store.ts
这里需要把“项目识别”和“项目技能隔离”收紧。
当前事实:
- syncBundleProject() 已支持按 project 写入 inventory
- listProjectSkills(projectId) 会按 boundSkillIds 过滤工作区 skills
- 但当前还会混入 curated generic skills,这和“进入项目后只看该项目自己的 skills”不完全一致
改造要求:
- syncBundleProject() 读取 bundle 物化后的 project.json,把项目级字段完整写入本地记录
- boundSkillIds 必须和实际 workspace/skills/<skillId> 交叉校验
- 若 boundSkillIds 声明了不存在 skill:
- 过滤掉无效项
- 写诊断日志
- 若过滤后为空,则项目标记为 error 或 not ready
- 增加一个明确策略:
- 专家项目页默认只展示本项目 boundSkillIds
- curated generic skills 不自动混入专家项目 skills 列表
- 如需保留通用技能,单独作为 home/global skills 展示,不算项目私有 skills
这是满足“抖音项目里只出现抖音技能,小红书里只出现小红书技能”的关键。
#### 3.3 project-execution-router.ts
当前这里已经基本满足要求。
当前事实:
- 若 project.json.defaultEntry.type === "workspace-entry",优先走 workspace-entry
- 没有 project.json 时,也会因为 AGENTS.md 命中 workspace marker
- 旧版 plugin marker 仍保留兼容
改造要求:
- 保持 workspace-entry 作为专家项目默认入口
- 保持 skill 显式选择时仍可走 skill
- 继续保留旧版 xhs plugin marker 兼容,作为迁移兜底
- 但对新标准 bundle,不再依赖 AGENTS.md 来“猜项目入口”,而是以 project.json 为准
- 若项目 defaultEntry 缺失或不合法:
- 给出明确诊断
- 不静默退化成普通 chat
#### 3.4 UI / IPC / 专家页
当前 UI 已有 projects、currentProjectId、setActive(projectId) 链路,改造重点是收口展示策略。
改造要求:
- 专家页一级列表显示 projects,不显示全局混合 skills
- 点击专家卡片后调用 projects.setActive(projectId)
- 进入项目后:
- 会话隔离在 project:<projectId>:<uuid>
- 技能面板只显示该项目 boundSkillIds
- 上下文只注入该项目的 AGENTS.md / SOUL.md / USER.md / README.md
- fresh install 初始化成功后:
- 首次云端 sync 完成即刷新专家页
- 如至少有一个 ready project,可自动把第一个项目设为 active,或保留显式选择页,但规则要固定
- 项目状态要可见:
- downloading
- syncing
- ready
- error
- 缺 project.json
- skill 缺失
- bundle 更新失败
### 4. 新电脑初始化必须打通的完整流程
目标不是“开发机能跑”,而是“新电脑安装客户端后初始化即可跑项目”。这条链必须定义成标准流程:
1. 安装客户端
2. 用户输入或绑定 employee api_key
3. Main 进程调用 openclaw-employee-config,action=init
4. 从返回的 skills[].skill.download_url 中识别 zip bundle
5. ProjectBundleService 下载并安装所有合法项目包
6. ProjectStoreService 建立本地 project inventory、active project、默认 session
7. 专家页显示抖音 / 小红书项目
8. 用户进入对应专家页发自然语言请求
9. 请求优先走该项目 workspace-entry
10. 项目在本地隔离工作区中执行
要把这条链在新电脑上稳定跑起来,还要补这些交付前约束:
- bundled runtime 必须覆盖项目依赖
- 如果抖音/小红书项目需要新 Python 依赖,不能只改 zip,必须同步扩展客户端 runtime
- 项目首次运行所需浏览器态、登录态、调试输出、缓存全部写入 memory/
- bundle 升级时保留 sessions.json、session-messages/、memory/
## Public Interfaces
需要锁定的公开契约只有这几项:
### 1. 云端返回契约
继续使用现有 openclaw-employee-config:
- skills[].skill.file_name
- skills[].skill.file_size
- skills[].skill.download_url
不新增 projects[]
### 2. 项目包契约
每个 zip 必须包含 project.json,至少包含:
- id
- name
- platform
- projectType
- description
- defaultEntry
- entries
- boundSkillIds
- ready
其中:
- defaultEntry.type = "workspace-entry"
- entries 至少包含一条 workspace-entry
### 3. 项目技能契约
skills/<skillId>/SKILL.md 继续只承担 skill 级职责:
- 展示名
- 描述
- 元数据
- skill 路由辅助信息
不承担项目级默认入口声明,不承担 project identity。
## Test Plan
必须覆盖这些场景,才能算“新电脑初始化后可插拔可运行”:
1. openclaw-employee-config 同时下发 douyin.zip 和 xhs.zip,客户端成功识别两个 bundle。
2. 两个 zip 都含标准 project.json 时,客户端在本地生成两个独立 project。
3. 专家页显示两个项目,切换项目只影响当前 active project,不串会话。
4. 进入 douyin 项目后,只显示 douyin 的 boundSkillIds,不混入 xhs skills,也不混入 curated generic skills。
5. 进入 xhs 项目后,只显示 xhs 的 boundSkillIds。
6. 在 douyin 项目内发送“生成一个苹果抖音视频文案”,默认命中 workspace-entry。
7. 在 xhs 项目内发送“小红书笔记文案”,默认命中 workspace-entry。
8. zip 缺少 project.json 时,bundle sync 明确报错,专家页不显示为 ready。
9. boundSkillIds 写错时,客户端记录诊断并标记项目异常,不崩溃。
10. bundle 更新后,项目目录被替换,但 memory/、sessions.json、session-messages/ 保留。
11. 云端配置移除 douyin.zip 时,本地 douyin project 和共享资源被清理,不影响 xhs。
12. fresh install + 真正 employee key + 真正云端接口下,初始化完成后专家页可直接使用项目。
## Assumptions
- 后续抖音和小红书 zip 都保持与你当前抖音包相同的根目录形态。
- 两个项目都按“一包一个项目”交付,不把多个项目塞进一个 zip。
- 你接受“项目识别靠 project.json,项目内能力靠 skills/*/SKILL.md”这套双层契约。
- 这次不做“客户端扫描全部 skills 自动反推项目”的重构。
- 若项目依赖超出当前 bundled runtime,runtime 扩容是单独任务,不纳入 zip 插件化本身
\ No newline at end of file
# 0410 进度
Date: 2026-04-10
Last Updated: 2026-04-13
Status: in-progress
## 今日最终判断
到 2026-04-10 这一步,项目状态已经不是“方案设计中”,而是:
- 客户端安装链路已基本可用
- XHS / Douyin 项目 bundle 接入客户端主链已基本打通
- fresh install 级别的 bundled runtime 验收今天已重新通过
- Douyin 已有新的完整成功样例,且又补出一条更短的单镜头成功样例
- Douyin 主流程里“视频成功但根状态误写失败”的 coordinator 收尾异常已修
- 客户端到专家项目的附件链路已落第一批最小闭环代码
- 但还不能下“新电脑安装客户端后,两个项目从配置接口拉 zip 就都已正式验收可以直接跑”的最终结论
最准确的口径是:
- “接入链路已通”
- “Douyin 本地真实工作流已跑通两条新样例”
- “XHS 有较强的 fresh-like 旧证据”
- “但客户端专家附件链路虽然已补第一批代码,仍未完成 smoke 和真实端到端验收”
- “但安装版客户端 + 配置接口拉 zip + 两项目都真实自动化跑完”的统一最终验收还没完全补齐
## 已完成
### 1. Runtime 依赖和探测已落地
相关文件:
- `build/runtime/python/requirements.in`
- `build/runtime/python/runtime-requirements.lock.txt`
- `packages/runtime-manager/src/index.ts`
已纳入并锁定:
- `greenlet`
- `playwright`
- `edge-tts`
- `python-dotenv`
- `pillow`
- `imageio-ffmpeg`
runtime 探测已从简单存在性检查升级为真实导入探测,能明确确认:
- Python 可执行可用
- `greenlet` 可导入
- `playwright.async_api` 可导入
- `edge_tts` 可导入
### 2. Bundle 契约已明显收紧
相关文件:
- `apps/desktop/src/main/services/project-bundle.ts`
当前 bundle 安装已从“猜测式安装”转向“强契约安装”:
- bundle 内必须有标准 `project.json`
- 缺少 `id` / `name` 会直接报错
- 已开始以 `project.json` 中声明的 `boundSkillIds` 作为项目绑定来源
### 3. 项目级 skills 收口已落地
相关文件:
- `apps/desktop/src/main/services/project-store.ts`
当前行为已调整为:
- 非 home 项目不再自动混入 curated generic skills
- `boundSkillIds` 会和实际 materialize 出来的项目 skill 目录交叉校验
- skill 缺失会进入诊断,并影响项目 ready 状态
### 4. XHS / Douyin 项目标准化已基本完成
相关文件:
- `workspace/xhs/project.json`
- `workspace/xhs/workspace_entry.py`
- `workspace/douyin/project.json`
- `workspace/douyin/workspace_entry.py`
两边都已经具备:
- 标准 `project.json`
- `workspace-entry` 自然语言入口
- `boundSkillIds`
- `bundlePackaging`
- 运行态写入 `memory/` 目录的路径约束
### 5. 客户端 fresh install runtime 验收今天已重新通过
这是今天最关键的新进展之一。
已完成:
- 重新 materialize runtime
- 重新打包 installer
- 重新跑 installer smoke
最新 installer:
- `dist/installer/QianjiangClaw-Setup-0.1.0.exe`
- 时间:2026-04-10 16:11:58
最新 installer smoke:
- `.tmp/installer-smoke/20260410-162021/installer-smoke-result.json`
- 结果:`ok=true`
已确认通过:
- bundled runtime 正常带入安装包
- installed app smoke 正常完成
- `pythonImportProbe`
- `greenletImportProbe`
- `playwrightAsyncImportProbe`
- `edgeTtsImportProbe`
说明 fresh install 下客户端 runtime 本身已经不再是主要阻塞项。
### 6. installer smoke 自身的假失败点已修掉
相关文件:
- `build/scripts/installer-smoke.ps1`
原先这里用 `python -c` 执行多行 probe,PowerShell 会破坏内层引号,导致假的 Python 语法错误。
现在已改为:
- 写临时 `.py` 文件
- 再调用 packaged Python 执行
- 执行后删除临时文件
### 7. XHS / Douyin 项目接入客户端主链已基本打通
当前已经有明确证据证明,客户端侧以下链路是通的:
- employee key / runtime cloud config fetch
- zip bundle sync
- 项目在客户端出现
- 专家页项目命中
- 会话绑定到 `project:xhs:*` / `project:douyin:*`
- `workspace-entry` 被命中
相关证据:
- `.tmp/xhs-expert-cloud-bundle-smoke/result.json`
- `.tmp/douyin-expert-cloud-bundle-smoke/result.json`
当前可以明确说:
- XHS / Douyin 的“项目接入客户端链路”是基本打通的
- 但这两条 smoke 仍然属于“启动验证”,不是“真实结果验收”
原因是:
- `build/scripts/xhs-expert-cloud-bundle-smoke.ps1`
- `build/scripts/douyin-expert-cloud-bundle-smoke.ps1`
- `build/scripts/electron-smoke.ps1`
目前都允许 `QJCLAW_SMOKE_ACCEPT_WORKSPACE_LAUNCH=1`,所以通过的含义更接近:
- 项目命中成功
- `workspace-entry` 启动成功
而不是:
- 项目真实自动化完整执行并产出最终结果
### 8. Douyin 旧失败点已定位并修掉
旧失败点已经明确不是“抖音项目包路由失败”,而是 Douyin 项目内部工作流问题。
已确认并修复:
- Seedance 请求里单独传 `reference_audio` 会触发 Ark 报错
- 错误:`reference_audio cannot be the only reference input`
- `run_seedance.py` 已加兜底
- 在缺少图/视频参考时,不再单独发送 `reference_audio`
相关文件:
- `workspace/douyin/skills/seedance-2-0-video-generator/scripts/run_seedance.py`
### 9. Douyin 主流程 placeholder 音频误传已修
今天还额外确认并修掉了一个真正影响成片的主流程问题:
- `seedance-silent*.wav` 此前会被当成 `main_audio` 传到 split
- 后续 `ffmpeg -shortest` 会把成片错误截短
当前已改为:
- 不再把 `seedance-silent*.wav` 当成主音频复用
- 不再把它写入新的 `video_request` / `project_inputs.main_audio`
- split 层也做了二次防呆
相关文件:
- `workspace/douyin/skills/douyin-master/scripts/coordinator.py`
- `workspace/douyin/skills/douyin-seedance-split/scripts/run_pipeline.py`
### 10. Douyin 已跑通新的完整验收样例:卖苹果宣传短视频
今天新增跑通了一条新的 Douyin 实战样例:
- 项目目录:`workspace/douyin/memory/output/卖苹果宣传短视频`
- 目标:`我要卖苹果,帮做一个抖音宣传视频,三个镜头就行,短一点`
- 结果:完整主流程成功,项目根状态成功,最终成片成功
关键结果:
- `workflow_summary.json` 已是 `stage=video_generated`
- `video_generation_status.json` 已是 `status=success`
- `latest_seedance_split_summary.json``segment_count=3`
- 最终视频:
- `workspace/douyin/memory/output/卖苹果宣传短视频/latest_seedance_split.mp4`
- `workspace/douyin/memory/output/卖苹果宣传短视频/seedance-split-runs/20260410-192611/final_video.mp4`
这说明到今天这一步,Douyin 不再只是“能启动项目”“能返回分镜”,而是已经至少有一条完整的新样例做到:
- 预览生成成功
- 三镜头拆分成功
- Seedance 分镜生成成功
- 本地拼接成功
- TTS 旁白 mux 成功
- 项目根状态回写成功
### 11. Douyin 又补通一条更短的单镜头验收样例:内裤推荐短视频
`卖苹果宣传短视频` 之外,今天又追加跑通了一条更短的 Douyin 样例:
- 项目目录:`workspace/douyin/memory/output/内裤推荐短视频`
- 目标:更短、更小、分镜更少,优先验证抖音主流程根状态成功回写
- 结果:单镜头成功、最终视频成功、项目根状态成功
关键结果:
- `workflow_summary.json` 已是 `stage=video_generated`
- `video_generation_status.json` 已是 `status=success`
- `latest_seedance_split_summary.json``segment_count=1`
- 最终时长约 `4.34s`
- 最终视频:
- `workspace/douyin/memory/output/内裤推荐短视频/latest_seedance_split.mp4`
- `workspace/douyin/memory/output/内裤推荐短视频/seedance-split-runs/20260410-211028/final_video.mp4`
这条样例的价值在于,它不是三镜头长样例,而是更接近后续“快速生成、短视频、小分镜”的实际使用场景。
### 12. Douyin coordinator 收尾假失败点已修
今天还顺手修掉了一个会影响最终状态口径的收尾问题:
- 之前出现过“Seedance 视频已经生成成功,但项目根状态被写成 error”
- 根因不是视频生成失败,而是 coordinator 收尾阶段日志输出触发 `[Errno 22] Invalid argument`
- 现在日志输出失败不会再把本来成功的工作流误打成失败
相关文件:
- `workspace/douyin/skills/douyin-master/scripts/coordinator.py`
### 13. XHS 有较强的 fresh-like 旧证据,但今天未按最新标准重跑
已有一份较强的旧证据表明,XHS 不只是“能命中项目”,而是在 fresh-like 路径下实际跑到项目产物:
- `.tmp/real-xhs-fresh-smoke-3/result.json`
- `.tmp/real-xhs-fresh-smoke-3/result.json.trace.log`
- `.tmp/real-xhs-fresh-smoke-3/user-data/projects/xhs`
该结果能证明:
- 安装 / 初始化 / bundle 同步 / 项目进入 / 流式执行都跑到了较深层
- `user-data/projects/xhs` 下确实出现了项目目录、技能、会话、memory、profile 和产物文件
但要注意:
- 这份证据时间是 2026-04-08
- 不是今天 2026-04-10 按最新 runtime / bundle / smoke 口径重新做的同轮验收
### 14. 客户端专家附件链路第一批最小闭环代码已落地
这次已经把“客户端 experts 页单图上传 -> 主进程项目内落盘 -> workspace-entry 执行层透传 -> Douyin/XHS Python 入口感知附件”的第一批最小闭环补进代码。
已完成:
- `shared-types` 已新增 `ChatAttachment` / `ProjectResolvedAttachment`
- `DesktopApi.chat.sendPrompt()` / `streamPrompt()` 已支持可选 `attachments`
- 主进程 `ipc.ts` 已支持把图片复制到当前项目 `inputs/images/main/`
- 附件已强制要求走 `workspace-entry`,不再允许图片挂到普通 skill fallback
- `project-workspace-executor` 已通过执行输入和环境变量继续透传附件
- experts 页已补单图选择、展示、移除、发送
- Douyin `workspace_entry.py` 已能读取主图,并在数字人场景下把图传给 coordinator
- XHS `workspace_entry.py` 已能感知附件进入项目上下文
相关文件:
- `packages/shared-types/src/index.ts`
- `apps/desktop/src/preload/index.ts`
- `apps/desktop/src/main/ipc.ts`
- `apps/desktop/src/main/services/project-workspace-executor.ts`
- `apps/desktop/src/main/project-workspace-agent-runner.ts`
- `apps/ui/src/App.tsx`
- `apps/ui/src/styles.css`
- `workspace/douyin/workspace_entry.py`
- `workspace/xhs/workspace_entry.py`
本轮已完成基础校验:
- `corepack pnpm typecheck` 通过
- `python -m py_compile workspace/douyin/workspace_entry.py workspace/xhs/workspace_entry.py` 通过
## 尚未完成
### 1. 还不能下“新电脑装完后两个项目都能直接跑起来并正式验收通过”的最终结论
这是当前最重要的边界。
基于目前事实,更准确的结论是:
- 客户端安装链路已通
- 项目 bundle 接入链路已通
- Douyin 已有新的完整成功样例
- XHS 有较强的 fresh-like 旧证据
但还不能等同于:
- 一台全新电脑安装客户端
- 用正式配置接口拉取当前两个 zip 项目包
- 两个项目都在安装版客户端里完整跑完真实自动化
- 并且已经完成统一最终验收
原因:
- 今天的 XHS / Douyin `expert cloud bundle smoke` 仍是“启动验证”性质
- Douyin 的完整成功样例是本地工作区真实流程成功,不是安装版客户端 cloud-bundle smoke 的最终结果验收
- XHS 的 fresh-like 强证据来自 2026-04-08,不是今天同轮复验
- 当前 smoke 使用的是本地 smoke cloud config 服务,不是计划文档中写的正式线上 Supabase 地址
### 2. `我们家的苹果` 旧案例还没有按完整主流程重新收口
`我们家的苹果` 这条线此前已经验证过:
- Seedance 分镜接口本身可以成功返回视频
- 参数问题 `reference_audio cannot be the only reference input` 已修
- `ffmpeg` 缺失问题已补
- placeholder 音频误传问题已修
但这条老案例没有再完整重跑一遍主流程去更新它自己的项目根状态文件,所以它仍然不是今天最后的验收样例。
### 3. Experts smoke 仍然偏“启动验证”
`xhs``douyin` 的 experts smoke 现在仍用了:
- `QJCLAW_SMOKE_ACCEPT_WORKSPACE_LAUNCH=1`
这意味着它更偏向验证:
- 项目是否命中
- `workspace-entry` 是否启动
- 项目会话是否正确绑定
而不是验证:
- 项目自动化流程是否真正执行完成
- 最终文件是否真正产出
### 4. 客户端专家附件链路已落第一批代码,但还没完成验收闭环
这一点是当前最新边界。
当前已经做到:
- experts 页可选 1 张本地图片
- `DesktopApi.chat.sendPrompt()` / `streamPrompt()` 已支持附件
- IPC 层已支持附件协议
- 主进程会把图片复制到当前项目 `inputs/images/main/`
- `project-workspace-executor` / `project-workspace-agent-runner` 已能透传附件
- Douyin / XHS `workspace_entry.py` 已能读取附件上下文
但还没有完成:
- experts smoke 升级到“验证附件真实进入项目执行层”
- 客户端带图实跑一轮 Douyin 数字人端到端验收
- XHS 对附件的业务语义消化仍未继续展开
所以当前不能说“附件链路已经验收完毕”,只能说“附件链路第一批最小闭环代码已经落地”。
专项计划仍见:
- `docs/douyin-xhs-插入/2026-04-10-客户端抖音专家附件打通计划.md`
### 5. Day 1 契约收口仍不算完全结束
当前主要收紧的是:
- bundle 侧
- project store 侧
- runtime / smoke 侧
但计划里点名的这些文件,这次没有看到明确收口:
- `apps/desktop/src/main/services/cloud-api.ts`
- `apps/desktop/src/main/services/project-workspace-executor.ts`
所以 Day 1 的“配置契约冻结”还不能算 100% 完成。
### 6. XHS / Douyin 源目录收尾清理还没做完
虽然运行态都在往 `memory/` 迁,但项目根目录里仍然有一些历史运行目录和旧说明没有完全清掉。
这会影响:
- bundle 源目录整洁度
- 交接理解成本
- 后续排错时对“哪些是源文件、哪些是运行产物”的判断
## 下一步建议
按优先级,下一步建议直接做下面几件事:
1. 先把 experts smoke 从“接受 workspace launch”收紧到“要求附件真实进入项目执行层”
2. 直接用客户端做一轮“上传人物图 -> Douyin expert -> 数字人”真实端到端验收
3. 用最新 runtime / bundle / smoke 标准,重新做一轮 XHS fresh-like 验收
4. 再完整复跑一次 `我们家的苹果`,把老案例的项目根状态也更新到成功态
5. 继续补 Day 1 的 `cloud-api.ts` / `project-workspace-executor.ts` 契约收口
6. 清理 `workspace/xhs``workspace/douyin` 根目录中的历史运行产物与旧说明
## 当前阶段判断
到 2026-04-10 这一步,项目整体进度可以这样判断:
- 基础运行时、bundle 契约、项目隔离、workspace-entry 已经进入可用阶段
- fresh install runtime 验收今天已经补齐,属于实质性推进
- XHS / Douyin 接入客户端主链已基本打通
- Douyin 已经有两条新的真实出片成功样例
- 客户端专家附件链路第一批最小闭环代码已落地,并完成基础类型/语法校验
- XHS 有较强的 fresh-like 旧证据
- 当前最大剩余风险已经从“客户端素材输入完全未打通”转成“附件链路 smoke 与真实端到端验收还没补完 + 统一最终验收还没完全补完”
一句话结论:
当前已经完成“能安装、能识别项目、能进入项目、能启动项目运行时,而且 Douyin 已有两条新的真实出片成功样例”,并且客户端专家附件链路第一批最小闭环代码也已经落地;但还没有完成“新电脑安装客户端后,XHS 和 Douyin 从配置接口拉 zip 就都已正式验收可直接跑”的最终封口。当前最明确的新阻塞点,已经变成“附件链路 smoke 和真实端到端验收还没补完”。
补充说明:
2026-04-13 基于当前仓库代码与产物的完成度盘点,见 `docs/douyin-xhs-插入/2026-04-13-代码事实完成度盘点.md`
## 2026-04-13 补充
今天新增的关键结论:
- Douyin / XHS 的附件 smoke 已经从“只验证 `workspace-entry` 启动”收紧到“验证附件真实进入项目执行层”。
- Douyin 已补齐一条带附件的真实 live-run 验收,说明附件不只是落盘,而是已经进入真实业务链路。
- XHS 的卡点已经缩小到“项目脚本与桌面运行时配置不兼容”,不是入口没进,也不是附件没进。
- 后续模型配置方向已经明确:长期不再让各项目直接硬编码 `qwen``xhsImage``volces` 这类 provider 名,而是逐步改成由客户端统一配置文案 / 视觉分析 / 生图 / 视频模型,再由执行器注入给项目。
详细盘点见:
- `docs/douyin-xhs-插入/2026-04-13-代码事实完成度盘点.md`
## 2026-04-13 XHS live-run 补充
- `workspace/xhs/scripts/qwen.py` 已补齐对桌面端 managed config 的兼容,不再只认项目内 `models.providers.qwen`,而是优先从执行器注入的 `OPENCLAW_CONFIG_PATH` 解析当前可用文本模型。
- `workspace/xhs/scripts/run.py` 已补齐两类兼容:
- 参考图分析阶段会先判断当前模型是否支持图片输入;若不支持,则退化为纯文本分析,避免把图片硬塞给 `openclaw-cloud/gpt-5.4-mini` 这类文本模型。
- 生图阶段不再把 `xhsImage` 当成唯一前提;当客户端当前 managed config 没有可用生图 provider 时,会把项目主图/附件图复制到 `memory/generated_images` 作为兜底产物,保证桌面端项目链路能闭环。
- 2026-04-13 已重新执行:
- `build/scripts/xhs-expert-live-run.ps1 -SkipMaterializeRuntime -SmokePort 4322 -BaseOutputDir D:\qjclaw\.tmp\xhs-expert-live-run-4322`
- 本次结果已闭环:
- `xhs_last_note.json` 已生成。
- `memory/generated_images` 已生成图片文件。
- `workspaceAttachmentPath` 存在,说明附件已进入项目执行层。
- `xhs_profile` 存在,说明项目脚本已实际运行。
- 需要明确区分的边界:
- 这次 XHS live-run 成功,证明的是“桌面端 managed config + 项目执行器 + XHS 项目脚本”的兼容链路已经打通。
- 这次生成出来的图片文件是附件兜底复用产物 `xhs_attachment_*.png`,不代表“客户端统一生图模型配置”已经完成。
# 抖音 / 小红书项目包插件化接入方案
Status: implementation-ready
本文是对当前仓库实现和真实项目包现状的落地说明,目标是把抖音、小红书这类云端 zip 项目接入为:
1. 专家页先选项目
2. 进入项目后只显示该项目自己的 skills
3. 会话、上下文、执行入口都保持项目隔离
4. 默认走项目级 `workspace-entry`
本文是对通用规范 [docs/remote-project-bundle-spec.zh-CN.md](D:\qjclaw\docs\remote-project-bundle-spec.zh-CN.md) 的补充,重点回答当前抖音包这种结构是否需要改、最小要改什么、客户端要怎么配合。
## 1. 当前事实
### 1.1 客户端当前已经具备的能力
当前仓库已经实现了这些主链路:
- `ProjectBundleService` 可以把云端 zip 下载、解压、物化到本地项目工作区
- `ProjectStoreService` 可以维护 `projects/<projectId>`、active project、project sessions、bound skills
- `ProjectExecutionRouter` 可以在 `workspace-entry``skill``chat-fallback` 之间路由
- `ProjectContextService` 会把当前项目的 `SOUL.md``USER.md``README.md`、bound skills 注入隔离上下文
- UI 已经有 `projects``currentProjectId``skills` 这些项目级展示能力
也就是说,客户端架构本身已经是“项目优先”,不是“全局 skills 池优先”。
### 1.2 真实抖音包现状
真实目录:
`D:\微信缓存\xwechat_files\wxid_wo77jy2n4p5q21_3789\msg\file\2026-04\douyin`
已确认的结构事实:
- 根目录就是一个完整项目根,不是单 skill 包
- 根目录存在 `skills/`
- 根目录存在 `AGENTS.md`
- 根目录存在 `SOUL.md`
- 根目录存在 `USER.md`
- 根目录存在 `openclaw.json`
- 根目录不存在 `project.json`
- 根目录不存在旧版 `plugin/openclaw.plugin.json`
- `skills/` 下已经有成组的 Douyin skills,例如:
- `douyin-master`
- `douyin-writer`
- `douyin-visual`
- `douyin-publisher`
- `douyin-seedance-split`
- `jimeng-omnihuman`
- `seedance-2-0-video-generator`
- `seedream-image-generator`
这说明该包已经具备“项目内容”和“项目内 skills”,缺的不是技能内容,而是客户端识别项目所需的最小项目清单。
### 1.3 小红书后续约束
后续小红书项目也按与当前抖音包相同的结构交付。
因此本方案要求:
- 抖音包和小红书包都采用相同的项目根组织方式
- 两个包都通过各自的 `project.json` 声明项目身份和默认入口
- 不要求客户端从 `SKILL.md` 反推整个项目
## 2. 结论
基于当前代码现状,两个项目包的最小改动是:
- 抖音包补一个极简 `project.json`
- 小红书包补一个极简 `project.json`
除此之外:
- `skills/` 目录结构可以先不改
- `SKILL.md` 顶部元数据可以继续保留,不需要改成项目级配置来源
- `AGENTS.md``SOUL.md``USER.md` 可以继续作为项目上下文文件存在
不推荐的方案:
- 不推荐只靠扫描 `skills/*/SKILL.md` 顶部 metadata 去推断整个项目
- 不推荐把“项目识别”和“skill 识别”混成一层
- 不推荐让客户端为当前两个包额外做复杂的 `openclaw.json` 兼容推断作为主路径
原因很直接:
- 当前客户端主链路已经围绕 `project.json` 工作
- skill frontmatter 目前只适合做 skill 展示和 skill 路由,不适合承担项目入口声明
- 补一个 `project.json` 的成本远低于补一整套客户端兼容推断逻辑
## 3. 项目包交付约定
### 3.1 一包一项目
每个 zip 只承载一个项目:
- `douyin.zip` 对应 `douyin`
- `xhs.zip` 对应 `xhs`
客户端继续按当前实现处理:
- 云端配置返回多个 zip 下载项
- 客户端下载并解压每个 zip
- 每个 zip 物化成一个独立 project
### 3.2 根目录约定
zip 解压后,根目录直接是项目根。
不要求再额外包一层无意义目录。
推荐最小结构:
```text
<project-root>/
project.json
AGENTS.md
SOUL.md
USER.md
README.md
skills/
output/
```
说明:
- `README.md` 强烈建议有,但不是本次唯一阻塞项
- `output/` 是否存在由项目自身决定,不影响客户端识别
### 3.3 `project.json` 的职责
`project.json` 在本方案里只承担项目级声明:
- 稳定项目 ID
- 专家页展示基础信息
- 项目平台
- 默认执行入口
- 项目绑定的 skills
它不负责:
- 描述每个 skill 的详细说明
- 取代 `SKILL.md`
- 取代 `AGENTS.md` / `SOUL.md` / `USER.md`
## 4. 项目包模板
### 4.1 抖音 `project.json`
放在抖音 zip 根目录:
```json
{
"id": "douyin",
"name": "douyin",
"platform": "douyin",
"projectType": "automation-project",
"description": "抖音视频文案与视频生成专家",
"version": "2026-04",
"defaultEntry": {
"id": "workspace-entry",
"type": "workspace-entry",
"requiresSkills": [],
"capabilities": [
"video-script",
"storyboard",
"video-generation",
"publish"
],
"intentAliases": [
"抖音",
"抖音视频",
"视频文案",
"分镜",
"口播视频",
"数字人视频",
"生成视频"
]
},
"entries": [
{
"id": "workspace-entry",
"type": "workspace-entry",
"requiresSkills": [],
"capabilities": [
"video-script",
"storyboard",
"video-generation",
"publish"
],
"intentAliases": [
"抖音",
"抖音视频",
"视频文案",
"分镜",
"口播视频",
"数字人视频",
"生成视频"
]
}
],
"boundSkillIds": [
"douyin-intake-planner",
"douyin-master",
"douyin-publisher",
"douyin-seedance-split",
"douyin-visual",
"douyin-writer",
"jimeng-omnihuman",
"seedance-2-0-video-generator",
"seedream-image-generator"
],
"ready": true
}
```
### 4.2 小红书 `project.json`
放在小红书 zip 根目录:
```json
{
"id": "xhs",
"name": "xhs",
"platform": "xiaohongshu",
"projectType": "automation-project",
"description": "小红书内容生成与发布专家",
"version": "2026-04",
"defaultEntry": {
"id": "workspace-entry",
"type": "workspace-entry",
"requiresSkills": [],
"capabilities": [
"topic-selection",
"copywriting",
"image-generation",
"publish"
],
"intentAliases": [
"小红书",
"笔记",
"种草文案",
"发笔记",
"封面图",
"生成配图"
]
},
"entries": [
{
"id": "workspace-entry",
"type": "workspace-entry",
"requiresSkills": [],
"capabilities": [
"topic-selection",
"copywriting",
"image-generation",
"publish"
],
"intentAliases": [
"小红书",
"笔记",
"种草文案",
"发笔记",
"封面图",
"生成配图"
]
}
],
"boundSkillIds": [
"xhs",
"xhs-pipeline"
],
"ready": true
}
```
### 4.3 模板约束
两个项目包都必须满足:
- `id` 稳定且不可漂移
- `boundSkillIds` 必须与包内 `skills/<skillId>` 目录名一致
- `defaultEntry.type` 固定为 `"workspace-entry"`
- `entries` 至少显式声明一条 `workspace-entry`
- 不把真实用户密钥、长期 token、生产私密凭证固化进 zip 包
## 5. 客户端改造方案
### 5.1 主链路保持不变
本次不需要推翻现有项目隔离架构。
客户端继续沿用当前实现:
1. 云端配置返回多个 zip
2. `ProjectBundleService` 下载并解压 zip
3. 每个 zip 物化到独立 `projects/<projectId>`
4. `ProjectStoreService` 把项目写入本地 inventory
5. 专家页按 project 展示
6. 进入项目后按当前 active project 读取该项目的 skills、sessions、context
### 5.2 `project-bundle.ts`
保持当前 bundle 同步逻辑,补两点明确约束:
- 安装后校验项目根必须存在 `project.json`
- 若缺失,给出明确错误,而不是静默降级
推荐行为:
- zip 缺少 `project.json` 时,bundle sync 标记为 error
- 错误内容包含 zip 文件名和项目根路径
不建议在这里新增“扫描 `openclaw.json` 自动生成项目”的主路径逻辑。
这类兼容逻辑只应作为临时兜底,不应成为标准交付方式。
### 5.3 `project-store.ts`
这里是本次最值得补强的小改造点。
建议增加:
- `boundSkillIds` 与实际 `skills/` 子目录交叉校验
-`boundSkillIds` 中有不存在的 skill,则:
- 从最终项目 skill 列表中过滤掉
- 记录日志
- 不让整个项目失效
建议保持:
- `listProjectSkills(projectId)` 只返回当前项目绑定的 skills
- session 仍保持 `project:<projectId>:<uuid>` 格式
### 5.4 `project-execution-router.ts`
这里不需要大改。
当前路由规则继续成立:
- 未显式选 skill 时,优先走 `workspace-entry`
- 发布/自动执行类请求,优先走项目级入口
- 只有项目内部需要精确 skill 分流时,才交给 skill router
这和抖音 / 小红书两个项目包的定位是一致的:
- 一级入口是项目
- skill 是项目内能力,不是项目本身
### 5.5 UI / 专家页
UI 也不需要推翻,只需要明确展示层次:
- 专家页展示 project 列表,不展示全局混合 skill 列表
- 点击项目卡片后切换 active project
- 进入项目后,只显示当前项目的 skills
- 当前项目的 sessions 也只属于当前 project
需要坚持的交互约束:
- 抖音项目不显示小红书 skills
- 小红书项目不显示抖音 skills
- 不允许跨项目复用 session skill 绑定
## 6. 为什么不走“只识别 skills 就够了”
“只识别各自 `skills/` 目录就可以跑起来”这句话只对一半:
- 对“项目内 skill 展示和 skill 路由”成立
- 对“项目本身如何被专家页识别、如何确定默认入口”不成立
当前代码里:
- project 识别靠 `project.json` 和项目级元数据
- skill 识别靠 `skills/*/SKILL.md`
这两层不能混成一层。
如果只靠 `SKILL.md` 反推项目,客户端需要新增:
- 从多个 skill 中推断项目 ID
- 从多个 skill 中推断默认入口
- 处理主 skill / 辅助 skill / 通用 skill 歧义
- 处理 skill 缺失时项目是否仍然可见
这比每个包补一个 `project.json` 明显更复杂,也更不稳定。
## 7. 验收标准
至少完成以下验证:
1. 云端配置同时下发 `douyin.zip``xhs.zip`
2. 客户端本地出现两个独立项目
3. 专家页出现两个项目卡片
4. 选中 `douyin` 后,只能看到 douyin skills
5. 选中 `xhs` 后,只能看到 xhs skills
6.`douyin` 项目内发“生成一个苹果抖音视频文案”,默认走 `workspace-entry`
7.`xhs` 项目内发“小红书笔记文案”,默认走 `workspace-entry`
8. 切换项目不会污染对方的 session skill 绑定
9. `boundSkillIds` 配错时,客户端给出可诊断错误,不崩
10. 移除某个 zip 后,对应项目能被清理,另一个项目不受影响
## 8. 推荐实施顺序
### 第一步:项目包侧
先做最小包改动:
- 给抖音包补 `project.json`
- 给小红书包补 `project.json`
- 校对 `boundSkillIds`
### 第二步:客户端侧
补小幅硬化:
- `project-bundle.ts` 增加 `project.json` 缺失校验
- `project-store.ts` 增加 `boundSkillIds` 与实际目录交叉校验
- UI 确认专家页使用 project 维度展示,不混显示全局 skills
### 第三步:联调验收
用真实云端配置跑完整链路:
- cloud config
- zip sync
- 专家页选项目
- 进入项目后发送自然语言
- 命中 `workspace-entry`
## 9. 最终决策
对当前这两个项目包,标准交付方式定为:
- 一包一项目
- 根目录保留现有结构
- 各自补一个极简 `project.json`
- 客户端继续沿用现有项目隔离架构
本期不把“只靠 `skills/*/SKILL.md` metadata 自动反推整个项目”作为主目标。
# 客户端抖音专家附件打通计划
Status: proposed
Date: 2026-04-10
## 1. 背景
当前客户端到 Douyin expert 的主链路,已经基本具备:
1. 专家页选择 `douyin` 项目
2. 会话绑定到 `project:douyin:*`
3. 默认命中项目 `workspace-entry`
4. 启动项目级执行链路
但这条链路目前仍然基本是“纯文本对话链路”。
对 Douyin 项目来说,这会直接卡住数字人能力,也会限制纯画面路线里的引用素材输入。
## 2. 当前代码事实
### 2.1 已打通部分
- 专家页可以命中项目级 `workspace-entry`
- Douyin 本地纯画面工作流已经有真实成功样例
- Douyin 主流程已支持:
- `--image`
- `--audio`
- `--seedance-reference-image`
- `--seedance-reference-video`
- `--seedance-reference-audio`
### 2.2 当前明确缺口
- 客户端专家页输入框目前只有文本输入,没有图片上传入口
- `DesktopApi.chat.sendPrompt()` / `streamPrompt()` 当前只有:
- `sessionId`
- `prompt`
- `skillId`
- IPC 层当前也只透传纯文本 prompt
- `project-workspace-executor` / `project-workspace-agent-runner` 当前只有文本 prompt 输入,没有附件协议
- Douyin 数字人链路当前明确要求必须有图片
### 2.3 对 Douyin 的直接影响
- 数字人路线:当前客户端无法把图片传给 expert,因此无法从客户端直接跑通数字人
- 纯画面路线:无图纯文案可以跑,但参考图 / 参考视频 / 参考音频能力当前无法从客户端输入
## 3. 目标
本次目标不是一次性做完整多模态聊天,而是先补齐最小闭环:
1. 客户端专家页支持选择并发送 1 张本地图片
2. 图片在 main 进程被复制到当前项目目录下的稳定路径
3. `workspace-entry` 能收到这张图的结构化输入
4. Douyin expert 能把这张图用于数字人主图输入
5. smoke 不再只验证 `workspace-entry launch`,至少验证“附件已进入项目执行层”
## 4. 方案范围
### 4.1 本次纳入
- 图片附件协议
- 专家页单图上传
- main 进程项目内落盘
- `workspace-entry` 附件透传
- Douyin expert 单图数字人最小闭环
- smoke 验证升级
### 4.2 本次不纳入
- 多图上传
- 音频上传
- 剪贴板图片
- URL 素材粘贴
- 通用多模态聊天体系重构
- 去修改 Douyin 项目“数字人必须传图”的业务约束
## 5. 实施方案
### 5.1 聊天协议与 IPC
扩展以下调用签名,新增可选 `attachments`
- `DesktopApi.chat.sendPrompt`
- `DesktopApi.chat.streamPrompt`
新增最小附件结构,v1 先只支持图片:
- `kind: "image"`
- `name`
- `mimeType`
- `localPath`
要求:
- 与当前纯文本调用兼容
- 无附件时行为保持不变
- renderer -> preload -> ipc -> main 全链路统一使用同一份附件结构
### 5.2 专家页 UI
在现有 composer 上补一个最小上传入口:
- 支持选择 1 张本地图片
- 已选择图片可见
- 重选时以最后一次选择覆盖
- 发送成功后清空附件
- 发送失败时保留附件,便于重试
本阶段不引入复杂交互:
- 不做多图排序
- 不做拖拽上传
- 不做素材管理器
### 5.3 Main 进程项目内落盘
main 进程收到图片后,不直接把临时路径传给项目,而是先复制到当前项目目录:
- 目标目录:`inputs/images/main/`
要求:
- 生成稳定文件名
- 绑定当前 `projectId` / `sessionId`
- 禁止跨项目复用错误路径
- 会话未绑定项目时直接返回明确错误
### 5.4 Workspace-entry 执行层
扩展:
- `ProjectExecutionRequest`
- `ProjectWorkspaceExecutionInput`
- `project-workspace-agent-runner` 的输入结构
执行策略:
- 保留原始 `prompt`
- 同时透传 `attachments`
- 如果当前 bundled agent 暂时不能直接吃结构化图片输入,则在 runner 层集中做一次降级,把图片路径转换成稳定提示注入
约束:
- 不在 renderer 层拼接图片说明
- 不在多个中间层重复组装 prompt
- 所有附件降级策略集中在执行层单点处理
### 5.5 Douyin expert 约定
v1 统一约定:
- 客户端上传的单张图片,默认视为“数字人主图 / main image”
这样可以先解当前最刚需的场景:
- 从客户端对话 Douyin expert
- 上传人物图
- 继续生成数字人口播视频
纯画面路线后续可以复用同一套附件协议,再细分为:
- `seedance_image`
- `reference_image`
- `reference_video`
- `reference_audio`
但这些不作为本次第一阶段的强验收项。
## 6. 验收标准
### 6.1 功能验收
满足以下结果即视为本阶段完成:
1. 专家页可选择并发送 1 张图片
2. 图片能落到当前项目 `inputs/images/main/`
3. Douyin expert 在项目执行层能读取到该图片路径
4. 数字人路线不再因为“客户端无法传图”而阻断
### 6.2 回归要求
以下行为不能被破坏:
1. 无附件的纯文本专家对话行为不变
2. 当前已打通的 `workspace-entry` 路由不回退为 skill fallback
3. 现有 Douyin 纯画面文本生成链路不回归
### 6.3 smoke 验收
至少新增或升级以下验证:
1. 专家页上传图片后,附件成功透传到项目执行层
2. `douyin expert cloud-bundle smoke` 不再只接受 `workspace-entry launch`
3. 保留现有纯文本 smoke,确保兼容旧行为
如果环境允许,再补一条本地真实验证:
1. 上传人物图
2. 用文案 + TTS 走数字人
3. 输出 `video_omnihuman.json` 或等效成功产物
## 7. 实施顺序
建议按以下顺序推进,避免前后返工:
1. 先补 shared types / preload / ipc 的附件协议
2. 再补专家页单图上传 UI
3. 再补 main 进程项目内落盘
4. 再补 workspace-entry executor / runner 附件透传
5. 最后补 Douyin smoke 和真实验证
## 8. 默认假设
- v1 只支持单张图片
- v1 只支持本地文件
- v1 不支持音频上传
- v1 不改 Douyin 数字人必须传图的既有约束
- 结构化多模态能力如果当前 runtime 未直接支持,允许 runner 层先做集中降级适配
# 新电脑初始化真实自动化一周计划
Status: proposed
Date Range: 2026-04-10 to 2026-04-16
## 1. 目标
本周目标不是“开发机可以跑”,而是把下面这条链路做成可验收的稳定闭环:
1. 新电脑安装客户端
2. 用户输入 employee key
3. 客户端调用 `https://spb-bp1wv2oe0hvfvi98.supabase.opentrust.net/functions/v1/openclaw-employee-config`
4. 从返回的 `skills[].skill.download_url` 识别抖音 / 小红书 zip 项目包
5. 客户端自动下载并解压到本地工作区
6. 专家页出现对应项目
7. 用户发送一句自然语言
8. 客户端命中项目 `workspace-entry`
9. 本地真实启动 Python / Playwright 自动化链路
## 2. 本周验收标准
本周结束时,至少满足以下结果:
1. 空白用户目录下首次安装,保存 employee key 后可自动完成 `init` 拉取和项目同步
2. `workspaceSummary` 中能看到非 home 项目,且 `currentProjectId``projectReady` 为真
3. 专家页发一句话时,默认走 `workspace-entry`,而不是 skill fallback
4. bundled runtime 不再因 `_greenlet``async_playwright` 导入失败而阻断真实自动化
5. 项目运行态在 bundle 更新后不会因为目录替换而丢失
6. 小红书项目在 fresh install 路径下完成至少一次真实自动化启动验证
## 3. 范围
本周纳入:
- `openclaw-employee-config` 返回契约与客户端解析契约对齐
- project bundle 标准化
- bundled runtime 依赖与探测硬化
- installer / experts 真实链路 smoke
- 小红书项目运行态迁移到 `memory/`
- 项目级 skill 展示与校验收口
本周不纳入:
- “扫描 `skills/*/SKILL.md` 自动反推项目”的重构
- 项目 skills 的彻底物理隔离重构
- 超出当前 bundled runtime 能力的大规模新依赖体系设计
## 4. 关键事实基线
- 当前客户端已经有 `employee-key -> runtime cloud fetch -> zip bundle sync -> project inventory -> experts page -> workspace-entry` 主链路
- 当前最大 fresh install 风险在 bundled runtime 的 Python 依赖校验过浅,尤其是 `greenlet` / `async_playwright`
- 当前 project bundle 缺失 `project.json` 时仍会被客户端降级猜测,不适合正式交付
- 当前项目运行态只保留 `sessions.json``session-messages/``memory/`,所以所有可变状态必须迁入 `memory/`
- 当前 `listProjectSkills()` 仍会混入 curated generic skills,不满足“进入项目后只看该项目能力”
## 5. 每日计划
### Day 1: 2026-04-10
目标:冻结契约,避免后续实现反复返工。
任务:
- 明确 `openclaw-employee-config` 返回字段的最小必需项
- 明确 zip 项目包的标准交付契约
- 明确 `project.json` 最低要求必须包含:
- `id`
- `name`
- `platform`
- `projectType`
- `workspaceAutomation`
- `defaultEntry`
- `entries`
- 明确本周验收以小红书链路为主,抖音按同一标准补齐
交付物:
- 本文档
- 项目包契约确认结论
### Day 2: 2026-04-11
目标:先堵住 fresh install 最容易失败的 bundled runtime 问题。
任务:
-`build/runtime/python/requirements.in` 和锁文件中显式纳入 `greenlet`
- 调整 `packages/runtime-manager/src/index.ts`
- 把 Python payload 探测从 `find_spec` 提升为真实关键导入探测
- 至少覆盖:
- `import greenlet`
- `from playwright.async_api import async_playwright`
- 调整 installer smoke,同步校验上述关键导入
交付物:
- runtime 依赖更新
- runtime 探测更新
- installer smoke 更新
验收点:
- 打包 Python 环境可真实导入 `greenlet`
- `pythonReady` 只在关键依赖通过时才为真
### Day 3: 2026-04-12
目标:把 bundle 接入从“能猜”改成“强契约”。
任务:
- 修改 `project-bundle.ts`
- 安装后要求项目根必须存在标准 `project.json`
- 缺失时 bundle sync 明确报错,不写入 ready project
- 保留现有 rollback / replace / preserve local state 逻辑
- 校验项目根结构兼容:
- zip 根就是项目根
- zip 根下 `projects/<projectId>`
交付物:
- bundle 解析与报错硬化
- 缺失 `project.json` 的明确诊断
验收点:
- 非标准 zip 无法被静默安装成 ready project
### Day 4: 2026-04-13
目标:收口项目隔离表现,避免专家页误混全局能力。
任务:
- 修改 `project-store.ts`
- `boundSkillIds` 与实际 `workspace/skills/<skillId>` 做交叉校验
- 对缺失 skill 做诊断日志和降级处理
- 专家项目视图下不再自动混入 curated generic skills
- 保持 session 继续按 `project:<projectId>:<uuid>` 隔离
交付物:
- 项目 skills 列表收口
- `boundSkillIds` 诊断
验收点:
- 进入 `xhs` 后只显示 `xhs` 绑定技能
- 进入 `douyin` 后只显示 `douyin` 绑定技能
### Day 5: 2026-04-14
目标:把小红书项目调整到真正适合 bundle 替换的状态。
任务:
-`workspace/xhs` 为模板,梳理真实自动化入口
- 确保 `project.json` 包含 `workspaceAutomation`
- 确保 `workspace_entry.py` 能处理自然语言 prompt
- 把运行态迁移到 `memory/`
- 重点清理这些项目根运行态:
- `xhs_profile`
- `generated_images`
- `openclaw_runs`
- `openclaw_debug`
- 其他浏览器态 / 草稿态 / 调试态文件
交付物:
- 可交付的小红书标准 bundle 源
验收点:
- bundle 替换后,小红书登录态和会话态仍保留
### Day 6: 2026-04-15
目标:让抖音项目按同一套标准补齐,而不是做特殊兼容。
任务:
- 给抖音项目补标准 `project.json`
-`workspaceAutomation``workspace_entry.py`
- 校对 `boundSkillIds`
- 确认抖音项目依赖不超出本周 bundled runtime 能力
- 如超出,单独列出 runtime 扩容项,不在 bundle 内偷偷引入
交付物:
- 可交付的抖音标准 bundle 源
验收点:
- 抖音和小红书都能以“一包一项目”方式被客户端识别
### Day 7: 2026-04-16
目标:做真正的 fresh install 验收,而不是开发机自测。
任务:
- 用空白用户目录执行 installer smoke
- 用空白用户目录执行 experts 页真实链路 smoke
- 重点验证:
- employee key 初始化
- zip 下载与项目同步
- 专家页项目出现
- `workspace-entry` 命中
- 小红书真实自动化成功启动
- bundle 替换后 `memory/` 保留
- 输出遗留问题清单和是否可以进入下周收尾
交付物:
- fresh install 验收结果
- 遗留问题清单
## 6. 文件级实施清单
本周高优先级涉及的代码文件:
- `apps/desktop/src/main/services/cloud-api.ts`
- `apps/desktop/src/main/services/project-bundle.ts`
- `apps/desktop/src/main/services/project-store.ts`
- `apps/desktop/src/main/services/project-workspace-executor.ts`
- `packages/runtime-manager/src/index.ts`
- `build/runtime/python/requirements.in`
- `build/runtime/python/runtime-requirements.lock.txt`
- `build/scripts/installer-smoke.ps1`
- `build/scripts/xhs-expert-cloud-bundle-smoke.ps1`
- `build/scripts/xhs-expert-live-run.ps1`
项目包侧高优先级文件:
- `workspace/xhs/project.json`
- `workspace/xhs/workspace_entry.py`
- `workspace/douyin/project.json`
- `workspace/douyin/workspace_entry.py`
如果真实项目源不在仓库内,则需要同步维护一份与仓库规范一致的交付模板。
## 7. 风险
1. 若抖音或小红书项目依赖超出当前 bundled runtime,单靠 zip 交付无法解决
2. 若真实自动化代码继续把运行态写在项目根,bundle 替换时仍会丢状态
3. 当前项目 skills 仍是共享物化到 `workspace/skills`,若未来两个项目出现同名 skill,仍存在覆盖风险
4. 如果服务端返回契约字段不稳定,fresh install 的初始化链路会出现非代码层问题
## 8. 周末结论口径
只有同时满足以下条件,本周工作才算达标:
1. 新电脑或空白用户目录下首次安装可完成初始化
2. employee key 触发的 `openclaw-employee-config` 可稳定下发 zip 项目包
3. 客户端可自动把 zip 物化为 ready project
4. 专家页可以直接选择项目并命中 `workspace-entry`
5. 小红书真实自动化在 fresh install 环境下成功启动
6. installer smoke 和 experts 真实链路 smoke 均通过
如果只做到“项目能出现”或“开发机能跑”,但 fresh install 不稳定,则本周目标不算完成。
# Context
当前桌面端实际上有两条**不能混用**的配置链路:
1. **项目 zip / 项目侧链路**:客户端会用员工密钥请求 `openclaw-employee-config`。这条链路服务的是项目包 / 项目运行时相关配置,不是客户端 model 设置来源。
2. **客户端设置链路**:客户端自己的 model 配置必须在设置页里单独绑定与保存。
`workspace` 下的小红书 / 抖音项目仍有多处模型写死:文案、生图、生视频分别在各自脚本里使用默认模型或启发式回退;同时客户端设置页虽然已经有部分 expert 配置能力,但没有完整的“客户端模型配置 UI / 消费链路”。因此现在的问题不是简单复用 employee config,而是要把**客户端设置****项目模型消费方**真正打通。
目标是把客户端设置页作为唯一入口:
- 客户端 model 配置在设置页绑定、保存、回读
- 主进程负责把这份客户端设置下发到项目执行链路
- `workspace` 只消费客户端下发的解析结果,不再各自维护散落的硬编码默认模型
# Recommended approach
## 1. 以现有 `expertModelConfig` 为中心扩展,不新建第二套模型配置对象
优先复用现有设置保存链路,而不是再加一个独立的 `clientModelConfig`
- 现有结构已经覆盖三类能力:`copywriting` / `image` / `video`
- UI、IPC、配置持久化已经能保存这三类 expert 配置
- 只需在每一项上补充 `modelId`(必要时补 `modelDisplayName` 仅用于展示)
建议目标结构:
- `expertModelConfig.copywriting = { baseUrl, apiKey, modelId }`
- `expertModelConfig.image = { baseUrl, apiKey, modelId }`
- `expertModelConfig.video = { baseUrl, apiKey, modelId }`
员工密钥仍保留在顶层 `apiKey`,但它只用于项目 zip / 项目侧链路,不作为客户端 model 配置来源。
## 2. 主进程统一做“客户端设置 -> 项目执行”的模型归一化
由桌面端主进程统一决定最终生效配置,优先级建议统一为:
1. 用户在设置页显式填写的 `modelId`
2. 对应 capability 的本地 `baseUrl` / `apiKey`
3. 现有脚本里的历史回退值(过渡期保留)
这里**不再把 `openclaw-employee-config` 当成客户端 model 默认值来源**。它继续服务项目 zip / 项目侧配置,但客户端模型选择完全来自设置页。
主进程需要输出一份**归一化后的运行时模型配置**,再注入到项目执行链路。不要让 `workspace` 内各脚本继续各自解析一套默认值。
## 3. `workspace` 只消费归一化结果,先兼容旧环境变量,再逐步去硬编码
XHS 和 Douyin 都先改成“优先读主进程传入配置,其次兼容现有 env,最后才走历史默认值”。这样可以分阶段上线,不需要一次性把所有旧分支删掉。
## 4. 首期范围只统一“模型选择”,不扩大到所有生成参数
首期重点打通:
- 客户端聊天 / 文案模型
- 生图模型
- 生视频模型
`IMAGE_SIZE``IMAGE_COUNT`、风格 prompt、Seedance 分辨率/比例、OmniHuman TTS voice 这类“生成参数默认值”暂不并入设置页,避免范围膨胀。它们可以先维持原样,等模型配置链路稳定后再考虑二期治理。
# Files to modify
## Desktop shared types / UI / main process
### `D:\qjclaw\packages\shared-types\src\index.ts`
- 扩展 `AppConfig` / `SaveConfigInput``expertModelConfig` 的类型定义,给 image / video / copywriting 增加 `modelId`
- 确认 `WorkspaceSummary` / 其他摘要结构是否需要暴露 capability 级别模型信息给 UI
### `D:\qjclaw\apps\ui\src\App.tsx`
- 设置页已有保存 `expertModelConfig` 的状态与 `saveConfig()` 链路,需补三类 `modelId` 的 UI 输入与本地 state
- 现有 `saveConfig()` 已会提交 `expertModelConfig`,应在此基础上把 `modelId` 一并提交
- 当前没有“客户端模型配置 UI”,这里是主要补齐点
### `D:\qjclaw\apps\desktop\src\main\ipc.ts`
- 确认 `config.save``workspace.getSummary`、项目执行请求构建处是否需要增加 capability 级模型透传
- 将主进程解析后的模型配置送入项目执行链路,而不是只用于聊天模型
### `D:\qjclaw\apps\desktop\src\main\services\cloud-api.ts`
- 继续保留 `openclaw-employee-config` 的现有职责,但不要把它作为客户端 model 默认值来源
- 仅检查是否有现有逻辑误把 employee config 的 `model_id` 当成客户端聊天模型默认值;如果有,需要与新的本地设置优先级重新梳理
## Workspace — XHS
### `D:\qjclaw\workspace\xhs\scripts\qwen.py`
当前热点:
- `ARK_TEXT_MODEL` 最终回退到 `qwen-plus`
- `ARK_VISION_MODEL` 与 provider 选择依赖启发式逻辑
需要改为:
- 先读归一化后的 copywriting / vision 配置
- 再兼容现有 `ARK_*` / `QWEN_*`
- 最后才回退历史默认值
### `D:\qjclaw\workspace\xhs\scripts\run.py`
当前热点:
- `XHS_IMAGE_MODEL` / provider 选择启发式
- `_candidate_image_provider_names()` / `_pick_image_model_id()` / `IMAGE_MODEL`
需要改为:
- 生图优先读主进程解析后的 image `modelId`
- 减少按 provider 名称、模型名猜测能力的逻辑作为主路径
### `D:\qjclaw\workspace\xhs\index.ts`
- 如果工具描述里仍写死固定模型品牌,需要同步去掉,以免 UI/文案与真实配置不一致
## Workspace — Douyin
### `D:\qjclaw\workspace\douyin\skills\douyin-master\scripts\coordinator.py`
当前热点:
- `writer_model: "qwen3-plus"`
- CLI 默认又是 `qwen3.5-plus`
- 统一编排入口却仍注入写死默认值
需要改为:
- coordinator 统一从客户端下发的归一化配置读取 copywriting / image / video 默认模型
- CLI 参数保留最高优先级覆盖
### `D:\qjclaw\workspace\douyin\skills\douyin-writer\scripts\generator.py`
当前热点:
- `llm_model="qwen3.5-plus"`
- `--llm-model` 默认值仍是硬编码
需要改为:
- 优先消费主进程注入配置
- 保留 CLI / env 兼容
- 最后才落到历史默认值
### `D:\qjclaw\workspace\douyin\skills\douyin-seedance-split\scripts\run_pipeline.py`
当前热点:
- `--llm-model default="qwen3-plus"`
- 与 coordinator / writer 存在重复默认值
需要改为:
- 统一走与 coordinator 相同的配置优先级
- 不再维护第二套 copywriting / image / video 默认模型
### `D:\qjclaw\workspace\douyin\skills\seedream-image-generator\scripts\run_seedream.py`
当前热点:
- `doubao-seedream-4-0-250828` 写死回退
需要改为:
- 优先读客户端设置中的 image `modelId`
- 再兼容 `SEEDREAM_MODEL`
- 最后才保留历史默认值兜底
### `D:\qjclaw\workspace\douyin\skills\seedance-2-0-video-generator\scripts\run_seedance.py`
当前热点:
- `doubao-seedance-2-0-260128` 写死回退
需要改为:
- 优先读客户端设置中的 video `modelId`
- 再兼容 `SEEDANCE_MODEL`
- 最后才保留历史默认值兜底
# Scope and impact
## 明确会动到的范围
1. **桌面端设置模型**
- shared types
- settings UI
- config save/load
- 主进程模型归一化逻辑
2. **客户端到项目的配置传递链路**
- config save -> main process -> project execution handoff
- env 注入 / runtime handoff
- 项目执行入口
3. **项目侧消费方**
- XHS 文案 / 视觉 / 生图
- Douyin 文案 / 生图 / 生视频
## 暂不建议纳入首期的范围
- employee config 接口协议扩展
- 生图尺寸、张数、风格词等生成参数
- Seedance ratio / resolution / audio / watermark 等非模型参数
- Omnihuman TTS voice 等与模型配置不同层级的运行参数
- 全量重构为新的统一 Python 配置库
# Risks
## 1. 现有保存配置缺少 `modelId`,需要平滑兼容
老配置里只有 `baseUrl` / `apiKey`。新增字段后,读取逻辑必须允许 `modelId` 为空;空值应解释为“继续走旧逻辑 / 历史默认值”,不能当成清空。
## 2. 需要把“客户端设置”和“employee config”职责彻底分开
当前部分链路已经会把 employee config 的 `modelId` 暴露到 `WorkspaceSummary` / 运行时配置里。如果后续又把它当客户端 model 默认值,就会重新混淆两条链路。首期要明确:
- employee config:项目 zip / 项目侧
- settings model config:客户端与项目模型选择
## 3. XHS / Douyin 各脚本仍依赖旧 env 名称
现有项目脚本散落读取:
- `ARK_*`
- `QWEN_*`
- `XHS_IMAGE_*`
- `SEEDREAM_*`
- `SEEDANCE_*`
如果主进程不继续注入这些兼容 env,首轮改动容易断链。建议首期保留旧 env 兼容层。
## 4. Douyin 内部默认值不一致,统一后可能改变历史行为
Douyin 当前同一能力存在 `qwen3-plus` / `qwen3.5-plus` 两套默认值。统一后会暴露出行为变化,需要明确“谁是最终默认值来源”。建议以后统一以:
- 用户设置
- 单一保底默认值
两层为准。
## 5. XHS 当前部分逻辑依赖模型能力猜测
例如按 provider 名称或 model id token 推测是不是视觉/生图模型。切到显式 `modelId` 后,这些猜测逻辑可能与新配置冲突。首期应改成“显式配置优先,启发式仅兜底”。
## 6. 调试复杂度会上升,必须增加可观测性
链路变成“设置页 -> 主进程归一化 -> runtime 注入 -> workspace 消费”后,如果没有清晰日志,很难判断最终生效的是哪一层。建议在主进程和项目入口增加脱敏后的 resolved-config 调试输出。
# Verification
## 1. 设置保存与回读
- 在设置页填写:copywriting/image/video 的 `baseUrl``apiKey``modelId`
- 保存后确认:
- UI 能正确回显保存值
- 老配置文件可正常升级加载
- 未填写 `modelId` 的旧配置不报错
## 2. 主进程归一化
- 不依赖 `openclaw-employee-config`,直接验证本地 settings 保存后的 resolved model config
- 验证优先级:
- settings 中显式 `modelId`
- 对应 capability 的 `baseUrl` / `apiKey`
- 历史回退值
## 3. 主进程到项目执行链路
- 在项目启动/执行前检查归一化后的 resolved model config
- 验证 XHS / Douyin 拿到的是同一套解析后的 capability 配置
- 验证旧 env 兼容字段仍被正确注入
## 4. XHS 端到端
- 文案/分析链路:确认 `xhs/scripts/qwen.py` 不再优先落到 `qwen-plus`
- 视觉分析链路:确认 `ARK_VISION_MODEL` 来源于客户端设置下发配置
- 生图链路:确认 `xhs/scripts/run.py` 使用 settings 中的 image `modelId`,而不是 provider heuristics
## 5. Douyin 端到端
- 文案生成:确认 `douyin-writer/scripts/generator.py` 使用统一后的 copywriting `modelId`
- Seedream 生图:确认 `run_seedream.py` 使用 settings 中的 image `modelId`
- Seedance 生视频:确认 `run_seedance.py` 使用 settings 中的 video `modelId`
- split pipeline:确认 `run_pipeline.py` 与 coordinator 使用同一套默认模型来源,不再各自写死
## 6. 回归测试
- 未填写任何 capability `modelId` 时,旧项目仍可执行
- 仅配置 copywriting 时,不影响 image/video
- 仅配置 image/video 时,不影响其他能力
- 保存空白 apiKey 字段时,不会误清除已有 capability 密钥
# Recommended execution order
1. 扩展 shared types 与 settings UI,补齐 `modelId` 保存能力
2. 在主进程建立统一的 resolved model config
3. 先接 Douyin:因为硬编码更多、收益最明显
4. 再接 XHS:收敛 `qwen.py``run.py`
5. 最后清理工具描述、日志与 smoke 测试
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment