Files
app/设计/02.正式方案/lineup-runtime-sdk-architecture.md
T

32 KiB
Raw Blame History

LineUp Runtime 与 App SDK 架构方案

版本: 0.1(架构基线) 状态: 已确认的 Runtime / SDK 方向;尚未完全落地到当前 Tauri 实现 日期: 2026-08-04 关联方案: LineUp App 层架构设计方案LineUp UI Surface 与 App Capability 协议

汇总入口: 本文是 Runtime / SDK 初稿的详细来源。后续设计以 LineUp App 最终设计方案 为准;后者收敛了本地 app_scope、兼容迁移和实施顺序。


0. 结论与范围

LineUp 不是“聊天应用里附带一个交互 Runtime”。LineUp App 本身就是运行在用户设备上的 协作 Runtime,可以把它理解为本地协调中心:它独占与 AppServer / Remote Agent 的连接, 维护会话和本地应用生态,并为上层应用提供统一的消息、工具、存储、权限和生命周期接口。 聊天只是第一个使用这些接口的内置 App。

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_scopeconversation_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. 运行时分层

┌──────────────────────────────────────────────────────────┐
│ Runtime Shell                                              │
│ 应用切换 · 默认入口 · 连接状态 · 通知 · 安全恢复          │
├──────────────────────────────────────────────────────────┤
│ Core App / Installed App                                   │
│ Interaction AppIM / 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 路由。

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 的全局管理事件也不省略路由键,而使用保留作用域:

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。

Catalog Entry → Downloading → Verifying → Installed → Enabled
                                              │             │
                                              │             ├── Active / Background / Suspended instances
                                              │             └── Disabled
                                              └── Update / Rollback / Remove

建议的 App Record

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 管理接口

interface RuntimeAppManager {
  listApps(filter?: AppListFilter): readonly AppRecord[];
  getApp(appScope: AppScope): AppRecord | undefined;
  subscribe(listener: (change: AppRegistryChange) => void): Unsubscribe;

  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>;
}

interface RuntimeAppOrchestrator {
  launch(request: LaunchAppRequest): Promise<AppInstanceHandle>;
  foreground(instanceID: AppInstanceID): Promise<AppInstanceHandle>;
  background(instanceID: AppInstanceID, reason?: string): Promise<AppInstanceHandle>;
  suspend(instanceID: AppInstanceID, reason?: string): Promise<AppInstanceHandle>;
  restore(instanceID: AppInstanceID): Promise<AppInstanceHandle>;
  closeInstance(instanceID: AppInstanceID): Promise<void>;
  getFocusStack(conversationID?: ConversationID): readonly AppInstanceID[];
}

安装、验签、升级、禁用和移除是异步操作,必须返回可观察的 AppOperation。禁用会阻止新实例和新 Tool 调用,并收口现有实例;移除会在实例关闭及用户确认后清理 Bundle 和 App 私有数据。

5.3 默认应用与安全回退

Runtime Shell 不属于任何 App。它负责应用切换、通知、连接状态和安全恢复。用户可选择一个具备 default_eligible entrypoint 的已启用 App 作为默认入口:

当前默认:chat   → 图文 IM 为主
未来默认:voice  → 实时语音为主

chat 是内建、不可移除的 Recovery App:默认 App 不兼容、被禁用、损坏或启动失败时,Runtime 必须回退到它。

启动优先级:

显式启动目标(深链接/通知)
  → 可安全恢复的前台工作
  → 用户 Default App
  → chat Recovery App

5.4 前台焦点与 App 间切换

Interaction App 是默认的人与 Agent 交互入口,但不是全局调度器。Runtime 的 App OrchestratorTool RouterFocus Manager 负责决定 Agent 请求由哪个 App、哪个 交互模式或哪个标准组件承接。Interact 只通过 SDK 呈现当前会话并提交用户 Action。

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_failedhandler_failed 结果。

6. Runtime Tool Registry 与动态 Inventory

6.1 App Tool

App 可在 Manifest 中声明 Agent 可调用方法。当前 Tool 由 App Scope、局部方法和契约版本定位:

whiteboard/board.create@1
whiteboard/board.apply_diagram@1
voice/voice.request_recording@1

Runtime 内部使用结构化键,而不依赖字符串拼接:

type ToolKey = {
  app_scope: AppScope;
  method: string;
  contract_version: string;
};

每个 Tool 声明至少包含:

  • 标题、面向 Agent 的说明、输入/输出 JSON Schema
  • querycommandinteractiveoperation 四种调用模型之一;
  • 前台要求、超时、幂等规则和风险等级;
  • 是否需启动 App 实例、是否允许 Runtime 自动启动;
  • 该方法可能请求的 Capability。

6.2 可见性与 Inventory

Runtime 向 Agent 公布的工具不是安装包的全部声明,而是动态交集:

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 调用流程

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

标准终态错误码至少包括:

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:

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 消息分类

第一版类型分组:

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 筛选链

Transport 收到原始消息
  → 协议:版本、必填 app_scope/conversation_id、type、大小、schema
  → 身份:Agent、用户、会话关联
  → 去重/顺序:id、sequence、cursor
  → App:安装、启用、版本、签名、Host 兼容性
  → Tool/CapabilityInventory、方法、参数、策略、前台条件
  → Scopeconversation、instance、operation 所属关系
  → SubscriptionApp Manifest 声明与 SDK 订阅交集
  → PersistRuntime Event / App Inbox / cursor
  → Deliver:投递给目标 App 的 SDK

