Skip to main content

rcli-e2e

Verify a built rcli binary against a pinned C++ desktop kit on macOS and Windows. Use when CI smoke/e2e is red, backends are missing, DLLs fail to load, or the Apple MLX host fails to link.

Quellinformationen

Repository
RunanywhereAI/RCLI
Letzte Quellaktivität
28. August 2026 um 01:29
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.544
Forks
85

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
rcli-e2e
description
Verify a built rcli binary against a pinned C++ desktop kit on macOS and Windows. Use when CI smoke/e2e is red, backends are missing, DLLs fail to load, or the Apple MLX host fails to link.
# RCLI e2e Entry: `scripts/e2e.sh <path-to-rcli>`. Always runs `scripts/smoke.sh`, then `scripts/e2e-modalities.sh` (engine-agnostic primitives). Public CI leaves modality knobs unset so every round-trip **skips**. Device runs set `RCLI_E2E_<MOD>` / `RCLI_E2E_MODEL_ROOTS` / `RCLI_E2E_AUTO=1`. See `rcli-device-e2e` for ANE/NPU. | Env | Primitive | Example | |---|---|---| | `RCLI_E2E_LLM` / `RCLI_E2E_MODEL` | llm | `mlx-qwen3` or a `*_HNPU` dir | | `RCLI_E2E_STT` | stt | `whisper-tiny` or `whisper_base_HNPU` | | `RCLI_E2E_TTS` | tts | `piper` or `kitten_micro_0_8_HNPU` | | `RCLI_E2E_VLM` | vlm | `smolvlm2` (SDK inserts the media marker) | | `RCLI_E2E_EMBED` | embed | `minilm` or `embeddinggemma_300m_HNPU` | | `RCLI_E2E_IMAGE` | image | compiled SD1.5 tree / `sd15` | | `RCLI_E2E_NEURT_MODEL` | classified by path | `sd15`, a Parakeet ANE tree, or `lfm2-230m-ane` | | `RCLI_E2E_VAD` | vad | `silero` | | `RCLI_E2E_RERANK` | rerank | `bge-reranker` | | `RCLI_E2E_SEGMENT` | segment | `segformer` (P6 PPM) | | `RCLI_E2E_ENGINE` | override only | `qhexrt` / `neurt` / `mlx` | Legacy `RCLI_E2E_MLX_MODEL` / `RCLI_E2E_NEURT_MODEL` / `RCLI_E2E_QHEXRT_MODEL` are classified by path/id into a primitive (not always image). Do not add new engine-named knobs. `scripts/assert-binary-backends.sh` greps `nm`/`llvm-nm`/`dumpbin`/`strings` for registrar symbols (`raMLXRegisterRuntime`, `rac_plugin_entry_neurt`, `rac_plugin_entry_qhexrt`, …) so a backends() listing cannot pass without the engine actually being linked into the bottle. Pass `RCLI_SDK_KIT` so overlay backends (`neurt` / `qhexrt`) are required when those libs are in the kit. `CMAKE_PREFIX_PATH` is only used for `HAS_*` flags and Windows DLL staging — an ambient overlay prefix must not make a public OSS bottle fail for missing NeuRT. ## What "green" means `scripts/assert-backends.sh` requires every engine the kit actually ships: | Condition | Required `rcli --json backends` name | |---|---| | no kit Config (public OSS bottle) | `llamacpp` + `onnx` + `sherpa` | | kit `RunAnywhere_HAS_LLAMACPP` TRUE | `llamacpp` | | kit `RunAnywhere_HAS_ONNX` TRUE | `onnx` | | kit `RunAnywhere_HAS_SHERPA` TRUE | `sherpa` | | Darwin arm64 product binary `rcli` (not `rcli-cxx`) | `mlx` | | overlay `lib/librac_backend_neurt.a` / `rac_backend_neurt.lib` | `neurt` | | overlay `lib/librac_backend_qhexrt.a` / `rac_backend_qhexrt.lib` | `qhexrt` | Do **not** drop sherpa from the expected list to make 0.20.26 Windows green while `HAS_SHERPA` is TRUE. That kit compiled sherpa with speech ops off (`RAC_SHERPA_ROUTABLE=0`): `rac_backend_sherpa_register()` returned SUCCESS, `capability_check` returned `BACKEND_UNAVAILABLE`, the registry refused the plugin. The fix is pin a routable kit (0.20.28+), not weaken the assertion. ## `backends` must walk every live primitive `src/commands/cmd_backends.cpp` iterates `1 .. RAC_PRIMITIVE_COUNT-1`, skipping retired wire value 6. ONNX without RAG only advertises SEGMENT / DIARIZE. A hardcoded GENERATE_TEXT / TRANSCRIBE / EMBED list made onnx invisible even when the plugin was registered. Do not reintroduce a primitive allow-list. ## Windows DLLs Win32 `LoadLibrary` searches the exe directory, then PATH. `e2e.sh` copies `third_party` / `bin` / `lib` `*.dll` next to `rcli.exe` and prepends those dirs to PATH **before** smoke. Skipping that produces "llamacpp only" even when the kit contains `rac_backend_onnx.lib` + `onnxruntime.dll`. Never pass `onnxruntime.dll` to `link.exe` (LNK1107) — link the import lib; stage the DLL at runtime. GitHub Windows: `GITHUB_WORKSPACE` is `D:\a\...`; msys `tar -C` needs `cygpath -u` (`fetch-kit.sh` already does). ## Apple MLX host link (Ninja) `scripts/bundle-core.sh` merges everything `rcli` links into `librcli_bundle.a` for SwiftPM. - Ninja **never** writes `CMakeFiles/rcli.dir/link.txt` (Makefiles only). - Harvest with `ninja -t commands rcli | tail -1`. The **last** command is the link. Grepping for `rcli` hits compile lines (`CMakeFiles/rcli.dir/…`). - Apple ld emits one token `-Wl,-force_load,/abs/path/lib.a`. That ends in `.a` but is not a path. Prefixing `BUILD/` produces `build/-Wl,-force_load,…`. Strip `-Wl,-force_load,` first. - Ninja lists archives twice; `libtool -static` then fails on duplicate members unless you dedupe. `scripts/build-mlx.sh` must dump the xcodebuild log on failure (`Undefined symbols` does not contain `error:`). Do not grep bare `error:` — every CompileC line contains `-Werror=`. Observed CI `32786359915`: grep `error:|Metal|BUILD` left only `clang: error: linker command failed`. Never put `#` comments in a `\`-continued `xcodebuild` invocation. Bash cuts the command there, so `OTHER_LDFLAGS` and the log redirect never run (empty `xcodebuild-mlx.log`, status taken from a later assignment). Link flags that must survive the Swift host: - `-Wl,-force_load,$BUILD/librcli_plugins.a` then `-L$BUILD -lrcli_bundle`. Force-load **only** the plugin backends (static registrars). Do **not** force-load llama-common: that pulls `download.cpp.o`, which references cpp-httplib `Client::Get` methods the kit never emitted as objects (`rcli-cxx` never needed that TU). Observed locally after revealing the real `Ld` log. - `-L$KIT/third_party -lonnxruntime` and `-Wl,-rpath,$KIT/third_party` — `bundle-core.sh` rewrites the kit dylib to `-l` and must keep `-L` plus the rpath `rcli-cxx` already had, or the Swift host abort-traps at launch (`Library not loaded: @rpath/libonnxruntime.dylib`). Harvest `-l*` as well as dylib conversions (`-ldl`, `-lbz2`). - Canonicalize `RCLI_SDK_SWIFT_PATH` with `cd && pwd`. SwiftPM's local package identity is the **directory name**, so `…/EXTERNAL/RCLI/../..` registers as `..`. Nested checkouts named `sdks1` must use that name in `.product(..., package:)`. Do not point `RCLI_SDK_SWIFT_PATH` at an unreleased `Package.swift` whose `sdkVersion` zips 404 (`v0.20.28` before publish). CI checks out the **tagged** SDK tree (`ref: v$SDK`) whose binaryTargets already exist. CI macOS runner is **macos-26** (Xcode 26 / Swift 6.2). The MLX host resolves `RunanywhereAI/runanywhere-sdks` `Package.swift`, which is `swift-tools-version: 6.2`. macos-15 is Xcode 16.4 / Swift 6.1 and fails after a successful libtool merge with `package 'runanywhere-sdks' is using Swift tools version 6.2.0 but the installed version is 6.1.0`. macos-14 is Swift 5.10. `release.yml` must use the same runner as `ci.yml`. ## Linux Linux bottles are not a v1 merge blocker. Windows x64 and macOS arm64 are. `scripts/e2e-linux.sh` exists for later. ## Private engines NeuRT / QHexRT only appear in `backends` when the overlay was applied. `scripts/e2e.sh` requires `neurt` / `qhexrt` when `lib/librac_backend_neurt.a` or `lib/rac_backend_qhexrt.lib` exists — not by grepping packaged `HAS_NEURT FALSE` (that stays false; find_package flips it when the archive is present). Public CI must pass without overlays. Image gen (`cmd_image.cpp`) is compiled out unless NeuRT is present. ## Device / overlay gotchas (0.5.1 + kit 0.20.28) Public bottles never list `neurt` or `qhexrt`. That is the product, not a test gap. Overlay-rebuild the product binary (`RCLI_APPLE_MLX_HOST=ON` on Mac; ARM64 MSVC + QHexRT overlay on Snapdragon). - **`CMAKE_PREFIX_PATH` is not an overlay opt-in.** Only `RCLI_SDK_KIT` makes e2e require `neurt`/`qhexrt`. An ambient overlay prefix from a previous rebuild will otherwise fail a public-bottle run. - **Binary assert:** never `nm | grep -q` under `pipefail` (SIGPIPE → false FAIL). Stream `strings -a` / `nm -a`. Darwin MLX proof is `mlx-swift_Cmlx.bundle` next to product `rcli` (`nm -gU` misses Swift host symbols). First C++ `rac_plugin_register(mlx)` logs `-811`; Swift callbacks then register MLX — noisy, not a miss. - **Windows ARM64 public/overlay kits have `HAS_LLAMACPP FALSE`.** Do not require `llamacpp` in e2e. Overlay `rcli.exe` listing **only** `qhexrt` (priority 150) is correct. On-disk GGUF (`qwen3.5-2b`) cannot run there. - **QHexRT generate needs QAIRT matching the device skel, not the overlay DLL set.** Snapdragon X2 Elite / Hexagon v81: `QNN_SDK_ROOT` + `ADSP_LIBRARY_PATH=%QNN_SDK_ROOT%\lib\hexagon-v81\unsigned`, copy `aarch64-windows-msvc` `QnnHtp.dll` / `QnnHtpPrepare.dll` / `QnnHtpV81Stub.dll` / `QnnHtpV81CalculatorStub.dll` / `QnnSystem.dll` next to `rcli.exe`. Overlay 2.47 DLLs vs device 2.41 skels fail; QAIRT **2.48** worked. Pass the `*_HNPU` directory (`--engine qhexrt`), not a GGUF. FastRPC `openSession` timeouts (~90s) then user-driver fallback are normal; a second generate while DSP is wedged fails with `Skel failed to process context binary` / `0x3ea` — `taskkill rcli.exe` and use a `.bat` with **fully expanded** `ADSP_LIBRARY_PATH` (nested `%QNN_SDK_ROOT%` in `cmd /c "set A=…&& set B=%A%\…"` does not expand). - **VS on the ARM64 box may be 2026 / 18 Community**, not 2022: `C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsarm64.bat`. CMake/Ninja live under VS CMake extensions; they are not on default PATH. - **v0.20.28 Windows ARM64 public kit omits `libcurl.lib`.** Copy from `arm64-windows-static` into the kit `lib/` before linking (fixed in the SDK packager for the *next* kit; do not retag 0.20.28). RCLI already links kit `libcurl.lib` when present. - **`rcli image generate` needs `--prompt` and `--out`**, not a positional prompt. `--steps 4` is enough for a smoke PNG. Help exists on the public bottle; real generate is compiled only with `RCLI_HAS_NEURT`. - **`sd15` catalog URL must be the compiled zip**, not the HF repo page (HTML ~160 KB). Unzip to a tree with `TextEncoder.mlmodelc` / `Unet.mlmodelc` / `VAEDecoder.mlmodelc` and pass that directory. COREML / QHEXRT catalog rows register `ModelInfo` (folder), not the single-file download factory — `rcli pull sd15` is not a substitute for the zip. - Published product bottles: macOS `rcli-$V-macos-arm64.tar.gz`, Windows **x64** zip. There is no public Windows ARM64 bottle; NPU is overlay-only. - **The private QHexRT overlay tarball used to ship zero skel files** (only `.dll`/`.lib`, no `.so`/`.cat`) — `rac-cli`'s own overlay build could not run `qwen3.8-27b-1bit-npu` (the Bonsai/Maple ternary decoder) out of the box; validating it required hand-copying `librun_main_on_hexagon_skel.so` + `.cat` in from the `electron-qhexrt` npm package as a workaround. Fixed in `runanywhere-sdks`' `scripts/build/package-private-engine-overlay.sh` (widened the copy filter and added a pass for `dsp/win-arm64/`). **RCLI itself never had the `ADSP_LIBRARY_PATH` bug the Electron binding had** — `fastrpc_win.cpp`'s `exe_dir()` fallback naturally resolves for `rcli.exe` because dependent DLLs/skels are staged flat beside the executable by this repo's own packaging convention — but that protection is a property of the *packaging layout*, not of RCLI's code, so it is not something to assume going forward. **Always build a fresh overlay from the actual release script and run the ternary model against it after any SDK kit-pin bump** that touches QHexRT — do not assume last time's manually-patched overlay is still representative of what a real user's overlay build produces. - **The private overlay tarball must be EXTRACTED ON TOP OF `kit/`, merging into the same directory tree (`overlay/bin/*` → `kit/bin/`, `overlay/lib/*` → `kit/lib/`, `overlay/include/*` → `kit/include/`, `overlay/share/...` → `kit/share/...`) — never kept as a separate sibling `overlay/` directory fed to CMake via a second `CMAKE_PREFIX_PATH` entry.** `rcli_stage_windows_runtime_dlls()` (`cmake/RunAnywhereSDK.cmake`) only ever copies from `${RunAnywhere_LIBRARY_DIR}/../bin` — i.e. `kit/bin` — so a same-named `overlay/bin` sitting next to `kit/` is silently never consulted. Worse, this fails **completely silently**: the build succeeds, `rcli.exe` links, and `rcli backends --json` returns `{"backends":[]}` with no error naming QHexRT at all (`find_library`-style detection in `RunAnywhereSDK.cmake` just doesn't find `kit/lib/rac_backend_qhexrt.lib` because it was never copied there). If a fresh overlay build reports zero backends, check this BEFORE suspecting the overlay tarball's contents. - **`qwen3.8-27b-1bit-npu`'s `HostOpFailed` had THREE compounding causes, found and fixed one at a time — a kit-pin bump to v0.20.31 alone was NOT enough; RCLI needed its own additional fix (below) even with a perfectly merged overlay.** 1. The overlay-skel-files-never-shipped bug (above), fixed upstream in `runanywhere-sdks`' overlay packaging script. 2. `qhexrt::qnn::Backend::profile()` — called (via the same `engines/qhexrt/qhexrt_session.cpp` this repo statically links, same as the Electron binding) to pick the `v75`/`v79`/`v81` manifest directory before the manifest is even parsed — shared its device query with the code path that opens a real QNN HTP device, so the ternary decoder's `host_only` manifest paid for a live QNN device it never needed. Fixed in `neurun` v0.20.31 (`Backend::profile()` no longer shares `ensure_device()` with `device()`) — see that repo's `qhexrt-profile-must-not-create-live-device` KB finding. 3. **RCLI-specific, and NOT fixed by the kit-pin bump alone**:
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen