zcbot/PROGRESS.md

248 lines
51 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.

# 实施进度
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。
最后更新:2026-07-08(个人微信 ClawBot 语音接入 + 企微语音路径补日志,bump 0.52.0)
---
## 状态
| Phase | 标题 | 状态 | 备注 |
|---|---|---|---|
| 1-3 | 骨架 + Skill + run_python | ✅ | 多 skill(coding/proposal/ppt/research/documents/imagegen/videogen/review/patent);CoreCoder 唯一匹配 edit;敏感 env 过滤 |
| 4 | 演化性能力 | 🟡 | Model Profile + Probing ✅;版本化 prompt 未做 |
| 5 | Eval Suite | ⏸ 不做 | dogfooding 替代,probe 覆盖健康检查 |
| 6 | 长任务工程化 | 🟡 | task + 恢复 ✅;双层记忆 ✅;context 压缩 ✅(加压力门槛) |
| 7 | 打磨 | ❌ | Docker 沙盒 / 更多 skill |
| §7 SaaS | DESIGN §7 路线 | 🟡 | A 事件流化 ✅;B 完工 ✅;D `/v1` JSON API ✅;D' 过渡 auth + dev SPA ✅;单活 run 锁 + cancel ✅;0004 schema 瘦身 ✅;入口归位 ✅;真 OIDC 待;**C Step 1-3 + 3d ✅(Executor + Docker 池 + DockerExecutor + fs 工具进容器)+ Step 5 部署前置对账 ✅ + 容器资源 yaml + 应用层磁盘配额 ✅ + dogfood 网络放开 + 容器内 pip/npm 源持久化 ✅**;**Step 4 完整 egress proxy + Step 3b PGID kill 协议延后到外部用户开放前**(还需 egress proxy + xfs project quota OS 层硬化,§7.5 落地清单 #2 #4)。 |
---
## 已完成关键能力
### 2026-07
- **07-08 / 0.53.0**:**录音文件转写工具 `transcribe_audio`**(用户上传录音要"转文字/总结"的需求):新 `core/asr_lfasr.py`(讯飞录音文件转写标准版,raasr v2:signa 签名 + upload/getResult 异步订单 + lattice 解析 + 说话人分离格式化)+ `tools/transcribe_audio.py`(look_at_image 同形态 host-side tool,路径复用 image_ref.resolve_in_root)。选 LFASR 弃 IAT 分片方案:单文件 5h/500MB、服务端解码常见格式(本地不需要 ffmpeg)、roleType=1 自带说话人分离(会议场景直接可用);全文落 `<音频名>.transcript.txt` 只回预览+路径,不撑爆 context。凭据 `XFYUN_APPID`(共用)+ 新 env `XFYUN_LFASR_SECRET_KEY`(独立 SecretKey,控制台「录音文件转写标准版」页),没配不挂工具;轮询期响应停止按钮。实测:TTS 合成 12.6s 中文语音 13s 出稿逐字全对;orderInfo.originalDuration 是上传参数回显、realDuration 才是真实时长(踩坑记入代码注释)。smoke `scripts/smoke_transcribe_audio.py`(离线 12 项)+ 诊断 `scripts/diag_lfasr.py`
- **07-08 / 0.52.6**:企微语音落地收尾——"文字/语音全无反应"根因定位:**回调注册在企微平台侧失效**(服务器/代码/env 全正常),后台重新保存「接收消息」API 配置即恢复;RUN 故障兜底补该行(判据:`[wecom] inbound` 行没有=平台没投递)。至此两渠道语音全链路用户实测跑通:个人微信(SILK→pilk)+ 企业微信(AMR→ffmpeg)→ 讯飞 IAT → 回显「已识别」→ 进对话。
- **07-08 / 0.52.5**:企微最终回复推送失败不再静默——用户报企微连文字也无回复:`_bg` 最终 `push_wecom` 返回值一直被忽略,message/send 失败(如企微「企业可信 IP」拦截 60020)完全无痕。改走 `_push_checked` 统一落 `[wecom] push failed: <reason>` 日志(带企微 errcode/errmsg)。
- **07-08 / 0.52.4**:企微回调加入站留痕日志——用户报企微发语音无反应且 `[wecom-voice]` 日志一行没有(语音分支被调用必打),疑企微侧未投递语音回调;但 text 路径原先零日志无法对照回调通断。解密成功后每条打 `[wecom] inbound msgtype=... from=...`,用"text 行出现、voice 行不出现"即可断定平台侧未投递。个人微信语音已用户实测跑通(0.52.0 链路)。
- **07-08 / 0.52.3**:sandbox 镜像 npm 步骤加重试——腾讯 npm 源拉 cytoscape 偶发 ECONNRESET 崩整个 build(部署实测),fetch-retries 2→5 + retry-maxtimeout 120s;RUN 故障兜底补该行,并写明"部署不涉及镜像变化时用 `--skip-build` 跳过重建"。
- **07-08 / 0.52.2**:sandbox 镜像 build 剔除 host-only 依赖——pilk 进 requirements 后镜像 build 也去装它,slim 基底无 gcc 整个 build 编崩(部署实测)。容器内 run_python 用不到语音解码,方案:requirements 行尾标 `# [host-only]`,Dockerfile 装包前 `grep -v '\[host-only\]'` 过滤(通用机制,后续 host-only 依赖复用);不往镜像塞 build-essential(+~250MB 没收益)。
- **07-08 / 0.52.1**:RUN 故障兜底补 pilk 源码编译坑——服务器 py3.12 无 pilk 预编译 wheel,pip 退源码编译撞缺 gcc(`x86_64-linux-gnu-gcc ... No such file or directory`),处理:`apt install build-essential python3-dev` 后重跑 update(用户部署实测踩到)。
- **07-08 / 0.52.0**:个人微信 ClawBot 语音接入(0.51.0 留的第二步)——用户真机发语音,0.51.0 加的 unhandled item 日志拿到结构:`voice_item`(type=3),media 与图片/文件同款 `{encrypt_query_param, aes_key}`,音频 SILK v3(`\x02#!SILK_V3` 头,ffmpeg 解不了)。实现:① `ilink.get_updates` 解析 voice_item → `InboundAttachment(kind="voice")`,CDN 下载/AES 解密全复用;② `core/audio.py` 重构出统一入口 `transcribe_voice(bytes)`(按字节头分流:SILK → pilk 解码 24k PCM + ffmpeg 重采样 16k,其余 AMR 等 → ffmpeg 直解),两渠道(wecom `_transcribe_wecom_voice` / ClawBot inbound)共用;③ `inbound._poll_binding` 语音附件就地转写:回执「🎤 已识别:…」→ 转写文本并入 m.text 进对话,不当文件落盘;失败回可读提示。**新依赖 pilk**(requirements,有 manylinux/win wheels)。已实测:pilk encode(tencent=True) 造微信同款 silk → 全链转写逐字正确,AMR 路径回归通过。另:**企微语音"无声失败"补日志**——用户报企微发语音无反应但日志无线索:voice 入站打 MediaId/Format 行、transcribe 异常打错误行、`push_wecom` 失败原样打 reason(原先返回值被忽略纯静默)、未处理 msgtype 也留行;待用户重测后按日志定位。企业微信语音消息转写进对话(0.47.0 留的二期)——回调新增 `msgtype=voice` 分支:media/get 下 AMR → 新模块 `core/audio.py`(ffmpeg 子进程 stdin/stdout 解成 16k/16bit/mono PCM,不落临时文件,格式自动探测)→ 复用 `asr_xfyun.transcribe()` → 转写文本当用户消息走同一条 `_run_channel_conversation` 链路。要点:① 下载/解码/转写全放后台任务(长语音数秒,inline 会踩企微 5s 回调窗口触发重推),回调只登记 MediaId 即回 success;② 识别结果先推「🎤 已识别:…」回显(微信端看不到识别成什么,识别错不回显用户一头雾水);③ 兜底分层:ffmpeg 缺失(AudioNotConfigured)/讯飞未配置(XfyunASRNotConfigured)/识别为空各回对应可读提示,不静默;④ 超 60s 截前 60s(讯飞上限,企微语音本身也限 60s);⑤ 未绑定成员发语音也回绑定指引(msgtype 白名单加 voice)。**服务器新增系统依赖 ffmpeg**(apt install ffmpeg / env FFMPEG_PATH,RUN.md env 段);个人微信 ClawBot 语音待真机探协议(getupdates 未识别 item 已加结构日志,预计 SILK v3 需 pilk 解码)。ppt 验收改纯代码几何质检,撤除 0.36.0 渲图 vision 验收闭环(DESIGN §8.10)——真实会话复盘:沙箱 chromium "找到了但渲染崩"无回退,硬门+死路逼模型 pip install cairosvg 手写渲染,look_at_image 逐页 26-42s 纯烧 token。删 accept_pages.py / acceptance.json 登记 / 导出验收门 / `--allow-unreviewed`;正确性由质检器 check13/14 几何检测保底(越界/压字/错位,导出边界自动复跑);svg_preview.py 保留为手动工具并修回退(chromium 渲染失败按页自动落 cairosvg),但 SKILL/SKILL_LIST **零提及渲图**(提示面不给渲染入口,模型不再主动渲);SKILL.md 阶段五简化为 finalize 单步 + 强调导出唯一入口 svg_to_pptx,Geometry warning 改"回源核对坐标"。放弃逐页美学验收,观感靠用户反馈迭代。
- **07-07 / 0.49.0**:语音输入流式化(边说边出字,消掉松手后停顿)——用户报"录完停顿几秒才出字",根因:整段模式按讯飞文档 40ms/帧节奏回放音频 = 按录音时长等比例白等(16.8s 音频实测等 4.6s)。改双通道:① **流式主通道** `WS /v1/asr/stream`——录音开始即连(首消息 JWT 鉴权,不走 query 防进 access log),前端增量降采样(carry 缓冲跨片连续)实时上行,服务端 `XfyunStream` 转发讯飞(dwa=wpgs)并**在服务端合并动态修正**(sn/pgs/rg),回推 partial 全文,录音面板实时字幕,松手只等最终帧——实测 16.8s 音频 **end→final 179ms**(61 个增量帧,文本与整段一致);引擎提前收尾(静音 10s/60s 上限)推 final 前端自动结束。② **整段 POST 兜底**(WS 连不上/中途挂/超时),帧间隔实测调优 40ms→8ms(4.6s→1.75s,文本一致,已到讯飞处理地板)。nginx 示例加 `location = /v1/asr/stream` WS Upgrade 段(不配不坏,退兜底);踩坑:讯飞控制台 IP 白名单(握手 403 "Your IP address is not allowed"),进 RUN 故障兜底。
- **07-07 / 0.48.1**:语音手势两端统一(用户提出 PC 也要能按住说话)——不再按 pointerType 分流,改按**按下时长**判别,PC 鼠标/手机触屏同一心智模型:按住 ≥300ms = 按住说话(松开即转写,上滑取消);快速点一下 <300ms = 转成连续录音免持(说完 Enter / 再点结束,Esc 取消;鼠标按住 60s 会累且易失手,长口述场景必须保留免持)。实现要点:press 发起的录音松手后合成 click 全压掉("松开转写完又开新录音"/"短按刚转免持被自己 click 停掉"),"点按钮停止连续录音" press 不压(`_pressActive` 区分);getUserMedia 完成前松手按同一时长规则收尾;键盘激活按钮( pointer 事件)兜底走 click 起录
- **07-07 / 0.48.0**:语音输入手势升级(纯前端,后端零改动)——业界对齐调研后两端分治: **触屏按住说话**(微信/DeepSeek ):`pointerdown`(pointerTypemouse)按住录音松开转写上滑 60px 进入"松开取消"(面板变红),pointer capture 保证滑出按钮仍收事件,touch 后合成 click 用时间窗压掉;② **桌面点击开停 + Enter/Esc 收尾**:说完按 Enter 结束转写Esc 取消(capture 拦截防落回 textarea 触发发送)。**明确不做桌面 VAD 静音自动停**:口述需求"边想边说"停顿 3~5s 是常态,自动截断比多按一下更伤,业界听写类(ChatGPT/Google Docs/Win+H)也全是手动收尾,自动停只属于 Siri 式短指令场景。③ 录音期 `#voice-rec-panel` 替换 textarea:实时波浪(采集 chunk 顺手算 RMS,1/8 抽样,零额外开销)+ 计时 + 手势提示;iOS Safari 手势内 `ctx.resume()`;授权弹窗期间松手 启动完成立即收尾
- **07-07 / 0.47.0**:web 端语音输入(讯飞语音听写 IAT)——聊天输入区新增「🎙 语音按钮:点击录音(Web Audio ScriptProcessor PCM 前端线性插值降采样 16k/16bit/mono)→ 再点停止 `POST /v1/asr/transcribe`( PCM body,require_user)→ 后端 `core/asr_xfyun.py` 连讯飞 wss(HMAC-SHA256 签名,9600B/ 40ms 节奏,vad_eos=10000 防句间停顿截尾,未开 dwa 整段拼接)→ 文本 insertText 插输入框光标处(接原生 undo ,**不自动发送**)。60s 上限自动停(讯飞单会话限制);录音需 HTTPS/localhost;渠道只读镜像 task 按钮锁定;`XFYUN_APPID/API_KEY/API_SECRET` env 未配返 501(**当前 .env 为测试 key,待换正式**)。诊断 `scripts/diag_asr.py`(静音冒烟 / PCM 文件真测);requirements 显式加 `websockets`已实测:TTS 合成中文 5.2s 音频经端点转写逐字正确企微语音消息(AMR ffmpeg 转码)留待二期;将来流式逐字上屏可复用 `build_auth_url` 签临时 URL
- **07-07 / 0.46.2**:消息分页窗口对齐轮次边界(纯前端,`chat.js`)——原按固定 30 条翻页/跳转,窗口边界常切在 assistant 工具调用序列中间(顶部出现孤儿 tool 消息),点目录圆点用 `before_idx=idx+11` 启发式(长轮拉不全短轮混无关上文)。业界调研确认:分页单位保持消息条数是共识(Discord/OpenAI 均按条 + 每页上限,轮次大小无上界不能当传输单位),轮次归组属渲染层职责实现:idx 连续 + outline 已含全部 user 轮次起点 前端可精确算区间,后端 API 零改动。① 向上翻页 `alignedEarlierLimit`:从窗口顶往前按整轮累加攒够 30 ,新窗口顶恒为 user 消息;② 圆点跳转:`after_idx=起点-1` + 相邻边界差精确拉整轮(短轮补到 30 铺满超大轮按 `MSG_FETCH_MAX=100` 截断,后续向上加载逐步自愈对齐);③ outline 未加载/idx 不在 outline 回退旧按条行为后端 limit clamp,前端以 100 硬上限自律
- **07-07 / 0.46.1**:撤除企微欢迎推送机制——实际部署采用聊天优先布局(不配应用主页 + 菜单工作台按钮),点应用直进会话,冷启动问题不复存在,0.46.0 的欢迎推送成了死重:删 `wecom_welcomes` (migration 0021 撤下,DB downgrade 0020,表建后无一行写入)、`maybe_send_wecom_welcome`、免登回调欢迎钩子群发脚本、`list_visible_userids`。**保留**:未绑定入站回绑定指引(聊天优先下必需)、`core/branding.py` 品牌单一源RUN.md 企微段只留推荐布局 + 未绑定指引两条
- **07-07 / 0.46.0**:企业微信会话冷启动 + 未绑定入站回指引——背景:应用配了应用主页后点应用只进主页,应用会话要等应用发过第一条消息才出现在成员消息列表(首次登录的员工没入口和 bot 打字)。最终采用**聊天优先布局**(企微后台不配主页菜单放工作台按钮指向 `/v1/wecom/entry`,点应用直进会话),代码侧: 回调对**未绑定成员** text/图片/文件消息不再静默,每条回一句绑定指引(聊天优先下新员工上来就打字,静默会被当成 bot 坏了;事件不回);② 新表 `wecom_welcomes`(0021,wecom_userid PK,未绑定成员也能去重)+ `service.maybe_send_wecom_welcome`(两层去重:已推过 / 已绑定且有 chat task;claim-first INSERT 并发安全,发送失败释放占坑),免登入口回调对首次进入的成员自动推欢迎语(菜单工作台」/主页两条路都触发);③ 可选工具 `scripts/wecom_welcome_broadcast.py`:配主页布局下给存量成员批量""会话入口(`--dry-run` 先看名单;可见范围枚举 `wecom.list_visible_userids`:agent/get + 部门/标签展开);④ 品牌名单一事实源挪到 `core/branding.py`(web 层外的欢迎语也要用,app.py BRAND 引它)。RUN.md 企微段同步推荐布局
- **07-07 / 0.45.0**:移动端显示修复 + 对外品牌名 env——① 浮层菜单(⋯ 任务菜单 `dom.js`、⚙ 媒体模型弹层 `chat.js`)原只做右对齐,手机上触发钮靠左时菜单冲出屏幕左缘盖住正文,改成"右对齐放不下左对齐 + 双向钳视口";手机断点补:菜单项加大触控目标模型下拉限宽 48vw、「管理入口统一挪到 任务/对话/文件 tabs 行右侧小按钮(embed 与普通模式同款, CSS order 实现不动 DOM)、header 品牌名单行省略。② env `ZCBOT_BRAND_NAME`(默认总院科研辅助助手」,zcbot 只是内部代号):`/healthz` brand 字段,前端 boot 拉取覆盖页面标题/顶栏/登录卡(静态页默认值也已改为默认品牌);微信/企微测试推送OAuth 提示页绑定页等用户可见文案全部改用品牌名或中性"助手",不再露 zcbotRUN.md env 段同步
- **07-07 / 0.44.0**:企业微信应用主页免登——企微后台应用主页 `/v1/wecom/entry`,成员点开应用即静默授权(snsapi_base)登进 embed 控制台后端两端点(entry 302 授权callback codeuserid反查绑定 JWTfragment token 302 `dev.html?embed=1&wecom=1`),UA 分支让外部浏览器退 wwlogin 扫码;前端 wecom 变体(fragment token 即清 hash,401 entry 静默重签,不需要 parent_origin);未绑定成员提示先在控制台绑定(不自动建号,避免重复账号)。EMBED.md §9 + RUN.md 企微段同步
- **07-07 / 0.43.1**:跳秒指示补两处空窗——① 刷新/重连接管后 phaseSince 随页面内存丢失,退回静态"思考中"不跳秒(恰是用户因疑似卡死而刷新的场景),重建直播卡时立即按"思考中"起跳,下一个阶段事件校正;② 发消息 POST 返回即起跳,覆盖 build_agent + 首轮 TTFT(原先要等 llm_start 才开始计时)。重连后秒数从重连时刻起算(非真实累计),可接受
- **07-07 / 0.43.0**:run 长耗时可视化——"前端一直静止显示思考中被当成卡死": 新增 SSE `reasoning{delta}` 事件(loop 提取 `delta.reasoning_content`,thinking 模型分钟级推理原先整段丢弃前端零反馈),前端渲染灰色折叠"思考过程",历史消息里持久化的 reasoning_content 同款渲染;② 前端活跃状态指示:TTFT/推理期占位段每秒跳"思考中/深度思考中 · Ns"(CSS attr(data-status)),工具卡运行中加 spinner + 跳秒结果到达定格为执行耗时;每轮 llm_start 重建占位段,工具轮之后不再空窗
- **07-06 / 0.42.5**:497 跳转示例 301308——平台走 http 入口 POST login 被客户端按 301 语义降级成 GET 405;308 保留方法/body治本仍是调用方直配 https(明文首跳暴露 platform_key)。
- **07-06 / 0.42.4**:497 跳转目标示例改写死域名(http://IP 进来被带回域名无证书警告;https://IP 直连警告 nginx 层无解,入口统一域名),进故障兜底
- **07-06 / 0.42.3**:nginx 示例补 TLS 正确写法(同端口单条 listen + error_page 497 https;`if ($scheme)` ssl-only 端口不触发)+ 企微回调只认 80/443 提醒;实际部署上 SSL 踩出,进故障兜底
- **07-06 / 0.42.2**:部署脚本 pip install `-q`——日常部署依赖没变,整屏 "already satisfied" 纯刷屏;装新包/报错仍输出
- **07-06 / 0.42.1**:修 `update_bluegreen.sh` wait_health 首次真跑就崩——`local a="$1" b="...$a..."` 同行赋值,bash 先展开整行再执行 local,`$a` 展开时无值,`set -u` unbound;拆多行
- **07-06 / 0.42.0 broker 外置 Redis(用户量上升重评落地)**:`web/broker.py` LocalRunBroker(原进程内实现)/ RedisRunBroker 同接口双实现,`ZCBOT_REDIS_URL` env 开关(不设 = 进程内,dev/单实例零影响)。Redis 版:event PUBLISH + 单条 async pubsub reader 路由本地 queue,done = SETEX(60s)+publish 双通道(订阅先挂 channel 再查 key 不漏),cancel = key GET poll 跨实例可达——蓝绿切换窗口刷新丢直播/停止失灵两边缘消失,稳态双实例分流从此只差 nginx 配置容错:启动 ping fail-fast运行中降级丢帧(10s 节流 log)、reader 1s 退避重连。`tests/test_broker_redis.py` 9 (fakeredis,含跨实例/晚订阅/降级);deploy bootstrap redis-server 步骤关键判断:排除 PG LISTEN/NOTIFY(token delta 耦主库) nginx sticky(部署窗 hash 重排),Redis 只管跨进程一跳fan-out 最后一公里仍在进程内
- **07-06 / 0.41.1 蓝绿端口方案反转**:nginx 接管原对外端口 8765(客户端 / platform 嵌入零改动),实例挪 8766(blue)/ 8767(green) 只绑本机——对外契约(URL:8765)不动优先于"实例沿用旧端口"的省事;顺带把切换窗口内对旧实例 run 点停止送达不到补进已知边缘文档
- **07-06 / 0.41.0 蓝绿无感部署(RUN.md B 档落地)**:生产部署零 503 窗口 + 在跑对话 SSE 直播不断。`zcbot@blue/green` systemd 实例(模板 unit + `deploy/instances/*.env`)+ nginx upstream 单行文件切流,编排在 `deploy/update_bluegreen.sh`(复用 `update.sh --prepare-only`;切流后轮询 DB 等旧色 run 自然清空再 stop——直接 stop 会被 uvicorn `timeout_graceful_shutdown=5` SSE)。双实例并存互踩三修:`tasks.run_owner`(0020)reaper 只收自己色sandbox 容器名/label 带实例色各清各的微信 ClawBot 长轮询 PG advisory lock 选主(detach 连接持锁,断连即让位);定时任务 claim 本就 SKIP LOCKED 免改关键判断:broker 刻意不出进程(不上 Redis),接受"切换瞬间刷新的用户看不到旧实例直播"这一边缘单实例部署 `ZCBOT_INSTANCE` 未设全部退回原行为,`update.sh` 保留不废
- **07-06 / 0.40.0 ppt 伪导出根治(三层)**:0.35.1 复发(模型照禁令里的"配方" cairosvg 手搓整页贴图导出)复盘——①平台层机检门落地(`core/pptx_guard.py` + loop 钩子:shell/run_python 新产出 .pptx 命中"≥80% 页整版位图 + deck 零原生文本"即注入 `[产物机检 ERROR]` 当场逼返工;判定刻意保守,`tests/test_pptx_guard.py` 8 );②禁令去菜谱:ppt/brief SKILL.md 否定式指令改"正面窄门"(唯一入口 + 报错就修/上报),删掉可照做的违规配方;③官方脚本 5 `pip install` hint 改环境说明(pptx_media/svg_preview/crop_images/fix_image_aspect/pptx_cli)——打印给 agent 的安装指令就是执行指令 DESIGN §8.9
- **07-06 / 0.39.2 research 对接 paper_server API Key**:paper_server GET 接口收紧要 Key ,`skills/research/paper.py` 全部请求带 `?api_key=`(env `PAPER_SERVER_API_KEY`),认证失败(paper_server 异常处理器压成 HTTP 400 + err_code)转成带指引的 RuntimeError;这把低价值只读 key 是唯一刻意放进 sandbox 的凭证——`run_python` env 过滤器加 allowlist 放行docker 模式 `_sandbox_env()` 透传进容器(顺带修掉 `PAPER_SERVER_URL` 覆盖不进 docker 的缺口)。
- **07-06 / 0.39.1 文档精简**:PROGRESS(865188 ) DESIGN(797218 )按各自边界契约压缩——PROGRESS 每条收成一行(做了啥+关键判断,细节查 git log),DESIGN 保留全部决策/取舍/硬协议清单/升级信号砍实现复述(协议细节指向代码与 probe 脚本),顺手把 §2 架构树补齐实际模块
- **07-06 / 0.39.0 skill 定向模型**:内置 skill 可在 frontmatter 声明 `model:`(pptGLM-5.2),对话中 `load_skill` 命中即 run 内热切(持久化 + emit `model_switch` + 前端分隔线,失败降级原模型);只信内置 skill跳档位门控不自动切回,"开关"=frontmatter 那一行(admin 总开关 + 预切方案经架构评审砍掉——第二事实源/第二执行点)。 DESIGN §3.5;新增 `tests/test_skill_model_pinning.py`
- **07-03 / 0.38.8**:列表状态灯(终态徽章+运行圆点)挪到文件夹行行首,底部数据行 space-between 均匀分布
- **07-03 / 0.38.7**:列表 meta 行数字组改靠左跟排 time-ago 锚行尾, active 静默后左侧"缺口"。
- **07-03 / 0.38.6**:status 徽章改"默认态静默"——active 不挂徽章(零信息噪音),completed/abandoned 保留徽章且整行淡化;绿脉冲点成唯一动效信号
- **07-03 / 0.38.5**:运行态标识精简为 7px 脉冲圆点(绿//),文案收进 hover title
- **07-03 / 0.38.4**:列表带出的 running 行自动挂 SSE(上限 4 条后台流, HTTP/1.1 连接占满),刷新页面/别处启动的 run 也实时零轮询;后台订阅不碰对话区
- **07-03 / 0.38.3**:任务列表加运行态标识(服务端 `run_status` 快照 + 本地 liveRuns 叠加),run 起止就地 patch DOM 不重拉列表
- **07-03 / 0.38.2**:ppt 模板 zongyuan_red 按官方总院模板逆向重建(COM 渲真页取实测色值/字体/logo 等资产,5 SVG 忠实还原);strategist 加唯一"主动提模板"场景——受众指向中国建材总院系时点名 zongyuan_red 候选
- **07-03 / 0.38.1**:进度 dock 展开会挤掉 chat-stream 可视高度,`task_progress` 分支补贴底回滚,"拉到底仍有内容被遮挡"。
- **07-03 / 0.38.0**:ppt 反纯文字页+图表落地硬门(7aa49195 复盘):版式指纹加 text-columns 原型spec 指派图表被退化成文字errorCJK 文字互叠升 errorlayout_grid content_bottom 越界检测策略层"素材含 3 组可比数值须至少 1-2 页真图表"。
- **07-03 / 0.37.2**:web 直播流式文字按轮次分段(每个可见工具卡关掉当前文字段新文字另起底部新段),修工具刷屏把文字推出视口;与历史态结构一致,run 结束 reload 无跳变
- **07-03 / 0.37.1**:seedream size 面积钳制——ARK 卡总像素非单边,tool `_normalize_size` 自动等比缩放进 `[min,max]` 区间(1920x10802560x1440),按真实出图尺寸记账;选自动钳而非返错重试,省一轮往返
- **07-03 / 0.37.0**:ppt 对齐网格锁(d1285247 复盘):spec_lock `layout_grid` 锁段(executor 吸附checker 强制)、质检加兄弟卡片近失对齐/网格偏离/版式指纹单调门策略纪律"同一版式原型整本 2 + 标题语义须被图形兑现"。
- **07-03 / 0.36.2**:进度条自愈——回放层加确定性单调不变量(某步 completed 则之前所有步视为 completed),模型跳步漏发自动补齐;根因是模型工具收尾不稳,纯提示拦不住
- **07-03 / 0.36.1**:ppt 门体系二轮硬化(139a59c5 重跑复盘):渲图验收"从没渲过"任何 CLI flag 不可豁免(运维兜底走 env)、图标门永远对 svg_output 源检测( `-s final` 误报雷)、导出前内嵌自动质检门 svg_final 嵌图一直失效的 bug(copytree `../images/` 解析落空)。
- **07-02 / 0.36.0**:ppt 渲图验收闭环(139a59c5 复盘,阶段六渲图验收被整个跳过):svg_preview 登记 acceptance.json( sha1+verdict)+ accept_pages.py 标记 + svg_to_pptx 导出验收硬门;质检加 check13 几何检测(图标压字/基线越界=error,文字互叠=warn 带坐标);管线改"验收在导出前"。边界:看没看 PNG 无法机器验证
- **07-02 / 0.35.1**:ppt SKILL 禁自搓导出器硬约束——模型曾整条绕开官方管线,cairosvg PNG 整页贴图交付(不可编辑图标图片全丢)。教训:官方工具内部的门只在模型用了它时生效;本次仅文档层,平台层自动检测暂缓(用户拍板)。
- **07-01 / 0.35.0**:快捷指令(触发词完整指令):`core/shortcuts.py` 解析用户 `shortcuts.md`,渠道+web 入口起 run 前整条精确匹配展开关键判断:这是入口层确定性替换而非 memory(零歧义0 token),维护仍走 memory 心智(对话里让模型写)。
- **07-01 / 0.34.7**:ppt 966041e5(23 页零图标):`svg_to_pptx.py` `sys.exit(main())`(所有 return 1 被吞成退出 0,最致命)、导出侧图标检查升硬门(`--allow-iconless` 逃生口)、验收改默认渲整本逐页过目 `| head` 截断质检输出
- **07-01 / 0.34.6**:look_at_image/seedream 接受容器绝对路径——`resolve_in_root` `/workspace/` 前缀翻回宿主 user_root(按字符串前缀判,Windows 上它不算绝对路径), send_email 口径一致
- **07-01 / 0.34.3**:admin 各用户用量加最近使用(刻意全量子查询不随 range,否则真实 last-used 被藏)。
- **07-01 / 0.34.2**:ppt 页数升独立拍板项(🔒 gate):必须拿到用户显式认可的具体张数才写大纲,禁区间中位数当默认
- **07-01 / 0.34.1**:web 清空对话同步清空右侧导航条( `state.outline=[]`)。
- **07-01 / 0.34.0**:ppt 工作目录重构:可再生构建产物(svg_final/preview/backup)收进隐藏 `.build/`,用户可见面从 ~11 项降到"+交付物"。svg_output(可编辑源) svg_final(自包含编译产物)是两态不可合并;终态(待做) svg_final 内存化
- **07-01 / 0.34.0 **:验证 ppt生成2 后修复:svg_preview cairosvg 兜底(渲前预展开 `<use data-icon>` INVALID_MATRIX)、扁平 gate 计入 circle 且收紧(≥60% 页无图形error)、executor 加反卡片映射(先看内容关系再选图形,卡片阵封顶 ~1/3 )。视觉验收的根因是服务器镜像旧没带 chromium, rebuild
### 2026-06 下半月(渠道/ppt SVG-first/管控)
- **06-30 / 0.33.5**:ppt 加商务红品牌预设(business-red,#C00000 + 政企口吻,设为中文政企汇报默认配色候选);用户没给图时主动提议 ai 配图(提议免费,确认才花钱)。
- **06-30 / 0.33.4**:修PPT 缺图形:质检加扁平 deck gate(文字密集全 deck 0 图形图元error)+ 策略层视觉下限(spec_lock 不许 page_charts page_layouts 同时空)。prompt+gate 抬下限,执行模型设计功力是上限
- **06-30 / 0.33.3**:修PPT 缺图标四层断点:references 23 ppt-master 残留路径修正 + 新建 icon_sync.py(strategist GATE 此前空转)、质检加"锁了图标却全 deck 0 图标error"、执行层强制内容页 1-3 图标导出预扫警告附:svg_preview 认容器 chromium + `--screenshot` 相对路径静默失败
- **06-30 / 0.33.2**:look_at_image 偶发超时改 tool 内透明重试( `ArkTimeoutError` 子类,仅超时/网络抖动重试),vision timeout 60120s;避免报错抛给主模型触发整调用重发烧 token
- **06-30 / 0.33.1**:修 web SVG 无法预览(前端按扩展名强制 blob mime + 后端 download .svg 显式回 `image/svg+xml`,双保险)。
- **06-29 / 0.33.0**:**ppt skill 清空重构为 SVG-first**(移植 ppt-master 引擎+设计知识, GUI):AI 逐页手写 SVG, Python 转换器译成原生可编辑 DrawingML;templates 全量入仓(icons 30MB);Confirm UI 换聊天 BLOCKING 确认,配图走 imagegen;端到端 4 deck 验证过
- **06-29 / 0.32.5**:system prompt 加全局 context 纪律铁律:大段工具输出会进历史每轮重发——中间数据落文件 read 用得上的片段
- **06-29 / 0.32.4**:定时任务默认单次超时 01800s(`DEFAULT_TIMEOUT_SECONDS` 单一事实源,显式 0 =不限)。
- **06-29 / 0.32.3**:brief skill context 纪律,"同一批 38 abstract 反复 dump 进上下文烧 2.5M token"(弱模型放飞);更大杠杆(框架层截断超大 stdout)留待单议
- **06-29 / 0.32.2**:修定时任务超时被误记成 ok:`_execute_scheduled_job` 超时分支置 `timed_out`,收尾按 error (计连续失败不投半成品 notify)。
- **06-29 / 0.32.0**:channel 长会话软重置(Phase 1):`tasks.context_base_idx`(0019),`Session.load` 只装 base 之后的消息进 LLM 上下文,历史全量留表;自动 gap( 6h)软重置 + 手动新话题硬重置Phase 2 摘要 / Phase 3 检索延后
- **06-26 / 0.31.3**:消息框支持拖拽文件;附件 chip 独立托盘 `#chat-attach`(与状态文字解耦),修多次粘贴互相顶掉
- **06-26 / 0.31.2**:目录圆点错位再修:点选加跳转锁防平滑滚动途中被 scroll-spy 抢写;触底且无更新内容时直接判最后一轮(经典"不可达末项"bug)。
- **06-26 / 0.31.1**:admin 7 天用量表加合计行(纯前端 tfoot)。
- **06-26 / 0.31.0**:per-account 模型访问控制——**档位制**(复用休眠列 `users.plan`,「档位模型集合 agent.yaml `model_tiers`,管理成本 O(档位)):list 端点按档过滤resolve 显式选档外模型403 task 存量模型出档持久降级 flash;admin 加档位列+图例
- **06-26 / 0.30.0**:新增豆包 Seed 2.1(turbo/pro/evolving)+ GLM 5.2 文本模型档案( yaml 即上下拉);pro52 glm.pro(5.1)并存不动线上引用
- **06-26 / 0.29.0**:定时任务执行历史:右栏改 Tab(详情/执行记录),新端点 `GET /v1/schedules/{id}/tasks` 分页;保留全部历史不剪枝
- **06-26 / 0.28.1**:渠道绑定/对话/管理收进左栏卡片(未绑定/已绑无对话/已绑有对话三态), rail微信按钮
- **06-26 / 0.28.0**:定时任务 task 归属(`tasks.scheduled_job_id`,0017,普通列表过滤掉)+ push 统一记录到渠道对话——记录下沉到 `send_to_user`,投递成功即写 assistant 摘要消息(`messages.kind="push"`,0018,取回复时跳过),用户可基于推送追问
- **06-25 / 0.27.4-0.27.3**:渠道镜像对话从任务列表置顶行改成左栏固定卡片(`/v1/channel_tasks`,列表查询排除渠道任务),两卡并排;企业微信对话同微信一样 web 端只读
- **06-25 / 0.27.2**:企业微信入站支持图片/文件(`media/get` 下载InboundAttachment,复用个人微信同一落盘/注入约定)。
- **06-25 / 0.27.1**:`wechat_push` 加可选 `channel` 参数定向投递,"点名企微仍广播到个微";不静默回退到别的渠道
- **06-25 / 0.27.0**:企业微信入站对话:回调 webhook( `wecom_crypto.py` 验签解密)+ 把个微会话核心抽成 `_run_channel_conversation(channel)` 两渠道共用各一张会话 task;回复走主动推(agent 5s 被动窗口)。
- **06-25 / 0.26.10**:修企微扫码绑定——网页授权端点只能企微客户端内打开, `wwlogin/sso/login` 扫码授权端点(桌面浏览器出二维码)。
- **06-25 / 0.26.9**:修 wechat_push 漏挂企微:提取 `service.active_channels()` 作渠道清单唯一真相源,门槛与投递同源,根除两处各列各的漏判
- **06-25 / 0.26.3**:企微加手填 userid绑定第二条路——推送是出站直连根本不需要域名,只有 OAuth 扫码要
- **06-25 / 0.26.2-0.26.1**:监控页近 7 天按日期倒序;用户名展示统一兜底链 `name→user_name→email→uid8`(监控页 + dev 顶栏)。
- **06-25 / 0.26.0**:平台登录注入用户档案 name/user_name(0016 加两列;`ensure_user_row` upsert,COALESCE 语义传空不覆盖);`/v1/me` 回带
- **06-25 / 0.25.2**:登录失败提示修正——凭据错统一给账号或密码错误」,不再回显被网关改写的状态码
- **06-24 / 0.25.1**:微信 task web 端改只读镜像(单一交互权威锚定微信;24h 窗口约束下"双向打通"只能有时同步,不做)。
- **06-24 / 0.25.0**:微信入站收图片/文件(此前静默丢弃):ilink 解析 image/file item + CDN 下载 AES-ECB 解密,落盘 `inbound/` 并按 web 端粘贴图同一约定注入正文
- **06-24 / 0.24.3**:微信绑定两表合一 `channel_bindings`(判别列+JSONB 多态,0015 搬数据+drop 旧表)——加渠道零 migration;service 公共 API 形状不变,调用方零改动
- **06-24 / 0.24.1**:修 host-side 工具(send_email/wechat_push)发不出附件:`tools/base.py` 加共享 `_resolve_user_file`(容器路径翻译+越界校验),base_dir cwd working_dir
- **06-24 / 0.24.0**:企业微信渠道 B:纯推送 + OAuth 扫码绑定(用户拍板"和邮箱似的"不做对话)——无条件主动推正补 ClawBot 24h 窗口短板,定时简报必达首选
- **06-24 / 0.23.2-0.23.0**:配 QQ SMTP + 发件人显示名走 `SMTP_FROM_NAME`;`tasks.channel` (0013)微信 task 后端置顶 + 品牌绿徽章
- **06-24 / 0.22.2-0.22.1**:微信绑定 UI 并入主 SPA(rail modal);修顶栏 token 计量栏回复后不刷新(fetchSse 收尾重拉 meta)。
- **06-24 / 0.22.0**:**微信接入第一期 ClawBot 个人微信**(官方个人号 Bot API,零封号):协议全程真机实测(`client_id` 每条必唯一、`context_token` 24h 复用主动推送成立文件走 AES-128-ECB+CDN);`core/wechat/` 四模块 + 0012 + `wechat_push` 工具 + 定时 notify wechat 通道;凭据加密列不进沙箱
- **06-23 / 0.21.0**:**平台渲染层 `rendering/`**:渲染是平台能力非 skill 内容(共享库进 skill 会破坏自包含/ fork), skill 重复的 render_docx 收敛成配置化 profile + chromium mdpdf(不用 weasyprint);重构前后 docx 字节一致零回归;需一次 deploy 原子激活
- **06-23 / 0.20.4**:消息目录定位错位修:跳转改 `block:"start"` 与活跃判定同锚点,容差 8024
- **06-22 / 0.20.3**:crons modal z-index;登录页 focus 引用错 id
- **06-21 / 0.20.2**:发送期修复悬空 tool_calls——run 中断留下的 `assistant.tool_calls` 无对应 tool 结果会被 API task error;`_repair_dangling_tool_calls` 发送前补占位 tool 消息,不改库存量坏数据自愈
- **06-18 / 0.20.0**:brief 重定位重要文献速览」(只描述不给建议,Elsevier 优先,web 动向单列),8 文件精简到 3
- **06-18 / 0.19.0**:**定时任务 v1**(`scheduled_jobs`):job 本体=cron+一句 prompt+会话模式,"发邮件" agent 动作不是字段(加能力不改 schema);croniter 只当 next_run 计算器,调度是 plain-asyncio 守护循环不上框架;对话端完整 CRUD前端只读+停用/删除;isolated/persistent 两模式
- **06-18 / 0.18.0**:新增 brief skill(文献计量趋势型简报,documents/research/web 三路取数,六阶段);顺带抽化学式下标白名单补进三个 render_docx(CO2/C3S 平排数字老毛病)。
- **06-17 / 0.17.0**:任务软删除(`deleted_at`,0010):公测后对话轨迹是语料,硬删推翻;DELETE 改置位 + restore 端点,文件不动
- **06-17 / 0.16.2**:用户操作说明书(+精简两版,不出现产品代号);文献库库容口径 21W+→100W+ 全量 10 处改
- **06-17 / 0.16.1**:新增 paper skill(期刊论文写作):调研 ARS 等开源不直接装(license/领域/引文格式不合),移植流程骨架底座全换 zcbot 自有;中英双语×三类型用子 md 分流;微型 fixture 端到端 smoke
- **06-16 / 0.16.0**:look_at_image 图像理解(Doubao Seed 2.0 Lite,一次读图 0.01):主模型纯文本按需"借眼睛",否决换 vision 主模型(DeepSeek code/tool-calling 是核心);`usage_events.kind=vision` migration;路径解析抽 `tools/image_ref.py` 共用
- **06-16 / 0.15.0**:seedream i2i 改图(`reference_images` v1 单图,不传=文生图行为不变);前端发送时注入粘贴图路径 `[用户上传的参考图]`(修既有缺口:粘贴的图路径根本到不了模型)。
- **06-16 / 0.14.0**:ask_user 方案确认选项卡(Claude ):虚拟工具调用即提前结束本轮,点选项= label 当新用户消息发,零额外 LLM 往返;严格收窄到"2-4 个互斥方向"防变爱问
- **06-16 / 0.13.0**:消息目录:右侧悬浮圆点轨道(每点=一轮提问,hover 标题点击定位), outline 端点只取 user 消息 idx+片段;消息列表支持双向分页
- **06-16 / 0.12.16**:切 task 提速:meta messages 改并发拉(此前串行 await 是真瓶颈,索引没问题),首屏窗口 6030
### 2026-06 上半月(前端打磨/记忆/admin/token 治理)
- **06-15 / 0.12.15**:plot_pub 吸收 nature-figure 投稿级复合图设计纪律(只迁设计 IP 不整包移植,示例改建材领域)。
- **06-15 / 0.12.14**:消息分页:尾部窗口 + 顶部 sentinel 向上滚动加载更早;不传 limit 保持旧行为
- **06-15 / 0.12.13-0.12.10**:文件预览四连:滚动不穿透(overscroll-behavior+wheel 断冒泡)、图片 Ctrl+滚轮缩放(CSS zoom max-width 夹回,改显式 px)、双击复位放大后左键拖动平移
- **06-15 / 0.12.9**:sandbox 镜像加 `fonts-noto-color-emoji`, mermaid emoji 全豆腐块
- **06-15 / 0.12.8**:左栏筛选区默认折叠(显式展开过才记住展开)。
- **06-15 / 0.12.7**:system prompt backend 注入运行环境——原写死 Windows/cmd,docker 下误导模型 Linux 里打 cmd 构文 + 不知渲图走本地原则:全局环境事实归 system(高杠杆),可选方法归 skill
- **06-14 / 0.12.6**:容器 `mmdc` wrapper 自动注入 puppeteer config(`--no-sandbox` ),裸调一次成;不开 first-class tool(mermaid 纯本地计算,专用 tool 只留给带 key 计费能力)。
- **06-14 / 0.12.5**:容器 `docker run` `--shm-size 512m`(默认 64MB chromium 起不来,一次对话烧 120k token 才绕道)。
- **06-13 / 0.12.4-0.12.1**:模型选择瘦身(对话下拉常驻生图/生视频收 弹层);筛选区可折叠;中栏 5 按钮收完成+⋯」菜单 + 消息阅读限宽 + 色彩收敛(颜色=后果);移动端 task 列表可滚等四小修
- **06-12 / 0.12.0**:**双层记忆升级 agent 自管**:`memory_block` 记忆维护契约+可写路径锚点常驻(空记忆也注,解冷启动),agent 用已有 fs 工具自维护;召回升级 frontmatter description;前端只读记忆面板(看走 GUI改全走对话——单一写入口不会写坏格式)。
- **06-12 / 0.11.1**:进入公测期:CLAUDE.md 兼容策略翻新为"对外契约必须向后兼容纯内部实现仍最优重写"。
- **06-12 / 0.11.0**:admin 增强:TOC + 按模型/各用户用量独立端点(range/sort/分页,零用量用户条件放 JOIN ON)+ 存储分页 + 导出 PDF(客户端 window.print 零依赖)。
- **06-12 / 0.10.1**:**修上下文压缩投毒**:旧 assistant tool_call 参数被压成 `{"_compacted":...}` marker,模型照葫芦画瓢当真实参数吐出(DB 实测 83 次报错里 61 次是仿写)→ run_python 空转修:参数一律原样保留,只压 tool 结果 + skill——模型看到的范本永远真实可执行
- **06-12 / 0.9.x**:admin 管理后台:`users.role` (0009)+ `require_admin`(role DB 查不进 JWT,改完即时生效)+ `/v1/admin/overview` 五段聚合 + 各用户用量分页 + 独立 admin.html(阈值热力色,10s 轮询);命名定 admin(既盖""又盖"")。
- **06-11**:版本号机制(`core/__init__.__version__` 单一事实源FastAPI/healthz/前端左栏,改版本只动一行);显式 ThreadPoolExecutor 接管默认池 + `[stats]` 60s 采样日志(空闲静默);dev SPA技能查看 modal(纯查看+删除,编辑走对话);**用户私有 skill**(`user_root/.skills/`,多来源 registry user wins覆盖显式标注 skill 不崩扫描;写走 host-side `save_skill`/`fork_skill`——fs 工具跨 backend 够不到 user_root)。
- **06-10**:system prompt 瘦身 ~40 + 媒体段按需注入( ARK key 才发);上下文压缩加压力门槛(超阈值才压, DeepSeek 前缀缓存);单轮停机判据从步数解耦为进展信号(`_RepeatGuard` + run `_stall`,max_iterations 降为纯 backstop);systemctl restart 优雅 drain in-flight run(先拒新再等收尾)。
- **06-09**:PPTX 前端在线预览(sofficePDF 复用已有 iframe 路径,缓存+超时 kill);药3 幽灵路径不复现 + 回归测试钉死;ppt 补信息设计纪律件(takeaway/kpi/卡片组合件 + pptx_preview PNG 验观感)。
- **06-08**:loop 加病理性重复调用守卫(`_RepeatGuard` 按指纹累计"无产出重复",SOFT2 提示/HARD4 拦截);检索/抓取 host 工具批量化(单数改列表,一轮并发一批——高轮数烧 token 三股根因之一);ppt 视觉系统升级卡片式;system prompt 少来回原则;ppt 工作流批量化(N ~2N 轮降到 3-4 )。
- **06-06**:前端模块化 Step 2 收官(main.js 271975 行入口, 15 个零构建 ES module); flash 大参数 tool_call arguments 损坏——校验 json.loads 失败丢弃整轮重 roll(不入库,断投毒级联),最多 3 次后降级非流式
- **06-05**:前端模块化 Step 1( 5 个叶子模块);run_python 过程脚本约定落 `scripts/`;新增 standard skill(GB/T 1.12020 自建,重点对接 CSTM 团标)。
- **06-04**:ppt 版式 helper 收进 `pptx_helpers.py` + 修中文字体(`font.name` 只写 latin 是根因, ea/cs);quality_check 加内容形状重叠检测 + 三色制判定(非灰阶 3);前端存储进度条;容器 env 收编 `_CONTAINER_ENV` 三路共用
- **06-03**:修 docker system prompt 焊死宿主路径(容器注入 `/workspace/<wd_rel>`);顺扫清 SKILL.md 残留宿主路径;图标种子库降只读;镜像源改清华/腾讯;workspace 落数据盘改 bind mount(回退 env 覆盖——与相对存储锚点冲突)。
- **06-01**:一键部署 `deploy/update.sh`(pullpipmigratebuildrestarthealthz,自更新重跑守卫); MP 工具全量下载致 IP 被封(补分页);sandbox 镜像加中文字体;documents/MP host-side tools(key 不进 sandbox)。
### 2026-05(骨架→SaaS 化→dev SPA)
- **05-29**:Seedream i2i base64 通路 probe(内网无需对象存储)+ tool_call 标题改中文活动描述
- **05-28**:新增 analyze skill(问题拆解协调器)+ 3 个科学计算 skill(pymatgen/stats_ml/plot_pub,服务无机非金属材料 R&D);`config/models/local.yaml` 接内网模型(涉密专用,thinking_mode=false);Python 3.103.12;LoadSkillTool docker 返容器路径;review 加长文档分章深审
- **05-27**:ppt 歧义先反问(升格 system prompt 通用原则)+ description 白名单收紧路由;skill 热更新每次现扫
- **05-25**:前端 CDN 依赖本地化 vendor/;上传进度/布局拖拽打磨;接入博查 web_search + web_fetch(SSRF 内网屏蔽)。
- **05-22**:dev SPA iframe embed 模式(postMessage 握手,PLATFORM_KEY 不下发浏览器)+ task_id 定位;媒体生成每日配额( 20 /5 视频);产物路径协议刚性化(`<wd_name>/<rel>` 全形式);Seedance 视频生成接入 + videogen skill;移动端自适应。
- **05-21**:新增 imagegen skill(五步法 + BLOCKING 确认防白烧钱)+ documents skill(内部材料学科库);sandbox 阻塞地位写进 DESIGN(shell 黑名单是装饰品,正确防线在 OS 层);task 预选 skill 注入提示;SSE 客户端重连;research fetch_pdf 直链 + pg_trgm 索引;同 wd 并发软警告(Claude Code 同款信任+软警告);paper_server 收编为 research skill。
- **05-20**:LLM 调用切 streaming(cancel 秒退 + 打字机);豆包 Seedream 5.0 接入 + 0007 全表统一 CNY;artifact chip 演进 + seedream 透明性 banner;润色按钮;fs 输出 user_root 相对路径;clear 端点;CLAUDE.md 加「实施前先对方案」。
- **05-19**:0006 task 级模型切换 + usage_events v2(units jsonb 多态);登录撤邀请码复用邮箱密码;SENTINEL user 彻底撤;任务/文件 `⋯` 菜单;proposal mermaid 强制;文件预览弹框。
- **05-18**:入口归位(cli.py→main.py,删 CLI REPL);0004 schema 大瘦身(删 runs,run_status 合入 tasks);files API 升格唯一目录树 mutation 入口(DB-FS 一致性服务端内化);task 级协作式 cancel;单活 run 锁 + 孤儿 reaper;proposal 流程图管线;skill 机制改可选辅助;UI 中文化。
- **05-17**:0003 name+working_dir+skill 三件套(任务标识与目录解耦);tasks 分页+筛选;task=name-based 项目目录(废 UUID 派生,同 name 共享,memory 进 `.memory/` dotfile)。
- **05-15**:§7 D `/v1` JSON API 落地(Phase G Jinja2/HTMX 撤);D' 过渡 auth(PLATFORM_KEY→JWT)+ dev SPA;task_dir 改相对存储(`core/paths.py`);workspace 统一 per-user。
- **05-14 → 05-12**:§7.1 心智修正 Folder-centric→Task 一等公民;§7 B ORM 5 表 + alembic(state.json 全废入 PG);§7 改写 user-direct(多租户方案废弃)。
### 历史(2026-Q1 → 05-11)
- **Phase 1-4**:骨架 / 三 skill / run_python / Model Profile + Probing;ppt v3 商务红 + apply_brand + Iconify;素材摄取改 markitdown CLI。
- **05-06 → 05-11**:Phase 6 部分(task + state.json + tokens 累计);TUI rich + `/resume`;DESIGN §7 初版(05-12 重写);`cli.py export` + `core/export_docx.py`;`atomic_write_text` + `core/memory.py`;loop 事件流化铺 SSE 路。
- **06-04 token 优化启动(DESIGN §8.2)**:chat usage 记 cache hit/miss + cost 兜底;`run_python` 加 `script_path` 模式;`core/context.py` 压缩旧 tool / load_skill(不改持久化历史)。
- **06-05 记账给缓存命中折价**:缓存命中按全价记致成本虚高 2-3x,成本公式拆三段 + 历史 backfill。
---
## 关键决策与偏差
| 项 | 决策 | 备注 |
|---|---|---|
| 工具基目录 | cwd(读)+ working_dir(写) | system prompt 同时注入两者绝对路径 |
| Workspace 布局 | `workspace/users/<user_id>/{.memory/, <name>/}` | per-user 隔离;memory dotfile 防撞;同 name 多 task 共享 |
| Eval Suite | 不做 | 个人工具 dogfooding |
| 版本化 prompt | 直接 `general_v1.md` | 真要切再做 |
| run_python 沙盒 | subprocess + env 过滤 | Docker 在 §7 C 阶段 |
| 兼容层 | 开发期不写 | DB schema / 字段 / API 改动直接切,见 CLAUDE.md |
| `/v1/files/*` 与 DB | files API 作目录树唯一 mutation 入口,DB-FS 一致性服务端内化 | rename / delete 顶层目录 DB-aware |
| 单活 run | task 同时最多 1 个活 run | gate 在 `post_message` 同事务 `SELECT FOR UPDATE` |
| LLM 调用走 streaming | `chat_stream` + `stream_chunk_builder` 拼回;chunk 间 + tool_call 间 poll cancel | cancel 延迟 100ms 级;content delta 即时 emit |
| 上下文压缩 | 加压力门槛,超阈值才压 | 护前缀缓存 + 不丢旧细节(§8.2 / 06-10) |
| 停机判据 | max_iterations 降为 backstop,靠进展信号掐空转 | `_RepeatGuard` + run 级 `_stall`(06-10) |
---
## 文件清单
```
core/capabilities.py 75 ← 模型档案增加 CNY/Mtok 计费兜底字段
core/llm.py 151 ← litellm 离线 cost map env + chat_stream(stream + include_usage)
core/loop.py 300 ← sink.emit + _stream_llm(chunk 间 poll cancel + emit delta)+ _RepeatGuard + usage cache 明细
core/context.py 95 ← LLM 调用前压缩旧 tool / load_skill 消息(带压力门槛),保 tool_call 协议字段
core/sinks.py 101
core/paths.py 50 ← task_dir db form 归一
core/probe.py 243
core/session.py 153 ← ORM
core/task.py 82 ← PG-backed TaskState
core/skills.py 180 ← 多来源 registry(SkillSource)+ source 标记 + 覆盖感知(user wins)+ load_errors + container_dir
core/memory.py 81 ← per-user `.memory/` dotfile
core/export_docx.py 383
core/storage/{__init__,engine,models,usage,utils}.py ← 4 表(0004-0007 演进);record_chat/image_usage
core/ark_client.py 105 ← 火山方舟 HTTP 客户端
core/asr_xfyun.py 170 ← 讯飞语音听写 IAT wss 客户端(整段 PCM→文本;web 语音输入用,diag: scripts/diag_asr.py)
core/asr_lfasr.py 250 ← 讯飞录音文件转写 LFASR 客户端(异步订单 + 说话人分离;transcribe_audio 工具底座,diag: scripts/diag_lfasr.py)
core/agent_builder.py 340 ← 装配 lib(有 ARK_API_KEY 才挂 SeedreamTool);build_skill_registry 装两来源
core/executor.py / sandbox/{network,pool}.py / executor_docker.py ← Executor ABC + Docker per-user 容器池
tools/{base,fs,shell,run_python,skill_tool,skill_authoring,seedream,seedance,web_search,web_fetch,documents,materials_project,transcribe_audio}.py ← skill_authoring=save_skill/fork_skill(host-side 写 user .skills)
main.py ~210 ← 入口:web / db / probe / user / sandbox check
db/migrations/versions/ 0001-0008
web/app.py ~1360 ← /v1 JSON API + user_id 隔离 + run lock + cancel + files + pptx 预览 + skills(列表/正文/删)
web/auth.py ~190 ← 邮箱密码 + platform_key → JWT
web/broker.py / sinks.py / pptx_render.py
web/static/dev.html + js/*.js ← dev SPA 拆 15 个零构建 ES module(main.js 入口;skills.js=技能查看 modal)
web/static/vendor/ ~1 MB ← jszip / docx-preview / xlsx
─────────────────────────────────
Python 合计 ~3400 行(+ dev SPA + vendor 1MB);加 skills 脚本 + 配置,总仓库约 3800 行
```
---
## 下一步候选(性价比排序)
1. **CORS 收紧**(~半小时,已接入真实用户应尽快做)—— `allow_origins``*` 改读 env 域名 allowlist;与 OIDC 解耦。
- **真 OIDC**(~1 天,选做)—— `/v1/auth/login` 内部换 ID token 校验(路由层 Depends 不动);**邮箱密码长期保留并存**。platform_key 信任模型可接受则可延后,真要弃 PLATFORM_KEY 共享密钥时再做(延后无技术债)。
2. **§7 C Executor + sandbox 收尾**(~3-5 天,按 §7.5 落地清单)—— 剩 Step 4 完整 egress proxy + Step 3b PGID kill 协议 + xfs project quota OS 层硬化。**Stage C DoD** = 6 条落地清单全完成 + 红队回归通过(metadata IP / PG IP block、残留进程清理、跨 user 网络隔离、egress allowlist)。**多用户在线跑代码 hard prereq**。
3. **Phase 6 context 第二步 task summary**(~1 天)—— 旧消息压成一条 summary(区分硬约束/计划/文件路径/关键事实),不直接塞回旧 tool 原文。
> §7 B + D + D' + 单活 run 锁 + cancel + 0004 schema 瘦身 + 入口归位 + Stage C 主体已完工。剩余:真 OIDC → C 收尾 → F(deploy/billing)。§7 E CLI 双模式撤;Phase G Jinja2/HTMX 撤(详见 DESIGN §7.9)。