4D OxiBonsai

Version:
20.0.6
License:

MIT License

Last Update:
1
4

Description

oxibonsai is a pure Rust inference engine for PrismML’s Bonsai family.

README

oxibonsai for 4D

Overview / Integration guide

Run the OxiBonsai local HTTP server from 4D 20+.
This repository is the MIT-licensed 4D component and its build/packaging integration,
not the upstream inference engine. The upstream Rust engine is Apache-2.0 licensed.

The documentation site adopts the shared local inference site design v1.0.0,
with oxibonsai's own branding and capabilities. Guideline updates are reviewed
centrally
and adopted explicitly here; there is no shared runtime stylesheet or dependency.
The sidebar and stack use assets/icon.png, copied unchanged from
oxibonsai/Resources/icon.png; the favicon and touch icon are resized versions
of that resource, not replacement artwork. Preview the site with
bundle exec jekyll serve --destination .build/site and open
http://127.0.0.1:4000/oxibonsai/. Check the overview and guide in light and dark
mode at 1440, 1024, 768, 390 and 320 CSS-pixel widths when changing the layout
or styles. Check keyboard navigation, clipboard feedback, table scrolling,
local links, and the stack layout (beside the hero above 1000px, below otherwise).

Installation and targets

Download a component from Releases,
install the .4dbase in your application's Components folder, and restart 4D.
Source projects declare the miyako/tcp, miyako/workers, and miyako/event
dependencies in oxibonsai/Project/Sources/dependencies.json; resolve these with
4D's dependency manager when using the source project.
Model weights are not included and require separate disk space and RAM.

Component targets and bundled executables
Component targetResource executableBuild features
macOS Apple SiliconResources/bin/macOS/oxibonsai (universal)server,metal
macOS Intelsame universal executableserver (CPU)
Windows x64Resources/bin/Windows/oxibonsai.exeserver (CPU)
Windows ARM64Resources/bin/WindowsARM/oxibonsai.exeserver (CPU)

No Linux component or CUDA-enabled executable is packaged here. Upstream's optional
CUDA, RAG, and other CLI capabilities are not promises of this component's builds.
The wrapper chooses a bundled executable for the current platform, or falls back to
oxibonsai on PATH when that file is absent.

Use from 4D

The example downloads the Bonsai GGUF if needed, then starts the server on
http://127.0.0.1:8080. Use a tokenizer matching your model; the bundled
Resources/models/tokenizer.json is the fallback, not a universal tokenizer.

var $oxibonsai : cs.oxibonsai
var $homeFolder; $modelFolder : 4D.Folder
var $huggingface : cs.event.huggingface
var $huggingfaces : cs.event.huggingfaces
var $event : cs.event.event
var $options : Object

$homeFolder:=Folder(fk home folder).folder(".GGUF")
$modelFolder:=$homeFolder.folder("Bonsai")

$event:=cs.event.event.new()
$event.onError:=Formula(ALERT($2.message))
$event.onSuccess:=Formula(ALERT($2.models.extract("name").join(",")+" started"))
$event.onData:=Formula(MESSAGE(This.file.fullName+":"+String((This.range.end/This.range.length)*100; "###.00%")))
$event.onResponse:=Formula(MESSAGE(This.file.fullName+":download complete"))
$event.onTerminate:=Formula(LOG EVENT(Into 4D debug message; "oxibonsai process terminated"))

$options:={host: "127.0.0.1"; max_seq_len: 8192; pool_size: 1; \
max_concurrent_requests: 4; request_timeout_ms: 60000}

$huggingface:=cs.event.huggingface.new($modelFolder; "prism-ml/Bonsai-8B-gguf"; ["Bonsai-8B.gguf"])
$huggingfaces:=cs.event.huggingfaces.new([$huggingface])
$oxibonsai:=cs.oxibonsai.new(8080; $huggingfaces; $homeFolder; $options; $event)

onSuccess currently means the worker was started, not that model loading
or an HTTP readiness check succeeded. Check GET /health before sending requests;
loading a large model can take time. Call $oxibonsai.terminate() to stop the worker.

