diff --git a/README.md b/README.md index 2c56457..a6f4ea3 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Chat Core App - 登录、同步、发送、本地回显、Markdown、Agent 状态和刷新恢复保持回归通过; - 当前 Tauri/Web 回归为 23 个测试文件、99 个测试,`npm run build` 通过。 -完整边界、MiniApp SDK 路线和发布安全约束见 [APP架构设计.md](APP架构设计.md)。 +完整边界、MiniApp SDK 路线和发布安全约束见 [APP架构设计.md](设计/APP架构设计.md)。 ## 开发与验证 @@ -92,22 +92,26 @@ npm run desktop:dev ## 文档入口 -- [APP架构设计.md](APP架构设计.md):LineUp App、Runtime、MiniApp SDK、Surface/Capability 安全与后续迭代的权威架构设计; +- [设计/README.md](设计/README.md):当前设计文档入口和文档分工说明; +- [APP架构设计.md](设计/APP架构设计.md):LineUp App、Runtime、MiniApp SDK、Surface/Capability 安全与后续迭代的权威架构设计; - [程序文件清单与功能说明.md](程序文件清单与功能说明.md):客户端 Runtime、Chat Core App、Tauri/Web Host 与测试的文件清单; - [tauri/src/README.md](tauri/src/README.md):源码目录、依赖方向与模块放置规则; - [tauri/README.md](tauri/README.md):Tauri/Web Host 的运行、构建、行为回归和历史里程碑; - [迭代/](迭代/00.base/00.base.md):按迭代目录记录当前基线、设计评审和后续 Runtime Kernel / 应用编排目标; -- [LineUp App 最终设计方案](../设计/02.正式方案/app_final_design.md):当前架构的唯一汇总入口; -- [LineUp App 层架构方案](../设计/02.正式方案/lineup-app-layer-architecture.md):M0~M4 历史实施记录与迁移基础; -- [LineUp Runtime 与 App SDK 架构方案](../设计/02.正式方案/lineup-runtime-sdk-architecture.md):Runtime / SDK 的详细契约来源; -- [LineUp UI Surface 与 App Capability 协议](../设计/02.正式方案/lineup-ui-surface-protocol.md):Surface sandbox 和 Capability Gateway 协议; +- [LineUp App 最终设计方案](设计/02.正式方案/app_final_design.md):当前架构的唯一汇总入口; +- [LineUp App 层架构方案](设计/02.正式方案/lineup-app-layer-architecture.md):M0~M4 历史实施记录与迁移基础; +- [LineUp Runtime 与 App SDK 架构方案](设计/02.正式方案/lineup-runtime-sdk-architecture.md):Runtime / SDK 的详细契约来源; +- [LineUp UI Surface 与 App Capability 协议](设计/02.正式方案/lineup-ui-surface-protocol.md):Surface sandbox 和 Capability Gateway 协议; ## 工作区目录 ```text lineup-app/ ├── README.md # LineUp App 工作区入口 -├── APP架构设计.md # 当前权威架构、SDK 与发布安全设计 +├── 设计/ # 当前设计文档 +│ ├── README.md +│ ├── APP架构设计.md +│ └── 02.正式方案/ └── tauri/ # Tauri Desktop + Web Reference Host ├── src/ # Runtime、Core App 与 Host 组合入口 └── src-tauri/ # Tauri Rust Host diff --git a/tauri/README.md b/tauri/README.md index 0b5ef13..eeca15e 100644 --- a/tauri/README.md +++ b/tauri/README.md @@ -29,7 +29,7 @@ Surface、Capability、签名 Bundle 与隔离 bridge 已有 M2~M4 的实现 ## Milestone 0 当前行为基线 -本节记录 Runtime 重构前已经由 Mac 开发态验证的行为。它是 M0 的回归基线,不代表最终模块结构;正式阶段任务和准入门槛见 [App Layer 架构方案 §9.1](../../设计/02.正式方案/lineup-app-layer-architecture.md#91-阶段任务清单与硬性准入门槛)。 +本节记录 Runtime 重构前已经由 Mac 开发态验证的行为。它是 M0 的回归基线,不代表最终模块结构;正式阶段任务和准入门槛见 [App Layer 架构方案 §9.1](../设计/02.正式方案/lineup-app-layer-architecture.md#91-阶段任务清单与硬性准入门槛)。 | 范围 | 当前行为 | 当前实现位置 | 重构后必须保持 | |---|---|---|---| diff --git a/程序文件清单与功能说明.md b/程序文件清单与功能说明.md index a0867d2..e77be65 100644 --- a/程序文件清单与功能说明.md +++ b/程序文件清单与功能说明.md @@ -152,8 +152,8 @@ npm run desktop:dev - [工作区 README](README.md):产品基线、MVP-R1、开发入口与文档导航。 - [迭代基线与目标](迭代/00.base/00.base.md):`00.base` 已实现内容和 `01.kernel` Runtime Kernel 目标。 -- [APP 架构设计](APP架构设计.md):LineUp App、Runtime、MiniApp SDK、发布安全与后续阶段。 +- [APP 架构设计](设计/APP架构设计.md):LineUp App、Runtime、MiniApp SDK、发布安全与后续阶段。 - [Tauri/Web 源码导航](tauri/src/README.md):目录边界与依赖方向。 - [Tauri/Web Host README](tauri/README.md):Host 运行、构建、行为回归与历史记录。 - [根程序文件清单](../程序文件清单与功能说明.md):AppServer、Hermes、WuKongIM 和运行配置。 -- [App 最终设计方案](../设计/02.正式方案/app_final_design.md):架构决策的唯一汇总入口。 +- [App 最终设计方案](设计/02.正式方案/app_final_design.md):架构决策的唯一汇总入口。 diff --git a/设计/02.正式方案/app_final_design.md b/设计/02.正式方案/app_final_design.md new file mode 100644 index 0000000..aa1a22b --- /dev/null +++ b/设计/02.正式方案/app_final_design.md @@ -0,0 +1,813 @@ +# LineUp App 最终设计方案 + +**版本:** 1.0(当前开发基线) +**状态:** 当前 App 设计的唯一汇总入口 +**日期:** 2026-08-04 +**来源:** [App 层架构方案](lineup-app-layer-architecture.md)、[Runtime 与 App SDK 架构方案](lineup-runtime-sdk-architecture.md)、[UI Surface 与 App Capability 协议](lineup-ui-surface-protocol.md) + +--- + +## 0. 一句话定义 + +**LineUp 是运行在用户设备上的协作 Runtime,也就是整个产品的本地协调中心。** + +Runtime 负责连接 AppServer 和 Remote Agent,保存会话与消息,管理应用、工具、权限和 +本地恢复。图文聊天、应用注册表、语音对话、画板和游戏则是在这个底座上运行的 App。 +用户使用 App 完成操作,Agent 发来消息或请求;两边都先交给 Runtime 处理,因此任何 App +都不需要、也不能自己处理连接、登录态或系统权限。 + +```text +Remote Agent + │ 标准 LineUp 消息 + ▼ +AppServer / IM + ▼ +┌─────────────────────────────────────────────────────────┐ +│ LineUp Runtime │ +│ │ +│ 连接 · 会话 · 消息筛选 · App 管理 · Tool 管理 │ +│ 权限 · Artifact · 存储 · Outbox · 恢复 · 审计 │ +└─────────────┬───────────────────────────┬───────────────┘ + │ Runtime SDK │ Host Provider + ▼ ▼ + Core / Installed App Tauri / OS + chat · app-registry 文件 · 麦克风 + voice · whiteboard 通知 · 窗口 + game · … 安全存储 +``` + +## 1. 本方案的结论与优先级 + +本文件收敛正式方案目录下的三份已有文档,并在冲突处做出当前开发阶段的明确选择。 + +| 主题 | 最终决定 | +|---|---| +| App 的本体 | 整个产品是 `LineUpRuntime`;聊天不是 Runtime 本身。默认的 `Interaction App` 负责组织人与 Agent 的主交互,当前实现形态是 `chat`/图文 IM。 | +| 默认入口 | `Interaction App` 是当前默认和 Recovery App;当前默认模式是 `im`(代码兼容作用域仍为 `chat`),以后可切换到实时音频或视频模式。 | +| App 之间的关系 | App 只调用 Runtime SDK,不直接访问 AppServer、Agent、另一个 App 或 Tauri 特权 API。 | +| Agent 交互 | Agent 只与 Runtime 通信;Runtime 按会话和应用作用域筛选并投递给 App。 | +| 路由最小键 | 所有可路由消息必须有 `app_scope` 与 `conversation_id`;可选 `instance_id`、`operation_id`、`call_id`。 | +| App 生态阶段 | 当前只使用本地短作用域,如 `chat`、`whiteboard`、`draw-and-guess`;暂不引入供应商身份、反向域名 App ID 或全局命名空间。 | +| 丰富交互 | 标准内容先用可信内建组件;复杂互动用受限 Surface;设备/系统动作只能经 Capability Gateway。 | +| Agent 工具 | App 在 Manifest 声明方法,Runtime 汇总为动态 Inventory;Agent 只能调用当前 Inventory 中的方法。 | +| Runtime SDK | SDK 提供状态订阅、Agent 消息订阅、Action、Tool、应用导航、Artifact、存储、Capability 和生命周期接口。 | +| Host | Tauri Desktop Host 与同代码的 Web Reference Host 是当前唯一实现/验收基线:前者是正式桌面外壳,后者是浏览器开发和验证入口;它们不是两个客户端。不规划独立 Android/Kotlin 客户端或 Wails Host。 | + +本文件优先于来源文档中关于**后续 Runtime 重构**的结构描述。来源文档中的 M0~M4 完成记录、当前已实现字段和历史验收事实仍然有效;它们不自动成为新 Runtime 的长期模块边界。 + +## 2. 系统边界 + +### 2.1 Runtime、App 与 Host:先分清三者 + +这三个词经常同时出现,但职责不同:Runtime 是后台协调者,App 是用户看到的功能,Host +是让 Runtime 运行在桌面窗口或浏览器中的外壳。Host 不能绕过 Runtime 直接把系统能力 +交给 App 或 Agent。 + +```text +Runtime + 管理连接、状态、应用、工具、权限和副作用。 + +App + 面向用户或 Agent 的功能单元;只能通过 SDK 与 Runtime 协作。 + +Host + 提供操作系统或 WebView 能力;由 Runtime 使用,不直接暴露给 App/Agent。 +``` + +| 主体 | 必须负责 | 明确不负责 | +|---|---|---| +| Runtime | 连接 AppServer/Agent、管理会话与路由、安排 App 生命周期、Tool、Capability、持久化和审计 | 具体页面 DOM、任意 App 的业务 UI。 | +| Chat App | 图文会话、时间线、输入、任务/交互卡片和 Artifact 基础展示 | `fetch` AppServer、同步 cursor、Agent 原始包解析、文件系统。 | +| App Registry App | 让用户查看已安装 App,并请求安装/启用/禁用/移除或选择默认入口 | 直接写 Registry、删除 Bundle、绕过验签。 | +| Installed App | 自己的交互体验、已声明 Tool、已声明事件和私有状态 | Tauri `invoke`、Host DOM、token、任意网络和其他 App 数据。 | +| Tauri Host Provider | 在 Runtime 授权后实现文件、音频、通知、窗口和安全存储等系统操作 | 协议解释、应用策略和 Agent 路由。 | + +### 2.2 关键禁止项 + +```text +App → AppServer / Agent 直接网络连接 禁止 +App → 直接构造并发送未校验 Agent Envelope 禁止 +Surface → Tauri invoke / 父页面 DOM / 登录态 禁止 +Agent → 任意 App JavaScript 函数或 Host 特权 API 禁止 +Agent → 静默安装、启用、禁用或移除 App 禁止 +Surface Event → 直接执行系统能力 禁止 +``` + +## 3. Runtime 的内部模型 + +### 3.1 三类输入输出 + +Runtime 采用 Event / Command / Effect 分层。 + +```text +Event:已经发生的事实 + Agent 文本、任务进度、用户点击、画板变更、录音完成、连接断开。 + +Command:希望 Runtime 处理的动作 + 发送消息、调用 Tool、启动 App、启用 App、请求保存文件。 + +Effect:Runtime 决定执行的副作用 + 网络发送、文件选择、录音、通知、创建 Surface、写存储。 +``` + +处理顺序固定为: + +```text +接收 Event / Command + → 验证与授权 + → 更新 Runtime State + → 持久化事实 / Outbox + → 产生 Effect + → Effect 结果重新进入 Runtime,成为 Event + → 生成面向 App 的状态投影或消息投递 +``` + +第一版采用“事件驱动状态机 + 必要快照”,不实施完整 Event Sourcing。关键入站事件、用户决定、Tool 终态、outbox 和审计需持久化;纯渲染细节、焦点和滚动位置不必写入 Runtime 事实日志。 + +### 3.2 顶层状态 + +```text +identity + 用户、设备、认证会话。 + +connection + AppServer 连接、sync cursor、重试、实时状态、outbox。 + +conversations + conversation、关联 Agent、消息引用、任务、交互、Artifact 元数据。 + +apps + App Registry、默认 App、运行实例、每个 App 的可靠 Inbox。 + +tools + Tool 声明、Inventory revision、调用记录、operation 与进度。 + +capabilities + 权限请求、用户决定、系统权限、执行状态与最小审计。 +``` + +### 3.3 Runtime 生命周期 + +```text +created + → restoring + → authenticating + → synchronizing + → online + ↘ reconnecting / offline_degraded + → stopping + → stopped +``` + +启动时 Runtime 必须恢复 App Registry、默认入口、cursor、outbox、App Inbox、未完成 Tool 和可恢复实例。追平服务器历史后才开始正常实时投递;离线时可接受的用户/App Action 进入 outbox,重连后以幂等键和顺序发送。 + +## 4. 应用模型 + +### 4.1 本地应用作用域 + +当前阶段使用 Runtime 本地注册的 `app_scope`,而不是全球 App 身份: + +```text +chat +app-registry +settings +voice +whiteboard +draw-and-guess +runtime +``` + +`app_scope` 的职责仅是本机启动、消息路由、Tool 路由、存储隔离和实例归属。它不是供应商身份,不要求跨市场唯一,也不承担开放生态的所有权模型。 + +未来如需市场、多供应商和跨设备分发,可以在 Manifest 中增加稳定身份映射;但不能改变本方案中的 `app_scope + conversation_id` 路由与隔离语义。 + +### 4.2 应用类型 + +| 类型 | 典型项 | 来源与执行方式 | 管理规则 | +|---|---|---|---| +| Core App | `chat`、`app-registry`、`settings` | 跟随 Runtime 发行的可信代码 | 不可由市场 Bundle 覆盖;`chat` 不可移除。 | +| Installed App | `voice`、`whiteboard`、`draw-and-guess` | 经 Runtime 验证的 Bundle,在受限 Surface 中运行 | 可安装、启用、禁用、更新、回滚、移除。 | +| Capability | 录音、选文件、保存、通知 | Tauri/OS 经 Runtime Host Provider 提供 | 不是 App,也不是自动授予的权限。 | + +### 4.3 App Registry 与默认入口 + +Runtime App Manager 是安装和状态的唯一事实源: + +```ts +type AppRecord = { + app_scope: AppScope; + kind: "core" | "installed"; + installed_version: string; + previous_version?: string; + enabled: boolean; + install_state: "installed" | "updating" | "failed"; + active_instance_count: number; + installed_at: string; + enabled_at?: string; +}; + +interface RuntimeAppManager { + listApps(filter?: AppListFilter): readonly AppRecord[]; + getApp(appScope: AppScope): AppRecord | undefined; + install(request: InstallAppRequest): Promise; + enable(appScope: AppScope): Promise; + disable(appScope: AppScope, options?: DisableAppOptions): Promise; + update(appScope: AppScope, targetVersion?: string): Promise; + rollback(appScope: AppScope): Promise; + remove(appScope: AppScope, options?: RemoveAppOptions): Promise; + launch(request: LaunchAppRequest): Promise; + closeInstance(instanceID: AppInstanceID): Promise; +} +``` + +App Registry App 只调用上述接口,不直接管理 Bundle 文件。安装、验证、启用、升级和移除是异步操作,必须有可观察的 `AppOperation`。 + +Runtime Shell 始终独立于上层 App,负责应用切换、全局连接状态、通知和安全恢复。其启动目标优先级: + +```text +显式目标(深链接 / 通知) + → 可安全恢复的前台实例 + → 用户设定的 Default App + → chat Recovery App +``` + +`chat` 是当前图文 IM 主入口,也是不可移除的 Recovery App。未来用户可将 `voice` 设为默认入口;这只改变主要交互方式,不改变会话、Agent、outbox 或 Artifact 的归属。 + +### 4.4 App 实例生命周期 + +```text +not_running → launching → active → backgrounded → suspended + ↘ restoring → active +active / suspended → closing → closed + ↘ failed +``` + +- Chat 与 App Registry 默认是单一全局实例; +- 工具型 App 默认按 `conversation_id` 创建实例,可用 `instance_id` 区分同会话的多个实例; +- 禁用阻止新调用并收口现有实例;移除在实例关闭且用户确认后清理 Bundle/私有数据; +- Surface 被回收时 App 通过 Runtime snapshot 恢复,不能重复发送先前的用户事件。 + +### 4.5 Runtime 编排、Interact 与扩展 App + +`Interaction App` 是默认的人与 Agent 交互应用,但它不是整个 App 生态的调度器。应用 +启动、Tool 路由、前后台焦点、实例生命周期和恢复均由 Runtime 管理;Interact 只负责 +当前主会话的交互体验,以及把扩展 App 的结果投影回会话。 + +```text +LineUp Runtime + ├── App Registry / App Instance Manager + ├── Tool Router / App Router + ├── Focus Manager / Lifecycle Manager + └── Conversation / Store / Outbox + │ + ├── Interaction App(Core App) + │ ├── IM mode:文字、图片、短消息 + │ ├── Audio mode:实时语音 + │ ├── Video mode:实时视频 + │ └── 标准交互原语:choice / confirm / input + │ + └── Installed App + ├── whiteboard + ├── draw-and-guess + └── task-dashboard +``` + +Runtime 的职责是判断一个 Agent 请求应由哪个应用实例、交互模式或标准组件承接;Interact +不直接执行任意 Tool,也不负责切换其他 App 的前台状态。它通过 SDK 接收 Runtime 已经 +校验过的交互事件,并提交声明性用户 Action。 + +应用焦点是 Runtime 状态的一部分: + +```text +interaction:audio-001 running / foreground + ↓ Agent 请求启动 draw-and-guess +interaction:audio-001 background 或 suspended +draw-and-guess:game-001 starting → running / foreground +``` + +原来的实例不会因为切换前台就被删除。Runtime 保存焦点栈和实例状态,以便游戏结束、用户 +退出或新应用失败时恢复原来的 Interaction App 和会话模式。 + +一次“启动你画我猜”的完整流程是: + +```text +Agent launch(draw-and-guess) + → Runtime 校验 Envelope、Inventory、Manifest、参数和 App 状态 + → 创建 draw-and-guess App Instance + → 保存当前 Interaction App/Audio Instance 的焦点位置 + → 将旧实例切换为 background / suspended + → 将新实例切换为 foreground + → App 通过 SDK 创建自己的 Surface 并接收用户操作 + → 结果经 Runtime 持久化、审计并回传 Agent + → 游戏结束或关闭后恢复焦点栈中的 Interaction App +``` + +标准选择框、确认框和输入框属于 Interaction App 的内建交互原语,不需要作为独立安装包; +画板、游戏和复杂任务面板属于可安装扩展 App,与 Interaction App 是 Runtime 上的平级应用。 + +因此,Runtime 负责“能否调用、调用到哪里、哪个实例在前台以及如何恢复”;Interact 负责 +“如何在主交互体验中呈现和协调结果”;扩展 App 负责“具体功能和自己的交互界面”。 + +## 5. 消息、筛选与实时订阅 + +### 5.1 统一路由 Envelope + +所有 Agent、Runtime、App、User 与 Host 之间的可路由消息都必须带作用域: + +```ts +type RuntimeEnvelope = { + v: 1; + id: string; + type: string; + timestamp: string; + + sender: { + kind: "agent" | "runtime" | "app" | "user" | "host"; + id: string; + }; + + target: { + kind: "runtime" | "app"; + app_scope: AppScope; + instance_id?: AppInstanceID; + }; + + scope: { + app_scope: AppScope; + conversation_id: ConversationID; + instance_id?: AppInstanceID; + operation_id?: OperationID; + }; + + correlation?: { + reply_to?: string; + call_id?: ToolCallID; + inventory_revision?: string; + sequence?: number; + }; + + payload: JsonValue; +}; +``` + +全局 Runtime 事件同样保留作用域: + +```text +target.app_scope = runtime +scope.app_scope = runtime +conversation_id = runtime:global +``` + +### 5.2 现有协议兼容 + +当前 Tauri 实现与 M0~M4 golden fixture 使用 `lineup.v1.*` 类型,以及 Surface payload 内的旧 `app.id` 字段。这些是**当前实现兼容事实**,不能在没有版本迁移和 golden fixture 的情况下直接删除。 + +Runtime 重构的规则是: + +```text +旧 LineUp v1 Envelope + → Runtime Compatibility Adapter + → 补齐/映射 app_scope、conversation_id、instance_id + → RuntimeEnvelope + → App SDK +``` + +新的 Runtime/App SDK 边界不得再依赖旧 `app.id` 的供应商命名语义。R0 负责冻结新旧字段的映射表、拒绝规则和双向 fixture;在映射完成前,旧协议继续只由 Runtime 适配层处理,App 永远不直接读取它。 + +### 5.3 Runtime 筛选链 + +```text +Transport 原始输入 + → 版本、type、app_scope/conversation_id、大小、schema 校验 + → Agent 身份与会话关联校验 + → id / sequence / cursor 去重与顺序处理 + → App 安装、启用、版本、Host 兼容性校验 + → Tool / Capability、Inventory、参数、策略、App 启动和前台条件校验 + → conversation / instance / operation 所属关系校验 + → Manifest 订阅声明与 SDK 订阅条件求交 + → Runtime Event / App Inbox / cursor 持久化 + → 向目标 App SDK 投递标准化消息 +``` + +Runtime 不广播原始 Agent 消息。相同 conversation 下,Chat 和 Voice 可以收到经 Runtime 投影的 Agent status;白板只收到本实例声明的 patch、Tool 调用和 lifecycle 事件,除非其 Manifest 明确申请并获准其他订阅。 + +### 5.4 App SDK 的实时 Agent 消息能力 + +SDK 同时提供实时订阅和可靠 Inbox 补读: + +```ts +interface AgentMessageAPI { + list(request?: { + conversation_id?: ConversationID; + after?: AgentMessageCursor; + limit?: number; + }): Promise; + + subscribe( + options: { + conversation_id?: ConversationID; + types?: readonly AgentMessageType[]; + include_pending?: boolean; + }, + handler: (message: AgentAppMessage) => Promise | void, + ): Unsubscribe; + + acknowledge(message_id: string): Promise; +} +``` + +投递语义: + +1. Runtime 先校验、标准化和持久化,后调用订阅者; +2. 每条消息有唯一 `message_id`,App 必须幂等处理; +3. 展示类消息可自动 ACK;Tool 调用、状态 patch 和需业务处理的消息要求 App 显式 ACK; +4. App 未运行、暂停或崩溃时,消息进入该 App 的 Inbox;恢复后 `list()` 与 `subscribe()` 补齐; +5. App 禁用、移除或不兼容时,Runtime 对关键 Agent 调用返回确定拒绝,不能静默丢弃。 + +实际投递集是: + +```text +Manifest agent_subscriptions + ∩ SDK subscribe filter + ∩ App 当前权限 + ∩ conversation / instance scope + ∩ Agent target app_scope + ∩ Runtime Policy +``` + +## 6. Runtime SDK v1 + +SDK 是上层 App 使用 Runtime 的唯一标准入口。Core App 拿到完整 App SDK;Installed App 只得到同一语义的受限 Surface Bridge SDK。 + +```ts +interface LineUpAppRuntimeSDK { + readonly app: AppContext; + readonly lifecycle: AppLifecycleAPI; + readonly state: AppStateAPI; + readonly agentMessages: AgentMessageAPI; + readonly actions: AppActionAPI; + readonly tools: AppToolAPI; + readonly apps: AppNavigationAPI; + readonly artifacts: ArtifactAPI; + readonly storage: ScopedStorageAPI; + readonly capabilities: CapabilityRequestAPI; + readonly diagnostics: DiagnosticsAPI; +} +``` + +### 6.1 Context、状态和生命周期 + +```ts +interface AppContext { + app_scope: AppScope; + app_version: string; + instance_id: AppInstanceID; + kind: "core" | "installed"; + entrypoint: string; + scope: { + conversation_id?: ConversationID; + operation_id?: OperationID; + parent_instance_id?: AppInstanceID; + }; + granted_permissions: readonly AppPermission[]; +} + +interface AppStateAPI { + snapshot(): ViewModel; + subscribe(listener: (view: ViewModel, change: AppStateChange) => void): Unsubscribe; +} +``` + +App 只读取按其 Scope 裁剪的 View Model,不读取全量 Runtime State。生命周期包含 `start`、`foreground`、`background`、`suspend`、`restore` 与 `closing`;Runtime 保留禁用、移除和强制收口的最终权力。 + +### 6.2 Action、Tool 与跨 App 导航 + +```ts +interface AppActionAPI { + dispatch(action: AppAction): Promise; +} + +interface AppToolAPI { + onInvoke(listener: (call: AppToolInvocation) => Promise): Unsubscribe; + progress(request: { call_id: ToolCallID; progress: ToolProgress }): Promise; + complete(request: { call_id: ToolCallID; result: JsonValue }): Promise; + fail(request: { call_id: ToolCallID; code: AppToolErrorCode; message?: string }): Promise; +} + +interface AppNavigationAPI { + listAvailable(): readonly AppSummary[]; + launch(request: LaunchAppRequest): Promise; + focus(instanceID: AppInstanceID): Promise; + close(instanceID: AppInstanceID): Promise; + openDefaultApp(): Promise; +} +``` + +App 只能提交声明性 Action,不能构造原始 Agent Envelope。跨 App 打开、聚焦和关闭也必须经 Runtime 校验目标 App 的启用状态、入口、展示模式和会话作用域。 + +### 6.3 Artifact、存储与 Capability + +```text +Artifact + Runtime 管理元数据、受限读取、创建、会话引用、下载和用户保存。 + +Storage + Runtime 为每个 app_scope 提供隔离 JSON 数据与 snapshot;管理配额、迁移和清理。 + +Capability + App 以 purpose + input 请求;Runtime 决定是否确认、调用 Host、审计并返回受控结果。 +``` + +Capability SDK 形状: + +```ts +interface CapabilityRequestAPI { + request(request: { + capability: CapabilityName; + purpose: string; + input: JsonValue; + scope?: AppScope; + }): Promise>; +} +``` + +Runtime 必须检查:Manifest 声明、App 启用状态、Host 支持、前台要求、用户确认、系统权限、策略、速率限制和审计。结果只能是 `completed`、`cancelled_by_user`、`permission_denied`、`unsupported_on_host`、`policy_denied`、`expired` 或受控 `failed`,不暴露路径、token 或底层原生异常。 + +## 7. Tool、Inventory 与 Agent 调用 + +### 7.1 App Tool 声明 + +每个 App 可以声明 Agent 可调用 Tool。当前的完整定位是: + +```text +app_scope / method / contract_version + +whiteboard / board.create / 1 +voice / voice.request_recording / 1 +draw-and-guess / game.start_round / 1 +``` + +Tool Manifest 至少包括:标题、面向 Agent 的说明、输入/输出 JSON Schema、调用模型、超时、幂等性、前台要求、风险等级、App 启动策略和可能使用的 Capability。 + +调用模型固定为: + +| 模型 | 用途 | 示例 | +|---|---|---| +| `query` | 只读、快速 | 查询画板摘要。 | +| `command` | 确定性状态改变 | 创建白板、开始一局游戏。 | +| `interactive` | 必须等待用户参与 | 录音、填写复杂表单。 | +| `operation` | 长时间执行并有进度 | 导出画板、处理大文件。 | + +### 7.2 动态 Runtime Inventory + +Runtime 向每个活跃 Agent 会话发布 revisioned Inventory。它包含当前可用的标准组件、已启用 App、Surface、Tool 和 Capability;它不是安装命令,也不携带 Bundle 源码、token、文件路径或用户私有内容。 + +```text +Agent 可见 Tool + = 已验证 Manifest Tool + ∩ App enabled + ∩ Host supported + ∩ 用户 / 组织策略允许 + ∩ Agent + conversation scope 允许 + ∩ 所需前置条件满足 +``` + +App 启用、禁用、更新、撤销、Host 能力变化或策略收紧后,Runtime 增加 revision 并重新发布。Agent 的 Tool 调用必须携带 `inventory_revision`;旧 revision 的调用必须安全拒绝并提示 Agent 刷新清单。 + +### 7.3 Tool 调用闭环 + +```text +Agent tool.invoke + → Runtime 校验 Envelope / Inventory / Tool / 参数 / Scope + → Tool Router 判断直接执行、启动 App、切换前台或等待用户交互 + → App Instance / Focus Manager 创建或切换实例 + → Interaction App、交互模式或扩展 App 承接请求 + → App SDK 发送 progress / result / error + → Runtime 校验输出、持久化、更新焦点并回传 Agent +``` + +至少支持以下确定错误码: + +```text +cancelled_by_user permission_denied app_disabled +app_not_installed app_version_mismatch tool_not_visible +invalid_arguments foreground_required operation_expired +handler_failed +``` + +Tool 是 App 的业务方法;Capability 是 Runtime/Host 的系统能力。Tool 可请求 Capability,但不会因声明 Tool 自动获得麦克风、文件或剪贴板权限。 + +## 8. Surface 与安全边界 + +### 8.1 标准组件优先 + +文字、Markdown、图片、链接、状态、任务进度、choice、confirm、input、Artifact 基础预览优先采用 Runtime / Core App 的可信内建渲染器。它们必须可访问、可测试、可离线恢复,并保持 Markdown sanitizer、外链保护和严格 schema。 + +Surface 仅用于画板、地图、图表、复杂表单、游戏、专业编辑器等内建组件不足以表达的复杂交互。 + +### 8.2 Installed App Surface + +下载型 App 运行在隔离容器中: + +```text +iframe sandbox="allow-scripts" + - 不带 allow-same-origin + - 不带 allow-popups / allow-top-navigation / allow-forms + - 默认 CSP 禁止网络和外部脚本 + - 只经严格 postMessage / Surface Bridge SDK 通信 +``` + +Runtime/Host 必须验证 `event.source`、当前 `instance_id`、消息类型、事件名、JSON schema、消息大小和声明的投递策略。Surface 只能接收 state patch、触发已声明事件、处理已声明 Tool 调用、使用隔离存储和请求受控 Capability。 + +Surface 不能: + +```text +读取父页面 DOM、localStorage 或 token +调用 Tauri invoke +访问其他 App 的数据和实例 +直接访问 Agent / AppServer +任意联网、导航、弹窗或加载远端脚本 +直接执行 app.call / 系统能力 +``` + +用户在 Surface 中的操作只是 App Event;需要系统副作用时,Runtime 仍按 Capability 规则确认、执行和审计。 + +### 8.3 Bundle 与发布 + +当前已验证的生产安全原则保持不变:Bundle 必须是不可变 artifact,执行前检查来源、大小、SHA-256、签名、Host 兼容性和回滚条件;验证失败不得进入 active cache。开发期 inline bundle 只能是受限开发 fixture,不是长期市场供应方式。 + +本阶段仅定义本地 `app_scope`,不定义开放市场发布者身份。Bundle 信任、App 管理和 Tool 可见性仍必须由 Runtime 控制;将来引入供应商身份时须以新 Manifest 版本扩展,不能放宽本节隔离规则。 + +## 9. App Manifest 最小契约 + +```json +{ + "format": "lineup.app.v1", + "app_scope": "whiteboard", + "version": "1.0.0", + "runtime_sdk": { + "api_version": "1", + "required_features": [ + "app.lifecycle.v1", + "app.tools.v1", + "surface.state.v1" + ], + "optional_features": ["artifact.create.v1"] + }, + "entrypoints": [ + {"id": "canvas", "kind": "contextual", "default_eligible": false} + ], + "agent_subscriptions": [ + {"type": "lineup.app.state.patch", "scope": "instance"}, + {"type": "lineup.tool.invoke", "scope": "conversation"} + ], + "tools": [ + { + "method": "board.create", + "contract_version": "1", + "invocation": {"kind": "command", "activation": "launch_if_needed"}, + "input_schema": {"type": "object", "additionalProperties": false}, + "output_schema": {"type": "object", "additionalProperties": false} + } + ] +} +``` + +Runtime 在安装、启用和启动时验证 SDK API 版本与 feature 集;App 不兼容、未启用或当前 Host 不支持时,不得进入 Inventory、创建实例或接收 Tool 调用。 + +## 10. Tauri 参考实现的最终模块边界 + +```text +lineup-app/ +├── runtime-core/ +│ ├── communication/ AppServer transport、sync、outbox +│ ├── coordination/ event、state、router、policy、audit +│ ├── apps/ app registry、instance manager、default app +│ ├── tools/ tool registry、inventory、call lifecycle +│ ├── capabilities/ capability gateway +│ └── persistence/ runtime store、app inbox、artifact metadata +├── runtime-sdk/ +│ ├── app.ts Core App SDK +│ ├── manifest.ts App/Tool/Subscription 类型 +│ ├── protocol.ts RuntimeEnvelope / schema +│ ├── errors.ts 稳定错误码 +│ └── testkit/ +├── surface-sdk/ +│ ├── bridge.ts sandbox message bridge +│ └── surface.ts Installed App 最小 SDK +└── tauri/ + ├── src/ + │ ├── bootstrap/ 应用启动装配层 + │ ├── runtime-host/ Web/Tauri Host Provider adapter + │ ├── shell/ switcher、default、recovery + │ └── core-apps/ chat、app-registry、settings + └── src-tauri/ Rust 文件、音频、通知、窗口 Provider +``` + +`lineup-app/tauri/src/main.ts` 是当前 Tauri/Web Host 的启动装配入口:它创建 Host 侧适配、 +`LineUpRuntime` 与默认 Runtime App Host,并把它们接起来。它不创建或持有 Transport、 +Store、sync loop、outbox,也不解析原始 Agent payload。现阶段仍有可信 Renderer、Surface +与 Capability 的 Host 集成代码;后续可以继续迁移这些 UI 适配,但不得把 Runtime 所有权 +重新放回 `main.ts`。 + +可直接迁移的现有基础: + +| 当前模块 | 最终归属 | +|---|---| +| `transport-adapter.ts` | `runtime-core/communication/` | +| `conversation-store.ts` | `runtime-core/persistence/` | +| `interaction-kernel.ts` | `runtime-core/coordination/` 的协议入口/兼容适配基础 | +| Tool/Task/Execution 状态机 | Chat App 的投影 + Runtime call state | +| `surface-registry.ts` | `runtime-core/apps/` 的 App Registry 基础 | +| `surface-instance-manager.ts` | `runtime-core/apps/` 的 Instance Manager 基础 | +| Bundle manifest/cache/policy | `runtime-core/apps/` 与 Execution Plane | +| `client-inventory.ts` | `runtime-core/tools/` 的动态 Inventory Publisher | +| `capability-*` | `runtime-core/capabilities/` | +| `trusted-dom-renderers.ts` | `tauri/src/core-apps/chat/` | + +## 11. 实施顺序 + +### F0:冻结契约与兼容映射 + +- 定义 `RuntimeEnvelope`、`app_scope`、`conversation_id`、`instance_id`、`operation_id`、`call_id` 的类型和校验; +- 定义旧 `lineup.v1.*` 到 RuntimeEnvelope 的兼容映射; +- 定义 Runtime SDK v1、Surface Bridge SDK v1、App Manifest、Tool Descriptor 和错误码; +- 为全部契约建立 golden fixture;不改变当前可验证的 M0~M4 行为。 + +### F1:Runtime Core 与 Interaction Core App(当前 `chat` 实现) + +- 从 `main.ts` 提取单一 `LineUpRuntime`; +- Runtime 独占 Transport、Store、outbox、原始消息校验和筛选; +- 将当前图文 IM 迁为 Interaction Core App 的 `chat` 实现; +- 当前 `chat` 用 `state.subscribe()` 和 `agentMessages.subscribe()` 获取已验证投影,不再依赖 Transport; +- 保持登录、同步、本地回显、Markdown、Tool Call、Task、Artifact 的回归行为。 + +#### MVP-R1 实施状态(2026-08-04) + +F0 与 F1 中支撑图文聊天迁移的最小闭环已落地并经自动化回归验证。此处的“完成”仅指下列 MVP 边界;Manifest、Installed App、完整 Tool Inventory 和应用市场仍属于后续阶段。 + +| MVP 项 | 当前实现 | 验证位置 | +|---|---|---| +| Runtime 单一所有权 | `LineUpRuntime` 唯一创建并持有 `TransportAdapter`、`ConversationStore`、`InteractionKernel`、同步循环与 outbox。 | `tauri/src/runtime/coordination/lineup-runtime.ts`、`lineup-runtime.test.ts` | +| Core App 入口 | `CoreAppRegistry` 记录当前可作为默认入口的 Core App;`CoreAppHostRegistry` 再根据 `app_scope` 找到对应的可信装配器。当前默认实现仍是 `chat`,但 `main.ts` 不再直接依赖 Chat 内部 Renderer 和 Shell。 | `runtime/app-management/app-registry.ts`、`runtime-app-host.ts`、`core-apps/chat/chat-app-host.ts`、`runtime-app-host.test.ts` | +| Chat SDK 边界 | Chat 仅以 `ChatRuntimeSDK` 订阅状态/Agent 消息、读取 Inbox、ACK,并以 Runtime Action 发送文本或交互动作。 | `runtime/app-management/app-sdk.ts`、`main.ts` | +| 作用域与旧协议兼容 | 入站消息先经 `resolveIncomingScope`;旧 `lineup.v1` 自动映射为当前会话的 `chat` 作用域,显式非法或不匹配的 scope 在投递前拒绝。 | `runtime/coordination/runtime-envelope.ts`、`lineup-runtime.test.ts` | +| 恢复与幂等 | `ConversationStore` 持久化 App Inbox;未 ACK 消息在 Runtime 重建后恢复,同一 `message_id` 不重复投递。 | `runtime/persistence/conversation-store.ts`、`conversation-store.test.ts`、`lineup-runtime.test.ts` | + +本阶段不修改 AppServer 或 Hermes 的既有 `lineup.v1` 协议。兼容层只存在于 Runtime 内部,因此上层 Chat App 不读取旧协议字段,也不需要同步升级远端。 + +### F2:App Registry 与默认 App + +- 将开发期 Surface Registry 迁为 Runtime App Registry; +- 实现 App Instance Manager、App Focus Manager 和生命周期状态(foreground/background/suspended); +- 实现 Runtime Tool Router / App Orchestrator:校验 Tool 后决定直接执行、启动 App、切换前台或等待用户交互; +- 实现 App 启用、禁用、移除、版本记录、实例收口和默认入口选择; +- 实现 `app-registry` Core App; +- 将当前 `chat` 作为 Interaction App 的 IM 实现,为后续 Audio/Video 模式预留 entrypoint 和恢复策略。 + +### F3:Tool Registry、Inventory 与 SDK Inbox + +- 解析 Manifest Tool/Subscription 并计算可见性; +- 在 Runtime 连接与状态变化时同步 revisioned Inventory 给 Agent;Tool 可声明是否需要启动 App、是否要求前台以及结束后是否恢复原焦点; +- 实现 Agent Tool → Runtime → App SDK → result/progress 的可靠闭环; +- 将 MVP-R1 已实现的 Chat App Inbox、ACK、断线/崩溃恢复和拒绝码推广为所有受管理 App 的通用可靠投递机制。 + +### F4:第一个 Installed App + +- 选择画板或任务面板作为第一个完整 Installed App; +- 验收 install → enable → Inventory → Tool 调用 → App 启动/前台切换 → Surface 事件 → Agent result → 原前台恢复 → disable/remove; +- 语音/视频属于 Interaction App 的模式或受 Runtime 管理的扩展 App,必须复用 Runtime SDK、Tool、Artifact 和 Capability 通道,不建立独立 Agent 通信链路。 + +## 12. 完成准入条件 + +```text +消息与隔离 + [ ] 缺少/非法 app_scope 或 conversation_id 的可路由消息被拒绝。 + [ ] App 不能收到其他 App 或其他 conversation 的 Agent 原始消息。 + [ ] App 未运行时关键消息可从 Inbox 有界恢复,重复投递不重复执行。 + +应用管理 + [ ] 启用/禁用/移除改变 Tool 可见性,并更新 Agent Inventory revision。 + [ ] 默认 App 失效时必定回退至 Interaction App 的 IM/`chat` Recovery 入口。 + [ ] 禁用/移除能收口活动实例、焦点栈、调用和私有数据清理流程。 + [ ] Agent 启动扩展 App 时,Runtime 能将当前前台实例切换到后台,并在扩展结束后恢复原焦点。 + +工具与能力 + [ ] Agent 只能调用当前 Inventory 中、参数 schema 合法的 Tool。 + [ ] Tool 的 result/progress/error 经 Runtime 校验、持久化和审计。 + [ ] App / Surface 无法绕过 Capability Gateway 获得系统权限。 + +安全 + [ ] Installed App 无法访问 Tauri invoke、Host DOM、token、任意网络或其他 App 数据。 + [ ] Bundle 只有在完整性和签名验证后才可运行;失败可回滚且不污染 active cache。 +``` + +## 13. 旧文档的后续定位 + +| 文档 | 保留价值 | 在本方案后的定位 | +|---|---|---| +| [App 层架构方案](lineup-app-layer-architecture.md) | M0~M4 已实现边界、测试和验收事实;Markdown、Surface、Capability 原则 | 迁移基础与历史实施记录。 | +| [Runtime 与 App SDK 架构方案](lineup-runtime-sdk-architecture.md) | Runtime、App Manager、Tool Registry、SDK、消息筛选的完整初稿 | 被本文件收敛后的详细来源;以本文件的 `app_scope` 和实施顺序为准。 | +| [UI Surface 与 App Capability 协议](lineup-ui-surface-protocol.md) | Surface sandbox、bridge、Capability 风险分级、inventory 和 Bundle 安全规则 | 协议细节来源;R0 需完成其旧字段到 RuntimeEnvelope 的版本化映射。 | + +以后新增 App 设计、SDK 方法、Agent Tool、Surface 或 Capability 时,先修改本文件的边界/契约,再实施代码和细节协议,避免重新把功能堆回聊天页面或创建绕开 Runtime 的平行通道。 diff --git a/设计/02.正式方案/lineup-app-layer-architecture.md b/设计/02.正式方案/lineup-app-layer-architecture.md new file mode 100644 index 0000000..de9f7b3 --- /dev/null +++ b/设计/02.正式方案/lineup-app-layer-architecture.md @@ -0,0 +1,132 @@ +# LineUp App 层架构与迁移记录 + +**版本:** 2.0(Runtime 基线) +**状态:** 当前实现边界与历史迁移记录 +**日期:** 2026-08-04 +**最终决策入口:** [LineUp App 最终设计方案](app_final_design.md) + +## 1. 当前结论 + +LineUp 是运行在用户设备上的协作 Runtime,不是某个平台上的独立聊天客户端。可以把 +Runtime 理解为本地协调中心:它负责连接、消息、存储和恢复;`chat` 是它首先加载的可信 +内置功能。未来的语音、画板、游戏和应用中心也必须使用同一套 Runtime / SDK 边界,不能 +各自再建立一条到 Agent 的通信链路。 + +当前唯一实现与验收基线: + +```text +Tauri 2 Desktop Host + Web Reference Host +``` + +这两个 Host 是同一套 TypeScript Runtime 的两种外壳:Tauri Desktop Host 用于正式桌面 +交付及受控系统能力;Web Reference Host 用于浏览器开发、Tailscale 联调和自动化测试。 +它们不是两套产品,Web 版也不能替代桌面版的系统能力。独立 Android/Kotlin 客户端与 +Wails Host 均不在当前或后续规划范围内;早期实验细节仅保留在 Git 历史,不构成架构或 +验收依据。 + +## 2. App 层边界 + +```text +Remote Agent / AppServer + │ lineup.v1 wire protocol + ▼ +┌────────────────────────────────────────────────────────┐ +│ LineUpRuntime │ +│ Transport · sync loop · Store · Outbox · App Inbox │ +│ scope 路由 · Compatibility Adapter · Tool · Capability │ +└─────────────────────┬──────────────────────────────────┘ + │ Runtime SDK + ▼ +┌────────────────────────────────────────────────────────┐ +│ Core / Installed App │ +│ chat · app-registry · voice · whiteboard │ +└────────────────────────────────────────────────────────┘ +``` + +| 层 | 必须负责 | 不得负责 | +|---|---|---| +| `LineUpRuntime` | 处理 AppServer/Agent 通信、会话、原始协议兼容、scope 筛选、Store、sync、outbox、App Inbox、Tool 路由、App 实例和前台焦点、权限与恢复。 | 具体业务页面 DOM。 | +| Interaction Core App | 用户实际使用的主交互界面:当前是 Chat/IM,未来包含 Audio/Video 模式、标准交互原语和扩展结果投影。 | 直连 AppServer、维护 cursor、解析 Agent 原始包、调度其他 App 或直接写 Runtime Store。 | +| Runtime SDK | App 与 Runtime 之间唯一的受限接口:提供 snapshot、订阅、Agent 消息、Inbox ACK、Runtime Action、App 导航和生命周期请求。 | 把 Transport、token、Host 特权 API 暴露给 App。 | +| Tauri/Web Host | 把 Runtime 放进桌面窗口或浏览器,并提供对应的 DOM/系统能力。 | 解释协议、决定 App 调度、绕过 Runtime 路由和策略。 | +| Surface | 在隔离执行域呈现已验证 Bundle,并经受限 bridge 上报事件。 | 访问 Host DOM、登录态、Tauri API、任意网络。 | + +## 3. MVP-R1:Runtime 托管 Chat + +当前 MVP 已完成并以 Tauri/Web 自动化回归验证以下八项条件: + +| 条件 | 当前事实 | +|---|---| +| MVP-01 | `LineUpRuntime` 唯一创建并持有 Transport、`ConversationStore`、sync loop 与 outbox。 | +| MVP-02 | Runtime 从本地 `CoreAppRegistry` 解析默认 `chat`,`RuntimeAppHost` 负责挂载其 Shell;`main.ts` 不创建聊天页面。 | +| MVP-03 | Chat 只经 `ChatRuntimeSDK` 订阅 Agent 消息、状态和 Chat-safe Runtime 事件,并以 Action 发送文本、交互、结果与取消。 | +| MVP-04 | Runtime 向 Chat 投递前验证 `app_scope = chat` 与当前 `conversation_id`;非法/不匹配消息被拒绝。 | +| MVP-05 | Compatibility Adapter 在 Runtime 内将旧 `lineup.v1` 映射为内部 `RuntimeEnvelope`;远端无须同步重写。 | +| MVP-06 | 登录、同步、发送、本地回显、Markdown、Agent 状态、Tool/Task 与刷新恢复保持回归。 | +| MVP-07 | Store 持久化每个 App 的 Inbox;运行时重建后未 ACK 消息可恢复,`message_id` 去重。 | +| MVP-08 | `npm test -- --run` 通过 21 个文件 / 94 个测试;`npm run build` 通过。 | + +源代码目录和依赖方向见 [Tauri/Web 源码导航](../../tauri/src/README.md)。 + +## 4. 当前源码归属 + +```text +lineup-app/tauri/src/ +├── main.ts # 启动装配入口:连接 Tauri/Web Host、Runtime 与默认 App +├── core-apps/chat/ # 当前 Interaction App 的 IM 实现、Renderer、样式 +└── runtime/ + ├── app-management/ # Registry、App Instance、焦点、生命周期、Host + ├── communication/ # Transport Adapter + ├── coordination/ # Runtime、Kernel、Envelope、Tool/Task/交互编排 + ├── persistence/ # Conversation Store、Outbox、App Inbox + ├── protocol/ # lineup.v1 解码与 golden fixture + ├── surfaces/ # Surface 生命周期、Bundle、隔离 Host + ├── capabilities/ # Registry、执行、审计 + ├── artifacts/ # Artifact 元数据与缓存 + └── inventory/ # Agent 可见 Inventory +``` + +依赖必须保持单向: + +```text +core-apps/interaction(当前 chat) → runtime/app-management SDK → runtime/coordination + └→ communication / persistence / protocol +Host adapters → runtime/coordination +Surface → restricted bridge → Runtime Action / Capability Gateway +``` + +## 5. 历史迁移的保留价值 + +早期 M0~M4 工作建立了当前 Runtime 的可复用安全基础。它们是迁移记录,不是新的功能 +排期或平行客户端路线: + +| 历史阶段 | 保留成果 | 当前归属 | +|---|---|---| +| M0 | HTTP Transport、Conversation Store、协议解码、Markdown、基础回归 | `communication`、`persistence`、`protocol`、Chat Renderer | +| M1 | Tool Call、Task、可靠交互结果、受限执行摘要 | `coordination`、Chat SDK 投影 | +| M2 | 本地 Surface Registry、实例生命周期、隔离 iframe 与恢复 | `surfaces` | +| M3 | Capability Registry、用户确认、审计与受限 Host 执行 | `capabilities` | +| M4 | 签名 Manifest、Bundle 校验/缓存/回滚、golden fixture | `surfaces`、`protocol/golden` | + +早期文档中的阶段性“尚未实现”或旧目录路径不得用来判断当前能力;需要审计细节时通过 +Git 历史检索。 + +## 6. 后续阶段 + +```text +F2 持久化 App Registry、App Instance/Focus Manager、默认 App 切换 +F3 Runtime Tool Router、动态 Inventory、可靠 App SDK Tool 闭环 +F4 Interaction App 的 IM/Audio/Video 模式边界与第一个 Installed App +``` + +未来 App 必须复用 `app_scope + conversation_id`、Runtime SDK、Tool/Capability、Artifact、 +Store、outbox 与恢复机制;禁止新建独立 Agent 通信通道。 + +## 7. 文档关系 + +| 文档 | 用途 | +|---|---| +| [app_final_design.md](app_final_design.md) | 当前产品、Runtime、App、SDK 与实施优先级的唯一汇总入口。 | +| [lineup-runtime-sdk-architecture.md](lineup-runtime-sdk-architecture.md) | Runtime / SDK 的详细接口与未来 App Manager 契约。 | +| [lineup-ui-surface-protocol.md](lineup-ui-surface-protocol.md) | Surface sandbox、bridge、Capability 和 Bundle 安全协议。 | +| 本文件 | 当前实现边界、源码归属与 M0~M4 的迁移价值。 | diff --git a/设计/02.正式方案/lineup-runtime-sdk-architecture.md b/设计/02.正式方案/lineup-runtime-sdk-architecture.md new file mode 100644 index 0000000..fa433b8 --- /dev/null +++ b/设计/02.正式方案/lineup-runtime-sdk-architecture.md @@ -0,0 +1,726 @@ +# LineUp Runtime 与 App SDK 架构方案 + +**版本:** 0.1(架构基线) +**状态:** 已确认的 Runtime / SDK 方向;尚未完全落地到当前 Tauri 实现 +**日期:** 2026-08-04 +**关联方案:** [LineUp App 层架构设计方案](lineup-app-layer-architecture.md)、[LineUp UI Surface 与 App Capability 协议](lineup-ui-surface-protocol.md) + +> **汇总入口:** 本文是 Runtime / SDK 初稿的详细来源。后续设计以 [LineUp App 最终设计方案](app_final_design.md) 为准;后者收敛了本地 `app_scope`、兼容迁移和实施顺序。 + +--- + +## 0. 结论与范围 + +LineUp 不是“聊天应用里附带一个交互 Runtime”。**LineUp App 本身就是运行在用户设备上的 +协作 Runtime**,可以把它理解为本地协调中心:它独占与 AppServer / Remote Agent 的连接, +维护会话和本地应用生态,并为上层应用提供统一的消息、工具、存储、权限和生命周期接口。 +聊天只是第一个使用这些接口的内置 App。 + +```text +Remote Agent + │ LineUp Runtime Envelope + ▼ +AppServer / IM Transport + ▼ +┌───────────────────────────────────────────────────────────────┐ +│ LineUp Runtime │ +│ │ +│ Connection · Session · Event Routing · App Manager │ +│ Tool Registry · Capability Gateway · Storage · Audit │ +└───────────────┬──────────────────────────────┬────────────────┘ + │ │ + ▼ ▼ + Core App Installed App + chat whiteboard + app-registry voice + settings draw-and-guess +``` + +本方案定义: + +- Runtime 与 Remote Agent、AppServer、上层 App、Tauri Host 的边界; +- 动态应用列表、应用身份、应用安装/启用/禁用/移除与实例生命周期; +- 应用向 Agent 公布工具方法的标准模型; +- Runtime 对消息的统一 Envelope、筛选、可靠投递与 App SDK 订阅接口; +- Core App、Installed App 和 Tauri Host 的信任分层; +- SDK v1 的最小接口和工程模块边界。 + +本方案不在本次冻结:市场目录的商业模型、支付、公开开发者身份认证细节、多人/多 Agent 共享工作区、完整事件溯源和后台持续执行策略。它们必须建立在本方案的身份、路由和权限边界上。 + +## 1. 基本术语 + +| 术语 | 含义 | +|---|---| +| **Runtime** | 用户设备上的长期协作运行底座;唯一负责 AppServer/Agent 通信、应用管理和 Host 能力调度。 | +| **App** | 用户实际使用的功能单元。Chat、应用注册表、语音、白板和游戏都是 App。 | +| **Core App** | 跟随 LineUp Runtime 一起发布、默认受信任的内置 App,例如 `chat`。 | +| **Installed App** | 从受信来源安装、验证后在受限执行环境中运行的 App。 | +| **App Registry** | Runtime 在本机保存的应用清单,记录安装包、版本、启用状态、实例和回滚信息;它是这些状态的唯一依据。 | +| **Tool** | App 先在 Manifest 中说明、Runtime 再公布给 Agent 的可调用方法。Agent 不能任意调用 App 内部函数。 | +| **Capability** | Runtime / Host 保管的系统能力,例如录音、选择文件、保存 Artifact;App 必须请求,不能自动获得。 | +| **Surface** | 一个受限的交互小界面,例如一块画板、一个语音会话面板或一局游戏。 | +| **Conversation** | 用户与一个主 Agent 协作的一段会话范围;App 实例、工具调用和 Artifact 默认都归属这段会话。 | + +## 2. 不可变架构原则 + +1. **Runtime 是唯一 Agent 通信入口。** App 不直接访问 AppServer、IM SDK、WebSocket、HTTP cursor 或 Agent endpoint。 +2. **App 只与 Runtime 通信。** Chat、Voice、Market、白板均通过 SDK 读状态、订阅消息、提交动作和请求能力。 +3. **每一条可路由 Runtime 消息必须具有 `app_scope` 与 `conversation_id`。** Runtime 以它们作为本地路由、授权、筛选、持久化和投递的首要键。 +4. **原始 Agent payload 不交给 App。** Runtime 完成版本、身份、schema、大小、去重和作用域校验后,才产生可订阅的标准化消息。 +5. **应用可调用方法必须先声明、后公布、再调用。** Agent 不执行 App 内任意函数,只能调用当前 Inventory 中精确声明的方法。 +6. **系统能力由 Runtime 独占。** Agent 和 App 只能请求 Capability;文件、麦克风、通知、剪贴板、窗口、密钥等均不得直接访问。 +7. **应用状态、消息和副作用分离。** Event 是已发生事实,Command 是请求动作,Effect 是 Runtime 执行的受控副作用。 +8. **UI 是 Runtime 状态的投影。** App 重启、断网或 Surface 回收后,Runtime 能依据持久化状态恢复到可解释的协作状态。 + +## 3. 运行时分层 + +```text +┌──────────────────────────────────────────────────────────┐ +│ Runtime Shell │ +│ 应用切换 · 默认入口 · 连接状态 · 通知 · 安全恢复 │ +├──────────────────────────────────────────────────────────┤ +│ Core App / Installed App │ +│ Interaction App(IM / Audio / Video) · App Registry │ +│ Settings · Whiteboard · Game · …(Installed App) │ +├──────────────────────────────────────────────────────────┤ +│ LineUp App Runtime SDK / Surface Bridge SDK │ +├──────────────────────────────────────────────────────────┤ +│ LineUp Runtime Core │ +│ Communication · Coordination · App Management · Tooling │ +├──────────────────────────────────────────────────────────┤ +│ Runtime Host Provider │ +│ Tauri Desktop / Web Reference Host 的文件、通知、窗口等 │ +└──────────────────────────────────────────────────────────┘ +``` + +Runtime 内部有三个平面: + +| 平面 | 职责 | +|---|---| +| Communication Plane | 登录、AppServer 连接、历史同步、实时入站、ACK、outbox、重连。 | +| Coordination Plane | Envelope 校验、事件路由、会话/Agent 状态、App 生命周期、Tool Registry、Inventory、策略与审计。 | +| Execution Plane | Tauri/Host Capability、Surface Sandbox、Bundle Cache、Artifact 内容和受控副作用。 | + +## 4. 应用作用域 + +本阶段**不定义跨市场、跨供应商的 App 身份、反向域名命名空间或发布者归属模型**。Runtime 仅维护本机可用的应用作用域键(`app_scope`),用于启动、隔离存储、消息路由和 Tool 路由。 + +```text +chat +app-registry +settings +voice +whiteboard +draw-and-guess +``` + +`app_scope` 是 Runtime 本地注册表中的短名称,不承诺在未来开放市场中全局唯一。开放生态时再通过版本化 Manifest 引入稳定 App ID、供应商身份和命名空间映射;届时不得破坏本节定义的 scope 路由语义。 + +### 4.1 作用域键 + +| 键 | 用途 | +|---|---| +| `conversation_id` | 协作会话边界;所有可路由消息均必填。 | +| `app_scope` | 消息所属/目标 App 边界;所有可路由消息均必填。 | +| `instance_id` | 可选;精确标识某块白板、语音会话或游戏实例。 | +| `operation_id` | 可选;标识长任务、导出、执行进度或异步工具操作。 | +| `call_id` | 可选;标识 Agent 发起的一次 Tool 调用。 | + +Runtime 的全局管理事件也不省略路由键,而使用保留作用域: + +```text +app_scope: runtime 或具体 Core App +conversation_id: runtime:global +``` + +第三方 App 不得使用或伪造上述保留身份。 + +## 5. Runtime App Manager 与交互编排 + +### 5.1 应用目录与状态 + +Runtime 维护本地 `App Registry`,它是 App 安装、版本、信任和启用状态的唯一事实源; +`App Instance Manager` 单独维护运行实例、前后台焦点和生命周期。App Catalog/市场只提供 +候选条目;市场 App 不直接写文件、删除 Bundle 或改写 Registry。 + +```text +Catalog Entry → Downloading → Verifying → Installed → Enabled + │ │ + │ ├── Active / Background / Suspended instances + │ └── Disabled + └── Update / Rollback / Remove +``` + +建议的 App Record: + +```ts +type AppRecord = { + app_scope: AppScope; + kind: "core" | "installed"; + installed_version: string; + previous_version?: string; + enabled: boolean; + install_state: "installed" | "updating" | "failed"; + active_instance_count: number; + installed_at: string; + enabled_at?: string; +}; + +type AppInstanceRecord = { + instance_id: AppInstanceID; + app_scope: AppScope; + conversation_id?: ConversationID; + state: "starting" | "foreground" | "background" | "suspended" | "stopping" | "stopped" | "failed"; + parent_instance_id?: AppInstanceID; + started_at: string; + stopped_at?: string; + error?: string; +}; +``` + +### 5.2 Runtime 管理接口 + +```ts +interface RuntimeAppManager { + listApps(filter?: AppListFilter): readonly AppRecord[]; + getApp(appScope: AppScope): AppRecord | undefined; + subscribe(listener: (change: AppRegistryChange) => void): Unsubscribe; + + install(request: InstallAppRequest): Promise; + enable(appScope: AppScope): Promise; + disable(appScope: AppScope, options?: DisableAppOptions): Promise; + update(appScope: AppScope, targetVersion?: string): Promise; + rollback(appScope: AppScope): Promise; + remove(appScope: AppScope, options?: RemoveAppOptions): Promise; + + launch(request: LaunchAppRequest): Promise; + closeInstance(instanceID: AppInstanceID): Promise; +} + +interface RuntimeAppOrchestrator { + launch(request: LaunchAppRequest): Promise; + foreground(instanceID: AppInstanceID): Promise; + background(instanceID: AppInstanceID, reason?: string): Promise; + suspend(instanceID: AppInstanceID, reason?: string): Promise; + restore(instanceID: AppInstanceID): Promise; + closeInstance(instanceID: AppInstanceID): Promise; + getFocusStack(conversationID?: ConversationID): readonly AppInstanceID[]; +} +``` + +安装、验签、升级、禁用和移除是异步操作,必须返回可观察的 `AppOperation`。禁用会阻止新实例和新 Tool 调用,并收口现有实例;移除会在实例关闭及用户确认后清理 Bundle 和 App 私有数据。 + +### 5.3 默认应用与安全回退 + +Runtime Shell 不属于任何 App。它负责应用切换、通知、连接状态和安全恢复。用户可选择一个具备 `default_eligible` entrypoint 的已启用 App 作为默认入口: + +```text +当前默认:chat → 图文 IM 为主 +未来默认:voice → 实时语音为主 +``` + +`chat` 是内建、不可移除的 Recovery App:默认 App 不兼容、被禁用、损坏或启动失败时,Runtime 必须回退到它。 + +启动优先级: + +```text +显式启动目标(深链接/通知) + → 可安全恢复的前台工作 + → 用户 Default App + → chat Recovery App +``` + +### 5.4 前台焦点与 App 间切换 + +`Interaction App` 是默认的人与 Agent 交互入口,但不是全局调度器。Runtime 的 +`App Orchestrator`、`Tool Router` 和 `Focus Manager` 负责决定 Agent 请求由哪个 App、哪个 +交互模式或哪个标准组件承接。Interact 只通过 SDK 呈现当前会话并提交用户 Action。 + +```text +Interaction App / Audio Mode foreground + → Agent 请求 launch(draw-and-guess) +Runtime 校验 Tool、Manifest、Inventory、参数和前台条件 + → Audio Instance background / suspended + → Draw-and-Guess Instance starting → foreground + → 游戏结果经 Runtime 回传 Agent + → 关闭或结束后按 focus stack 恢复 Interaction App +``` + +前后台切换必须保留原实例和 `conversation_id` 的关联,不能因为界面暂时不可见就删除 +未完成 Tool Call、Surface 或 App Inbox。若目标 App 启动失败,Runtime 应恢复原前台实例并 +向 Agent 返回受控的 `app_start_failed` 或 `handler_failed` 结果。 + +## 6. Runtime Tool Registry 与动态 Inventory + +### 6.1 App Tool + +App 可在 Manifest 中声明 Agent 可调用方法。当前 Tool 由 App Scope、局部方法和契约版本定位: + +```text +whiteboard/board.create@1 +whiteboard/board.apply_diagram@1 +voice/voice.request_recording@1 +``` + +Runtime 内部使用结构化键,而不依赖字符串拼接: + +```ts +type ToolKey = { + app_scope: AppScope; + method: string; + contract_version: string; +}; +``` + +每个 Tool 声明至少包含: + +- 标题、面向 Agent 的说明、输入/输出 JSON Schema; +- `query`、`command`、`interactive`、`operation` 四种调用模型之一; +- 前台要求、超时、幂等规则和风险等级; +- 是否需启动 App 实例、是否允许 Runtime 自动启动; +- 该方法可能请求的 Capability。 + +### 6.2 可见性与 Inventory + +Runtime 向 Agent 公布的工具不是安装包的全部声明,而是动态交集: + +```text +Agent 可见 Tool + = 已验证 Manifest Tool + ∩ App 已启用 + ∩ 当前 Host 支持 + ∩ 用户/组织策略允许 + ∩ 当前 Agent 和 conversation scope 允许 + ∩ 所需前置权限满足 +``` + +Inventory 包含 App、Tool、Surface 和 Runtime Capability,并具有 revision。Runtime 在连接建立、App 启用/禁用/升级/撤销、Host 能力变化或策略收紧后重新发布。Agent 调用必须携带其看到的 `inventory_revision`;过期清单的调用应被安全拒绝并提示刷新。 + +### 6.3 Tool 调用流程 + +```text +Agent lineup.tool.invoke + → Runtime 验证 Envelope、Agent、inventory revision、App 状态和参数 schema + → 创建 call record / 审计记录 + → Tool Router 判断直接执行、启动 App、切换前台、等待用户交互,或创建异步 operation + → App Orchestrator / Interaction App / Installed App 承接调用 + → App 经 SDK 返回 progress / result / error + → Runtime 验证输出 schema、持久化、更新焦点并回传 Agent +``` + +标准终态错误码至少包括: + +```text +cancelled_by_user +permission_denied +app_disabled +app_not_installed +app_version_mismatch +tool_not_visible +invalid_arguments +foreground_required +operation_expired +handler_failed +``` + +## 7. 统一消息 Envelope 与路由 + +### 7.1 Runtime Envelope + +所有 Agent、Runtime、App、User 和 Host 之间的可路由消息使用统一基础 Envelope: + +```ts +type RuntimeEnvelope = { + v: 1; + id: string; + type: string; + timestamp: string; + + sender: { + kind: "agent" | "runtime" | "app" | "user" | "host"; + id: string; + }; + + target: { + kind: "runtime" | "app"; + app_scope: AppScope; + instance_id?: AppInstanceID; + }; + + scope: { + app_scope: AppScope; + conversation_id: ConversationID; + instance_id?: AppInstanceID; + operation_id?: OperationID; + }; + + correlation?: { + reply_to?: string; + call_id?: string; + inventory_revision?: string; + sequence?: number; + }; + + payload: JsonValue; +}; +``` + +`scope.app_scope` 是消息所属的本地应用作用域,`target.app_scope` 是指定的消费 App。通常二者相同;Runtime 协调型消息可使用 `runtime` 作为 target,再由 Runtime 生成安全的 App 投影并分发。 + +### 7.2 消息分类 + +第一版类型分组: + +```text +lineup.content.* 文本、图片、音频、链接、Artifact 引用 +lineup.agent.* presence、status、task、progress +lineup.interaction.* choice、confirm、input、form +lineup.tool.* invoke、accepted、progress、result、error、cancel +lineup.app.* state.patch、event、open、close、lifecycle +lineup.capability.* request、result +lineup.runtime.* inventory、connection、app registry、policy、error +``` + +具体 schema 将在协议文档版本化;SDK 不暴露未经校验的原始 JSON。 + +### 7.3 Runtime 筛选链 + +```text +Transport 收到原始消息 + → 协议:版本、必填 app_scope/conversation_id、type、大小、schema + → 身份:Agent、用户、会话关联 + → 去重/顺序:id、sequence、cursor + → App:安装、启用、版本、签名、Host 兼容性 + → Tool/Capability:Inventory、方法、参数、策略、前台条件 + → Scope:conversation、instance、operation 所属关系 + → Subscription:App Manifest 声明与 SDK 订阅交集 + → Persist:Runtime Event / App Inbox / cursor + → Deliver:投递给目标 App 的 SDK +``` + +Runtime 不对所有 App 广播原始消息。一个白板 App 即使与 Chat 位于同一 conversation,也只能收到其 Manifest 声明且 Runtime 授权的实例 patch、Tool 调用或事件。 + +## 8. Runtime SDK v1 + +### 8.1 双通道模型 + +```text +Inbound:Runtime → App + - 已验证 Agent 消息 + - App 专属状态投影 + - Tool 调用 + - Runtime / App 生命周期 + +Outbound:App → Runtime + - 用户与 App 声明性 Action + - Tool result / progress / error + - Surface Event + - Capability request + - 可恢复 State Snapshot +``` + +顶层接口: + +```ts +interface LineUpAppRuntimeSDK { + readonly app: AppContext; + readonly lifecycle: AppLifecycleAPI; + readonly state: AppStateAPI; + readonly agentMessages: AgentMessageAPI; + readonly actions: AppActionAPI; + readonly tools: AppToolAPI; + readonly apps: AppNavigationAPI; + readonly artifacts: ArtifactAPI; + readonly storage: ScopedStorageAPI; + readonly capabilities: CapabilityRequestAPI; + readonly diagnostics: DiagnosticsAPI; +} +``` + +App 得到的是按 App Scope、conversation 和实例作用域裁剪后的接口和 View Model,而不是全量 Runtime State 或原始 Transport。 + +### 8.2 App Context、状态与生命周期 + +```ts +interface AppContext { + app_scope: AppScope; + app_version: string; + instance_id: AppInstanceID; + kind: "core" | "installed"; + entrypoint: string; + scope: { + conversation_id?: ConversationID; + operation_id?: OperationID; + parent_instance_id?: AppInstanceID; + }; + granted_permissions: readonly AppPermission[]; +} + +interface AppStateAPI { + snapshot(): ViewModel; + subscribe(listener: (view: ViewModel, change: AppStateChange) => void): Unsubscribe; +} +``` + +生命周期包含 `start`、`foreground`、`background`、`suspend`、`restore`、`closing`。App 可以保存快照并请求延迟关闭,但 Runtime 保留禁用、移除、内存回收和强制收口的最终权力。 + +### 8.3 Agent 消息订阅与可靠 Inbox + +SDK 提供实时订阅,同时提供持久化 Inbox 补读: + +```ts +interface AgentMessageAPI { + list(request?: { + conversation_id?: ConversationID; + after?: AgentMessageCursor; + limit?: number; + }): Promise; + + subscribe( + options: { + conversation_id?: ConversationID; + types?: readonly AgentMessageType[]; + include_pending?: boolean; + }, + handler: (message: AgentAppMessage) => Promise | void, + ): Unsubscribe; + + acknowledge(message_id: string): Promise; +} +``` + +投递语义: + +1. Runtime 先验证并持久化,再回调 App; +2. 每条消息有唯一 `message_id`,App 必须幂等处理; +3. 展示类消息可自动确认;Tool 调用、状态 patch 等业务消息需 App 显式 ACK; +4. App 未运行、暂停或崩溃时,Runtime 写入该 App Inbox;恢复后通过 `list()` 与 `subscribe()` 补齐; +5. App 禁用、移除或不兼容时,Runtime 不静默投递或丢弃关键调用,而向 Agent 返回标准拒绝。 + +App 的订阅条件只是请求;实际投递集为: + +```text +Manifest agent_subscriptions + ∩ SDK subscribe filter + ∩ App 权限 + ∩ conversation / instance scope + ∩ Agent target app_scope + ∩ Runtime Policy +``` + +### 8.4 Action、Tool、App 导航与 Artifact + +App 只提交声明性 Action;不得构造原始 Agent Envelope 或直接访问 Transport: + +```ts +interface AppActionAPI { + dispatch(action: AppAction): Promise; +} + +interface AppToolAPI { + onInvoke(listener: (call: AppToolInvocation) => Promise): Unsubscribe; + progress(request: { call_id: ToolCallID; progress: ToolProgress }): Promise; + complete(request: { call_id: ToolCallID; result: JsonValue }): Promise; + fail(request: { call_id: ToolCallID; code: AppToolErrorCode; message?: string }): Promise; +} + +interface AppNavigationAPI { + listAvailable(): readonly AppSummary[]; + launch(request: LaunchAppRequest): Promise; + focus(instanceID: AppInstanceID): Promise; + background(instanceID: AppInstanceID, reason?: string): Promise; + suspend(instanceID: AppInstanceID, reason?: string): Promise; + close(instanceID: AppInstanceID): Promise; + openDefaultApp(): Promise; +} +``` + +`AppNavigationAPI` 只是 App 发给 Runtime 的受限请求接口。真正的 Tool Router、App Instance +Manager 和 Focus Manager 位于 Runtime 内部:它们负责检查 App 是否已安装/启用、是否满足 +前台条件、是否需要用户确认,以及切换失败时恢复原前台实例。Interact 可以请求启动扩展 +App,但不能直接决定其他 App 的生命周期。 + +Artifact、媒体与文件通过 Runtime Artifact Store 暴露元数据、受限读取、创建、会话引用和用户保存;App 不取得任意路径或跨 App 文件访问权。 + +### 8.5 存储与 Capability + +每个 App 使用 Runtime 管理的作用域隔离存储: + +```text +app-data/chat/ +app-data/app-registry/ +app-data/voice/ +app-data/whiteboard/ +``` + +SDK 中的 `storage` 提供 JSON 数据和可恢复 snapshot,Runtime 负责配额、升级迁移、禁用和移除时的清理。Capability 必须通过统一请求接口: + +```ts +interface CapabilityRequestAPI { + request(request: { + capability: CapabilityName; + purpose: string; + input: JsonValue; + scope?: AppScope; + }): Promise>; +} +``` + +Runtime 检查 Manifest 声明、App 启用状态、Host 支持、前台要求、用户确认、系统权限、策略、限流与审计;App 只能获得受控结果。 + +## 9. 信任分层与 Surface Bridge SDK + +| 层级 | 例子 | 可用接口 | 明确禁止 | +|---|---|---|---| +| Core App | Chat、App Registry、Settings | 完整 App Runtime SDK(仍受 Scope 和 Capability 约束) | 直接绕过 Transport/Capability Gateway。 | +| Installed App | 白板、语音、游戏 | 受限 Surface Bridge SDK:状态、已声明 Tool、事件、隔离存储、Capability request | Tauri invoke、父 DOM、token、任意网络、其他 App 数据。 | +| Host Provider | Tauri Desktop / Web Reference Host 实现 | Runtime 内部 Host Provider API | 向 Runtime 提供系统能力;不直接暴露给 Agent/Surface。 | + +下载型 App 使用 `iframe sandbox="allow-scripts"` 或等价隔离容器;不包含 `allow-same-origin`。它经严格 CSP、来源验证和消息 schema 校验的桥接访问 Surface SDK。第一版不支持市场下载包执行本地 Rust、Node、Shell 或任意浏览器特权代码。 + +## 10. App Manifest 的 Runtime/SDK 声明 + +每个 App Manifest 除 Bundle、签名和 Surface 外,还应声明 Runtime SDK 与消息/工具契约。当前阶段只使用本地 `app_scope`,不在 Manifest 中固化供应商身份或全局命名空间: + +```json +{ + "format": "lineup.app.v1", + "app_scope": "whiteboard", + "version": "1.2.0", + "runtime_sdk": { + "api_version": "1", + "required_features": ["app.lifecycle.v1", "app.tools.v1", "surface.state.v1"], + "optional_features": ["artifact.create.v1"] + }, + "entrypoints": [ + {"id": "canvas", "kind": "contextual", "default_eligible": false} + ], + "agent_subscriptions": [ + {"type": "lineup.app.state.patch", "scope": "instance"}, + {"type": "lineup.tool.invoke", "scope": "conversation"} + ], + "tools": [ + { + "method": "board.create", + "contract_version": "1", + "invocation": {"kind": "command", "activation": "launch_if_needed"}, + "input_schema": {"type": "object", "additionalProperties": false}, + "output_schema": {"type": "object", "additionalProperties": false} + } + ] +} +``` + +Runtime 在安装、启用和启动时进行 SDK 版本及 feature 协商;不兼容 App 不进入可用 Inventory,也不得启动。 + +## 11. Runtime 状态与恢复 + +顶层 Runtime State 至少包含: + +```text +identity 用户、设备、认证会话 +connection AppServer 状态、cursor、重试、outbox +conversations Agent 映射、消息引用、任务、交互、Artifact 元数据 +apps App Registry、默认 App、运行实例、App Inbox +tools 已声明 Tool、可见性、调用与 operation +capabilities 授权、执行状态、最小审计 +``` + +第一版采用“事件驱动状态机 + 必要快照”,而非完整 Event Sourcing:关键入站事件、用户决定、Tool 结果、outbox 和审计记录持久化;渲染细节和短暂 UI 状态不必全部写入事件日志。 + +Runtime 生命周期: + +```text +created → restoring → authenticating → synchronizing → online + ↘ reconnecting / offline_degraded +online / offline_degraded → stopping → stopped +``` + +启动时恢复 App Registry、默认入口、会话 cursor、outbox、App Inbox、未完成 Tool 和可恢复实例;追平历史后再开始实时投递。离线时用户/App Action 进入 outbox,重连后按幂等键和顺序处理。 + +## 12. 推荐工程边界 + +```text +lineup-app/ +├── runtime-core/ +│ ├── communication/ Transport、sync、outbox +│ ├── coordination/ Event、state、router、policy、focus、audit +│ ├── apps/ App Manager、Registry、Instance、Focus、Lifecycle Manager +│ ├── tools/ Tool Registry、Inventory、Router、call lifecycle +│ ├── capabilities/ Capability Gateway +│ └── persistence/ Runtime Store、App Inbox、Artifact metadata +├── runtime-sdk/ +│ ├── app.ts Core App SDK 类型 +│ ├── manifest.ts App/Tool/Subscription Manifest 类型 +│ ├── protocol.ts Runtime Envelope 与 schema +│ ├── errors.ts 稳定错误码 +│ └── testkit/ +├── surface-sdk/ +│ ├── bridge.ts sandbox postMessage bridge +│ └── surface.ts Installed App 最小接口 +└── tauri/ + ├── src/ + │ ├── bootstrap/ Tauri/Web 的应用启动装配层 + │ ├── runtime-host/ Runtime Host Provider 适配 + │ ├── core-apps/ chat、app-registry、settings + │ └── shell/ app switcher、default app、recovery + └── src-tauri/ 文件、音频、通知、窗口等 Rust Provider +``` + +当前 `lineup-app/tauri/src/main.ts` 同时承担 Runtime、Chat、Host Adapter 和开发 Fixture 的职责,是拆分的主要对象。现有 `InteractionKernel`、Transport、Conversation Store、Surface Registry、Instance Manager、Bundle Cache、Capability Registry 与 Inventory Publisher 可作为上述 Runtime Core 的迁移基础。 + +## 13. 第一阶段落地顺序与验收 + +### R0:冻结 Runtime/SDK 合约 + +- 固化 `RuntimeEnvelope`、app scope / conversation ID / instance ID 规则; +- 固化 Event / Command / Effect 边界; +- 定义 `LineUpAppRuntimeSDK`、`Surface Bridge SDK` 与 Manifest TypeScript 类型; +- 为 Envelope、App Manifest、Tool Descriptor、SDK 错误码准备 golden fixtures。 + +### R1:建立 Runtime Core 和 Interaction Core App(当前 `chat` 实现) + +- 将 Runtime 的创建与装配集中在单一启动入口,不让 `main.ts` 变成通信和业务逻辑的堆放处; +- Runtime 独占 Transport、Store、outbox 和入站筛选; +- 将当前图文 IM 重构为 Interaction Core App 的 `chat` 实现; +- 当前 `chat` 通过 `agentMessages.subscribe()` 获取已验证的 Agent 消息,不再直接依赖 Transport; +- 保持当前登录、同步、本地回显、Markdown、Tool Call、Task 与 Artifact 回归行为。 + +### R2:App Registry Core App + +- 将现有开发期 `SurfaceRegistry` 升级为 Runtime App Registry; +- 实现 Core App 记录、Installed App 记录、enable/disable/remove 和默认 App 选择; +- 将 Registry UI 实现为 `app-registry`,仅调用 `RuntimeAppManager`; +- App 状态变化后正确更新 Runtime Inventory。 + +### R3:Tool Registry 与 App SDK Inbox + +- 实现 Manifest Tool / Subscription 解析与可见性筛选; +- 将动态 Inventory 同步给 Agent; +- 实现 Agent `tool.invoke` → Runtime → App SDK → `tool.result` 的可靠闭环; +- App 未运行时持久化 Inbox,恢复后可幂等补读。 + +### R4:第一个 Installed App 闭环 + +- 接入一个已签名的画板或任务面板 App; +- 验收 install → enable → inventory 更新 → Agent 调用 Tool → App 启动 → Surface 事件 → Agent result → disable/remove; +- 后续语音 App 复用同一 SDK、Tool、Capability 与 Artifact 通道,而不是再实现独立通信链路。 + +硬性验收: + +```text +1. 缺少或非法 app_scope / conversation_id 的可路由消息被 Runtime 拒绝; +2. App 不会收到其他 App 或其他 conversation 的 Agent 原始消息; +3. App 被禁用后,其 Tool 从 Inventory 移除且新调用被拒绝; +4. 断线/重启后 App Inbox、outbox、Tool 调用和实例状态能有界恢复; +5. 下载型 App 无法访问 Tauri invoke、Host DOM、token 或未授予 Capability; +6. 默认 App 不可用时 Runtime 自动进入 chat Recovery App; +7. 所有 Tool 调用、权限拒绝与终态结果均可按 app_scope、conversation_id、call_id 审计和测试。 +``` + +## 14. 与已有正式方案的关系 + +- 本文将 [App 层架构方案](lineup-app-layer-architecture.md) 中的 Interaction Runtime 从“聊天 Host 内部模块”收敛为整个 App 的 Runtime,并补充了 App Manager、App Tool Registry、SDK 和消息路由模型。 +- 本文不废弃 [UI Surface 与 App Capability 协议](lineup-ui-surface-protocol.md) 中已完成的 Surface 隔离、Capability 确认、生产 Bundle 验签和动态 inventory 原则;后续应将其协议字段迁移/扩展为本文定义的 Runtime Envelope、App Manifest 和 Tool Registry,而不能引入绕开 Runtime 的平行通道。 +- 现有 M2/M4 文档和实现使用的 `app id` 是当前 Surface 协议的实现字段。本方案在 Runtime 重构阶段以 `app_scope` 作为本地路由字段;供应商身份和全局命名空间将在后续生态阶段通过独立、版本化的兼容设计重新引入。 +- 当前 M0~M4 实现可作为 Runtime 的迁移基础,但其现有文件边界不是最终 Runtime/App/SDK 边界。 diff --git a/设计/02.正式方案/lineup-ui-surface-protocol.md b/设计/02.正式方案/lineup-ui-surface-protocol.md new file mode 100644 index 0000000..604b734 --- /dev/null +++ b/设计/02.正式方案/lineup-ui-surface-protocol.md @@ -0,0 +1,226 @@ +# LineUp UI Surface 与 App Capability 协议 + +**版本:** 1.0(提案) +**状态:** 已有 Web Chat Reference Host +**日期:** 2026-08-02 + +> **汇总入口:** 本文保留 Surface 与 Capability 的协议和安全细节。后续 Runtime、SDK、App 管理及旧 `app.id` 字段的兼容迁移以 [LineUp App 最终设计方案](app_final_design.md) 为准。 + +## 1. 目标 + +LineUp 的 Agent 不应只能回一段文本,也不应获得在宿主 App 任意执行代码的权限。本协议定义一个类似“小程序表现层”的受控扩展模型: + +```text +Agent / Adapter + ├─ lineup.v1.ui.open / patch / close ─────→ UI Surface Host + │ └─ sandbox HTML + CSS + JS + ├─ lineup.v1.app.call ─────→ App Capability Registry + │ └─ 用户确认 / 系统权限 / 本机执行 + ←─ lineup.v1.ui.event / app.result ────── 用户动作或受控调用结果 +``` + +它有两层,不可混用: + +| 层 | 作用 | 能做什么 | 不能做什么 | +|---|---|---|---| +| `UI Surface` | 呈现交互界面 | 显示 HTML/CSS/JS、收集用户事件、接收状态更新 | 读取宿主登录态、直接访问设备能力、直接调用 IM / 网络 | +| `App Capability` | 调用宿主上层应用能力 | 在能力注册、权限和用户确认后打开链接、写剪贴板、选文件、调用原生模块等 | 由 Surface 脚本绕过权限直接调用 | + +标准 Markdown、文本、状态、进度、choice、confirm、input 等仍应优先由宿主内置渲染器实现。Surface 适用于仪表盘、地图、复杂表单、图表、可视化编辑器等无法由内置组件良好表达的界面。 + +## 2. 安全模型(不可省略) + +1. Agent 的 UI bundle 被视为**不可信内容**,不是 App 代码的一部分。 +2. Web Host 必须使用独立 origin 的 `iframe sandbox="allow-scripts"`。禁止 `allow-same-origin`、`allow-top-navigation`、`allow-popups`、`allow-forms`。 +3. Surface 的 CSP 至少为 `default-src 'none'; connect-src 'none'; img-src data: blob:; style-src 'unsafe-inline'; script-src 'unsafe-inline'`。默认不得联网、加载远程脚本、访问摄像头或地理位置。 +4. 宿主与 Surface 仅用 `postMessage` 通信;宿主必须同时验证 `event.source`、消息命名空间、`instance_id`、事件名、JSON 类型与大小。 +5. Surface 事件只是“用户意图”回传。任何上层 App / 原生能力都必须由 Agent 另行发送 `app.call`,再由宿主依据注册表、风险等级和用户授权执行。 +6. Content 不得写入宿主 DOM。Markdown 使用解析器后仍须 sanitizer;HTML Surface 只能放进 sandbox `srcdoc`。 +7. 生产环境应只接受已签名或在 Agent allowlist 中的 bundle hash;Reference Host 先以严格 sandbox 保障隔离,并保留 `app.integrity` 字段用于升级。 + +## 3. 消息类型 + +所有消息均使用既有 `lineup.v1` 信封。`conversation_id`、`id`、`sender`、`target` 的规则不变。 + +| Type | 方向 | 含义 | +|---|---|---| +| `lineup.v1.ui.open` | Agent → Client | 创建或替换一个 Surface 实例 | +| `lineup.v1.ui.patch` | Agent → Client | 向已打开实例推送新的状态;不可注入或替换代码 | +| `lineup.v1.ui.close` | Agent → Client | 关闭实例 | +| `lineup.v1.ui.event` | Client → Agent | Surface 中的用户事件或用户关闭事件 | +| `lineup.v1.client.inventory` | Client → Agent | 当前 Host 的 revisioned 最小接口清单:标准组件、应用中心已启用 app Surface 与 policy 筛选后的 capability | +| `lineup.v1.app.list` | Client → Agent | 可选的兼容 capability-only 投影;不得替代完整 inventory 或宣称安装/授权 | +| `lineup.v1.app.call` | Agent → Client | 请求调用一个声明过的 capability | +| `lineup.v1.app.result` | Client → Agent | 调用完成、拒绝、失败或不支持的结果 | + +未知的 `ui.*` 或 `app.*` type 只能安全显示或回复 `unsupported`,不得执行。 + +## 4. UI Surface 合约 + +### 4.1 打开 + +```json +{ + "v": 1, + "id": "msg_ui_01", + "type": "lineup.v1.ui.open", + "conversation_id": "conv_01", + "sender": {"kind": "agent", "id": "agent_hermes_main"}, + "payload": { + "instance_id": "weather.dashboard.01", + "app": { + "id": "com.lineup.weather.dashboard", + "name": "天气面板", + "version": "1.0.0", + "integrity": "sha256-BASE64_DIGEST", + "html": "
", + "css": "main { padding: 16px }", + "js": "document.querySelector('#refresh').onclick=()=>LineUpSurface.event('refresh',{unit:'c'})" + }, + "state": {"city": "北京", "temperature": 22} + } +} +``` + +约束: + +- `instance_id` 在一个会话内唯一,格式为 `[A-Za-z0-9._:-]{1,128}`;相同 ID 的 `ui.open` 表示替换旧实例; +- `app.id` 为反向域名风格的稳定应用 ID,`version` 为 SemVer; +- `html`、`css`、`js` 是 Surface bundle;单个 bundle 的生产上限建议为 160 KiB,资源应使用经过 Artifact 管理和签名的本地引用,禁止任意公网 URL; +- `state` 必须是 JSON object。UI bundle 将在 `ready` 后和每次 `ui.patch` 收到它; +- **`ui.patch` 只能更新 `state`,绝不能更新 HTML/CSS/JS。** 若要升级 bundle,关闭旧实例并以新 `version` 打开新实例。 + +### 4.2 Surface bridge + +Host 注入唯一的全局对象: + +```js +LineUpSurface.event('refresh', { unit: 'c' }) +LineUpSurface.onState((state) => render(state)) +LineUpSurface.resize(document.documentElement.scrollHeight) +``` + +它只允许以下上行消息: + +```json +{ + "namespace": "lineup.surface.v1", + "type": "event", + "event": "refresh", + "data": {"unit": "c"} +} +``` + +Host 将其转换为: + +```json +{ + "type": "lineup.v1.ui.event", + "payload": { + "instance_id": "weather.dashboard.01", + "event": "refresh", + "data": {"unit": "c"} + } +} +``` + +`event` 采用 `[A-Za-z][A-Za-z0-9._:-]{0,63}`,`data` 必须为小于 16 KiB 的 JSON object。Surface 不拥有 `app.call` bridge。 + +### 4.3 状态更新与关闭 + +```json +{"type":"lineup.v1.ui.patch","payload":{"instance_id":"weather.dashboard.01","state":{"city":"上海","temperature":28}}} +``` + +```json +{"type":"lineup.v1.ui.close","payload":{"instance_id":"weather.dashboard.01","reason":"completed"}} +``` + +用户主动关闭时 Client 应回送 `ui.event`,其中 `event` 为 `close`。 + +## 5. App Capability 合约 + +### 5.1 动态 Client Inventory + +客户端在会话建立完成后,以及应用中心的 app 启用/停用/升级、Host policy 或 capability 可见性变化时,向**对应 Agent 会话**发送 `client.inventory`。它有单调递增或不可复用的 `revision`;Agent 必须用最新 revision 决定可请求的组件、Surface 和能力。收到撤销后的旧 app id、Surface 或 capability 引用时,Client 只返回确定的 `unsupported / revoked` 结果,绝不回退到执行或加载远端 bundle。 + +```json +{ + "type": "lineup.v1.client.inventory", + "payload": { + "revision": "catalog-42", + "standard_components": [ + {"id":"choice","version":"1"}, + {"id":"confirm","version":"1"}, + {"id":"input","version":"1"} + ], + "applications": [ + { + "id":"com.lineup.svg-canvas", + "version":"1.0.0", + "surfaces":[{"id":"canvas","events":["draw","resize","snapshot"]}] + } + ], + "capabilities": [ + {"name":"artifact.save","version":"1.0","risk":"user_confirmation"} + ] + } +} +``` + +`applications` 只能列出应用中心中**已启用且已在本地完成相应阶段验证**的应用,不包含 bundle 源码、安装来源、登录态、文件路径或用户内容。SVG 画板这样的 app 只允许 Agent 以 app id 创建受限 Surface,并通过用户触发的 `ui.event(draw / resize / snapshot)` 获取声明性画布事件;inventory 不授予远程脚本注入、读取宿主 DOM 或本机能力权限。 + +### 5.2 Capability 声明(`app.list` 兼容投影) + +客户端可在 inventory 之后或 capability 变化时发送 `app.list` 作为仅包含 capability 的兼容投影。只有 inventory / app.list 中声明且仍未被撤销的 `capability` 才能被请求;声明从不等同于授权。 + +```json +{ + "type": "lineup.v1.app.list", + "payload": { + "capabilities": [ + {"name":"app.open_url","version":"1.0","risk":"user_confirmation","input_schema":{"type":"object","required":["url"]}}, + {"name":"clipboard.write","version":"1.0","risk":"user_confirmation","input_schema":{"type":"object","required":["text"]}}, + {"name":"device.pick_file","version":"1.0","risk":"system_permission","input_schema":{"type":"object"}} + ] + } +} +``` + +风险必须是下列之一:`display_only`、`user_confirmation`、`system_permission`、`restricted`。后两者不能被记住为永久授权,且必须经过原生系统权限或额外身份校验。 + +### 5.3 调用与结果 + +```json +{ + "type": "lineup.v1.app.call", + "payload": { + "call_id": "call_open_docs_01", + "capability": "app.open_url", + "reason": "打开部署文档供你核对", + "expires_at": "2026-08-02T12:10:00Z", + "arguments": {"url": "https://example.com/docs"} + } +} +``` + +Client 必须向用户说明 capability 和 `reason`,收到确认后再执行,随后使用相同 `call_id` 回传: + +```json +{ + "type": "lineup.v1.app.result", + "payload": { + "call_id": "call_open_docs_01", + "status": "completed", + "result": {"opened": true} + } +} +``` + +`status`:`completed | rejected | cancelled | expired | unsupported | failed`。同一 `call_id` 必须幂等;调用记录与授权决定应由 Gateway 审计。 + +## 6. Reference Host 当前实现与阶段边界 + +截至 2026-08-03,Tauri Reference Host 已完成 M0 和 M1-01~M1-03:严格 Envelope / Kernel / Store / Renderer 边界,Markdown、status/progress/error、choice、confirm、input 的可信原生渲染与本地状态恢复。它**尚未**实现 `client.inventory` 发送、应用中心、`ui.open / patch / close` 的 Surface Host、远端或本地 app bundle 加载、`app.call` 执行、Capability Registry 或 `app.result` 网络回传。 + +因此,这份协议中的 Surface、inventory 与 Capability 段落是后续 M2~M4 的正式契约,不是当前 Web Chat 已开放的功能。M2 建立应用中心本地启用注册表与隔离 Surface;M3 才生成/更新并通知 `client.inventory`,再实施 Capability policy;M4 负责下载、完整性校验、缓存、回滚与 Host 一致性。当前只以 Tauri Desktop Host 与同代码 Web Reference Host 实现这些边界;不规划独立 Android/iOS/Wails 客户端。 diff --git a/APP架构设计.md b/设计/APP架构设计.md similarity index 97% rename from APP架构设计.md rename to 设计/APP架构设计.md index fd276c9..0fcdaa4 100644 --- a/APP架构设计.md +++ b/设计/APP架构设计.md @@ -522,7 +522,7 @@ 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: +[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 和错误码 @@ -584,10 +584,10 @@ npm run build ## 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):跨文档详细契约来源; +- [迭代/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):跨文档详细契约来源; 若与本文的产品术语或当前迭代顺序冲突,以本文为准并同步更新上游方案。 diff --git a/设计/README.md b/设计/README.md new file mode 100644 index 0000000..25e55cb --- /dev/null +++ b/设计/README.md @@ -0,0 +1,20 @@ +# LineUp App 当前设计文档 + +这里集中放置 LineUp App 当前阶段仍在使用的设计文档。LineUp App 是用户使用的主应用,Runtime 是 App 内部提供给 MiniApp 的核心运行环境;当前设计以这组文档为准。 + +## 当前权威入口 + +- [APP架构设计.md](APP架构设计.md):当前产品边界、Runtime、MiniApp、SDK、Interact 以及发布安全约束的总入口。 +- [LineUp App 最终设计方案](02.正式方案/app_final_design.md):当前架构、契约和实施顺序的详细汇总。 + +## 详细方案 + +- [LineUp App 层架构与迁移记录](02.正式方案/lineup-app-layer-architecture.md):M0~M4 的实施边界、迁移记录和分层规则。 +- [LineUp Runtime 与 App SDK 架构方案](02.正式方案/lineup-runtime-sdk-architecture.md):Runtime、App Manager、Tool Registry、SDK 和消息路由的详细方案。 +- [LineUp UI Surface 与 App Capability 协议](02.正式方案/lineup-ui-surface-protocol.md):Surface、Capability、权限确认和 Bundle 安全规则。 + +## 迭代和评审 + +迭代定义以及每轮设计评审、验收记录保留在 [迭代/](../迭代/README.md)。设计文档描述长期架构和当前阶段的约束,迭代文档描述具体要交付的工作。 + +根目录下的 `设计/00.records` 和 `设计/01.前期分析与设计` 属于历史资料,不作为当前 LineUp App 设计的主入口。 diff --git a/迭代/03.sdk_and_coreapp/01.design_review.md b/迭代/03.sdk_and_coreapp/01.design_review.md index 2d41d1e..800a915 100644 --- a/迭代/03.sdk_and_coreapp/01.design_review.md +++ b/迭代/03.sdk_and_coreapp/01.design_review.md @@ -2,7 +2,7 @@ > 评审日期:2026-08-05 > 评审编号:01 -> 评审基线:[APP架构设计.md](../../APP架构设计.md) +> 评审基线:[APP架构设计.md](../../设计/APP架构设计.md) > 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) > 评审方式:独立子 agent 只读评审;本文件记录评审意见,不代表已采纳或已实现。 @@ -79,13 +79,13 @@ Runtime 连接。 本轮评审问题均已得到设计结论,后续进入实现时应以 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) -和 [APP架构设计.md](../../APP架构设计.md) 为准。 +和 [APP架构设计.md](../../设计/APP架构设计.md) 为准。 ## 2. 阻塞问题 ### B1. Task Dashboard 的可信 DOM / Host adapter 权限突破了当前信任模型 -**架构基线**在 [APP架构设计.md](../../APP架构设计.md) 的 MiniApp 信任模型中明确: +**架构基线**在 [APP架构设计.md](../../设计/APP架构设计.md) 的 MiniApp 信任模型中明确: - `Interact / System MiniApp` 可使用可信内建 DOM 组件; - Installed MiniApp 必须经隔离 iframe / Surface Bridge 运行。 @@ -348,6 +348,6 @@ bundled 参考 MiniApp,本阶段就完成其端到端路径。因此删除重 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)。 +5. 把 S1~S5 与第 5 节的验收场景回填入 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) 和必要的 [APP架构设计.md](../../设计/APP架构设计.md)。 在上述收敛前,不建议开始 `standard-interaction-service` 或参考 MiniApp 的实现,以免重新形成 Chat / Interact 专用旁路。 diff --git a/迭代/03.sdk_and_coreapp/03.design_review.md b/迭代/03.sdk_and_coreapp/03.design_review.md index 943f72a..75bff2b 100644 --- a/迭代/03.sdk_and_coreapp/03.design_review.md +++ b/迭代/03.sdk_and_coreapp/03.design_review.md @@ -3,7 +3,7 @@ > 评审编号: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) +> 参考资料:[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 均已确认并回填主定义文档;后续不再进行纯设计评审,直接进入实现,并在实现完成后做一次关闭式复核。 diff --git a/迭代/03.sdk_and_coreapp/03.sdk_and_coreapp.md b/迭代/03.sdk_and_coreapp/03.sdk_and_coreapp.md index eea4f9b..7096eba 100644 --- a/迭代/03.sdk_and_coreapp/03.sdk_and_coreapp.md +++ b/迭代/03.sdk_and_coreapp/03.sdk_and_coreapp.md @@ -4,7 +4,7 @@ **状态:** 已完成(P0~P3 问题已清空,代码、自动化测试和真实浏览器验收通过) **日期:** 2026-08-05 **前置基线:** [00.base.md](../00.base/00.base.md)、[01.kernel.md](../01.kernel/01.kernel.md) -**权威架构:** [APP架构设计.md](../../APP架构设计.md) +**权威架构:** [APP架构设计.md](../../设计/APP架构设计.md) ## 1. 迭代目标 @@ -1050,7 +1050,7 @@ fixture,再修改实现,不能在业务代码里悄悄改变契约。 7. **端到端验收与文档回填** - 运行完整单元测试和生产构建; - 通过 Tauri/Web Reference Host 完成代表性浏览器验收; - - 将最终 SDK 形态与参考 MiniApp 结果回填 [APP架构设计.md](../../APP架构设计.md)。 + - 将最终 SDK 形态与参考 MiniApp 结果回填 [APP架构设计.md](../../设计/APP架构设计.md)。 ## 9. 验收目标 diff --git a/迭代/03.sdk_and_coreapp/04.acceptance_review.md b/迭代/03.sdk_and_coreapp/04.acceptance_review.md index e08a752..49dc831 100644 --- a/迭代/03.sdk_and_coreapp/04.acceptance_review.md +++ b/迭代/03.sdk_and_coreapp/04.acceptance_review.md @@ -3,7 +3,7 @@ > 评审编号:04 > 评审日期:2026-08-05 > 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) -> 架构基线:[APP架构设计.md](../../APP架构设计.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 已确认本迭代可以标记为“已完成”。 diff --git a/迭代/03.sdk_and_coreapp/05.acceptance_review.md b/迭代/03.sdk_and_coreapp/05.acceptance_review.md index 4efa2a9..ddaacec 100644 --- a/迭代/03.sdk_and_coreapp/05.acceptance_review.md +++ b/迭代/03.sdk_and_coreapp/05.acceptance_review.md @@ -3,7 +3,7 @@ > 评审编号:05 > 评审日期:2026-08-06 > 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) -> 架构基线:[APP架构设计.md](../../APP架构设计.md) +> 架构基线:[APP架构设计.md](../../设计/APP架构设计.md) > 参考评审:[04.acceptance_review.md](04.acceptance_review.md) > 评审方式:独立子 agent 只读验收 + 主 agent 逐项复核;检查当前代码、Manifest、SDK 契约、自动化测试、构建和文档证据。 > 总体结论:本轮发现的 P3 契约/证据问题均已逐项修复并分别提交;当前没有遗留 P0~P3 问题。