初始化 agent_ops 文档治理体系

This commit is contained in:
2026-08-07 16:56:51 +08:00
commit 10840909ab
75 changed files with 15750 additions and 0 deletions
@@ -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 汇总为动态 InventoryAgent 只能调用当前 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、请求保存文件。
EffectRuntime 决定执行的副作用
网络发送、文件选择、录音、通知、创建 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<AppOperation>;
enable(appScope: AppScope): Promise<AppOperation>;
disable(appScope: AppScope, options?: DisableAppOptions): Promise<AppOperation>;
update(appScope: AppScope, targetVersion?: string): Promise<AppOperation>;
rollback(appScope: AppScope): Promise<AppOperation>;
remove(appScope: AppScope, options?: RemoveAppOptions): Promise<AppOperation>;
launch(request: LaunchAppRequest): Promise<AppInstanceHandle>;
closeInstance(instanceID: AppInstanceID): Promise<void>;
}
```
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 AppCore 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 实现与 M0M4 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<AgentMessagePage>;
subscribe(
options: {
conversation_id?: ConversationID;
types?: readonly AgentMessageType[];
include_pending?: boolean;
},
handler: (message: AgentAppMessage) => Promise<void> | void,
): Unsubscribe;
acknowledge(message_id: string): Promise<void>;
}
```
投递语义:
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 SDKInstalled 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<ViewModel = unknown> {
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<CommandReceipt>;
}
interface AppToolAPI {
onInvoke(listener: (call: AppToolInvocation) => Promise<AppToolOutcome>): Unsubscribe;
progress(request: { call_id: ToolCallID; progress: ToolProgress }): Promise<void>;
complete(request: { call_id: ToolCallID; result: JsonValue }): Promise<void>;
fail(request: { call_id: ToolCallID; code: AppToolErrorCode; message?: string }): Promise<void>;
}
interface AppNavigationAPI {
listAvailable(): readonly AppSummary[];
launch(request: LaunchAppRequest): Promise<AppInstanceHandle>;
focus(instanceID: AppInstanceID): Promise<void>;
close(instanceID: AppInstanceID): Promise<void>;
openDefaultApp(): Promise<void>;
}
```
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<T extends JsonValue>(request: {
capability: CapabilityName;
purpose: string;
input: JsonValue;
scope?: AppScope;
}): Promise<CapabilityResult<T>>;
}
```
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 行为。
### F1Runtime 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 不读取旧协议字段,也不需要同步升级远端。
### F2App 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 和恢复策略。
### F3Tool Registry、Inventory 与 SDK Inbox
- 解析 Manifest Tool/Subscription 并计算可见性;
- 在 Runtime 连接与状态变化时同步 revisioned Inventory 给 AgentTool 可声明是否需要启动 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 的平行通道。