If there is nothing to download (no huggingfaces, or none of them resolves to a
file), the server is started with options.model when it is an existing local
4D.File. Otherwise event.onError receives an error with code 2 and the server
is not started. The server is launched at most once per wrapper attempt. event
may be Null (no callbacks are delivered) when nothing needs to be downloaded;
an actual download still requires an event, because the downloader in the
separate event component does not accept Null.

Options and API

Options use underscores; the wrapper converts them to CLI hyphens. The model
downloader supplies model as a 4D.File. Optional tokenizer must also be a
4D.File; omitting it selects the bundled tokenizer.

4D options and corresponding server flags
4D option / CLI flagUpstream default / meaning
host / --host127.0.0.1
constructor port / --port8080
max_seq_len / --max-seq-len4096, prompt plus generation context
pool_size / --pool-sizeCPU: min(4, cores); GPU/Metal clamped to 1
max_concurrent_requests / --max-concurrent-requests32; excess requests return 503
request_timeout_ms / --request-timeout-ms60000; timed-out requests return 408
bearer_token / --bearer-tokenUnset: no authentication
config / --configOptional upstream TOML config (observability settings; not a substitute for server flags)

Keep the loopback binding unless you deliberately configure network access.
bearer_token is forwarded to the server; clients must send
Authorization: Bearer <token>. Upstream also accepts OXIBONSAI_BEARER_TOKEN
from the environment, avoiding a token in process arguments. /health and
/metrics are exempt from bearer authentication; admin endpoints are not.
The CLI loads .env from its working directory or parents; explicit flags take
precedence over the supported environment defaults. In this upstream revision,
serve does not apply the TOML server settings; use the explicit flags above.
Do not put secrets in this repository.

For 4D AI Kit's OpenAI-compatible provider, use base URL
http://127.0.0.1:8080/v1, the model ID returned by GET /v1/models, and
the same bearer token if configured.

API boundaries of the component's server entry point
APIComponent's oxibonsai serve
GET /v1/modelsAvailable
POST /v1/chat/completionsAvailable, including streaming upstream
POST /v1/completionsAvailable upstream
POST /v1/embeddingsAvailable, but uses TF-IDF/byte-hash vectors, not Bonsai model embeddings
Images, files, moderationsNot exposed by this server entry point

Upstream's separate image CLI and oxibonsai-serve binary are not used by this wrapper.
The embeddings endpoint accepts but ignores the requested model name; do not
treat its lexical vectors as learned semantic embeddings from the loaded GGUF.

Reproducible source builds

As checked on 2026-11-02, upstream's latest release is v0.2.3
(published 2026-07-22); its master HEAD and the dereferenced tag both resolve to
1d10c48e14754ff6999158f8fa13c7c92b40b0dc, committed
2026-07-22 09:54:07 UTC. The existing bundled executables already report
0.2.3, but have no recorded build provenance; this update establishes a
source-built packaging path rather than claiming a newer upstream version.

upstream.json pins the commit, package oxibonsai-cli,
binary oxibonsai, target features, and Rust 1.99.0. Upstream declares
Rust >=1.86, but its source repository does not track Cargo.lock; this repository
supplies a resolved lockfile and uses --locked with a pinned newer compiler.
No upstream prebuilt executables are downloaded. Reproducibility here means pinned
source/dependencies/toolchain/features, not a guarantee of byte-identical binaries
across different SDK or linker versions.

Install Python 3.12+, Git, rustup, CMake, and a native C/C++ toolchain (Xcode
command-line tools on macOS; Visual Studio C++ Build Tools and Windows SDK on
Windows). The resolved TLS dependency includes aws-lc-sys, so this build is not
C-toolchain-free even though the inference engine is Rust. On a matching
native host, for example Apple Silicon:

rustup toolchain install 1.99.0 --profile minimal --target aarch64-apple-darwin
python3 scripts/build-server.py --target aarch64-apple-darwin
python3 -m unittest discover -s scripts/tests -v

Use the corresponding target triple from upstream.json on each other host.
The script fetches the exact commit, checks the source is clean, copies the
lockfile, builds release mode with explicit features, checks --version and
serve --help, and writes the executable plus SHA-256 provenance to
.build/server/artifacts/<target>/. It refuses inherited RUSTFLAGS and
CARGO_ENCODED_RUSTFLAGS. Windows builds explicitly set the recorded
-C target-feature=+crt-static so the VC runtime is not an unbundled prerequisite.
For an update, change the pin intentionally, regenerate Cargo.lock using the
pinned Rust toolchain against that source, and rerun all four native builds.
Use a fresh --work-dir when changing the source pin.

The source-build workflow runs on native
macOS ARM/Intel and Windows x64/ARM64 runners. It combines the Mac slices with
lipo, verifies both architectures, checks each artifact's source/lockfile/hash,
audits Mach-O imports and normal/delayed PE imports against system runtimes,
and uploads server-resource-bin with the complete 4D resource layout and
source.json. The upstream license is included in both native artifacts and
the final Resources/bin/UPSTREAM-LICENSE.txt, with its checksum recorded.
Manifest resource paths always use forward slashes, including on Windows.
The lockfile and checked-in license use LF bytes on every platform; the build
exports the upstream license from the pinned Git object rather than a potentially
CRLF-converted working copy. Checksums remain exact byte hashes.
CI uses Python 3.13.17, which has native distributions for all four runners.
For manual staging on macOS, collect the four target artifact
directories and run:

python3 scripts/package-server.py --artifacts .build/native --output .build/bin

Each native binary is smoke-tested on its own runner before universal packaging.
Assembly requires all four targets, exact provenance, system-only runtime closure,
an empty output directory and files strictly smaller than GitHub's 100 MiB limit
(104,857,600 bytes), including the combined universal Mac executable.
Unexpected resources, missing targets and external runtime DLLs fail before
replacement. No Git LFS conversion or partial matrix update is attempted.

Native refresh, then quick component publication

  1. Intentionally update upstream.json, Cargo.lock and the upstream license
    together when adopting new source. Run Build server from source for
    read-only validation; PR/push/build-only runs only upload artifacts.
  2. After reviewing the source change on main, explicitly run
    Update committed native resources
    from main with update_git=true. This rebuilds the pinned source on all
    four native runners, then verifies and commits/pushes precisely these paths:
    oxibonsai/Resources/bin/macOS/oxibonsai,
    oxibonsai/Resources/bin/Windows/oxibonsai.exe,
    oxibonsai/Resources/bin/WindowsARM/oxibonsai.exe,
    oxibonsai/Resources/bin/UPSTREAM-LICENSE.txt and
    oxibonsai/Resources/bin/source.json. It does not modify models/tokenizers,
    wrapper filenames, other platforms or component version metadata.
  3. Review the resulting resource commit, then separately dispatch
    Publish
    on main with the desired component version increment. A GITHUB_TOKEN
    push does not trigger other push workflows.
    The native updater deliberately
    has no publication dispatch and no actions: write permission.

Configure required reviewers and main branch restrictions for the native-update
and component-publish GitHub environments. Only the gated updater job receives
contents: write; PR/native compilation jobs are read-only and do not receive
deployment secrets. Branch protection must permit the authorized bot's normal
fast-forward push; the updater never bypasses protection, force-pushes, rebases,
or retries against a changed main. Main freshness is checked before replacement
and commit, and a race at push is rejected by Git. Native updates and production
Publish share a non-cancelling concurrency group.

Bootstrap requirement: the old tracked executables have no source.json;
they are preserved, not assigned fabricated build provenance. The first complete
authorized native update must land before the new committed-resource Publish
and component PR compilation gates can pass. The old successful CI artifacts
also require an unbundled vcruntime140.dll on both Windows architectures and
are therefore not suitable for installing under the new contract. Run the new
static-CRT Windows builds rather than copying those artifacts into Git.
For a staged rollout, land the reviewed workflow/scripts/docs first without a
4D source/resource change: these paths do not trigger production Publish.
The native updater does not depend on Publish, the component compile job,
or an existing resource manifest, so it can perform the first refresh on main.
The initial component PR resource check is intentionally red until that verified
resource commit exists; it must not be interpreted as a native build failure or
waived with a legacy-success fallback. Then validate an ordinary 4D-only change
against the committed resources before authorizing a separate Publish dispatch.

