Image / video labeling backend for the MoonBit Labeler app: 27 async ops over @fs/@json for folder browsing, image IO, label IO, schema normalization (parse/serialize round-trip), class management (including the class rename), per-frame video labels, and VOC/YOLO/COCO export. The op_handlers are pure async MoonBit functions and can be wired into any IPC layer (Proton/CEF, stdio JSON-RPC, HTTP, WASM, custom bridge). Includes a `pub async fn dispatch_op(op : String, payload : Json) -> Json` entry point (in `extensions/labeler`) for embedding outside the CEF runtime; the package is native-only, so a consuming package must declare `supported_targets = \"native\"`.

moon install moonbit-community/proton_cli@0.9.0which drops it in ~/.moon/bin. Pin the version to the one in
moon.mod: all published Proton modules use one lockstep version, so
an unpinned install floats to the newest release and silently drifts
out of lockstep. See https://github.com/moonbit-community/proton.# From the project root:
moon install moonbit-community/proton_cli@0.9.0 # the CLI itself
moon update # sync moon.mod deps
proton_cli setup # download the CEF runtime
cd frontend && npm install && cd .. # Vite + frontend depsproton_cli build -- --release
# output: target/proton-dist/moonbit-labeler/moonbit-labeler.exeproton_cli package --format app
# output: target/proton-dist/moonbit-labeler/moonbit-labeler.exe
# plus the CEF runtime beside it (libcef.dll, *.pak, ...)cd target/proton-dist
tar -a -cf moonbit-labeler-0.2.16.zip moonbit-labelermoon test --target native # 85 tests (blackbox + unit)
node frontend/qa/webkit_picker_blackbox.test.mjs # frontend blackbox
# The async half of the IPC (the class rename and the video path) is
# covered by Node scripts that drive the real --stdio bridge. They need an
# executable with the CEF runtime beside it, i.e. the packaged app:
node tests/stdio/class_revision_stdio_blackbox.test.mjs \
target/proton-dist/moonbit-labeler/moonbit-labeler.exe
node tests/stdio/video_stdio_blackbox.test.mjs \
target/proton-dist/moonbit-labeler/moonbit-labeler.exe --expect-ffmpeg# launch the packaged exe (it picks CEF mode if libcef.dll is present,
# --stdio mode if not — see _build/run.bat for the full wrapper):
_build/run.bat
# OR drive the labeler backend over JSON-RPC without launching CEF:
target/proton-dist/moonbit-labeler/moonbit-labeler.exe --stdio
# ...then send one JSON object per line on stdin, read responses on stdout..
├── app/ # runnable entry (CEF + stdio)
├── extensions/labeler/ # 27 IPC ops + label/VOC/YOLO/COCO pipeline
├── frontend/ # Vite + vanilla-JS UI (built into the exe at pack time)
├── moon.mod # deps: proton@0.9.0, proton_contract@0.9.0, moonbit_image@0.3.9 (async comes from the builtin moonbitlang/core)
├── proton.project.json # identifier, frontend, package (output dir, formats, version)
└── AGENTS.md # setup + commands + smoke-test recipe (read first)pub async fn dispatch_op(op : String, payload : Json) -> Jsonmoon add riantr/moonbit_labeler@0.2.16import {
"riantr/moonbit_labeler@0.2.16",
}# cmd/main/moon.pkg
import {
"riantr/moonbit_labeler/extensions/labeler",
"moonbitlang/core/async",
"moonbitlang/core/json",
}
supported_targets = "native"
pkgtype(kind: "executable")
options(
"allow-experimental-packages": [ "moonbitlang/core/async" ],
)// cmd/main/main.mbt
///|
async fn main {
let ops = @labeler.dispatch_op_list()
println("op count = " + ops.length().to_string())
// `dispatch_op` is async and raises, so the error is handled here rather
// than letting `main` raise.
let text = @labeler.dispatch_op(
"list_images",
@json.parse("{\"path\":\"C:/some/images\"}"),
).stringify() catch {
_ => "dispatch failed"
}
println(text)
}fn async_package_anchor() -> Boolasync fn fs_package_anchor() -> Boolfn image_package_anchor() -> Boolfn labeler_package_anchor() -> Boolfn ref_package_anchor() -> BoolInstall
Download zipImage / video labeling backend for the MoonBit Labeler app: 27 async ops over @fs/@json for folder browsing, image IO, label IO, schema normalization (parse/serialize round-trip), class management (including the class rename), per-frame video labels, and VOC/YOLO/COCO export. The op_handlers are pure async MoonBit functions and can be wired into any IPC layer (Proton/CEF, stdio JSON-RPC, HTTP, WASM, custom bridge). Includes a `pub async fn dispatch_op(op : String, payload : Json) -> Json` entry point (in `extensions/labeler`) for embedding outside the CEF runtime; the package is native-only, so a consuming package must declare `supported_targets = \"native\"`.