Skip to content

feat(slides): semantic-v3 分批落页与收敛策略 + Agent 调试台历史归档/离线回放 + 桌面执行时间线与进度卡 - #319

Merged
21335464876 merged 16 commits into
devfrom
feat/slides-layout-tree
Oct 26, 2026
Merged

21335464876 merged 16 commits into
devfrom
feat/slides-layout-tree

Conversation

@lzp-plus

Copy link
Copy Markdown
Collaborator

概要

在 #315 已合入 dev 的基础上,继续集成 feat/slides-layout-tree 上的排版链路收口与 Agent 调试台持久化改造(14 个提交,196 个文件,+29462/−5220)。

1. Agent 调试台:历史归档与离线回放

  • 终态 run 异步落盘 <dataDir>/agent-debug/<source>/(index.json + runs/YYYYMMDD/<runId>.ndjson):临时文件 + rename 原子写、串行队列、索引损坏自愈、按 7 天 / 2000 条 / 1 GiB 裁剪;NXCORE_AGENT_DEBUG_ARCHIVE(_DAYS|_RUNS|_MAX_MB) 控制,关闭即完全不写盘。
  • snapshot 新增 archived=include|only|exclude 与 archive 概况;run 带 origin,并按查询补全 sessionTitle;dispose() 改 async,运行中 run 先按 interrupted 收尾落盘。
  • dev server 新增 archive 只读数据来源:EverRoom 未启动也能直接读磁盘历史;来源带 backend/available/archiveDir/runCount/latestStartedAt,按「可用 live → 归档 → 不可用 live」排序、失效自动回落。
  • 逐页任务页序:契约新增 slidePageIndex/slidePageCount,调试页显示 P3/12 徽标,Agent 行聚合运行中页序(连续段压缩为 P1–P16)。
  • 文档 docs/agent-debug-persistence.zh-CN.md、docs/agent-debug-offline-archive.zh-CN.md,冒烟脚本 3 个。

2. slides:semantic-v3 单一路径与分批落页

  • 分批流水线:内容批次一就绪即推进落页,existingDeck 续落只补未落定页;layouter 契约新增 blocked;检查点表 0083_slides_generation_checkpoints.sql 记录批次/deck 进度/预算快照。
  • 生成预算默认不设限(字段缺省或 Infinity 即不限,仅显式有限值限流);冒烟期墙钟放宽(planner/builder/layouter 1800s、layouter 输出 131072、planner 去 maxToolCalls),slides_draft 并发等待 20min。
  • 提交校验收口:连续 3 次未过改报 unrecoverable 并引导 blocked;讲稿以 content.notes 为唯一权威回填;notes 归一抽成 normalizeSpeakerNotes 单一口径。
  • emoji 判定与 genoffice 引擎对齐(不再把 2190–21FF 箭头当 emoji),修「→」等必留文本导致 validate 永不禁敛、页级空转 1800s 的根因。
  • layouter 收敛策略(SYSTEM.md / SKILL):单页定稿、validate ≤4 次、warning 只做一次确定性降级、提交前自检、单页 submit ≤3 次;相似页重排跳过 skipped/blocked 页。
  • slides_draft 参数 schema 按 task 拆分 Union(draft/style/style_select/generate/edit),style 续接按 draftDocumentId 反查最新风格会话。

3. desktop

  • 执行时间线:工具名 → 文案/图标改显式映射表(agent/analysis/document/slides/task 等分类,未知才归 other),补中英文案。
  • PPT 进度卡:用户做出选择后立即收起;失败/中断紧凑态可直接重试;工具失败不再弹遮挡式 toast。
  • 产物未打开时自动打开改「catalog 优先、legacy 兜底」;catalogEntry 分页兜底(目录超过一页也能按 id 命中);Room 内显式上传跳过 ingest 噪音过滤;子代理执行行显示上下文用量圆环。

4. 其他

  • agent-runtime-pi:DeepSeek 显式关思考、上下文预算改按真实 usage 与中文口径核算。
  • 新增/更新文档与脚本;移除本地草稿笔记(.gitignore 补充)。

