OpenProgram · 设计 · 运行时 / UI

嵌套 LLM 节点内容:聊天式有序块

展开 LLM 节点后,按执行顺序显示完整可展示内容:Markdown 正文、思考摘要、函数引用、并行组、重试边界。复用聊天窗口组件。取消固定的「LLM Reply / Reasoning」分区;底层仍区分内容类型。本页定义当前协议、持久化和 UI 语义。

权威设计 扩展 execution_stream.v1,不另起聊天协议 流式、DAG 与持久化使用同一身份 对照:agentic-llm-streaming.zh.html

0. 现状复核(对照最新代码)

能力实现边界必须保持的约束
execution_stream.v1每个嵌套 LLM 节点维护 attempt 与有序 blocks;块包含 text、reasoning_summary、tool_ref、tool_arguments、refusal 等类型。所有增量和 snapshot 都使用相同的 block_id、block_index;前端不根据 WS 到达时间重排。
DAG / tool identity工具节点的 metadata 保存原始 tool_call_id 与 qualified tool_call_occurrence_id;tool_ref 只保存引用的 ref_node_id、名称和 occurrence。同一个 occurrence 只能对应一个工具行;provider 重新使用原始 call id 时,按 round/message-qualified occurrence 建立新行。参数、进度、结果和错误从该 DAG 节点读取,不能在 stream 中复制第二份终态数据。
attempt 语义正常工具结果后的模型请求仍属于当前 attempt;传输失败、结构化输出失败等真正恢复才创建新 attempt。turn_end 只表示一次 provider round 结束,不自动创建 attempt 边界;新 attempt 必须有明确失败原因。
持久化checkpoint、metadata.stream、live snapshot 和 terminal snapshot 都包含完整可展示 attempts/blocks(受 retention 策略约束);legacy preview 字段仍可截断。owner 消失或 worker 重启后,历史读取接口只凭持久化 snapshot 恢复顺序、引用和终态,不重新调用模型。live snapshot 也不能静默丢失 Markdown 前缀。
工具引用身份:不重复传输工具参数/结果全文。工具执行入口在创建或发现 DAG 工具节点时写入原始 tool_call_id 和 qualified occurrence,stream 再通过 occurrence_id → ref_node_id 发布引用。映射未及时可见时先发布带稳定 occurrence 的占位行,随后用同一 block_id 补齐 ref_node_id;不能改成第二行或伪造完成状态。
现有 tool_arguments 块适合「参数仍在生成」的瞬时预览;终态展示以树节点为准,避免双源真相。

1. 展开后如何排列

2. 执行树与节点内容的职责

视图用途
执行树调用关系、并行分支、运行状态、耗时、失败位置
节点内容该 LLM 节点内部按序发生的正文 / 思考 / 函数引用

3. 函数内部再调模型

4. 并行函数

5. 有序块协议(扩展 execution_stream.v1)

每个 LLM node_id 在每次 attempt 内维护有序 blocks[]。顺序由执行端确定;前端不得按 WS 到达时间猜测。

块 kind必要字段说明
textblock_id, content, statusMarkdown 正文;流式 delta
reasoning_summaryblock_id, content, status, retention可展示思考;策略可省略持久化
tool_refblock_id, tool_call_id, occurrence_id, node_id, optional group_id引用树节点;不内嵌结果全文。occurrence 缺失时仅兼容旧记录。
tool_arguments(可保留)参数流式预览;终态以树为准
parallel_groupgroup_id, ordered tool_ref ids并行外壳;组 id 由执行端产生;子引用保持发起序。没有明确并发批次时不得创建。
attempt_boundaryattempt_id, reason, status失败重试边界;旧 attempt 折叠保留
refusal / unsupported已有保持

继续生成 vs 失败重试

{
  "type": "execution_stream",
  "schema_version": 1,
  "op": "block_started",
  "node_id": "call_9f3e",
  "attempt_id": "att_2",
  "block_id": "blk_tool_7",
  "block_index": 4,
  "kind": "tool_ref",
  "tool_call_id": "call_abc",
  "occurrence_id": "occ_7e4c",
  "ref_node_id": "exec_read_file_01",
  "group_id": "par_1"
}

6. Markdown 流式与滚动

7. 断线 / 刷新 / 失败

8. 实现顺序

  1. 有序块协议 + 持久化:扩展 kind;tool_ref / parallel_group;metadata 与 checkpoint 写入完整 attempt.blocks。
  2. 统一内容组件 LlmNodeContent:复用 chat Markdown / 思考折叠 / 函数行(只读树)。
  3. 接入节点详情:去掉 Reply/Reasoning 分区;验证序列、刷新、恢复。
  4. 卡片展开复用同一组件。
  5. 并行、递归、重试边界、滚动验收。
任一阶段不得缩成「先拼两个字符串再慢慢加」——那会破坏顺序契约。

9. 验收场景(必须)

模型先输出 Markdown → 并行调用两个函数 → 其中一个函数内部再调模型(含 read_file)→ 外层继续输出;期间断线并刷新。恢复后:块顺序、函数状态、层级与断线前一致。

实现状态

范围状态证据边界
协议与状态合并已实现CallStreamState、execution-stream reducer 与协议测试覆盖有序 blocks、tool_ref、attempt 和版本恢复。
统一节点内容组件已实现卡片展开和右侧详情使用 LlmNodeContent;Markdown、思考折叠、工具引用和 earlier attempt 使用同一渲染路径。
权限边界、展开状态与递归详情已实现隐藏节点在投影前丢弃;io/llm 仅显示允许的后代;节点/attempt/block 展开状态持久化;递归超过 8 层显示详情入口。
工具身份、正常续写、并行事件一致性本任务修复以真实 DAG 节点映射、同一 attempt 续写和显式并行批次为验收边界。
owner 消失 / worker 重启后的完整恢复本任务修复以持久化 snapshot 和历史读取接口的可观测结果为准;真实模型长任务仍需现场验收。
真实模型与默认 App 验收待现场执行需要在默认 profile、端口 18100、现有 App 中执行确定性 nested tool 场景;本页不把单元测试当作现场验收。

交互示意