Publish has no native build job or native artifact download. Normal 4D-only
changes use the committed resources, validate their checksums/runtime closure
before the version bump, compile 4D, and verify the packaged resources again
before signing. Both hosted and self-hosted modes use the same path; Python
3.12+ and native inspection tools must be available on the packaging host.
PRs compile/validate read-only and can never publish or use the self-hosted runner.
The component version (package.json) is independent of upstream 0.2.3.

The compiler helper is pinned, and component-dependencies.json pins
checksum-verified tcp/workers/event release archives. A structured Compile project
report must contain success: true and an empty diagnostics array; archive
existence alone is not success. Packaging also requires a .4DZ (case-insensitive),
generated Libraries and the unchanged tokenizer. Signing includes every Mach-O
code object, including generated Libraries
, not just the CLI. Developer ID team,
timestamp, hardened runtime, notarization Accepted, DMG signing/stapling and
assessment are fail-closed gates. Only afterward are the local version commit and
tag pushed atomically without force and release assets uploaded.

Resources/bin/source.json describes pre-component-signing hashes.
Signing changes executable bytes; Resources/signed-code.json records final
signed code hashes, and the release SHA256SUMS records the final ZIP/DMG bytes.

Building/help checks need no model. Real inference and readiness testing require
a compatible GGUF/tokenizer and sufficient RAM; neither a successful compilation
nor the wrapper's start callback proves inference quality.

Earlier source-build validation (2026-11-02)

Both macOS release targets were built from the pinned source. A universal binary
passed version/help checks on ARM64 and Intel via Rosetta, and both slices
accepted the wrapper's server flags and reported a missing GGUF explicitly.
Eight build/packaging tests, fourteen upstream HTTP/CLI regression tests
(using synthetic tiny models), workflow linting, and the Jekyll site build passed.
This does not validate production-model inference quality or Metal performance.

Windows x64/ARM64 builds require the native Windows CI jobs and were not run on
this Mac; Intel execution here used Rosetta, not physical Intel hardware.
Full 4D compilation/runtime integration and signing/notarization were not
exercised locally (tool4d and deployment credentials were not used).
No production GGUF was downloaded. The Metal dependency block 0.1.6 emits a
Rust future-incompatibility warning; the pinned compiler still builds it.
No release workflow was triggered.

For the build-back-to-Git audit, actual artifacts from successful native run
41401312312 measured 28,355,168 bytes (universal Mac),
13,504,000 bytes (Windows x64) and 11,643,392 bytes (Windows ARM64).
These are measured CI outputs, not the older Git copies and not measurements of
the new static-CRT Windows builds. They demonstrate size headroom only; the
Windows runtime audit above prevents their installation. Each future update
measures its own final files before committing. Local contract tests are not
evidence that unrun Windows builds, 4D compilation or credentialed signing passed.

The new local macOS builds passed version/help and system-library closure checks;
their combined universal executable is 28,354,688 bytes, with both architectures
executed on Apple Silicon (Intel via Rosetta). New static-CRT Windows outputs
remain unrun and unmeasured.

The local 4D check used the same tool4d 20.7 build 20.101905, compiler revision
b73a89a9eac2636f59bcbd020ccf0aad954cab64 and invocation flags as established CI.
With pinned dependencies, it emitted {"success":true,"errors":[]} and generated
a .4DZ, generic compiled code, an ARM64 Library and matching tokenizer.
However, tool4d exited 139 during shutdown on macOS 26.7, including with the
unchanged compiler entry point and with a no-compilation/no-dependency control
method. This local runtime/environment failure is not specific to the new compile
invocation; its precise native crash cause is unresolved. The command's nonzero
exit is not suppressed, so this is not a successful packaging run or evidence
of credentialed signing/notarization. Hosted macOS 15 validation is still required.

Credits and licensing

Engine: cool-japan/oxibonsai, Apache-2.0
(bundled license).
4D integration: miyako/oxibonsai, MIT.
Native workflow conventions follow
llama-cpp,
CTranslate2, and
onnx-genai, adapted to this Rust CLI.