Files
MediaCrawler/mac-agent-os-main/CHANGELOG.md
T
butubb 2112c1a870
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s
feat(monitor): 抖音 Web 接口客户端 —— 绕开爬虫子进程,直接发 HTTP
移植自 mac-agent-os 的 mediacrawler_adapter:不起子进程、不开页面,用浏览器里那份
登录态直接调抖音 Web 接口。产物键名照抄 store/douyin,所以 ingest 那条链路一个字不用改。

**目前能用的(真环境实测,非推断)**:

    profile/other : 200, 7075 字节  —— 博主主页指标(粉丝/获赞/作品数/昵称)
    aweme/detail  : 200, 45425 字节 —— 单条作品详情(含点赞/评论/收藏/分享)

**目前不能用的:作品列表 `aweme/post`。** 两个互相独立的原因:
  1. 这个接口被抖音单独升级成了真校验:不带 x-tt-argus 回 403「Uifid Not Found」,
     带上 dummy 值回 200 + **空 body**。也就是说「头在不在」骗得过,「真校验」过不了。
     同一套头打 profile/other 和 aweme/detail 都是通的 —— 抖音是挑着接口加保护的,
     挑中的恰好是「批量拉作品列表」这个最敏感的动作。
  2. 改走页面截获也不行:CDP 浏览器打开博主主页会落到「验证码中间页」(当天大量探测的
     代价,过几小时要重测)。

  所以现在的边界是:**已知作品的指标刷新能做,自动发现新作品做不了**。

**排查中控住变量后得到的两条事实**(都写进注释了):
  · `Accept` / `Accept-Language` / `Referer` 才是主页接口能返回真数据的原因 —— 只有
    UA+client hints+Cookie 时是 200 但仅 121 字节的空壳,补上这三个头变 7074 字节。
    (我先前猜的 sec-ch-ua 不是关键。)
  · 因此 UA 与 client hints 必须**成套地取自同一个浏览器**,所以 BrowserIdentity 一次
    从 CDP 取齐 cookie + UA + hints,而不是各自写死。

「200 + 空 body 必须当场报错」也是刻意写死的:放过去它会在下游变成「这个博主没作品」,
把一次失败伪装成一条正常结果 —— 爬虫那条路正是这么栽的,还被翻译成「账号被封」。

测试 +11:cookie 解析、请求头成套性(含 uifid 缺失/回退)、产物键名与 store 对齐、
以及 _get 的三条失败路径(空 body / 403 带网关原话 / 正常返回)。
2026-10-10 17:12:25 +08:00

2029 lines
142 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AgentOS 项目变更日志
## [4.24.0] - 2026-10-03
### 🔄 新模块:人物置换(Wan2.2-Animate 接入视频工厂)
- **独立包** `05_tools/09_ave/scripts/person_swap/`(api / preprocess / service 三件套)
- **后端** `routes/person_swap.py`:6 个路由 `/api/person-swap/*`(状态/任务/上传/取消/受控文件服务)
- **前端** `views/person-swap.js` → 视频工厂「🔄 人物置换」:状态条 + 上传进度 + 任务轮询 + 成片下载
- **API 全链路校准(实测)**:两步式上传(`getPolicy` → OSS 直传);模型真名 **`wan2.2-animate-mix`**;
字段 `input.image_url` / `input.video_url` / `parameters.mode`;**std ¥0.6/秒 · pro ¥0.9/秒**
- **任务队列**:SQLite + 后台单 worker + 失败自动重试 + **月度费用护栏**
- **相对独立**:不占养号槽位(不经过 command_bus),独立队列与预算
### 🎙 声音链路(音频先行 + 对口型 + 分轨 + 音效)
- **音频先行**(`dubbing.pre_synthesize`):先合成台词音频 → 按音频**真实时长**调整镜头时长
(口型与节奏对得上的前提);音频存 `pre_audio/` 供后续复用,不重复 TTS
- **对口型**(百炼 **VideoRetalk** · ¥0.08/秒 · **1800 秒免费额度**):
仅对「**有台词 + 有出场人物**」的镜头做;音频复用先行产物;参考图取角色资产;失败自动退回原片段
- **声音分轨**:台词轨(与画面绑定)+ **旁白轨**(独立输出,避免重复混入主轨)
- **音效链路**:`load_sfx_assets` / `match_sfx` / `mix_segment(sfx_items)` 按 `at_second` **精确插入**
- **画面跟随音频对齐**(`composer/align.py`):音频变速会变调、画面变速无损 → **剪画面**;
对口型镜头跳过;变速比超 ±1.5x 跳过
- **一步到位**:出片完成自动配音混流 → `final_muxed.mp4`
### 🎨 去 AI 感体系
- **风格包**(`composer/realism.py`):9 种拍摄风格 —— 自拍第一人称 / 手持 Vlog / 伪纪录片 /
访谈纪实 / 电影感 / 商业棚拍 / 2D 动画 / 3D 动画 / 产品广告(每种含设备·光线·机位·质感·情绪·负面词)
- **反 AI 感**(`realism_boost`):3 档;**strong 档自动剔除「4K/超清/无瑕/大师作品」等反真实词**
(研究结论:这类词是"塑料感"的头号来源)
- **20 位真实导演风格库**(`composer/director_styles.py`):斯皮尔伯格 / 稀奇柯克 / 库布里克 /
黑泽明 / 塔可夫斯基 / 王家卫 / 诺兰 / 芬奇 / 维伦纽瓦 / 毕赣 / 张艺谋 / 侯孝贤 / 朴赍郁 / 马力克 等
—— 与拍摄风格**独立叠加**(风格 = 设备质感;导演 = 镜头语言与叙事逻辑)
- **参考图按景别分配**:特写/近景用**角色图**(保脸);全景/空镜用**场地图**(保环境)
- **研究归档**:`05_tools/09_ave/docs/realism/`(21 篇方法论原文)+ `PLANS/REALISM_GUIDE.md`
(来源:muse-video-skill「参考图优于文字描述」· lanshu-awesome-ai-video-kit · DirectorSKILL 等)
### 🔧 基础能力治理
- **能力清单对账**:修正 5 处「清单 ≠ 实际」;新增 `frame_chain` / `voice_lock` 登记(代码早已实现却未登记)
- **能力体检脚本** `capability_doctor.py`:静态核对 impl 文件 / api_key 配置 / 状态一致性,揪出"名不副实"
- **首尾帧衔接接线**(`chain_from_prev`):`kling_video.generate_video(tail_image_path=)` 透传 +
新增 `composer/frames.py`(本地 ffmpeg 抽首/尾帧,零成本)
- **多角色一致性**:导演「多角色同框纪律」(避免同框露脸 → 正反打/过肩/中远景)+ 逐镜头 `cast_in_shot` 标注
- **出片质检** `composer/qa.py`:接触印相表(抽帧拼图,一眼核对口型 / 跨镜人脸一致性)
- **任务持久化 + 续跑**:任务状态落 `job.json`;重启后标记 `interrupted`;**续跑复用已生成镜头**(不重复扣费)
### 🐛 修复(均为实测定位的真 bug)
- **Pexels 素材搜索一直 403**:代码缺 `User-Agent`(key 本身可用)→ 现已可用(3879 条竖屏素材)
- **音效库上传 404**:`AssetStore.create()` 的 id 优先级写反(写成 name 优先 → 传入 id 被忽略)
- **影棚词污染提示词**:资产描述里的「柔光箱/85mm/纯灰色背景」被注入导演 → 新增清理 + 丢弃空壳标签
- **过度清理 bug**:正则 `\w` 匹配中文 → 正常描述被误清空
- **参考图解析不认演员表**:多角色分镜全部退化为文生视频(人脸随机)
- **TTS 长期不可用**(三个真根因):模型名无效(`cosyvoice-v3.5-plus` 不存在,应为 `v3-flash`)/
`instruction` 参数触发 `418` / 路径少一层
- **可灵时长档位阈值错**:7→5.2(原 6 秒镜头只生成 5 秒 → 拼接穿帮)
- **写死的假 ffprobe**:`~/.local/bin/ffprobe` 是 ffmpeg 的软链 → 新增身份校验 + stderr 解析兜底
### ⚠️ 已知限制
- 可灵只接受**一张**输入图 → 「角色参考图(保人脸)」与「上一镜尾帧(保连续)」**二选一**(现优先保人脸)
- 图生视频的**多角色同框**只能保主角人脸(配角不保)
- 音效库暂缺「倒吸一口气」「叹气」素材
- **前端改动需硬刷新**(`Cmd+Shift+R`):视图按 chunk 加载
## [4.23.1] - 2026-10-02
### 生成前审核「全链条」推广(角色生成器 / 导演创作 / 流程画布)
承接 4.23.0(资产参考图),把「**生成前看到将发送的内容**」推广到其余所有生成入口:
- **🎨 角色生成器**(`char-gen.js`)
- 点「生成」→ 审核面板显示**完整提示词**(**可编辑**)+ 视角 / 引擎 / 张数 / 费用
- 确认后带 `prompt_override` 生成(后端**优先用编辑后的提示词**)
- **🎬 导演创作 · 生成成片**(`ave-director.js`)
- 出片前审核面板列出**每个镜头的完整提示词** + 能力 / 引擎 / 是否绑角色 + 费用明细
- **🎞️ 流程画布 · 运行**(`workflow.js`)
- 运行前审核面板列出**各生成节点的配置参数** + 镜头上限 + 费用
- 并提示:具体镜头提示词由上游「分镜」节点在运行时组装 → 可先去「导演创作」预览
- **🌐 全局挂载**(`inline.js`):`window.openGenerateReview` —— 任何视图都能用同一个审核面板
- **后端**(`routes/ave_assets.py`):生成接口支持 `prompt_override`(用户改过的提示词优先)
- **流程状态**:新增「就绪」(`ready`)徽章 —— 表示**等待全部上游节点完成**
### 修复
- 补上缺失的 `_sbSetVfx()` 定义(此前 HTML 有引用但**无函数定义** → 选特效下拉会报错)
## [4.23.0] - 2026-10-02
### 🔍 生成前「内容审核」(不再只有费用提示)+ 通用审核组件
**用户反馈(关键)**:"只告诉我有费用、却不告诉我传了什么,那不叫审核,那叫通知" + "我要看到传给大模型的是什么"
**新增通用组件** `frontend/src/views/gen-review.js` → `openGenerateReview(opts)`
- 可复用的「生成前审核面板」:显示将发送的**完整内容**(可编辑)+ 参数 + 费用
- 支持:多字段编辑 · 参数表格 · **来源字段**折叠展示 · 提示说明 · 确认/取消
- 所有生成入口统一用它 → 交互一致,"每一步前面都能调整"
**首批接入:🎨 资产参考图生成**(用户点名的链路)
- **原问题**:点「AI 生成」直接调接口,提示词由后端组装,**前端完全看不到**(只有"有费用"的确认框)
- **新增后端接口** `POST /{kind}/{aid}/preview-image-prompt`(**纯计算,零费用**)
返回:完整提示词 + 自动组装版本 + 供应商/尺寸/槽位 + 费用提示 + **来源字段**
- **前端改造**(`assets-common.js`):
- 点「🎨 AI 生成」→ 先调 preview → 弹**审核面板**(提示词可直接编辑)
- 面板提示:"描述不够具体时先回去补字段再生成"(引导提高质量)
- 点「✅ 确认生成」才真正调生成接口(**传用户编辑后的提示词**)
- 审核组件未加载时**兜底**:确认框里也**显示完整提示词**(不再只讲费用)
**实测**(场景「病房-302」→ 生成「全景」参考图):
```
供应商: 可灵(Kling) | 尺寸: 9:16 | 槽位: wide
费用: 可灵图片按张计费(约 ¥0.2~0.5/张)
📝 将发送给模型的完整提示词:
场景空间:病房-302,靠窗有一张病床,床头柜放水杯,窗外能看到医院走廊,
空间类型:医院单人病房,光源状态:日光灯偏冷,窗外自然光,
材质要点:白色墙面、浅灰地板、金属床架,全景广角,真实空间摄影,自然透视,无人物,高清
来源字段: {name, space_type, lighting, materials, description}
```
### 📋 生成入口审核现状盘点(供后续推广)
| 生成入口 | 之前 | 现在 |
|:--|:--|:--|
| 🎨 资产参考图生成 | ❌ 只有费用确认 | ✅ **完整提示词可编辑** |
| 角色生成器 | 🟡 有实时预览,生成确认框不带提示词 | ⏳ 待接入 |
| 导演创作 · 生成成片 | 🟡 有"预览方案",确认框不显示提示词 | ⏳ 待接入 |
| 流程画布 · 运行 | 🟡 只有费用确认 | ⏳ 待接入 |
| 评论/讨论生成 | 🟡 生成后可见,生成前无预览 | ⏳ 待接入 |
## [4.22.1] - 2026-10-02
### 🔴 修复:变速(慢动作/快进)音轨丢失 + 前端接线
**用户反馈**:"慢动作也做出来,就是音频不见了" —— 用户报告正确 ✓
**真根因**(`composer/speed_ramp.py` 的 ffmpeg filter 图非法):
- `_build_atempo_filter()` 返回 `[0:a]atempo=0.5[a]`(**自带**输入/输出标签)
- 但调用处又拼了一个 `[a]` → `setpts=2.0*PTS[v];[0:a]atempo=0.5[a][a]` ❌
- → ffmpeg 报 filter 图错误,音频编码 **0 字节**,输出只剩画面
(`-shortest` 让结果看起来像"原片复制")
**修复**:去掉多余的 `[a]`(af 已自带标签)
**实测**(用有音轨的成片,源 12.46 秒):
| 变速 | 结果 | 音轨 |
|:--|:--|:--|
| 0.5x 慢动作 | 12.46s → **24.93s**(正好 2 倍) | ✅ 有音轨 |
| 2.0x 快进 | 12.46s → **6.22s**(正好一半) | ✅ 有音轨 |
| 1.0x 正常 | 保持原样 | — |
**前端接线**(让变速真正可用):
- 分镜卡片加「**速度**」下拉(1x / 0.5x 慢动作 / 0.25x 超慢 / 2x 快进)
- 新增 `_sbSetSpeed()`(写 `shot.speed.factor`)→ 执行器读它并调 `speed_ramp`
- **补上缺失的 `_sbSetVfx()`**(此前 HTML 引用了但未定义 → 特效下拉会报错)
**变速是零成本**(纯本地 FFmpeg,不调 AI)✓
## [4.22.0] - 2026-10-02
### ✨ 视频特效接入(可灵运镜控制)+ vfx 能力分层调研
**背景**:用户问"视频特效要不要接入" —— 做了调研并落地可立即用的部分。
**实现:运镜类特效 → 可灵 `camera_control`**
- `KlingVideoClient.build_camera_control()`:特效类型 → 可灵运镜参数
- 🌀 环绕运镜 → `{type: simple, config: {horizontal: 6}}`
- ⏱️ 子弹时间 → `{type: simple, config: {roll: 5}}`
- 🐢 慢动作 → `{type: simple, config: {vertical: 3}}`
- 🔍 焦点锁定 → `{type: simple, config: {zoom: 4}}`
- + 可灵官方预设 4 种:⬇️ 下摇后拉 / ⬆️ 前推上摇 / ↩️ 左转前推 / ↪️ 右转前推
- `generate_video()` 新增 `vfx_type` / `vfx_params` → 提交任务时带 `camera_control`
- 分镜卡片:生成能力选「✨ 视频特效」时**出现特效下拉**(8 种);也可从「镜头语言」的"环绕/推/拉"自动映射
- 「本镜头将用」显示具体特效名(如 `✨ 视频特效(🌀 环绕运镜)· 引擎:可灵运镜控制 camera_control`)
**实测**(Playwright 端到端):
```
分镜卡片 6 个 / 每卡片 6 个下拉
设为 vfx → 特效下拉出现(8 选项)
选「环绕运镜」→ 文案带出特效名 ✓
无 console 错误 ✓
```
### 📌 vfx 能力分层(重要结论)
**可灵本身没有「子弹时间 / 真慢动作」的专用能力** —— 视频接口只有 `camera_control`(运镜,8 种预设)。所以特效分三层:
| 类型 | 实现 | 状态 |
|:--|:--|:--|
| **运镜类**(环绕 / 推拉 / 焦点锁定 / 子弹时间近似) | 可灵 `camera_control` | ✅ **本次已接入** |
| **变速类**(真慢动作 / 速度斜坡) | 本地 **FFmpeg**(`composer/speed_ramp.py`) | 🟡 已有实现,待接入(**零成本**) |
| **复杂视觉特效**(变形 / 粒子 / 风格化) | **ComfyUI 工作流**(本地部署 / RunningHub 云端) | ⚪ 未接入(需选路线) |
## [4.21.0] - 2026-10-02
### 分镜镜头加「生成能力」下拉(手动覆盖自动判定)—— 补上之前漏做的 ①
**背景**:用户此前提出的「分镜里加能力选择下拉」被误判为"已有"(当时把"镜头类型下拉"当成了能力选择),
实际缺:**没有「自动」选项**、**没有「图生视频」选项**(只能靠绑角色自动触发,无法手动指定)。
- **数据层**:`Shot` 新增 `generation_capability`(`""` = 自动判定;可填 `text_to_video` / `image_to_video` / `vfx` / `comfyui`)
- **前端**(`ave-director.js`):
- 镜头卡片新增**第 2 个下拉**「生成能力」:⚙️ 自动判定 / 🎬 文生视频 / 🖼️ 图生视频 / ✨ 视频特效 / 🧩 ComfyUI
- 手动指定时**下拉边框高亮**(一眼看出哪些镜头被手动改过)
- `_capOfShot()` 改为**优先读手动指定**,为空才走自动判定(类型 + 是否绑角色)
- 「本镜头将用」实时反映(选"图生视频"但未绑角色会提示"将退化为文生视频")
- **后端**:`_cap_for_shot()`(预览接口用)同步支持手动覆盖
- **执行器**(`composer/pipeline.py::_generate_shot`)**真正按它生成**:
- `image_to_video` 或(自动 + 绑角色)→ **图生视频**(自动取角色参考图)
- `_resolve_character_ref()`:优先标准槽位(front / front_face / portrait / side / full),否则取任意存在的图
- 指定图生视频但取不到参考图 → **明确警告并退化为文生视频**(不静默失败)
- 实测:
- 后端:4 个镜头分别指定 自动/文生/图生/特效 → 能力判定**逐一正确** ✓
- 参考图解析:`找回的2张生成图 → ref_gen1.png` · `中国 → ref_front.jpg` · 不存在的角色 → 空 ✓
- 前端:6 卡片 × 6 下拉 / 5 个能力选项 / 切换后「本镜头将用」实时更新 / 无 console 错误 ✓
## [4.20.0] - 2026-10-02
### 费用防护完善:单价可配置 + 弹框显示完整费用明细
**用户反馈**:"弹框没显示金额" + "加一个我估计的输入框,算钱显示出来,默认 0.6 元/秒" + "我要加一个设置费用的地方"
- **新增「设置 → 💰 费用」分组**:
- 可灵单价(元/秒,默认 **0.6** = Kling 3.0 无声 720P)
- 单次运行镜头上限(默认 5,费用硬保护)
- **弹框改为完整明细**(原来单价硬编码、金额可能不显示):
- 生成节点数 / 每节点镜头数 / 总秒数 / 单价 / 预估费用
- 两处都加:① 流程画布运行前 ② 导演创作「生成成片」前
- 实测:弹框含「预估费用 / 单价 / 具体金额」三项全通过
### 计费口径澄清
**可灵 Kling 3.0 官方价:¥0.6/秒**(无声 720P 档)
- **5 秒镜头 = ¥3**(不是 ¥5);10 秒镜头 = ¥6
- 用户设置 0.6 元/秒是**正确**的
## [4.18.3] - 2026-10-02
### 「生产记录」升级为统一产物中心(按完整流程分组 + 全部产物可播放)
**用户反馈**:跑了多次,产物散在文件系统里,页面上看不到,只能靠问才知道文件在哪
- **后端新增** `GET /api/ave/artifacts`:扫描 `runtime/ave/` 下**所有**视频产物
(`renders/` 看板出片 + `workflow/` 流程各节点)→ 时间倒序 + **可播放 URL**
- **后端新增分组** `group=true`(默认):按**流程**分组(`workflow/<run_id>` / `renders/<job_id>`)
- 每组含:`final`(成片,优先 final_muxed)+ `items`(全部产物含中间)+ `count` + `total_mb`
- `stage` 分类:final(成片)/ concat(拼接未混流)/ shot(生成原始)/ deai(去AI化后)/ norm(规范化)/ other
- **前端「生产记录」页**:
- **每组一张卡片**:成片播放器 + 流程名 + 产物数 + 总大小 + 时间
- 「**▸ 查看该流程全部产物(N)**」→ 展开该流程的**所有文件**(阶段标注 + 大小 + ▶ 单独播放)
- 「显示中间产物」开关(控制是否显示无成片的纯中间流程)
- 实测:渲染 **6 组流程卡片 / 7 个可播放成片**,无 console 错误 ✓
## [4.19.0] - 2026-10-02
### 资产注入(「提前喂给导演」)+ 分镜卡片显示生成能力
**用户问题**:"导演生成分镜时要用到资源库里的场景/道具/产品,这些怎么进去?是生成分镜后再分配,还是生成时就喂给导演?"
**答案:提前喂(已实现)** —— 在**生成分镜之前**把资产**详情**注入导演提示词
- **机制**:`*_id`(资产引用)+ `*_context`(详情文本)
- `storyboard/generate` 收到 `location_id`/`character_id` 等 → **自动从资产库查详情** → 填入 `*_context`
- 导演提示词改用 `*_context`(详情)而非 ID → 画面描述**具体**
- **实测(关键验证)**:
- 建场地「病房-302」(space_type=医院单人病房 · lighting=日光灯偏冷 · materials=白色墙面、浅灰地板、金属床架)
- 生成分镜 → 画面:*「病房-302内景,靠窗的病床整洁铺着白色床单,**床头柜**上放着透明水杯…**日光灯**偏冷的光线洒在**白色墙面**上…**窗外**自然光…**浅灰**地板」*
- **5 个场地特征词全部命中** ✓(此前只会写泛泛的"我在病房里")
- **提示词改造**(v5.2 + legacy 两个导演):新增「资产设定(★必须严格使用,不要自己另编;同一资产在所有镜头中保持一致)」段落
- **schema**:`GlobalAnchors` 新增 `character_context` / `location_context` / `product_context` / `props_context`
### 分镜卡片显示「本镜头将用」
- 每个镜头卡片显示:**⚡ 本镜头将用:{能力} · 引擎:{模型}**
- 判定规则:`vfx`→特效 · `comfyui`→工作流 · `3d_character`→3D 渲染 · `talking_head`→口播/口型 · **绑角色→图生视频(保一致性)** · 否则→文生视频
- 未接入的能力明确标注"(未接入,生成时会跳过)",不假装可用
## [4.18.5] - 2026-10-02
### 阿里 API Key 轮换(用户提供新 Key)+ pre-commit hook 补漏
**用户操作**:提供新的阿里 API Key(`sk-ws-…` 格式,旧 Key 已泄露)
**验证与替换**:
- 新 Key **三个接口全部通过**:OpenAI 兼容接口 ✅ · DashScope 原生接口 ✅ · 模型列表(**518 个模型**)✅
- **TTS 实测成功**:用新 Key 生成 3.19 秒音频(49.9KB)✅
- **已替换**(走配置页接口):旧 Key **自动归档**(标记「被替换」,可一键回滚)· 文件权限 `600` · 不进 git
- 端到端复验:从**配置中心**读 Key 跑 TTS → 成功(59.7KB)✅
**🔒 pre-commit hook 补漏(重要)**:
- 原模式 `sk-[A-Za-z0-9]{20,}` **匹配不到**新版 key(`sk-ws-` 含 `.` 和 `-`,只匹配到 `sk-ws` 4 字符)
- 已补 `sk-ws-[A-Za-z0-9._-]{20,}` 模式 → **实测拦截成功**(提交含新 key 被阻止 + 脱敏显示)
## [4.18.4] - 2026-10-02
### API 配置页补全(13 → 24 项)+ 阿里 Key 核对
**用户反馈**:"服务 → 🔑 API 配置 里没找到阿里的 key,是不是不全?把现在有的都补全,注意保密"
**排查结论**:配置页白名单只有 **13 项**,而本机 `local.yaml` 实际有 **24 项** → **缺 11 项**
**补全的 11 项**:
- 🔊 **火山 TTS**:`volcano.app_id`(**TTS 必需**)· `volcano.api_key` · `volcano.access_key_id` · `volcano.secret_access_key` · `volcano.tts_model`
- 🔊 **阿里 TTS**:`aliyun.cosyvoice_model`(**TTS 模型名,关键**)
- 👁️ 阿里:`aliyun.wan_model`(人物置换模型)
- 🎨 可灵:`kling.base_url` · `kling.auth_type`
- 🖼️ Pexels:`pexels.rate_limit`
- 🤖 LLM:`llm.volc_ark_key`
**核对结论(用户问的阿里 Key)**:
- 本机 `aliyun.api_key`(脱敏 `sk-7e62…2c3a`)与用户提供的 Key **前 8 / 后 5 位完全一致** → **确认为同一个** ✅
- 实测:**Key 有效且余额正常**(充值已到账)✅
**保密**:接口仍只返回**脱敏值**(前 4 + 后 4),完整 Key 只存本机 `600` 权限文件、不进 git ✓
**新增「TTS 配置校验」**(`_test_aliyun_tts`,**零费用**):
- 校验 DashScope Key 有效性 + CosyVoice 模型名格式(**不实际生成音频**,不消耗 TTS 额度)
- 绑在「阿里百炼 API Key」的 🧪 测试上 → 点一下即知 TTS 是否就绪
- 实测:`✅ Key 有效 · 模型名 cosyvoice-v3.5-plus-bailian-7a1d40`
**TTS 实测通过**(用户充值后验证):阿里 CosyVoice 生成 2.8 秒音频(43.8KB),耗时 2.1 秒 ✓
## [4.18.3] - 2026-10-02
### 资产引用改为「下拉选择」(不再手输 ID)—— 全局锚点 + 角色库联动
**用户反馈**:"导演创作里面使用角色还需要手动输入角色 ID、地点 ID,应该做成下拉框直接从资源库选;其他的是不是都有这个问题?已有底座了,使用时就该直接下拉选择"
**排查结果**:
- `ave-director.js`:**全局锚点**(角色 ID / 地点 ID)是**手输框** → **要改** ✓
- `characters.js`:`_chUse` 用 `alert` 告诉用户"节点里填 character_id = xxx"(**让用户手抄**)→ **要改** ✓
- `ave-capabilities.js`:只是字段名中文映射表 → 不用改 ✓
**改动**:
- **导演创作页「⚙️ 全局锚点」**三个 ID 输入框 → **资源库下拉**
- 👤 角色(从角色库)· 🏞️ 地点/场景(从场景库)· 📦 产品(从产品库)· 🎲 种子(保持输入)
- 显示格式:`名称(id)`,值 = id(执行器按 id 取资产)
- 页面加载时自动拉取资源库填充;载入已保存分镜时**自动回填选中**
- **角色库「🔗 使用」按钮**:不再让用户手抄 ID → **写入 localStorage + 跳转导演页并自动预选该角色**
**实测**:
```
角色下拉: 3 选项((不使用角色)/ 找回的2张生成图 / 中国)
地点下拉: 2 选项((不指定地点)/ 病房)
产品下拉: 2 选项((无)/ 奶茶)
无 console 错误 ✓
```
## [4.18.2] - 2026-10-02
### 生产记录改为「按流程分组」展示(一次完整流程 = 一个卡片,可展开看全部产物)
**用户需求**:"按一次成片、也就是一个完整流程算一个;我需要再去看一个流程里面的全部产物 —— 这样就不会显示很多重复的,还能保留中间的我来调整"
- **后端** `/api/ave/artifacts` 新增 `group` 参数(**默认 True**):按**流程**分组
- 分组键:`workflow/<run_id>` 或 `renders/<job_id>` → **一次完整流程 = 一组**
- 每组含:`final`(成片,优先 `final_muxed`)+ `items`(该流程**全部产物**含中间)+ `count` + `total_mb`
- `stage` 分类:`final`(成片)/ `concat`(拼接未混流)/ `shot`(生成原始)/ `deai`(去AI化后)/ `norm`(规范化)/ `other`
- **前端**「生产记录」页:
- **每组一张卡片**:成片播放器 + 流程名 + 产物数 + 总大小 + 时间
- 「**▸ 查看该流程全部产物(N)**」按钮 → 展开该流程的**所有文件**(含中间产物,每行带阶段标注 + 大小 + ▶ 单独播放)
- 顶部「显示中间产物」开关:控制是否显示**没有成片的纯中间产物流程**
- 实测:**7 个流程组**(共 31 个文件)—— 不再是 31 个平铺文件,重复感消失
## [4.18.1] - 2026-10-02
### 修复:生产记录「视频变多且重复」的误解 —— 产物列表混入中间文件
**用户反馈**:"视频又多了,很多是重复的;后端不是加了控制吗?为什么还会生产视频?又花钱了吗?"
**排查结论(关键澄清)**:
- **没有额外花钱**:可灵视频任务 **22 条**(与之前完全一致)、图片 **30 条**(一致)→ **今天新增 0 条**
- 所有可灵调用均发生在 **10-01**(最新 20:50),**今天(10-02)未触发任何生成**
- **"视频变多"的真相**:`/api/ave/artifacts` 扫描 `runtime/ave/` 下**所有 mp4**。而**一次流程产生一条产物链**:
`shot_01.mp4`(生成原始)→ `deai_01.mp4`(去 AI 化)→ `norm_01.mp4`(规范化)
→ `final.mp4`(拼接)→ `final_muxed.mp4`(混流成片)
→ 共 31 个文件,看着"多且重复",**其实只有 7 个是真成片**,其余是**本地 ffmpeg 处理**的中间产物(**不花钱**)
**修复**:
- 后端 `/api/ave/artifacts` 新增 `only_final` 参数(**默认 True**)+ `stage` 分类标注
(`final` / `concat` / `deai` / `norm` / `shot` / `other`)
- 前端「生产记录」页:**默认只显示真成片**;勾选「显示中间产物」才展开全部
- 实测:默认视图 **7 个成片**(清晰不重复);全量 31 个(含中间产物)
## [4.18.0] - 2026-10-02
### 资产「锁定 + 版本记录」机制(角色一致性保障)+ 修复详情面板看不到参考图
**用户需求**:"角色如果开始使用就要锁定,生成时的提示词和种子数就要固定记下来,还有用的哪个模型都要记住,为了版本说明用"
**① 锁定机制**
- 数据字段:`locked` / `locked_at` / `locked_reason` / `locked_by` / `unlock_history`
- **自动锁定**:首次被流程引用(`bump_usage`)→ 自动锁定 ✓
- **手动锁定 / 解锁**:`POST /{kind}/{aid}/lock`、`/unlock`(解锁需填原因,记入 `unlock_history`)
- **锁定保护** `LOCK_PROTECTED_FIELDS`:`reference_images` / `generation_history` / `active_version` / `consistency_seed` / `voice`
→ 锁定时修改这些字段**会被拒绝**并给出明确提示
- **仍允许**:锁定后追加**新版本图**(新槽位名),只是不能覆盖已有槽位
**② 版本记录(`generation_history`)**
- 每次生成记录:**版本号 / 时间 / 提示词 / 负面提示词 / seed / 引擎 / 模型 / 槽位 / 文件 / 参数**
- 同时更新 `active_version` / `last_generation` / `consistency_seed`(供后续生成保持一致)
- 查询接口:`GET /{kind}/{aid}/history`
**③ 修复:详情面板"参考图都没有"**
- 根因:详情面板只渲染**固定 4 个槽位**(front / side / back / full),而实际槽位是 `gen1` / `gen2` / `portrait`…
- 修复:**动态列出所有已存在槽位** + 补齐未填的标准槽位
**前端**:详情面板新增「🔒 锁定状态条」(含原因/时间/解锁按钮)+「📌 生成历史」(版本 / 引擎 / 模型 / seed / 提示词)
实测:锁定 → 覆盖被拒(提示明确)→ 解锁 ✓ · 详情面板 2 张图加载成功 ✓
## [4.17.0] - 2026-10-02
### 角色生成器:**补上缺失的组装预览接口** + 即梦引擎 + 提示词清理
**排查结论(重要)**:
- 前端 `char-gen.js` **早已有**完整的「标签页 + 实时提示词预览」实现(347 行,含图片结果展示、费用确认)
- 但它调用的 `POST /characters/assemble-prompt` **后端不存在** → 实时预览**一直静默失败**(404)
- **本次补上该接口** → 实时预览真正可用
**本次实际新增/修复**:
- ✅ **`POST /api/ave/assets/characters/assemble-prompt`**(纯计算,**不生成、不扣费**)→ 前端实时预览用
- ✅ **即梦引擎**(`_seedream_generate`):火山方舟 Seedream 4.0 / 5.0,支持文生图 / 图生图(`ref_image`)
- 引擎下拉加即梦(密钥 `volcano.ark_api_key`)
- ⚠️ 模型需先在**火山方舟控制台 → 开通管理**开通;错误提示会明确告知 + 给出可用模型名
- ✅ **提示词清理** `_polish_prompt()` / `_empty_label_set()`:去掉空字段标签残留(`鼻梁。身穿。神色。`)
- 做法:从 `CHAR_LAYERS` 收集层/字段中文标签 + 组装器固定前缀词 → 精确替换「标签。」
- ⚠️ 踩坑:变长 look-behind `(?<=。|^)` 在 Python `re` 中非法(`look-behind requires fixed-width pattern`)→ 改用捕获组 / 标签集合
### 修复:找回用户"丢失"的 2 张生成图
- 图**生成成功了**(可灵任务 `934648689544040491` / `934648911431073867` 均 succeed,22:48/22:49)
- 但**存本地时崩溃**(`CharacterStore.kind_dir` 缺失)→ 图只留在可灵服务器
- 已下载到 `agent-local/runtime/ave/generated_images/`(870KB / 1297KB)并入库角色「找回的2张生成图」
## [4.16.1] - 2026-10-02
### 🔴 重大修复:本机 `ffprobe` 实为 `ffmpeg` 符号链接 → 全项目媒体探测**静默失败**
**背景**:优化"去 AI 化体积膨胀"时发现码率读取**始终返回兜底值** —— 深挖发现:
```
~/.local/bin/ffprobe -> ~/.local/bin/ffmpeg ← 竟然是符号链接!
```
**本机根本没装 ffprobe**,调用 `ffprobe -show_entries ...` 实际在调 `ffmpeg` → 报
`Unrecognized option` → **所有 ffprobe 调用静默失败**。
**影响面(严重)**:
| 模块 | 后果 |
|:--|:--|
| `beat_sync.py`(**卡点合成**) | 取时长失败 → **固定返回假值 30 秒** → 节拍对齐全错 |
| `hybrid.py`(**混合合成**) | 同上 |
| `speed_ramp.py`(变速) | 同上 |
| `ffmpeg.py`(视频尺寸探测) | 尺寸取不到 → 走目标尺寸兜底(可能裁切异常) |
| `lipsync.py` / `exporter.py` / `wan2_2.py` / `bgm_download.py` | 时长 / 校验失败 |
**修复**:`lib/ffmpeg.py` 新增**兼容探测函数**(用 `ffmpeg -i` 解析 —— 完全可用):
- `probe_info(path)` → `{duration, bitrate_kbps, size_bytes, has_audio, has_video, width, height}`
- `probe_duration(path)` · `has_audio_stream(path)`
- 批量替换 **7 处** `ffprobe` 调用(beat_sync / hybrid / speed_ramp / ffmpeg / lipsync / bgm_download / exporter / wan2_2)
**实测**:`_get_duration()` 从假值 **30.0 秒 → 真实 8.00 秒** ✓
**附带收益(去 AI 化体积)**:`de_ai` 的 CRF 改为**按源码率自适应**
(< 3000 kbps → CRF 27 / < 6000 → 25 / 否则 23)
实测:`norm_01` 2.03 → **1.25 MB(↓38%)** · `norm_02` 1.34 → **1.04 MB(↓22%)**
## [4.16.0] - 2026-10-02
### 新增:🎬 分镜可视化编辑(镜头语言**下拉选择**)
**背景**(用户反馈):"如果分镜的内容不合适,我怎么调呢?怎么才能追加?"
**原状**:分镜表可改**文字**(画面描述/台词/情绪/时长/类型),但**镜头语言是自由文本**(`近景 / 平视 / 固定 / 浅`)→ 不规范、易写错。
- **镜头语言改为 4 个下拉**(改了**直接影响生成提示词**):
| 字段 | 选项 |
|:--|:--|
| **景别** | 特写 · 近景 · 中近景 · 中景 · 中全 · 全景 · 远景 |
| **机位** | 平视 · 略俯 · 俯视 · 略仰 · 仰视 · 过肩 |
| **运动** | 固定 · 推 · 拉 · 摇 · 移 · 跟 · 环绕 · 升降 |
| **景深** | 极浅 · 浅 · 中 · 深 |
- 未选时显示灰色占位(如「景别」),选了变亮 ✓
- 实测:6 卡片 × 5 下拉 = **30 个**,选项数 6/8/7/9/5,**无 console 错误** ✓
**分镜的调整 / 追加方式(完整清单)**:
| 操作 | 方式 |
|:--|:--|
| 改画面/台词/情绪 | 直接编辑输入框 |
| **改镜头语言** | **下拉选**(本次新增) |
| 改时长 / 类型 | 数字框 / 下拉 |
| **追加镜头** | 「➕ 添加镜头」按钮 |
| 删除镜头 | ✕ |
| 调顺序 | ↑ / ↓ |
| 重生成单镜头 | 🔄 重生成(LLM 只重出这个镜头) |
| 整体重来 | 改故事 / 选项 → 「生成分镜」 |
| 修改已有分镜 | 改完点「💾 保存」 |
## [4.15.8] - 2026-10-02
### 优化:BGM 选择器**优先读资产库**(「🎵 BGM 库」上传的音频可直接被流程选用)
**背景**:发现 BGM 有**两套数据互不相通** ——
- `music_selector` 的 `music_library.yaml`(有元数据,但 `assets/bgm/` 无实际音频文件)
- 资产库「🎵 BGM 库」(用户在页面上传的音频)
→ 结论:**用户在资产库上传的 BGM 不会被流程用到**
**修复**:`_impl_music_select` 改为**两级查找**
1. **优先读资产库**(`AssetStore("bgm")`):按 `name` / `mood` / `tags` 过滤 + **扫描目录找真实音频文件**(mp3/wav/m4a/aac/flac/ogg)
2. **回落内置音乐库**(原 `music_library.yaml` 逻辑)
- 产物新增 `source` 字段(`资产库` / `内置音乐库`),便于排查
- 错误提示改为可操作:「到『🎵 BGM 库』上传音频(上传后会自动被选择器读到)」
**实测**:无资产库 BGM 时正确回落,并给出明确指引 ✓
## [4.15.7] - 2026-10-02
### 优化:Pexels 素材**并行下载**(实测提速明显)
**背景**:`basic_dub` 模板实测时素材下载耗时过长(5 段超 5 分钟仍未完成)。
**根因**:`search_videos()` 的下载循环是**串行**(逐个 `httpx.get` + 一次性读入内存)。
**修复**:改为**并行下载**(`ThreadPoolExecutor`,最多 4 路)
- 先「选取候选」(过滤时长 + 挑文件)→ 再**并行下载**(`as_completed` 收集结果)
**实测**:**5 段素材 71.2 秒完成**(此前串行超 5 分钟未完成)✓
- 分辨率优选同时生效(4 段 1080x1920 + 1 段 1080x2048)
- 个别视频无 1080p 版本时回落,由 `_normalize_clip()` 统一规格兜底
## [4.15.6] - 2026-10-02
### 修复:审核门(`audit_gate`)**切断数据流**(下游拿不到上游文本/分镜)
**背景**:实测 `audit_gate` 暂停/继续时发现 —— 暂停恢复正常,但**下游节点失败**:
`字幕生成需要上游分镜(含台词)或文本`。
**根因**:`audit_gate` 通过后只写入 `{"approved": True}`,**没有透传上游产物** →
数据流断在审核门(下游的 `ctx["inputs"]` 为空)。
**修复**(两处):
1. `_run_node()` 的 `audit_gate` 分支:`auto_approve` 直接通过时**合并上游产物**到输出
2. `resume()`:暂停恢复时**遍历入边、把上游 context 合并进审核门产物**(+ `approved` 标记)
**实测**:
```
n1 script → success
n2 audit_gate → paused ⏸️ → resume → completed(approved: true + 透传 text)✓
n3 subtitle → success(生成 2 段字幕)✓
整体: completed · 无错误
```
## [4.15.5] - 2026-10-02
### 新增:卡点变速 / 口播+卡点**混合合成**接入(此前只做普通拼接)
**背景**:审计发现 `composer/beat_sync.py`(**674 行** — 节拍检测 + 能量感知 + 帧锁定变速)与
`composer/hybrid.py`(人声静音锚点 + BGM 能量变速)**都已实现,但没接进执行器** ——
「卡点视频」「口播+卡点混合」模板实际只做了**普通拼接,没有卡点/混合效果**。
- **`_impl_video_concat` 新增合成模式分支**(按 `cfg.compose_mode`):
| 模式 | 行为 |
|:--|:--|
| (默认)`simple` | 拼接 → 去 AI 化 → 混流(人声 / BGM / 字幕) |
| **`beat_sync`** | 调 `compose_beat_sync()`:**BGM 节拍检测 → 素材分组 → 帧锁定变速卡点** |
| **`hybrid`** | 调 `compose_hybrid()`:**人声静音锚点 + BGM 能量变速 → 帧锁定拼接** |
- **两个模板启用**:`beat_sync` 模板 output → `compose_mode: "beat_sync"`;`hybrid_dub` → `compose_mode: "hybrid"`
- **顺带修复**:这两个模板的素材节点**缺关键词**(上游是 `style` 透传节点 → 无文本 → 素材搜索失败)
→ 补默认关键词(`城市 生活` / `生活 日常`,用户可改)
## [4.15.4] - 2026-10-02
### 修复:素材版成片体积失控(Pexels 原始素材未规范化)
**背景**:用 `basic_dub` 模板端到端实测(脚本 → TTS → 素材 → BGM → 合成)**5 节点全部 success** ✓
但成片 **37.9 MB**(明显偏大)。
**根因**(实测素材参数对比):
| 项 | Pexels 原始素材 | 应统一为 |
|:--|:--|:--|
| 分辨率 | `1080x2048`(非 9:16) | `1080x1920` |
| 像素格式 | **`yuv444p`**(4:4:4,体积大) | `yuv420p` |
| 帧率 | 25 fps | 30 fps |
| 时长 | **23 秒 / 17 秒**(超长片段) | ≤ 8 秒 |
→ 直接拼接 = 5 段原始素材原样累加 = 37.9 MB
**修复**:新增 `StoryboardPipeline._normalize_clip()`
- 拼接前**统一规格**:缩放裁切到目标分辨率 · 转 `yuv420p` · 统一 30fps · **裁到最长 8 秒**
- 接入 `render_from_clips()`:每片段 **先规范化 → 再去 AI 化 → 再拼接**
- 对**所有来源**生效(Pexels 素材 / 可灵生成 / 混合)
**实测**(同一批素材):**37.8 MB → 15.82 MB(缩小 2.4 倍)**,规格统一为 1080x1920 / yuv420p / 30fps ✓
## [4.15.3] - 2026-10-02
### 修复:3 个流程模板"跑不通"(缺画面来源 + 旧默认值)
**背景**:审计 6 个流程模板时发现 3 个**结构不完整**(用户点到会失败)。
| 模板 | 问题 | 修复 |
|:--|:--|:--|
| **数字人口播** | ① `voice_id` 是**旧模型名**(`cosyvoice-v3.5-plus`,会覆盖配置里的正确 model → TTS 失败)② `lip_sync` 走**透传节点**(口型未接)③ **无画面来源** → output 必失败 | 删掉旧 voice_id(用配置默认)· **补 `storyboard` + `model` 节点**(人物画面生成)· 描述标注"当前以可灵生成人物画面替代专用数字人 API" |
| **口播+卡点混合** | ① 同上旧 voice_id ② **无画面来源** | 删掉旧 voice_id · **补 `material` 素材节点**(4 段竖屏) |
| **卡点视频** | ① `mood: upbeat`(**音乐库无此风格** → 选择失败)② **无画面来源** | `mood` 改空(走热门)· **补 `material` 素材节点**(5 段) |
**复核结果(6 个模板全部完整)**:
```
✅ 基础口播 5节点 | 能力4 | 画面源有 | 跳过0 | 断边0
✅ 卡点视频 5节点 | 能力3 | 画面源有 | 跳过0 | 断边0
✅ 角色叙事 8节点 | 能力4 | 画面源有 | 跳过0 | 断边0
✅ 数字人口播 6节点 | 能力4 | 画面源有 | 跳过0 | 断边0
✅ 口播+卡点 5节点 | 能力3 | 画面源有 | 跳过0 | 断边0
✅ 短剧创作 12节点 | 能力7 | 画面源有 | 跳过0 | 断边0
```
## [4.15.2] - 2026-10-02
### 新增:补齐 2 个能力实现(`script_generate` 剧本改编 + `person_swap` 人物置换)
**背景**:能力审计发现这两个"注册了但执行器没接" → 流程里对应节点会**跳过**。
- **`script_generate`(剧本改编)** → 接入 `CAP_IMPLS`
- 故事/主题 → **结构化口播脚本**(LLM):分段 + 口语化旁白 + **每段配「画面提示」**
- 约束:开头有钩子 · 结尾有行动号召 · 保留原始信息不编造
- 实测:`我住院第三天,做了痔疮微创手术…` → **3 段脚本**
```
① 我住院第三天了,刚做完痔疮微创手术,说真的,没你们想的那么可怕。
【画面:穿着病号服躺在病床上,对着镜头说话,床头挂着输液瓶】
② 今天宋佳主任来查房,说我恢复得挺好,就叮嘱我一句——别久坐。
【画面:医生查房的背影或侧影,或病房走廊推镜头】
③ 所以有这毛病的朋友,别拖,早看早好,真的少遭罪。
【画面:坐在病床边认真对着镜头说,最后定格在病房窗外】
```
- **`person_swap`(人物置换)** → 接入 `CAP_IMPLS`
- 参考图(可直接取**角色资产的参考图**)+ 源视频 → 调百炼 `wan2.2-animate-mix` 换人
- **费用确认硬拦截**(按秒计费,需 `confirm_cost`)
- 参考图解析:节点 `ref_image` 配置,或自动从指定角色的 `reference_images` 取
**执行器已接入能力:8 → 10 个**
## [4.15.1] - 2026-10-02
### 修复:分镜"刷新后找不回"(缺「打开已保存分镜」入口)
**背景**:分镜生成后保存在后端(`runtime/ave/storyboards/`),但**前端没有打开的入口** → 刷新页面后只能重新生成(浪费 LLM 调用)。
- **后端补接口** `GET /api/ave/storyboards/{project_id}`(返回完整分镜,含 shots)
- **前端加「📂 打开已保存分镜」下拉**(显示 标题 · 镜头数 · 时长,可随时切回历史分镜)
- **页面打开时自动载入最新一个**(刷新后不丢)
- 实测:下拉 4 项 · 自动载入 `vid_20261001_215445`(6 镜头)· 分镜表渲染 6 卡片 · 无 console 错误 ✓
## [4.15.0] - 2026-10-02
### 新增:分镜→成片「过程透明化」(预览提示词 + 能力 + 中文拍摄风格)
**背景**(用户反馈):"点生成成片就直接生成了,但每个镜头用什么内容、提示词长什么样、用什么基础能力,我都没看到 —— 是不是缺东西?"
**确认缺口(用户判断正确)**:分镜表只展示画面描述/镜头契约,而**编译后的生成提示词、所用能力/引擎、参数**全部不可见;点"生成成片"直接进黑盒。
#### ① 新增「🎬 预览生成方案」按钮(**纯预览,零费用**)
- 新接口 `POST /api/ave/storyboard/preview-prompts`:**只做提示词组装与能力判定,不调用生成**
- 每个镜头展示:**生成能力** · **引擎/模型**(可灵 kling-v3)· **参数**(时长/画幅)· **是否绑定角色参考图** · **完整提示词**(六模块结构 376~424 字)
- 实测:6 镜头分镜 → 逐镜头显示提示词与能力 ✓
#### ② 拍摄风格**中文化** + 扩充到 6 种(含**自拍 / 第一人称**)
| 值 | 中文标签 |
|:--|:--|
| `documentary_realism` | 伪纪录片 · 真实自然(像随手拍的生活记录) |
| `cinematic` | 电影感 · 考究构图 |
| `vlog_handheld` | 手持 Vlog · 第一视角(边走边拍) |
| `studio_clean` | 棚拍干净 · 商业感 |
| **`selfie_pov`** | **手机自拍 · 第一人称(举着手机自己拍自己)** |
| `interview_doc` | 访谈纪实 · 半身对镜(像接受采访) |
#### ③ 能力判定逻辑(`_cap_for_shot`)
| 镜头类型 | 使用能力 |
|:--|:--|
| `talking_head` | 口播/口型(当前以图生视频 + 后期口型替代) |
| `vfx` | 视频特效(运镜/慢动作) |
| `comfyui` | ComfyUI 工作流(面部/风格控制) |
| 绑定了 `character_id` | **图生视频**(用角色参考图保住人脸一致性) |
| 其他 | 文生视频 |
**已知待补(用户提出,待确认/接入)**:
1. **4 种导演系统只接了 2 个**(legacy + v5.2)—— 另 2 种(clip-storyboard / Seedance / OpenDirector)待接入
2. **人脸表情 / 口型**暂无专用能力(`talking_head` 目前走图生视频替代)
3. **自拍/第一人称**已加拍摄风格选项,待实测生成效果
## [4.14.0] - 2026-10-02
### 修复 + 增强:角色生成器**恢复结构化字段**(10 层 61 项)+ 视角 / 引擎可选
**背景**(用户反馈):"原来有很多提醒我输入的关键词(眼睛类型、鼻子…),你现在直接变成 AI 提示词,那些都用不到了?我描述不全,AI 扩写能扩全吗?"
**根因**:上一版把角色生成器简化成"一句话 + AI 扩写",**废弃了原有的分层字段体系**(设计倒退)。
#### ① 恢复结构化字段(10 主层 + 4 子层 = 61 项,44 个下拉)
- 新接口 `GET /api/ave/assets/character-layers`:直接读 `character_generator.prompt_assembler` 的 **CHAR_LAYERS**(**复用既有设计,不重写**)
| 层 | 项数 | 示例字段 |
|:--|:--|:--|
| 🆔 核心身份 | 5 | 角色名 · 性别 · 年龄 · 种族/地域 · 世界观/时代 |
| 🗿 面部轮廓 | 4 | 脸型 · 下颌线 · 颧骨 · 额头 |
| 👁️ 五官细节 | 4 子层 14 项 | **眼型/瞳孔色/大小/眼神** · 眉型/状态/眉色 · **鼻梁/鼻头/鼻翼** · 唇型/唇色 |
| 💇 头发 | 5 | 发型 · 发色 · 长度 … |
| ✨ 皮肤与妆容 | 7 | 肤色 · 质感 · 妆容 … |
| 🏋️ 体型与姿态 | 5 | — |
| 👔 服装与配饰 | 7 | — |
| 😊 神态与表情 | 5 | — |
| 📸 光线与镜头 | 5 | — |
| 🌄 背景与场景 | 4 | — |
- **44 个下拉选择**(有预设选项,不用自己想)+ 17 个文本输入 → 大部分直接选 ✓
#### ② 视角可选(5 种)+ ③ 引擎可选
- 视角:`正面定妆照` / `全身照` / `多视角九宫格` / `场景照` / `表情特写`
- 引擎:当前 `可灵(Kling)`(图片额度需单独充值),其他引擎预留
#### ④ 流程
填字段(**都可选填**)→ 👁 预览提示词 → 选视角/引擎 → 🎨 生成(**弹费用确认**)→ **自动入库角色库**
- 提示词由后端 `CharacterPromptSystem.build_prompt(variant=...)` 组装 —— **复用 813 行既有实现**
- 🔴 修复路由冲突:`/character-layers` 被 `/{kind}` 通配路由抢走(返回空)→ 移到通配路由**之前**
- 实测:**10 层 + 61 字段(44 下拉)+ 5 视角 + 引擎选择**渲染正常,无 console 错误 ✓
### 「AI 扩写」的正确定位(架构澄清)
**字段是主体,AI 扩写是补充**:用户填关键设定(大范围),AI 在此**基础上**补细节;
而不是让 AI 凭空想象(那会偏离用户意图)。
- `prompt_assembler.build_prompt()` 按字段**精确组装**(保真)
- `characters-helper/expand-direction`(LLM)保留为**可选辅助**(想不起细节时用)
## [4.13.1] - 2026-10-02
### 新增:🛡️ 生成操作**后端强制确认**(防止任何入口绕过前端确认框)
**背景**(用户强烈反馈):"所有需要调用大模型生成的内容,特别是视频的,**你必须弹出来提醒我**" —— 之前只有前端确认框,**用 API / 脚本直接调用可以绕过**。
- **后端硬拦截**(`workflows.py::_impl_text_to_video`):调用可灵**之前**检查 `confirm_cost`,未显式传 `true` 直接拒绝(**在扣费前拦住**)
- **全局开关**:环境变量 `AVE_ALLOW_GENERATION=0` → **完全禁止生成**(想彻底锁死费用时用)
- **参数链路打通**:`/api/workflow/run` → `start_run(confirm_cost=)` → `runner` → `ctx` → 能力实现
- **前端**:用户在费用预估框点「确定」后才传 `confirm_cost: true`
- 实测:含生成节点但不传确认 → **failed + 明确提示**(**零成本验证,未调用可灵**)✓
### 📌 行为准则(AI 操作侧,本次事件的根本改进)
**任何会产生真实费用的操作(可灵生成、大模型批量调用、素材下载等),必须先向用户说明预计花费并等待确认,不得自行发起。**
—— 本次"12 条测试视频"与"反复跑流程"引发的费用担忧,根因是执行方未先确认额度。
## [4.13.0] - 2026-10-02
### 新增:🔔 全局任务通知 + 🎬 统一产物中心(生成结果**主动可见**)
**背景**(用户反馈):跑了 12 次生成,"我都不知道文件在哪,生成完不是应该有个通知吗?" —— 产物散落文件系统、页面上看不到、也没有主动提示。
#### ① 统一产物中心(`📋 生产记录` 页)
- 新接口 `GET /api/ave/artifacts`:扫描 `runtime/ave/` 下**所有**视频产物
(`renders/` 看板出片 + `workflow/` 流程各节点产物),按时间倒序 + **可直接播放的 URL**
- 前端新增「**🎬 全部生成产物**」区块:网格布局 + **每条带播放器**(9:16 适配),显示 时间/大小/来源/节点/文件名
- 实测:页面渲染 **17 个可播放视频**(今天的全部产物),无 console 错误
#### ② 全局任务通知(在任何页面都能收到)
- `inline.js` 加**全局通知器**:每 8 秒轮询「流程 runs」+「出片 renders」→ 发现**新完成** →
右上角 **toast**(✅ 成功 / ❌ 失败),带「**🎬 查看产物**」按钮直接跳转
- 首轮只登记「**完成已超 60 秒的历史**」(避免刷屏);**刚完成的仍会通知**(覆盖"页面打开时任务刚好结束")
- 流程画布 / 导演创作页在各自轮询里也会弹 toast(双保险)
#### 🔧 踩坑修复(3 个,都由实测发现)
1. **toast 函数被 tree-shake**:`showToast` 原定义在按需加载的 `productions.js` → 首页拿不到
→ 移到 `inline.js`(全局模块)
2. **通知器被 tree-shake**:纯 IIFE `(function(){...})()` 被 Rollup 判定无副作用而移除(产物里搜不到)
→ 改为 `window.initGlobalNotifier = function(){...}; window.initGlobalNotifier();`
3. **状态登记时序 Bug**:`seen.add()` 在状态检查**之前** → 首次见到 `running` 就登记,完成时被跳过
→ 改为**只在终态时登记**
- 实测:从「外部 API 触发任务」到「页面弹通知」全链路通过(含边界:页面加载 1.8 秒内启动任务也能收到)
## [4.12.3] - 2026-10-02
### 新增:🛡️ 生成类操作的**费用防护**(前端确认 + 后端硬上限)
**背景**:验证阶段连续生成了 12 条测试视频(60.5 秒),事后才发现消耗 —— 正式使用前应有拦截。
- **前端(运行前确认)**:点「▶️ 运行」时,若流程含视频生成节点,先弹出**费用预估确认**:
```
🎬 即将调用可灵生成视频
· 生成节点:1 个
· 每个最多 3 镜头(5 秒/镜头)
· 合计约 3 个镜头 = 15 秒
· 预估费用 ≈ ¥9.0 起(按 ¥0.6/秒 保守估,实际可能更高)
确认开始?(这会产生真实费用)
```
- **后端(硬上限 + 日志)**:
- 单次运行生成镜头数**硬上限 5**(`AVE_MAX_SHOTS_PER_RUN` 可调,超限直接拒绝并说明原因)
- 生成前日志打印预估:`💰 将调用可灵生成 N 个镜头(约 N×5 秒,按 ¥0.6/秒 估 ≈ ¥X)`
- 目的:避免「误点运行 → 大量扣费」;跑生成类流程时必须**明确知情**
## [4.12.2] - 2026-10-02
### 修复:旧角色生成器污染已废弃的 registry.yaml(意外写入)
**背景**:提交时发现工作区有 6 项意外改动 —— `character_registry/registry.yaml` 被写入**垃圾数据**(`【身份_2145`)+ 4 个自动备份
- **根因**:点旧「角色生成器」(`inline.js` / `c2_remote.js` 仍调 `/api/characters/generate-from-direction`,该路由在 **`app.py:420`**)→ 链路调 `character_generator.pipeline` → **`AssetRegistrar._save_registry()` 写入 `registry.yaml`**
- 而 registry **早已废弃**(账号/角色归属以 `ORACLE.yaml` 为准,见 CONSTITUTION 规则 3)→ 写入即污染仓库
- **修复**:
1. **`AssetRegistrar._save_registry()` 加开关** —— 默认**不再写入**,仅 `AVE_WRITE_REGISTRY=1` 时写(并打印提示)
2. `.gitignore` 加入 `character_registry/backups/`(自动备份不再入库)
3. **回滚**被污染的两个文件 + 删除 4 个垃圾备份
- 实测:调用 `_save_registry()` → 输出「registry.yaml 已废弃,跳过写入」且文件未被改动 ✓
**说明**:旧接口(`/api/characters/*`)保留(`c2_remote.js` 仍调用),但**不再污染 registry**;新流程(角色生成器重写版)走 `/api/ave/assets/*` ✓
## [4.12.1] - 2026-10-02
### 优化:其余资产页补齐字段建议(产品 / 道具 / 服装)
- **产品库**:`must_keep`(必保特征)→ **datalist**,8 个建议(logo 位置与大小 / 包装主色 / 瓶身盒型形状 / 标签字体 / 开盖方式 / 整体比例 / 材质质感 / 品牌色带);「一致性种子」加说明文案
- **道具库**:`structure`(结构/比例)→ **datalist**,8 个建议(长约 20cm / 可开合 / 金属拉丝质感 / 木质纹理 / 透明材质 / 便携小巧 / 大件醒目 / 带文字标识)
- **服装库**:`material`(材质)→ **datalist**,12 个建议(纯棉 / 麻料 / 真丝 / 羊毛 / 牛仔 / 皮革 / 针织 / 化纤 / 绸缎 / 灯芯绒 / 雪纺 / PU 皮)
- 实测:产品库 1 datalist + **4 个「🎨 AI 生成」按钮**(正/侧/细节/手持)· 道具库 1 + 3 · 服装库 1 + 3,**无 console 错误**
**至此资产库 10 类全部具备**:字段下拉/建议 + 上传 + **AI 生成参考图**
## [4.12.0] - 2026-10-02
### 新增:资产库「AI 生成参考图」(文生图)+ 字段下拉建议
**背景**(用户反馈):角色库/场景库的参考图只能手动上传,没有"自动生成";且场景的「光源状态/材质要点」等字段是空白输入框,不知道怎么填。
- **🎭 角色生成器重构**(原版调用**不存在的** `/api/characters/*` 接口 → "角色生成失败")
- 新流程:填角色名 + 一句话想法 → **✨ AI 扩展提示词**(LLM 生成完整定妆照描述)→ **🎨 生成并存入角色库**
- 新接口 `POST /api/ave/assets/characters-helper/expand-direction`(LLM 扩展)
- 实测扩展效果:`40岁女性医生,温和专业` → **"…面部轮廓柔和大方,眼神沉静有亲和力,深色利落短发齐耳,身穿整洁白色医生大褂,内搭浅蓝色衬衫,胸前挂工作证,神态从容温和…真实摄影风格,纯色浅灰背景,自然柔和光线,半身定妆照,高清质感"** ✓
- 失败时**不丢数据**:角色已创建,提示"可到角色库重试生成或直接上传"
- 生成哪张可选:半身定妆照 / 正面全身 / 侧面 / 背面 / 全身
- **🎨 AI 生成参考图**(后端 + 前端)
- 新接口 `POST /api/ave/assets/{kind}/{aid}/generate-image`:按资产字段**自动组装提示词** → 调可灵文生图 → 轮询 → **下载存入该槽位**(`ref_{slot}.png`)
- 支持 10 类资产(角色/场景/真实场地/产品/道具/服装…),各类型的提示词模板不同(角色=定妆照构图;场景=空间+光源+材质;产品=多角度+必选特征)
- 前端:**每个参考图槽位旁新增「🎨 AI 生成」按钮**(已有图时显示"覆盖",含 30~90 秒 loading 提示)
- 也支持传入自定义 `prompt` 覆盖自动组装
- **🔴 修复:可灵图片模型名**:`kling-v1` 图片模型**已停用**(`code 1203`)→ 改用 **`kling-v3`**(与视频同一模型名)
- 实测:`kling-v3` 提交通过 → 提示「**图片额度不足(1102)**,视频额度与图片额度分开计费」→ 需为图片单独充值
- **字段下拉建议**(`assets-common.js` 新增 `datalist` 类型 = **可下拉选也可自由填**)
- 场景库:光源状态(10 个预设)· 材质要点(10 个)· 空间拓扑(8 个)—— 全部带 placeholder 示例
- 实测:详情页 3 个 datalist + 1 个 select + **3 个「🎨 AI 生成」按钮** 渲染正常,无 console 错误
- **关于「角色生成器」**:其调用的 `/api/characters/*` 接口在后端**不存在**(旧前端残留)→ 导致"角色生成失败"。已改用「角色库 → 🎨 AI 生成」路径(见下版改造)
## [4.11.10] - 2026-10-02
### 新增:停止运行中的流程(⏹ 停止)—— 补齐运维能力
**背景**:实测时 material 节点长时间卡住(旧逻辑中文搜 Pexels + 4K 下载),**只能靠重启 Dashboard 清理**(会丢失全部运行记录)—— 缺"停止"能力
- **执行器** `WorkflowRunner.cancel(run_id)`:标记 `cancelled` → 执行器**在节点边界检查并退出**(已完成节点的产物保留)
- **接口** `POST /api/workflow/runs/{run_id}/cancel`
- **前端**:运行区新增「**⏹ 停止**」按钮(红色 + 确认框)
- 实测:启动 → 请求停止 → 状态变为 `cancelled` ✓(当前节点执行完即退出)
## [4.11.9] - 2026-10-02
### 修复:Pexels 中文关键词搜不到 + 4K 大文件下载慢(实测发现)
**背景**:用户配置 Pexels key 后首次使用,中文关键词「医院 走廊」搜索长时间无结果
- **根因 1(翻译失效)**:`_translate_query` 只是**静态词典替换**(`ZH_TO_EN` 仅覆盖几十个词),"走廊"等未收录 → 中文直接丢给 Pexels → 命中率极低 → 多轮回落累积耗时
- **修复**:改为**两级翻译** —— ① 静态词典(快、零成本)→ ② 词典未完全覆盖时**用 LLM 翻译**(DeepSeek)
- 实测:`医院 走廊` → **`Hospital corridor`**(命中 4 个候选)✓
- **根因 2(下载慢)**:`_pick_best_file` 按「分辨率越高越好」打分 → 选中 **4K(2160x3840,13MB+)** → 下载慢
- **修复**:改为**优选 ~1080x1920**(标准竖屏,够用且下载快;4K 扣分)
- 实测:下载 1080x1920(5.4MB / 6.6MB)✓
- **根因 3(回落轮数无上限)**:关键词回落可能很多轮 → **修复**:限制**最多 3 轮**
- **附带发现(环境)**:macOS 系统代理(`127.0.0.1:7892`)会让 python urllib 的 **localhost 请求也走代理 → 502**(curl 不读系统代理所以正常)→ 调试脚本需禁用代理(`ProxyHandler({})` 或 `no_proxy`)
### ✅ 完整链路验证成功(用户配置 Pexels + 阿里充值后)
```
run wf_17ccb6dc8ce3 → completed(**20 秒**,5 节点全部 success)
n1 script → n2 material(Pexels) → n3 tts(阿里) → n4 subtitle → n5 output(混流)
成片 final_muxed.mp4:3.21 MB / 12.46 秒 / 1080x1920 @30fps
· Video: h264 ✓
· Audio: aac 22050Hz ✓(**有声音**)
· 字幕已烧录(3 段,时间轴与语音对齐)
产物链:voice.wav(TTS)→ subtitles.ass → deai(去AI化)→ final.mp4 → **final_muxed.mp4**
```
**「脚本 → 素材 → 配音 → 字幕 → 成片」完整口播视频全自动生成已打通** ✓
## [4.11.8] - 2026-10-01
### 维护:能力注册表状态校准(让「能力库」页反映真实现状)
- **`lipsync`(对口型)**:
- providers 修正为**实际实现** —— 代码用的是 **fal.ai(Kling Lipsync)**,原注册表误写为火山/D-ID
- 新增 `key_ref: fal.api_key`(未配置)+ note 说明
- status:`ready → partial`(依赖未配置的 fal key)
- **`de_ai`(去 AI 化)**:`planned → ready`(已实现且被合成节点自动调用,补 `consumer` 字段)
- **`subtitle`(字幕生成)**:`partial → ready`(已接入执行器第 8 个能力,补 `consumer` 字段)
- 状态分布:**ready 20 / partial 2 / planned 3**
- partial:`person_swap`(百炼欠费)· `lipsync`(fal key 未配)
- planned:`comfyui_workflow` · `vfx_apply` · `character_3d`(尚未实现)
**能力依赖一览(需配 key 的)**:`llm.api_key`(DeepSeek,已配)· `kling.api_key`(已配)· `aliyun.api_key`(**欠费**)· `volcano.voice_app_key` / `ark_api_key` · `pexels.api_key`(**未配**)· `fal.api_key`(**未配**)
## [4.11.7] - 2026-10-01
### 修复:TTS 失败提示不明(`Connection is already closed` 掩盖真实原因)
- **背景**:完整口播流程实测时 TTS 节点失败,报错只有 `Connection is already closed`,看不出真实原因
- **根因(实测定位)**:**阿里百炼账号欠费** —— 底层 websocket 实际返回
`error_code: "Arrearage"` / `"Access denied, please make sure your account is in good standing."`,
但被 websockets 库的通用异常掩盖(之前 TTS 成功是因额度尚在)
- 影响范围:**TTS(阿里 CosyVoice)+ 人物置换(同账号百炼)**
- **修复**(`voice_synthesizer/aliyun.py`):把异常翻译成可操作提示
- `Arrearage` → 「**账号欠费** —— 到阿里云控制台充值后重试」
- `Connection is already closed` → 「连接被关闭:① 欠费 ② Key 无效/过期 ③ 网络中断 → 去「🔑 API 配置 → 🧪 测试」验证账号状态」
- `Unauthorized / 401` → 「鉴权失败 → 更新 API Key」
- 实测:提示现在明确指向欠费原因 ✓
**🔴 用户待办**:阿里百炼账号充值(同时解锁 TTS 与人物置换)
## [4.11.6] - 2026-10-01
### 升级:合成节点支持「视频 + 人声 + BGM + 字幕」混流(口播线真正闭环)
- **`_impl_video_concat` 升级**(`workflows.py`):
- ① 画面:上游片段 → 去 AI 化 → 拼接
- ② **混流**:自动收集上游 **TTS 人声**(`audio_path`)+ **BGM**(`path`,相对路径自动解析)+ **字幕**(`subtitle_path`)→ 输出带声音、带字幕的成片
- 混流失败时**降级返回纯画面成片**(不阻断流程,附提示)
- 产物新增:`has_voice` / `has_bgm` / `has_subtitle` / `muxed`
- **新增混流方法** `StoryboardPipeline.mux_final()`(`composer/pipeline.py`)
- 字幕**烧录**(`-vf ass=...`)· 人声主音轨 · BGM 压低 + 淡入淡出 + `amix` 混合
- **🔴 踩坑修复(实测发现)**:本机 **ffmpeg 6.0 在「视频重编码(libx264) + 音频映射」同一命令里会静默丢音频** —— 输出流声明了 `aac` 但编码 **0 字节**(`-c:v copy` 时才正常保留)
- 定位:3 个变体测试(无 `-pix_fmt` / 带 `-pix_fmt` / 加 `aresample`)**全部丢音轨**;换 `-c:v copy` 立即正常
- **修复**:改用**两步法** —— 第 1 步视频(烧字幕/重编码,`-an` 无音频)→ 第 2 步以 `-c:v copy` 混入音频
- 并加**音轨存在性校验**(防静默丢音轨,缺失即明确报错)
- 实测:成片 + TTS + 字幕 → 混流输出 **0.62MB**,含 **Video(yuv420p 720x1280) + Audio(aac 22050Hz)** ✓ 字幕已烧录
**已接入执行器的能力(8 个)** + **混流输出** —— 口播视频完整链路打通
## [4.11.5] - 2026-10-01
### 新增:字幕生成能力接入执行器(第 8 个能力)
- **`subtitle` 接入** `CAP_IMPLS`(`workflows.py`):
- 复用 `composer/ffmpeg.py::create_subtitles`(生成 **ASS 字幕**,竖屏 1080x1920 自适应字号/边距)
- **两种来源**:① **上游分镜**(按镜头台词 + 时间轴自动累加)② **纯文本**(按句切分,约 5 字/秒估算时长)
- 分辨率优先级:节点配置 > 分镜输出规格 > 默认 1080x1920
- 产物:`subtitle_path` + 段数 + 格式
- **命名统一**:能力 id 对齐能力注册表(`subtitle`;原映射误写成 `subtitle_generate`)
- 实测:`script → subtitle` → **success**,生成 3 段 ASS 字幕(含样式头 + 事件表)✓
**已接入执行器的能力(8 个)**:分镜规划 · 提示词生成 · 视频生成(可灵)· 视频合成 · TTS 语音 · 素材搜索 · BGM 选择 · **字幕生成**
## [4.11.4] - 2026-10-01
### 新增:BGM 选择能力接入执行器(第 7 个能力)
- **`music_select` 接入** `CAP_IMPLS`(`workflows.py`):
- 复用 `music_selector.BGMSelector`(本地音乐库 `music_library.yaml`)
- 选择方式:**关键词搜索**(`keyword`)> **按风格**(`style`/`mood`,库内取值:治愈 / 燃系 / 舒缓 / 宏大)> **默认热门**(trending)
- **文件存在性校验**:优先返回音频文件真实存在的条目;全都不存在时给出明确提示(避免下游合成才发现)
- 产物:`bgm`(选中条目)+ `path` + `style` + `bpm` + `candidates`(候选列表)
- **改进**:BGM 节点默认 `mood` 由 `upbeat`(库中无此风格)改为**空** → 默认走「热门」,开箱可用
- 实测:`bgm(style=治愈)` → **success**(命中 2 条)✓
**已接入执行器的能力(7 个)**:分镜规划 · 提示词生成 · 视频生成(可灵)· 视频合成 · TTS 语音 · 素材搜索 · **BGM 选择**
## [4.11.3] - 2026-10-01
### 新增:素材搜索能力接入执行器(第 6 个能力)
- **`material_search` 接入** `CAP_IMPLS`(`workflows.py`):
- 复用 `material_producer/pexels/search.py::search_videos`(含**中文自动翻译为英文** + **3 轮回落搜索**提升命中率 + portrait 竖屏优先)
- 关键词来源:节点 `query`/`keywords` 配置 或 **上游文本**
- 参数:`count`(数量)· `min_duration`(最短时长)· `orientation`(portrait / landscape / square)
- 产物:`clips`(本地文件路径)+ `materials`(含时长/尺寸/原始链接)
- 实测:`script → material` 流程 → n1 文本透传 success · n2 **明确报错**「Pexels API Key 未配置 → 去 🔑 API 配置」(**框架正确**,配置后即自动可用)
**⚠️ 需配置**:Pexels API Key(`pexels.api_key`,免费申请 pexels.com/api)—— 配好后口播线即可自动配画面素材。
**已接入执行器的能力(6 个)**:分镜规划 · 提示词生成 · 视频生成(可灵)· 视频合成 · **TTS 语音** · **素材搜索**
## [4.11.2] - 2026-10-01
### 新增:TTS 合成能力接入执行器(口播线的关键一环打通)
- **`tts_generate` 接入** `CAP_IMPLS`(`workflows.py`):
- 支持**火山豆包 TTS**(`voice_synthesizer/volcano.py`)与**阿里 CosyVoice**(`voice_synthesizer/aliyun.py`)
- **未指定供应商时自动选可用的**:火山(需 `access_token`)> 阿里(需 `api_key`)—— 都没有时给出明确指引
- 文本来源:本次节点 `text` 配置 或 **上游透传文本**(`script`/`story_prototype` 节点的内容)
- 产物:`audio_path`(写入 run 产物目录)+ 字数
- **修复 2 个真实问题**:
1. **火山 TTS 报 400**:代码里的 AK/SK 签名是**简化版 basic auth**(非火山真实签名),且 `appid` 传空 → 现在**明确提示**"需配 access_token(或改用阿里)",不再静默失败
2. **阿里 TTS 返回空**:节点默认 `voice_id`(旧模型名 `cosyvoice-v3.5-plus`)**覆盖了配置里的正确 model**(带项目 ID)→ 改为**配置优先**
- **产物透传补全**(`app.py`):`audio_path` / `char_count` / `provider` / `model` / `prompt` 加入摘要字段
- **前端**:节点产物预览新增**音频播放器**(显示文件名与字数)
- 实测:`script → tts` 流程 → **completed**,生成 **92KB 语音文件** ✓(阿里 CosyVoice)
## [4.11.1] - 2026-10-01
### 新增:流程入口页全部落地(占位页 → 一键加载模板到画布)
- **7 个流程入口页**(原为「待实现」占位)全部替换为**可用入口**:
| 入口 | 模板 | 节点数 | 预估成本 |
|:--|:--|:--|:--|
| 🎭 短剧创作 | `short_drama` | 12 | ¥15-50 |
| 🎙️ 基础口播 | `basic_dub` | 5 | ¥2-5 |
| 🥁 卡点视频 | `beat_sync` | 4 | ¥1-3 |
| 📖 角色叙事 | `character_narrative` | 8 | ¥10-25 |
| 👤 数字人口播 | `digital_human` | 4 | ¥3-8 |
| 🎞️ 口播+混剪 | `hybrid_dub` | 4 | — |
| ➕ 新建流程 | (空白画布) | — | — |
- **共享入口组件** `views/flow-entry.js`:展示**流程步骤链预览** + 预估成本 + 使用提示 → 点「▶️ 开始」**把模板加载到流程画布**
- 实现:写 `localStorage.wf_pending_template` → 切到 `workflow` 视图 → 画布加载时读取并自动展开模板(`workflow.js` 配合)
- 实测:短剧创作入口显示「12 个节点 + 完整步骤链 + 开始按钮」→ 点击后**画布自动加载 12 个节点** ✓ 无 console 错误
- 说明:菜单里**不再有"待实现"占位页**(视频工厂相关页面全部可用)
## [4.11.0] - 2026-10-01
### 新增(P2):编排通电 —— 工作流执行器**真跑**(节点逐个执行 + 产物预览 + 重做)
**背景**:`WorkflowRunner._execute()` 此前只做拓扑排序后把节点标记 `completed`,**没有任何节点真执行** —— 这是「点开工作流不跑」的根因。本次按 `PLANS/VIDEO_FACTORY_MASTER.md` 附录 E 完成执行器。
- **节点 → 能力映射**(`NODE_TO_CAPABILITY`):9 类能力节点绑定真实能力;5 类输入/参数节点(`script`/`story_prototype`/`strategy`/`style`/`character`)**透传**
- **能力实现**(`CAP_IMPLS`,4 个已接入):
- `storyboard_plan` → 导演系统(默认 v5.2)生成统一分镜 Schema
- `prompt_gen` → 六模块提示词编译器
- `text_to_video` → 可灵 `kling-v3` 逐镜头生成(受「镜头数」限制,**控制试跑成本**)
- `video_concat` → 去 AI 化 + 拼接成片(复用 `composer/pipeline.py`)
- 其余能力(tts / material / bgm / subtitle…)→ **明确输出 `skipped` + 原因**(不假装成功)
- **执行器重写**(`WorkflowRunner`):
- 逐节点执行 + **产物存 run context** + 上游产物自动注入下游(自动识别 storyboard / clips / prompts)
- 配置合并:**能力默认值 ← 节点 config**
- `audit_gate` → **暂停**(`paused`),等人工「⏩ 继续」
- 失败即停 + 错误明确指向节点;支持 `from_node`(从某节点起跑下游)与 `resume`(暂停恢复)
- **后端接口**:`GET /api/workflow/runs` 返回**真实运行**(原为硬编码空数组);`GET .../{run_id}` 带产物摘要;新增 `.../resume`、`.../redo/{node_id}`、`.../artifacts`
- **前端画布**(`views/workflow.js`):
- 节点**状态徽章**(完成/执行中/失败/跳过/待审核,颜色区分)
- 运行区新增「**镜头数**」输入(控制生成成本)+「⏩ 继续」按钮
- 配置面板底部:**执行状态** + **产物摘要**(含**视频预览**)+「🔄 重做此节点」+「▶️ 从此起跑下游」
- 运行后**自动轮询**(3 秒)刷新状态
- 实测:
- **框架**(零成本):`basic_dub` → script 透传 success · tts/material/bgm **明确 skipped** · output 因无上游 failed(原因清晰)✓
- **真实流程**(`script → storyboard → model → output`,限 1 镜头):n1 success → n2 **分镜生成成功** → n3 **可灵生成中** ✓
## [4.10.7] - 2026-10-01
### 修复:素材库重做(旧接口 → 通用资产组件)+ 补 `materials` 资产类型
- **修复 1(语义)**:`assets.js` 原调 `/api/assets`(矩阵养号时代旧接口),标题还是「📦 资产库」
→ 重写为「🖼️ 素材库」(通用资产组件驱动,`kind=materials`)
- 字段:类型(图片/视频/音频/其他)· 来源(自己上传/采集/AI 生成/客户提供)· 描述 + 素材文件上传预览
- 定位区分:素材库是**文件级素材**(无业务字段);结构化资产(角色/场景/产品)带业务字段(如 `must_keep`)
- **修复 2(400 错误)**:后端 `ASSET_DIRS` 白名单缺 `materials` → 素材库请求全部 400 → 已补
- 实测:页面正常渲染(搜索/筛选/空态说明)· **无 console 错误**
## [4.10.6] - 2026-10-01
### 新增:✨ 特效预设(资产库最后一块 —— 9 类资产全部就位)
- `views/ave-vfx-presets.js`(复用通用资产组件,配置驱动)
- **特效类型**:子弹时间 / 环绕运镜 / 慢动作 / 焦点锁定 / 自定义
- **字段**:运镜参数(可灵 `camera_control` 六轴 horizontal/vertical/pan/tilt/roll/zoom)· 提示词后缀 · 建议时长 · 效果预览图
- 规范依据:《DCS 说明书 v2.0》第八节(特效运镜库)
- **资产库至此 9 类全部可用**:🧑 角色 · 🏞️ 场景 · 🏙️ 真实场地 · 📦 产品 · 🧰 道具 · 👗 服装 · 🔊 音色 · 🎵 BGM · 💥 音效 · ✨ 特效预设
- 实测:页面正常渲染(搜索 / 筛选 / 空态说明)· 无 console 错误
## [4.10.5] - 2026-10-01
### 新增:⚙️ 视频工厂设置(全局默认:去AI化 / 输出规格 / 渲染)
- **设置页** `views/ave-settings.js` + 后端 `GET/POST /api/ave/settings`
- **🎨 去 AI 化**:启用开关 · 模糊 sigma · 颗粒强度 · 饱和度偏移 · 色温 · 输出 CRF(每项带说明与默认值提示)
- **📐 输出规格**:分辨率(竖屏/方形/横屏)· 帧率 · 码率
- **⚡ 渲染**:并发出片数 · 可灵默认模型 · 单镜头时长
- 保存 / 恢复默认 · 页面显示配置文件路径
- 存储:`agent-local/tools/ave/config/settings.yaml`(本机生效、不进 git)
- 后端实现要点:**白名单键**(防写入未知字段)+ **按分组深度合并**(只改传入的项,其余保留)
- 实测:GET 返回默认值 ✓ · POST 保存(blur 0.4→0.6 / 并发 3→2)✓ · 读回正确且其他项未动 ✓ · 文件落盘 ✓ · 恢复默认 ✓
## [4.10.4] - 2026-10-01
### 新增:能力中心补齐(🔌 供应商管理 + 🧪 能力试跑)+ 密钥状态修复
- **🔌 供应商管理页**(`views/ave-providers.js`)
- 按能力汇总**所有可选供应商**:🟢 默认标记 / ✅⚠️ 密钥状态 / 模型名 / 密钥字段(如 `kling.api_key`)
- 分类筛选 · 一键「设为默认」· 顶部指引(密钥去哪配、参数去哪改)
- 实测:25 个能力、**39 个供应商**(密钥已配 18)、6 个分类
- **🧪 能力试跑页**(`views/ave-test-cap.js` + 后端 `POST /api/ave/capabilities/{id}/test`)
- **先「🔍 预检」后「▶️ 真跑」**:预检**零费用**(解析将用的供应商/模型/合并参数/密钥状态),确认无误再真跑(二次确认 + 费用提示)
- 真跑已接入:文本/图片 → 视频(可灵);其余能力返回"预检通过 + 实现未接入(附实现位置)"
- 实测:预检正常显示供应商/模型/参数/密钥状态;`text_to_video` → 可灵 kling-v3
- **产物预览接口** `GET /api/ave/file?path=`(**仅限 ave 产物/资产目录**,防目录穿越 —— 实测 `/etc/passwd` 被拒 403)
- **🔴 修复:密钥状态误判为未配置**(`capabilities/__init__.py`)
- 根因:代码读 `api_key_ref` 字段,而 `capabilities.yaml` 里用的是 **`key_ref`** → 全部返回"未配置"
- 修复:兼容两种字段名 → 实测 **27 个需密钥的供应商中 18 个已配**(可灵/火山/百炼 ✅)
## [4.10.3] - 2026-10-01
### 调研:可灵模型清单核对(图片 vs 视频)—— 图片接口报错疑同因
排查「图片接口报 1102 余额不足、但视频接口可用」时,核对官方定价页得到的**模型清单**:
| 类别 | 可用模型(官方定价页) | 计费 | 我们的状态 |
|:--|:--|:--|:--|
| **图片** | **Kling Image 3.0 / 3.0 Omni**(文生图+图生图,1K/2K,omni 支持 4K)· **Kling Image O1** · **Kling Image 2.1**(文生图 4 积分 / 图生图 8 积分 / 多图参考 16 积分) | 8 积分(¥0.2)/张 | ⚠️ **API `model_name` 待确认**(旧的 `kling-v1` 图片模型已停用 —— 与视频 `kling-v1`→`kling-v3` 是同类问题) |
| **视频** | **Kling 3.0 / 3.0 Turbo / 3.0 Omni**(含动作控制、有声/无声)· Avatar(数字人) | 0.6~3.0 积分/秒 | ✅ **已用 `kling-v3` 验证可用**(19 条任务记录) |
| 其他 | 动作控制 · 对口型 · Avatar 数字人 · 虚拟试穿(新版)· 文生音效 / 视频生音效 / 音色定制 | 按次/按秒 | ⚪ 待接入(可扩展能力注册表) |
**结论与待办**:
- 图片接口的 1102 报错**很可能也是模型名过期**(与视频同因,非余额)—— 官方文档为 SPA,`model_name` 参数值未能抓取;**未做试错调用(避免扣费)**
- **角色定妆照生成**(`character_sheet.py` / 资产库"生成"入口)需先确认图片 `model_name`(建议用官方控制台或 Dashboard「🔑 API 配置 → 🧪 测试」确认后填入)
- 视频侧另有 **Avatar(数字人)** 与 **对口型** 能力可扩展 —— 正好对应流程里的「数字人口播」
## [4.10.2] - 2026-10-01
### 新增(P3 续):资产库全类型落地(8 类资产页 + 配置驱动通用组件)
- **通用资产组件** `views/assets-common.js`(418 行,配置驱动)
- 一套 UI 覆盖全部资产类型:搜索(防抖)+ 筛选(按类型自定义)+ 排序 + **卡片/表格视图**(记忆)+ **详情抽屉**(编辑字段 + 上传参考图/音频 + 删除 + 引用提示)
- 各资产页只需约 25 行配置(`kind` / `refKeys` 参考图槽 / `filters` 筛选项 / `editFields` 编辑字段)
- 音频类资产(音色/BGM/音效)自动无图槽、提供音频上传与播放
- **8 类资产页面**(按《DCS 说明书 v2.0》第五节字段规范配置)
| 资产 | 参考图槽 | 特有字段 |
|:--|:--|:--|
| 🏞️ 场景库 | 全景/细节/光线 | 空间类型 · 光源状态 · 材质要点 · 空间拓扑 |
| 🏙️ 真实场地 | 全景/细节/光线 | 地址 · 实拍要点 |
| 📦 产品库 | 正/侧/细节/手持 | 类别 · **must_keep 必保特征** · 一致性种子 |
| 🧰 道具库 | 正/侧/细节 | 持用状态 · 新旧状态 · 结构比例 · 可见面 |
| 👗 服装库 | 正/背/细节 | 季节 · 材质 · 关联角色 |
| 🔊 音色库 | (音频) | 性别 · 来源 · **供应商音色 ID** |
| 🎵 BGM 库 | (音频) | 情绪 · 节奏 · 时长 · 版权 |
| 💥 音效库 | (音频) | 类别 · 时长 · 建议插入位置 |
- 后端 `ave_assets.py` 已支持全部 10 类资产(无需改动)
- 实测:8 个页面全部正常渲染(标题/统计/搜索/筛选/视图切换/空态说明)· 新建场景 → 详情抽屉(3 上传槽 + 各字段)· 无 console 错误
## [4.10.1] - 2026-10-01
### 新增(P3):资源库落地 —— 角色库完整实现(数据层 + 接口 + 前端)
按《DCS 说明书 v2.0》第五节目录规范实现,替代旧的 `character_registry`(单 yaml、无筛选、无分类)。
- **数据层** `09_ave/scripts/assets_manager/__init__.py`
- `AssetStore`:通用资产仓库(列表/搜索/筛选/排序/CRUD/上传文件/软删除到 `_trash/`)
- `CharacterStore`:角色特化 + 统计(按类型/用途/有音色)
- `migrate_from_registry()`:旧 14 角色 → 新目录结构(保留全部原字段)
- **目录规范**(按 DCS 第五节):`agent-local/tools/ave/assets/characters/{id}/`(`meta.json` + `ref_*.png` + `voice_sample.mp3`)
- **后端接口** `routes/ave_assets.py`(10 端点,支持 10 类资产)
- `GET/POST/PATCH/DELETE /api/ave/assets/{kind}[/{aid}]`
- `GET .../stats` · `POST .../{aid}/file`(上传)· `GET .../{aid}/file/{name}`(预览,防目录穿越)
- `POST /api/ave/assets/migrate`(迁移旧数据)
- `{kind}` = characters / locations / real_locations / products / props / wardrobe / voices / bgm / sfx / vfx_presets
- **前端角色库** `views/characters.js`(138 → 404 行,完全重做)
- **搜索**(名字/标签/描述,防抖 300ms)+ **筛选**(类型/用途/标签/有音色)+ **排序**(最近更新/名字/使用次数)
- **卡片视图 / 表格视图**(记忆用户选择)
- **详情抽屉**:编辑(名字/类型/用途/标签/描述)+ **上传参考图**(正/侧/背/全身)+ **上传音色** + 删除 + 引用提示
- **新建角色** → 创建后直接打开详情补图
- 实测:迁移 14 角色 ✓ · 搜索「程序」命中「阿远」✓ · 筛选 type=anime ✓ · 详情抽屉(5 个图/上传元素 + 音色区)✓ · 无 console 错误
## [4.10.0] - 2026-10-01
### 重构(P1):视频工厂菜单按新架构重组(一级 4 块 / 二级具体项)
**背景**:架构对齐用户设计文档后,此前"资产/创作/编排/配置"四组平铺的结构不符合实际心智(导演创作只是一条流程;人物置换也是流程不是资产)。本次按 `PLANS/VIDEO_FACTORY_MASTER.md` 第二节重组。
- **新菜单结构**(`nav-menu.js`,单点定义)
- `📦 视频工厂 · 资源库`(12 项):角色库 · 角色生成器 · **场景库** · **真实场地** · **道具库** · **产品库** · **服装库** · 素材库 · **音色库** · **BGM 库** · **音效库** · **特效预设**
- `🎞️ 视频工厂 · 流程`(10 项):导演创作 ★ · **短剧创作** · **基础口播** · **卡点视频** · **角色叙事** · **数字人口播** · **口播+混剪** · 人物置换 · 流程画布 · **新建流程**
- `🧩 视频工厂 · 能力中心`(3 项):能力配置 · **供应商管理** · **能力试跑**
- `📊 视频工厂 · 运营`(4 项):生产记录 · **费用统计** · **历史操作** · **设置**
- (原「视频·资产/创作/编排/配置」四组已移除;`工作流` 改名「流程画布」,`能力库` 改名「能力配置」)
- **20 个占位页**(P1 骨架):新建页面先占位,明确标注「待实现」+ **规划内容**(按 DCS 文档第五/七节与用户需求),指向架构文档
- **视图注册**:`view-registry.js` 注册 20 个新视图
- 实测:菜单 4 组渲染正常 · 占位页全部可打开(标题 + 规划内容)· 无 console 错误
**说明**:本次**只动菜单/入口,不碰任何逻辑**。P3(资源库落地)与 P2(流程通电)随后按序进行。
## [4.9.8] - 2026-10-01
### 文档:视频工厂架构重构 v2.0(按实际使用需求重新梳理,纠正此前的结构错误)
- **新增 `PLANS/VIDEO_FACTORY_MASTER.md`**(**唯一权威架构文档**,289 行)
- **三层模型**:流程(做事入口)· 能力(零件,可替换/可配模型)· 资产(原料库)
- **纠正此前的结构错误**:
- 「导演创作」是**一条流程**(不是独立板块,与口播/卡点/短剧同级)
- 「人物置换」也是**一条流程**(选人→换人),不属于资产
- 「工作流」= 流程本身(画布是流程的编辑/查看形式)
- 菜单不按"资产/创作/编排"平铺,改按「流程 / 能力 / 资产 / 辅助」四大块
- **流程清单 8 条**(6 条原有 + 导演创作 + 人物置换),每条标注现状与待修
- **执行与审查机制**(用户核心需求):逐步模式 / 自动模式 · 每节点产物预览(文本可编辑 / 音频图视频可播放重做)· 改配置后「🔄 重做」· 「从某节点起重跑下游」
- **节点配置体系**:能力默认值 → 流程级 → 节点级(三来源全暴露)· 供应商 + 模型独立下拉 · 节点可「替换能力」
- 后端 6 层架构 + 现有代码映射(复用/改造/重写)+ **P1~P7 改造计划**
- **归档旧文档** → `90_archive/video_factory_docs_20261001/`(含归档说明,标注失效部分与仍可参考部分)
- **现状确认(重要)**:`workflows.py` 的 6 条流程模板**结构完整**(15 种节点定义、画布 UI、节点配置面板),但 `WorkflowRunner._execute()` **只做拓扑排序后标记 completed**,**没有任何节点真正执行** —— 这是"点开工作流不跑"的根因,P2 阶段重写执行器
## [4.9.7] - 2026-10-01
### 新增:可灵 Webhook 回调支持(验签 + 自动转存产物)
**参考**:可灵官方回调协议文档(`klingai.com/document-api/api/get-started/callbacks`)
- **验签模块** `09_ave/scripts/lib/kling_webhook.py`
- 按官方规范实现:签名串 `{webhook-id}.{webhook-timestamp}.{rawBody}`,密钥 `base64Decode(secret 去 whsec_ 前缀)`,签名 `base64(HMAC-SHA256(key, 签名串))`
- **常量时间比较**(`hmac.compare_digest`)防时序攻击 · **±5 分钟时间窗**防重放 · 支持多签名头(`v1,a v1,b` 任一匹配)
- `parse_callback()`:解析回调 body(`id`/`status`(submitted|processing|**succeeded**|failed)/`outputs[]`)
- secret 来源:环境变量 `KLING_WEBHOOK_SECRET` > `agent-local/.../local.yaml → kling.webhook_secret`
- **回调端点**(`routes/ave.py`)
- `POST /api/ave/kling/callback`:验签(失败 401)→ 解析 → 落盘 `agent-local/runtime/ave/callbacks/<task_id>.json` → **后台自动转存产物**(因官方提示生成资源 **30 天后清理**)
- `GET /api/ave/kling/callbacks`:最近回调记录(排查用)
- `GET /api/ave/kling/webhook-info`:配置状态(脱敏,不回显 secret)
- **配置页新增字段**:`kling.webhook_secret`(可在 Dashboard → 🔑 API 配置 管理)
- **安全**:secret 仅存 `agent-local/tools/ave/config/local.yaml`(**600 权限、不进 git**,已核验)
- 实测:验签 6 项自测全过(正确通过/篡改拒绝/过期拒绝/多签名/解析)+ 端点 3 项(合法 200 / 错误签名 401 / 缺头 401)全过
⚠️ **使用前提**:可灵服务器需能访问回调地址(**需公网可达**)。当前 Dashboard 在局域网(192.168.31.102)+ Tailscale(100.111.43.6,私有网络)→ 可灵无法直连;如需启用 webhook:路由器端口映射本机公网 IP,或用 `tailscale funnel` 暴露。**在此之前继续用轮询(已稳定工作,不依赖回调)**。
## [4.9.6] - 2026-10-01
### 新增:六模块提示词编译器(整合成熟方法论)+ 合格成片确认闭环
- **六模块提示词编译器**(`composer/pipeline.py::build_shot_prompt` 重写)
- 按 **ai-film-skills / produce-ai-video / `references/storyboard-prompt-compiler.md`** 的母提示词方法论重构
- 六模块结构:**① 生成任务**(时长/类型/画幅/机位方式)· **② 主要主体**(角色/服装/动作/表演)· **③ 场景状态**(地点/光源依据/镜头语言/道具)· **④ 情绪目标** · **⑤ 视觉风格**(拍摄风格 + **负向约束**:不要运镜特效痕迹/AI 塑料质感/字幕水印/快速变焦)· **⑥ 分段脚本**(景别/机位/摄影机/景深/光学/画面动作/台词)
- 实测:v5.2 分镜 → 每镜头提示词约 470~530 字(原为逗号拼接的短句),信息完整度显著提升
- **交付状态闭环**:新增 `POST /api/ave/storyboard/render/{job_id}/review`
- 用户确认「已完整播放审查」→ 交付状态由「候选成片」升级为「**合格成片**」
- 校验:任务未完成(400)/ 存在失败镜头(400)/ 任务不存在(404)
- 前端:候选成片(无失败)后显示「✅ 我已完整看过(标记合格成片)」按钮
- 严格遵循方法论:**未经完整播放审查不得称合格**
- **方法论库入库**:`ai-film-skills` 的 **129 个 `references/`** 文档(六模块编译器 · 设计记忆协议 · 摄影设计引擎 · 合格成片验收 · 十二项完成门 · 构图与轴线 · 运镜诊断 …)
## [4.9.5] - 2026-10-01
### 优化:逐镜头**并发生成**(出片提速 3.4 倍)+ 体积再降
- **⚡ 并发生成**:`StoryboardPipeline.render(max_workers=3)` 默认 3 路并发调用生成引擎
- **实测:3 镜头出片 6.5 分钟 → 1.9 分钟(提速 3.4 倍)**
- 并发结果**按镜头序号归位**(`clips_by_idx` + 锁),保证成片顺序与分镜一致(实测片段顺序 01→02→03 ✓)
- 单镜头失败不影响其他镜头(互不阻塞)
- **📦 体积优化叠加**:并发测试成片 **3.2 MB**(对比优化前 39.6 MB,**缩小 12 倍**)
- CRF 23 + 并发 = 单段约 1.0~1.3 MB(原 11.9~14.3 MB)
- **交付状态生效**:并发测试返回「候选成片 | 已生成拼接,尚未完整播放审查」✓(诚实标注,未夸大为合格)
## [4.9.4] - 2026-10-01
### 新增:看板「一键出片」闭环(前端 → 后端 → 生成 → 成片)+ 去 AI 化体积优化
- **🎬 前端一键出片**(`views/ave-director.js`)
- 分镜表新增「🎥 生成成片」按钮(原为占位,点击无反应)→ **真实出片**
- 确认框显示镜头数与预计耗时 → 启动后**进度条 + 实时日志**(generate / deai / concat 每步状态)
- 完成后显示**交付状态徽章** + 成片路径 + 段数/时长;失败显示原因与失败镜头清单
- 修复命名冲突:原 `_sbRender()`(渲染分镜表,模块内)与出片函数重名 → 出片改名 `_sbRenderVideo`,并撤销 3 处误改调用
- **后端出片接口**(`routes/ave.py`,3 个端点)
- `POST /api/ave/storyboard/render`:**后台线程**执行出片(分镜 dict 或 project_id),立即返回 `job_id`
- `GET /api/ave/storyboard/render/{job_id}`:进度轮询(进度数组 + 状态 + 成片路径 + 交付状态)
- `GET /api/ave/renders`:出片历史
- 产物落盘:`agent-local/runtime/ave/renders/<job_id>/`(含各镜头片段 + 去AI化片段 + final.mp4)
- **🔧 去 AI 化体积优化**:`DEFAULT_CRF 18 → 23`
- 实测:同一镜头 `3.16MB → 0.97MB`(**不再是"去AI化后膨胀 4 倍",反而缩到 1/3**,视觉几乎无差)
- **交付状态三级标注**(整合 produce-ai-video 验收方法论)
- `Storyboard` 新增 `delivery_status` / `delivery_note`
- `合格成片`(全镜头成功 + 已完整播放审查)/ `候选成片`(可播放但有失败镜头或未经审查)/ `未完成/待验证`
- **诚实原则**:未经完整播放审查的成片一律标为「候选成片」,不夸大为合格
- 实测:看板接口启动 → 后台出片 1 镜头 → 进度 6 步实时更新 → 成片落盘 `final.mp4`(968KB / 5 秒)✓ 无失败
## [4.9.3] - 2026-10-01
### 新增 + 重大修复:可灵视频生成引擎接入(找出"不能用"的真正原因:模型名过期)
- **🔴 根因(重要)**:可灵 **`kling-v1` / `kling-v1-5` / `kling-v1-6` / `kling-v2` / `kling-v2-1` / `kling-v2-master` 均已停用或不支持**(`code:1203` / `1201`),
**可用模型是 `kling-v3`** → 这是"充值了却用不了"的真正原因(**不是余额问题**)
- 实测:`kling-v3` 提交成功(`code:0`)→ 任务 6 次轮询后 `succeed` → **5.04 秒视频生成成功、下载 4.65MB**
- **可灵视频生成能力** `05_tools/09_ave/scripts/capabilities/kling_video.py`(新增,222 行)
- `KlingVideoClient`:文生视频(`/v1/videos/text2video`)/ 图生视频(`/v1/videos/image2video`)+ 任务轮询 + 下载
- 鉴权:`api_key`(Bearer)优先 → `access_key + secret_key`(JWT HS256)回退
- **错误分类明确**:余额不足(1102)/ 鉴权失败(1101)/ 模型停用(1203)分别给出可操作提示
- 下载兼容:签名 URL(含 `cacheKey`)免鉴权优先,401/403 时带鉴权重试
- **接入流水线**:`composer/pipeline.py::_generate_shot()` 默认调用可灵引擎;新增 `build_shot_prompt()`(分镜 → 生成提示词:画面 + 镜头契约 + 情绪 + 全局锚点 + 去AI化倾向)、`_aspect_ratio()`(按输出分辨率推断 9:16 / 16:9)
- **能力注册表更新**:`text_to_video` / `image_to_video` / `text_to_image` 的 kling 模型名 → **`kling-v3`**;`text_to_video` 状态 `planned → ready`,补 impl 与实测来源
- **外加:ai-film-skills 完整技能包入库**(Apache-2.0)
- **18 个技能包**(324KB)下载入库 `09_ave/skills/ai-film-skills/skills/`
- 重点包:`ai-short-drama-production`(11KB AI 短剧制作)· `produce-ai-video`(8.4KB 视频制作)· `character-asset` / `scene-asset` / `prop-asset`(15KB/15KB/13KB 资产规范)· `director-agent`(10.8KB)· `ai-storyboard-director`(6.5KB v5.2 分镜)· 7 个题材风格包(cyberpunk/epic/fantasy/horror/noir/romance/wuxia)· 2 个数据包
- 仓库根文档:`SKILL_CATALOG.md` / `INSTALLATION.md` / `COMPATIBILITY.md` / `docs/WORKFLOW.md`
## [4.9.2] - 2026-10-01
### 新增:AI Storyboard Director v5.2 技能入库并启用(导演可切换验证成功)
- **技能文档入库** `09_ave/skills/ai-film-skills/docs/skills/zh-CN/`(Apache-2.0)
- `ai-storyboard-director.md`(v5.2 分镜导演,7.1KB)← 核心
- `director-agent.md`(编剧与导演)、`character-asset.md` / `scene-asset.md` / `prop-asset.md`(资产规范)
- 获取方式:命令行走不通时用浏览器下载 zip(GitHub 网络限制,已在 `skills/README.md` 写明两条路径)
- **v5.2 导演自动启用**:`storyboard_v52.py` 检测到技能文档 → `available=True` → 前端导演下拉由置灰变可选
- **实测对比(同一故事 / 4 镜头 / 20 秒)**:
| 维度 | legacy(简单提示词) | **v5.2(技能方法论)** |
|:--|:--|:--|
| 画面描述 | 一句话 | **完整场面调度**(手机支架位置、光线来源、景深层次) |
| 镜头契约 | 有 | **精细**(近景/平视略俯/固定/景深浅) |
| 情绪 | 单词 | **完整描述**("平静、略带疲惫但放松,像跟朋友随口聊天") |
| 连续性 | — | **跨镜头承接**("同一病房,镜头位置不变,我从半躺调整成坐直") |
| 镜头设计 | 机械分配 | **按内容选**(查房用"过肩中景";下地走用"床尾高度跟拍全景") |
- 验证了框架核心设计:**换导演系统,下游完全不用改**(同一 `generate()` 契约,输出统一 Schema)
## [4.9.1] - 2026-10-01
### 修复 + 新增:FFmpeg 路径统一(合成链此前**从未跑通**的根因)+ 分镜→成片流水线
- **🔴 修复:FFmpeg 路径**(`lib/ffmpeg.py` 新增)
- **根因**:本机 FFmpeg 装在 `~/.local/bin`(非 brew,不在 PATH),但 `composer/ffmpeg.py` 等模块用裸 `subprocess.run(["ffmpeg", ...])` → **合成类功能一直失败**
- 修复:新增 `lib/ffmpeg.py`(统一解析 `FFMPEG` / `FFPROBE` 绝对路径),批量替换 **37 处**裸命令(`composer/ffmpeg.py` 14 + `beat_sync.py` 11 + `hybrid.py` 7 + `speed_ramp.py` 5)
- 实测:`concat_segments()` 拼接成功(FFmpeg 路径解析为 `/Users/.../.local/bin/ffmpeg`)
- **新增:分镜 → 成片流水线** `composer/pipeline.py`(S2-6)
- `render_from_clips()`:已有片段 → 去AI化 → 拼接 → 成片(**可独立使用/测试**)
- `render()`:分镜 → 逐镜头生成 → 去AI化 → 拼接 → 成片(支持 `generate_fn` 注入引擎;进度回调 `progress_cb`)
- 逐镜头状态回写(`shot.status` / `artifact` / `error`),部分失败不中断(**失败镜头跳过,其余照常出片**)
- 实测:3 镜头完整管道 → 去AI化 3 段 → 拼接 → 成片 10.5MB,进度事件 14 条全通 ✓
- 生成环节:`_generate_shot()` 未接引擎时**报明确错误**(指引去「🧩 能力库」配供应商),引擎就绪即自动可用
## [4.9.0] - 2026-10-01
### 新增:S2 导演创作 —— 故事 → 分镜 → 可编辑(统一分镜 Schema 落地)
**框架**:`PLANS/VIDEO_FACTORY_FRAMEWORK.md` S2 阶段。核心是让「统一分镜 Schema」成为中枢:任何导演系统输出它,下游(编排/能力/执行)全不用改。
- **统一分镜 Schema** `09_ave/scripts/schemas.py`(**14 个 pydantic 模型**,按 DCS 第四节)
- `Storyboard` / `Shot` / `GlobalAnchors` / `ShotContract` / `VFXConfig` / `ExpressionDetail` / `SFX` / `AudioConfig` / `Subtitle` / `Transition` / `Speed` / `ColorConfig` / `PostProcess` / `OutputConfig`
- 便捷方法:`total_duration()` / `shot_by_id()` / `reindex()` / `to_dict()` / `from_dict()` / `save()` / `load()` / `summary()`
- 与现有 `scene_planner` 双向互转:`scenes_to_storyboard()` / `storyboard_to_scenes()`
- **导演适配器框架** `09_ave/scripts/directors/`(**替换点①**)
- `base.py`:`BaseDirector`(唯一契约 `generate(story, anchors, options) -> Storyboard`)+ 通用选项
- `llm.py`:导演层共用 LLM 客户端(三级配置优先级 + 熔断 + JSON 容错解析)
- `legacy_scene_planner.py`:**本地导演**(LLM 直出分镜,含镜头契约 + 单镜头重生成)
- `storyboard_v52.py`:**AI Storyboard Director v5.2**(技能型导演:读技能文档作系统提示词 + 先锁视觉概念再拆镜头;**文档未就位时自动标记不可用**,前端下拉置灰)
- `__init__.py`:注册表(`get_director` / `default_director` / `list_info`),**加新导演只改这里一处**
- **去 AI 化处理链** `09_ave/scripts/composer/de_ai.py`(DCS 第八节)
- 滤镜链:`gblur → noise → eq saturation → curves → colortemperature`(默认 模糊0.4 / 颗粒12 / 饱和-0.12 / 色温5300K)
- FFmpeg 绝对路径探测(本机 `~/.local/bin`)+ `apply_to_storyboard()` 按分镜配置处理
- **后端接口** `routes/ave.py` 扩展:`GET /api/ave/directors`、`POST /api/ave/storyboard/generate|revise|save`、`GET /api/ave/storyboards`
- **前端「🎬 导演创作」页** `views/ave-director.js`(菜单新增 `🎞️ 视频·创作` 组)
- 导演下拉(显示 kind/可用性/特性)+ **按导演 options_schema 自动生成选项**(镜头数/时长/风格…)
- 故事输入 + 全局锚点(角色/地点/一致性种子)
- **分镜表**:逐镜头可改(画面描述/镜头契约/台词/情绪/时长/类型)、🔄 单镜头重生成、删除、上下移、➕ 加镜头、💾 保存
- 实测:Schema 构造/JSON往返/格式互转/reindex ✓;legacy 导演真实出 5 镜头(镜头契约专业:近景/平视/固定/景深浅)✓;去 AI 化 FFmpeg 实测成功 ✓;接口出 4 镜头 20 秒 ✓;前端生成 6 镜头 30 秒渲染无错 ✓
- ⚠️ **待解决**(外部依赖,非代码问题):① 可灵仍报余额不足(`code:1102`,充值未到账?)② 火山方舟即梦模型名待确认(需控制台开通)→ 解决后即可跑通「分镜 → 逐镜头生成 → 去AI化 → 拼接 → 成片」
## [4.8.1] - 2026-10-01
### 优化:视频工厂菜单重组 + 能力库信息详细化 + 空壳目录清理
- **菜单重组**(消除"散乱"):原 `🎬 视频工厂` 9 项平铺 → 拆为 3 个清晰分组
- `📦 🎬 视频·资产`:角色库 / 角色生成器 / 素材库 / 人物置换
- `⚙️ 🎬 视频·编排`:工作流 / 能力库 / 生产记录 / 费用分析
- `🔧 🎬 视频·配置`:能力总览(原「能力目录」,与「能力库」区分:总览=只读,能力库=可编辑注册表)
- `🎬 视频·创作`(导演创作/口播/卡点…)待 S2 建立页面后加入
- **能力库信息详细化**(说人话):
- 顶部三句话讲清:🔑 **密钥在「⚙️ 服务 → 🔑 API 配置」配**、🤖 **模型由供应商决定可覆盖**、➕ **加能力只改 yaml**
- 每个供应商旁标明**密钥配置字段**(如 `volcano.voice_app_key`)+ 多供应商列出全部可选
- **输入/输出分区中文化**:`📥 输入:文本内容(text)· 情绪(emotion,可选)` / `📤 输出:音频文件(audio_path)· 时长(duration)`
- 补充:执行方式(本地线程 / 远程 guardd)、实现位置、来源
- **能力注册表补全**(25 个能力):修正 `tts_generate` 实现位置(→ `voice_synthesizer/` 391 行);新增 `script_generate` 脚本生成(`script_generator/` 377 行)
- **清理空壳目录**:7 个早期编号目录(`01_director_parser` … `07_service_layer`,均 0 行)**归档**到 `90_archive/ave_legacy_numbered_dirs_20261001/`(含 README 说明);确认实现都在无编号目录
- **标注废弃**:`agentos/plugins/ave.py` 引用的 5 个脚本路径全部不存在(本来就跑不通)→ 文件头加废弃说明并指向真实入口(`main.py` / `video_factory.py` / Dashboard)
## [4.8.0] - 2026-10-01
### 新增:视频工厂「🧩 能力库」—— 能力注册表(S1 落地)
**背景**:视频工厂框架对齐(见 `PLANS/VIDEO_FACTORY_FRAMEWORK.md`),S1 = 建立「能力真相源」。
此前能力散落后端代码/架构文档/外部 API 四处,无统一清单,导致"越堆越乱"。
- **能力注册表** `05_tools/09_ave/config/capabilities.yaml`(**能力真相源**,460 行)
- **24 个能力**分 5 类:音频 6 / 视觉 5 / 视频 4 / 分析 5 / 外部 4
- 每个能力含:`input`/`output` 契约、`params_schema`(自动生成配置 UI)、`providers[]`(**多供应商可选**)、`defaults`、`execution`(本地/远程)、`impl`(实现位置)、`status`(ready/partial/planned)、`source`
- 密钥只存引用(`api_key_ref` → 指向「🔑 API 配置」页),本文件不含密钥
- 状态现状:✅ 可用 17 / 🟡 部分 2 / ⚪ 规划中 5
- **加载器** `09_ave/scripts/capabilities/__init__.py`
- 查询(all/get/by_category/providers_of)+ 修改(set_default 改供应商/模型、set_param_default 改参数默认值,含范围 clamp 与枚举校验)+ 密钥配置状态检查(不读密钥内容)
- **后端接口** `10_dashboard/routes/ave.py`(`/api/ave/*`)
- `GET /capabilities`(列表 + 密钥状态)|`POST /capabilities/{id}/default`|`POST /capabilities/{id}/param`|`GET /capabilities/maintenance`
- **前端「🧩 能力库」页** `views/ave-capabilities.js`(菜单:视频工厂 → 🧩 能力库)
- 统计徽章(总/可用/部分/规划)· 分类 Tab · 能力卡片(供应商下拉含 🔑 状态、模型、参数表单按 schema 生成)
- 编辑 → 💾 保存(落盘 yaml 即时生效,全流程共用)· 底部提示可清理的空壳目录
- 实测:接口读 24 能力 ✓;改默认供应商/参数落盘 ✓;越界 clamp(99 → 上限 2)✓;非法枚举 400 ✓;前端 24 卡片渲染 + 编辑保存 + 无 console 错误 ✓
## [4.7.1] - 2026-09-25
### 修复:账号中心远程账号昵称/粉丝"消失"(guardd profiles 查询超时被静默吞掉)
- **现象**:账号中心里 5kecheng / 7kecheng 的账号(41 个)昵称、粉丝全部为空,只有本机 15 个正常
- **根因**(`dashboard.err` 实证):
```
guardd_api GET http://100.72.182.121:9090/accounts/profiles -> timeout
guardd_api GET http://100.65.35.28:9090/accounts/profiles -> timeout
```
`_guardd_api` 走 raw socket + **默认 timeout=5s**,而 profiles 响应体约 **12.5KB**(需多次 recv),
Tailscale 网络抖动时超时 → 异常被 `except: pass` 静默吞掉 → 返回空 → 昵称/粉丝全丢;
更糟的是**空结果被写入 5 分钟缓存**,导致失败后持续空
- **修复**(`services/account_service.py`):
1. profiles 查询:timeout 5s → **15s** + **重试 1 次**
2. status 查询:同样 timeout 15s + 重试
3. **失败不再污染缓存**:有旧缓存则沿用(并记 warning),无缓存则不写(留待下次重试)
- 实测:5kecheng **0/21 → 20/21** 有昵称、7kecheng 20/20、本机 15/15,连续 3 次请求稳定
## [4.7.0] - 2026-09-25
### 新增:评论工作台第三种模式「📌 指定评论」(我提供内容,账号领单条)
- **模式切换**:🎯 定向评论 / 💬 多人讨论 / **📌 指定评论**(第三个按钮)
- **流程**:粘贴评论内容 → 🔍 解析整理 → 列表可编辑/删除 → 数量校验 → 📤 分发
- **解析整理**(纯前端,0 AI 调用):
- 一行一条;自动去掉序号前缀(`1.` `2、` `[3]` `-` `•` `①` 等)
- 去首尾引号(中英文)、去空行、**自动去重**
- 可选「整段按句号拆分」(整段粘贴时按 。!? 切句)
- **1 账号 1 条**:随机抽「评论数」个账号,评论顺序同时打散(避免按序对应被识别)
- **数量校验**(实时 + 分发前双提示):
- 账号 < 评论 → ⚠️ "请补选 N 个账号,或删掉 N 条评论"
- 账号 > 评论 → ℹ️ "N 个账号领评论,剩余 M 个:按所选动作处理"
- 相等 → ✅ 数量匹配
- **多余账号动作**:不参与 / 只浏览(暂未实现,等同不参与)/ 去点赞
- 后端 `_build_assigned_plan`(command_bus)+ dispatch 分支 `assigned_comment`
- 实测:解析去重(5 行→3 条)、数量校验文案、dry_run 分发(5 账号 / 3 评论 / 多余点赞 → 5 任务,0 错误)
## [4.6.5] - 2026-09-20
### 修复:worker 机器误跑 Dashboard 导致「数据视图分裂」(标签改了看不到)
**根因**:三台机器都装了 Dashboard 并 launchd 自启(5kecheng 从 8/21 起持续运行)。
Dashboard 是联邦统一控制平面(只有 master 应运行),worker 各自跑导致账号标签/备注等
本机数据在不同看板显示不同值 → 用户在本机改标签、去那台机器看却没变。
- **停用 worker Dashboard**:5kechengdeAir 已停用(launchctl bootout + plist 改名 .disabled,保留 guardd);
7kecheng 机器离线,待上线后执行脚本
- **新增一键脚本** `00_bootstrap/disable_worker_dashboard.sh`:
- 多来源身份识别(hostname / ComputerName / LocalHostName / HOST_ID.md)→ master 上执行会**自动中止**(需 --force 才继续)
- 停用后验证 Dashboard 进程=0 / guardd 进程>0 / 9988 端口释放
- **文档**:FEDERATION_GUIDE §3.1 增加「部署原则:只有 master 运行 Dashboard」+ 正确访问方式(统一访问 http://100.111.43.6:9988)
- 验证:5kecheng 停用后中心看板仍正常聚合三台账号(21+20+15=56);guardd 心跳正常
## [4.6.4] - 2026-09-20
### 重构:侧边栏菜单单点化(消除三份硬编码菜单的技术债)
- **新增** `frontend/src/nav-menu.js`:全项目菜单的**唯一**定义处(5 分组 30 项)
- **三处统一引用**:`inline.js` / `navigation.js` / `modules/matrix_views.js` 均改为 `import { NAV_GROUPS }` + `const groups = NAV_GROUPS`(其他代码零改动)
- **零行为变化**:以重构前**实际生效**的菜单(matrix_views.js 的启用项)为基准;旧菜单里未上线的项(matrix-corpus / matrix-commands 等)以注释形式保留在 nav-menu.js,需要时取消注释即可
- 验证:构建产物「API 配置」出现次数 **3 → 1**(确认单点);三处无残留旧菜单定义;菜单规模 5 组 30 项
- 收益:**以后新增/删除菜单只改 nav-menu.js 一处**,不会再出现改了菜单看不到(4.6.2 踩过的坑)
## [4.6.3] - 2026-09-20
### 新增:API Key 版本管理(替换 / 回滚 / 删除 —— 支持轮换已泄露的 key)
- **保存即归档**:填入新 key 保存时,旧值**自动存入历史**(标记「被替换」),不会丢失
- **🔄 一键回滚**:历史面板列出该字段的所有版本(脱敏 + 备注 + 时间 + 🟢使用中),点「🔄 启用」即可切回旧版本;切换前的当前值也会自动归档,可来回切
- **🗑 删除版本**:确认无用的旧版本(如已泄露的 key)一键删除;**使用中的版本禁止删除**(提示先切换)
- 存储:`agent-local/tools/ave/config/key_history.yaml`(600 权限,不进 git);接口只回传索引 + 脱敏值,**不下发完整 key**
- 后端:`POST /config/api-keys/activate`(切换生效)/ `POST /config/api-keys/delete`(删除版本);GET 增加 `history` 字段
- 实测全流程:保存 A → 保存 B(A 自动归档)→ 切换回 A(B 归档,A 变使用中)→ 删除 B → 删除使用中版本被拒(400)✓
## [4.6.2] - 2026-09-19
### 修复:🔑 API 配置菜单项看不到(菜单存在**三处**硬编码,实际生效的那处未改)
- **根因**:侧边栏菜单有三处硬编码定义,`main.js` 的 import 顺序决定谁生效:
```
12: import './inline.js' → 菜单 A(最先,被覆盖)
18: import './navigation.js' → 菜单 B(被覆盖)
24: import './modules/matrix_views.js' → 菜单 C ← 最后加载,实际生效
```
新加的 api-config 只加在 A/B 两处,**生效的 C 没加** → 用户看不到
- **修复**:三处菜单的「服务」分组全部补上 `api-config`;构建产物验证「API 配置」出现 3 次 ✓
- **顺带健壮性**:`inline.js` 的 `_renderNav()` 优先委托 `window.renderNav()`;`navigation.js` 自动渲染加 `DOMContentLoaded` 保护
- **技术债记录**:三处菜单硬编码重复(`inline.js` / `navigation.js` / `modules/matrix_views.js`),建议后续抽为统一 `nav-menu.js` 单点定义,避免同类问题再发
## [4.6.1] - 2026-09-19
### 优化:AI 配置单点化(key 全项目只在配置中心一处)
- **`AIGenerator._load_config()` 三级优先级**:
1. 环境变量 `DEEPSEEK_API_KEY` / `DEEPSEEK_BASE_URL` / `DEEPSEEK_MODEL`(最高,容器/CI 友好)
2. **配置中心** `agent-local/tools/ave/config/local.yaml → llm.*`(推荐,全项目唯一配置点)
3. 兼容旧配置 `05_tools/07_matrix/config/ai.yaml → ai.*`(兜底)
- **`ai.yaml` 的 key 清空**(本机文件):改 key 只需在 Dashboard → 🔑 API 配置 一处操作,彻底避免两处不一致
- **配置页新增 2 项**:`模型名`(如 deepseek-v4-flash)/ `API 地址`,与密钥区分处理
- 接口新增 `secret` 标记:密钥类脱敏显示(前 5 + 后 4)+ 输入框 password;普通配置(模型名/地址)明文显示 + 输入框 text
- ⚠️ **修正一处副作用**:`local.yaml → llm.model` 原为 `deepseek-chat`,会覆盖 ai.yaml 的 `deepseek-v4-flash`(导致改用计费更高的模型)→ 已修正为 `deepseek-v4-flash`,并写入 ai_usage 日志验证
- 实测:环境变量覆盖 ✅ / 配置中心覆盖 ai.yaml ✅(临时目录精确验证)/ 缺配置中心时回退 ✅ / 端到端生成 ✅(日志记录 model=deepseek-v4-flash)
## [4.6.0] - 2026-09-19
### 新增:🔑 API 配置页面 + pre-commit 防泄露钩子(公开仓库密钥安全方案)
背景:仓库保持 public,但历史曾误提交密钥(百炼 / DeepSeek)。本版提供「各使用者自行配置密钥」的完整机制。
- **🔑 API 配置页面**(Dashboard → 服务 → 🔑 API 配置)
- 按用途分组展示 10 项配置:AI 文本(DeepSeek)/ 视觉分析+人物置换(百炼)/ 图像生成(可灵)/ 素材(Pexels)/ 视频生成(火山方舟·即梦)/ 语音合成(火山)
- 每项显示**脱敏状态**(前 5 + 后 4 位)+ ✅已配置/⚠️未配置徽章 + 「🧪 测试」就地验证连通性
- 输入框填入新 key → 保存(留空保存 = 清除);页面明示「只存本机、不进 git」
- 后端 `routes/api_config.py`:GET 状态 / POST 保存 / POST 测试;写入 `agent-local/.../local.yaml`(自动 chmod 600)
- **安全设计**:接口一律脱敏不回显完整 key;仅允许写入白名单字段(防越权);日志只记后 4 位
- **pre-commit 防泄露钩子**(`00_bootstrap/hooks/pre-commit`,deploy.sh 自动安装)
- 提交前扫描暂存内容,命中 key 模式(`sk-`/`api-key-kling-`/`AKLT`/`LTAI`/`ark-`)即**阻止提交**并提示
- 实测:假 key 提交被正确拦截 ✓
- **deploy.sh 引导**:部署完成后提示「打开 Dashboard → 🔑 API 配置填自己的 key」+ 环境变量用法
- 实测:状态查询 9/10 项正确脱敏;保存 → 600 权限 → 清除 全链路通过;越权路径被拒(400);测试接口正确识别(可灵✅ / 百炼账号欠费⚠️ / DeepSeek 旧 key 401❌)
## [4.5.9] - 2026-09-19
### 新增:初次抓取筛选增强(点赞/评论区间 + 发布时间)
- **👍 点赞区间**:原「点赞≥」单值 → 改为 `下限~上限` 区间(留空=不限)
- **💬 评论区间**(新增):`下限~上限`,可按互动热度筛(如只要 100~1000 评论的)
- **📅 发布时间区间**(新增):日期选择器 `从~到`,按视频发布时间筛选
- 兼容两种日期格式:API 的 `2026-08-24 21:15:29` 与页面兜底的 `20260814`(统一归一化为 `YYYY-MM-DD`)
- 行数据新增 `data-comments` / `data-pub` 属性;两处筛选逻辑(初次抓取 + 导入路径)同步更新
- 实测:区间边界逻辑验证通过(赞 10~100 时 150 赞被正确过滤、无数据行在区间/日期筛选下被排除、空筛选全显示)
## [4.5.8] - 2026-09-18
### 新增:引导条数可控 + 引导要求强化
- **🎯 引导条数**输入框:指定带引导要素的评论条数(留空=自动 30%;填大些可多生成再挑选;0=不带引导)
- **引导要求提到最高优先级**(prompt 首位):明确「必须恰好 N 条带出,一条都不能少」,并给出多角度示例(有人问怎么找 / 有人分享经历 / 有人说预约方式 / 有人夸技术)
- **自然过渡引导**:若引导要素与讨论主题差异大,要求用自然联想过渡(吃辣油腻 → 肠胃遭不住 → 找医生 → 怎么挂号),杜绝生硬插入
- 容量保护:引导条数不超过「总数 − 路人条数」,避免与路人配比冲突
- 实测(10 条 + 引导 6 条 + 引导路径):明确引导 4 条 + 痛点铺垫 3 条,植入自然("我爸那次拖着不去,后来朋友介绍了个肛肠科主任…关键要提前约")
- 用法建议:引导条数填大(如 8)+ 倍数 1.5x → 生成更多含引导的评论,从中挑选终稿
## [4.5.7] - 2026-09-18
### 新增:讨论角色配比 + 长评论 + 生成倍数(+ 修复 max_tokens 截断)
- **👥 角色配置**(折叠区):8 角色(过来人/追问者/赞同者/纠结者/质疑者/分享者/路人/好奇者)可填条数配比 → AI 严格按配比生成;留空 = AI 自由发挥(prompt 要求角色多样、不机械轮换)
- **📖 长评论条数**:控制 60~150 字「娓娓道来讲经历」型评论数量(默认 2,0~3)—— 由过来人讲亲身经历,有前因后果有细节
- **⚡ 生成倍数** 1x/1.5x/2x(默认 1.5x):多生成便于人工挑选删除(配比模式放大配比、自由模式放大总数)
- **铺垫克制硬约束**:开场闲聊 + 转折过渡合计 ≤ 总数 25%,尽快进入实质讨论
- **🔧 修复 AI 输出被截断**(根因):`_call_api` 的 `max_tokens` 原硬编码 300,加长评论后 token 需求暴增(10 条含 2 长评论需 ~1000 token)→ 只输出 4 条;改为**动态计算**(`total×60 + 长评论×250 + 300`,上限 4000),timeout 30s→60s
- **warning 提示**:AI 输出条数不足期望时前端明确提示("AI 少输出 N 条,可重新生成或手动补"),期望值按配比总和计算
- 实测:配比 10 条 → 精确输出 10 条(过来人3/追问者2/路人2/赞同者2/纠结者1),长评论 3 条质量达标
## [4.5.6] - 2026-09-18
### 新增:讨论主题自动提取 + 引导路径(起点→要素→收尾)
- **🎯 主题自动提取**:解析视频后自动从标题提炼讨论主题(如标题含"肥肠面" → 主题"肥肠面");主题框旁加「🔄 提取」按钮可重提;不覆盖用户已填
- **🧭 引导路径**(新增字段,与讨论走向并存):
- 起点 = 讨论主题(自动来)+ 终点 = 引导要素(用户填)
- 「🤖 AI 生成路径」按钮:按「开场 → 转折 → 逐个要素 → 收尾行动」推演
- **步数自适应**:max(3, 2 + 要素数),封顶 6 步(1 要素→3 步 / 2 要素→4 步 / 3 要素→5 步)
- 约束:引导要素一个都不能漏,每个至少 1 步承载;最后一步负责行动收尾
- 生成讨论时把「主题 + 引导要素 + 引导路径 + 讨论走向」一起喂给 AI,保证讨论**按路径推进并落到引导目标**
- 实测(肥肠面例子):主题提炼"肥肠面"✓;2 要素→路径 4 步✓;生成 10 条讨论严格按路径推进(聊肥肠面 → 肠胃遭不住 → 推荐主任 → 预约挂号),要素全覆盖
- 后端:`POST /comment-workbench/extract-topic`、`POST /comment-workbench/generate-path`(+ corpus.py extract_topic / generate_guide_path)
## [4.5.5] - 2026-09-17
### 优化:讨论走向改为三步显式流程(写想法 → AI 生成 → 采用)
- **① 写想法**:自然语言随便写(可跳跃、口语)
- **② AI 生成讨论方向**:AI 理解后输出 3~6 阶段结构化方向,显示在独立框,**可手动修改**
- **③ ✅ 采用此方向**:点采用后写入「最终走向」(生成讨论时使用),流程有明确确认步骤
- 切换预设走向时自动隐藏 AI 方向区,保持流程清晰
- 实测:三步流程(生成→修改→采用→写入最终走向)验证通过
## [4.5.4] - 2026-09-17
### 新增:讨论走向「预设模板 + AI 拆解」
- **6 个预设走向**(下拉选择,不用自己想):疑问解答型 / 亲历分享型 / 质疑争论型 / 对比选择型 / 场景切入型 / 感叹种草型
- **自定义自然语言 → AI 拆解**:写一段话(可跳跃、口语化),点「🤖 AI 拆解走向」→ AI 输出 3~6 阶段的清晰走向 → 可在结果框手动修改后再生成
- 解决「用户写的走向 AI 读不懂」问题:先拆解成结构化走向,再作为生成 prompt 输入
- 实测(用户原始想法:「讨论肥肠引到肛肠医院,对面开肥肠店,医生下来吃…宋佳…孙刘星」):
→ AI 拆解出 6 阶段(肥肠店位置 → 发现就在医院对面 → 调侃医生下楼吃 → 聊医院名气 → 具体医生 → 收尾调侃),关键信息零遗漏
- 后端:`POST /api/comment-workbench/parse-outline` + AIGenerator.parse_discussion_outline
## [4.5.3] - 2026-09-17
### 新增:评论工作台「多人讨论」模式(AI 一次生成讨论剧本 → 拆条分发)
- **生成机制**:AI **一次调用**生成完整讨论剧本(多人接力对话,每行带角色标签),系统按行拆成独立评论
- 实测:12 条一次生成,角色标签齐全、接力感强、3 个引导对象自然分散植入、路人打酱油 2 条
- **多引导对象**:引导要素支持多行(多个推荐对象),AI 分给不同发言者自然带出("你推你的我推我的")
- **弱指向表达**:prompt 要求避免「楼上/上面说的」等强顺序词(适配多机并行发布)
- **条数随机分配**:下限保底 + 均匀随机加成(非刻意均摊,自然出现 1/2/3 条混合)
- **账号不足校验**:总条数 × 每账号上限 → 计算最少发言账号数,不足时明确提示补选或减条
- **围观账号**:多余账号自动不参与(不发言);路人氛围由 AI 写进剧本
- 前端:评论工作台加模式切换(🎯定向评论 / 💬多人讨论)+ 讨论设置面板 + 对话流预览(可编辑/删除)
- 后端:`POST /api/comment-workbench/generate-discussion`(生成剧本)+ command_bus `discussion` 分发分支
- 实测:dry_run 端到端链路(5 条讨论 → 5 个任务,无错误)
## [4.5.2] - 2026-08-24
### 新增:抓取源批量跟踪视频博主
- **抓取源 Tab 新增「📌 批量跟踪视频博主」折叠面板** — 粘贴视频链接(每行一个,支持「标题: xxx + 链接」格式),一键解析 + 批量跟踪博主
- **🔍 解析链接** — 正则提取全部 URL 并去重,显示数量
- **📌 批量跟踪** — 逐个调用 track-author 解析博主加入「博主监控」,实时日志显示 新增/已存在/失败 + 失败明细,重复博主自动跳过
- **后端 `_extract_aweme_id` 支持抖音精选页链接** — `jingxuan?modal_id=xxx` / `discover?modal_id=xxx` 格式(modal_id 即视频 aweme_id),此前只支持 `/video/数字` 和短链
- 实测:jingxuan 链接正确解析 aweme_id(7673872336403957937 等),批量跟踪需抖音登录态
## [4.5.1] - 2026-08-23
### 新增:评论互动「存为默认」设置持久化
- **💾 存为默认** — 执行区新增按钮,把当前所有互动/评论设置存入浏览器 localStorage:互动动作比例(点赞/收藏/评论)、执行间隔、评论闸门(每视频上限/每账号日限/节奏)、评论内容设置(13 角色条数)、引导内容 + 引导引用比例、AI 改写开关
- **自动填充** — 下次打开评论互动页面自动应用已保存默认值(角色输入框在展开评论内容设置时按默认值初始化)
- **↩️ 恢复默认** — 清除已保存默认,恢复系统默认值(引导类各 1 条、其余 0)
- 实测:保存→读取→角色初始值→清除 全链路验证通过
### 修复:评论互动多视频生成只有 1 个视频评论(URL query 被截断)
- 根因:`_ia_parse` 的 URL 提取 `line.split(/[?\s]/)` 把 `?` 后的 query string 截掉,抖音 jingxuan 链接的 `modal_id` 在 `?` 后 → 40 个视频 url 全变成同一个 `https://www.douyin.com/jingxuan` → 评论池 `comment_map` 只剩 1 个 key
- 修复:改为 `line.trim().split(/\s+/)` 只按空白切分,保留完整 URL(含 modal_id)
- 实测:3 个视频解析出 3 个唯一 url,commentMap 3 个 key
## [4.5.0] - 2026-08-16
### 新增:评论互动全量模型(v2 重构,替换 4.4.0 分组模型)
#### 核心变化:账号分组 → 账号全量 × 视频按比例 × 动作组合
- **账号全量执行** — 每个账号对"命中的视频"执行该视频的动作组合(点赞/收藏/评论连做),不再分组分工(删除点赞组/收藏组/评论组概念)
- **视频比例控制** — 点赞 90% / 收藏 30% / 评论 60%(可调 0-100),每个视频独立随机决定动作组合,未命中任何动作的视频直接跳过
- **评论两道闸门(防封号)** — 每视频评论上限(默认 5,随机挑账号评)+ 每账号日评论上限(默认 20,到限自动降级为只赞藏)
- **评论内容可控** — 评论互动内置「⚙️ 评论内容设置」折叠面板(13 角色数字输入 → 按视频生成评论池 → 可编辑/删除/重新生成),执行时按序领取设定内容(`comment_map`),未设定退回随机语料
- **蓝图组合机制** — 引擎支持 `+` 分隔组合蓝图名(如 `interact_like+interact_collect+interact_comment`),`merge_blueprints()` 合并 steps(goto_url 去重 + 连续 wait 合并),无需新蓝图即可同视频多动作连做
- **删除误导项** — 删除百分比滑块(strategy 模式下实际不生效)、浏览作者其他作品(默认不执行)、关注动作、账号分组参数
#### 新增:评论工作台疑问类角色(一问一答)
- **🙋 提问(questioner)** + **💬 回答(answerer)** 两个独立角色,新增「疑问类(一问一答)」分组(提问默认 17% > 回答 12%)
- 语料库新增「解答」分类(14 条评论 + 5 模板,通用化无行业限制,混用"隔空回应式"/"独立解答式")
- 后端 `role_counts` 精确计数模式(`generate` 接口 + `batch_get_comments_by_roles` 支持,每个角色精确取 N 条,不受比例取整误差影响)
#### 修复:抖音页面改版兼容(8 月中 data-e2e 属性变更)
- **前置条件软条件机制** — `Condition.soft` 标志:like/collect/follow 的按钮 selector 条件失败时不再跳过(skipped),放行底层兜底(键盘 Z / JS 文字查找 / 坐标);其他操作硬条件行为完全不变(保护旧蓝图)
- **评论内容生效** — `_resolve_args` 的 `@corpus` 占位符优先使用 `--comment-text`(计划/面板设定的内容),未指定才从语料库随机取
- **账号中心远程昵称取不到** — `account_service.py get_all_accounts()` 远程账号 profile 合并被 if/else 逻辑错误挡住(远程账号 tags 为空永远进不了 `_get_profile_for_account` 分支),改为无条件合并远程 profile(guardd `/accounts/profiles`),本机与远程对等
- **账号标签保存不上** — 远程账号打标签 PATCH 返回 400(本机 MatrixManager 无此账号);改为远程账号 tags 写入集中标签文件(`agent-local/data/account_tags_cache.json`,读取侧 `_load_tags_cache` 已读此文件);前端 `_saveTags` 增加响应检查(失败不再静默)
- **评论互动 MD 表格导入** — 导入区新增「📋 MD表格」入口:粘贴 Markdown 表格(`| 标题 | 链接 | 评论数 |`)自动正则提取「标题+链接」对并解析(纯前端正则,0 AI 调用)
- **评论互动引导内容** — 评论内容设置面板新增「🎯 引导内容」输入框 + 「引导引用比例」(默认 80%):引导类(guide_*)+ 回答型(answerer)角色按比例在 AI 生成时结合引导内容(如"引导关注公众号约号"),其他角色正常;不输入引导内容则行为不变
- **AI 优化与消耗监控** — AIGenerator 关闭思考模式(`thinking: disabled`,评论生成无需推理,reasoning_tokens 归零,成本直降);AI 调用记录 token 用量到 `agent-local/runtime/ai_usage.jsonl`;新增 `/api/ops/ai/usage` 聚合接口;看板「统计概览」首页新增「🤖 今日 AI 消耗」卡片(token/费用/次数/缓存命中率,按 flash 官方空闲价估算)
#### 技术说明
- 计划生成器 `_build_interact_plan` v2 位于 `command_bus.py`,strategy 参数改为 `like_ratio / collect_ratio / comment_ratio / comment_per_video / comment_daily_limit / pace`
- 组合蓝图实现在 `engine.py` 的 `merge_blueprints()`
- 前端数字输入全部带范围保护(比例 0-100、评论上限 0-20、日限 1-100、角色条数 0-20)
- 改动文件:`command_bus.py` / `matrix-interact.js` / `comment-workbench.js` / `comment_workbench.py` / `mc/corpus.py` / `corpus/douyin.yaml` / `engine.py` / `douyin_ops.py` / `ops/_base.py`
- ⚠️ `01_core/VERSION` 未修改(版本由 ghai 决定),正式发布时同步
## [4.4.0] - 2026-08-09
### 新增:互动计划生成器(批量互动防封号核心)
#### 核心能力
- **账号分组(30赞/5评/5藏)** — 40 账号按数量随机分组,不同动作混合执行,模拟真人分散行为
- **每视频评论配额** — 每条视频最多 N 条评论(默认 5,可调 3/10),不再全量账号评论
- **每账号评论日上限** — 默认 12 条/天,达上限自动踢出轮动池(点赞/关注不限流)
- **账号轮动** — 评论账号随机轮动分配,避免同一账号连续刷
- **评论内容随机** — 从语料库随机取(dict 解析兼容),避免重复文案
- **执行节奏两档** — 🐢宽松(慢安全)/ ⚡紧凑(快风险高),间隔按动作区分
#### 配套
- 新增 `interact_collect.json` 蓝图(收藏操作,之前是占位符)
- 批量互动页新增「📊 互动策略」参数区(评论上限/评论日上限/分组数/节奏)
#### 修复
- `--comment_text` → `--comment-text`(参数名连字符,argparse 不再报错)
- 语料库 dict 解析(`{"text":...}` 取 text 字段)
- 前端接受 `accepted` 状态(提交成功不再误报"未知错误")
#### 技术说明
- 计划生成器在 `command_bus.py` 的 `_build_interact_plan()`,strategy 模式走独立路径,不动 mc 引擎/guardd
- 账号数 < 分组需求时,账号优先填评论组(收藏/点赞组可能为空)
## [4.3.0] - 2026-08-05
### 新增:抖音博主监控系统(抖追踪重大升级)
#### 博主跟踪闭环
- **视频行「👤 跟踪」按钮** — 在抖追踪「跟踪中」列表,一键把视频作者加入博主监控
- **博主监控 Tab** — 博主列表(粉丝/涨粉/作品数/今日采集状态)+ 手动刷新单个/全部
- **每日快照** — 记录粉丝数/获赞数/作品数/新视频,按天存 `douyin_authors.json`
- **新视频发现** — 刷新博主时自动发现新视频并加入视频跟踪
- **趋势查看** — 博主历史快照展开(每日粉丝/作品/新视频)
- **前3条视频展示** — 博主行直接显示最新3条视频(标题+点赞/评论/收藏)
#### 抖追踪列表增强
- **标题/作者关键字动态筛选** — 输入即过滤(不重建 DOM,五笔输入不失焦)
- **每页条数 100/200/300 可选** + 上一页/下一页/跳页
- **跟踪中搜索/全选/删除选中** — 批量清理无效跟踪
- **已跟踪状态持久化** — 用博主 uid 精确匹配,刷新后不再重复跟踪
#### 修复
- 账号选择器筛选改为**包含逻辑(AND)** + 保留选中状态(原为排除逻辑,只能选一个条件)
- track-video 重复跟踪不再覆盖 `prev_stats`(保留对比链)
- 去掉指挥台历史失败累计告警(只增不减无告警意义)
- 抖追踪全部更新 F5 后恢复进度提示(sessionStorage)
#### 技术说明
- 博主数据接口用「数字 uid」(`profile/other`、`aweme/post`),不能用 sec_user_id(会报 UserId不合法)
- 新增 8 个博主监控 API 端点 + `get_author_profile`/`get_author_videos` 采集函数
## [4.2.2] - 2026-07-26/27
### 运维改进 + 账号中心增强
#### 修复:clear-all 清不完远程机器队列
- **`_guardd_api()` 加 timeout 参数** — 默认 5s,clear-all 用 10s
- **clear-all 返回逐台结果** — 全部成功返回 `ok`,有失败返回 `partial`
- 解决了远程机器偶尔连通性差导致队列清不干净的问题
#### 新增:账号中心批量删除标签
- 选中多个账号后底部弹出「🏷️ 删除标签」按钮
- 弹窗列出选中账号的所有标签,点击即删除
- 逐账号 PATCH 更新,界面自动更新
#### 修复:5kecheng guardd POST 挂死
- guardd 运行 28 天后 `do_POST` handler 卡死(`rfile.read` 阻塞)
- 重启后恢复,guardd 版本号更新至 v2.3.1
#### 修复:mediacrawler_adapter CDP 采集优化
- 去掉 Playwright 降级方案(headless 模式有封号风险)
- CDP 断连时全量重建 Playwright 实例,不重用旧 state
- 新增 Chrome 状态检测 + 一键重启 API
- 新增登录状态检测 + 打开登录页功能
- 复用已有 Chrome 页面执行 fetch,不创建新标签页(零闪烁)
## [4.3.0] - 2026-07-15/16
### 抖追踪系统 + CDP 采集引擎
#### 新增:抖追踪全链路
- **🎵 抖追踪 Tab** — 从 tyhtak API 导入视频列表 → CDP 采集 → 跟踪 → 历史
- **📡 跟踪中 Tab** — 独立跟踪专项页,显示 👍/💬/⭐ 数据 + 评论区
- **全选/勾选机制** — 列表全选勾选框 + 单条勾选 + 采集选中/跟踪选中
- **一键复制** — 单条复制、复制已选、复制全部(标题+链接)
- **刷新全部 / 更新选中** — 逐个刷新(3 秒间隔)+ 进度显示,支持选择性刷新
- **评论展开** — 默认 5 条,点「展开全部」看 20 条
#### 新增:MediaCrawler 风格 CDP 采集引擎
- **`mediacrawler_adapter.py`** — Chrome CDP 模式,复用 Chrome 登录态调抖音官方 API
- 全局单例 Session,不复用已关闭 tab,避免重复开浏览器
- CDP 不可用时自动降级 Playwright 标准模式
- 获取准确数据:点赞/评论/收藏/分享/20条热评
#### 新增:Chrome 远程调试开机自启
- **`com.agentos.chrome-debug.plist`** — launchd 管理,KeepAlive 崩溃后自动重启
- **`chrome_debug.sh`** — 检测 9222 端口,不在线自动启动 Chrome
#### 修复:评论工作台
- 粘贴解析支持「标题+链接」配对格式(检测 douyin.com 链接模式)
- 视频列表显示双行排版:标题 + 网址(小字灰色)
#### 修复:前端导航/路由
- 浏览器标题跟随路由页面切换(`AgentOS - 矩阵总览` 等)
- 删除 `_tryMigratedView` 双路由系统
- 修复 `#view-dynamic` display 问题
- 删除废弃视图文件:matrix-record/backup/export/run/settings
- 构建产物加入 `.gitignore`(`static/assets/`)
## [4.2.2] - 2026-06-26
### 定向评论B模式修复 — 输入方式+登录检测
#### `<douyin_ops.py>` post_comment
- **修复** B模式 (`/video/` 独立页面) 评论输入不生效问题
- 输入方式改为 **pbcopy + Meta+V 粘贴**(复制 reply_comment 方案)
- 原因:Draft.js + Camoufox(Firefox) 下 `press_sequentially` 分发的键盘事件不被正确拦截
- 粘贴是浏览器原生操作,Draft.js 可靠处理 `insertFromPaste` 事件
- 输入后验证:`_verify_comment_posted()` 检查评论区前5条是否含刚发文字
- 选择器顺序恢复为 `[contenteditable="true"]` 优先
#### `<login_state_machine.py>` DouyinDetector & DouyinLoginRecovery
- **修复** 登录检测误触广告问题("登录后领取奖励"广告被当成未登录信号)
- **LOGGED_IN_ANCHORS** 增强:+3 个顶栏头像选择器(`[class*="DyHeader"] [class*="avatar"]` 等)
- **NOT_LOGGED_ANCHORS** 移除 `'div:has-text("登录后")'` — 太宽泛会匹配广告
- **页面文本检测** 去掉 `"登录后"` 关键词(同样匹配广告)
- **`_trigger_login` JS 兜底** 改为只查 `button, a` + `offsetHeight > 10` 过滤,防止点到广告元素
### 验证
- [ ] 定向评论手动测试中
## [4.2.1] - 2026-06-25
### 命令传导统一治理
- **新建 `PLANS/COMMAND_UNIFICATION_PLAN.md`** — 命令传导统一治理方案 v1.0
- **CommandBus 新增 CMD_REGISTRY 注册表** — 统一 cmd_type → 命令模板映射,collect 自动按账号平台选择采集蓝图
- **前端统一调用路径** — matrix-collect.js 改走 POST /api/ops/run,参数格式统一为 {type, accounts, params}
- **删除废弃路由** — routes/matrix.py 中 /collect-homepage、/collect-homepage/phone、/collect-homepage/cancel、/collect-homepage/status 已删除
- **platforms/ 标记 deprecated** — collect() 方法中的存档脚本引用已替换,添加废弃标记
- **CLI mc collect --all 修复** — 支持 --all 参数采集所有账号
- **AUDIT_5LAYER_REPORT.md 更新** — 信息采集路径审计状态更新
### 验证
- [x] Phase 1: CommandBus CMD_REGISTRY 注册表已添加,collect 默认带 --blueprints
- [x] Phase 2: matrix-collect.js 已改走 /api/ops/run,/collect-homepage 路由已删除
- [x] Phase 3: CLI mc collect --all/--phone/--account/--status 全部修复
- [x] Phase 4: platforms/*/plugin.py collect() 已改走 CommandBus,标记 deprecated
- [x] Phase 5: AUDIT_5LAYER_REPORT.md 信息采集审计已更新
## [4.2.0] - 2026-06-21
### 文档体系重构
- **新建 `01_core/VERSION`** — 版本唯一来源,终结版本打架
- **新建 `99_system/INDEX.md`** — 项目文档总索引,一处维护全部引用
- **精简 AGENTS.md** — 从 180 行→56 行,去掉过时硬编码数字
- **精简 README.md** — 从 246 行→26 行,改为入口性质
### 技能归档
- **归档 4 个空技能**:content_processor、web_crawler、auto_collector、cloakbrowser_controller(移至 `02_skills/_archived/`)
- **collect_to_inbox 降级**:SKILL.md 从 v2.0 降为 v1.0,标记 `status: legacy`,文档与实际代码一致
### 版本收敛
- **guardd.py 版本从 VERSION 读取**:不再硬编码 `version = "2.3.0"`
- **所有 version.json 对齐到 SKILL_CARD.yaml**:memory_manager 1.2.0, inbox_refine 1.1.0, kb_manager 1.1.0, sync_manager 1.1.0
- **collect_to_inbox SKILL_CARD 降级**:1.1.0→1.0.0 `status: legacy`
### 架构宪法发布
- **新建 `CONSTITUTION.md`**(根目录)— 架构总纲,包含 12 维全景、10 条硬规则、版本规则、开发决策流程
- **部署到 `~/.workbuddy/CONSTITUTION.md`** — WorkBuddy AI 按需加载,开发工具硬性读取
- **规则 11:架构变更必须更新宪法** — 目录层级/功能维度/版本规则/文件权限等变更时同步更新
- **`99_system/ARCHITECTURE_CONSTITUTION.md`** 标记为已迁移(指向根目录版本)
- **所有入口已更新**:AGENTS.md / 99_system/INDEX.md / apply-config.sh
- **inbox_refine SKILL.md 对齐**:1.0.0→1.1.0
- **03_knowledge/versions.json 更新**:4.1.0→4.2.0
### 代码层清理
- **统一 CLI 入口**:`00_setup/agentos` 成为统一入口,同时加载 `07_matrix/scripts/agentos/plugins/` 的联邦命令
- **`mc` 脚本指向统一 CLI**:优先使用 00_setup/agentos 包路径
- **废止 accounts_registry.yaml**:所有账号分配统一在 ORACLE.yaml 中管理
- `guardd _sync_account_override()` 改为读取 ORACLE.yaml
- 支持 ORACLE 多平台格式(一个 identity 绑定 douyin + xiaohongshu)
- **删除 guardd cross_machine 心跳写入**:不再写入 `cross_machine/machines/{UID}/heartbeat.json`,避免 Git 污染
- **自动化配置入仓**:新建 `01_core/automation/`
- `workflows.yaml` — WorkBuddy 4 个自动化任务定义
- `launchd/com.agentos.guardd.plist.template` — guardd plist 模板
### 文档修复
- **FEDERATION_GUIDE.md 数字更新**:蓝图 14→12,guardd 检查项更新为 9 模块
- **federated-multi-machine-architecture.md guardd 模块更新**:7→9,补齐 dashboard_sync 和 sync_checker
- **SOUL.md.v2-backup 归档标记**
- **03_knowledge/99_system/ 冗余文件归档**:ARCHITECTURE_AUDIT.md 等 6 个文件标记为已归档
## [4.1.0] - 2026-05-15
### 联邦式多机协同架构(V2.1)
- **新增 `docs/DASHBOARD_DATA_LAYER_V2.md`** — 联邦式数据架构完整设计文档
- **新增 7 大协同子系统**:
1. 状态机(heartbeat.json, 5-10min 周期, 15min 离线判定)
2. 事件总线(events/ 跨机事件日志, 10 种事件类型)
3. 任务协作(tasks/ 异步文件机制, pending→in_progress→completed)
4. 加密通讯(RSA-4096 密钥对, 公钥注册/私钥本地, encrypted/ 加密消息)
5. 知识双向同步(拉取总知识库更新 + 推送本地知识到 submissions/)
6. 自动升级(versions.json 版本清单, breaking 自动/手动双模式)
7. 文件直传(SSH rsync 全自动 + AirDrop 半自动备选)
- **新增 `guardd` 守护进程**:9 模块主循环(最初文档记录为 7 模块,实际代码实现 9 模块,v4.2.0 已修正), launchd 安装, 5 分钟周期, 全规则引擎 0 token 消耗
- **新增 `cross_machine/` 子目录**:events/ status/ tasks/ encrypted/ knowledge/
- **README.md 升级 v4.1.0**:新增"多机联邦协作"章节 + 第四层导航
- **新增安全边界**:私钥/API Key 固定在 agent-local/identity/secrets/, 永不进入 agent-sync/
### 文档更新
- 新增 03_knowledge/99_system/ 知识卡片:联邦式多机协同架构
- 新增 01_core/MAINTENANCE_GUIDE.md guardd 运维章节
## [4.0.0] - 2026-05-03
### 系统文档体系重构
- 根目录精简:从 12 个文件减至 4 个(README + CHANGELOG + requirements + .gitignore)
- 删除废弃文件:01_submissions.md(空)、agent-os.code-workspace、REQUIREMENTS.md(与requirements.txt重复)、VERSION(不再维护)
- 归档过时文档:CORE-ARCHITECTURE.md / SKILLS-CATALOG.md / QUICKSTART.md → 99_system/archive/
- README.md 重写为三层导航体系(入口→系统文档→技能/知识库)
- 新增 01_core/UPDATE_SYSTEM.md 更新体系规范
- 新增 99_system/architecture/loading-architecture.md 四管道加载架构
- 新增 99_system/architecture/trigger-matching-analysis.md 触发词方案分析
### 协议体系重构
- SOUL.md v4.0 精简版:5671B(减重 40%),仅含行为规则+模式切换+安全边界
- 协议文件从 20_methods/agent-protocols/ → 99_system/protocols/
- 4 个协议全部重写对齐新规范(高阶思维/跨域联想/卡壳干预/知识审查)
- 新增 trigger_matcher.py 语义匹配脚本(关键词+Embedding混合模式)
### 配置维护
- apply-config.sh v2.0:增加版本追踪 + 多机角色预设 + 自动注册
- .config-version.json 自动生成部署记录
- .obsidian/ 解除 Git 追踪(各机器独立配置不冲突)
- 知识库清理:归档测试文件 + 删除 14 个空占位目录 + README 更新
- **`agentos config`** — 配置管理子命令(status/diff/apply/rollback)
- `01_core/CONFIG_MANIFEST.yaml` — 配置清单(9文件,A/B/C三类管理)
- `agentos/config_mgr.py` — 配置管理引擎
- `agentos init` 新增 PATH 自动检测配置
- `VERSION` 文件(版本号唯一来源)
### 修复
- 路径清理:删除 `~/workbuddy-agent-os/agent-sync/` 和 `~/workbuddy-agent-os/agent-local/` 残留目录
- 5 个脚本的 help 文本从"agent-os-local 根目录"修正为完整路径
### 变更
- Git 双远程仓库:Gitee + GitHub 同步推送
- 停用坚果云,完全切换到 Git 版本管理
## [2.2.0] — 2026-05-01
### 新增
- **`agentos upgrade`** — 统一模块升级引擎
- MODULE.md 标准化规范(首个: Matrix 模块)
- `auth_manager.py` 原子化登录模块
- SOUL.md v3.3 逐级加载重构(精简 72%)
- 4 个 G2 协议文件(meta-thinking/cross-domain/stuck/knowledge-review)
- Matrix 养号系统全链路稳定(3账号12/12步全部通过)
## [2.0.1] - 2026-04-25
### 修复
- **依赖管理统一**:删除旧的 `04_memory/vector_db/.venv`,统一使用 managed Python 专用 venv
- 旧路径:`~/workbuddy-agent-os/agent-sync/04_memory/vector_db/.venv`(分散,与脚本运行环境不一致)
- 新路径:`~/.workbuddy/binaries/python/envs/agent-os/`(统一,脚本和自动化共用)
- **init.sh 修复**:指向新 venv,用 `requirements.txt` 安装依赖
- **daily_digest.py 重写**:接入三个真实数据源(Claw 工作日志、WorkBuddy 系统画像、上轮摘要)
- **自动化任务修复**:Python 路径更新为新 venv
### 新增
- **bootstrap_from_memory.py**:冷启动脚本,首次运行时将已有 MEMORY.md 灌入 L1/L2
- **requirements.txt**:集中声明 Python 依赖(trafilatura + sqlite-utils)
- **WorkBuddy 自动化**:每日凌晨 2:00 自动执行 `daily_digest.py`(ID: `agentos`)
- **冷启动执行**:L2 写入 36 条初始事实,L1 索引同步建立
### 文档更新
- **REQUIREMENTS.md**:修正 venv 路径、更新实际设备状态、写清固定安装命令、新增自动化配置说明
- **QUICKSTART.md**:新增步骤 4(冷启动记忆体)、修正坚果云路径为 `~/NutstoreCloudBridge/`
- **README.md**:新增记忆数据流说明、固定路径速查表、补全目录说明
## [2.0.0] - 2026-04-25
### 新增
#### 核心框架
- L0→L1→L2→L3 四级记忆模型
- SOUL.md v2.0:完整的三层规则体系(硬约束/软约束/学习规则)
- IDENTITY.md v2.0:Claw 身份档案,含设备信息自动填充
- USER.md v2.0:ghai 用户档案
- mcp.json:MCP 协议基础配置模板
#### 初始化脚本
- init.sh:自动创建目录、安装依赖、填充设备信息
- apply-config.sh:核心配置部署到 ~/.workbuddy/
- import_skills.sh:技能导入
- export_skills.sh:技能打包导出
#### 技能包
- memory_manager:每日对话提炼、去重、冲突检测、版本管理
- daily_digest.py:每日提炼脚本(凌晨 2:00 自动运行)
- bootstrap_from_memory.py:冷启动(首次导入已有记忆)
- memory_cleanup.py:冲突消解与过期清理
- agent_memory_init.py:记忆体初始化
- kb_manager:知识库入库、分类、检索、备份
- kb_ingest.py:知识入库脚本(支持 URL/文件/文本)
- _template:技能模板(SKILL.md + version.json + skill.py)
- web_crawler:网页抓取(占位)
- sync_manager:同步管理(占位,由坚果云替代)
#### 知识库
- 按属性分层目录结构(概念/方法/事实/参考/资源/观点)
- 16 个一级领域子目录
- 知识卡片模板(概念卡/事实卡/方法卡/个人洞见卡)
- 领域分类表(domains.md)
- 知识属性分类表(nature-types.md + 分类决策树)
- 中文映射配置(folder-aliases.json)
- 知识分类提示词模板
#### 迁移脚本
- pack.sh:全量打包
- unpack.sh:解包还原
- backup.sh:手动备份
#### 说明文件
- README.md:项目概览
- QUICKSTART.md:5 分钟快速上手
- REQUIREMENTS.md:环境依赖清单
- CHANGELOG.md:本文件
### 设计决策
| 决策 | 选择 | 原因 |
|---|---|---|
| 知识库物理目录分层 | 按属性(概念/方法/事实/...)为第一层 | 人找知识先想"类型"再想"领域",机器检索空间更小 |
| 记忆读取策略 | L2 置信度不足直接截断,不 fallback 到 L3 | 节省 token,避免无关信息干扰 |
| 跨机同步 | 坚果云,不用 Git | 国内访问 Git 不稳定 |
| 存储策略 | 单条存储线 + 平台自适应 | 避免数据分裂,init.sh 自动检测系统 |
| 目录命名 | 英文文件夹名 + 中文映射 | 机器兼容性 + 人类可读性 |
| Python 环境 | managed Python + 专用 venv | 不污染系统环境,版本可控 |