Evidence

  • pnpm typecheck 等价检查本地通过(gateway / desktop / agent-contract / agent-runtime-pi)。
  • 定向测试全绿:gateway agent-debug(36) / agent-debug-archive(14) / config(28) / subagent-tools(59) / slides-layouter(13) / slides-layout-tail(30) / subagents(26) / slides-generation-harness(10);desktop agent-debug 系列(103) / 工具映射与进度卡(61),以及 test:ci 门禁(gateway config+server 47 条、desktop gateway-supervisor+memory-onboarding+saas-client 20 条)。
  • node scripts/render-layout-skills.mjs --check 通过。
  • 冒烟脚本:scripts/agent-debug-smoke.mjs、agent-debug-archive-e2e.mjs、agent-debug-offline-smoke.mjs。

Merge Danger

Door: two-way(回滚 = revert 本 PR;子模块需把 apps/desktop/vendor/genoffice 拨回 fbc2d8e)

Blast Radius:

  1. 子模块 apps/desktop/vendor/genoffice 指针 fbc2d8e → 407d822(已推送至 feat/everroom-ai-tab):新增组件画廊 PPTX 构建脚本;桌面端需重新 build 运行时产物。
  2. 新增迁移 0083_slides_generation_checkpoints.sql:只加表,不改存量数据。
  3. 生成链路默认不再设预算上限,只受父级取消与各 bundle timeoutSeconds 约束;需要硬边界的宿主可显式传 slidesGenerationBudget。
  4. Agent 调试台归档默认写 <dataDir>/agent-debug/(env 可关),不写业务库、不影响产品链路。

- 新增忽略规则:本地工作区/评测产物(.local/、worktrees/)、IDE 配置、
  测试与构建产物(coverage/、*.tsbuildinfo、.turbo/)、Electron 主进程打包
  产物 /index.js、外部资料 PDF。
- 本地草稿/调研笔记(feishu-notion-*.md、测试要点-*.md)只留本机:
  从仓库移除已入库的 3 份调研纪要与 2 份测试要点。
- planner:输入/输出 schema 换成语义契约(contentMode 恒 semantic-v3、
  sources/draftPages、pages[].content 为语义页),预算按整册一次成稿放宽
  (maxToolCalls 80、timeout 900s,思考关、输出上限 65536)。
- layouter:说明书改为按内容重点自主构图 + 渲染图自审;技能拆成基础语法
  与 components/legacy 参考,SKILL.md 与 components.md 仍由
  scripts/render-layout-skills.mjs 从权威正文生成。
- editor:收敛为语义指定页修复器(storyboard/v3);styler/builder 说明书
  与 schema 同步新链路用语。
- 删除 slides-reviewer 代理及其两份布局技能:审页改由 layouter 看着渲染图
  自审,不再有独立审页派发。
- deepseek 系模型:显式声明 thinkingFormat: deepseek。此前 reasoning:"off"
  只是不发 reasoning 参数,上游仍默认先思考(实测对「1+1」也烧 64 token),
  编排/落页这类长任务白烧几分钟;声明后 thinkingLevel=off 才落到
  thinking:{type:"disabled"}。其它 provider 行为不变。
- 上下文预算:新增 estimateContextTokens(ASCII 走 chars/4、中文按字计),
  guardRunMessages 优先用 pi session.getContextUsage() 的真实 usage,拿不到
  才退回估算。旧口径对中文 + JSON 内容低估一半(113k 真实 token 只估到
  52.7k),64k 阈值永不触发、只能靠 pi overflow 压缩兜底。
- agent-contract:SubagentInvocationNode 增加 contextUsage / contextCompacting,
  供调用树透出每个子代理自己的用量快照与压缩态。
- 新增测试覆盖 deepseek 关闭思考的请求体、中文 token 估算与真实 usage 裁剪。
- 语义内容链路:新增 slides-semantic-contract / stage / bindings——planner
  输出按语义页契约归位与校验(来源覆盖、数字一致性、哈希),页级绑定核对
  真正渲染出来的内容;内容只有 semantic-v3 一条路径,NXCORE_SLIDES_CONTENT_MODE
  开关删除。
