Skip to content

fix(ppt-live): tolerate bad project JSON and degrade unexportable elements#1617

Merged
bobleer merged 1 commit into
GCWing:mainfrom
bobleer:fix/ppt-live-json-contract-and-export-degradation
Jul 18, 2026
Merged

fix(ppt-live): tolerate bad project JSON and degrade unexportable elements#1617
bobleer merged 1 commit into
GCWing:mainfrom
bobleer:fix/ppt-live-json-contract-and-export-degradation

Conversation

@bobleer

@bobleer bobleer commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

背景

PPT Live 的两个高频可用性问题:

  1. 生成中断:agent 写入的 project.json 一旦出现 markdown 围栏、JS 注释、尾随逗号或写入截断,严格 JSON.parse 直接抛出 invalid_project_json,一次续跑失败就"生成未完成"异常结束。
  2. 导出阻断:PPTX 导出管线是 fail-closed 设计——任何一个元素无法表示为可编辑 PowerPoint 几何(典型:pptx-source-NN 的多层/inset/spread box-shadow、text-shadow、filter、SVG paint server 等),整个 deck 导出直接失败。

修改

生成链路:容错 + 让 agent 把活做完

  • deck-project-contract.js 新增容错 JSON 解析链:剥离围栏/注释/尾随逗号 → 截断文档修复(闭合字符串与括号、丢弃不完整尾部片段);仅在全部修复失败后才报 invalid_project_json(仍带定向续跑提示)。
  • 读取重试的 accept 只接受不伪造结构的修复,写入中的文件不会提前被接受。
  • 契约类可恢复错误(坏/缺失 project.json、缺页、deck 不可读)的有界续跑次数从 2 提升到 4:每次续跑都是同一会话内的定向修复(只修 JSON、只补缺页),而不是放弃整份接近完成的 deck。

导出链路:降级而不是阻断

  • 新增 export-degrade.js 降级层:
    • 不支持的样式(box-shadow、text-shadow、filter、mask、animation、background-image、inline margin)→ 就地剥离,元素正常导出;
    • 不可表示的 SVG 构造(paint server、mask、filter、defs 几何、复杂 transform)→ 简化或移除;
    • 无法表示的元素(canvas/video/外部资源等)→ 移除;
    • 修复后仍失败的页 → 替换为简化可编辑场景(纯色背景 + 文本),保证页数不少;
    • OOXML 序列化阶段单页失败 → 替换为空白页。
  • parseBoxShadow 优化:多层 shadow 取首个可用非 inset 层映射为原生 outer shadow;负/柔 spread 按 0 近似;纯 ring 仍走既有的同心 shape 重写。
  • 每次降级都记录并通过 options.onDegrade 汇入导出摘要:新增 degraded 计数与"降级处理"阶段标签,所有降级码均有中英文案。
  • element-model 页面:跳过不可表示的单个元素而不是整页失败。
  • 删除导出路径上的 fail-closed preflight-slide-audit(其阻断项要么被 sanitizer 中和,要么由降级循环处理)。
  • 同步更新 ppt-design authoring 契约(SKILL.md / editable-pptx.md / data-information-visualization.md / agent-prompt.js)与 README,描述新的降级行为。

验证

  • node --test src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/test/*.test.mjs:181/181 通过(含新增的多层 shadow、负 spread、inset 剥离、text-shadow 剥离、元素跳过、简化场景、容错 JSON 等用例)。
  • cargo check -p bitfun-product-domains 通过。
  • builtin-ppt-live 版本号 231 → 232(meta.json / bundle.json / builtin.rs 三处一致),bundle 已重建。

…ments

Generation:
- Parse agent-written project.json tolerantly: strip markdown fences,
  JS comments and trailing commas, and repair truncated documents,
  instead of aborting the whole generation on invalid_project_json.
- Retry recoverable file-contract failures (bad/missing project.json,
  missing slides, unreadable deck) with more bounded continuation
  attempts so the agent finishes the deck in the same session.

Export:
- Add an export degradation layer (export-degrade.js): unsupported
  styles (box-shadow, text-shadow, filter, mask, animation, background
  images, inline margins) are stripped, unrepresentable SVG constructs
  are simplified or removed, unexportable elements are removed, and a
  slide that still fails is replaced with a simplified editable scene.
- Map multi-layer and negative/soft-spread box-shadows to the first
  usable native outer shadow layer instead of blocking.
- Guard OOXML serialization per slide: a scene that fails to serialize
  is replaced with a blank slide instead of failing the whole deck.
- Report every degradation in the export summary (new 'degraded' count
  and phase, localized reasons for all degrade codes).
- Update the ppt-design authoring contract to describe degradation and
  drop the retired fail-closed preflight audit from the export path.

Bump builtin-ppt-live to version 232.
@bobleer
bobleer merged commit 519c685 into GCWing:main Jul 18, 2026
5 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.

1 participant