14 KiB
03.sdk_and_coreapp 第 3 次设计评审记录
评审编号:03 评审日期:2026-08-05 评审对象:03.sdk_and_coreapp.md 参考资料:APP架构设计.md、01.design_review.md、02.design_review.md 评审方式:基于当前主定义的独立只读复核;重点检查已确认的边界在契约、实施步骤与验收目标之间是否能够由同一套实现兑现。 结论:产品层级、标准交互归属和受限 MiniApp 信任模型已稳定;未发现 P0 架构冲突。经本轮统一收敛,3 项 P1 与 2 项 P3 均已确认并回填主定义文档;后续不再进行纯设计评审,直接进入实现,并在实现完成后做一次关闭式复核。
问题清单(Outline)
状态标记: ✅ 已确认并回填设计; 🟡 待产品/架构决策; 🔵 待在契约中细化; ⚪ 文档或实施编排建议; — 不适用或无此问题。
本清单是本次评审的当前有效视图。后文说明问题为何会造成实现分歧,并给出需要冻结的最小决策;在问题确认前,建议不是实施依据。确认后应先更新本清单,再回填 03.sdk_and_coreapp.md 的契约、实施步骤和验收项。
| 状态 | 编号 | 问题 | 当前结论 / 下一步 |
|---|---|---|---|
| — | P0 | 阻塞级架构冲突 | 未发现。Runtime 为唯一通信与裁决方、标准交互属于 Interact、bundled MiniApp 受限运行的主线一致。 |
| ✅ | P1-1 | 用户关闭 App 时,尚未结束的普通 MiniApp Tool 怎样收敛 | 已确认并回填:一旦 Runtime 接受关闭,未终态的普通 Tool 原子转为 cancelled(app_closed);已提交结果只继续 outbox;随后关闭 Surface、停止 instance、结束子会话并恢复焦点。标准交互不自动取消。 |
| ✅ | P1-2 | Agent dismiss 等待中的标准交互,缺少可执行的控制契约 |
已确认并回填:Runtime 私有 interaction.dismiss 以 control_id + call_id 请求;Runtime 从受认证 Envelope 推导 Agent/会话,幂等处理并只写唯一 cancelled outbox。App 已关闭事件带出仍 pending 的交互 call_id。 |
| ✅ | P1-3 | interactive Tool 如何确定 App 子会话关联,和通用 ToolDescriptor.target 怎样一致 |
已确认并回填:无 app_session_context 一律归主 IM;有上下文时 Runtime 验证同 Agent、同父会话的 App 子会话,已关闭会话可仅作历史关联。interactive 不使用普通 Tool target。 |
| ✅ | P3-1 | 标准交互请求类型不能直接作为 fixture 或代码依据 | 已确认并回填:去除重复字段,定义请求联合类型;可回答交互使用 Runtime 计算的 expires_in_ms,默认 15 分钟、范围 1 分钟至 24 小时;notice 不接受期限。 |
| ✅ | P3-2 | Whiteboard 的完成后关闭表述与统一生命周期规则冲突 | 已确认并回填:所有 bundled App 的普通 Tool 完成只结束 Tool;关闭 Surface/instance/子会话只能由显式 Lifecycle 关闭处理。重复目录条目已删除。 |
通过项
Interact是唯一kind = systemMiniApp;Task Dashboard 与 Whiteboard 均是kind = bundled,没有可信 Host DOM、Tauri、Transport、Store、Agent 或任意网络特权。notice / choice / confirm / input始终是人与 Agent 的会话交互,不进入任何 MiniApp SDK Inbox 或sdk.tools.subscribe;前台 bundled App 上的视觉覆盖不成为 owner 或提交权限。- Runtime 保存交互归属并以原子状态写入决定唯一结果;用户首次有效回答、Agent dismiss、到期和 Runtime 失败不会产生多条 Agent outbox。
- App 子会话只保存人与 Agent 围绕 App 的交互,不记录 Dashboard 表单、画板编辑等 App 内部业务动作;关闭 App 不自动取消仍 pending 的 Interact 交互。
- 普通
input按现有 IM 内容与日志基线处理;秘密输入已正确作为未来独立的password-inputP4 遗留事项保留在 02.design_review.md。
P0:阻塞问题
无。
P1:开始相关编码前必须确认(均已解决)
P1-1:用户关闭 App 时,尚未结束的普通 MiniApp Tool 怎样收敛
用人话说: 用户把 Task Dashboard 或 Whiteboard 关掉时,Runtime 不能让刚才交给那个 App 的工作 悬在半空。Agent 要么收到“这项工作已取消/失败”的唯一结果,要么 Runtime 明确保留一个可恢复、仍有执行者 的工作;不能只关闭画面而不说明 Tool 的命运。
当前文档同时出现了三种没有被统一的说法:
Task Dashboard Tool 完成
→ 不自动关闭 Dashboard 或 App 子会话
Whiteboard App 完成或失败
→ Runtime 关闭 Surface、恢复 Interact
MiniApp requestClose()
→ Runtime 检查 pending Tool、Surface、operation 和 Policy
→ 允许关闭或返回拒绝码
最后一条没有说明“检查之后”的规则。若用户关闭正在执行 Tool 的 App,Tool 是被拒绝关闭、由 Runtime 先取消 Tool、由 App 收到取消后再关闭,还是允许 Surface 消失但实例在后台恢复执行?这些选择对 outbox、恢复和用户 看到的状态都不同。Whiteboard 的“完成后关闭”也与 Task Dashboard 的“完成不关闭”相互冲突。
已确认(2026-08-05): 一旦 Runtime 接受用户、MiniApp 或 Policy 的关闭请求,关闭的意思就是释放该
App instance,不是把它偷偷留在后台。Runtime 不再向该 instance 投递新 Tool;对绑定该 instance 且仍为
received / routing / waiting_for_app / running 的普通 Tool,以 app_closed 原因原子转为 cancelled,并且
每条 Tool 只写一条 cancelled outbox。已处于 submitted 的 Tool 结果不可改写,Runtime 继续将已固定的结果
可靠发出。之后 Runtime 关闭 Surface、停止 instance、结束 App 子会话并恢复前一有效前台 App。
同一时刻 Tool 完成与关闭竞争时,第一个原子终态写入获胜;重复关闭、重启恢复和迟到上报不得产生第二条 outbox。用户若只想暂时离开 App,应进入后台而不是关闭。此规则只处理普通 MiniApp Tool;仍 pending 的 人与 Agent 标准交互不自动取消,Runtime 仅通知 Agent,由 Agent 选择是否 dismiss。
以下原“需要冻结”的项目均由上述决议覆盖:
- 对每种 Tool 状态(
waiting_for_app、running、submitted等),规定用户/Policy 请求关闭时的行为; - 规定普通 Tool 的最终结果由谁写入、是否必须先让 Tool 进入
completed / failed / cancelled / expired才能完成关闭; - 明确“关闭 App instance”“关闭该 App 的 Surface”“Tool 成功/失败”三者不是同一个事件,并定义允许的先后顺序;
- 将 Task Dashboard 与 Whiteboard 的完成、关闭和焦点恢复规则统一到同一条生命周期原则;
- 增加关闭进行中 Tool、重启恢复和重复关闭只产生一个最终 Tool outbox 的验收 fixture。
P1-2:Agent dismiss 等待中的标准交互,缺少可执行的控制契约
用人话说: 文档已经允许 Agent 看到“画板已关闭”后,决定把之前的问题收起来。这很好;但还没有写清 Agent 发来的“收起这题”消息长什么样,Runtime 怎么确认它收的是正确那一道题,以及网络重发时如何不重复 通知 Agent。实现者因此可能各自发明一个临时控制消息。
当前仅有行为描述:
Agent remote dismiss
→ Runtime 将 pending / presented interaction 终结为 cancelled
→ 写入唯一 cancelled outbox
但缺少下面的契约:
- Agent 发起
dismiss使用interaction_id、原始call_id,还是二者都使用; - Runtime 如何从已保存记录校验
agent_id、conversation_id与当前状态,而不是信任客户端字段; - 目标已回答、已到期或同一条 dismiss 重放时,应得到何种稳定回执,是否绝不新增 outbox;
- Runtime 发出的 App 已关闭事件如何关联原 Tool/interaction,使 Agent 能准确选择要 dismiss 的问题;
- dismiss 控制请求本身如何去重、审计并在 Runtime 重启后恢复处理。
已确认(2026-08-05): 定义 Runtime 私有的 Agent → Runtime interaction.dismiss 控制契约。Agent 使用
自己发起原 interactive Tool 时持有的 call_id 定位目标,并为每次控制请求提供唯一 control_id。Runtime 从
受认证 Envelope 取得 agent_id 与 conversation_id,不信任请求额外携带的归属字段;它以这两个值和
call_id 查找交互,原子地将仍 pending / presented 的记录转为 cancelled 并写入唯一 outbox。已终态或重放
请求只返回稳定幂等回执,不覆盖结果、不再写 outbox。
App 已关闭事件会携带仍 pending 的 pending_interaction_call_ids,让 Agent 能按业务需要精确 dismiss;该控制
契约不属于 MiniApp SDK,也不能投递给 Interact 或 bundled MiniApp。
P1-3:interactive Tool 如何确定 App 子会话关联,和通用 ToolDescriptor.target 怎样一致
用人话说: 视觉上哪个 App 在前台,不等于 Agent 的问题就属于哪个 App。例如用户正看 Whiteboard, Agent 仍可能问一条普通 IM 问题;反过来,画板已经关了,Agent 仍可能针对刚才的画板提问。因此 Runtime 不能用“当前前台 App”猜测问题应该放进哪个子会话。
当前记录有可选 app_session_id,且要求与 App 有关的问题写进子会话;但没有说明 Agent Tool 请求如何
表达这层上下文、Runtime 如何验证它。与此同时,所有 ToolDescriptor 都要求 target.app_scope,而
interactive 明确不创建/复用任何业务 MiniApp,也不投递给 Interact 的 SDK Tool Inbox。这会造成至少两种
不兼容实现:有人将交互强行 target 到 chat,有人直接跳过 target,也有人按当前前台 App 自动归档。
已确认(2026-08-05): 不带 app_session_context 的 interactive Tool 一律记录在主 IM,不创建或猜测
App 子会话。Agent 若要关联某段 App 工作,可在 interactive Tool 的运行时上下文中提供
app_session_context.app_session_id;Runtime 必须验证其属于同一 agent_id、父 conversation 和真实 App
子会话。已经关闭的子会话仍可作为历史上下文关联,但不会复活 instance 或旧问题。验证失败则拒绝该 Tool,
不创建交互。
handling = interactive 不使用普通 MiniApp Tool 的 target,也不因此变为 Interact MiniApp Tool。Runtime
在创建 App 子会话时向当前 Agent 可靠发送其稳定 ID,供后续 Agent 交互引用。
以下原“需要冻结”的项目均由上述决议覆盖:
- 不带经验证 App 上下文的
interactiveTool 一律写入主 IM,不创建 App 子会话; - 若 Agent 需要关联某段 App 工作,定义它可引用的稳定 App 子会话标识,以及 Runtime 必须验证的
agent_id、父 conversation、App session 状态和权限边界;已关闭 App 关联的问题是否仍允许保留,需要明确; - 为
handling = interactive定义与普通ToolDescriptor.target不同的明确规则:例如 target 对它不适用, 或只允许一个受限的“会话上下文”字段;不能让它暗中变成 Interact MiniApp Tool; - 在 fixture 中覆盖“Whiteboard 前台但问题属于主 IM”“App 已关闭但问题仍关联旧子会话”“非法/跨会话
app_session_id被拒绝并不产生交互”三种情况。
P2:本迭代验收前必须处理(本次无未决项)
本次未发现独立 P2 问题。P1 项处理后,应把其中的关闭、dismiss、上下文绑定 fixture 纳入本迭代验收。
P3:本迭代结束前必须处理(均已解决)
P3-1:标准交互请求类型不能直接作为 fixture 或代码依据
ChoiceRequest 代码块中 prompt 出现两次。它不是不同字段,直接照抄会造成 TypeScript 重复属性定义。
此外,记录使用了尚未声明的 StandardInteractionRequest,文字规定 Agent 可给出 1 分钟至 24 小时的期限,
但四种最低请求类型都没有统一的期限字段。
已确认(2026-08-05): 删除重复 prompt;StandardInteractionRequest 由四种请求组成。可回答交互
在请求中使用 expires_in_ms,Runtime 根据自身当前时间计算并持久化 expires_at;未提供时默认 15 分钟,
仅接受 1 分钟至 24 小时。notice 不等待回答,也不接受期限。fixture 覆盖默认、越界和 notice 错带期限。
P3-2:Whiteboard 的完成后关闭表述与统一生命周期规则冲突
Task Dashboard 已清楚规定 Tool 完成不会关闭 App;Whiteboard 的最小体验却写成“App 完成或失败,Runtime
关闭 Surface、恢复 Interact”。这会让两个同为 kind = bundled 的参考 App 获得不同且没有声明依据的
生命周期语义,也和“只有 AppLifecycleManager.close(instance_id) 才停止实例/结束子会话”不一致。
已确认(2026-08-05): Whiteboard 与 Task Dashboard 使用相同规则:Tool complete / fail 只结束 Tool;
Surface、instance、焦点和 App 子会话仅由前后台或显式 AppLifecycleManager.close 处理。SDK v1 不为
Whiteboard 预设“提交后自动关闭”的例外;将来若需要,必须作为显式 Lifecycle Policy 并遵循 P1-1 的关闭收敛。
实现模块目录树中的 conversation-store.ts 也重复出现一次,应一并删除重复行,避免错误引导目录改动。
P4~P5:遗留问题
本次没有新增 P4/P5。第 2 次评审已登记的 P4-1(历史提案可读性)和 P4-2(未来 password-input
秘密输入原语)继续作为不阻塞当前迭代的遗留问题,其延期原因与重新评估条件以
02.design_review.md 为准。