MoonViz 使用文档

本文覆盖引擎的全部对外集成面:CLI 行协议、Node SDK、MCP Server 与 Agent SKILL。所有路线共享同一份 .mbt.md 事实源与同一套双 Gate 校验。

总览

MoonViz 是用 纯 MoonBit 实现的原型设计基础引擎。核心不变量:

  • 单一事实源 —— 一份 .mbt.md(MoonBit literate 源码)就是整个项目。引擎不维护第二份状态。
  • 双路线编辑 —— 人类画布操作与 Agent 修改都回写同一源文件;导出分 export-mbt-human / export-mbt-agent 两个 Gate。
  • 预览从源重建 —— 任何视觉输出(SVG / 画布)都是对源的即时渲染,不存在旁路缓存。
  • 加密分发 —— 文档以 DDP 容器交付:DDP1 加密(Argon2id + XChaCha20-Poly1305)或 DDP2 免密(zstd + CRC32)。
引擎目录结构:core/(内核)· cli/(行协议 CLI)· mcp/(MCP Server)· decl/(声明库)· ddp/(Rust 编解码器)· sdk/node/(Node SDK)· playground/(实验场)· SKILL.md(Agent 技能)。

快速开始

前置条件

  • MoonBit 工具链:需要 moon 可执行文件(~/.moon/bin/moon 或 PATH 中)。
  • DDP 加解密需先构建 Rust 工具:cd moonviz/ddp && cargo build --release(产物 ddp/target/release/ddp_codec)。

跑通第一条链路

cd moonviz

# 有状态会话:stdin 一行命令 → stdout 一行 JSON
moon run --target native cli

# 会话内:
template login t_login 390 844        # 从模板建画板
update t_login welcome_title text="欢迎回来"
flow t_login t_home login_btn         # 点击 login_btn → 跳转 t_home
export-mbt-human                       # HumanGate 校验,返回 canonical .mbt.md
exit

每条命令返回一行 JSON:{"ok":true,...};导出命令额外携带 mbt(完整源码)、flows、artboards 等字段。

无会话渲染 / 校验

# 渲染(AgentGate 级重载:MBT 完整重建)
render-mbt-b64 <base64(mbt)>
# → {"ok":true,"entry":"t_login","flows":[...],"artboards":[{id,width,height,svg,nodes}]}

# 只校验不渲染
validate-mbt-b64 <base64(mbt)>
# → {"ok":true,"entry":...,"revision":...,"blockKinds":{...}}

CLI 行协议

协议约定:换行分帧 JSON——stdin 每行一条命令,stdout 每行一个 JSON 值。一个 CLI 进程 = 一个有状态 Project 会话;exit 或 stdin EOF 结束会话。

moon run --target native cli      # 在引擎根目录(含 cli/moon.pkg)执行

会话内命令(有状态)

命令说明
template <tplId> <name> <w> <h>从内置模板实例化画板(登录页、仪表盘、Web 落地页、桌面应用等 14 个完整页面模板)
create <name> <w> <h>新建空白画板
duplicate <src> <newName>复制画板
delete-artboard <id>删除画板(至少保留一个,引擎侧校验)
update <artboard> <node> k=v …更新节点属性(text/fill/x/y/w/h/radius/opacity/tracking…;字符串用 JSON 引号)
place <ab> <comp> <id> [variant|-] [x] [y] [w] [h] [k=v…]放置组件实例,一步指定最终尺寸(门在最终 bbox 评估)
move <artboard> <node> <x> <y>移动节点
copy <artboard> <node> <newId> <dx> <dy>复制节点
flip <artboard> <node> h|v|both|none翻转
reorder <artboard> <node> front|back|up|downZ 序调整
group / ungroup / align编组 / 解组 / 对齐
flow <from> <to> <triggerNode>建立交互流(tap 触发跳转)
resize-canvas / restyle / theme画布尺寸 / 重排版式 / 主题
collab-merge多 Agent 三方合并(OT 冲突检测,规格:<base_rev> <agent>=<op>[+op...])
history设计版本控制:init / commit / log / undo / redo / checkout / diff
anim-css / anim-list预设动画 CSS(6 预设)/ 预设清单
protest原型测试脚本(tap:x:y>board; back>board; noviol; render)
export-mbt-humanHumanGate 导出 canonical .mbt.md(结构违规硬阻断)
export-mbt-agentAgentGate 导出(语义级校验)
export-svg / export-artifact / export-decl导出 SVG / 工件 / 声明物料
list-templates / list-components / list-themes / list-tokens枚举模板 / 组件(65 组件 × 115 变体)/ 主题 / 设计 token
constrain <ab> <intent>布局意图:居中|垂直居中|垂直排列|水平排列|等宽|等高|等间距|网格 N|顶部|底部|放大 N|缩小 N|边距 N|间距 N(层级/z-order 走 reorder;全包含背景直通)
lint / critique / infer设计 Lint / AI 设计批评 / 布局推理
responsive / spec / benchmark响应式断点 / 设计标注 / 性能基准
list-ops26 条 mutating op 字典(usage/分类/双门禁)
help / list-tools / exit帮助 / 53 工具字典 / 退出