- 分批编排:arrange 按 6~8 页切批,单批独立失败/重试/checkpoint,合并后仍走
  整册语义校验;素材检索前移到网关(materialHits 随输入下发),配图预热由
  网关统一入池,planner 工具面收紧(去 material_search、conversation_search
  限 2 次、文档读取只回正文与分页字段)。
- 并发:子代理按 slides / default / background 三池隔离(默认 16 / 4 / 2,
  全池总上限不变),新增 NXCORE_SLIDES_DECK_CONCURRENCY=16 与
  NXCORE_SUBAGENT_SLIDES_* 配置,单册页级窗口与典型页数对齐。
- 布局:新增 v3 骨架(按 form × emphasis × 内容量选骨架、容量不协商),
  落页后把该页渲染图直投布局模型自审(取代独立审页代理),删除
  review-context / page-preview-context / materials/agent-tool。
- 视觉档:slidesReviewerPi 更名 slidesVisionPi,支持从 SaaS vlm 槽或主模型
  (NXCORE_SUBAGENT_SLIDES_VISION_SOURCE=background)取模。
- .env.example 同步说明 content mode 开关已删除。
- 抽出 contextUsageRing 组件:composer 与执行时间线共用同一套圆环与文案
  (≥85% 换警示色、压缩中呼吸、点击展开占用构成)。
- 子代理摘要行在名字旁内联该子代理自己的用量圆环,数字收在悬停 title;
  轮询签名纳入用量/压缩态,快照变化会触发重渲染。
- 测试覆盖内联圆环与名字的顺序、高占用警示色、只有压缩信号时的呼吸态。
- 写入格式仍是 v2 页面,但 composition 不再由输入模式决定:语义内容下
  Layouter 按内容重点自主选择构图与分区。
- 说明 SKILL.md 与 components.md 由 scripts/render-layout-skills.mjs 从本文
  生成,旧模式契约移到 legacy.md;notes 超出容量时报阻塞而非截断。
- 组件/style/table/group 等规则按新链路更新措辞:组件参数以组件参考为准,
  style 用语义枚举,结构化表格保留表头与行列顺序。
catalogEntry 此前只查 listCatalog(200, 0):目录超过 200 条后,历史产物按 id
查永远 404(桌面端「未打开产物自动打开」、@ 文件引用取当前版本都走它)。
改为先查首页,未命中再按 total 分页扫描兜底。

补 file-catalog 回归:250 条目录中第 2 页的条目仍可命中,缺失 id 返回 null。
用户显式指定 roomId(Room 内上传/导入)=明确保存意图,与 web-clipper 同等
豁免过滤器。否则缺 AI 描述的图片只有占位正文,过滤器按「空内容」整批拦下:
文件已入库却在 Room 里静默消失(2026-10-23 实证:14 张 jpg 中被误杀 9 张)。

补 ingest-filter 回归:显式 roomId 不过闸、直接扇出并带 entryRoomId。
requestRendererOpen 此前只查 files.get()(legacy uploaded_files),而 agent
生成/导入的产物都在 catalog(file_entries),因此 agent 生成的 PPT 永远
file_not_found,「未打开自动打开」从未成功过。

改为先查 catalogEntry,未命中再退回 legacy get();补两条回归:catalog 命中
不调 legacy、catalog 未命中回退 get。
.tmp-inspect/ 是本地调试用 SQLite 快照(单文件 370MB+),只留本机不入库。
落页链路(slides-layout-tail / tools)
- 分批流水线:内容批次一通过契约就推进落页尾部(异步页流),首批完成即开始
  落页,不再等整册编排;落页后立即异步自审(4 路并发),先落页、后提质。
- 续落:existingDeck 复用同一 deck 文件,只补未落定页;配图确认/中断恢复走
  同一路径,落页进度写回 plan.__deck。
- layouter 契约新增 blocked 分支(reason/attempts/requestedAction),不再用
  done 伪装阻塞;工具调用预算改为可选(不声明=不设上限),timeout 放宽。
- 「桌面端未打开该 PPT」导致的落页被拒单独标记,最终载荷给出可重试原因。

生成预算与断点(新模块)
- SlidesGenerationBudget:30min / 2M token / 128 次调用,统一约束编排、修复、
  布局与视觉复检;abort 传播到 dispatch、awaitCapacity 与页级重试,中断时
  保留已落页面与草稿。