Runtime 不对所有 App 广播原始消息。一个白板 App 即使与 Chat 位于同一 conversation,也只能收到其 Manifest 声明且 Runtime 授权的实例 patch、Tool 调用或事件。

8. Runtime SDK v1

8.1 双通道模型

InboundRuntime → App
  - 已验证 Agent 消息
  - App 专属状态投影
  - Tool 调用
  - Runtime / App 生命周期

OutboundApp → Runtime
  - 用户与 App 声明性 Action
  - Tool result / progress / error
  - Surface Event
  - Capability request
  - 可恢复 State Snapshot

顶层接口:

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、状态与生命周期

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;
}

生命周期包含 startforegroundbackgroundsuspendrestoreclosing。App 可以保存快照并请求延迟关闭,但 Runtime 保留禁用、移除、内存回收和强制收口的最终权力。

8.3 Agent 消息订阅与可靠 Inbox

SDK 提供实时订阅,同时提供持久化 Inbox 补读:

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 先验证并持久化,再回调 App;
  2. 每条消息有唯一 message_idApp 必须幂等处理;
  3. 展示类消息可自动确认;Tool 调用、状态 patch 等业务消息需 App 显式 ACK;
  4. App 未运行、暂停或崩溃时,Runtime 写入该 App Inbox;恢复后通过 list()subscribe() 补齐;
  5. App 禁用、移除或不兼容时,Runtime 不静默投递或丢弃关键调用,而向 Agent 返回标准拒绝。

App 的订阅条件只是请求;实际投递集为:

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

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>;
  background(instanceID: AppInstanceID, reason?: string): Promise<void>;
  suspend(instanceID: AppInstanceID, reason?: string): Promise<void>;
  close(instanceID: AppInstanceID): Promise<void>;
  openDefaultApp(): Promise<void>;
}

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 管理的作用域隔离存储:

app-data/chat/
app-data/app-registry/
app-data/voice/
app-data/whiteboard/

SDK 中的 storage 提供 JSON 数据和可恢复 snapshotRuntime 负责配额、升级迁移、禁用和移除时的清理。Capability 必须通过统一请求接口:

interface CapabilityRequestAPI {
  request<T extends JsonValue>(request: {
    capability: CapabilityName;
    purpose: string;
    input: JsonValue;
    scope?: AppScope;
  }): Promise<CapabilityResult<T>>;
}

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 中固化供应商身份或全局命名空间:

{
  "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 至少包含:

identity       用户、设备、认证会话
connection     AppServer 状态、cursor、重试、outbox
conversations  Agent 映射、消息引用、任务、交互、Artifact 元数据
apps           App Registry、默认 App、运行实例、App Inbox
tools          已声明 Tool、可见性、调用与 operation
capabilities   授权、执行状态、最小审计

第一版采用“事件驱动状态机 + 必要快照”,而非完整 Event Sourcing:关键入站事件、用户决定、Tool 结果、outbox 和审计记录持久化;渲染细节和短暂 UI 状态不必全部写入事件日志。

Runtime 生命周期:

created → restoring → authenticating → synchronizing → online
                                      ↘ reconnecting / offline_degraded
online / offline_degraded → stopping → stopped

启动时恢复 App Registry、默认入口、会话 cursor、outbox、App Inbox、未完成 Tool 和可恢复实例;追平历史后再开始实时投递。离线时用户/App Action 进入 outbox,重连后按幂等键和顺序处理。

12. 推荐工程边界

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 边界;
  • 定义 LineUpAppRuntimeSDKSurface 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 回归行为。

R2App Registry Core App

  • 将现有开发期 SurfaceRegistry 升级为 Runtime App Registry
  • 实现 Core App 记录、Installed App 记录、enable/disable/remove 和默认 App 选择;
  • 将 Registry UI 实现为 app-registry,仅调用 RuntimeAppManager
  • App 状态变化后正确更新 Runtime Inventory。

R3Tool 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 通道,而不是再实现独立通信链路。

硬性验收:

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 层架构方案 中的 Interaction Runtime 从“聊天 Host 内部模块”收敛为整个 App 的 Runtime,并补充了 App Manager、App Tool Registry、SDK 和消息路由模型。
  • 本文不废弃 UI Surface 与 App Capability 协议 中已完成的 Surface 隔离、Capability 确认、生产 Bundle 验签和动态 inventory 原则;后续应将其协议字段迁移/扩展为本文定义的 Runtime Envelope、App Manifest 和 Tool Registry,而不能引入绕开 Runtime 的平行通道。
  • 现有 M2/M4 文档和实现使用的 app id 是当前 Surface 协议的实现字段。本方案在 Runtime 重构阶段以 app_scope 作为本地路由字段;供应商身份和全局命名空间将在后续生态阶段通过独立、版本化的兼容设计重新引入。
  • 当前 M0M4 实现可作为 Runtime 的迁移基础,但其现有文件边界不是最终 Runtime/App/SDK 边界。