On this page
arcane-os/ai/browser-decisions owns browser-local Laya typed decisions
and Julia-1 inference. Laya defaults to FP16 and Julia to FP32; an explicit
dtype is forwarded unchanged to the selected upstream loader. It is separate from chat and speech because these
models score caller-supplied options instead of generating conversational text.
Applications supply the model repository, state, questions, option meanings and
policy; the SDK owns the reusable tokenizer, tensors, inference and lifecycle.
Explicit use
import {createBrowserDecisionModel} from 'arcane-os/ai/browser-decisions';
const model = createBrowserDecisionModel(
{
family: 'laya',
model: 'onnx-community/laya-typed-decisions-ONNX',
revision: 'main',
device: 'webgpu'
}
);
const unsubscribe = model.subscribe(
function showModelStatus(state) {
status.textContent = state.progress?.phase ?? state.state;
}
);
runButton.addEventListener(
'click',
async function decideDragonTea() {
try {
const result = await model.evaluate(
[
{
state: 'A sleeping dragon blocks the kitchen. The kettle whistles.',
question: 'What should the tea robot do?',
options: ['Wait quietly', 'Boil the kettle']
}
]
);
output.textContent = result.decisions[0].value;
} catch (error) {
console.error('The decision request failed.', error);
status.textContent = 'The decision could not be completed.';
}
}
);
Here status, runButton and output are application DOM elements. Changing
the state, question or options changes the actual model request. Importing the
module and constructing the client start no Worker or download. Only explicit
load() or evaluate() use loads the selected runtime and model. Concurrent
requests share the same activation; ready inference reuses that model session.
For Julia, select family: 'julia' and
model: 'SupersonicLabs/Julia-1-ONNX'. This selects the official FP32 graph;
it does not substitute a quantized graph or another model.
Configuration and upstream delivery
| Field | Meaning |
|---|---|
family |
Required laya or julia; chooses the model's encoding and graph layout. |
model |
Required upstream repository/base URL accepted by Transformers.js. The application owns its selection. |
revision |
Upstream revision, default main; select a stable revision when repeatable model selection is needed. |
device |
Transformers.js backend, default webgpu; an explicit supported alternative is caller-owned. No automatic backend fallback. |
dtype |
Exact upstream precision selection; defaults to fp16 for Laya and fp32 for Julia. For Laya FP32, supply dtype: 'fp32'. Unsupported selections fail at the selected upstream loader rather than being replaced. |
runtime.local |
Default false. Explicit true selects deployment-local executable modules/WASM without executable Blob preparation; see the MV3 section below. |
runtime.moduleUrl |
Defaults to the self-contained CDN entry https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.3.0/dist/transformers.min.js, or ./decisions-runtime/transformers.min.js relative to this SDK module in local mode. The .web.js build expects a bundler to resolve its bare ONNX Runtime import and is unsuitable for a native module Worker. Explicit compatible URLs are retained; local mode requires files in the SDK Worker's deployment. With store and ordinary non-local mode, the SDK stores and materializes the complete entry for that activation. |
runtime.wasmPaths |
Optional upstream ONNX WASM location passed to the selected runtime's public environment API. Local mode defaults to the matching asyncify module/WASM under ./decisions-runtime/; it accepts a directory URL or explicit {mjs, wasm} URLs resolved relative to this SDK module. |
store |
Optional existing SDK DBOPFS model or speech artifact store exposing fetchResource(). It remains outside Worker configuration and owns actual model resources. Ordinary stored mode also owns the runtime entry; local mode loads only the exact selected executable files directly. |
Without store, the runtime, tokenizer and weights use normal upstream loading
and caching. With store, the selected loader still owns filenames and model
selection while model resources persist through that existing SDK store. The
SDK package does not contain upstream runtimes or models; the explicit local
materializer below acquires its selected executable distribution. Browser
network, cross-origin and backend availability still apply. WebGPU needs a
compatible browser/device context. Unsupported precision or backend errors
are returned, not replaced with a different model, backend or precision.
Laya defaults to dtype: 'fp16', loading onnx/model_fp16.onnx and its
model_fp16.onnx_data companion through Transformers.js. The published mixed
precision graph retains selected operations/outputs in FP32; FP16 selection
does not claim every graph operation runs in half precision. Explicit
dtype: 'fp32' selects the repository's FP32 graph through that same loader.
Julia selects dtype: 'fp32', loading root model.onnx with the exact
model.onnx.data external-data name. Its custom five-input graph is loaded
through the public generic PreTrainedModel API, not a text-generation
pipeline. Existing Wllama, cloud, speech and chat APIs are unchanged.
Extension-local executables (Manifest V3)
When packaging the application, opt into the upstream browser distribution through the public Node API:
import {packageApp} from 'arcane-os';
const release = await packageApp({
workspaceRoot: process.cwd(),
appId: 'moon-dashboard',
outputDirectory: 'dist/extension/app',
moduleFormat: 'native',
browserPwa: false,
browserDecisions: true
});
This acquires the official bundled Transformers.js 4.3.0
transformers.min.js, matching ONNX Runtime
1.31.0-dev.20260914-8d85527a0 ort-wasm-simd-threaded.asyncify.mjs and
ort-wasm-simd-threaded.asyncify.wasm, plus TRANSFORMERS-LICENSE and
ONNX-RUNTIME-LICENSE. The five complete files are acquired only into the
package stage, under decisions-runtime/ beside the selected SDK
ai/browser-decisions.mjs. Installed-package routes retain their actual
dependency path, including npm aliases: for example,
node_modules/arcane-os/browser-runtime/ai/decisions-runtime/ inside
release.outputRoot. The installed dependency and application source remain
unchanged; this route creates no workspace-root arcane/ projection.
Acquisition follows SDK module/asset rewriting, preserving complete upstream
executable content and licenses unchanged. It works with both
moduleFormat: 'native' and the default 'import-map'. The returned files
and release manifest include the distribution; when browser PWA generation
is enabled, its ordinary offline include/exclude selection applies too.
Retain the supplied licenses with the deployment. No bundler, Node engine
dependency tree, model graph or tokenizer is installed by this option. Select
browserDecisions: true on each package build that should acquire the closure.
The default false and dryRun: true perform no optional acquisition; dry runs
report selected input files rather than downloaded distribution files.
Existing physical workspace projections retain
materializeInstalledSdkRuntime({workspaceRoot, browserDecisions: true}).
That operation stages these files under arcane/sdk/ai/decisions-runtime/
before replacing the projection, returning directory, transformersVersion,
onnxRuntimeVersion and files under workspaceRuntime.browserDecisions.
materializeWorkspaceRuntimeContent() accepts the same option and returns
that record as result.browserDecisions. Repeat the option on each projection
refresh that should retain the closure. Installed-package applications use
packageApp() above, because their routes read from the installed dependency
rather than this separate projection.
Both operations share one distribution owner. Its fixed files are acquired
concurrently, once each per operation. Events
workspace.decisions.started and workspace.decisions.progress expose
completed/total file counts; each progress event also has file and url.
Cancellation and HTTP or observer failure abort/join pending acquisition and
preserve the prior package output or physical runtime. An HTTP failure retains
the complete response as
error.response (url, status, statusText, headers, content), including
inside AggregateError.errors when several operations fail.
Load from an extension-owned module script, using the deployed SDK path:
import {createBrowserDecisionModel} from './node_modules/arcane-os/browser-runtime/ai/browser-decisions.mjs';
const decisions = createBrowserDecisionModel({
family: 'laya',
model: 'onnx-community/laya-typed-decisions-ONNX',
dtype: 'fp16',
device: 'webgpu',
runtime: {local: true},
store // The application's existing SDK DBOPFS model store.
});
await decisions.load();
Use the actual deployed alias path when the dependency has another name;
physical projections instead use ./arcane/sdk/ai/browser-decisions.mjs.
For Julia-1, change the family/model to julia /
SupersonicLabs/Julia-1-ONNX and select dtype: 'fp32'. Model and tokenizer
data remain upstream resources served through the same store, preserving its
complete response, persistent cache, progress and cancellation behavior.
Construction stays lazy. Only the exact configured local executable URLs use
native fetch/module loading outside that store; other resources, including
other same-deployment URLs, retain the model resource bridge.
Local mode directly imports the deployment's module and explicit asyncify
factory, disables the upstream executable WASM cache and proxy, and selects
one WASM thread to avoid nested executable Blob workers. This leaves
device: 'webgpu' unchanged; it is not a CPU/backend fallback. Compatible
custom runtime.moduleUrl and runtime.wasmPaths: {mjs, wasm} selections must
share the SDK module's protocol and host. Relative selections resolve against
that module. A wasmPaths directory URL selects the same two asyncify filenames.
Use external module scripts in extension pages. Chrome's MV3 extension-page
CSP permits WebAssembly with script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; executable scripts and Workers remain packaged locally. The extension
owns the permissions required for its selected upstream model-data endpoints.
See Chrome's extension CSP contract.
This source integration does not establish an actual Chrome extension load,
WebGPU inference, or application acceptance; those outcomes require execution
in the selected extension environment.
Shared DBOPFS model resources
import {createDbopfsModelStore} from 'arcane-os/ai/browser-wasm';
import {createBrowserDecisionModel} from 'arcane-os/ai/browser-decisions';
// dbopfs is the application's existing Arcane DBOPFS instance.
const store = createDbopfsModelStore({dbopfs});
const decisions = createBrowserDecisionModel(
{
family: 'laya',
model: 'onnx-community/laya-typed-decisions-ONNX',
store
}
);
await decisions.load();
The same store may serve other SDK model clients. The application supplies no
tokenizer/configuration/graph manifest and performs no file routing. Explicit
activation without runtime.local first opens runtime.moduleUrl through store.fetchResource().
The SDK materializes the complete stored entry as a JavaScript object URL for
the dedicated Worker, without rewriting its content. The configured source URL
is retained for later activations, so they reuse the same stored resource rather
than saving a temporary object URL. Construction still starts no download.
Inside the dedicated decision Worker, Transformers.js's public env.fetch hook routes the
actual selected tokenizer, configuration, ONNX graph and external-data requests
to store.fetchResource(input, options). Its competing browser, custom and
filesystem model caches are disabled only for this explicit stored mode. The
default upstream ONNX WASM binary and factory preloads use this same hook.
Native support-file fetches in the dedicated Worker also use the store, except
for the exact deployment-local executable selections in local mode. The
default runtime entry is self-contained. Entry materialization does not rewrite
dependency imports in custom modules or preserve their original import.meta.url
base. Custom stored entries must work from an object URL; relative imports or
support-file URLs resolved against that module's original location require a
compatible self-contained entry. Native absolute ESM dependencies and an upstream
custom factory import outside its preload path remain browser-owned. No second
application cache or model substitution is introduced. Without store, the
configured runtime URL keeps its direct native module-loading behavior.
The store returns {file, status, statusText, headers, url, redirected}. The
Worker reconstructs the complete response with its actual HTTP status and
headers, so a missing optional upstream file remains a missing-file response.
New response bodies stream into ordered persistent shards, including resources
with unknown totals. Completed resources are reused by their semantic request
and URL selection. Interrupted closed shards remain available for HTTP Range
resume; a server returning a full response restarts that member without adding
the saved prefix twice. Independent resources remain concurrent, and repeated
requests for the same resource share its storage mutation owner. Existing saved
model formats are retained without a migration.
Resource progress uses {phase: 'download', completed, total, unit: 'shards', url}. completed counts closed persistent shards; total is null until the
resource finishes. This progress carries no network-size, rate or ETA fields.
Cancellation aborts the owned fetch and joins reader/writer cleanup before the
resource owner becomes available to a later request. Interrupted closed shards
are retained. Each non-local stored activation owns its runtime object URL and revokes it after
terminating the Worker on cancellation, failure, unload or disposal. A cancelled
runtime-entry fetch is joined before its waiting calls settle; a late response
cannot activate a replacement Worker. Runtime-entry HTTP failures retain the
complete stored response in error.response for developer diagnostics.
unload() and dispose() still acknowledge their lifecycle transition
synchronously; outstanding load()/evaluate() calls settle after their
resource cleanup.
Complete rows and results
evaluate(rows, {signal}) accepts an array in caller order. Each row has
string state, string question, string-array options, and optional
type defaulting to choice. Additional row fields remain in the returned
row without affecting inference. Neither strings nor option arrays are
trimmed, rewritten, clipped or capped by the SDK.
The model's required token framing puts the complete type/question header,
option markers/options and state into input_ids; accompanying inputs are
attention_mask, marker_pos, marker_mask and qtype. Right padding aligns
rows in a batch. Literal marker text inside supplied content remains content;
option positions identify only markers inserted by the encoding owner.
Tokenizer encoding is called without special-token insertion and without
the upstream batch-tokenizer truncation path.
The result is {decisions, outputs}. decisions follows input order and each
entry contains the original row record, option logits, unrounded raw-softmax
probabilities, the highest-logit answerIndex, and value:
| Type | value |
|---|---|
choice |
The complete selected option string. |
score |
Raw-softmax weighted zero-based option index. Applications map this to their own score scale. |
noul |
Probability of option 1; supply exactly [falseOption, trueOption] in that order. |
If the actual graph supplies act_logits, the entry additionally includes
complete actionLogits, unrounded actionProbabilities, and raw-softmax
actProbability at index 0. Julia's
published ONNX export has no action head; the SDK does not invent one.
outputs preserves every returned graph tensor, including padding and extra
named outputs, as {type, dims, data} with complete copied typed data. This
keeps model results available for explicit application interpretation and
diagnostics. Probabilities are raw model scores, not claimed calibrated
confidence, probabilities rounded to two decimal places, or policy decisions.
No result is inserted into chat history, memory extraction or DBOPFS.
Lifecycle, events and cancellation
status() returns {family, model, revision, device, dtype, state, loaded, busy, activeRequests, progress, error}. States are unloaded, loading,
ready, error and disposed. subscribe(listener, {emitCurrent: true, signal}) observes the owning Arcane event source, replays current state by
default and returns an unsubscribe function. Successful rows and graph results
return to the calling operation rather than lifecycle notifications. Complete
errors, including graph diagnostics when decoding fails, remain available in
error; they belong in developer diagnostics, not ordinary status text.
Work is acknowledged synchronously before loading/inference waits. Progress
reports real semantic phases such as waiting-for-model, loading-runtime, loading-tokenizer,
loading-model, download, ready, evaluating and complete; it is not a synthetic
percentage. Loading the model and tokenizer proceeds concurrently. Repeated
identical state text is tokenized once per batch. Independent requests are
accepted concurrently; the selected backend still owns its execution ordering.
load({signal}) explicitly prepares the shared activation. evaluate() also
loads on its first explicit use. An AbortSignal, unload() or dispose()
terminates the client's dedicated Worker and rejects all its outstanding
operations. Cancellation is client-wide because the model session and GPU
work belong to that Worker. Use separate clients when independent cancellation
is required. unload() permits later explicit reactivation; dispose() is
terminal. Old Worker replies cannot affect a replacement activation.
A Worker operation failure releases the failed activation and rejects its waiting calls. The next explicit use starts a fresh Worker rather than reusing an upstream inference queue that may remain rejected after a backend failure. Error records preserve the original name, message, stack, code, cause and available custom fields across the Worker boundary. Applications keep technical diagnostics out of ordinary user status.
Model limits and evidence
The published Laya and Julia families advertise an 8192-token native context. Their reference wrappers apply smaller budgets and, for Julia, a documented 2–20-option interface. The SDK does not reproduce those wrapper clipping or rounding policies or claim arbitrary lengths are supported by the graph. Actual model/backend failures remain observable. Long-input quality and option-count behavior must be established for the application's selected model; no hidden windowing or result aggregation is performed.
Julia's Transformers.js tokenizer route exists in the official browser adapter, alongside a Rust tokenizer. Repeated-space/Metaspace segmentation can differ between those tokenizer implementations. Complete text is preserved at the tokenizer boundary, and Python/Rust token-ID or numerical parity is not claimed. Applications needing that parity must use an established compatible tokenizer contract rather than silently rewriting text.
Upstream graph/loading contracts were reviewed from primary source. Browser model loading, FP16/FP32 inference, cancellation and numerical behavior require selected-output verification; static compatibility review alone is not a runtime pass.
Primary references: Laya ONNX, Laya reference, Julia-1 ONNX, Transformers.js 4.3.0.