无会话命令(单发)

命令说明
render-mbt-b64 <b64>完整渲染:返回全部画板 SVG + 交互流 + 入口
validate-mbt-b64 <b64>仅校验:返回 entry / revision / blockKinds
apply-human-mbt-op-b64 <mbt> <op>Human 操作:输入 MBT + 操作(JSON),返回新 canonical MBT + 渲染
apply-agent-mbt-op-b64 <mbt> <op>Agent 操作:同上,Gate 为 AgentGate
load-mbt-b64 <b64> / canonical-mbt-b64载入 / 规范化 MBT
为什么用 base64? MBT 源码是多行 Markdown,用 base64 编码后可安全塞进单行帧,避免换行分帧歧义。

Node SDK(@moonviz/engine-sdk)

SDK 是纯传输 / 编排层:拉起 CLI 子进程、编码命令、解析 JSON 行——不缓存、不建第二事实源。要求 Node ≥ 18,ESM。

import { MoonViz, Project, DDP, build } from '@moonviz/engine-sdk';

// 1. 引擎客户端(moonvizDir 指向引擎根,含 cli/moon.pkg)
const engine = new MoonViz({ moonvizDir: '../moonviz' });

// 2. 低层:直接下发一批命令(同一会话)
const templates = await engine.run(['list-templates']);

// 3. 高层:Project 构建器(累积命令,导出时一次执行)
const mbt = await build(engine, p => {
  p.template('login', 't_login', 390, 844);
  p.template('dashboard', 't_home', 390, 844);
  p.update('t_login', 'welcome_title', { text: '欢迎回来' });
  p.flow('t_login', 't_home', 'login_btn');
});                       // → canonical .mbt.md 文本

// 4. 渲染(AgentGate 重载)
const r = await engine.render(mbt);        // { ok, entry, flows, artboards }

// 5. 双 Gate 操作
const r2 = await engine.applyHumanOp(mbt, op);   // Human 编辑
const r3 = await engine.applyAgentOp(mbt, op);   // Agent 编辑

// 6. DDP 容器
const { bytes } = await DDP.encrypt(mbt, 'pass');   // DDP1 加密
const free = await DDP.encrypt(mbt, '');            // DDP2 免密
const back = await DDP.decrypt(free.bytes);         // → { mbt }

API 一览

导出说明
MoonViz引擎会话类:run(cmds) / last(cmds) / render / validate / applyHumanOp / applyAgentOp / apply / create
能力字典 / 清单tools()(53 工具含 inputSchema)/ ops()(26 op)/ listTemplates() / listComponents() / listThemes() / listTokens() —— 与 MCP tools/list、CLI list-tools·list-ops 同源
导出exportSvg(mbt, artboard) / exportHtml(mbt)(自包含可交互原型)
Project构建器:template/create/duplicate/deleteArtboard/update/move/flip/reorder/copy/flow/exportHuman + theme/token/interact/state/setState/exportHtml
Session有状态 CLI 会话(与 wasm 会话面对齐):open/exec/apply/lint/critique/autoFix/constrain/interactions/states/queryNodes/flows/spec/protest/collabMerge/animationCss/history/exportMbt/close —— constrain 为自然语言布局意图
DDPencrypt(mbt, password, {codecPath, moonvizDir}) / decrypt(bytes, password)
build(engine, recipe)一次性构建工厂
encodeProps(props)属性对象 → CLI k=v 片段
EngineError引擎 {ok:false} 响应异常(error 错误码 + detail 原始响应)

自检:cd moonviz && node sdk/node/test/selftest.mjs —— 覆盖 模板 → 操作 → 交互流 → 导出 → 渲染 → DDP1/DDP2 往返 + 能力对齐面(tools/ops/themes/tokens/exportHtml)。

WASM SDK(moonviz-engine-wasm)

