初始化 agent_ops 文档治理体系
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# 00.base 阶段摘要
|
||||
|
||||
**状态:** 已完成
|
||||
**来源:** `lineup-app/迭代/00.base/00.base.md`
|
||||
|
||||
## 1. 结论
|
||||
|
||||
`00.base` 建立了后续所有迭代不可倒退的基线:
|
||||
|
||||
- Runtime 独占 Transport、Store、sync loop、outbox 和 App Inbox;
|
||||
- Chat 只能通过 SDK 与 Runtime Action 工作;
|
||||
- Tauri Desktop Host + Web Reference Host 是统一客户端基线。
|
||||
|
||||
## 2. 现在如何看待这个阶段
|
||||
|
||||
它现在不是未来新迭代的讨论现场,而是所有后续阶段的底层约束来源。
|
||||
@@ -0,0 +1,124 @@
|
||||
# LineUp App 迭代基线:Runtime 托管 Chat
|
||||
|
||||
**迭代编号:** 00.base
|
||||
**状态:** 已实现、已验证
|
||||
**日期:** 2026-08-04
|
||||
**定位:** 后续迭代必须保持的客户端基础能力
|
||||
|
||||
## 1. 基线说明
|
||||
|
||||
本迭代建立了 LineUp Runtime 承载第一个 Core App 的最小闭环。当前实现中的 `chat` 是
|
||||
图文 IM 形态的应用;在后续设计中,它将演进为 `Interaction App` 的 IM 模式,但现阶段
|
||||
仍保留 `app_scope = "chat"` 作为代码和协议兼容名称。
|
||||
|
||||
当前客户端基线是:
|
||||
|
||||
```text
|
||||
Tauri 2 Desktop Host + Web Reference Host
|
||||
```
|
||||
|
||||
两种 Host 运行同一份 TypeScript Runtime 和 Core App:Tauri 用于正式桌面交付,Web 用于
|
||||
浏览器开发、Tailscale 联调和自动化验证。它们不是两套客户端,也不各自实现通信、同步或
|
||||
消息存储。
|
||||
|
||||
## 2. 已实现的 Runtime 边界
|
||||
|
||||
`LineUpRuntime` 是以下对象的唯一所有者:
|
||||
|
||||
```text
|
||||
Transport
|
||||
Conversation Store
|
||||
sync loop
|
||||
outbox
|
||||
App Inbox
|
||||
作用域筛选
|
||||
旧 lineup.v1 兼容
|
||||
去重与恢复
|
||||
```
|
||||
|
||||
Chat 不能直接访问 AppServer、Transport、Store、登录态或 Host 特权能力,只能使用
|
||||
`ChatRuntimeSDK`:
|
||||
|
||||
```text
|
||||
Runtime
|
||||
→ 校验、持久化和筛选 Agent 消息
|
||||
→ 投递 app_scope + conversation_id 匹配的消息
|
||||
→ 通过 SDK 提供订阅、Inbox、ACK 和 Runtime Action
|
||||
→ 接收 Chat 的用户动作并进入 outbox
|
||||
```
|
||||
|
||||
## 3. 已实现的应用加载关系
|
||||
|
||||
当前已经将“默认应用选择”和“应用具体挂载”分开:
|
||||
|
||||
```text
|
||||
CoreAppRegistry
|
||||
→ 选择默认 app_scope = chat
|
||||
|
||||
CoreAppHostRegistry
|
||||
→ 找到 chat 对应的 Host 装配器
|
||||
|
||||
chat-app-host.ts
|
||||
→ 加载 Chat Shell、样式、Renderer、DOM Context 和 SDK
|
||||
```
|
||||
|
||||
`main.ts` 现在只负责启动 Runtime、创建 Host 绑定和请求挂载默认 App,不再直接导入
|
||||
Chat 的样式、Renderer 或 Shell。
|
||||
|
||||
相关实现:
|
||||
|
||||
- `tauri/src/runtime/coordination/lineup-runtime.ts`
|
||||
- `tauri/src/runtime/app-management/app-registry.ts`
|
||||
- `tauri/src/runtime/app-management/runtime-app-host.ts`
|
||||
- `tauri/src/core-apps/chat/chat-app-host.ts`
|
||||
- `tauri/src/main.ts`
|
||||
|
||||
## 4. 已实现的消息和交互能力
|
||||
|
||||
当前基线已经覆盖:
|
||||
|
||||
- 登录、退出和会话恢复;
|
||||
- HTTP 增量同步与包含式 cursor;
|
||||
- 用户消息本地回显、发送状态和 outbox;
|
||||
- Agent Markdown 消息和安全 DOM 渲染;
|
||||
- Agent status、progress、error 和执行摘要;
|
||||
- `choice`、`confirm`、`input` Tool Call 的状态机和可信交互卡片;
|
||||
- Tool Result / Tool Cancel 回声;
|
||||
- Surface 生命周期的基础管理;
|
||||
- Capability Registry、确认、受限 Host 执行和审计;
|
||||
- Artifact 元数据校验与 Host 临时内容缓存;
|
||||
- App Inbox 的持久化、恢复、ACK 和 `message_id` 去重。
|
||||
|
||||
所有入站内容必须先经过 Runtime 协议和作用域校验。非法或不匹配的消息不得进入 Chat,
|
||||
未知内容只能安全降级,不能执行远端脚本或系统能力。
|
||||
|
||||
## 5. 基线验证
|
||||
|
||||
```text
|
||||
npm test -- --run
|
||||
21 个测试文件通过
|
||||
94 个测试通过
|
||||
|
||||
npm run build
|
||||
TypeScript 检查通过
|
||||
Vite production build 通过
|
||||
```
|
||||
|
||||
## 6. 本基线的边界
|
||||
|
||||
以下能力尚未作为本迭代的完整实现:
|
||||
|
||||
```text
|
||||
动态 App Registry
|
||||
App 安装、更新、回滚和移除
|
||||
App Instance Manager
|
||||
App Focus Manager
|
||||
Runtime Tool Router
|
||||
Interaction App 的 IM / Audio / Video 模式统一运行时
|
||||
扩展 App 的前后台切换和恢复
|
||||
完整应用市场
|
||||
```
|
||||
|
||||
这些内容属于 [01.kernel.md](../01.kernel/01.kernel.md) 定义的下一阶段目标。`00.base` 的意义是保护
|
||||
已经完成的通信、可靠投递、作用域和安全边界,后续重构不得让这些能力回到 App 或
|
||||
`main.ts` 中。
|
||||
@@ -0,0 +1,19 @@
|
||||
# 01.kernel 阶段摘要
|
||||
|
||||
**状态:** 目标设计
|
||||
**来源:** `lineup-app/迭代/01.kernel/01.kernel.md`
|
||||
|
||||
## 1. 结论
|
||||
|
||||
`01.kernel` 把 LineUp 从“Runtime 加载一个页面”推进为“Runtime 管理应用工作区”的设计骨架。
|
||||
|
||||
它明确了:
|
||||
|
||||
- App Registry
|
||||
- Instance Manager
|
||||
- Focus Manager
|
||||
- Lifecycle Manager
|
||||
- Tool Router
|
||||
- App Orchestrator
|
||||
|
||||
这些能力是后续 `03`、`04`、`04A` 的共用骨架。
|
||||
@@ -0,0 +1,293 @@
|
||||
# LineUp App 迭代目标:Runtime Kernel 与应用编排
|
||||
|
||||
**迭代编号:** 01.kernel
|
||||
**状态:** 目标设计,待实现
|
||||
**日期:** 2026-08-04
|
||||
**前置基线:** [00.base.md](../00.base/00.base.md)
|
||||
|
||||
## 1. 迭代目标
|
||||
|
||||
本迭代要把 LineUp 从“Runtime 加载一个 Chat 页面”推进为“Runtime 管理一个应用工作区”。
|
||||
Runtime 不仅负责网络、消息和存储,还要负责应用实例、工具路由、前后台焦点和恢复;
|
||||
`Interaction App` 则负责用户与 Agent 的核心交互体验。
|
||||
|
||||
目标结构:
|
||||
|
||||
```text
|
||||
LineUp Runtime
|
||||
│
|
||||
├── Runtime Shell / Desktop
|
||||
│ ├── 应用启动
|
||||
│ ├── 应用切换
|
||||
│ ├── 前后台与焦点
|
||||
│ ├── 通知和安全恢复
|
||||
│ └── Host 挂载协调
|
||||
│
|
||||
├── Interaction App(Core App)
|
||||
│ ├── IM Mode:文字、图片、短消息
|
||||
│ ├── Audio Mode:实时语音
|
||||
│ ├── Video Mode:实时视频
|
||||
│ └── 标准交互原语:choice / confirm / input
|
||||
│
|
||||
└── Installed / Extension Apps
|
||||
├── Whiteboard
|
||||
├── Draw-and-Guess
|
||||
├── Task Dashboard
|
||||
└── 其他可安装应用
|
||||
```
|
||||
|
||||
当前代码中的 `chat` 继续作为兼容实现名称,产品概念上将其定位为:
|
||||
|
||||
```text
|
||||
Interaction App 的 IM 实现
|
||||
```
|
||||
|
||||
后续是否将目录和作用域从 `chat` 正式迁移到 `interaction`,另行作为命名迁移任务处理,
|
||||
不与本迭代的运行时编排重构混在一起。
|
||||
|
||||
## 2. 核心职责分工
|
||||
|
||||
### 2.1 LineUp Runtime
|
||||
|
||||
Runtime 是整个应用工作区的底层协调中心,拥有最终调度和安全决策权:
|
||||
|
||||
- 管理 App Registry、App Instance 和焦点栈;
|
||||
- 校验 Agent Tool Call、Manifest、Inventory、参数和作用域;
|
||||
- 决定调用应直接执行、启动 App、切换前台、等待用户交互还是创建异步任务;
|
||||
- 维护 App 的启动、运行、后台、挂起、恢复、关闭和失败状态;
|
||||
- 管理 Conversation、Store、App Inbox、outbox、权限和审计;
|
||||
- 在扩展 App 结束或启动失败时恢复原来的前台实例。
|
||||
|
||||
### 2.2 Runtime Shell / Desktop
|
||||
|
||||
Runtime Shell 是一个拥有特殊权限的内置工作区。它在产品体验上类似桌面或 Launcher,
|
||||
但最终的生命周期和安全决策仍由 Runtime Core 管理。
|
||||
|
||||
它负责:
|
||||
|
||||
- 把 App 实例挂载到 Tauri 或 Web Host;
|
||||
- 显示当前前台 App;
|
||||
- 管理应用切换、恢复和关闭;
|
||||
- 提供全局连接状态、通知和安全恢复入口;
|
||||
- 向 App 传递受限的 Host 能力。
|
||||
|
||||
普通 App 不能伪造 Runtime Shell,也不能直接修改焦点栈。
|
||||
|
||||
### 2.3 Interaction App
|
||||
|
||||
Interaction App 是默认的人与 Agent 交互应用,但不是整个应用生态的调度器。
|
||||
|
||||
它负责:
|
||||
|
||||
- 当前 Conversation 的主要交互体验;
|
||||
- IM、Audio、Video 等交互模式;
|
||||
- 选择框、确认框、输入框和进度卡片等标准交互原语;
|
||||
- 显示普通 Agent 消息、任务、Tool 结果和扩展 App 的结果;
|
||||
- 通过 SDK 提交用户动作。
|
||||
|
||||
它不负责:
|
||||
|
||||
- 直接连接 AppServer 或 Agent;
|
||||
- 决定其他 App 是否启动;
|
||||
- 管理其他 App 的前后台状态;
|
||||
- 直接执行未经 Runtime 授权的 Tool 或 Capability。
|
||||
|
||||
### 2.4 Extension App
|
||||
|
||||
扩展 App 与 Interaction App 是 Runtime 上的平级应用。画板、你画我猜和任务面板拥有
|
||||
自己的页面、状态、Tool、Surface 和实例生命周期,但必须使用 Runtime SDK。
|
||||
|
||||
扩展 App 可以请求:
|
||||
|
||||
```text
|
||||
启动自己
|
||||
创建 Surface
|
||||
进入前台
|
||||
进入后台
|
||||
提交结果
|
||||
请求关闭
|
||||
```
|
||||
|
||||
最终是否允许、如何持久化、是否需要用户确认,由 Runtime 决定。
|
||||
|
||||
## 3. 应用实例与焦点模型
|
||||
|
||||
App Registry 管理“有哪些应用”,App Instance Manager 管理“哪些应用正在运行”。两者
|
||||
不能混为一个状态。
|
||||
|
||||
```ts
|
||||
type AppInstanceRecord = {
|
||||
instance_id: string;
|
||||
app_scope: string;
|
||||
conversation_id?: string;
|
||||
state:
|
||||
| "starting"
|
||||
| "foreground"
|
||||
| "background"
|
||||
| "suspended"
|
||||
| "stopping"
|
||||
| "stopped"
|
||||
| "failed";
|
||||
parent_instance_id?: string;
|
||||
started_at: string;
|
||||
stopped_at?: string;
|
||||
error?: string;
|
||||
};
|
||||
```
|
||||
|
||||
Runtime 需要保存当前会话的焦点栈:
|
||||
|
||||
```text
|
||||
focus_stack:
|
||||
interaction:audio-001
|
||||
draw-and-guess:game-001
|
||||
|
||||
foreground:
|
||||
draw-and-guess:game-001
|
||||
|
||||
background:
|
||||
interaction:audio-001
|
||||
```
|
||||
|
||||
应用切换不会自动删除原实例。原实例可能进入 `background` 或 `suspended`,在新应用关闭、
|
||||
失败或用户返回时恢复。
|
||||
|
||||
## 4. Tool 调度模型
|
||||
|
||||
Tool 调度权在 Runtime,不在 Interaction App。
|
||||
|
||||
```text
|
||||
Agent Tool Call
|
||||
→ Runtime 校验 Envelope / Inventory / Manifest / 参数 / Scope
|
||||
→ Tool Router 判断处理方式
|
||||
→ App Orchestrator 创建或切换 App Instance
|
||||
→ Focus Manager 调整前后台
|
||||
→ Interaction App / Mode / Extension App 承接
|
||||
→ App 通过 SDK 返回 progress / result / error
|
||||
→ Runtime 校验、持久化、审计并回传 Agent
|
||||
```
|
||||
|
||||
Tool 的处理方式至少包括:
|
||||
|
||||
```text
|
||||
direct 直接由 Runtime 或受信 App 处理
|
||||
interactive 交给 Interaction App 等待用户选择/确认/输入
|
||||
launch 启动或唤醒一个扩展 App
|
||||
foreground 要求目标 App 进入前台
|
||||
operation 创建长时间运行的异步任务
|
||||
```
|
||||
|
||||
Interact 可以请求 Runtime 启动扩展 App,但不能直接加载 Bundle、切换其他 App 或执行
|
||||
系统能力。
|
||||
|
||||
## 5. 典型场景:语音切换到你画我猜
|
||||
|
||||
开始时:
|
||||
|
||||
```text
|
||||
Runtime Shell
|
||||
└── Interaction App
|
||||
└── Audio Mode(foreground)
|
||||
```
|
||||
|
||||
用户说:“我们来玩一局你画我猜吧。” Agent 发来启动请求后:
|
||||
|
||||
```text
|
||||
Agent launch(draw-and-guess)
|
||||
→ Runtime 检查 App 是否已安装、启用和兼容
|
||||
→ 校验 Tool、Manifest、Inventory、参数和权限
|
||||
→ 创建 draw-and-guess:game-001
|
||||
→ 保存 interaction:audio-001 的焦点位置
|
||||
→ Audio Mode 进入 background / suspended
|
||||
→ Draw-and-Guess 进入 starting → foreground
|
||||
```
|
||||
|
||||
游戏完成后:
|
||||
|
||||
```text
|
||||
Draw-and-Guess App
|
||||
→ 通过 SDK 提交 game.result
|
||||
→ Runtime 持久化并回传 Agent
|
||||
→ 游戏实例关闭或挂起
|
||||
→ Runtime 恢复焦点栈中的 Audio Mode
|
||||
→ Interaction App 显示游戏结果
|
||||
```
|
||||
|
||||
游戏和原来的语音交互使用同一个 `conversation_id`,但拥有不同的 `instance_id`。这样既
|
||||
能把结果归还给同一个 Agent 会话,也能独立管理每个应用实例。
|
||||
|
||||
## 6. 标准交互原语与扩展 App 的边界
|
||||
|
||||
以下内容属于 Interaction App 的内建能力,不需要安装独立 App:
|
||||
|
||||
```text
|
||||
choice
|
||||
confirm
|
||||
input
|
||||
progress
|
||||
error
|
||||
```
|
||||
|
||||
例如 Agent 请求选择框:
|
||||
|
||||
```text
|
||||
Agent tool.call(choice)
|
||||
→ Runtime 校验并持久化 pending Tool Call
|
||||
→ Interaction App 在 IM 中显示 Choice Card
|
||||
→ 用户选择
|
||||
→ Runtime 校验 call_id 并写入 outbox
|
||||
→ Choice Card 变为 submitted / completed,不再可操作
|
||||
→ IM 时间线显示“你选择了……”
|
||||
```
|
||||
|
||||
选择框可以从界面上退出可操作状态,但交互记录不能从 Store 中删除。这样才能支持刷新
|
||||
恢复、Agent 回声、幂等去重和审计。
|
||||
|
||||
画板、游戏和复杂任务面板则属于可安装扩展 App,拥有自己的 Tool 和 Surface。
|
||||
|
||||
## 7. 目标模块
|
||||
|
||||
```text
|
||||
runtime/app-management/
|
||||
├── app-registry.ts
|
||||
├── app-instance-manager.ts
|
||||
├── app-focus-manager.ts
|
||||
├── app-lifecycle-manager.ts
|
||||
└── runtime-app-host.ts
|
||||
|
||||
runtime/coordination/
|
||||
├── tool-router.ts
|
||||
├── app-orchestrator.ts
|
||||
└── interaction-orchestrator.ts
|
||||
|
||||
core-apps/interaction/(当前由 core-apps/chat 兼容实现)
|
||||
├── interaction-runtime.ts
|
||||
├── interaction-shell.ts
|
||||
├── interaction-mode-registry.ts
|
||||
├── modes/im/
|
||||
├── modes/audio/
|
||||
├── modes/video/
|
||||
└── primitives/
|
||||
|
||||
installed-apps/
|
||||
├── whiteboard/
|
||||
├── draw-and-guess/
|
||||
└── task-dashboard/
|
||||
```
|
||||
|
||||
`RuntimeAppHost` 负责实际挂载和卸载;App Instance、Focus、Lifecycle 和 Tool Router 负责
|
||||
状态和决策。这样不会把所有业务规则重新堆回 `main.ts`。
|
||||
|
||||
## 8. 本迭代验收目标
|
||||
|
||||
```text
|
||||
1. Runtime 能从 App Registry 选择默认 Interaction App。
|
||||
2. Runtime 能创建、前台化、后台化、挂起、恢复和关闭 App Instance。
|
||||
3. Agent 启动扩展 App 时,当前前台 App 能安全进入后台。
|
||||
4. 扩展 App 结束或失败后,Runtime 能恢复原来的焦点和交互模式。
|
||||
5. Tool 调用必须经过 Runtime 的 Inventory、Manifest、参数、作用域和权限校验。
|
||||
6. Interaction App 能处理 choice / confirm / input 等标准交互原语。
|
||||
7. 扩展 App 只能通过 SDK 返回结果,不能直接访问 Agent、Host DOM 或系统特权。
|
||||
8. 断线或重启后,App Instance、Tool Call、App Inbox、outbox 和焦点栈可以有界恢复。
|
||||
9. 00.base 中已经通过的 21 个测试文件、94 个测试和生产构建不能退化。
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
# 03.sdk_and_coreapp 阶段摘要
|
||||
|
||||
**状态:** 已完成
|
||||
**来源:** `lineup-app/迭代/03.sdk_and_coreapp/03.sdk_and_coreapp.md`
|
||||
|
||||
## 1. 结论
|
||||
|
||||
这一阶段已经确认:
|
||||
|
||||
- `Interact` 是唯一 `system` MiniApp;
|
||||
- `Task Dashboard` 与 `Whiteboard` 是 `bundled` MiniApp;
|
||||
- 标准交互属于 Interact;
|
||||
- App 子会话、关闭收口、只读历史和继续处理规则已固定;
|
||||
- MiniApp SDK v1 已成为当前主契约。
|
||||
|
||||
## 2. 当前角色
|
||||
|
||||
这是后续所有工作区与 Tool 迭代的契约支柱,不再只是客户端内部参考阶段。
|
||||
@@ -0,0 +1,353 @@
|
||||
# `03.sdk_and_coreapp` 第 1 次设计评审记录
|
||||
|
||||
> 评审日期:2026-08-05
|
||||
> 评审编号:01
|
||||
> 评审基线:[APP架构设计.md](../../设计/APP架构设计.md)
|
||||
> 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)
|
||||
> 评审方式:独立子 agent 只读评审;本文件记录评审意见,不代表已采纳或已实现。
|
||||
|
||||
> **后续决议(2026-08-05):** `MiniAppManifest.kind` 收敛为 `system | bundled`。Task Dashboard
|
||||
> 与 Whiteboard 均为非系统级 `bundled` MiniApp,必须采用与一般 MiniApp 相同的受限 Surface /
|
||||
> Bridge 模型;“参考”仅描述它们在本迭代验证 SDK 的目的。下文的 `bundled-reference` 为评审时的
|
||||
> 历史术语,已由此决议取代。
|
||||
|
||||
> **后续决议(2026-08-05):** `notice / choice / confirm / input` 始终是 Interact 的人与 Agent
|
||||
> 会话交互,不属于 MiniApp SDK,也不用于 MiniApp 内部业务逻辑。当前 bundled MiniApp 位于前台时,
|
||||
> Interact / Shell 可在其上方显示同一会话的交互层;请求与答案仍只属于 Interact、当前会话和 Agent。
|
||||
|
||||
> **后续决议(2026-08-05):** 每个启动的 App instance 在主 IM 中创建或恢复一个 App 子会话;其中
|
||||
> 只保留人与 Agent 围绕该 App 的提问、回答和简洁结果。App 的内部按钮、表单、画布编辑等业务操作
|
||||
> 不进入子会话。后台化不结束子会话;真正结束时保留折叠历史;新的 instance 创建新的子会话。
|
||||
|
||||
> **后续决议(2026-08-05):** 已结束的 App 子会话可以在主 IM 中只读展开。用户选择“继续处理”时,
|
||||
> Runtime 创建新的 App instance 和新的子会话;新会话可引用旧会话或 App 数据,但不能续写旧记录或
|
||||
> 复活旧问题。
|
||||
|
||||
> **后续决议(2026-08-05,已更新):** App 子会话只在 `AppLifecycleManager.close` 使对应 instance
|
||||
> 停止或失败时结束;前后台切换、暂停和 Agent Tool 完成都不结束子会话。关闭时,Runtime 向 Agent
|
||||
> 可靠发送 App 已关闭事件;尚未回答的 Interact 交互不自动取消,Agent 可 remote dismiss,或让其继续
|
||||
> 在主 IM 中等待用户回答/超时。子会话保留为主 IM 历史。
|
||||
|
||||
> **后续决议(2026-08-05):** MVP 中一个 LineUp Runtime 只连接一个 Agent。每条标准交互和
|
||||
> App 子会话仍保存当前 `agent_uid` 作为 `agent_id`,但本迭代不实现多个 Agent 的连接、切换、
|
||||
> 会话列表、outbox 或路由。
|
||||
|
||||
## 问题清单(Outline)
|
||||
|
||||
> **状态标记:** ✅ 已解决并回填设计; 🟡 待产品/架构决策; 🔵 待在契约中细化; ⚪ 待实施编排或文档整理; — 不再适用。
|
||||
>
|
||||
> 本清单是当前有效视图;后文保留评审时的原始问题、分析和建议作为依据。每次确认一个决策或完成
|
||||
> 回填时,应先更新此处状态,再更新对应正文和验收项。
|
||||
|
||||
| 状态 | 编号 | 问题 | 当前结论 / 下一步 |
|
||||
|---|---|---|---|
|
||||
| ✅ | B1 | Task Dashboard 的信任级别与 UI 容器 | 已确认:Task Dashboard、Whiteboard 均为非系统级 `kind = bundled` MiniApp,必须运行于受限 Surface / Bridge,不能使用可信 Host DOM。 |
|
||||
| ✅ | I1 | `bundled-reference` / `bundled-development` 命名歧义 | 已确认:Manifest 枚举为 `system \| bundled`;“参考”仅描述当前迭代的工作目的。 |
|
||||
| ✅ | I2 | 标准交互由谁显示、答案如何回传 | 已确认:Interact / Shell 显示人与 Agent 的交互;bundled MiniApp 前台时可被该交互层覆盖。结果由 Runtime 可靠回传 Agent,不交给 MiniApp。 |
|
||||
| ✅ | I3 | 标准交互与 Agent Tool Call 的关系 | 已确认:标准交互仅由 Agent Tool 调起并创建交互记录;MiniApp 不存在 `sdk.ui.request`,不会自行创建 Agent Tool Call。 |
|
||||
| ✅ | I4 | 标准交互结果的返回通道 | 已确认:用户答案先回 Runtime,再可靠回传 Agent;不经 MiniApp Inbox、Tool 订阅或 MiniApp SDK 返回。 |
|
||||
| ✅ | I5 | Request/Result schema、状态机、幂等与错误码 | 已确认第一版:`notice` 非阻塞;`confirm` 二选一且默认取消;`choice` 只支持 2~6 项单选;`input` 只支持一个文本输入;首次有效回答终结交互;默认 15 分钟超时,可在 1 分钟~24 小时内调整。 |
|
||||
| ✅ | I6 | 敏感输入的持久化、恢复、审计和日志边界 | 已确认:未提交草稿仅存在当前运行期间,重启即清空;已提交的人与 Agent 答案保留在所属主 IM 或 App 子会话中,随父 IM 会话处理;二者均不写日志、Telemetry 或普通审计明文。 |
|
||||
| ✅ | I7 | App 子会话与主 IM 的关系 | 已确认:每个 App instance 创建/恢复一个子会话;后台保留,真正结束后在主 IM 中折叠存档,新 instance 独立。仅记录人与 Agent 围绕 App 的交互,不记录 App 内部业务操作。 |
|
||||
| ✅ | I8 | 已结束 App 子会话的查看与继续处理 | 已确认:旧子会话可只读展开;继续旧工作创建新 instance / 新子会话,可引用旧上下文,但不追加旧记录或复活旧问题。 |
|
||||
| ✅ | I9 | App 子会话何时结束 | 已确认:仅 `AppLifecycleManager.close` 导致 instance stopped/failed 时结束;前后台切换、暂停、Agent Tool 完成不结束。关闭时 Runtime 向 Agent 发送 App 已关闭事件,但不自动取消未回答的 Interact 交互。 |
|
||||
| ✅ | I10 | MVP 的 Agent 身份范围 | 已确认:Runtime 仅连接一个 Agent;交互和 App 子会话保存该 `agent_id`,但不实现多 Agent 连接、切换或路由。 |
|
||||
| — | S1 | `parent_call_id` 的关联校验与父 Tool 终止后的处置 | 不再适用:MiniApp 不再发起标准交互;标准交互直接绑定 Agent call 与 conversation。 |
|
||||
| ✅ | S2 | 交互层显示与恢复规则 | 已确认:原 App 前台时显示交互层;切换到其他 App/IM 时收起并在子会话标记“等待你的回答”;用户可在 IM 或回到原 App 后回答;关闭 App 只移除覆盖层并通知 Agent,不自动取消交互。 |
|
||||
| ✅ | S3 | Interact 呈现与 Agent Tool 回传的分层 | 已确认:Interact / Shell 只显示并把用户动作/答案交给 Runtime;Runtime 根据已保存的交互上下文校验、持久化和可靠回传 Agent;不经过 MiniApp。 |
|
||||
| ✅ | S4 | 阶段编号重复 | 已确认:Task Dashboard / Whiteboard 的端到端参考实现属于 `03.sdk_and_coreapp`;移除重复的 `03.reference-miniapps`,后续应用分发阶段保持为 `04.app-delivery-registry`。 |
|
||||
| ✅ | S5 | 实施步骤顺序 | 已确认:先完成通用 Tool 闭环,再完成 Runtime 独占的 Agent interaction service 和 Interact 回传契约,之后才适配 Interact、实现两个 bundled 参考 MiniApp,最后端到端验收。 |
|
||||
|
||||
## 1. 总体结论
|
||||
|
||||
这份文件保留了首次评审时提出的问题和建议,方便追溯讨论过程;其中涉及 `sdk.ui`、MiniApp 发起
|
||||
标准交互、owner 注入等早期设想,均已被本文件顶部的“后续决议”和问题清单中的最终结论取代,不能作为
|
||||
实施依据。
|
||||
|
||||
当前已经收敛的核心结论是:
|
||||
|
||||
- 产品层级是 **LineUp App → LineUp Runtime → MiniApps**,Runtime 不是与 MiniApp 平级的产品 App。
|
||||
- `notice / choice / confirm / input` 是 Interact 中人与 Agent 对话的一部分,不是 MiniApp SDK,也不能由
|
||||
bundled MiniApp 发起、读取、提交或取消。
|
||||
- Interact / Shell 只呈现和收集用户答案;Runtime 保存交互归属、校验首次有效回答、写入可靠 outbox,并
|
||||
向当前唯一 Agent 回传结果。
|
||||
- Task Dashboard 与 Whiteboard 都是 `kind = bundled`;它们使用一般 MiniApp 的受限 Surface、Bridge、
|
||||
生命周期和 SDK,只保留自身的业务 UI。
|
||||
- 保留 `lineup.v1.tool.call(choice | confirm | input)` 的 Agent 交互兼容入口;不在本迭代迁移
|
||||
`chat → interact` 命名。
|
||||
- 本迭代不建设 AppServer Catalog、下载、安装、更新、市场、远程 Bundle、真实媒体/文件能力或多 Agent
|
||||
Runtime 连接。
|
||||
|
||||
本轮评审问题均已得到设计结论,后续进入实现时应以 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)
|
||||
和 [APP架构设计.md](../../设计/APP架构设计.md) 为准。
|
||||
|
||||
## 2. 阻塞问题
|
||||
|
||||
### B1. Task Dashboard 的可信 DOM / Host adapter 权限突破了当前信任模型
|
||||
|
||||
**架构基线**在 [APP架构设计.md](../../设计/APP架构设计.md) 的 MiniApp 信任模型中明确:
|
||||
|
||||
- `Interact / System MiniApp` 可使用可信内建 DOM 组件;
|
||||
- Installed MiniApp 必须经隔离 iframe / Surface Bridge 运行。
|
||||
|
||||
而 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) 同时写了:
|
||||
|
||||
```text
|
||||
Task Dashboard 可由受信 Host adapter 挂载;Whiteboard 必须走受限 Surface
|
||||
```
|
||||
|
||||
并将 Task Dashboard 定义为:
|
||||
|
||||
```text
|
||||
kind = bundled-reference
|
||||
```
|
||||
|
||||
且说明它可使用“随 LineUp 发布的受信 Host adapter”。
|
||||
|
||||
**问题:** 当前权威架构没有明确授权 `bundled-reference` 获得与 System MiniApp 相同的可信 DOM 容器。若 Host adapter 可执行或挂载 Task Dashboard 的 UI,而未经过受限 Surface,隔离边界、SDK 受限视图和“禁止访问 Host DOM”就无法以同一安全模型证明。
|
||||
|
||||
**需要冻结的决策(二选一):**
|
||||
|
||||
1. **保守方案,且最符合当前权威基线:** Task Dashboard 和 Whiteboard 都是非 System MiniApp,必须经隔离 Surface / Bridge 运行。Host adapter 仅作为 Runtime/Shell 的不可见装配层,不向 MiniApp 提供可直接操作的可信 Host DOM。
|
||||
2. **若产品确实需要 Task Dashboard 使用可信原生 DOM:** 将其升级为 `kind = system`,并在架构主文档新增或明确“bundled trusted system MiniApp”信任层、发布来源、可用 DOM 权限和审计边界;不能继续称其为普通 `bundled-reference`。
|
||||
|
||||
**建议验收:**
|
||||
|
||||
- 若维持 `bundled-reference`,Task Dashboard 无法获得 Host 根 DOM、Tauri invoke 或未授权 Host adapter。
|
||||
- 若改为 `system`,仍要验证其特权只限 Runtime SDK,不能取得 Transport、Store 或 Agent 访问权。
|
||||
|
||||
## 3. 重要问题
|
||||
|
||||
### I1. `bundled-development` 与 `bundled-reference` 的术语、Manifest 枚举未建立映射
|
||||
|
||||
迭代文档把“内置”解释为 `bundled-development`,但冻结的 `MiniAppManifest.kind` 只有:
|
||||
|
||||
```ts
|
||||
kind: "system" | "bundled-reference";
|
||||
```
|
||||
|
||||
架构主文档也使用了“参考 MiniApp 在此阶段可以是 `bundled-development`”的表述。
|
||||
|
||||
这两个词可以共存,但必须明确它们不是互相竞争的 `kind` 枚举值。
|
||||
|
||||
**建议补充最小映射表:**
|
||||
|
||||
| 概念 | 建议语义 |
|
||||
|---|---|
|
||||
| `bundled-development` | 本迭代的交付/加载方式:随开发 Host 预置,不下载、不安装、不经服务端 Catalog。 |
|
||||
| `kind = bundled-reference` | Manifest 身份:参考 MiniApp,决定 SDK / Surface 信任策略。 |
|
||||
| `kind = system` | 随产品发布、代码可信的系统 MiniApp,例如 Interact。 |
|
||||
|
||||
并明确:`bundled-development` **不是** `MiniAppManifest.kind` 的第三个取值。
|
||||
|
||||
### I2. `sdk.ui` 缺少 Renderer 如何安全提交用户结果给 Runtime 的闭环契约
|
||||
|
||||
当前公开 API 只有:
|
||||
|
||||
```ts
|
||||
request(...)
|
||||
get(...)
|
||||
subscribe(...)
|
||||
cancel(...)
|
||||
```
|
||||
|
||||
但未定义:
|
||||
|
||||
- Runtime 如何把被 Policy 选中、可呈现的 interaction record 交给 renderer;
|
||||
- renderer 如何提交 `submitted`、`result` 或 `cancelled`;
|
||||
- Runtime 如何校验 `interaction_id`、owner、renderer binding、状态迁移、一次性提交和结果 schema;
|
||||
- 在 opaque-origin iframe / Surface Bridge 内,呈现和回传采用何种受限消息协议;
|
||||
- renderer 与 owner 是同一 MiniApp 时,是否通过 `sdk.ui` 提交,还是只能通过 Runtime/Shell 私有 Renderer API 提交。
|
||||
|
||||
**建议冻结 Runtime 私有 Renderer Contract / 最小 Bridge Contract:**
|
||||
|
||||
```text
|
||||
Runtime 分配 interaction_id + renderer_binding + presentation container/surface
|
||||
→ renderer 仅接收 presentation-safe request projection
|
||||
→ renderer 向 Runtime-owned endpoint 提交 action/result
|
||||
→ Runtime 校验:
|
||||
- 被分配的 renderer / container
|
||||
- interaction_id
|
||||
- owner binding
|
||||
- 当前状态与一次性提交
|
||||
- result schema
|
||||
- expiry
|
||||
→ Runtime 持久化状态迁移,并向 owner-scoped ui 订阅发出更新
|
||||
```
|
||||
|
||||
隔离 Surface 至少还要限定消息白名单、`surface_id` / `instance_id` 绑定和 nonce 或等效关联方式;不得只凭 origin 信任。
|
||||
|
||||
### I3. 标准交互与 `RuntimeToolCallRecord` 的关系不清晰
|
||||
|
||||
当前文档同时规定:
|
||||
|
||||
- MiniApp 可调用 `sdk.ui.request(...)`;
|
||||
- owner 的 source 可为 `agent_tool | miniapp_tool | runtime_policy`;
|
||||
- 所有标准交互“必须映射为 Runtime 统一的 `interactive` Tool Call / `StandardInteractionRecord`”。
|
||||
|
||||
因此会产生问题:Task Dashboard 在没有 Agent Tool Call、例如用户点击“关闭未完成任务”时调用 `sdk.ui.request(confirm)`,Runtime 是否必须凭空创建 Agent-facing `RuntimeToolCallRecord`?
|
||||
|
||||
**建议明确拆成三条路径:**
|
||||
|
||||
| 来源 | Runtime 记录 | 与 Agent Tool 的关系 |
|
||||
|---|---|---|
|
||||
| Agent / legacy `lineup.v1.tool.call(choice/confirm/input)` | `RuntimeToolCallRecord` + `StandardInteractionRecord` | 交互终态受控驱动该 Tool 的后续处理。 |
|
||||
| MiniApp `sdk.ui.request(...)` | owner-bound `StandardInteractionRecord` | 不自动创建新的 Agent Tool;若提供合法 `parent_call_id`,只建立关联。父 Tool 的完成由 owner 经 `sdk.tools.*` 决定。 |
|
||||
| Runtime Policy 自发提示 | `runtime_policy` owner 的 interaction record | 需明确其是否绑定某一 Capability / lifecycle request。 |
|
||||
|
||||
没有 parent Tool 的交互只改变 MiniApp 本地工作流,不应制造 Inventory、Agent 回传或 outbox 语义。
|
||||
|
||||
### I4. 结果投递位置与公开 API 不一致
|
||||
|
||||
流程写“结果仅投递回 owner MiniApp 的 Tool/Inbox”,但 SDK 已公开 `sdk.ui.get/subscribe`。
|
||||
|
||||
否则实现可能分叉成:
|
||||
|
||||
1. 结果通过 `sdk.ui.subscribe` 的 record update 返回;
|
||||
2. 结果作为 Inbox 消息;
|
||||
3. 结果通过 parent Tool 的 SDK Tool event 返回。
|
||||
|
||||
**建议冻结为:**
|
||||
|
||||
```text
|
||||
sdk.ui.get / sdk.ui.subscribe
|
||||
= owner 获取标准交互状态与结果的唯一 UI-domain 通道
|
||||
|
||||
sdk.inbox
|
||||
= Agent / Runtime 入站消息;不复用为 interaction result transport
|
||||
|
||||
sdk.tools.complete / fail / cancel
|
||||
= owner 根据 UI result 自行决定是否推进关联 parent Tool
|
||||
```
|
||||
|
||||
还需定义:订阅是否立即回放 owner 当前 pending records、终态保留/清理策略、断线重连后的重放及去重语义。
|
||||
|
||||
### I5. Schema、状态机、幂等规则不足以支持安全验收
|
||||
|
||||
已有四类 request 及基础状态,但还需要明确:
|
||||
|
||||
- `StandardInteractionResult` 与 `InteractionReceipt` 的类型;
|
||||
- `choice.actions[].id` 的唯一性、最大数量、空数组是否允许,以及 single/multi/button 的选择基数;
|
||||
- `input.fields[].id` 的唯一性、字段数上限、必填、数值解析、空字符串、长度和范围的适用规则;
|
||||
- `notice` 的“只读”与 `acknowledged` 的精确定义:是否需要用户确认、是否自动完成、是否可超时;
|
||||
- `request`、`submit`、`cancel`、超时、恢复之间的合法状态迁移;
|
||||
- 并发提交、重放、重复取消、跨 Surface 重放的确定性返回;
|
||||
- 交互专用稳定拒绝码。
|
||||
|
||||
建议至少增加:
|
||||
|
||||
```text
|
||||
interaction_not_found
|
||||
interaction_owner_mismatch
|
||||
interaction_state_invalid
|
||||
interaction_expired
|
||||
interaction_result_invalid
|
||||
interaction_renderer_mismatch
|
||||
parent_call_invalid
|
||||
```
|
||||
|
||||
### I6. 持久化、审计与敏感输入的日志最小化约束尚未衔接
|
||||
|
||||
`input` 可以含用户自由文本;标准交互要求持久化、恢复和审计,但架构文档又要求日志不得包含身份、会话、消息正文、Tool 参数、token 或 artifact 内容。
|
||||
|
||||
**建议明确:**
|
||||
|
||||
- 恢复所需的受保护 operational state、审计最小元数据、日志/Telemetry 三者的分层;
|
||||
- `input` 草稿和结果的保留期、终态清理策略,以及是否加密;
|
||||
- 审计仅记录 interaction ID、kind、受保护 owner 标识、状态迁移和错误码;
|
||||
- title、prompt、字段值和 action label 不进入日志、指标、错误详情或普通审计明文;
|
||||
- 验收增加日志负向断言。
|
||||
|
||||
## 4. 建议完善项
|
||||
|
||||
### S1. 扩大 `parent_call_id` 校验条件
|
||||
|
||||
除“属于当前实例且状态允许关联”外,Runtime 至少应校验:
|
||||
|
||||
```text
|
||||
同 app_scope
|
||||
同 instance_id
|
||||
同 conversation_id
|
||||
父 Tool 非终态
|
||||
不存在跨 owner 关联
|
||||
```
|
||||
|
||||
还要定义父 Tool 被取消或超时时关联 interaction 的处理:自动取消、保留为独立操作,或交由 Policy 决定。否则恢复后容易遗留孤儿卡片。
|
||||
|
||||
### S2. 将 presentation policy 写成可判定矩阵
|
||||
|
||||
至少应覆盖:
|
||||
|
||||
| owner 状态 / 容器 | 建议行为 |
|
||||
|---|---|
|
||||
| Agent IM / Interact 有效 | Interact IM timeline/card。 |
|
||||
| owner 前台且存在合法 renderer | owner 容器或已绑定 Surface 的标准 modal/sheet/card。 |
|
||||
| owner 后台或 suspended | 保持 pending;通知/唤醒仅经 Policy,不得抢占焦点。 |
|
||||
| Surface 已关闭或失效 | 不向旧 Surface 投递;恢复、降级或安全失败。 |
|
||||
| renderer 不可用 | 保持 pending 或返回稳定拒绝码;不能把 payload 注入 Host DOM。 |
|
||||
| 系统能力确认 | 走 Capability Gateway,禁止降级为普通 `confirm`。 |
|
||||
|
||||
### S3. Interact 呈现与 Agent Tool 回传的分层
|
||||
|
||||
**已确认(2026-08-05):** 用户在 Interact 中回答时,Interact 只负责显示问题、收集用户动作并把
|
||||
答案交给 Runtime。它不是 Agent 的消息发送端,也不负责判断答案属于哪个 Agent、哪个会话或哪个 App
|
||||
子会话。
|
||||
|
||||
```text
|
||||
Interact / Shell 显示问题
|
||||
→ 用户作答
|
||||
→ Interact 向 Runtime 提交「interaction_id + 用户动作/答案」
|
||||
→ Runtime 从已保存的交互记录取得 agent_id、conversation、App 子会话和 Agent Tool 归属
|
||||
→ Runtime 核对 Interact 实例、展示位置、状态、期限、答案格式和首次提交
|
||||
→ Runtime 持久化会话记录与终态,并写入可靠 outbox
|
||||
→ Runtime 向当前唯一 Agent 回传一次结果
|
||||
```
|
||||
|
||||
提交端不能传递或覆盖 `agent_id`、`conversation_id`、`call_id`、`app_session_id` 等归属信息;这些
|
||||
只能由 Runtime 创建交互时保存。重复点击、刷新后的旧页面、无效展示位置、过期或已结束问题的提交都
|
||||
必须被拒绝,且不能改变已经保存的结果或再次通知 Agent。Task Dashboard、Whiteboard 等 bundled
|
||||
MiniApp 始终不参与这条链路,也读不到问题或答案。
|
||||
|
||||
### S4. 统一阶段编号
|
||||
|
||||
**已确认(2026-08-05):** Task Dashboard 与 Whiteboard 是 `03.sdk_and_coreapp` 中用来验证 SDK 的
|
||||
bundled 参考 MiniApp,本阶段就完成其端到端路径。因此删除重复的 `03.reference-miniapps`;后续阶段
|
||||
保持为 `04.app-delivery-registry`,不需要整体重编号。
|
||||
|
||||
### S5. 在实施步骤中拆出标准交互服务和 renderer/Bridge 契约
|
||||
|
||||
**已确认(2026-08-05):** 实施顺序已调整为:
|
||||
|
||||
1. 冻结契约与测试样本;
|
||||
2. 实现 Runtime 通用 Tool 闭环;
|
||||
3. 实现 Runtime 独占的 Agent interaction service,以及 Runtime ↔ Interact 的最小呈现/提交契约;
|
||||
4. 再适配 Interact IM 和 App 子会话;
|
||||
5. 最后通过 Task Dashboard、Whiteboard 验证一般 bundled MiniApp 路径,并进行端到端验收。
|
||||
|
||||
这样标准交互不会先被做成 Chat 专用或 MiniApp SDK 能力;Interact 只是第一个使用 Runtime 私有交互
|
||||
契约的系统级呈现者,两个 bundled MiniApp 则只验证各自的 Tool、Surface 和业务 UI 边界。
|
||||
|
||||
## 5. 建议新增的最小验收场景
|
||||
|
||||
1. A 实例提交属于 B 实例、不同 conversation 或已终态 Tool 的 `parent_call_id` 时,Runtime 拒绝且不创建 record。
|
||||
2. A 创建 interaction 后,B 无法 `get`、订阅、取消、提交,或通过伪造 `interaction_id` 获得任何 payload/result。
|
||||
3. 同一 interaction 的两次 renderer submit 只有一次成功;第二次得到稳定终态错误且不改变已持久化结果。
|
||||
4. 旧 `lineup.v1.tool.call(choice|confirm|input)` 创建关联 Tool Call 和 owner 为 Interact IM context 的 interaction;用户结果先由 Runtime 落库,再由 Interact 以 owner 身份完成 Tool。
|
||||
5. Task Dashboard 无 parent Tool 的 `sdk.ui.request(confirm)` 不创建 Agent-facing Tool Call、不写 Agent outbox;带合法 parent Tool 时仅关联,不自动完成该 Tool。
|
||||
6. Task Dashboard 前台时,标准 modal/sheet/card 在其合法容器显示,焦点栈与 Interact background 状态不被改写。
|
||||
7. Whiteboard 在 Surface reload、关闭、旧 iframe 重放提交时,`surface_id` 与 renderer binding 都被验证,旧 iframe 消息被拒绝。
|
||||
8. 非法 input、重复/未知 choice action、过期 interaction、跨 owner cancel 都被拒绝且不写错误结果。
|
||||
9. 标准交互输入值、提示正文、选择标签不出现在日志、Telemetry 或 Audit 明文中;重启恢复仅保留设计允许的最小数据。
|
||||
10. 若维持 `bundled-reference`,Task Dashboard 不能直接挂载可信 Host DOM;若改为 `system`,必须有对应的 manifest/source-trust 回归用例。
|
||||
|
||||
## 6. 建议的阅读和决策顺序
|
||||
|
||||
明天继续时,建议按以下顺序决策和回填:
|
||||
|
||||
1. 先决定 **B1:Task Dashboard 的信任级别与 UI 容器**;
|
||||
2. 冻结 **I2:Renderer → Runtime 的提交/Bridge 契约**;
|
||||
3. 冻结 **I3/I4:StandardInteractionRecord 与 Tool Call 的关系,以及 UI result 的唯一返回通道**;
|
||||
4. 细化 **I5/I6:schema、状态机、幂等、错误码、持久化与日志最小化**;
|
||||
5. 把 S1~S5 与第 5 节的验收场景回填入 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) 和必要的 [APP架构设计.md](../../设计/APP架构设计.md)。
|
||||
|
||||
在上述收敛前,不建议开始 `standard-interaction-service` 或参考 MiniApp 的实现,以免重新形成 Chat / Interact 专用旁路。
|
||||
@@ -0,0 +1,164 @@
|
||||
# `03.sdk_and_coreapp` 第 2 次设计评审记录
|
||||
|
||||
> 评审编号:02
|
||||
> 评审日期:2026-08-05
|
||||
> 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)、[01.design_review.md](01.design_review.md)
|
||||
> 评审方式:独立子 agent 只读复核
|
||||
> 结论:核心方向已收敛;没有 P0 阻塞问题。以下 P1 项需在开始编码前逐项确认并回填主定义文档。
|
||||
|
||||
## 问题清单(Outline)
|
||||
|
||||
> **状态标记:** ✅ 已确认并回填设计; 🟡 待产品/架构决策; 🔵 待在契约中细化; ⚪ 文档或实施编排建议; — 不适用或无此问题。
|
||||
>
|
||||
> 本清单是本次评审的当前有效视图。后文保留每个问题的背景和建议;在问题被确认前,建议不是实施依据。
|
||||
> 确认后应先更新本清单,再回填 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) 的契约、实施步骤和验收项。
|
||||
|
||||
| 状态 | 编号 | 问题 | 当前结论 / 下一步 |
|
||||
|---|---|---|---|
|
||||
| — | P0 | 阻塞级架构冲突 | 本次未发现需要推倒既有模型的 P0 问题。 |
|
||||
| ✅ | P1-1 | Task Dashboard 示例中 Tool 完成后关闭 App | 已回填:Tool 完成只回传 Agent;App 保留、后台或关闭由用户动作、`requestClose` 或 Lifecycle Policy 决定,只有真正 `AppLifecycleManager.close` 才结束 App 与子会话。 |
|
||||
| ✅ | P1-2 | `interactive` Tool 的专用路由 | 已回填:`interactive` 是 Runtime 自己处理的 Agent 交互分支,不创建/复用业务 MiniApp instance,不调整业务 App 焦点,也不进入任何 MiniApp SDK Tool Inbox;Runtime 私有契约交给 Interact / Shell 呈现。 |
|
||||
| — | P1-3 | 展示位置切换后的提交资格 | 不再适用:展示位置不是交互 owner 或提交权限。切换 App 前后台、关闭 App 或改在 IM 显示不改变同一 `interaction_id` 的归属;Runtime 只接受首次有效回答,之后才拒绝重复/重放。 |
|
||||
| ✅ | P1-4 | Tool 与交互的取消、超时和并发提交 | 已回填:用户回答、Agent dismiss、到期和 Runtime 失败竞争同一唯一终态;Runtime 第一个原子状态写入获胜,Tool 跟随同一结果,且只写一条 outbox。interactive Tool 仅使用交互 `expires_at`,不维护独立超时。 |
|
||||
| ✅ | P1-5 | `notice` 的 Tool 完成时点与结果 | 已回填:notice 必须保留为 Interact / IM 的只读卡片,可选同时 Toast 数秒;Runtime 持久化卡片并安排呈现后,立即以 `{ outcome: "accepted" }` 完成并回传,不表示用户已阅读。 |
|
||||
| — | P2-1 | 将普通标准交互统一当作敏感秘密输入 | 不再适用:`notice / choice / confirm / input` 按普通 IM 会话内容与日志基线处理;本迭代不为它们另设秘密输入契约或专门负向扫描。未提交草稿仍只在运行期存在,重启清空。 |
|
||||
| ⚪ | P4-1 | 首次评审中的历史提案可读性 | **遗留问题:** 不阻塞本迭代;建议在下一次文档整理或新评审时,进一步突出其中 `sdk.ui`、owner、`parent_call_id` 等旧提案仅供追溯、不可实施。 |
|
||||
| ⚪ | P4-2 | `password-input` 秘密输入原语 | **遗留问题:** 当前不阻塞 `03`;真正出现密码、卡密、私钥或临时 token 的 Agent 交互需求时,单独定义该原语及其不显示明文、不进入普通 IM 正文/日志/Telemetry/审计、可靠传递与清理等安全契约。 |
|
||||
|
||||
## 通过项
|
||||
|
||||
- 标准交互已经清楚限定为 Interact 中的人与 Agent 会话交互,而非 MiniApp SDK;公开 SDK 不包含 `sdk.ui`。
|
||||
- Task Dashboard、Whiteboard 已收敛为 `kind = bundled`,必须走受限 Surface / Bridge,不能取得可信 Host DOM、Tauri、Transport、Store、Agent 或其他 MiniApp 数据。
|
||||
- 用户答案经 Interact 交给 Runtime;Runtime 保存交互归属、校验、持久化并可靠回传当前唯一 Agent,bundled MiniApp 不参与。
|
||||
- App 子会话正确区分了人与 Agent 的记录和 MiniApp 内部业务操作;前后台、关闭、历史只读和“继续处理”的总体规则一致。
|
||||
- MVP 单 Agent 边界明确,没有提前引入多 Agent 连接、切换或路由。
|
||||
|
||||
## P0:阻塞问题
|
||||
|
||||
无。
|
||||
|
||||
## P1:开始编码前需要确认的事项
|
||||
|
||||
### P1-1:Tool 完成不应自动关闭 Task Dashboard
|
||||
|
||||
**已解决(2026-08-05):** 主定义文档已经确认“Agent Tool 完成不自动关闭 App,也不结束 App
|
||||
子会话”。Task Dashboard 示例与验收现已统一为该规则。
|
||||
|
||||
当前规则:
|
||||
|
||||
```text
|
||||
Tool 完成
|
||||
→ Runtime 持久化并回传 Agent
|
||||
→ App 是否保持前台、进入后台或关闭,取决于用户动作、MiniApp requestClose 或 Lifecycle Policy
|
||||
→ 只有真正执行 AppLifecycleManager.close,才结束 App 与 App 子会话
|
||||
```
|
||||
|
||||
验收已要求:Tool 成功回传后 Dashboard 可继续使用;只有真正关闭才结束子会话。
|
||||
|
||||
### P1-2:interactive Tool 必须不进入 MiniApp SDK Tool Inbox
|
||||
|
||||
**已解决(2026-08-05):** 通用 Tool 路由、实施步骤和验收已明确拆开 `interactive` 与一般 Tool。
|
||||
`notice / choice / confirm / input` 不会投递到 App Orchestrator、业务 MiniApp instance、SDK Tool Inbox
|
||||
或 `sdk.tools.subscribe`。
|
||||
|
||||
当前规则:
|
||||
|
||||
```text
|
||||
handling = interactive
|
||||
→ 不投递任何 MiniApp SDK Tool Inbox
|
||||
→ Runtime Agent interaction service 创建 StandardInteractionRecord
|
||||
→ Runtime 私有契约交给 Interact / Shell 呈现
|
||||
→ Interact 提交 interaction_id + 用户动作/答案
|
||||
→ Runtime 校验、持久化、outbox 回传 Agent
|
||||
|
||||
handling = direct / launch / foreground / operation
|
||||
→ 才进入 App Orchestrator、SDK Tool Inbox、MiniApp tools.* 路径
|
||||
```
|
||||
|
||||
验收已要求:Agent 发起的四类标准交互不得出现在任何 MiniApp Inbox 或 `sdk.tools.subscribe`。
|
||||
|
||||
### P1-3:切换展示位置后,旧页面必须失去提交资格
|
||||
|
||||
**不再适用(2026-08-05):** 该问题错误地把 App 上方覆盖层或 IM 卡片当成了交互的 owner。标准交互
|
||||
始终属于 Interact / 主 IM;`app_session_id` 只保留与哪段 App 工作相关的上下文,不形成 UI 父子关系。
|
||||
|
||||
切换 App 前后台、关闭 App 或改变展示位置不改变同一个 `interaction_id` 的归属,也不需要用
|
||||
`presentation_id` / `presentation_revision` 废止旧页面的回答资格。只要用户仍处于有效 LineUp /
|
||||
Interact 会话且交互尚未终态,Runtime 可接受该交互的首次有效回答;以后到达的重复、重放或迟到提交
|
||||
因交互已经终态而被拒绝。Shell 可以避免用户看到重复视觉卡片,但这是体验策略,不是结果正确性的依据。
|
||||
|
||||
验收应覆盖:交互从 Whiteboard 覆盖层改在 IM 中显示、Whiteboard 关闭后交互仍 pending 时,任一有效
|
||||
Interact 页面提交的第一份答案只产生一次持久化结果和一次 Agent 回传;后续提交不改变结果。
|
||||
|
||||
### P1-4:Tool 与交互的取消、超时和并发提交需要收敛规则
|
||||
|
||||
**已解决(2026-08-05):** Runtime 是标准交互的唯一终态裁决者。用户回答、Agent dismiss、到期和
|
||||
Runtime 失败都竞争同一条交互的唯一结果。
|
||||
|
||||
当前规则:
|
||||
|
||||
```text
|
||||
Runtime 对仍为 pending / presented 的 interaction 执行原子状态写入
|
||||
→ 第一个成功写入的动作获胜
|
||||
→ 用户回答:持久化答案,Tool 得到 answered
|
||||
→ Agent dismiss:交互与 Tool 得到 cancelled
|
||||
→ expires_at 到期:交互与 Tool 得到 expired
|
||||
→ Runtime 失败:交互与 Tool 得到 failed
|
||||
→ 同一事务或等价原子动作中只创建一条 Tool 结果 outbox
|
||||
|
||||
任何后到的回答、dismiss、取消或超时处理
|
||||
→ interaction_already_final
|
||||
→ 不覆盖结果,不创建第二条 outbox
|
||||
```
|
||||
|
||||
MVP 中 interactive Tool 没有另一套独立 timeout;其期限就是交互 `expires_at`。Agent 主动停止等待必须走
|
||||
`dismiss`,不走独立的通用 Tool 取消路径。
|
||||
|
||||
### P1-5:`notice` 的完成时点和 Tool 结果需要固定
|
||||
|
||||
**已解决(2026-08-05):** `notice` 是 Interact / IM 中持久保留的只读卡片;Toast 只是同一条 notice
|
||||
记录的可选短暂提醒,不是没有历史的独立消息。
|
||||
|
||||
```text
|
||||
Runtime 校验并持久化 notice 卡片
|
||||
→ 交给 Interact 呈现
|
||||
→ 当前前台界面可同时 Toast 数秒
|
||||
→ Runtime 立即以 { outcome: "accepted" } 完成并回传一次 Tool 结果
|
||||
```
|
||||
|
||||
`accepted` 只表示 Runtime 已接受、保存并安排呈现,不表示用户已看见或阅读。Toast 自动消失、用户忽略
|
||||
Toast 或收起 notice 卡片,均不产生新的 Agent 结果;持久化或安排呈现前 Runtime 失败时,结果为 `failed`。
|
||||
|
||||
## P2:本迭代验收前必须处理(本次无未决项)
|
||||
|
||||
### P2-1:将普通标准交互统一当作敏感秘密输入
|
||||
|
||||
**不再适用(2026-08-05):** 此问题把所有标准交互一概当成秘密输入,边界过重且不符合产品语义。
|
||||
`notice`、`choice`、`confirm` 与普通 `input` 是人与 Agent 的正常 IM 会话内容:已提交的内容按普通 IM
|
||||
会话历史、保留与日志基线处理,不在 SDK v1 中额外定义为密码或秘密。全局日志基线仍然有效,不能因此
|
||||
随意打印会话正文、Tool 参数或 token。
|
||||
|
||||
未提交的 `input` 草稿仍只能存在于当前运行期;重启后清空,不自动提交、发送或进入 outbox。这是恢复
|
||||
和正确性要求,不代表普通 `input` 已升级为秘密输入能力。
|
||||
|
||||
## P4:遗留问题(不阻塞当前迭代)
|
||||
|
||||
### P4-1:首次评审中的历史提案可读性
|
||||
|
||||
**延期原因:** 顶部 Outline 和总体结论已经说明早期 `sdk.ui`、owner、`parent_call_id` 等提案不再是
|
||||
实施依据;这不影响当前 SDK、Runtime 或验收实现。
|
||||
|
||||
建议在下一次文档整理或新的设计评审时,将原始评审正文加上“仅供追溯,禁止作为实现、测试或验收依据”
|
||||
的更醒目标识,或移至附录。当前有效结论始终以主定义文档和评审记录顶部的 Outline 为准。
|
||||
|
||||
### P4-2:`password-input` 秘密输入原语
|
||||
|
||||
**延期原因:** 当前 `03` 要完成的是 `notice / choice / confirm / input` 的 SDK v1 与会话交互闭环;
|
||||
目前没有真实的密码、卡密、私钥或临时 token 输入场景。把秘密输入仅做成普通 `input` 的掩码样式,不能
|
||||
解决内容怎样保留、传递、重试和清理的问题,因此不在本迭代仓促实现。
|
||||
|
||||
**重新评估条件:** Agent 确实需要向用户收集密码、卡密、私钥、临时 token 或同类秘密时,启动单独设计。
|
||||
届时 `password-input` 应作为与 `input` 并列的 Agent 交互原语,由 Runtime 按 `kind` 强制执行安全契约,
|
||||
而不是允许 Agent 用普通 `input` 自行约定保护方式。至少要明确:界面不显示明文;主 IM 只保留“已提交
|
||||
敏感信息”等替代记录;内容不进入普通日志、Telemetry 或审计;可靠 outbox 的暂存、加密(如需要)、
|
||||
Agent 接收后的清理、重启、失败、重试与一次性传递规则。
|
||||
@@ -0,0 +1,174 @@
|
||||
# `03.sdk_and_coreapp` 第 3 次设计评审记录
|
||||
|
||||
> 评审编号:03
|
||||
> 评审日期:2026-08-05
|
||||
> 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)
|
||||
> 参考资料:[APP架构设计.md](../../设计/APP架构设计.md)、[01.design_review.md](01.design_review.md)、[02.design_review.md](02.design_review.md)
|
||||
> 评审方式:基于当前主定义的独立只读复核;重点检查已确认的边界在契约、实施步骤与验收目标之间是否能够由同一套实现兑现。
|
||||
> 结论:产品层级、标准交互归属和受限 MiniApp 信任模型已稳定;未发现 P0 架构冲突。经本轮统一收敛,3 项 P1 与 2 项 P3 均已确认并回填主定义文档;后续不再进行纯设计评审,直接进入实现,并在实现完成后做一次关闭式复核。
|
||||
|
||||
## 问题清单(Outline)
|
||||
|
||||
> **状态标记:** ✅ 已确认并回填设计; 🟡 待产品/架构决策; 🔵 待在契约中细化; ⚪ 文档或实施编排建议; — 不适用或无此问题。
|
||||
>
|
||||
> 本清单是本次评审的当前有效视图。后文说明问题为何会造成实现分歧,并给出需要冻结的最小决策;在问题确认前,建议不是实施依据。确认后应先更新本清单,再回填 [03.sdk_and_coreapp.md](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 = system` MiniApp;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-input` P4 遗留事项保留在 [02.design_review.md](02.design_review.md)。
|
||||
|
||||
## P0:阻塞问题
|
||||
|
||||
无。
|
||||
|
||||
## P1:开始相关编码前必须确认(均已解决)
|
||||
|
||||
### P1-1:用户关闭 App 时,尚未结束的普通 MiniApp Tool 怎样收敛
|
||||
|
||||
**用人话说:** 用户把 Task Dashboard 或 Whiteboard 关掉时,Runtime 不能让刚才交给那个 App 的工作
|
||||
悬在半空。Agent 要么收到“这项工作已取消/失败”的唯一结果,要么 Runtime 明确保留一个可恢复、仍有执行者
|
||||
的工作;不能只关闭画面而不说明 Tool 的命运。
|
||||
|
||||
当前文档同时出现了三种没有被统一的说法:
|
||||
|
||||
```text
|
||||
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。
|
||||
|
||||
以下原“需要冻结”的项目均由上述决议覆盖:
|
||||
|
||||
1. 对每种 Tool 状态(`waiting_for_app`、`running`、`submitted` 等),规定用户/Policy 请求关闭时的行为;
|
||||
2. 规定普通 Tool 的最终结果由谁写入、是否必须先让 Tool 进入 `completed / failed / cancelled / expired` 才能完成关闭;
|
||||
3. 明确“关闭 App instance”“关闭该 App 的 Surface”“Tool 成功/失败”三者不是同一个事件,并定义允许的先后顺序;
|
||||
4. 将 Task Dashboard 与 Whiteboard 的完成、关闭和焦点恢复规则统一到同一条生命周期原则;
|
||||
5. 增加关闭进行中 Tool、重启恢复和重复关闭只产生一个最终 Tool outbox 的验收 fixture。
|
||||
|
||||
### P1-2:Agent `dismiss` 等待中的标准交互,缺少可执行的控制契约
|
||||
|
||||
**用人话说:** 文档已经允许 Agent 看到“画板已关闭”后,决定把之前的问题收起来。这很好;但还没有写清
|
||||
Agent 发来的“收起这题”消息长什么样,Runtime 怎么确认它收的是正确那一道题,以及网络重发时如何不重复
|
||||
通知 Agent。实现者因此可能各自发明一个临时控制消息。
|
||||
|
||||
当前仅有行为描述:
|
||||
|
||||
```text
|
||||
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 交互引用。
|
||||
|
||||
以下原“需要冻结”的项目均由上述决议覆盖:
|
||||
|
||||
1. 不带经验证 App 上下文的 `interactive` Tool 一律写入主 IM,不创建 App 子会话;
|
||||
2. 若 Agent 需要关联某段 App 工作,定义它可引用的稳定 App 子会话标识,以及 Runtime 必须验证的
|
||||
`agent_id`、父 conversation、App session 状态和权限边界;已关闭 App 关联的问题是否仍允许保留,需要明确;
|
||||
3. 为 `handling = interactive` 定义与普通 `ToolDescriptor.target` 不同的明确规则:例如 target 对它不适用,
|
||||
或只允许一个受限的“会话上下文”字段;不能让它暗中变成 Interact MiniApp Tool;
|
||||
4. 在 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](02.design_review.md) 为准。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
||||
# `03.sdk_and_coreapp` 第 4 次验收评审记录
|
||||
|
||||
> 评审编号:04
|
||||
> 评审日期:2026-08-05
|
||||
> 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)
|
||||
> 架构基线:[APP架构设计.md](../../设计/APP架构设计.md)
|
||||
> 参考评审:[01.design_review.md](01.design_review.md)、[02.design_review.md](02.design_review.md)、[03.design_review.md](03.design_review.md)
|
||||
> 评审方式:主 agent 交叉检查 + 独立子 agent 只读验收;检查构建、自动化测试、Runtime/MiniApp/Host 代码、SDK 契约、Manifest 和真实浏览器路径。
|
||||
> 总体结论:本轮 P0~P3 问题已完成修复,并通过代码、自动化测试和真实浏览器闭环检查;独立验收 agent 已确认本迭代可以标记为“已完成”。
|
||||
|
||||
## 问题清单(Outline)
|
||||
|
||||
> **状态标记:** 🔴 未解决,必须处理;🟡 已提出修复方向,尚未实现;✅ 已解决;⚪ 可延期但必须保留记录。
|
||||
>
|
||||
> P0~P3 必须在当前迭代处理;P4~P5 可以延期,但要写清延期原因和重新评估条件。
|
||||
|
||||
| 状态 | 优先级 | 编号 | 问题 | 证据 | 当前结论 / 下一步 |
|
||||
|---|---:|---|---|---|---|
|
||||
| ✅ | P1 | A1 | MiniApp 的 Capability 请求绕过 Runtime 的 Manifest、Policy 和审计边界 | `tauri/src/runtime/coordination/lineup-runtime.ts`、`capability-audit.ts` | 已统一经过 Manifest 声明、Capability Registry/Policy、输入 schema、前台要求和审计记录,再进入普通 Agent 确认请求;拒绝原因也由 Runtime 返回。 |
|
||||
| ✅ | P1 | A2 | `bundled` MiniApp 的业务逻辑仍在可信 Host JS 中运行,没有真正的受限执行边界 | `tauri/src/main.ts`、`isolated-surface-host.ts`、agent-browser | 已移除 Host 直接实例化;Task Dashboard/Whiteboard 业务逻辑运行在 opaque `sandbox="allow-scripts"` iframe 内,只能通过 Runtime Bridge 请求能力;真实浏览器已复验。 |
|
||||
| ✅ | P1 | A3 | SDK 暴露完整 workspace,MiniApp 可看到其他 App 实例和全局焦点栈 | `lineup-runtime.ts`、`miniapp-sdk.ts` | 已从 `LineUpMiniAppSDK` 删除 `workspace()`,不再把全局实例和焦点栈交给 bundled MiniApp。 |
|
||||
| ✅ | P1 | A4 | 同一个 App 的多个 instance 之间 Inbox 订阅没有隔离 | `lineup-runtime.ts` | 已按 `app_scope + conversation_id + instance_id` 过滤实时订阅,并补充双实例回归测试。 |
|
||||
| ✅ | P1 | A5 | Interact 使用专用 `ChatRuntimeSDK` 旁路,没有和其他 MiniApp 共用 SDK v1 语义 | `tauri/src/runtime/app-management/app-sdk.ts`、`lineup-runtime.ts`、`main.ts` | 已明确为“通用 Runtime 操作 + 可信 UI 投影”:Interact 保留可信 DOM 和 IM 展示,但行为统一走 `sdk.runtime.*`,展示走 `sdk.ui.*`;旧扁平方法仅作兼容别名。 |
|
||||
| ✅ | P1 | A6 | 标准交互的超时、dismiss、提交和答案 schema 没有由 Runtime 统一裁决 | `lineup-runtime.ts`、`agent-interaction-service.ts`、`standard-interaction-contract.ts` | 已让本地提交、取消、过期和 Agent dismiss 同步推进 Interaction 与 Kernel;notice 也会完成 Kernel;四种答案在 Runtime 按固定 schema 校验,默认有效期和重启过期均只写一条 outbox。 |
|
||||
| ✅ | P2 | A7 | 迭代文档中的 Tool 名称和代码 Manifest 不一致 | 主文档 §5.2/§5.3;`reference-miniapps.ts` | 已统一为 `task-dashboard.open`、`task-dashboard.update`、`whiteboard.open`、`whiteboard.submit`;Manifest schema、MiniApp 实现、sandbox iframe、fixture 和测试均已同步。 |
|
||||
| ✅ | P2 | A8 | 当前 Task Dashboard/Whiteboard Surface 主要是 Host 硬编码的静态页面,无法证明真实业务 UI 在各自受限 Surface 内运行 | `main.ts`、`isolated-surface-host.ts`、agent-browser Console/IM 结果 | 已修复 Bridge 方法校验不接受 SDK 的 camelCase `tools.reportProgress` 的问题。真实浏览器中分别注入并完成 `task-dashboard.open` 与 `whiteboard.open`:两者均经过 `tools.list → tools.reportProgress → surface.patch(如适用)→ tools.complete`,IM 中收到 completed 结果;两个 iframe 都是 `sandbox="allow-scripts"`、opaque origin,错误 iframe source 发送伪造 complete 不会产生 evil 结果。 |
|
||||
| ✅ | P2 | A9 | MiniApp progress 没有进入可恢复的 Tool 状态记录 | `miniapp-tool-state.ts`、`lineup-runtime.test.ts` | 已在 Tool 记录保存最后一次 `percent/status/detail`,ConversationStore 随记录持久化;Runtime 重启后可恢复,且补充状态机和重启回归测试。 |
|
||||
| ✅ | P3 | A10 | App session 记录和 opened/closed 事件没有显式保存 `agent_id` / `conversation_id` 字段 | `lineup-runtime.ts`、`lineup-runtime.test.ts` | opened/closed 事件现在都带 `agent_id`、`conversation_id`、`app_session_id`、`instance_id`、`app_scope`;并补充生命周期回归测试。 |
|
||||
| ✅ | P3 | A11 | 旧的 `openExtensionApp` 公开入口仍提供较宽的旁路能力 | `lineup-runtime.ts`、`app-sdk.ts` | 已删除 `openExtensionApp()` 和 `ExtensionRuntimeSDK`;bundled MiniApp 只能通过统一的 `openBundledMiniApp()` SDK 和 Runtime Bridge 访问能力。旧测试已改为验证统一生命周期路径。 |
|
||||
|
||||
## 1. 已验证通过的部分
|
||||
|
||||
- `npm run build` 通过。
|
||||
- `npm test -- --run` 通过:29 个测试文件、135 个测试(含 Bridge camelCase 方法、Tool 契约、默认有效期、重启过期和答案 schema 回归)。
|
||||
- `git diff --check` 通过。
|
||||
- MiniApp progress 回归通过:状态机保存最新进度,Runtime 重启后恢复 `percent/status/detail`。
|
||||
- 使用独立 `agent-browser` 会话登录本地测试账号成功;AppServer `/login`、`/messages/send`、`/messages/sync` 均可用。
|
||||
- 主 IM 页面、同步状态、应用子会话区域和“启用任务面板”入口可见。
|
||||
- 用户消息可以发送并显示“已发送”。
|
||||
- AppServer 频道中的其他用户消息已能被 Runtime 安全忽略;真实页面不再出现此前大量的 `scope_mismatch`。
|
||||
|
||||
这些证据与后续真实 Tool 闭环日志共同证明 MiniApp 隔离、统一 SDK 和状态机契约满足本轮架构要求。
|
||||
|
||||
## 2. P1 问题说明
|
||||
|
||||
### A1:Capability 请求没有经过 Runtime 的完整裁决(已修复)
|
||||
|
||||
现在 `sdk.capabilities.request(name, reason, input)` 只会进入 Runtime 的统一入口。Runtime 依次检查当前实例
|
||||
对应的 bundled Manifest 是否声明该能力、Capability Registry/Policy 是否可用、输入是否符合 schema,以及
|
||||
能力要求的前台状态;拒绝会返回明确原因,并写入不含敏感参数的审计记录。
|
||||
|
||||
通过检查后,Runtime 生成唯一 `call_id`,记录 pending 审计项,再进入普通 `lineup.v1.app.call` Agent 确认流程。
|
||||
MiniApp 不会拿到 Host handler、Transport 或权限对象。
|
||||
|
||||
### A2:bundled MiniApp 实际仍是可信代码(已修复)
|
||||
|
||||
已删除 `main.ts` 中对 `TaskDashboardMiniApp` 和 `WhiteboardMiniApp` 的直接实例化。开发版 Surface 现在把
|
||||
Task Dashboard/Whiteboard 的业务脚本放进 opaque sandbox iframe,iframe 只能发送经过校验的
|
||||
`lineup.miniapp.v1.request`,由 Runtime 执行 Inbox、Tool、生命周期和 Surface 操作;Host 不再把 Runtime 对象、
|
||||
Store 或 Transport 注入 MiniApp。
|
||||
|
||||
这与架构文档要求一致:`bundled` MiniApp 也必须使用受限 Surface/Bridge,不能因为随 Host 内置就取得
|
||||
System MiniApp 的可信 DOM 或其他特权。Task Dashboard 和 Whiteboard 已按这一边界运行,真实浏览器验收也确认
|
||||
它们的 Bridge 请求会经过 Runtime 的 instance/source 校验。
|
||||
|
||||
### A3/A4:SDK 数据边界没有做到 instance 级别(已修复)
|
||||
|
||||
`LineUpMiniAppSDK` 已不再提供 `workspace()`,因此 MiniApp 不能查看其他 instance 或 Runtime 焦点栈。
|
||||
|
||||
`inbox.list()`、ACK 和 `inbox.subscribe()` 现在都按 `app_scope + conversation_id + instance_id` 过滤;新增回归
|
||||
测试验证同一 App 的两个 instance 不会互收消息。
|
||||
|
||||
### A5:Interact 的 SDK 语义没有统一(已修复)
|
||||
|
||||
Interact 仍然可以使用可信 DOM,但它的 SDK 已明确拆成两层:`sdk.runtime.*` 提供 Runtime 行为入口,
|
||||
`sdk.ui.*` 提供 IM 和子会话的可信展示投影。标准交互、消息发送、草稿、任务操作仍由 Runtime 完成;UI
|
||||
投影没有 Transport、Store、Agent 原始 Envelope 或 Host 特权。旧的扁平 `ChatRuntimeSDK` 方法只保留为
|
||||
兼容别名,避免把 Interact 的 UI 适配误解成另一套协议。
|
||||
|
||||
### A6:标准交互有两套状态,可能互相打架(已修复)
|
||||
|
||||
已统一处理以下路径:
|
||||
|
||||
- 本地提交、取消、过期和 Agent dismiss 都同时更新 Interaction 与 Kernel Tool;任一侧不能迁移时会恢复另一侧的旧快照。
|
||||
- notice 在呈现完成时也会同步完成 Kernel Tool,避免重启后出现 Interaction 已完成而 Tool 仍 pending。
|
||||
- `choice` 只接受 `{ action_id }`,且 action 必须来自请求;`confirm` 只接受 `{ approved: boolean }`;`input` 只接受 `{ text: string }`,并校验必填和长度。
|
||||
- 终态只创建一次对应的 Tool result/cancel outbox;重复提交、重复 dismiss 和已过期提交不会再次写出站消息。
|
||||
|
||||
现在 UI、持久化记录和 Agent 看到的最终结果由 Runtime 统一推进,重复终态不会再次写出站消息。
|
||||
|
||||
## 3. 验收结论
|
||||
|
||||
当前结论为(完成本轮 P1-1~P1-4,并收敛 A7 后):
|
||||
|
||||
```text
|
||||
功能回归:通过
|
||||
基础构建与自动化测试:通过
|
||||
真实登录和消息发送:通过
|
||||
App 架构边界:通过(A1/A2/A5/A6 已实现,A2 已完成真实 iframe 复验)
|
||||
MiniApp 隔离与 SDK 规范:A1~A11 已通过。
|
||||
标准交互终态契约:通过
|
||||
迭代整体验收:通过代码、自动化测试、真实浏览器闭环和独立验收;主迭代文档已标记为“已完成”。
|
||||
```
|
||||
|
||||
本轮独立验收由子 agent `acceptance_round_08` 完成:29 个测试文件、135 个测试通过,构建和 `git diff --check` 通过;A8 的共享 agent-browser 日志确认 Task Dashboard 与 Whiteboard 均完成 `tools.list → tools.reportProgress → surface.patch(适用时)→ tools.complete`,错误 source/instance 请求未产生伪造结果。A1~A11 全部关闭,没有 P0~P3 遗留问题。
|
||||
@@ -0,0 +1,94 @@
|
||||
# `03.sdk_and_coreapp` 第 5 次验收评审记录
|
||||
|
||||
> 评审编号:05
|
||||
> 评审日期:2026-08-06
|
||||
> 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)
|
||||
> 架构基线:[APP架构设计.md](../../设计/APP架构设计.md)
|
||||
> 参考评审:[04.acceptance_review.md](04.acceptance_review.md)
|
||||
> 评审方式:独立子 agent 只读验收 + 主 agent 逐项复核;检查当前代码、Manifest、SDK 契约、自动化测试、构建和文档证据。
|
||||
> 总体结论:本轮发现的 P3 契约/证据问题均已逐项修复并分别提交;当前没有遗留 P0~P3 问题。
|
||||
|
||||
## 问题清单(Outline)
|
||||
|
||||
> **状态标记:** 🔴 未解决,必须处理;🟡 已提出修复方向,尚未实现;✅ 已解决;⚪ 可延期但必须保留记录。
|
||||
> P0~P3 必须在当前迭代处理;P4~P5 可以延期,但必须保留问题、延期原因和重新评估条件。
|
||||
|
||||
| 状态 | 优先级 | 编号 | 问题 | 当前结论 / 证据 |
|
||||
|---|---:|---|---|---|
|
||||
| ✅ | P3 | A12 | Registry 安装输入仍接受旧的 `core` / `extension` kind 别名,和冻结的 `system \| bundled` 契约不一致 | `CoreAppRecordInput` 已收紧为 `system \| bundled`;旧测试 fixture 已迁移;提交 `44b6a83`。 |
|
||||
| ✅ | P3 | A13 | 主迭代文档中的测试数量过期 | 主文档已更新为当前 `30 个测试文件、137 个测试`;提交 `94817f7` 后随新增回归测试再次更新,提交 `ca9e8b9`。 |
|
||||
| ✅ | P3 | A14 | Manifest Tool 的多项权限原先只保留第一项,可能造成后续权限漏检 | `requires_permissions[]` 已完整保存并逐项校验;Manifest/Registry 也拒绝未声明或重复权限;新增回归测试;提交 `e91d07b`。 |
|
||||
| ✅ | P3 | A15 | 当前冻结约束未硬性保证只有 Interact 能使用 `kind = system` | Registry 现在拒绝除 `chat`(Interact 兼容 scope)之外的 system MiniApp,并有回归测试;提交 `fec04a9`。 |
|
||||
|
||||
## 1. 本轮基础门禁
|
||||
|
||||
当前执行结果:
|
||||
|
||||
```text
|
||||
npm test -- --run 30 个测试文件、137 个测试通过
|
||||
npm run build 通过
|
||||
git diff --check 通过
|
||||
git status 工作树干净
|
||||
```
|
||||
|
||||
本轮独立子 agent 的只读审计确认:
|
||||
|
||||
- Interact 仍使用 `sdk.runtime.*` 与 `sdk.ui.*` 两层适配,没有第二套 Transport、Store、Tool 或 Capability 协议;
|
||||
- Task Dashboard 和 Whiteboard 仍是 `kind = bundled`,运行于 `sandbox="allow-scripts"` 的 opaque iframe;
|
||||
- MiniApp 只能通过 Runtime Bridge 请求 Inbox、Tool、Lifecycle、Surface 和 Capability;
|
||||
- `workspace()`、`openExtensionApp()`、`ExtensionRuntimeSDK` 等旧旁路没有恢复;
|
||||
- A1~A11 的已修复约束没有发现回退。
|
||||
|
||||
## 2. P3 修复说明
|
||||
|
||||
### A12:冻结 kind 词汇
|
||||
|
||||
主文档规定 `MiniAppManifest.kind` 只有 `system | bundled`。本轮发现 Runtime 的注册输入仍允许旧的
|
||||
`core | extension`,虽然最终会转换,仍会让调用方继续依赖已废弃词汇。
|
||||
|
||||
现在 `CoreAppRecordInput` 只接受 `system | bundled`,Registry 不再负责旧名称转换;受影响的测试 fixture
|
||||
已全部迁移为 `bundled`。这样 Manifest、Registry、Inventory 和 Tool Router 使用同一套名称。
|
||||
|
||||
### A13:更新验收证据
|
||||
|
||||
新增回归测试后,测试总数已经变化。本轮把主迭代文档中的旧统计更新为当前实际值 `30/137`,避免完成定义引用过期数字。
|
||||
|
||||
### A14:完整检查 Tool 权限
|
||||
|
||||
一个 Tool 可能声明多个权限。Runtime 现在保留完整的 `requires_permissions[]`,注册时要求这些权限都在 Manifest
|
||||
的 `permissions` 中且没有重复,路由时逐项确认 App 当前确实拥有每一项;缺任何一项都不会把调用交给 MiniApp。
|
||||
|
||||
### A15:限制 system MiniApp 范围
|
||||
|
||||
本迭代只有 Interact 是系统级 MiniApp,当前兼容 scope 是 `chat`。Registry 在安装边界拒绝其他 scope 的
|
||||
`kind = system`,并通过回归测试固定这一不变量。Task Dashboard 和 Whiteboard 仍只能作为受限 `bundled` MiniApp。
|
||||
|
||||
## 3. 浏览器证据说明
|
||||
|
||||
本轮独立 agent 检查时,当前环境没有正在监听的 Web Host/AppServer 进程,因此没有把本轮称为“重新触发的真实
|
||||
浏览器闭环”。Task Dashboard / Whiteboard 的真实 Bridge 闭环证据沿用上一轮共享会话记录:
|
||||
|
||||
```text
|
||||
tools.list
|
||||
→ tools.reportProgress
|
||||
→ surface.patch(Task Dashboard 适用)
|
||||
→ tools.complete
|
||||
→ IM 收到 completed 结果
|
||||
```
|
||||
|
||||
上一轮还验证了 iframe 的 `sandbox="allow-scripts"`、opaque origin、CSP、`event.source + instance_id` 校验,
|
||||
以及错误 source/instance 伪造消息不会改变 Runtime 状态。本轮新增修改没有触及这条浏览器路径;代码门禁和回归
|
||||
测试均通过。若下一轮需要重新取得独立浏览器证据,应先启动 Web Host 和 AppServer,再按相同路径复验。
|
||||
|
||||
## 4. 结论
|
||||
|
||||
```text
|
||||
P0:无
|
||||
P1:无
|
||||
P2:无
|
||||
P3:A12、A13、A14、A15 均已解决
|
||||
P4~P5:无新增遗留
|
||||
```
|
||||
|
||||
本轮没有需要留到下一迭代的 P0~P3 问题。主迭代文档仍可保持“已完成”状态;后续若增加新的 system MiniApp,
|
||||
必须先重新评审并修改本迭代冻结的唯一 system 约束,而不能绕过 Registry 安装边界。
|
||||
Reference in New Issue
Block a user