docs(lineup-app): organize current design documents
This commit is contained in:
+593
@@ -0,0 +1,593 @@
|
||||
# LineUp App 架构设计
|
||||
|
||||
**状态:** 当前权威设计基线
|
||||
**更新日期:** 2026-08-04
|
||||
**适用实现:** Tauri 2 Desktop Host 与同代码 Web Reference Host
|
||||
**本文取代:** `DESIGN.md`、`M4_COMPATIBILITY_AND_RELEASE.md`、`TECHNOLOGY_SELECTION.md`
|
||||
|
||||
## 1. 设计结论
|
||||
|
||||
**LineUp 是用户安装和使用的主应用;LineUp Runtime 是 LineUp App 内部提供给小程序的核心
|
||||
运行环境。** Runtime 不是与小程序平级的产品 App,也不是一个独立客户端。
|
||||
|
||||
```text
|
||||
LineUp App
|
||||
│
|
||||
├── App Shell / Host
|
||||
│ ├── 当前前台小程序的挂载与切换
|
||||
│ ├── 连接状态、通知和安全恢复入口
|
||||
│ └── Tauri / Web Host Provider
|
||||
│
|
||||
├── LineUp Runtime
|
||||
│ ├── AppServer / Remote Agent 通信
|
||||
│ ├── Conversation、Store、sync loop、outbox
|
||||
│ ├── MiniApp Registry、Instance、Focus、Lifecycle
|
||||
│ ├── Tool Router、Inbox、Inventory
|
||||
│ ├── Surface、Capability、Artifact、Audit
|
||||
│ └── LineUp MiniApp SDK
|
||||
│
|
||||
└── MiniApps
|
||||
├── Interact(系统内建:IM / Audio / Video)
|
||||
├── Task Dashboard(参考 / 已安装小程序)
|
||||
├── Whiteboard(参考 / 已安装小程序)
|
||||
├── Draw-and-Guess(参考 / 已安装小程序)
|
||||
└── 未来第三方小程序
|
||||
```
|
||||
|
||||
任何 MiniApp 都必须通过 Runtime SDK 使用通信、Tool、生命周期、Surface 和系统能力;不得
|
||||
建立独立 Agent 通信链路,或直接访问 Host 特权、Store、认证信息及其他 MiniApp 数据。
|
||||
|
||||
## 2. 产品边界与术语
|
||||
|
||||
| 术语 | 含义 | 不能做什么 |
|
||||
|---|---|---|
|
||||
| **LineUp App** | 用户实际使用的主应用、产品容器和交付单位。 | 不能把业务规则重新堆进 Shell。 |
|
||||
| **App Shell / Host** | Tauri 或 Web 中的挂载、切换、通知、恢复和受限 Host Provider。 | 不解释 Agent 协议,不决定 Tool/App 路由。 |
|
||||
| **LineUp Runtime** | App 内部的长期协调环境;唯一拥有通信、可靠性、MiniApp 调度与安全决策。 | 不负责任意 MiniApp 的具体 DOM 或业务 UX。 |
|
||||
| **MiniApp** | 运行在 Runtime 上的功能单元。 | 不直连 Agent/AppServer,不直写 Runtime 状态。 |
|
||||
| **System MiniApp** | 随 LineUp 发布、代码可信的内建 MiniApp,如 Interact。 | 仍不能绕过 Runtime 调度或 Capability Policy。 |
|
||||
| **Installed MiniApp** | 经验证后在受限 Surface 中运行的小程序。 | 不访问 Host DOM、Tauri invoke、token、任意网络或其他 MiniApp。 |
|
||||
| **MiniApp SDK** | Runtime 向 MiniApp 开放的受控能力集合。 | 不是通用 Web、Tauri 或 Agent SDK。 |
|
||||
| **Tool** | Agent 通过 Runtime 调用的、Manifest 已声明的 MiniApp 功能。 | 不是 App 内部任意函数。 |
|
||||
| **Capability** | Runtime/Host 保管的录音、文件、通知等系统能力。 | 不是 MiniApp 自动拥有的权限。 |
|
||||
| **Surface** | 复杂交互使用的受限 UI 容器。 | 不承载未验证远端脚本或 Host 特权。 |
|
||||
|
||||
### 2.1 Interact MiniApp
|
||||
|
||||
`Interact` 是第一个系统级 MiniApp,也是用户与 Agent 的默认交互入口:
|
||||
|
||||
```text
|
||||
Interact MiniApp
|
||||
├── IM Mode:文字、图片、短消息、任务和结果投影
|
||||
├── Audio Mode:实时语音(后续)
|
||||
├── Video Mode:实时视频(后续)
|
||||
└── IM 标准交互的默认 Renderer Provider:notice / choice / confirm / input
|
||||
```
|
||||
|
||||
当前实现仍保留兼容名称:
|
||||
|
||||
```text
|
||||
产品概念:Interact MiniApp
|
||||
当前 app_scope:chat
|
||||
当前目录:tauri/src/core-apps/chat/
|
||||
```
|
||||
|
||||
目录和作用域改名属于独立迁移任务,不能和 Runtime/MiniApp SDK 重构混在一起。
|
||||
|
||||
Interact 是可信内建代码,因此可以使用 LineUp 的可信 DOM 组件;但它和所有 MiniApp 一样,
|
||||
必须经 SDK 请求 Runtime 行为,不能直接访问 Transport、Conversation Store、焦点栈、App
|
||||
Registry、原始 Agent Envelope 或系统能力。
|
||||
|
||||
Interact 的 SDK 采用“通用 Runtime 操作 + 可信 UI 投影”的适配方式:Runtime 操作负责消息发送、
|
||||
标准交互提交/取消/过期、草稿和任务操作;UI 投影只负责 IM 视图、Agent 消息订阅和子会话展示。
|
||||
UI 投影不是另一套通信或存储协议,Interact 的可信 DOM 也不因此取得 Transport、Store、原始
|
||||
Agent Envelope、Host DOM 根节点或系统能力。当前 `chat` 兼容接口保留扁平方法,但新代码应按
|
||||
`sdk.runtime.*` 和 `sdk.ui.*` 使用。
|
||||
|
||||
## 3. 当前技术与 Host 基线
|
||||
|
||||
唯一客户端实现与验收基线是:
|
||||
|
||||
```text
|
||||
Tauri 2 Desktop Host + Web Reference Host
|
||||
```
|
||||
|
||||
它们运行同一份 TypeScript Runtime 与 MiniApp 代码,并不是两个客户端:
|
||||
|
||||
- **Web Reference Host**:浏览器开发、Tailscale 联调和自动化验证入口;只能提供可安全降级
|
||||
的浏览器能力。
|
||||
- **Tauri Desktop Host**:正式桌面交付;只在 Runtime 授权后提供文件、通知、媒体等 Host
|
||||
Provider 能力。
|
||||
|
||||
不规划独立 Android/Kotlin 客户端,也不规划 Wails Host。已退役的 Android/Wails Spike 只保留
|
||||
在 Git 历史中,不能作为架构、协议、目录或验收依据。
|
||||
|
||||
开发命令:
|
||||
|
||||
```bash
|
||||
cd lineup-app/tauri
|
||||
|
||||
npm run web:dev # Web / Tailscale Reference Host
|
||||
npm run desktop:dev # Tauri Desktop Host
|
||||
npm test -- --run # Runtime、MiniApp 与 Host 回归
|
||||
npm run build # TypeScript 检查与 Web production build
|
||||
```
|
||||
|
||||
Web Host 与 AppServer 的地址必须按访问位置匹配:同机浏览器使用 `127.0.0.1`,Tailscale 浏览器
|
||||
使用受信任的 Tailscale 地址。`0.0.0.0` 仅是服务器监听地址,不能作为浏览器 API 目标。
|
||||
|
||||
## 4. Runtime 的唯一所有权
|
||||
|
||||
Runtime 是以下对象的唯一所有者:
|
||||
|
||||
```text
|
||||
Transport
|
||||
Conversation Store
|
||||
sync loop
|
||||
outbox
|
||||
协议兼容与原始 Envelope 校验
|
||||
作用域筛选与 message_id 去重
|
||||
MiniApp Inbox 与 ACK
|
||||
MiniApp Registry、Instance、Focus、Lifecycle
|
||||
Tool Router、Inventory、Capability、Surface、审计与恢复
|
||||
```
|
||||
|
||||
当前消息路径必须保持单向:
|
||||
|
||||
```text
|
||||
AppServer / Remote Agent
|
||||
→ LineUp Runtime
|
||||
→ 协议、scope、权限、去重和持久化
|
||||
→ MiniApp SDK Inbox / Tool Call
|
||||
→ MiniApp UX
|
||||
→ SDK Result / Progress / Lifecycle Request
|
||||
→ Runtime 校验、审计、outbox
|
||||
→ AppServer / Remote Agent
|
||||
```
|
||||
|
||||
禁止项:
|
||||
|
||||
```text
|
||||
MiniApp 直接 fetch AppServer 或 Agent
|
||||
MiniApp 直接读写 Conversation Store、sync cursor 或 outbox
|
||||
MiniApp 构造或发送原始 Agent Envelope
|
||||
MiniApp 直接切换其他 MiniApp、改写 focus stack 或 Registry
|
||||
MiniApp 直接调用 Tauri invoke、Host DOM 根节点或系统能力
|
||||
Surface 从消息 payload 直接加载 URL、HTML、CSS、JS、Bundle 或 source
|
||||
```
|
||||
|
||||
## 5. MiniApp 信任模型与 SDK 权限视图
|
||||
|
||||
所有 MiniApp 共享 Runtime 的协议语义,但按来源获得不同的 SDK 视图。
|
||||
|
||||
| 能力 | Interact / System MiniApp | Installed MiniApp |
|
||||
|---|---:|---:|
|
||||
| 接收自身 Inbox、ACK | 可以 | 可以 |
|
||||
| 接收 Runtime Tool Call | 可以 | 可以 |
|
||||
| 上报 progress / result / error | 可以 | 可以 |
|
||||
| 请求前台、后台、关闭 | 可以,由 Runtime 决定 | 可以,由 Runtime 决定 |
|
||||
| 请求 Surface | 可以,经 Runtime Policy | 可以,经 Runtime Policy |
|
||||
| 请求 Capability | 可以,经 Runtime Policy | 可以,经 Runtime Policy |
|
||||
| 可信内建 DOM 组件 | 可以 | 不可以 |
|
||||
| 隔离 iframe / Surface Bridge | 可选 | 必须 |
|
||||
| 直连 Transport、Store、Agent | 不可以 | 不可以 |
|
||||
| 直接 Host / Tauri / OS 调用 | 不可以 | 不可以 |
|
||||
| 读取其他 MiniApp 数据 | 不可以 | 不可以 |
|
||||
|
||||
系统内建不等于绕过 Runtime:可信来源只决定代码的发布与 UI 执行方式,不改变 Runtime 的
|
||||
通信、焦点、Tool、权限和审计边界。
|
||||
|
||||
## 6. MiniApp 实例、焦点与恢复
|
||||
|
||||
MiniApp Registry 管理“有哪些小程序”,Instance Manager 管理“哪些实例正在运行”。二者不能
|
||||
混为一个状态。
|
||||
|
||||
```ts
|
||||
type MiniAppInstanceRecord = {
|
||||
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 保存焦点栈,不以单个 MiniApp 自己的布尔状态作为事实来源:
|
||||
|
||||
```text
|
||||
focus stack:
|
||||
chat:audio-001
|
||||
draw-and-guess:game-001
|
||||
|
||||
foreground:
|
||||
draw-and-guess:game-001
|
||||
|
||||
background:
|
||||
chat:audio-001
|
||||
```
|
||||
|
||||
当扩展 MiniApp 关闭或失败时,Runtime 必须恢复焦点栈中的前一有效实例。重启后,Runtime
|
||||
恢复有界的实例与焦点状态;`starting` 或 `stopping` 中断的实例必须安全降级为 `suspended`,
|
||||
不得伪装为已完成的 Host 操作。
|
||||
|
||||
## 7. MiniApp SDK v1
|
||||
|
||||
下一阶段的核心交付是 **LineUp MiniApp SDK v1**。SDK 不是万能 API,而是 Runtime 根据
|
||||
Manifest、实例状态、权限和 Policy 开放的最小请求集合。
|
||||
|
||||
```ts
|
||||
interface LineUpMiniAppSDK {
|
||||
readonly context: MiniAppContext;
|
||||
|
||||
inbox: MiniAppInboxAPI;
|
||||
tools: MiniAppToolAPI;
|
||||
lifecycle: MiniAppLifecycleAPI;
|
||||
surfaces: MiniAppSurfaceAPI;
|
||||
capabilities: MiniAppCapabilityRequestAPI;
|
||||
}
|
||||
|
||||
type MiniAppContext = {
|
||||
app_scope: string;
|
||||
instance_id: string;
|
||||
conversation_id: string;
|
||||
app_version: string;
|
||||
state: "starting" | "foreground" | "background" | "suspended";
|
||||
};
|
||||
```
|
||||
|
||||
### 7.1 Inbox
|
||||
|
||||
```ts
|
||||
interface MiniAppInboxAPI {
|
||||
list(after_message_id?: string): readonly MiniAppMessage[];
|
||||
subscribe(listener: (message: MiniAppMessage) => void): Unsubscribe;
|
||||
acknowledge(message_id: string): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
Runtime 在投递前校验 Envelope、scope、目标 MiniApp、实例状态和去重;消息先持久化,再由
|
||||
MiniApp ACK。后台化、刷新、Surface 重载或 Runtime 重启不能丢失未处理消息。
|
||||
|
||||
### 7.2 Tool
|
||||
|
||||
```ts
|
||||
interface MiniAppToolAPI {
|
||||
subscribe(listener: (call: MiniAppToolCall) => void): Unsubscribe;
|
||||
get(call_id: string): MiniAppToolCall | undefined;
|
||||
reportProgress(call_id: string, progress: MiniAppToolProgress): Promise<CommandReceipt>;
|
||||
complete(call_id: string, result: JsonObject): Promise<CommandReceipt>;
|
||||
fail(call_id: string, failure: MiniAppToolFailure): Promise<CommandReceipt>;
|
||||
cancel(call_id: string, reason?: string): Promise<CommandReceipt>;
|
||||
}
|
||||
```
|
||||
|
||||
`complete`、`fail`、`cancel` 都是对 Runtime 的请求,不是直接网络发送。Runtime 必须验证
|
||||
`call_id` 的实例归属、合法状态迁移、输入/输出 schema、幂等性和权限,然后持久化、审计并
|
||||
写入 outbox。
|
||||
|
||||
一旦 Runtime 接受某个 App instance 的关闭,关闭表示释放该 instance,不是把它留在后台:Runtime 停止
|
||||
向它投递新普通 Tool,将仍为 `received / routing / waiting_for_app / running` 的绑定 Tool 原子收敛为
|
||||
`cancelled(app_closed)`,每条 Tool 只写一条 cancelled outbox;已 `submitted` 的结果不可改写,继续可靠发出。
|
||||
然后才关闭 Surface、停止 instance、结束 App 子会话并恢复焦点。普通 Tool 的完成或失败本身不关闭 App。
|
||||
标准交互是例外:App 关闭只通知 Agent,不自动取消仍 pending 的人与 Agent 交互。
|
||||
|
||||
### 7.3 人与 Agent 标准交互、Lifecycle、Surface 与 Capability
|
||||
|
||||
`notice`、`choice`、`confirm`、`input` 是 Interact 的人与 Agent 交互组件,与 IM 消息同属于
|
||||
当前会话;它们不是 MiniApp SDK,也不用于 MiniApp 自己的业务表单、确认或输入。Agent 通过
|
||||
标准 Tool 交互请求发起它们,Runtime 校验、持久化、恢复、审计并可靠回传结果,Interact 负责呈现。
|
||||
|
||||
这四种是普通的人与 Agent 会话交互,不在 SDK v1 中统一定义为密码或秘密输入。已提交内容遵循普通 IM
|
||||
的会话历史、保留和日志基线;尤其不能因为它们是普通输入,就突破全局“日志不记录会话正文、Tool 参数、
|
||||
token 等内容”的约束。未提交 `input` 草稿仅保留在当前运行期,重启清空。密码、卡密、私钥、临时 token
|
||||
等真正秘密输入留待未来作为独立的 `password-input` 原语设计;届时 Runtime 必须按类型强制其展示、记录、
|
||||
传递和清理规则,Agent 不能用普通 `input` 绕过这些保护。
|
||||
|
||||
每条人与 Agent 的标准交互都必须在 Interact / IM 中留下相应的卡片、气泡或结果记录。`notice` 是只读
|
||||
IM 卡片;当前界面可同时短暂 Toast 提醒,但 Toast 只是同一条记录的辅助呈现,不能作为唯一消息或用户
|
||||
已阅读的证明。Runtime 成功持久化 notice 卡片并交给 Interact 呈现后,即可向 Agent 返回 `accepted`。
|
||||
|
||||
MVP 中,一个 LineUp Runtime 只连接一个 Agent,当前登录会话的 `agent_uid` 作为每条交互和
|
||||
App 子会话的 `agent_id`。此处保存 Agent 身份是为了让答案按创建时的上下文回到正确对象;本阶段
|
||||
不实现多 Agent 连接、切换、会话列表、outbox 或跨 Agent 路由。
|
||||
|
||||
Agent 发 interactive Tool 时,未带经过 Runtime 验证的 `app_session_context.app_session_id`,一律归入主 IM;
|
||||
Runtime 绝不能按当前前台 App 猜测归属。若带有该上下文,Runtime 只接受同一 Agent、同一父会话的真实
|
||||
App 子会话;已经关闭的子会话可保留为历史上下文,但不复活旧 App。Runtime 创建子会话时会可靠告知 Agent
|
||||
其稳定 ID,非法或跨会话的引用直接拒绝且不创建交互。
|
||||
|
||||
当 Interact 位于前台时,标准交互显示在 IM 时间线/卡片中;当 bundled MiniApp 位于前台时,
|
||||
Interact / Shell 可以在当前 App 之上显示同一会话的交互层。视觉位置不改变归属:请求和结果始终
|
||||
属于当前 conversation、Agent call 与 Interact instance,结果经 Runtime 回传 Agent,而不交给
|
||||
前台 MiniApp。
|
||||
|
||||
用户作答时,Interact 只把“交互 ID + 用户动作/答案”交给 Runtime,不直接把答案发送给 Agent。Runtime
|
||||
从创建时保存的记录取得 Agent、主会话、App 子会话和 Tool 的归属,并核对当前 LineUp / Interact 会话、
|
||||
有效期、答案格式和是否已结束。只有第一次有效回答可以写入会话历史和可靠 outbox;后续重复或重放提交
|
||||
不得改变结果,也不得再次通知 Agent。展示位置不是交互的 owner 或提交权限:App 前后台切换、关闭或从
|
||||
覆盖层改在 IM 显示,都不改变交互归属。客户端不能提交或改写 Agent、会话、Tool 或 App 子会话的归属字段。
|
||||
|
||||
用户回答、Agent remote dismiss、到期和 Runtime 失败都只能竞争同一条交互的唯一终态。Runtime 以第一个
|
||||
成功完成的原子状态写入为准,并同时持久化唯一 Tool 结果/outbox;后来到达的动作不得覆盖结果或再次通知
|
||||
Agent。MVP 中 interactive Tool 的等待期限与交互的 `expires_at` 相同,Agent 主动停止等待必须走 Runtime
|
||||
私有的 `interaction.dismiss(control_id, call_id)`:Runtime 从受认证 Envelope 推导 Agent 和会话,以 `call_id`
|
||||
定位交互。重放或目标已终态只返回稳定幂等回执,绝不再写 outbox;该控制契约不属于 MiniApp SDK。
|
||||
|
||||
启动一个 App instance 会在主 IM 会话中创建或恢复与之关联的 App 子会话,并可靠向当前 Agent 发送
|
||||
`app_session.opened`,提供 `agent_id`、`conversation_id`、`app_session_id`、`app_scope` 与 `instance_id`。
|
||||
主 IM 将其显示为可展开的
|
||||
折叠组,记录 Agent 的提问、用户回答和 Agent 的简洁结果;它不记录 App 内部业务操作,例如用户在
|
||||
Task Dashboard 点击按钮或填写 App 自己的表单、在 Whiteboard 绘制和编辑内容。App 进入后台时,
|
||||
子会话仍继续;Agent Tool 完成也不自动结束子会话。只有 Runtime 的 `AppLifecycleManager.close` 使
|
||||
instance 进入 stopped 或 failed、并从 focus stack 移除时,子会话才结束但保留为主 IM 的历史。新的
|
||||
App instance 必须创建新的子会话,不接续旧实例记录。
|
||||
|
||||
已结束子会话可在主 IM 中只读展开,但不会重新启动 App、重新执行操作或复活未回答的问题。用户选择
|
||||
“继续处理”旧工作时,Runtime 启动新的 App instance 和新的子会话;新子会话可以引用旧会话、artifact
|
||||
或已保存的 App 状态作为上下文,但不能向旧子会话追加记录。
|
||||
|
||||
若 App 子会话关联等待回答的 Agent 问题,App 位于前台时 Interact 可在其上方显示提问层;用户切换到
|
||||
其他 App 或普通 IM 时,该层收起但问题继续等待,主 IM 的对应折叠组标记“等待你的回答”。用户既可
|
||||
展开该组直接回答,也可回到原 App 后回答。Shell 可避免用户看到重复的视觉卡片,但展示位置不改变交互
|
||||
归属或提交资格;Runtime 通过首次有效回答和终态检查防止重复结果。真正关闭 App 会按普通 Tool 的
|
||||
`app_closed` 规则先收敛未终态 Tool,随后移除该 App 上方的展示层并结束 App 子会话。Runtime 将关闭事件
|
||||
(含仍 pending 的 interaction call_id)可靠通知 Agent;问题本身仍属于 Interact / 主 IM,直到 Agent 远程
|
||||
dismiss、用户回答、到期或 Runtime 失败才结束。
|
||||
|
||||
因此 bundled MiniApp 不能发起、读取、提交或取消这类 Agent 交互,也不因其显示在自身上方而获得
|
||||
Host DOM 或会话数据。复杂、高频或私有业务 UI(例如 Task Dashboard 的“新建任务”表单、Whiteboard
|
||||
画布文字编辑、画笔、颜色选择、拖放和工具栏)必须留在 MiniApp 自己的 Surface 内。系统权限确认
|
||||
(文件、麦克风、通知等)则属于 Runtime/Host Capability Gateway,而不是普通 `confirm`。
|
||||
|
||||
```ts
|
||||
interface MiniAppLifecycleAPI {
|
||||
requestForeground(): Promise<CommandReceipt>;
|
||||
requestBackground(): Promise<CommandReceipt>;
|
||||
requestClose(reason?: string): Promise<CommandReceipt>;
|
||||
}
|
||||
```
|
||||
|
||||
MiniApp 只能请求生命周期变化;Runtime 决定是否允许。若接受关闭,则按上面的 `app_closed` 收敛普通 Tool、
|
||||
处理 Surface 并恢复焦点;若用户只想暂时离开,应请求后台化。
|
||||
|
||||
Surface 与 Capability 也只能请求:
|
||||
|
||||
```text
|
||||
MiniApp requestOpenSurface / requestCapability
|
||||
→ Runtime 校验 Manifest、Policy、实例状态和用户确认要求
|
||||
→ Host Provider 执行受限操作
|
||||
→ Runtime 记录审计并返回受控结果
|
||||
```
|
||||
|
||||
不应在 SDK v1 提供 `fetch`、任意网络、任意文件系统、剪贴板、麦克风、摄像头或 Tauri
|
||||
直接调用。高风险能力以后通过 Capability Request 按需开放。
|
||||
|
||||
## 8. Tool Contract 与 Inventory
|
||||
|
||||
MiniApp 只能在 Manifest 中声明 Tool;Agent 只能调用当前 Runtime 已公布 Inventory 中的 Tool。
|
||||
|
||||
```ts
|
||||
type ToolDescriptorBase = {
|
||||
id: string; // 例如 task-dashboard.open
|
||||
version: 1;
|
||||
input_schema: JsonSchema;
|
||||
output_schema: JsonSchema;
|
||||
permissions?: readonly string[];
|
||||
};
|
||||
|
||||
type ToolDescriptor = ToolDescriptorBase & (
|
||||
| { handling: "interactive"; target?: never }
|
||||
| {
|
||||
handling: "direct" | "launch" | "foreground" | "operation";
|
||||
target: {
|
||||
app_scope: string;
|
||||
requires_foreground: boolean;
|
||||
restore_previous_focus: boolean;
|
||||
};
|
||||
timeout_ms?: number;
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
统一调度路径:
|
||||
|
||||
```text
|
||||
Agent Tool Invoke
|
||||
→ Runtime 校验 Envelope、Inventory revision、Tool Descriptor、参数、scope、App 状态和权限
|
||||
→ 创建可持久化 Tool Call / 审计记录
|
||||
→ Tool Router 判定 direct / interactive / launch / foreground / operation
|
||||
├── interactive:不使用 target、不创建业务 instance,只由 Runtime 建立 Interact 会话交互
|
||||
└── 其他 handling:投递到目标 MiniApp instance
|
||||
→ MiniApp SDK 报告 progress / result / error
|
||||
→ Runtime 校验输出 schema、持久化、更新焦点、写 outbox
|
||||
→ Agent 收到可靠结果
|
||||
```
|
||||
|
||||
`notice`、`choice`、`confirm`、`input` 是 Agent 调起的 Runtime 统一 `interactive` Tool/交互记录
|
||||
能力。Interact 提供会话语义和呈现,Runtime 持有记录与可靠结果路径;其他 MiniApp 只能作为当前
|
||||
前台界面被 Interact 交互层覆盖,不能调用、实现或取得该交互的内容与结果。
|
||||
|
||||
可回答交互的请求以相对 `expires_in_ms` 指定期限;Runtime 计算和持久化 `expires_at`,缺省 15 分钟,
|
||||
仅接受 1 分钟至 24 小时。notice 不等待回答,也不接受期限。
|
||||
|
||||
建议稳定拒绝码至少包括:
|
||||
|
||||
```text
|
||||
inventory_revision_mismatch
|
||||
tool_not_advertised
|
||||
tool_input_invalid
|
||||
tool_output_invalid
|
||||
app_disabled
|
||||
app_instance_not_found
|
||||
app_scope_mismatch
|
||||
lifecycle_denied
|
||||
capability_denied
|
||||
call_already_final
|
||||
```
|
||||
|
||||
## 9. Surface、Bundle、Capability 与发布安全
|
||||
|
||||
复杂 UI 只能运行在受限 Surface 中。Installed MiniApp 的生产 Bundle 必须满足:
|
||||
|
||||
```text
|
||||
签名 Manifest
|
||||
→ 精确 byte size 校验
|
||||
→ SHA-256 校验
|
||||
→ 原子写入已验证 cache
|
||||
→ app_id + exact version 解析
|
||||
→ sandbox="allow-scripts" 的隔离 Surface
|
||||
```
|
||||
|
||||
### 9.1 Host 兼容矩阵
|
||||
|
||||
| 情况 | Host 必须行为 | 禁止行为 | 观测信号 |
|
||||
|---|---|---|---|
|
||||
| 旧 Client 收到未知 `lineup.v1.*` | 安全 fallback,不执行 | 将 payload 当 HTML/能力执行 | `unsupported_type` / `unsupported_version` |
|
||||
| 新 Client 收到旧 plain text | 仅作为 Markdown 显示 | 赋予交互或能力 | legacy markdown renderer |
|
||||
| 不支持目标 Surface version | 不挂载,显示安全提示 | 自动前移到相邻版本 | `surface_unavailable` |
|
||||
| 收到生产 Surface | 仅在签名、长度、SHA-256 成功后挂载已验证 bytes | 接收 URL、HTML、JS、Bundle/source | install disposition |
|
||||
| 候选 Bundle 验证失败 | 保留当前 active 已验证版本 | 覆盖 active bytes 或执行候选 | `signature_invalid` 等 |
|
||||
| active Bundle 被撤销 | 原子回滚到已验证 predecessor;没有则不可用 | 回退到未验证缓存/远端 URL | `rolled_back` / `unavailable` |
|
||||
| Bridge 收到非当前 iframe 消息 | 丢弃 | 仅相信 origin 字符串或调用 Host API | bridge rejection counter |
|
||||
| Capability Catalog 变化 | 发布最小新 Inventory | 用过期 Inventory 自动执行 | catalog revision |
|
||||
|
||||
### 9.2 生产发布序列
|
||||
|
||||
1. 发布方创建不可变 artifact 与生产 Manifest:`app_id`、精确版本、artifact ID、长度、
|
||||
SHA-256、最小 Host 版本、权限、可信 `key_id`、Ed25519 签名。
|
||||
2. Manifest 与 Bundle 部署在 Host 配置的 HTTPS artifact 服务;Manifest 不携带 URL、HTML、
|
||||
CSS、JS 或 source。
|
||||
3. Host 在临时内存中验证签名、精确长度与 SHA-256;失败不写 cache。
|
||||
4. 验证成功后原子安装,并只解析精确 `app_id + version`;不得自动前移版本。
|
||||
5. 仅向满足最小 Host 版本且已启用目标版本的 Client 灰度发布。
|
||||
6. 监控签名、摘要、下载、Bridge 与 Capability 状态;安全事件发生时只回滚到已验证的
|
||||
predecessor。
|
||||
7. 回滚后保留审计元数据,但不记录 artifact 内容、URL、token、文件路径或 Capability 参数;
|
||||
新 artifact 必须使用新版本号。
|
||||
|
||||
正式 HTTPS Host 才可被标记为 production-capable。HTTP LAN 开发 Host 在浏览器 WebCrypto
|
||||
受限时必须安全拒绝验签,不能为了联调放宽该规则。
|
||||
|
||||
## 10. 当前实现状态
|
||||
|
||||
### 10.1 已完成:历史安全基础
|
||||
|
||||
历史 M0~M4 已完成并沉淀在当前代码中;它们不是新的平行排期:
|
||||
|
||||
| 历史阶段 | 保留能力 |
|
||||
|---|---|
|
||||
| M0 | HTTP Transport、Conversation Store、协议解码、Markdown、安全 fallback、基础回归 |
|
||||
| M1 | Tool Call、Task、可靠交互结果、执行摘要、可信 choice/confirm/input |
|
||||
| M2 | Surface Registry、实例生命周期、隔离 iframe 与恢复 |
|
||||
| M3 | Capability Registry、用户确认、审计与受限 Host 执行 |
|
||||
| M4 | 签名 Manifest、Bundle 校验/缓存/回滚、golden fixture |
|
||||
|
||||
### 10.2 已完成:第二次升级
|
||||
|
||||
```text
|
||||
00.base
|
||||
→ Runtime 托管 Interact IM(当前兼容名 chat)的稳定基线
|
||||
|
||||
01.kernel
|
||||
→ MiniApp Instance / Focus / Lifecycle、Tool Router、App Orchestrator、
|
||||
Extension SDK 雏形、Workspace 持久化和恢复
|
||||
```
|
||||
|
||||
当前实现已验证登录、同步、本地回显、Markdown、安全渲染、Tool Call、Task、Surface、
|
||||
Capability、App Inbox、outbox、实例焦点恢复和生产构建。自动化回归当前为 23 个测试文件、
|
||||
99 个测试;`npm run build` 通过。
|
||||
|
||||
Runtime 的关键结构位于:
|
||||
|
||||
```text
|
||||
tauri/src/runtime/app-management/
|
||||
tauri/src/runtime/coordination/
|
||||
tauri/src/runtime/persistence/
|
||||
tauri/src/runtime/protocol/
|
||||
tauri/src/runtime/surfaces/
|
||||
tauri/src/runtime/capabilities/
|
||||
tauri/src/core-apps/chat/
|
||||
```
|
||||
|
||||
### 10.3 下一阶段:03.sdk_and_coreapp
|
||||
|
||||
下一阶段不是应用市场,也不是立即建设服务端下载目录。目标见
|
||||
[03.sdk_and_coreapp.md](../迭代/03.sdk_and_coreapp/03.sdk_and_coreapp.md):定义并验证 MiniApp SDK v1:
|
||||
|
||||
```text
|
||||
冻结 AppManifest、ToolDescriptor、Tool Call、App Context、Result/Progress/Error 和错误码
|
||||
→ Runtime 实现通用 SDK 请求路由、schema 校验、审计、恢复和 revisioned Inventory
|
||||
→ Interact 适配为第一个 System MiniApp SDK 样本
|
||||
→ Task Dashboard 作为第一个参考 MiniApp 验证 Tool、progress、result、focus 与恢复
|
||||
→ Whiteboard 验证受限 Surface、状态 patch、Artifact 与 Capability 请求
|
||||
```
|
||||
|
||||
参考 MiniApp 在此阶段使用 `kind = bundled`:随开发 Host 内置、有 Manifest 和 Runtime 注册记录,
|
||||
但不依赖服务端 Catalog、远程下载或第三方发布。`bundled` 不是系统级信任;参考只描述这些
|
||||
MiniApp 在当前阶段用于验证 SDK 的工作目的,不是 Manifest 类型名称。
|
||||
|
||||
### 10.4 后续阶段
|
||||
|
||||
MiniApp SDK 与参考实现稳定后,再按顺序推进:
|
||||
|
||||
```text
|
||||
04.app-delivery-registry
|
||||
→ Catalog Entry、Manifest/Bundle 下载、验签、安装、启用、禁用、更新、回滚、移除
|
||||
|
||||
05.catalog-and-market(按产品需要)
|
||||
→ 搜索、分类、发布者、安装 UX、组织分发与可能的商业能力
|
||||
```
|
||||
|
||||
`03.sdk_and_coreapp` 已经包含 Task Dashboard 和 Whiteboard 的端到端参考实现;不再另设
|
||||
`03.reference-miniapps`,以免把同一批工作拆成两个编号。
|
||||
|
||||
“市场”属于最后的产品分发层,不能反向决定 Runtime、SDK、Tool 或安全模型。
|
||||
|
||||
## 11. 验收与发布门槛
|
||||
|
||||
每次 Runtime、MiniApp SDK 或 Host 改动至少满足:
|
||||
|
||||
```text
|
||||
npm test -- --run
|
||||
npm run build
|
||||
```
|
||||
|
||||
对于 SDK/参考 MiniApp,还必须有以下证据:
|
||||
|
||||
1. 合法与非法 Manifest、Inventory revision、Tool 输入/输出 schema 的自动化测试;
|
||||
2. Tool 启动 MiniApp、前后台切换、结果回传、失败回焦和重启恢复的场景测试;接受关闭后,未终态普通 Tool
|
||||
仅产生一次 `app_closed` 取消、已 submitted 结果继续 outbox,随后才关闭 Surface / instance 并恢复焦点;
|
||||
3. Interact 的 `notice / choice / confirm / input` 会话呈现不退化,覆盖 IM 内联与前台 bundled
|
||||
MiniApp 上交互层的显示、conversation/call 绑定、结果可靠回传 Agent、默认/越界交互期限、非法
|
||||
`app_session_context` 拒绝、`interaction.dismiss` 幂等重放,以及 bundled MiniApp 无法访问或提交交互的测试;
|
||||
4. MVP 的单 Agent 身份随交互和 App 子会话持久化;不新增多 Agent 连接、切换、会话列表或路由;
|
||||
5. App instance 的子会话创建、后台/暂停保留、`AppLifecycleManager.close` 后结束折叠、重启恢复和新 instance 隔离可验证;创建时会可靠向 Agent
|
||||
提供 `app_session_id`,关闭时会发出包含仍 pending interaction call_id 的可靠 App 已关闭事件,但不会自动
|
||||
取消 Interact 交互;子会话只包含人与 Agent 的交互,不包含 MiniApp 的内部业务操作;
|
||||
6. 已结束子会话可只读查看;“继续处理”旧工作会创建新 instance / 新子会话,可引用旧上下文但不复活旧问题;
|
||||
7. App 切换时未回答问题从前台 App 上方收起并在对应子会话标记;用户可在 IM 或回到原 App 后回答,且同一问题不可重复提交;
|
||||
8. Installed MiniApp 无法取得 Host DOM、Tauri invoke、token、任意网络或其他 MiniApp 数据;
|
||||
9. 有头浏览器验证登录、同步、本地回显和代表性 MiniApp 路径;
|
||||
10. 对生产 Bundle,验证签名 `open → patch → close → rollback`、隔离 Bridge 和 Capability 拒绝路径;
|
||||
11. `git diff --check` 无格式错误,日志不得包含身份、会话、消息正文、Tool 参数、token 或
|
||||
artifact 内容。
|
||||
|
||||
## 12. 相关文档与源码导航
|
||||
|
||||
- [迭代/00.base/00.base.md](../迭代/00.base/00.base.md):Runtime 托管 Interact IM 的稳定基线。
|
||||
- [迭代/01.kernel/01.kernel.md](../迭代/01.kernel/01.kernel.md):Runtime Kernel 与 MiniApp 编排目标和验收。
|
||||
- [tauri/src/README.md](../tauri/src/README.md):当前源码目录和依赖方向。
|
||||
- [tauri/README.md](../tauri/README.md):Tauri/Web Host 的运行、回归与历史实施细节。
|
||||
- [程序文件清单与功能说明.md](../程序文件清单与功能说明.md):实现文件和功能说明。
|
||||
- [LineUp App 最终设计方案](02.正式方案/app_final_design.md):跨文档详细契约来源;
|
||||
若与本文的产品术语或当前迭代顺序冲突,以本文为准并同步更新上游方案。
|
||||
Reference in New Issue
Block a user