Desktop app binaries (Windows x86-64, .zip and single-file .exe): https://github.com/riantr/moonbit-labeler/releases -- this module is the backend only. 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\"`.

| Asset | Size | What it is |
|---|---|---|
| moonbit-labeler-0.2.17-bundle.exe | 247 MiB | One file. A self-extracting LunaPack bundle: run it and it unpacks itself into a .lunapack/ cache directory next to the executable. |
| moonbit-labeler-0.2.17.zip | 419 MiB | The staged application directory: moonbit-labeler.exe plus the CEF runtime beside it. |
moon add riantr/moonbit_labeler@0.2.17moon 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.| Target | Support |
|---|---|
| Desktop app (Proton + CEF) | Windows x86-64 — the exe, the zip and the LunaPack bundle are built and smoke-tested on windows-latest |
| --stdio JSON-RPC bridge | Windows x86-64 — the same executable with no CEF window |
| Backend library (extensions/labeler) | Native, any OS — the published module declares supported_targets = "+native", so it is not published for the wasm target at all. CI proves the Linux native case by resolving the package from mooncakes.io and building a consumer against it; macOS is not exercised in CI |
# 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.17.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.17import {
"riantr/moonbit_labeler@0.2.17",
}# examples/consumer/moon.pkg
import {
"riantr/moonbit_labeler/extensions/labeler",
"moonbitlang/core/async",
}
supported_targets = "native"
pkgtype(kind: "executable")
options(
"allow-experimental-packages": [ "moonbitlang/core/async" ],
)// examples/consumer/main.mbt
///|
async fn main {
let ops = @labeler.dispatch_op_list()
println("op count = " + ops.length().to_string())
// Round-trip a label through the shared normalizer. `parse_label`
// touches no filesystem, so the result is deterministic.
//
// `dispatch_op` is async and raises, so `main` is async and the error
// is handled at the call site rather than by letting `main` raise.
let payload = ToJson::to_json(ParsePayload::{
text: ToJson::to_json(ProbeLabel::{ img_name: "probe.png", }).stringify(),
fallback_img_name: "probe.png",
})
let text = @labeler.dispatch_op("parse_label", payload).stringify() catch {
_ => "dispatch failed"
}
println(text)
}
///|
/// The label the probe round-trips.
#derive(ToJson)
struct ProbeLabel {
img_name : String
}
///|
/// The `parse_label` request payload.
#derive(ToJson)
struct ParsePayload {
text : String
fallback_img_name : String
}op count = 27
{"label_text":"{\"img_name\":\"probe.png\",\"infos\":[],\"bindings\":[]}","err":""}fn async_package_anchor() -> Boolasync fn fs_package_anchor() -> Boolfn image_package_anchor() -> Boolfn labeler_package_anchor() -> Boolfn ref_package_anchor() -> BoolInstall
Download zipDesktop app binaries (Windows x86-64, .zip and single-file .exe): https://github.com/riantr/moonbit-labeler/releases -- this module is the backend only. 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\"`.