arcane-os 0.66.0 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +1 -1
- package/browser-runtime/ai/core-image.mjs +84 -34
- package/browser-runtime/ai/core-local.mjs +195 -43
- package/browser-runtime/ai/core-onnx.mjs +71 -12
- package/docs/reference/README.md +6 -0
- package/docs/reference/availability-and-normalization.md +1 -0
- package/docs/reference/core-native-packaging.md +11 -4
- package/docs/reference/core-repositories.md +93 -9
- package/docs/reference/core-runtime.md +46 -5
- package/docs/reference/inventory/package-api.json +62 -20
- package/docs/reference/inventory/runtime-components.json +2 -1
- package/docs/reference/inventory/runtime-modules.json +3 -3
- package/docs/reference/local-ai.md +112 -2
- package/docs/reference/local-image-generation.md +15 -4
- package/docs/reference/model-assets.md +50 -3
- package/docs/reference/native-decisions.md +181 -0
- package/docs/reference/runtime-components.md +62 -5
- package/docs/reference/runtime-modules.md +44 -7
- package/docs/reference/sdk-api.md +229 -19
- package/package.json +5 -2
- package/runtime/arcane/components/theme-switcher.html +112 -13
- package/runtime/arcane/modules/PreferenceStore.js +18 -13
- package/runtime/arcane/modules/SystemAppearance.js +24 -6
- package/src/core/repositories.mjs +27 -8
- package/src/core/runtime.mjs +26 -1
- package/src/core/services/decisions.mjs +144 -0
- package/src/core/services/local-ai.mjs +31 -9
- package/src/core/services/model-assets.mjs +98 -13
- package/src/git-identity.mjs +22 -58
- package/src/local-ai/decision-tokenizer-worker.mjs +31 -0
- package/src/local-ai/decision-tokenizer.mjs +109 -0
- package/src/local-ai/decisions.mjs +273 -0
- package/src/local-ai/dev.mjs +8 -2
- package/src/local-ai/onnx-worker.mjs +67 -7
- package/src/local-ai/onnx.mjs +23 -12
- package/src/native/portable-layout.mjs +8 -3
- package/src/repository.mjs +144 -4
|
@@ -174,6 +174,34 @@ This factory accepts chat/ONNX requirements; the separate
|
|
|
174
174
|
owns image requirements. The development and generated native composition
|
|
175
175
|
split the shared application record accordingly.
|
|
176
176
|
|
|
177
|
+
### Native service owners
|
|
178
|
+
|
|
179
|
+
A native application service uses its Core lifecycle or request context to
|
|
180
|
+
obtain the existing selected owner:
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
const localAI = await context.getService('local-ai');
|
|
184
|
+
const onnx = localAI.getONNXRuntime();
|
|
185
|
+
const modelAssets = await context.getService('model-assets');
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`getService()` awaits only that service's existing startup. The synchronous
|
|
189
|
+
`getONNXRuntime()` returns its actual `load/run/unload/current/subscribe/close`
|
|
190
|
+
owner; it neither prepares another runtime nor loads a model. An unselected
|
|
191
|
+
engine reports `LOCAL_AI_RUNTIME_NOT_SELECTED`; an unavailable or recovering
|
|
192
|
+
owner reports `LOCAL_AI_RUNTIME_UNAVAILABLE`, and an aborted service lifetime
|
|
193
|
+
retains its abort reason. Development and generated native compositions register
|
|
194
|
+
one shared model-assets service when ONNX or image generation is selected.
|
|
195
|
+
|
|
196
|
+
Reacquire `getONNXRuntime()` on each explicit model load because runtime recovery
|
|
197
|
+
replaces that owner. Retain the acquired handle for that session's cleanup and
|
|
198
|
+
await its `unload({id})` without an already-aborted request signal before releasing
|
|
199
|
+
the corresponding model-assets retain handle. The native ONNX owner joins actual
|
|
200
|
+
worker exit; a cancelled request's rejection alone does not establish that exit.
|
|
201
|
+
Core closes services concurrently, and the host can cancel in-flight native work
|
|
202
|
+
at shutdown. These native members require no renderer readiness and introduce no
|
|
203
|
+
second inference engine. See [native Core composition](core-runtime.md#native-service-composition).
|
|
204
|
+
|
|
177
205
|
`localai.status` returns `{runtimes}` and, when Ollama is selected, the existing
|
|
178
206
|
`ollama` and `models.ollama` catalog fields. Runtime records distinguish
|
|
179
207
|
`installed`, `available`, `state`, `models`, ownership and errors. A listening
|
|
@@ -198,6 +226,14 @@ background health polling.
|
|
|
198
226
|
| `llama.unload` | `{model}` | Current state after release |
|
|
199
227
|
| `llama.chat` | `{model,payload,stream?,streamId?}` | Complete OpenAI-shaped completion |
|
|
200
228
|
|
|
229
|
+
`llama.status` and `llama.models` observe the selected service without loading,
|
|
230
|
+
restarting or waiting for it. Starting, loading, stopped and failed services
|
|
231
|
+
return their retained state/catalog; an available service supplies a fresh
|
|
232
|
+
catalog observation. The llama.cpp runtime record includes `released: true`
|
|
233
|
+
only after Core successfully closes its owned single-model server. Explicit
|
|
234
|
+
load, inference or recovery can resume that engine; observation cannot.
|
|
235
|
+
Status observation adds no background polling.
|
|
236
|
+
|
|
201
237
|
The `payload` is the complete request. SDK option names are translated only at
|
|
202
238
|
the upstream protocol boundary; messages, tool definitions and documents remain
|
|
203
239
|
unchanged. An explicit `payload.model` selects that request's model. Core waits
|
|
@@ -213,7 +249,8 @@ observe load, sleep and unload changes. Direct servers expose readiness at
|
|
|
213
249
|
request boundaries; they do not offer the router's passive model event stream.
|
|
214
250
|
|
|
215
251
|
Unloading a model from an owned single-model server closes that owned process;
|
|
216
|
-
a subsequent load can start it again.
|
|
252
|
+
a subsequent load can start it again. Repeating that unload returns the released
|
|
253
|
+
state without restarting the process. Releasing an externally owned direct
|
|
217
254
|
server returns `released: true, unloaded: false`, retaining the real catalog
|
|
218
255
|
and leaving that server running.
|
|
219
256
|
|
|
@@ -289,6 +326,38 @@ does not install software or select a model. A missing Core connection reports
|
|
|
289
326
|
unavailability, leaving browser Wllama/ONNX routes available for the application
|
|
290
327
|
to select.
|
|
291
328
|
|
|
329
|
+
Omit `client` to follow the installed Core client through
|
|
330
|
+
[`subscribeCoreClient`](core-client.md): construction may precede installation.
|
|
331
|
+
Each installation reads `llama.status` without selecting, downloading or loading
|
|
332
|
+
a model. Retirement or replacement synchronously revokes this provider's
|
|
333
|
+
`status().loaded`, cancels its owned operations and detaches the old lifecycle
|
|
334
|
+
listener. Late results cannot restore the retired selection. Explicitly load
|
|
335
|
+
the selection against the replacement client before inference. Passing a
|
|
336
|
+
`client`, including `null`, keeps that caller-supplied connection fixed.
|
|
337
|
+
|
|
338
|
+
`status()` is this provider's current state. The `arcane-ai-provider/2` contract
|
|
339
|
+
does not provide a provider-state subscription, so this installation handling
|
|
340
|
+
alone does not update an idle AI runtime's retained role state. The provider
|
|
341
|
+
runtime still reconciles the provider at its existing operation boundaries.
|
|
342
|
+
`inspect()` reports whether an explicit load can proceed, separately from
|
|
343
|
+
`status().loaded`. A genuine `starting` or `loading` service without an error
|
|
344
|
+
permits that load preflight even before its catalog arrives; Core's `llama.load`
|
|
345
|
+
waits for startup and verifies the exact requested model. An owned, successfully
|
|
346
|
+
released service permits loading only a model retained in its actual catalog.
|
|
347
|
+
An available service still requires that catalog membership. These observations
|
|
348
|
+
do not fabricate model records or readiness, and unavailable external services,
|
|
349
|
+
closed services and actual errors remain unavailable.
|
|
350
|
+
|
|
351
|
+
`dispose()` removes installation and service subscriptions and cancels owned
|
|
352
|
+
operations synchronously, then attempts its actually retained model's release
|
|
353
|
+
through its captured client. A configured selection alone does not own a native
|
|
354
|
+
model: disposing before load or after successful unload sends no native release,
|
|
355
|
+
including when the caller explicitly supplied `client: null`. A failed release
|
|
356
|
+
rejects with the actual error even though the provider is disposed; disposal
|
|
357
|
+
does not establish successful native unload.
|
|
358
|
+
It never unloads a retired selection through a replacement client or closes the
|
|
359
|
+
shared Core client.
|
|
360
|
+
|
|
292
361
|
If a router evicts the primary model while serving a request-specific model,
|
|
293
362
|
reload the primary selection before its next request. The provider does not
|
|
294
363
|
silently change the application's saved model choice. Release registration
|
|
@@ -316,13 +385,45 @@ try {
|
|
|
316
385
|
```
|
|
317
386
|
|
|
318
387
|
The factory accepts `{modulePath,signal?,onEvent?}` and starts no worker until
|
|
319
|
-
`load({id,model,sessionOptions?,signal?})`. The model path is absolute for this
|
|
388
|
+
`load({id,model,sessionOptions?,executionPreference?,signal?})`. The model path is absolute for this
|
|
320
389
|
direct Node API. Session creation defaults to the CPU execution provider;
|
|
321
390
|
explicit native session options remain caller-owned. The returned session
|
|
322
391
|
record contains `id`, `model`, `state`, `loaded`, `error`, input/output names and
|
|
323
392
|
metadata. A live ID requires explicit unload before replacement. An ID may be
|
|
324
393
|
loaded again once its previous worker exits after a failed load or unload.
|
|
325
394
|
A run error retains the loaded session so a corrected request can use it.
|
|
395
|
+
`current().sessions[].stopping` becomes `true` when terminal shutdown begins,
|
|
396
|
+
including worker failure or explicit cancellation/unload. The session is then
|
|
397
|
+
unavailable for new runs even while `loaded` remains `true` until actual exit.
|
|
398
|
+
A recoverable run error keeps `stopping:false` and the loaded session usable.
|
|
399
|
+
`current().sessions[].exited` reports actual worker exit, independently of a
|
|
400
|
+
rejected load or inference. Unload joins worker exit and output delivery even
|
|
401
|
+
when requesting termination fails; complete cleanup errors remain observable.
|
|
402
|
+
|
|
403
|
+
Select `executionPreference: 'gpu'` to try the installed runtime's advertised
|
|
404
|
+
CUDA, TensorRT, DirectML, CoreML and WebGPU providers in that order, followed by
|
|
405
|
+
CPU when no accelerator session can be created. Discovery runs once per load;
|
|
406
|
+
each advertised candidate receives one actual session-creation attempt with CPU
|
|
407
|
+
available for graph nodes that the accelerator cannot handle. No provider is
|
|
408
|
+
downloaded by selection. The upstream `bundled` flag describes packaging and
|
|
409
|
+
does not exclude separately installed CUDA or TensorRT libraries. An explicit
|
|
410
|
+
`sessionOptions.executionProviders`, including an empty array, takes precedence
|
|
411
|
+
and is passed unchanged without automatic discovery or retries. Automatic
|
|
412
|
+
DirectML attempts default `enableMemPattern` to `false` and `executionMode` to
|
|
413
|
+
`'sequential'` as required by that provider; explicit caller values remain
|
|
414
|
+
unchanged, including on the final CPU attempt.
|
|
415
|
+
|
|
416
|
+
Automatic GPU selection adds an `execution` record to the loaded session and
|
|
417
|
+
its ordinary state events: `preference`, complete `supportedBackends`,
|
|
418
|
+
`selectedProviders`, ordered `attempts` with their full errors, `fallback`, and
|
|
419
|
+
`discoveryError`. Each attempt records `executionProviders`, `status`
|
|
420
|
+
(`configured` or `failed`), and `error`. `fallback: true` means the SDK created
|
|
421
|
+
the final CPU session after GPU preference, including when no GPU candidate was
|
|
422
|
+
advertised. Successful creation establishes an accepted provider configuration;
|
|
423
|
+
it does not establish that a GPU executed any graph nodes. If every attempt
|
|
424
|
+
fails, the load error retains the complete attempt errors and `execution`
|
|
425
|
+
record. Inference failures retain their existing behavior and do not replay
|
|
426
|
+
inference on another provider.
|
|
326
427
|
|
|
327
428
|
`run({id,feeds,fetches?,runOptions?,signal?})` returns the complete output-name
|
|
328
429
|
map of `{type,dims,data}` tensors. Input records use that same shape with native
|
|
@@ -383,6 +484,15 @@ Closing the accessor cancels its requests and subscriptions; model unloading
|
|
|
383
484
|
is explicit because other accessors may share the Core session. It never
|
|
384
485
|
closes the shared Core client.
|
|
385
486
|
|
|
487
|
+
Omitting `client` follows Core installation events with current-client replay,
|
|
488
|
+
including installation after construction. Each new connection reads
|
|
489
|
+
`onnx.status`; it does not install a runtime or load a model. Retirement or
|
|
490
|
+
replacement immediately clears retained session readiness and cancels this
|
|
491
|
+
accessor's operations. Late old-client state and results are ignored. Passing
|
|
492
|
+
an explicit `client`, including `null`, retains caller ownership and does not
|
|
493
|
+
follow global installation changes. `close()` also removes the installation
|
|
494
|
+
subscription.
|
|
495
|
+
|
|
386
496
|
Construction neither opens a connection nor installs a runtime. A browser needs
|
|
387
497
|
an already available native Core service or the explicit development bridge.
|
|
388
498
|
Unavailable native ONNX leaves browser ONNX/Wllama under the application's
|
|
@@ -199,14 +199,16 @@ ordered `Blob` or `File` members after its resumable download. Range support
|
|
|
199
199
|
allows concurrent transfer within a member; those transfer parts remain the
|
|
200
200
|
store's concern. Use `offline: true` to require an already complete stored model.
|
|
201
201
|
The store does not select or run the image engine. In source development,
|
|
202
|
-
|
|
203
|
-
in [Local AI through Core](local-ai.md#development)
|
|
204
|
-
|
|
202
|
+
use the development Core bootstrap described
|
|
203
|
+
in [Local AI through Core](local-ai.md#development). The accessor can be
|
|
204
|
+
constructed before that client is installed; perform model operations once
|
|
205
|
+
the service is available. Native hosts install their Core client through the
|
|
206
|
+
existing host path.
|
|
205
207
|
An ordinary browser without Core reports local image generation as unavailable.
|
|
206
208
|
|
|
207
209
|
| Member | Contract |
|
|
208
210
|
|---|---|
|
|
209
|
-
| `createCoreImageRuntime({client?, signal?, onEvent?})` |
|
|
211
|
+
| `createCoreImageRuntime({client?, signal?, onEvent?})` | Follows Core installation and lifecycle events by default, asynchronously reading status for each client. An explicit `client`, including `null`, remains caller-owned. It returns immediately. |
|
|
210
212
|
| `load({model, context?, assetProjectionId?, resourcePaths?, signal?})` | Loads the selected model and returns authoritative service state after native completion. `context` supplies native context options. |
|
|
211
213
|
| `generate({model, prompt, parameters?, assetProjectionId?, resourcePaths?, signal?, onProgress?})` | Returns the complete result with `images: [{blob, mediaType, width, height}]`. Additional runtime result metadata remains present. |
|
|
212
214
|
| `unload({signal?})` | Explicitly unloads the shared selected native context and returns its resulting state. |
|
|
@@ -229,6 +231,15 @@ model definitions, including their resource metadata before engine preparation
|
|
|
229
231
|
finishes. Installed files do not imply a loaded model. A late status
|
|
230
232
|
response never overwrites a newer lifecycle event.
|
|
231
233
|
|
|
234
|
+
With `client` omitted, the accessor consumes the shared
|
|
235
|
+
[`subscribeCoreClient`](core-client.md) installation stream. A late installation
|
|
236
|
+
attaches the service listener and reads current status; it never installs an
|
|
237
|
+
engine or loads a model. Retirement or replacement synchronously clears
|
|
238
|
+
readiness and transient `Thinking`, cancels owned requests and detaches the
|
|
239
|
+
retired service listener. Old state, progress and results cannot update the
|
|
240
|
+
replacement connection. `close()` also removes the installation subscription;
|
|
241
|
+
it does not claim that the shared native model was unloaded.
|
|
242
|
+
|
|
232
243
|
Prompts and parameters pass unchanged to the native runtime. Native option
|
|
233
244
|
names, supported model operations and defaults belong to that runtime and the
|
|
234
245
|
selected model definition. A prompt containing U+0000 or an unpaired UTF-16
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Native working files from
|
|
1
|
+
# Native working files from model assets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Browser preparation and native retain/release ownership were first published in `arcane-os@0.61.0`. Browser
|
|
4
4
|
preparation is exported by `arcane-os/ai/core-model-assets`, and the native
|
|
5
5
|
service by `arcane-os/core/model-assets`. The image example below uses
|
|
6
6
|
`arcane-os/ai/core-image`, published in the same release.
|
|
@@ -87,6 +87,53 @@ cleanup failures remain observable.
|
|
|
87
87
|
|
|
88
88
|
## Native ownership
|
|
89
89
|
|
|
90
|
+
Native services can prepare explicitly selected upstream members without a
|
|
91
|
+
renderer or browser store. Obtain the registered shared service through
|
|
92
|
+
`await context.getService('model-assets')`, then use its native preparation API:
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const modelAssets = await context.getService('model-assets');
|
|
96
|
+
const projection = await modelAssets.prepare({
|
|
97
|
+
id: selectedOperationId,
|
|
98
|
+
workingDirectory: selectedWorkingDirectory,
|
|
99
|
+
members: selectedMembers, // [{path: 'onnx/model.onnx', url: selectedURL}, ...]
|
|
100
|
+
signal,
|
|
101
|
+
onProgress: renderPreparationProgress
|
|
102
|
+
});
|
|
103
|
+
const use = modelAssets.retain(projection.id);
|
|
104
|
+
await modelAssets.release(projection.id);
|
|
105
|
+
try {
|
|
106
|
+
await ownNativeModelLifetime(use.members);
|
|
107
|
+
} finally {
|
|
108
|
+
// Join actual native unload/worker exit before releasing these files.
|
|
109
|
+
await use.release();
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`prepare({id,workingDirectory,members,signal,onProgress})` performs standard
|
|
114
|
+
fetches only when explicitly called. Every member has its original relative
|
|
115
|
+
`path` and selected `url`; the caller supplies the complete companion-file set.
|
|
116
|
+
Independent members download concurrently. Each complete response stream is
|
|
117
|
+
written directly through the existing ordered native file owner, without a
|
|
118
|
+
whole-model buffer or base64 conversion. No model or runtime is selected or
|
|
119
|
+
downloaded by service startup. The result is the ready projection snapshot with
|
|
120
|
+
ordered `members: [{path,nativePath}]`.
|
|
121
|
+
|
|
122
|
+
Progress uses `open`, `download`, `complete` and `ready` phases, with
|
|
123
|
+
`completed`, `total` and `unit:'files'`; member progress additionally includes
|
|
124
|
+
`memberIndex` and `path`. Progress callbacks may return a promise, which the
|
|
125
|
+
preparation observes. They must not await cleanup of the preparation currently
|
|
126
|
+
calling them. Callback failures remain preparation failures. HTTP failures
|
|
127
|
+
retain `url`, `status` and the complete response text in `response`.
|
|
128
|
+
|
|
129
|
+
`release(id)` relinquishes preparation ownership without a request signal.
|
|
130
|
+
For active native downloads, release or disposal aborts their fetches and joins
|
|
131
|
+
the transfer tasks and native writes before deleting only their owned child
|
|
132
|
+
directory. Preparation cancellation and failure follow that same cleanup path;
|
|
133
|
+
the original failures and cleanup failures remain observable. A native retain
|
|
134
|
+
handle continues to protect completed files through actual engine release.
|
|
135
|
+
Native preparation leaves browser DBOPFS originals and unrelated files alone.
|
|
136
|
+
|
|
90
137
|
```javascript
|
|
91
138
|
import {createModelAssetService} from 'arcane-os/core/model-assets';
|
|
92
139
|
|
|
@@ -103,7 +150,7 @@ try {
|
|
|
103
150
|
```
|
|
104
151
|
|
|
105
152
|
`createModelAssetService({appRoot})` returns a Core service with `current()`,
|
|
106
|
-
`retain(id)` and `dispose()`. `retain()` accepts only a completed projection
|
|
153
|
+
`prepare(options)`, `retain(id)`, `release(id)` and `dispose()`. `retain()` accepts only a completed projection
|
|
107
154
|
and returns `{id,directory,members,release}`. A native engine takes this handle
|
|
108
155
|
before loading and releases it after actual unload, failed-load cleanup or
|
|
109
156
|
worker exit. A rejected inference/load promise alone does not establish native
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Native Laya typed decisions
|
|
2
|
+
|
|
3
|
+
`arcane-os/local-ai/decisions` and `arcane-os/core/decisions` run the selected
|
|
4
|
+
Laya FP32 graph through the SDK's existing native ONNX owner. Tokenization runs
|
|
5
|
+
in its own Node Worker. A Core service can load and evaluate decisions without
|
|
6
|
+
a renderer, browser session, WebGPU browser context or chat provider.
|
|
7
|
+
|
|
8
|
+
The application owns the model selection, original state text, questions,
|
|
9
|
+
options and interpretation. The SDK owns model preparation, token framing,
|
|
10
|
+
inference and cleanup. This is option scoring, not a conversational LLM, a
|
|
11
|
+
replacement for a configured chat model or the cloud System One API.
|
|
12
|
+
|
|
13
|
+
## Compose with existing Core services
|
|
14
|
+
|
|
15
|
+
Register a decision service alongside the selected local-AI and model-assets
|
|
16
|
+
services in the application's existing Core runtime:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import {createNativeDecisionService} from 'arcane-os/core/decisions';
|
|
20
|
+
|
|
21
|
+
const decisions = createNativeDecisionService({
|
|
22
|
+
model: 'onnx-community/laya-typed-decisions-ONNX',
|
|
23
|
+
dtype: 'fp32',
|
|
24
|
+
workingDirectory: '.models/laya'
|
|
25
|
+
}, {appRoot});
|
|
26
|
+
|
|
27
|
+
// Include decisions in the existing createCoreRuntime({services}) selection.
|
|
28
|
+
// That runtime already owns local-ai with ONNX selected and model-assets.
|
|
29
|
+
await runtime.getService('decisions');
|
|
30
|
+
await decisions.load(); // Explicit activation; no model download at registration.
|
|
31
|
+
try {
|
|
32
|
+
const result = await decisions.evaluate([{
|
|
33
|
+
state: 'The moon chef has one kettle and seventeen impatient dragons.',
|
|
34
|
+
question: 'What should the chef prepare?',
|
|
35
|
+
options: ['Tea', 'An inflatable castle']
|
|
36
|
+
}]);
|
|
37
|
+
console.log(result.decisions[0].value);
|
|
38
|
+
} finally {
|
|
39
|
+
await decisions.unload();
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Here `runtime` and `appRoot` are the application's existing Core runtime and
|
|
44
|
+
root. Add the service before starting that runtime; the example does not create
|
|
45
|
+
a second Core host or engine. Development and packaged native compositions
|
|
46
|
+
already register one model-assets service when ONNX is selected. The decision
|
|
47
|
+
service obtains those exact owners with `context.getService('local-ai')`,
|
|
48
|
+
`localAI.getONNXRuntime()` and `context.getService('model-assets')` on explicit
|
|
49
|
+
load. It reacquires the current ONNX owner after a later runtime recovery.
|
|
50
|
+
See [Core composition](core-runtime.md#native-service-composition) and
|
|
51
|
+
[native service owners](local-ai.md#native-service-owners).
|
|
52
|
+
|
|
53
|
+
`createNativeDecisionService(configuration, {appRoot})` defaults its service
|
|
54
|
+
name to `decisions`. It exposes `load`, `evaluate`, `classify` (an alias for
|
|
55
|
+
`evaluate`), `current`, `subscribe`, `unload` and `dispose`, plus Core lifecycle
|
|
56
|
+
`start(context)`. Its RPC methods are:
|
|
57
|
+
|
|
58
|
+
| Method | Parameters and result |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `decisions.status` | Current lifecycle snapshot; does not load anything. |
|
|
61
|
+
| `decisions.load` | Explicit activation; returns the ready lifecycle snapshot. The request signal cancels activation. |
|
|
62
|
+
| `decisions.evaluate` | `{rows, runOptions?}`; returns `{decisions, outputs}`. The request signal cancels the active model operation. |
|
|
63
|
+
| `decisions.unload` | Releases the activation. Service-lifetime cleanup continues after the caller disconnects. |
|
|
64
|
+
|
|
65
|
+
RPC evaluation uses the SDK's existing complete JSON tensor encoding for
|
|
66
|
+
`outputs` at the transport boundary. Direct native evaluation returns native
|
|
67
|
+
typed tensor records. Service notifications use `decisions.state`; direct
|
|
68
|
+
`subscribe(listener, {emitCurrent:true, signal})` replays current state by
|
|
69
|
+
default and returns an unsubscribe function. Startup stores the service
|
|
70
|
+
context only: importing or registering this service starts no tokenizer,
|
|
71
|
+
model download or inference.
|
|
72
|
+
|
|
73
|
+
## Direct native model
|
|
74
|
+
|
|
75
|
+
`createNativeDecisionModel(options)` from `arcane-os/local-ai/decisions` returns
|
|
76
|
+
`{load, evaluate, classify, current, status, subscribe, unload, dispose}`.
|
|
77
|
+
`status` aliases `current`; `classify` aliases `evaluate`. Supply the existing
|
|
78
|
+
native `onnx` owner, plus either the existing `modelAssets` owner and selected
|
|
79
|
+
`workingDirectory`, or caller-owned native files:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
import {createNativeDecisionModel} from 'arcane-os/local-ai/decisions';
|
|
83
|
+
|
|
84
|
+
const decisions = createNativeDecisionModel({
|
|
85
|
+
onnx: localAI.getONNXRuntime(),
|
|
86
|
+
paths: {
|
|
87
|
+
model: selectedGraphPath,
|
|
88
|
+
tokenizer: selectedTokenizerPath,
|
|
89
|
+
tokenizerConfig: selectedTokenizerConfigPath
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
These direct paths are native filesystem paths. Keep the graph's external data
|
|
95
|
+
beside it under the exact filename required by the graph. The Core service
|
|
96
|
+
resolves configured `paths` relative to `appRoot`; it does not copy or remove
|
|
97
|
+
caller-owned files. For SDK-prepared files, the default selected upstream is
|
|
98
|
+
`onnx-community/laya-typed-decisions-ONNX`, revision `main`, with exactly:
|
|
99
|
+
|
|
100
|
+
- `onnx/model.onnx` and `onnx/model.onnx_data`;
|
|
101
|
+
- `tokenizer.json` and `tokenizer_config.json`.
|
|
102
|
+
|
|
103
|
+
`model` selects the upstream Hugging Face repository and `revision` its
|
|
104
|
+
revision. Native preparation performs normal upstream fetches only during
|
|
105
|
+
explicit `load()`. It streams complete members through the existing working
|
|
106
|
+
file owner; it neither vendors the weights nor creates a second persistent
|
|
107
|
+
model store. The approved `@huggingface/tokenizers@0.2.0` dependency reads the
|
|
108
|
+
selected tokenizer files in its Worker. No Transformers or second ONNX runtime
|
|
109
|
+
is loaded by this API.
|
|
110
|
+
|
|
111
|
+
This graph selection requires `dtype:'fp32'`, which is also the default; another
|
|
112
|
+
dtype reports the incompatible selection rather than substituting a graph.
|
|
113
|
+
`sessionOptions` and `runOptions` pass to the existing native ONNX API unchanged.
|
|
114
|
+
`executionPreference` defaults to `gpu` here: actual advertised native GPU
|
|
115
|
+
provider creation is attempted, followed by an honest CPU fallback. Explicit
|
|
116
|
+
`sessionOptions.executionProviders` takes precedence. The underlying generic
|
|
117
|
+
ONNX factory continues to default to CPU. Accepted provider configuration is
|
|
118
|
+
not evidence that GPU nodes executed. Full provider-attempt diagnostics remain
|
|
119
|
+
in `execution`; see [native ONNX sessions](local-ai.md#native-onnx-sessions).
|
|
120
|
+
|
|
121
|
+
## Complete inputs and outputs
|
|
122
|
+
|
|
123
|
+
`evaluate(rows, {signal, runOptions})` requires an explicitly loaded or loading
|
|
124
|
+
activation; it does not silently load an inactive model. Rows retain their
|
|
125
|
+
caller order, complete `state`, `question` and string-array `options`, plus
|
|
126
|
+
optional `type` (`choice`, `score` or `noul`). Additional row fields remain in
|
|
127
|
+
the returned row. Strings are not trimmed, rewritten or clipped. The shared
|
|
128
|
+
browser/native encoding owner constructs only the model's necessary token
|
|
129
|
+
framing; repeated identical state is tokenized once per batch. Tokenization
|
|
130
|
+
and ONNX execution run outside Core's foreground thread.
|
|
131
|
+
|
|
132
|
+
The result is `{decisions, outputs}`. Each decision contains its original
|
|
133
|
+
`row`, complete option `logits`, unrounded raw-softmax `probabilities`,
|
|
134
|
+
`answerIndex` and `value`. `choice` returns the selected complete option;
|
|
135
|
+
`score` returns the probability-weighted zero-based option index; `noul`
|
|
136
|
+
requires `[falseOption, trueOption]` and returns the probability of option 1.
|
|
137
|
+
When the graph actually supplies `act_logits`, action logits, probabilities
|
|
138
|
+
and `actProbability` are also returned. Every named graph output is retained
|
|
139
|
+
as `{type, dims, data}`, including extra tensors and padding. Raw model scores
|
|
140
|
+
are not claimed calibrated confidence. Results do not enter chat history,
|
|
141
|
+
memory extraction or DBOPFS automatically.
|
|
142
|
+
|
|
143
|
+
The model's real graph/context limits still apply. There is no SDK token cap,
|
|
144
|
+
silent chunking or fabricated result aggregation. Native/browser token-ID or
|
|
145
|
+
numerical parity requires execution evidence for the selected tokenizer and
|
|
146
|
+
runtime; sharing the encoding implementation alone does not establish it.
|
|
147
|
+
|
|
148
|
+
## Lifetime and cancellation
|
|
149
|
+
|
|
150
|
+
`current()` returns `{family, model, revision, dtype, state, loaded, busy,
|
|
151
|
+
activeRequests, progress, error, execution}`. States include `unloaded`,
|
|
152
|
+
`loading`, `ready`, `unloading`, `disposing`, `disposed` and `error`. Semantic
|
|
153
|
+
progress includes model preparation, tokenization and evaluation; downloaded
|
|
154
|
+
members report files, not byte progress. Complete technical errors belong in
|
|
155
|
+
developer diagnostics, while the application owns its user-facing status.
|
|
156
|
+
|
|
157
|
+
Concurrent callers share one explicit activation. Cancelling a load or
|
|
158
|
+
evaluation cancels that activation and its outstanding operations, because the
|
|
159
|
+
native session and tokenizer have one owner. Use separately owned models when
|
|
160
|
+
independent cancellation is required. The construction `signal` governs the
|
|
161
|
+
whole model lifetime. `unload()` permits another explicit load after successful
|
|
162
|
+
cleanup; `dispose()` is terminal. Readiness is revoked as disposal begins.
|
|
163
|
+
|
|
164
|
+
Retained model files remain owned until the ONNX and tokenizer Workers really
|
|
165
|
+
exit. A rejected load, inference or termination request alone does not permit
|
|
166
|
+
file deletion. Cleanup joins active operations and native output delivery,
|
|
167
|
+
preserves cleanup errors, then releases only its working projection. It never
|
|
168
|
+
deletes supplied `paths`. A failed ordinary row does not destroy a healthy
|
|
169
|
+
loaded session or cancel sibling evaluations. The ONNX owner's `stopping:true`
|
|
170
|
+
retires decision readiness immediately on terminal Worker failure or shutdown,
|
|
171
|
+
even while its physical `loaded` state remains true pending actual exit. Cancelled or
|
|
172
|
+
retired operations cannot return a successful late result.
|
|
173
|
+
|
|
174
|
+
Shared Node/Worker/filesystem code is portable across Windows, Linux and macOS;
|
|
175
|
+
the selected ONNX Runtime build and provider determine actual platform/device
|
|
176
|
+
availability. Android requires the host's supported native adaptation. Static
|
|
177
|
+
source review and synthetic authored fixtures are not model execution or a
|
|
178
|
+
claim of tested platform, precision or accelerator behavior.
|
|
179
|
+
|
|
180
|
+
Upstream selection: [Laya FP32 model files](https://huggingface.co/onnx-community/laya-typed-decisions-ONNX/tree/main),
|
|
181
|
+
[Tokenizer package](https://www.npmjs.com/package/@huggingface/tokenizers).
|
|
@@ -112,7 +112,7 @@ snapshot remains owned until the browser's `afterprint` event.
|
|
|
112
112
|
| [`task-progress.html`](#task-progresshtml) | Runs and displays a task list with started/change/complete/error state. | `configure()`<br>`setTasks()`<br>`updateTask()`<br>`runTasks()`<br>`clear()`<br>`destroy()` | `task-progress-ready`<br>`task-progress-started`<br>`task-progress-change`<br>`task-progress-complete`<br>`task-progress-error` | Task state normalized; injected task results mixed |
|
|
113
113
|
| [`terminal-workspace.html`](#terminal-workspacehtml) | Presents multiple terminal sessions, output, active selection, theme, and terminal actions. | `configure()`<br>`addSession()`<br>`removeSession()`<br>`activateSession()`<br>`append()`<br>`clear()`<br>`setState()`<br>`setTheme()`<br>`focus()`<br>`destroy()` | `terminal-workspace-ready`<br>`terminal-submit`<br>`terminal-interrupt`<br>`terminal-clear`<br>`terminal-session-new`<br>`terminal-session-close`<br>`terminal-session-select`<br>`terminal-settings` | UI/session state normalized; native command results supplied externally |
|
|
114
114
|
| [`theme-editor.html`](#theme-editorhtml) | Edits, previews, saves, and resets semantic custom theme tokens. | `configure()`<br>`getTheme()`<br>`setTheme()`<br>`setBusy()`<br>`setStatus()`<br>`destroy()` | `theme-editor-ready`<br>`theme-preview`<br>`theme-save`<br>`theme-reset` | Fully normalized Theme values |
|
|
115
|
-
| [`theme-switcher.html`](#theme-switcherhtml) | Selects and refreshes system, light, dark, or custom theme mode. | `setMode()`<br>`refresh()` | No component-specific event | Preference/native appearance behavior mixed; no component-ready contract |
|
|
115
|
+
| [`theme-switcher.html`](#theme-switcherhtml) | Selects and refreshes system, light, dark, or custom theme mode with per-instance choices and labels. | `configure()`<br>`setMode()`<br>`refresh()` | No component-specific event | Preference/native appearance behavior mixed; no component-ready contract |
|
|
116
116
|
| [`unified-inbox.html`](#unified-inboxhtml) | Displays provider-neutral communication threads with active/loading state. | `configure()`<br>`setThreads()`<br>`setActive()`<br>`setLoading()`<br>`destroy()` | `unified-inbox-ready`<br>`inbox-refresh`<br>`thread-select` | DOM-normalized |
|
|
117
117
|
| [`voice-transcription.html`](#voice-transcriptionhtml) | Records manual clips or optional continuous microphone audio with pause/periodic segments, ordered transcription and saves, retained failures, and complete transcript delivery. | `configure()`<br>`requestSTTActivation()`<br>`startRecording()`<br>`stopRecording()`<br>`retryTranscription()`<br>`cancelRecording()`<br>`save()`<br>`completeTranscription()/complete()`<br>`clear()`<br>`reset()`<br>`destroy()` | `voice-transcription-ready`<br>`voice-transcription-state`<br>`voice-transcription-segment`<br>`voice-transcription-empty`<br>`voice-transcription-error`<br>`voice-transcription-change`<br>`voice-transcription-complete`<br>`speech-transcription-complete`<br>`speech-transcription-cancelled`<br>`speech-stt-activation-request`<br>`speech-stt-activation-error` | Sticky STT readiness, capture/queue lifecycle, retry, cancellation, and complete state/text are normalized; media/provider behavior remains external |
|
|
118
118
|
| [`weather-widget.html`](#weather-widgethtml) | Displays normalized current and daily weather with refresh intent. | `setWeather()`<br>`clear()`<br>`destroy()` | `weather-widget-ready`<br>`weather-refresh` | Display normalized; provider supplied externally |
|
|
@@ -2015,11 +2015,61 @@ Shared dependencies: [`Theme.js`](runtime-entities.md#themejs).
|
|
|
2015
2015
|
|
|
2016
2016
|
### Overview
|
|
2017
2017
|
|
|
2018
|
-
Selects and refreshes system, light, dark, or custom theme mode.
|
|
2018
|
+
Selects and refreshes system, light, dark, or custom theme mode. Native buttons
|
|
2019
|
+
retain complete readable labels and wrap when their component runs out of room,
|
|
2020
|
+
independently of viewport width. Each button has a `2.75rem` minimum target in
|
|
2021
|
+
both dimensions. Selected buttons retain `aria-pressed` and an inset outline;
|
|
2022
|
+
disabled choices and keyboard focus have distinct presentation.
|
|
2019
2023
|
|
|
2020
2024
|
### Public surface
|
|
2021
2025
|
|
|
2022
|
-
Methods/properties: `setMode()`, `refresh()`.
|
|
2026
|
+
Methods/properties: `configure(options)`, `setMode(mode='system')`, `refresh()`.
|
|
2027
|
+
|
|
2028
|
+
`configure({modes,labels})` changes only this component's presentation:
|
|
2029
|
+
|
|
2030
|
+
- `modes` is an ordered array of the available identifiers `system`, `light`,
|
|
2031
|
+
`dark`, and `custom`. It selects both visible choices and DOM/keyboard order.
|
|
2032
|
+
Omitted `modes` retains the current presentation; an empty array displays no
|
|
2033
|
+
choices. Unknown or repeated identifiers throw `TypeError` before changing
|
|
2034
|
+
the presentation.
|
|
2035
|
+
- `labels` is a partial record of complete string labels keyed by those mode
|
|
2036
|
+
identifiers. Omitted labels keep their current text. Text is assigned through
|
|
2037
|
+
`textContent`, never interpreted as markup or reduced to initials. A label for
|
|
2038
|
+
a built-in mode that is not a string throws `TypeError`.
|
|
2039
|
+
- The return value is `{modes,labels}` containing independent mutable copies of
|
|
2040
|
+
the current presentation. Later changes to supplied/returned records do not
|
|
2041
|
+
reconfigure the component.
|
|
2042
|
+
|
|
2043
|
+
Label-only and unchanged-order configuration retain the existing buttons in
|
|
2044
|
+
place. An actual reorder restores keyboard focus to the previously focused
|
|
2045
|
+
button when that choice remains visible and enabled, without scrolling.
|
|
2046
|
+
|
|
2047
|
+
The default remains Auto / Light / Dark / Skin, using identifiers
|
|
2048
|
+
`system`, `light`, `dark`, and `custom`. A caller may omit Skin or change Auto's
|
|
2049
|
+
label to System without removing custom-theme support from other instances.
|
|
2050
|
+
Configuration never changes preferences, activates a theme, or replaces the
|
|
2051
|
+
current selected mode. If the active mode is omitted, no visible button claims
|
|
2052
|
+
to be selected. Restoring that choice restores its existing pressed and disabled
|
|
2053
|
+
state. Skin remains disabled until the manager has a saved custom theme.
|
|
2054
|
+
|
|
2055
|
+
For the initial presentation, `data-modes` accepts whitespace-separated mode
|
|
2056
|
+
identifiers and `data-system-label` supplies the complete system-mode label.
|
|
2057
|
+
These attributes are read once before the asynchronous ThemeManager import and
|
|
2058
|
+
preference refresh, so initial choices do not wait for `html-import-ready`.
|
|
2059
|
+
Use `configure()` after that event for subsequent presentation changes;
|
|
2060
|
+
changing these attributes later does not reconfigure an existing instance.
|
|
2061
|
+
|
|
2062
|
+
`setMode()` updates pressed state and the host's `data-mode` only. `refresh()`
|
|
2063
|
+
loads the existing ThemeManager state, updates selection and Skin availability,
|
|
2064
|
+
and resolves with the complete manager state. Clicking a choice uses the same
|
|
2065
|
+
manager persistence/activation operation; buttons remain disabled while that
|
|
2066
|
+
operation is pending. Presentation configuration preserves that pending state.
|
|
2067
|
+
|
|
2068
|
+
The host inherits text color. Existing `--app-bar-border` (falling back to
|
|
2069
|
+
`--border-color`), `--app-bar-accent` (then `--secondary-color`),
|
|
2070
|
+
`--app-bar-active-text` (then `--primary-color`), and `--focus-color` overrides
|
|
2071
|
+
remain supported. Applications own their palette and surrounding placement;
|
|
2072
|
+
the component adds no application-specific palette or settings section.
|
|
2023
2073
|
|
|
2024
2074
|
This fragment declares no component-specific readiness or action event; use the loader's `html-import-ready` only to know that import execution completed.
|
|
2025
2075
|
|
|
@@ -2033,11 +2083,18 @@ Shared dependencies: [`ThemeManager.js`](runtime-modules.md#thememanagerjs).
|
|
|
2033
2083
|
|
|
2034
2084
|
```html
|
|
2035
2085
|
<html-import
|
|
2036
|
-
id="theme-switcher
|
|
2037
|
-
href="/arcane/components/theme-switcher.html"
|
|
2086
|
+
id="theme-switcher"
|
|
2087
|
+
href="/node_modules/arcane-os/runtime/arcane/components/theme-switcher.html"
|
|
2088
|
+
data-modes="light dark system"
|
|
2089
|
+
data-system-label="System">
|
|
2038
2090
|
</html-import>
|
|
2039
2091
|
```
|
|
2040
2092
|
|
|
2093
|
+
This instance displays Light / Dark / System in that order. An instance without
|
|
2094
|
+
the two configuration attributes retains all four default choices. Both use
|
|
2095
|
+
the existing shared preference owner; presentation does not create a new store
|
|
2096
|
+
or migrate saved themes.
|
|
2097
|
+
|
|
2041
2098
|
## unified-inbox.html
|
|
2042
2099
|
|
|
2043
2100
|
### Overview
|
|
@@ -120,7 +120,7 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
120
120
|
| [`OllamaSettings.js`](#ollamasettingsjs) | esm | Defines complete runtime/service preference schemas and deterministic Arcane brain alias names. | Cross-host | Fully normalized settings/name contract. |
|
|
121
121
|
| [`OpenMeteoWeatherProvider.js`](#openmeteoweatherproviderjs) | esm | Searches and loads Open-Meteo data into complete mutable Arcane weather entities. | Browser / native WebView / server with fetch + cloud | Provider data normalized to mutable entities; transport errors mixed. |
|
|
122
122
|
| [`PersistentAIChatSession.js`](#persistentaichatsessionjs) | esm | Adds explicit retained-history/memory policy to complete configured chat without changing DBOPFS or ChatEntity semantics. | Browser / native WebView with DBOPFS and configured chat | Retained context commits atomically; `persist:false` turns are one-operation-only. |
|
|
123
|
-
| [`PreferenceStore.js`](#preferencestorejs) | esm | Loads and updates schema-defined app preferences through native storage with a narrow browser fallback. | Browser/native hybrid | Complete
|
|
123
|
+
| [`PreferenceStore.js`](#preferencestorejs) | esm | Loads and updates schema-defined app preferences through native storage with a narrow browser fallback. | Browser/native hybrid | Complete values and operation context retained; exact optional namespace absence or existing Android unsupported capability selects the existing local adapter; partial-service and genuine failures remain errors; an advertised rejected batch is never retried serially. |
|
|
124
124
|
| [`PreparedSpeech.js`](#preparedspeechjs) | esm | Owns detached ordered preparation, semantic audio reuse, and per-caller cancellation behind AI.prepareTTS. | Browser / native WebView with injected synthesis and optional DBOPFS | Complete original inputs, ordered audio metadata, durable reuse, and observable preparation results. |
|
|
125
125
|
| [`PrintView.js`](#printviewjs) | esm | Prints current rendered content and title through one document-owned print lifecycle. | Browser / supported native WebView print implementation | Complete rendered snapshot, preparation cancellation, resource lifetime, and honest request result. |
|
|
126
126
|
| [`QRCode.min.js`](#qrcodeminjs) | classic-script | Vendored QRCode generator for DOM, canvas, SVG, and image output. | Browser vendor script | Vendor-native. |
|
|
@@ -134,7 +134,7 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
134
134
|
| [`ScreenCapture.js`](#screencapturejs) | esm | Captures a display surface as image, video, or GIF with explicit lifecycle events. | Browser / native WebView | State/events normalized; permission and codec errors mixed. |
|
|
135
135
|
| [`SpeechPlayback.js`](#speechplaybackjs) | esm | Admits complete speech segments to a capacity-advertising provider immediately, retains serialized native/custom lookahead, and plays every result in exact indexed order. | Browser + native bridge | Stored part text stays exact; the outbound speech-input copy receives automatic formatting-mark cleanup; provider/media failures remain mixed. |
|
|
136
136
|
| [`StaticDocumentCatalog.js`](#staticdocumentcatalogjs) | esm | Loads a positive static document inventory with cache, search, and complete context. | Browser / native WebView / server with fetch | Mutable complete catalog/content normalization; malformed data and transport failures remain visible. |
|
|
137
|
-
| [`SystemAppearance.js`](#systemappearancejs) | esm | Reads or applies native appearance, returning an explicit unsupported
|
|
137
|
+
| [`SystemAppearance.js`](#systemappearancejs) | esm | Reads or applies native appearance, returning an explicit unsupported result when the bridge or optional namespace is absent. | Browser/native hybrid | Exact absent optional namespace normalized with its complete error; partial-method and genuine native errors preserved. |
|
|
138
138
|
| [`SystemPlatformPresentation.js`](#systemplatformpresentationjs) | classic-script | Maps kernel names to presentation labels/classes without granting platform authority. | Browser / native WebView classic script | Fully normalized presentation only. |
|
|
139
139
|
| [`SystemToolRegistry.js`](#systemtoolregistryjs) | esm | Registers validated command builders and constructs command strings without executing them. | Cross-host | Fully normalized definitions/quoting. |
|
|
140
140
|
| [`TerminalClient.js`](#terminalclientjs) | esm | Maps native terminal sessions and Arcane events into an EventTarget client. | Native bridge | Client events/state normalized; native result/error mixed. |
|
|
@@ -3475,9 +3475,31 @@ Exact exports: `PREFERENCE_STORE_ERROR_CODES`,
|
|
|
3475
3475
|
|
|
3476
3476
|
**Browser/native hybrid.** Complete ordinary values and returned snapshots remain
|
|
3477
3477
|
mutable after schema normalization. Non-Android
|
|
3478
|
-
`Arcane.preferences.setMany()` supplies the optional atomic batch.
|
|
3479
|
-
|
|
3480
|
-
|
|
3478
|
+
`Arcane.preferences.setMany()` supplies the optional atomic batch. The default
|
|
3479
|
+
adapter uses the existing app-scoped localStorage owner when there is no native
|
|
3480
|
+
preferences facade, on the existing Android route, or after either the existing
|
|
3481
|
+
`ANDROID_CAPABILITY_UNSUPPORTED` error or an exact Core lookup error:
|
|
3482
|
+
`code:'METHOD_NOT_ALLOWED'`, `reason:'core-namespace-unavailable'`,
|
|
3483
|
+
`namespace:'preferences'`, and `method:'preferences.<current operation>'`.
|
|
3484
|
+
This marker proves the entire optional namespace was absent before dispatch.
|
|
3485
|
+
A missing method in a partial/read-only service, an older unmarked error,
|
|
3486
|
+
permission denial, persistence failure, transport error, or cancellation never
|
|
3487
|
+
selects local storage. Explicit caller adapters retain their own behavior.
|
|
3488
|
+
|
|
3489
|
+
For `get`, `set`, and `delete`, that positively absent namespace retries the
|
|
3490
|
+
same operation once through the existing local adapter, then keeps that adapter
|
|
3491
|
+
for the store's later operations. Complete arguments and the existing
|
|
3492
|
+
`{operationId,signal}` context are retained. Disposal and caller cancellation
|
|
3493
|
+
are checked before selecting or invoking the local adapter, so a late native
|
|
3494
|
+
absence result cannot start a cancelled local write. No data location, schema,
|
|
3495
|
+
saved value, or migration is introduced.
|
|
3496
|
+
|
|
3497
|
+
An in-flight advertised `setMany` batch is never downgraded to serial writes
|
|
3498
|
+
after rejection. Exact namespace absence selects the local adapter for later
|
|
3499
|
+
operations and preserves that batch's original rejection with no local write.
|
|
3500
|
+
ThemeManager's first Light/Dark/System choice uses two ordinary `set` calls,
|
|
3501
|
+
not a batch: both may complete through the existing local owner before the
|
|
3502
|
+
selected theme is applied. Its persistence-first ordering is unchanged.
|
|
3481
3503
|
If cancellation settles after a native batch was dispatched, reload the store to
|
|
3482
3504
|
reconcile any atomic host commit that completed before cancellation. Transport:
|
|
3483
3505
|
Arcane.preferences or app-scoped localStorage. [Deep protocol details](protocols.md).
|
|
@@ -4064,7 +4086,8 @@ console.log(Object.keys(module));
|
|
|
4064
4086
|
|
|
4065
4087
|
### Overview
|
|
4066
4088
|
|
|
4067
|
-
Reads or applies native appearance, returning an explicit unsupported
|
|
4089
|
+
Reads or applies native appearance, returning an explicit unsupported result
|
|
4090
|
+
when the bridge or its optional namespace is absent.
|
|
4068
4091
|
|
|
4069
4092
|
### Public surface
|
|
4070
4093
|
|
|
@@ -4074,7 +4097,21 @@ Exact exports: `default`.
|
|
|
4074
4097
|
|
|
4075
4098
|
### Availability and normalization
|
|
4076
4099
|
|
|
4077
|
-
**Browser/native hybrid.**
|
|
4100
|
+
**Browser/native hybrid.** No bridge or callable method retains the existing
|
|
4101
|
+
`{supported:false,platform:'browser'}` result. A callable facade is not proof of
|
|
4102
|
+
an installed service: `available()` reports callable `apply` presence only.
|
|
4103
|
+
`current()` and `apply()` recognize only a matching Core
|
|
4104
|
+
`METHOD_NOT_ALLOWED` error with `reason:'core-namespace-unavailable'`,
|
|
4105
|
+
`namespace:'appearance'`, and the exact requested method. They return
|
|
4106
|
+
`{supported:false,reason:'core-namespace-unavailable',error}`, retaining the
|
|
4107
|
+
complete original error for diagnostics and making no platform or native
|
|
4108
|
+
application claim. Absence is not cached, so later service registration can
|
|
4109
|
+
serve the next operation. Partial-method absence, unmarked permission errors,
|
|
4110
|
+
transport/cancellation failures and all other native errors reject unchanged.
|
|
4111
|
+
Native success values and existing appearance input normalization remain
|
|
4112
|
+
unchanged. ThemeManager may therefore complete a browser color-scheme change
|
|
4113
|
+
when native appearance is explicitly unsupported, while genuine failures stay
|
|
4114
|
+
observable. Transport: Arcane.appearance. [Deep protocol details](protocols.md).
|
|
4078
4115
|
|
|
4079
4116
|
### Example
|
|
4080
4117
|
|