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|down | Z 序调整 |
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-human | HumanGate 导出 canonical .mbt.md(结构违规硬阻断) |
export-mbt-agent | AgentGate 导出(语义级校验) |
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-ops | 26 条 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 |
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 为自然语言布局意图 |
DDP | encrypt(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.js | 22(V8 WasmGC shipping) |
| Chrome / Edge | 119+ |
| Firefox | 120+ |
| Safari | 18.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 ≥22 | wasmtime / 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 显示列表接入
| 后端 | 实现 | 特性 |
|---|---|---|
| SVG | core/svg.mbt 字符串构建 | 系统字体栈、e1–e3 阴影令牌、linear:/radial: 渐变、多行文本基线公式;Studio/查看器/WASM SDK 共用 |
| PNG | playground/render2+png+deflate 自研软光栅 | 2x 超采样抗锯齿、圆角扫描线、5×7 位图字体、fixed-Huffman DEFLATE(产物小 5–20 倍),零图像库 |
| 终端 | playground/canvas.mbt | ANSI 真彩字符栅格、相机平移缩放、pick_at 命中支持拖拽编辑 |
| RenderPlan | core/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。
| 格式 | 构成 | 用途 |
|---|---|---|
| DDP1 | Argon2id 密钥派生 + XChaCha20-Poly1305 AEAD | 带密码加密分发;错密码 → 认证失败 |
| DDP2 | zstd 压缩 + 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 / MOON | moon 可执行所在目录 | → PATH → ~/.moon/bin/moon → /opt/homebrew/bin/moon |
MOONVIZ_DDP_HELPER | ddp_codec 完整路径 | → <moonviz>/ddp/target/{debug,release}/ddp_codec |
深度文档(仓库 docs/)
| # | 文档 | 内容 |
|---|---|---|
| 01 | architecture | 分层架构与红线 |
| 02 | mbtmd-format | .mbt.md literate 源码格式 |
| 03 | scene-graph | 场景图模型 |
| 04 | layout-and-predicates | 布局谓词与推理 |
| 05 | sync-pipeline | 双向同步管线 |
| 06 | render | SVG 渲染管线 |
| 07 | agent-loop | Agent 循环与双 Gate |
| 08 | roadmap-risks | 路线图与风险 |
| 09 | rendering-ecosystem | 渲染生态位 |