- slides_generation_checkpoints 表 + Store:key 含内容、agent 版本与模型配置,
  记录批次、deck 进度与预算快照,重启后只补失败批次。

内容契约与模型口径
- planner 输入支持网关预取 sourceDocuments(40k 字符/篇),工具侧跳过重复
  读文档;arrange schema 精简为页级必填,draft 保持宽松;同步输入/输出 schema
  与测试。
- 删除 slides reviewer / vision 槽的独立预算与 env(NXCORE_AI_SLIDES_REVIEWER*、
  NXCORE_SUBAGENT_SLIDES_VISION_SOURCE):主模型已多模态,layouter 与主 Agent
  同底座;slides bundle 显式 32k 输出、low 思考档。
- runtime-pi:usage 改在 message_end 记账,随 context.usage 下发 runUsage,
  预算与调试页按真实用量核算。

Agent 调试台(新功能,独立于产品 UI)
- Gateway 内存 trace(run/事件环形缓冲,不落库)+ /v1/agent-debug/* 只读接口;
  内置 / dispatch-only / 本机 CLI Agent 在 runtime 边界统一埋点。
- 桌面端独立 vite 调试页:Agent 列表、run 时间线、工具/思考流、原始事件与 JSON;
  `pnpm debug:agents` 启动。
- 文档 docs/agent-debug-page.zh-CN.md、冒烟脚本与只读数据契约。

其他
- 新增的「共享 token 预算」用例漏注册 slides-builder,slides_draft 工具不会
  创建,补上注册后通过。
- 补齐 slides 语义链路/分批/布局计划文档、语义评测与并发阶梯脚本、schema
  同步脚本。
Agent 调试台:历史归档与会话找回
- 新增 AgentDebugArchive:终态 run 异步写 <dataDir>/agent-debug/<source>
  (index.json + runs/YYYYMMDD/<runId>.ndjson),tmp+rename 原子写、串行队列;
  index.json 缺失/损坏时扫描重建;默认保留 7 天 / 2000 条 / 1 GiB 并按最旧裁剪;
  NXCORE_AGENT_DEBUG_ARCHIVE(_DAYS|_RUNS|_MAX_MB) 控制,关闭时完全不写盘。
- trace-store:listRuns(limit, archived=include|only|exclude) 合并内存与归档
  (同 runId 以内存为准),getRun/listEvents 内存未命中回落到归档;dispose()
  改 async——运行中的 run 先按 interrupted 收尾落盘,再等写盘队列排空并清缓冲,
  Gateway onClose await 它。
- 契约:新增 AgentDebugRunOrigin / AgentDebugArchiveInfo;run 带 origin,并新增
  查询时补全的 sessionTitle(唯一 sessionId 一次批量查 agent_sessions,
  子 Agent / 已删除会话为 null,不落归档)。
- 调试页:范围三态(全部/本次/历史)、会话筛选与会话分组、历史模式默认选最新
  归档 run、归档关闭时禁用历史入口;筛选/分组纯函数拆到
  history/browseOrder/useBrowsingList 并补单测。
- 文档 docs/agent-debug-persistence.zh-CN.md 并更新调试台总览;
  新增 scripts/agent-debug-archive-e2e.mjs 端到端脚本。

slides 子代理与执行时间线
- 生成预算默认不设上限(DEFAULT_GENERATION_BUDGET 改为空对象):字段缺省或
  Infinity 即该维度不设限,只有显式有限值才限流;remainingMs 未设限返回 Infinity。
- 放宽冒烟期墙钟与容量等待:planner/builder/layouter 1800s、layouter 输出预算
  131072、planner 去掉 maxToolCalls;slides_draft 并发等待预算放宽到 20min,
  arrange 单批不再额外收紧超时并放宽重试等待。
- 提交期内容校验连续 3 次不过改报 unrecoverable 并引导 blocked,避免
  validate↔submit 空转撞墙钟;讲稿以 content.notes 为唯一权威回填,
  避免模型改写导致「讲稿未完整保留」永远提交不过。
- emoji 判定与 genoffice 引擎对齐(不再把 2190–21FF 箭头当 emoji),修「→」等
  必留文本导致 validate 永不禁敛、页级空转 1800s 的根因;notes 归一抽成
  normalizeSpeakerNotes,schema 归一/内容校验/落页编译共用同一口径。
- layouter 交回的 designIntent 传入视觉自审;checkpoint 收口到最终状态;
  相似页重排跳过 skipped/blocked 页;style 续接按 draftDocumentId 反查最新
  风格会话,slides_draft 的 style 不再强制要求草稿 id。
- 桌面端:工具时间线改显式「工具名 → 文案/图标」映射表(补 agent/analysis/
  document/slides/task 等分类与 i18n 文案,未知工具才归 other);PPT 进度卡
  做出选择后立即收起,失败/中断的紧凑卡可直接重试,工具失败不再弹遮挡式 toast。

其他
- 单测同步:subagents.test 的 layouter 输出上限改为 131072;补归档、历史浏览、
  工具映射与进度卡用例。
- 文档同步:slides-arrange-batching / slides-layout-tree-spec /
  slides-subagent-harness;.env.example 补归档相关 env 说明。
离线归档来源(dev server 侧,只读)
- vite.agent-debug.config.mts 新增 archive 数据来源:直接读
  <dataDir>/agent-debug/<source>/ 的 index.json + runs/*.ndjson,按与 Gateway 相同的
  接口形状响应 /v1/agent-debug/{snapshot,runs/:id/events},不经过 Gateway 也不需要
  Gateway 进程存活;归档目录从 manifest 的 dataDir 扫描发现、按目录去重。
- 新增 apps/desktop/debug/host/archive-source.ts:index 按 mtime 缓存、坏行/坏文件
  跳过、只读读取;archive 来源 id = archive- + sha1(归档目录) 前 12 位(跨重启稳定),
  label 按 main/cursor-completion 语义化为「历史归档 · 主网关 / 补全服务」。
- sources 响应扩展 backend / available / archiveDir / runCount / latestStartedAt
  (均为可选,旧 dev server 按缺省值兼容);live 来源用 manifest pid 做存活探测。
- 调试页:来源下拉区分 live 与「历史归档 · 只读」,按「可用 live → archive →
  不可用 live」排序并默认选中可用来源;live 失效(EverRoom 退出)自动回落到归档;
  选中归档来源时范围锁定在「历史」,「本次」不可点。
- 文档 docs/agent-debug-offline-archive.zh-CN.md + 冒烟脚本
  scripts/agent-debug-offline-smoke.mjs。

逐页任务页序
- 契约新增 slidePageIndex / slidePageCount;Gateway 从子 Agent dispatch input 的
  0 起 pageIndex 换算成 1 起页序,随 run 元数据落归档;非逐页/非法值不写。
- 调试页 Run 行显示 P3/12 徽标,Agent 行按 Agent 聚合运行中页序并把连续段压缩成
  P1–P16 / P1–P3 P7 +2;纯函数拆到 slidePage.ts 并补单测。

slides-layouter 收敛策略(提示词/SKILL)
- 单页定稿:validate 每页最多 4 次,第一次 ok:true 后立即提交、不再做变体;
  同一缺陷改 2 次不消失就按「删装饰 → 合并卡片 → 降层级 → 换简单 composition」
  简化后校验一次提交,仍不行走 blocked,禁止整页重画。
- image_ar / min_size / contrast 等 warning 只做一次确定性降级,不带已知缺陷硬交。
- 提交前自检 designIntent、mustShow bindings、notes 与 content.notes 逐字一致;
  单页 submit 最多 3 次,超限改交 blocked。

其他
- 新增 archive-source / slide-pages / sources 单测,补 history 与 gateway
  agent-debug 用例(逐页页序换算、非逐页不写字段)。
- tsconfig include 补 debug/ 与 agent-debug vite 配置,纳入类型检查。
- 同步 docs/agent-debug-page.zh-CN.md。
genoffice 侧新增 apps/slides/genoffice-build-pages-v2.mts:读 gallery specs,
逐页走 parsePageSpec + buildPagePptx 真机同链,用于 EverRoom 布局落页的
本地对比与回归复现。
@21335464876
21335464876 merged commit 64d941b into dev Oct 26, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants