ZorvAI · GenUI 技术构架与功能介绍

1 阅读7分钟

ZorvAI · GenUI 技术构架与功能介绍

版本:v1.0.89 / 2026-09-12 开源地址:github.com/Quor-a/Zorv… 本文基于当前源码(commit 1fefa2f)编写,覆盖「全屏 GenUI 模式」与「返回 ZorvAI 对话框」修复后的真实架构。


一、GenUI 是什么

GenUI 是 ZorvAI 内置的**「生成式界面」(Generative UI)**能力:用户用一句话下指令,AI 不只是回一段文字,而是 直接生成一整个可交互的 HTML 界面(仪表盘、卡片、表单、图表、工具面板……),整屏即 AI 的回复。

它在 ZorvAI 里有 两条集成路径,二者共享同一套渲染引擎与工具系统,但承载位置不同:

路径承载位置入口状态
① 全屏模式与文本对话框平级的整屏生成器QuroGenUiApp / GenScaffold主推,本文重点
② Surface 变体嵌在普通对话里的画布GenUiSurfaceScreen + QuroChatViewModel.generateGenUi历史兼容,已并入主对话管线

切换方式:对话框控制条把会话类型切到 genuiQuroMainScreen 改挂 QuroGenUiApp 全屏界面。


二、整体架构总览

graph TB
    subgraph App["ZorvAI :app 主模块"]
        VM["QuroChatViewModel\n(pushGenUiHtmlToChat)"]
        Main["QuroMainScreen / QuroApp\n会话类型 genui ↔ normal"]
        Tools["ZorvAI 完整工具系统\nbuildQuroRegistry + QuroToolEngine\n(终端/ACI/MCP/CMS/Linux/屏幕/文件/记忆/经验/动态UI)"]
        Memory["QuroMemoryRepository\n(共享记忆 quro_memory.json)"]
        ModelCfg["QuroModelConfigRepository\n(共享模型配置)"]
        Perm["QuroPermissionHolder\n(工具执行权限把关)"]
    end

    subgraph Genui["ZorvAI :genui 库模块(全屏模式)"]
        Entry["QuroGenUiApp\n全屏入口"]
        Scaffold["GenScaffold\n界面壳 / 状态机 / 时间线 / 界面栈"]
        Loop["AgentLoop\n决策轮 + 渲染轮"]
        Adapter["ZorvToolAdapter\n工具适配层(委托 ZorvAI)"]
        Canvas["GenUiCanvas\nWebView 渲染引擎 + MoBridge"]
        Stores["GenStore / SoulStore / ToolGate / AgentMemory\n(三子系统,已对接共享存储)"]
    end

    Main -->|genui 类型| Entry
    Entry --> Scaffold
    Scaffold -->|generate| Loop
    Loop -->|工具调用| Adapter
    Adapter -->|declarations/execute| Tools
    Adapter -->|记忆| Memory
    Adapter -->|执行权限| Perm
    Loop -->|流式 HTML| Canvas
    Scaffold -->|onDone 回写| VM
    VM -->|miniapp 围栏消息| Chat["ZorvAI 对话框气泡\nMsgBlock.MiniApp WebView"]

    Stores -.->|模型配置| ModelCfg
    Stores -.->|记忆| Memory
    Stores -.->|权限偏好| Perm

模块边界铁律genui 是被 app 依赖的库模块,绝不能反向依赖 app。跨模块一律用 函数型回调 / 接口genui 声明、app 实现),例如 onPushToChat: (html, title) -> Unit, GenUI 不 import QuroChatViewModel


三、分层文件索引

入口与界面壳

  • genui/app/QuroGenUiApp.kt —— 全屏模式根 Composable,含设置子页路由(灵魂/记忆/权限/模型/设置)。
  • genui/app/ui/shell/GenScaffold.kt —— 核心界面壳:画布状态机(决策/工具/等待/渲染/完成/失败)、思考时间线、 界面栈、历史浏览、三种原生叠加层(XML / Compose / Canvas)。generate() 启动 AgentLooponDone 触发回写。

智能体主循环

  • genui/app/agent/AgentLoop.kt —— 两阶段 Agent 循环(决策轮 + 渲染轮),结构化事件流 AgentEvent
  • genui/app/agent/Soul.kt —— 灵魂卡(AI 自动孵化的人格 + 视觉签名),注入渲染轮提示词。
  • genui/app/agent/AgentMemory.kt —— 记忆库,委托 QuroMemoryRepository(group=genui)。
  • genui/app/agent/ToolGate.kt —— GenUI 权限策略存储(L1–L5),落点 SharedPreferences("quro_genui_toolgate")
  • genui/app/agent/tools/ZorvToolAdapter.kt —— 工具适配层,把工具整体对接 ZorvAI 完整工具系统。
  • genui/app/agent/tools/BuiltinTools.kt —— GenUI 原生私有小工具集(已弃用,保留参考)。

模型与协议

  • genui/app/llm/LLMClient.kt / FastClient.kt —— 主模型通道 / 快速模型预检通道。
  • genui/app/llm/Prompts.kt —— 系统提示词(灵魂 + 记忆索引 + 界面历史 + 输出契约)。
  • genui/app/llm/ProviderPresets.kt —— 供应商预设。
  • genui/app/store/GenStore.kt / ModelProvider.kt / QuroGenUiBridge.kt —— 本地存储 + 模型配置桥(← QuroModelConfigRepository)。
  • genui/app/store/Protocol.kt —— 协议枚举(OPENAI / 其他)。

渲染引擎

  • ui/genui/GenUiCanvas.kt —— 端上唯一渲染责任:WebView + __moHost MoBridge,流式 document.write
  • genui/app/render/A2UIRenderer.kt —— A2UI 渲染器(忠实移植)。
  • genui/app/render/XmlLayoutRenderer.kt / ComposeDescRenderer.kt / CanvasNativeView.kt —— 三种原生通道渲染。
  • genui/app/render/RenderChannel.kt / RuntimeRegistry.kt / CodeLangRegistry.kt —— 渲染通道分派、运行时注册、代码语言。

返回 ZorvAI 对话框(修复后)

  • ui/QuroChatViewModel.kt —— pushGenUiHtmlToChat(html, title):把 HTML 包成 ```miniapp 围栏写入当前会话。
  • ui/QuroMainScreen.kt —— 传 lambda onPushToChat = { html, title -> chatVm.pushGenUiHtmlToChat(...) }

四、生成时序(决策轮 + 渲染轮)

sequenceDiagram
    participant U as 用户
    participant S as GenScaffold
    participant L as AgentLoop
    participant T as ZorvToolAdapter
    participant Z as ZorvAI 工具引擎
    participant C as GenUiCanvas
    participant V as QuroChatViewModel

    U->>S: 输入指令
    S->>L: generate(prompt)
    L->>L: 决策轮(带 tools,OpenAI 协议)
    loop 模型自行决定查几轮
        L->>T: 声明工具(coreSpecs)
        L->>T: 调用工具(name, args)
        T->>Z: execute(QuroToolEngine)
        Z-->>T: 工具结果
        T-->>L: 回填上下文
    end
    L->>C: 渲染轮(流式 onHtmlDelta)
    C-->>U: 画布逐字绘制界面
    L->>L: onDone(full, title)
    S->>V: onPushToChat(full, title)
    V->>V: 写 miniapp 围栏消息 + commitCurrent
    V-->>U: ZorvAI 对话框出现 MiniApp 气泡

决策轮provider.protocol == OPENAI 才启用 function calling):

  • 系统提示强制「禁止写 HTML,只决定工具调用 / 回 NO_TOOLS」。
  • 工具轮数不腰斩:模型想查多少轮查多少轮,靠两道安全闸兜底—— ① 死循环检测(完全相同 tool+args 重复达到阈值);② 很宽松的总时长上限。
  • 工具结果回填上下文;模型自行收尾后进入渲染轮。

渲染轮(流式、不带 tools):

  • 全部上下文(含工具结果)折成 user 备注交给模型,逐字输出 <!DOCTYPE html> 文档。
  • 流式增量经 onHtmlDelta 实时 document.writeGenUiCanvas(截断在标签中间也安全)。
  • 灵魂卡视觉签名在此轮注入,决定 UI 美学方向。
  • 完成 document.close()onDone(full, title) 出口。

五、工具委派:对接 ZorvAI 完整工具系统

早期 GenUI 全模式用私有 BuiltinTools(~30 个小工具,与 ZorvAI 主对话是两套孤岛)。现已整体替换为 ZorvToolAdapter,对外暴露与 BuiltinTools 同形成员(declarations / execute / gateFor / gate / memory), AgentLoop 仅一行改动(BuiltinToolsZorvToolAdapter),决策轮/渲染轮逻辑零改动。

  • declarations()QuroToolRegistry.coreSpecs():主对话默认下发的完整工具集 (终端 / ACI / MCP / CMS / Linux 环境 / 屏幕控制 / 文件 / 记忆 / 经验 / 动态 UI 等)。
  • execute(name, args)QuroToolCallQuroToolEngine(registry).execute(...):droid-mcp 派发, 复用主对话同一套真实工具实现。
  • 权限:真正执行由 QuroToolEngine 内的 QuroPermissionHolder 把关(与主对话一致), ZorvGate 对决策轮一律放行,避免双重弹窗;GenUI 的 ToolGate(L1–L5)保留作「权限设置屏」数据落点, grantAlways 把偏好固化到共享 SP。
  • 记忆:仍用已对接的 AgentMemory(→ QuroMemoryRepository,group=genui)。

六、三子系统对接 ZorvAI 共享存储

GenUI 设置页的「记忆库 / 工具权限 / 模型服务」三个子系统,已从 GenUI 私有存储迁到 ZorvAI 共享域:

子系统原存储现对接隔离/落点
记忆库filesDir/gen/*QuroMemoryRepositorygroup=genui 隔离,确定性 id=genui:<key>
工具权限gen/toolgate.jsonSharedPreferences("quro_genui_toolgate")审计日志仍文件式 gen/audit.jsonl
模型服务GenUI 私有 GenStoreQuroModelConfigRepository固定 id=quro_main,与文本对话共用同一份配置

设计原则:三处均保持公共 API 签名不变,仅改底层落点,降回归风险。 ⇒ GenUI「模型服务」页直接编辑全应用共用的那份模型配置,不再需要进 GenUI 单独加供应商。


七、返回 ZorvAI 对话框(本次修复核心)

问题:GenUI 全屏生成完成后,整屏 HTML 只进自身画布 / 界面栈,从不回写 ZorvAI 文本对话框。 用户要的是「生成的东西出现在普通对话里,能翻回来看、能点开」。

修复GenScaffold.onDoneonPushToChat(full, title)):

  • ```miniapp 围栏包裹整屏 HTML,写一条 MsgBlock.MiniApp 气泡——复用既有小程序 WebView 渲染通路。
  • 关键技巧:裸 HTML 会被 parseBlocksisFullHtmlDocument 误判成 Code("html") 代码块(不渲染), 必须加 miniapp 围栏才能走 MiniAppWebView 真实渲染。
  • 跨模块用函数型回调:onPushToChat: (html, title) -> UnitGenScaffold/QuroGenUiApp 声明, QuroMainScreen 用 lambda 桥接 chatVm.pushGenUiHtmlToChatchatVm:app 内 QuroApp 单例)。
graph LR
    A[&#34;GenScaffold.onDone(full, title)&#34;] --> B[&#34;onPushToChat(full, title)&#34;]
    B --> C[&#34;QuroMainScreen lambda&#34;]
    C --> D[&#34;chatVm.pushGenUiHtmlToChat(html, title)&#34;]
    D --> E[&#34;store.add('```miniapp\\n'+html+'```')&#34;]
    E --> F[&#34;commitCurrent() 落盘 + 刷新 _messages&#34;]
    F --> G[&#34;对话框出现 MiniApp WebView 气泡&#34;]

已知取舍:MiniApp 气泡 WebView 不含 GenUI 的 /assets/runtimes(echarts/three…)与 __moHost MoBridge, 图表库/设备桥在气泡内可能不生效(HTML 结构仍渲染)。全屏画布仍是完整体验面,对话框气泡是「返回/预览」。 「一层一层」流式增量回写未做(onDone 一次性回写整屏)。


八、功能清单

生成能力

  • 一句话生成完整可交互 HTML 界面(仪表盘 / 卡片 / 表单 / 图表 / 工具面板)。
  • 两阶段 Agent:自主调研(工具调用)→ 流式渲染,工具轮数不腰斩。

工具与能力

  • 复用 ZorvAI 完整工具系统:终端、ACI、MCP、CMS、Linux 环境、屏幕控制、文件、记忆、经验、动态 UI。
  • 灵魂卡人格 + 视觉签名注入,决定生成界面的美学风格。

界面与交互

  • 画布状态机:决策 / 调用工具 / 等待授权 / 绘制 / 完成 / 失败,实时状态行。
  • 思考时间线:决策与工具全过程结构化呈现,含参数、耗时、结果摘要。
  • 界面栈:多次生成可翻看的历史浏览。
  • 三种原生叠加层:XML / Compose / Canvas(AI 声明通道时在画布上叠真实原生渲染)。
  • 深色模式:画布背景随 darkMode#0F1115 / #FCFAF5)。

设置子系统(已对接共享存储)

  • 灵魂 / 记忆库 / 工具权限 / 模型服务 四个单字直达设置页。
  • 模型服务与文本对话共用同一份配置。

与对话框联动

  • 全屏生成结果回写 ZorvAI 对话框为 MiniApp 气泡(可翻看、可点开)。
  • 历史界面可从界面栈或对话框气泡回放。

九、版本与发布


十、已知取舍与后续

  1. MiniApp 气泡运行时不完整:气泡 WebView 不含 GenUI /assets/runtimes 与 MoBridge, 图表库/设备桥在气泡内可能不生效。若要 1:1 还原,需让气泡复用 GenUiCanvas 资产加载器。
  2. 流式增量回写未做onDone 一次性回写整屏,未实现「一层一层」流式返回对话框。
  3. 模块边界genui 库模块不得反向依赖 app,跨模块一律函数型回调/接口。
  4. Surface 变体GenUiSurfaceScreen 已并入主对话管线,作为历史兼容保留。