引擎的 WebAssembly GC 构建:渲染与校验管线跑在进程内 wasm 实例里——零工具链、零子进程、零服务器。通过 JS String Builtins,MoonBit String 与宿主字符串直接互通。API 面:render / validate / applyOp(双门禁)/ exportHtml / listComponents / listTemplates / listThemes / listTokens / listOps,以及会话面 sessionOpen/sessionApply/sessionConstrain/sessionAutoFix/sessionGenerateResponsive/sessionTap/sessionSave(i32 句柄;改文档面成功信封带 canonical mbt,宿主须保存供下次 open 用)。

classic 字符串 ABI 已契约化:对象布局双判别式、UTF-16LE 编码、槽协议全文档见 docs/wasm-abi.md,CI 断言防漂移。

标准 wasm 产物(宿主中立):moon build --target wasm 产出纯 WASM MVP 模块(线性内存、0 imports、(i32)->i32 签名、导出 memory)——不依赖任何宿主特定提案,wasmtime/wasmi 等任何规范运行时均可实例化。字符串 ABI:对象 = [4B refcnt][4B header][len×UTF-16LE],header = (kind<<30)|(shift<<28)|len。

环境要求

宿主最低版本
Node.js22(V8 WasmGC shipping)
Chrome / Edge119+
Firefox120+
Safari18.2+

用法

import { createEngine } from 'moonviz-engine-wasm';

// Node:自动读包内 dist/moonviz.wasm
const engine = await createEngine();

// 浏览器:传入 Response
// const engine = await createEngine(fetch('/assets/moonviz.wasm'));

const view = engine.render(mbt);      // 同步、进程内
// { ok, entry, flows, artboards: [{ id, width, height, svg, nodes }] }
const check = engine.validate(mbt);
// { ok, entry, revision, blockKinds }

双产物选型

wasm-gc 产物(本包)classic 标准产物moonviz-engine-sdk
标准WASM GC + JS String Builtins(提案仅 JS 引擎实现)纯 WASM MVP(跨平台、宿主中立)进程外 CLI 协议
可运行宿主浏览器 / Node ≥22wasmtime / wasmi 等任意规范运行时Node ≥18
能力面一致:render / validate / 双 Gate applyOp / exportHtml / 五个清单 API全量 CLI:会话 / 编辑 / 交互流 / 双 Gate 导出 / DDP
字符串 ABI宿主内建字符串直通线性内存对象:[4B refcnt][4B header][len×UTF-16LE]JSON 文本协议
DDP 加解密✗✗✓(Rust codec 独立交付)

构建产物(两种均在 wasm/moon.pkg 配置导出面,各 71 个:27 个 session_* 会话 API + 25 个 _in 槽变体 + 19 个无状态/清单 API;classic 另含 memory):

moon build --release --target wasm-gc wasm   # JS 宿主 → 拷贝到 sdk/wasm/dist/moonviz.wasm
moon build --release --target wasm wasm      # 标准 MVP → _build/wasm/release/build/wasm/wasm.wasm

classic 产物已接入 GitHub Actions:engine-v* tag 触发的构建会在 GitHub Releases 归档全量产物——4 平台二进制 tarball + 双 wasm 构建(版本化命名 moonviz-wasm-gc-<ver>.wasm / moonviz-wasm-classic-<ver>.wasm)+ 集成包 tarball(SDK / wasm 绑定 / MCP 启动器 / Skill,版本由 CI 统一盖戳)。分发仅走 GitHub Releases。classic 读取方向 ABI:返回值 i32 为字符串对象指针,长度位于 ptr-4(u32),UTF-16LE 数据从 ptr 开始;入参方向的 _in 槽变体(arg 槽协议)已全量落地。会话 API(27 个 session_*,i32 句柄)与 CLI 会话能力对齐:apply_agent 走 AgentGate(违规返回 mbt_gate_block)、已关句柄返回 invalid_session_handle、只读导出统一 {ok,data} 信封、save 快照可经 session_open_project_json 回灌、session_count 观测泄漏、session_history 提供产品内撤销/时间旅行(undo/redo/checkout 响应回传 canonical mbt,与 apply 契约同形)。改文档会话面(session_apply_agent/human、session_constrain、session_auto_fix、session_generate_responsive、session_tap、session_component_compile_b64)成功信封一律回传 canonical mbt("mbt" 字段):按 canonical 交换的宿主必须保存返回文本供下次 session_open 使用,否则变更在重开后静默丢失。版本号自 core/version.mbt 单一常量注入,与 CI 的 MOONVIZ_VERSION 硬门校验一致;全部产物(含集成包)统一盖同一基线版本戳。

MCP Server

mcp/ 是标准 stdio JSON-RPC MCP Server,可直接接入 Claude Desktop、ZCode、Cursor 等任何 MCP 客户端。

引擎同时上架 mooncakes.io(MoonBit 官方包中心):moon add asdshuaishuai/moonviz 后经 sdk/ 门面(@sdk.new/apply/validate/render_svg/canonical)在 MoonBit 工程内直接内嵌引擎。

客户端配置

{
  "mcpServers": {
    "moonviz": {
      "command": "moon",
      "args": ["run", "--target", "native", "mcp"],
      "cwd": "/path/to/moonviz"
    }
  }
}

工具清单(52 个,节选;完整机器可读字典见 tools/list 或 moonviz-tools.json)

工具类别说明
initialize会话初始化项目会话,返回引擎能力清单
read_mbt源侧读取当前 canonical .mbt.md(源侧唯一读入口)
render_mbt源侧从源渲染全部画板 SVG + 交互流
list_artboards / list_templates / list_components / list_themes / list_tokens枚举画板 / 模板 / 组件 / 主题 / token
apply_template / apply_theme / set_token应用实例化模板 / 切换主题(角色重着色,可逆)/ 覆盖单个颜色令牌
interact / define_state / set_state / list_states交互⚡trigger→action 绑定 / 状态补丁 / 当前状态([cur:] 持久化)/ 状态清单
export_html / export_svg导出自包含可交互 HTML 原型(节点级导航/状态切换/toast)/ 单画板 SVG
collab_merge协作多 Agent 三方合并:OT 冲突检测 + 自动解决
history版本设计版本控制:时间旅行 / 提交日志 / 语义 diff
animation_presets / animation_css动画6 预设清单 / 节点 CSS @keyframes 生成
protest测试原型测试脚本(断言式:导航/输入/渲染/违规)
list_ops字典26 条 mutating op 机器可读字典(usage/category/gates)
lint_design / auto_fix质量设计 Lint 与自动修复
critique智能AI 设计批评(启发式规则集)
infer_page_type / infer_missing智能页面类型推断 / 缺失元素推断
extract_design_system智能从既有画板反向提取设计系统
generate_spec / generate_responsive生成开发移交标注 / 响应式断点变体
place_component结构放置组件实例(variant/x/y/w/h/args——w/h 一步最终尺寸,门在最终 bbox 评估)
update_node / move_node节点编辑修改任意节点属性(30+ 键,含 align/italic/dash/visible/layout/name)
group_nodes / ungroup_node / align_nodes结构打组 / 解组 / 多节点对齐
resize_canvas / restyle_component结构画板缩放(约束重排)/ 主组件样式传播
interact / uninteract / interactions交互注册(10 触发器 × 9 动作)/ 清除 / 结构化回读
define_state / set_state / list_states组件状态多态状态补丁 / 激活切换 / 清单
export_svg / export_artifact导出SVG / 工件导出
benchmark性能渲染性能基准
ddp_view分发DDP 容器只读元数据(不暴露变更路径)
源侧边界:read_mbt 与 render_mbt 是源侧读写入口;ddp_view 严格只读。变更一律走带 Gate 校验的导出路径,杜绝旁路写入。

SKILL 技能(Agent 集成)

引擎根目录的 SKILL.md 是给 coding agent(ZCode / Claude Code / Codex 等)的操作规范。将引擎仓库加入 Agent 可访问路径,或在技能目录中引用它,Agent 即可按规范安全驱动引擎。

SKILL 约定的核心规范

  • 事实源纪律:任何修改必须回写 .mbt.md,禁止只改画布或只改内存态。
  • 双 Gate 语义:模拟人类操作用 Human 路线(结构违规硬阻断);程序化批量修改用 Agent 路线(语义级校验 + debt 记账)。
  • 操作入口:优先 MCP 工具;无 MCP 环境时退回 CLI 行协议;Node 宿主用 SDK。
  • 渲染即验证:每次修改后用 render_mbt / render-mbt-b64 重建视觉并比对预期。
  • 红线:不缓存渲染结果、不绕过 Gate 导出、不直接改 DDP 二进制。
# 在 Agent 技能目录中挂载(示例:软链 SKILL.md)
ln -s /path/to/moonviz/SKILL.md ~/.zcode/skills/moonviz/SKILL.md

Studio 与 Viewer

deepDesign Studio(Tauri,人类路线)

仓库 moonviz-demo-tauri。macOS 原生体验的画布编辑器:模板快速起步、双 Gate 编辑、MBT 源码视图、线框/高保真切换、Agent 协作面板。导出即 .mbt.md / DDP。

cd moonviz-demo-tauri
cargo tauri dev      # 开发
cargo tauri build    # 打包 .app / .dmg

ddpView(macOS 原生,只读查看器)

仓库 ddpView-mac。SwiftUI + AppKit 的 DDP 文档查看器:解密(DDP1/DDP2)→ 校验 → 渲染画板 → 点击交互区跳转。全程只读。

cd ddpView-mac
swift build -c release && ./make-app.sh    # 产出 ddpView.app
./run.sh [file.ddp]                        # 启动(自动定位相邻 moonviz/)
ddpView.app/Contents/MacOS/DDPView --selftest <file.ddp> [<pwd>]   # 无头自检

绘制方案与渲染管线

一份 .mbt.md 变成像素的完整链路(详见 docs/10 完整技术文档):

.mbt.md ─①声明加载→ 场景图 Document ─②两遍法布局求解→ 绝对矩形
        ─③P0–P4 谓词 + 双 Gate 验收→ ┬─ SVG(系统字体栈/elevation 阴影/渐变)
                                   ├─ PNG(2x 超采样 AA + 纯 MoonBit DEFLATE)
                                   └─ 终端 ANSI 真彩画布(Camera/pick 拖拽)
任意宿主后端(Canvas/Skia/OpenGL)经 RenderPlan 显示列表接入
后端实现特性
SVGcore/svg.mbt 字符串构建系统字体栈、e1–e3 阴影令牌、linear:/radial: 渐变、多行文本基线公式;Studio/查看器/WASM SDK 共用
PNGplayground/render2+png+deflate 自研软光栅2x 超采样抗锯齿、圆角扫描线、5×7 位图字体、fixed-Huffman DEFLATE(产物小 5–20 倍),零图像库
终端playground/canvas.mbtANSI 真彩字符栅格、相机平移缩放、pick_at 命中支持拖拽编辑
RenderPlancore/runtime.mbt后端无关显示列表 + 事件协议,宿主只实现解释器

二进制分发与工具链风险

预编译二进制(CLI 1.26MB / MCP 1.10MB)自包含、仅链系统 libc——moon 工具链只存在于编译时。MCP 走 npx moonviz-mcp 平台包;Node SDK 安装 moonviz-bin-<platform> 后自动发现预编译 CLI(或 MOONVIZ_CLI_BIN),全程零工具链。CI 与 Pages 构建使用 latest 工具链(历史锁定版本目录会从下载 CDN 下架),每次构建以全量 `moon test` + CLI/MCP 冒烟挡板验证;已发布产物永久冻结不受影响。平台 tarball 同时归档于 GitHub Releases(engine-v* tag)——分发不依赖 npm 单渠道。

DDP 容器(Rust ddp_codec)

DDP 是文档分发格式,由引擎仓库内独立的 Rust 工具 ddp_codec 编解码。协议:stdin 单行 JSON → stdout 单行 JSON。

格式构成用途
DDP1Argon2id 密钥派生 + XChaCha20-Poly1305 AEAD带密码加密分发;错密码 → 认证失败
DDP2zstd 压缩 + CRC32 完整性校验(无加密)免密场景:预览、CI、演示
# 加密(DDP1)
echo '{"operation":"encrypt","mbt_b64":"…","password":"p@ss"}' | ddp_codec
# → {"ok":true,"ddp_b64":"…"}

# 免密(DDP2):password 传空串
echo '{"operation":"encrypt","mbt_b64":"…","password":""}' | ddp_codec

# 解密
echo '{"operation":"decrypt","ddp_b64":"…","password":"p@ss"}' | ddp_codec
# → {"ok":true,"mbt_b64":"…"}

环境变量

变量作用回退顺序
MOONVIZ_DIR引擎根目录(须含 cli/moon.pkg)参数 moonvizDir → 环境变量 → 自动向上查找(SDK)/相邻目录启发(Viewer)
MOONVIZ_MOON / MOONmoon 可执行所在目录→ PATH → ~/.moon/bin/moon → /opt/homebrew/bin/moon
MOONVIZ_DDP_HELPERddp_codec 完整路径→ <moonviz>/ddp/target/{debug,release}/ddp_codec

深度文档(仓库 docs/)

#文档内容
01architecture分层架构与红线
02mbtmd-format.mbt.md literate 源码格式
03scene-graph场景图模型
04layout-and-predicates布局谓词与推理
05sync-pipeline双向同步管线
06renderSVG 渲染管线
07agent-loopAgent 循环与双 Gate
08roadmap-risks路线图与风险
09rendering-ecosystem渲染生态位