arcane-os 0.67.0 → 0.69.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 CHANGED
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.69.0
4
+
5
+ - Add explicit `textFormat:'plain'` speech input through prepared speech,
6
+ direct TTS requests and the browser Kokoro provider. Preserve complete input,
7
+ whitespace and formatting characters, original-part cache identity and
8
+ cancellation while leaving default narration behavior unchanged. This input
9
+ option does not change the selected engine's synthesis limits.
10
+ - Add optional `native.window` width, height and resizable configuration.
11
+ Forward logical client dimensions through native manifests; the matching
12
+ Windows host applies initial DPI-aware usable-screen fitting while preserving
13
+ omitted defaults and subsequent application/user sizing. Other platform
14
+ adapters retain their existing sizing behavior.
15
+ - Preserve selected theme-switcher colors during hover by applying ordinary
16
+ hover fill only to unselected enabled buttons. Keep complete labels, focus,
17
+ disabled states, tokens and per-instance configuration unchanged.
18
+
19
+ ## 0.68.0
20
+
21
+ - Add per-instance theme-switcher `configure({modes,labels})` and initial
22
+ `data-modes` / `data-system-label` presentation. Applications can select
23
+ Light / Dark / System with complete readable labels while the default
24
+ Auto / Light / Dark / Skin choices remain unchanged. Preserve selected,
25
+ disabled and keyboard-focus states with wrapping based on component space.
26
+ - Distinguish a wholly absent Core namespace from a missing method in a
27
+ registered service. Retain `METHOD_NOT_ALLOWED` and add exact `method`,
28
+ `namespace` and `reason` lookup metadata; genuine handler errors remain intact.
29
+ - Let the default preference adapter complete single operations through its
30
+ existing app-scoped local store only after an exact absent preferences
31
+ namespace response, retaining cancellation, disposal and full values.
32
+ An advertised rejected atomic batch is never retried as serial writes.
33
+ - Treat an exactly absent optional appearance namespace as unsupported, keeping
34
+ the original diagnostic. Preserve partial-service and genuine errors, the
35
+ existing theme persistence order, native window theming and app-owned host
36
+ preferences. No OS-wide appearance change, migration or dependency is added.
37
+
3
38
  ## 0.67.0
4
39
 
5
40
  - Add native Laya FP32 typed decisions through `arcane-os/local-ai/decisions`
package/README.md CHANGED
@@ -20,7 +20,7 @@ selected SDK projection or an explicit live SDK source mount. Both profiles
20
20
  share the theme, packaging, event, cancellation,
21
21
  and browser run contracts while retaining their selected application layout.
22
22
 
23
- This checkout defines the `0.67.0` SDK contract. Development applications declare
23
+ This checkout defines the `0.69.0` SDK contract. Development applications declare
24
24
  `arcane-os` as `latest` and retain their lockfile. Exact SDK pins begin when Roshi
25
25
  designates a production build. Follow [Consumer updates](docs/consumer-updates.md)
26
26
  to refresh and compare the installed SDK and lockfile with the published channel;
@@ -469,11 +469,16 @@ keeping apostrophes, commas, and hyphens that join Unicode letters or numbers
469
469
  inside the same segment.
470
470
  Mute, stop, provider transition, and cancellation still govern the whole queue.
471
471
 
472
- Every TTS call automatically removes repeated same formatting marks (`*`, `#`,
472
+ TTS narration removes repeated same formatting marks (`*`, `#`,
473
473
  `_`, backtick, `~`) from its outbound speech-input copy before synthesis.
474
474
  Streaming calls also recognize a run split across chunks. Single marks and
475
- ordinary repeated punctuation remain literal. No application option is needed;
476
- an existing `textFormat` extra is ignored and cannot disable cleanup. Original
475
+ ordinary repeated punctuation remain literal. Complete synthesis calls may
476
+ select `textFormat:'plain'` to preserve exact input: supply it in `prepareTTS`
477
+ options or the payload of `fetchTTS`, provider-runtime TTS requests, or direct
478
+ Kokoro requests. The SDK consumes this control before engine/host dispatch;
479
+ omission keeps the default cleanup. Streaming narration and `SpeechPlayback`
480
+ retain their existing formatting behavior. This option does not change the
481
+ selected engine's input capacity or establish complete upstream synthesis. Original
477
482
  messages and caller payloads remain unchanged for display, storage, and model
478
483
  input. The `arcane-os/speech-text` entrypoint exports the same
479
484
  `MarkdownSpeech` streaming class and `stripSpeechFormatting()` one-pass helper
@@ -906,7 +906,7 @@ function normalizeSynthesisPayload(payload, authority, speechInputPrepared) {
906
906
  if (shared) {
907
907
  descriptors = genericPayloadDescriptors(
908
908
  payload,
909
- ["model", "voice", "input", "responseFormat", "speed"],
909
+ ["model", "voice", "input", "textFormat", "responseFormat", "speed"],
910
910
  ["model", "input", "responseFormat"],
911
911
  "Shared speech synthesis payload",
912
912
  "tts-synthesis",
@@ -927,7 +927,7 @@ function normalizeSynthesisPayload(payload, authority, speechInputPrepared) {
927
927
  } else {
928
928
  descriptors = genericPayloadDescriptors(
929
929
  payload,
930
- ["model", "voice", "text", "speed"],
930
+ ["model", "voice", "text", "textFormat", "speed"],
931
931
  ["text"],
932
932
  "Browser Kokoro synthesis payload",
933
933
  "tts-synthesis",
@@ -936,7 +936,9 @@ function normalizeSynthesisPayload(payload, authority, speechInputPrepared) {
936
936
  textValue = descriptors.text.value;
937
937
  }
938
938
  const suppliedText = is.string(textValue) ? textValue : "";
939
- const text = speechInputPrepared === true ? suppliedText : stripSpeechFormatting(suppliedText);
939
+ const text = speechInputPrepared === true || descriptors.textFormat?.value === "plain"
940
+ ? suppliedText
941
+ : stripSpeechFormatting(suppliedText);
940
942
  const voiceValue = Object.hasOwn(descriptors, "voice")
941
943
  ? descriptors.voice.value
942
944
  : authority.defaultVoice;
@@ -49,11 +49,14 @@ alone does not make bare module names resolve in a browser.
49
49
  | Import a shipped renderer module | [Runtime module catalog](runtime-modules.md) |
50
50
  | Use a shared entity | [Runtime entity modules](runtime-entities.md) and [exact export contracts](core/arcane-entities.md) |
51
51
  | Load a reusable HTML component | [Runtime component catalog](runtime-components.md) |
52
+ | Present Light / Dark / System choices with complete labels | [Theme-switcher configuration](runtime-components.md#theme-switcherhtml) |
53
+ | Use optional Core preferences and appearance without masking real failures | [PreferenceStore](runtime-modules.md#preferencestorejs), [SystemAppearance](runtime-modules.md#systemappearancejs), and [Core lookup errors](core-runtime.md#state-and-frames) |
52
54
  | Submit complete speech parts immediately and play them in order | [`SpeechPlayback`](runtime-modules.md#speechplaybackjs) and the [basic browser example](ai/browser-speech.md#play-a-complete-array-with-speechplayback) |
53
55
  | Call `globalThis.Arcane` | [Arcane Core API](core/arcane-api.md) |
54
56
  | Connect a browser to one Core transport | [Core browser client](core-client.md) |
55
57
  | Cancel one Core speech synthesis request without changing its payload | [Speech request lifetime](core-client.md#events-and-request-lifetime) and [Core facade](sdk-api.md#createcorefacade) |
56
58
  | Compose native Core dispatch, service lifecycle, and stdio hosting | [Native Core runtime](core-runtime.md) |
59
+ | Reuse dependency-ready native services without a renderer | [Core service composition](core-runtime.md#native-service-composition) and [existing ONNX owner](local-ai.md#native-service-owners) |
57
60
  | Compose application Core services during source development, independently of local AI | [Development Core services](core-development.md) |
58
61
  | Own an explicitly selected native Codex App Server session | [Codex App Server](codex-app-server.md) |
59
62
  | Expose application-owned tools and static resources through Node STDIO | [MCP STDIO server](mcp-stdio.md) |
@@ -66,12 +69,14 @@ alone does not make bare module names resolve in a browser.
66
69
  | Select the optional Intel NPU encoder with independent CUDA or CPU decoding | [Intel NPU Whisper](../guides/native-whisper-openvino.md) |
67
70
  | Edit an original PNG with a complete prompt and explicit strength | [Local image editing](local-image-editing.md) |
68
71
  | Project complete stored model files into native working files | [Model assets through Core](model-assets.md) |
72
+ | Prepare selected upstream model members in native services | [Native preparation and retained lifetime](model-assets.md#native-ownership) |
69
73
  | Retain a Nemotron model and diarize caller-fed audio streams | [Native speaker diarization](diarization.md) |
70
74
  | Persist application-selected preferences through Core | [Core preferences service](core-preferences.md) |
71
75
  | Read complete selected Git text without changing a checkout | [Git text snapshots](git-text-snapshot.md) |
72
76
  | Own a native working checkout under per-user ArcaneData/Repos | [Native repository workspaces](core-repositories.md) |
73
77
  | Read Git identity defaults or select child-only author and credential hints | [Git identity configuration](core-repositories.md#git-identity-configuration) |
74
78
  | Write, commit and push complete selected repository text | [Selected-text repository writing](core-repositories.md#write-commit-and-push-selected-text) |
79
+ | Observe existing checkout configuration and capture an explicit remote/ref | [Repository configuration and selected targets](core-repositories.md#existing-checkout-configuration-and-selected-targets) |
75
80
  | Build an installed-SDK portable Core payload | [Portable Core packaging](core-native-packaging.md) |
76
81
  | Pass host-selected state defaults and unchanged explicit launch values to services | [Launch-time locations](core-native-packaging.md#launch-time-locations) |
77
82
  | Build a Windows executable without an OS checkout | [Windows executable packaging](core-native-packaging.md#windows-executable) |
@@ -79,6 +84,7 @@ alone does not make bare module names resolve in a browser.
79
84
  | Subscribe to native events | [Arcane event reference](core/arcane-events.md) |
80
85
  | Use provider-neutral AI lifecycle, chat, speech, persistence, or document context | [Normalized AI](#normalized-ai) |
81
86
  | Choose a normalized typed browser decision surface | [Browser typed decisions](ai/browser-decisions.md) |
87
+ | Score complete typed options with native Laya FP32 | [Native typed decisions](native-decisions.md) |
82
88
  | Run a caller-selected local LLM in the browser | [Browser-WASM local AI](ai/browser-wasm.md) |
83
89
  | Run caller-selected Whisper/Kokoro, native browser recognition/voices or cloud TTS | [Browser speech providers](ai/browser-speech.md) |
84
90
  | Send TWiN chat, System One state/questions or image requests | [TWiN Cloud guide](ai/twin-cloud.md) |
@@ -239,6 +245,7 @@ Ollama, Wllama, Whisper, Kokoro, native, or cloud transport:
239
245
  | Run application-selected native llama.cpp/Ollama chat | [`arcane-os/ai/core-local`, `arcane-os/core/local-ai`](local-ai.md) | Explicit Core connection and selected native runtimes; installation, availability and loaded-model readiness remain distinct. |
240
246
  | Transcribe complete recordings with a retained native Whisper model | [`arcane-os/local-ai/whisper`](local-whisper.md) and [Core speech](native-speech.md) | Matching native helper, Whisper libraries, decoder and selected model; Windows defaults and explicit other-platform distributions have distinct preparation requirements. |
241
247
  | Run a local ONNX graph with named tensors | [`arcane-os/local-ai/onnx`, `arcane-os/ai/core-onnx`](local-ai.md#native-onnx-sessions) | Retained native workers; browser access requires an available Core ONNX service. |
248
+ | Score typed options without a renderer | [`arcane-os/local-ai/decisions`, `arcane-os/core/decisions`](native-decisions.md) | Explicit native Laya FP32 activation using the existing ONNX owner; complete scores and outputs, joined Worker cleanup. |
242
249
  | Generate local images from complete prompts and selected model resources | [`arcane-os/local-ai/image`, `arcane-os/ai/core-image`](local-image-generation.md) | Prepared native image runtime; browser access requires its Core service. CPU Windows/Linux and Mac Metal/CPU paths have distinct actual host requirements. |
243
250
  | Supply complete stored model members to a native engine | [`arcane-os/ai/core-model-assets`, `arcane-os/core/model-assets`](model-assets.md) | Available Core service; DBOPFS originals stay authoritative while native owners retain working files. |
244
251
  | Run caller-selected Whisper/Kokoro locally | [`arcane-os/ai/browser-speech`](ai/browser-speech.md) | Browser with DBOPFS, Web Locks, Workers and selected upstream sources; automatic WebNN NPU, WebGPU, then WASM loading, or an explicit backend. |
@@ -805,14 +805,17 @@ does not select another page or speak background work.
805
805
 
806
806
  ### Preparation inputs and reuse
807
807
 
808
- `ai.prepareTTS({parts,storage,identity,signal,onState})` accepts an ordered array
808
+ `ai.prepareTTS({parts,textFormat,storage,identity,signal,onState})` accepts an ordered array
809
809
  of strings or `{input,voice?,speed?,pauseAfterMs?}` records. An omitted voice
810
810
  uses the selected model default; omitted speed uses `ai.voiceSpeed`; omitted
811
811
  pause is zero. The SDK snapshots the selected speech configuration and current
812
812
  punctuation/word-cadence options for that preparation. A part's pause applies
813
813
  after its final extracted segment. Complete original input remains available
814
- for semantic comparison; automatic Markdown cleanup affects only the speech
815
- copy and occurs once before segmentation.
814
+ for semantic comparison; default Markdown cleanup affects only the speech
815
+ copy and occurs once before segmentation. Set `textFormat:'plain'` to preserve
816
+ each supplied input exactly through that segmentation. The prepared segment
817
+ text participates in semantic reuse, so a changed synthesis input does not
818
+ reuse audio produced from the cleaned version.
816
819
 
817
820
  `storage` is optional. When supplied, `{db,table,key}` names the caller's ready
818
821
  DBOPFS instance and its application-owned table/key. The SDK stores complete
@@ -977,7 +980,7 @@ speech method retain their existing behavior.
977
980
  ## Automatic speech-input formatting cleanup
978
981
 
979
982
  The shared streaming, audio-file, and `SpeechPlayback` paths remove repeated
980
- same formatting marks from the outbound speech-input copy automatically:
983
+ same formatting marks from the outbound speech-input copy by default:
981
984
 
982
985
  ```javascript
983
986
  ai.streamTTS('## Heading\n**Hello');
@@ -994,10 +997,13 @@ waits for its next character or the final flush.
994
997
 
995
998
  `end:true`, `finishTTS()`, or cancellation clears pending streaming formatting
996
999
  state. `fetchTTS()`, provider-runtime TTS requests, direct Kokoro provider
997
- requests, and `SpeechPlayback` apply the same cleanup to complete input. An
998
- existing `textFormat` extra is ignored and cannot disable or select cleanup.
1000
+ requests, and `SpeechPlayback` apply the same default cleanup to complete input.
1001
+ Complete-input APIs can explicitly select `textFormat:'plain'` as described
1002
+ below. The streaming `streamTTS()` options still ignore `textFormat`;
1003
+ streaming narration and `SpeechPlayback` keep their existing cleanup.
999
1004
  SDK-internal delegation carries `{speechInputPrepared:true}` outside the speech
1000
- payload only after one cleanup pass, preventing a second non-idempotent pass.
1005
+ payload after its owner selects text treatment, preventing a second
1006
+ non-idempotent cleanup pass or cleanup of explicitly plain input.
1001
1007
  Applications omit that internal metadata. Displayed messages, saved history,
1002
1008
  model input, caller payload objects, language, voice, synthesis capacity, and
1003
1009
  playback timing are not changed by the filter.
@@ -1023,6 +1029,39 @@ console.log(speechText.append('## Head', false)); // ' Head'
1023
1029
  console.log(speechText.append('ing', true)); // ing
1024
1030
  ```
1025
1031
 
1032
+ ### Exact complete synthesis input
1033
+
1034
+ Use the public `textFormat:'plain'` selection for already-authored speech or an
1035
+ exact generated preview. It belongs in `prepareTTS` options, or alongside the
1036
+ `input`/`text` field of a complete synthesis payload:
1037
+
1038
+ ```javascript
1039
+ function preparePreview(ai, preview, signal) {
1040
+ return ai.prepareTTS({parts: [preview], textFormat: 'plain', signal});
1041
+ }
1042
+
1043
+ function fetchPreview(ai, preview, signal) {
1044
+ return ai.fetchTTS({input: preview, textFormat: 'plain'}, signal);
1045
+ }
1046
+ ```
1047
+
1048
+ The same payload field is supported by `AI.prepareTTSPlayback()` for audio-file
1049
+ providers, `AIProviderRuntime.request('tts', {operation:'synthesize', payload,
1050
+ localOnly, signal})`, its `synthesize(payload, options)` alias, and direct
1051
+ Kokoro `request()` calls using either `{text,...}` or `{model,input,...}`.
1052
+ The SDK consumes `textFormat` before engine/host dispatch. The original nonblank input,
1053
+ including whitespace and repeated formatting marks, remains unchanged; voice,
1054
+ speed, selected model, cancellation and audio ordering retain their existing
1055
+ owners. Only `'plain'` selects exact input; omission and other values retain
1056
+ the existing narration cleanup. Applications never supply the internal
1057
+ `speechInputPrepared` argument.
1058
+
1059
+ This selection governs SDK text treatment, not the selected engine's input
1060
+ capacity or pronunciation. [Kokoro.js 1.2.1](https://github.com/hexgrad/kokoro/blob/664c76a704021239ba59c84dcbaa4d3dece01fe9/kokoro.js/src/kokoro.js)
1061
+ still tokenizes with truncation in both `generate()` and `stream()`; plain input
1062
+ does not establish complete audio for an oversized engine input. The SDK's existing complete-text forwarding
1063
+ fixture does not prove upstream synthesis completeness.
1064
+
1026
1065
  ## Choose a device or reduce memory use
1027
1066
 
1028
1067
  Local Whisper and Kokoro roles accept
@@ -1610,10 +1649,11 @@ const result = await kokoro.request({
1610
1649
  The voice belongs to the caller-selected inventory; omission uses that model's
1611
1650
  default voice. The provider-native result is
1612
1651
  `{audio:Float32Array,sampleRate,voice}`. The provider/2 shared request form accepts
1613
- `{model,input,responseFormat:'wav',voice?,speed?}` and returns
1652
+ `{model,input,textFormat?,responseFormat:'wav',voice?,speed?}` and returns
1614
1653
  `{audio:Uint8Array,contentType:'audio/wav'}`. High-level `AI.fetchTTS()` wraps
1615
1654
  that provider result in a WAV `Blob`. Returned provider records remain ordinary
1616
- mutable values.
1655
+ mutable values. Both payload forms accept `textFormat:'plain'` to retain exact
1656
+ input; omission keeps the default speech-formatting cleanup.
1617
1657
 
1618
1658
  ## Lifecycle and cancellation
1619
1659
 
@@ -74,6 +74,7 @@ where listed. See [native output and host requirements](core-native-packaging.md
74
74
  | Share one native WebSocket by exact URI and ordered protocols | `arcane-os/websocket-client` | **Node** and **Browser**, using the host's native `WebSocket` | The selected upstream `ws-share` instance owns the connection pool and global observation. Native socket messages and events remain unchanged; there is no reconnect, heartbeat, application envelope, storage, or fallback. |
75
75
  | Build browser UI and app-local behavior | `/arcane/modules/*.js`, shared entities, and components | **Browser**; many modules also run inside every native renderer | Pure modules own their result contracts. Modules that call `Arcane` inherit the bridge boundary described below. |
76
76
  | Score caller-supplied typed options with Laya or Julia | `arcane-os/ai/browser-decisions` | **Browser** only; caller-selected upstream runtime/model and backend | Typed decisions retain complete rows and return typed values, scores, probabilities, and diagnostics in caller order. This surface is separate from chat and speech and does not silently change model, precision, backend, or family. |
77
+ | Score complete typed options with native Laya FP32 | [`arcane-os/local-ai/decisions`, `arcane-os/core/decisions`](native-decisions.md) | **Node** Windows/Linux/macOS with selected ONNX Runtime and model; Android needs host adaptation | Reuses the existing native ONNX owner and a tokenizer Worker, with explicit load and joined cleanup. Preserves separate state/question/options/type, original rows, raw scores and complete graph outputs. GPU preference attempts actual advertised providers before CPU; provider configuration does not prove physical acceleration. No renderer, chat provider or automatic persistence is required. |
77
78
  | Select and observe independent LLM/STT/TTS roles | `/arcane/modules/AIProviderRuntime.js` and `AIRuntimeState.js` | **Cross-host** controller/state; registered providers retain their own host requirements | Required/projected provider members, route/configuration records, and status fields; per-role lifecycle, cancellation, stream cleanup, sticky state, and startup barriers are normalized. `localOnly` creates no fallback. |
78
79
  | Run a caller-selected local LLM entirely in a browser renderer | `arcane-os/ai/browser-wasm` through `createArcaneAI()` | **Browser** only; secure context, WebAssembly, and OPFS/DBOPFS; full WebGPU offload by default or explicit CPU with `gpuLayers:0` | The public AI API module normalizes multi-model lifecycle, status, complete all-choice streaming, cancellation, exact ordered structural tool-call visibility, and session persistence. Model sources are canonical ordered file descriptors; licenses and model choice remain application policy. |
79
80
  | Run caller-selected Whisper or Kokoro in a browser renderer | `arcane-os/ai/browser-speech` registered with `AIProviderRuntime` | **Browser** only; DBOPFS, Web Locks, Workers, Fetch/object URLs, and a caller-supplied self-contained runtime/model closure are required | Independent provider/2 lifecycle and status, with `auto`, `webnn-npu`, `webgpu`, or `wasm` execution. Whisper owns one Worker/session; Kokoro defaults to four and accepts one through four. Complete model/runtime selection, offline behavior, cancellation, Worker teardown, and request/result shapes are normalized. No runtime/model content or cloud fallback is supplied. |
@@ -372,6 +372,47 @@ observes complete diagnostics and exit. Cancelling that operation closes its
372
372
  input, allowing the window and accepted Core service work to drain without a
373
373
  forced process termination.
374
374
 
375
+ ### Initial native window size
376
+
377
+ An application can select its initial client area and resizing behavior in
378
+ `arcane-app.json`, independently of its page layout:
379
+
380
+ ```json
381
+ {
382
+ "native": {
383
+ "type": "app",
384
+ "icon": "img/icon.png",
385
+ "order": 100,
386
+ "bundledApps": [],
387
+ "window": {"width": 1280, "height": 800, "resizable": true}
388
+ }
389
+ }
390
+ ```
391
+
392
+ This is the `native` portion of the existing app descriptor. Each `window`
393
+ member is optional. `width` and `height` are positive integral client dimensions
394
+ in logical pixels at 96 DPI; `resizable` is a boolean. Omitting a member retains
395
+ the host's existing choice, and omitting `window` preserves existing startup.
396
+ The native registry projection preserves the record; the browser package
397
+ projection gains no window controls. Portable and Windows assembly copy the
398
+ record to `arcane-native.json` as `window`, without changing page or service
399
+ content.
400
+
401
+ The matching Windows host applies the dimensions once on initial load, using
402
+ the display DPI and fitting the outer window within the selected monitor's
403
+ usable work area. This fit does not impose a persistent maximum size. Explicit
404
+ `resizable:false` uses a fixed frame and disables the maximize control; `true`
405
+ permits ordinary resizing and maximizing. Later app/user resizing remains
406
+ untouched. A composing launcher's `Load` handler runs after this initial sizing
407
+ and can restore its own saved window state. The SDK adds no saved-bounds store.
408
+
409
+ Direct Windows host composition uses nullable `ArcaneHostOptions` members
410
+ `InitialClientWidth`, `InitialClientHeight`, and `Resizable` with the same
411
+ semantics. Older precompiled Windows hosts do not read these options; use the
412
+ matching SDK host archive when rebuilding an application. The portable record
413
+ is available to platform adapters; this addition implements its Windows host
414
+ behavior and leaves window sizing on other platforms unchanged.
415
+
375
416
  ### Application icon and window colors
376
417
 
377
418
  `appDescriptor.native.icon` selects the application's existing app-relative
@@ -123,6 +123,20 @@ The shared `arcane-os/core/contracts` module owns `CORE_PROTOCOL` (`arcane/1`),
123
123
  availability errors remain observable; unavailable services are not replaced
124
124
  with browser behavior.
125
125
 
126
+ A request with no registered handler retains code `METHOD_NOT_ALLOWED` and
127
+ adds the exact `method`, its first dotted `namespace`, and a `reason`.
128
+ `core-namespace-unavailable` means the dispatcher has neither a service with
129
+ that name nor any registered method in that namespace. Otherwise the reason is
130
+ `core-method-unavailable`; the built-in `system`, `app`, and `version`
131
+ namespaces also count as present. This is a dispatch lookup result before any
132
+ handler or permission decision, not a capability-discovery call. A read-only
133
+ or partially registered service therefore never appears wholly absent.
134
+ Handler/startup/permission errors remain unchanged and acquire none of these
135
+ lookup markers. Generic or older `METHOD_NOT_ALLOWED` errors do not establish
136
+ namespace absence. An optional browser adapter may recognize the exact absent
137
+ namespace and method according to its own documented contract; the dispatcher
138
+ does not select or create another implementation.
139
+
126
140
  Events have `{protocol, type:'event', event, data, time}`:
127
141
 
128
142
  - `core.ready`: the dispatcher is connected; service/model readiness is separate.
@@ -1,17 +1,59 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "sdkVersion": "0.66.0",
3
+ "sdkVersion": "0.68.0",
4
4
  "environment": {
5
5
  "runtime": "Node.js for Node entrypoints; browser for browser-only entrypoints",
6
6
  "minimumVersion": "22.23.2 for Node entrypoints",
7
7
  "moduleSystem": "ESM"
8
8
  },
9
- "memberCount": 290,
9
+ "memberCount": 293,
10
10
  "runtimeSubpathPatterns": {
11
11
  "arcane-os/modules/*": "./runtime/arcane/modules/*",
12
12
  "arcane-os/entities/*": "./runtime/arcane/entities/*"
13
13
  },
14
14
  "members": [
15
+ {
16
+ "id": "local-ai-decisions:createNativeDecisionModel",
17
+ "name": "createNativeDecisionModel",
18
+ "displayName": "createNativeDecisionModel()",
19
+ "kind": "function",
20
+ "signature": "createNativeDecisionModel({onnx,modelAssets,workingDirectory,paths,model='onnx-community/laya-typed-decisions-ONNX',revision='main',dtype='fp32',sessionOptions,executionPreference='gpu',signal}={})",
21
+ "entrypoints": ["arcane-os/local-ai/decisions"],
22
+ "primaryImport": "arcane-os/local-ai/decisions",
23
+ "group": "Native typed decisions",
24
+ "summary": "Explicit native Laya FP32 option scoring through an existing ONNX owner and a tokenizer Worker.",
25
+ "availability": "Node on Windows/Linux/macOS with selected ONNX Runtime and model files; Android needs host adaptation",
26
+ "protocol": "Shared browser/native decision encoding with native named tensor results",
27
+ "normalization": "Returns load/evaluate/classify/current/status/subscribe/unload/dispose; preserves complete separate state/question/options/type and original rows, raw scores and every graph output. Explicit load prepares selected upstream files or uses caller-owned paths; GPU preference attempts advertised providers then CPU. Cancellation retires the shared activation; files remain retained through actual ONNX and tokenizer Worker exit. No chat history or duplicate inference engine."
28
+ },
29
+ {
30
+ "id": "core-decisions:createNativeDecisionService",
31
+ "name": "createNativeDecisionService",
32
+ "displayName": "createNativeDecisionService()",
33
+ "kind": "function",
34
+ "signature": "createNativeDecisionService(configuration={}, {appRoot=process.cwd()}={})",
35
+ "entrypoints": ["arcane-os/core/decisions"],
36
+ "primaryImport": "arcane-os/core/decisions",
37
+ "group": "Native typed decisions",
38
+ "summary": "Renderer-independent native Laya service reusing the registered local-AI and model-assets owners.",
39
+ "availability": "Node Core with selected native ONNX and model files",
40
+ "protocol": "arcane/1 decisions.status/load/evaluate/unload and decisions.state",
41
+ "normalization": "Registration starts no model or tokenizer. Explicit load obtains dependency-ready same-process owners and reacquires getONNXRuntime after recovery. Native load/evaluate/classify/current/subscribe/unload/dispose preserve complete results; RPC uses the existing tensor codec. Unload has accepted service lifetime; host shutdown cancels request-lifetime load/evaluation."
42
+ },
43
+ {
44
+ "id": "core-decisions:default",
45
+ "name": "default",
46
+ "displayName": "createNativeDecisionService default export",
47
+ "kind": "function",
48
+ "signature": "default as createNativeDecisionService",
49
+ "entrypoints": ["arcane-os/core/decisions"],
50
+ "primaryImport": "arcane-os/core/decisions",
51
+ "group": "Native typed decisions",
52
+ "summary": "Default binding for the same native decision Core service factory.",
53
+ "availability": "Node Core runtime",
54
+ "protocol": "arcane/1 service definition",
55
+ "normalization": "Binding identity equals the named createNativeDecisionService export"
56
+ },
15
57
  {
16
58
  "id": "local-ai-whisper:createWhisperRuntime",
17
59
  "name": "createWhisperRuntime",
@@ -227,14 +269,14 @@
227
269
  "name": "createCoreImageRuntime",
228
270
  "displayName": "createCoreImageRuntime()",
229
271
  "kind": "function",
230
- "signature": "createCoreImageRuntime({client=getInstalledCoreClient(),signal,onEvent}={})",
272
+ "signature": "createCoreImageRuntime({client,signal,onEvent}={})",
231
273
  "entrypoints": ["arcane-os/ai/core-image"],
232
274
  "primaryImport": "arcane-os/ai/core-image",
233
275
  "group": "Core local images",
234
276
  "summary": "Uses an available Core image service for generation and original-PNG editing with synchronous Thinking acknowledgement, lifecycle replay and complete PNG Blobs.",
235
277
  "availability": "Browser/native WebView with an available Core image service; construction opens no connection or model",
236
278
  "protocol": "arcane/1 image.status/load/generate/edit/unload and image.state/progress",
237
- "normalization": "Returns load/generate/edit/unload/inspect/current/subscribe/close; edit preserves the complete original PNG Blob/File through transport with explicit strength; timeoutMs is zero, close cancels only this accessor and explicit unload owns the shared model"
279
+ "normalization": "Returns load/generate/edit/unload/inspect/current/subscribe/close; omitted client follows installation/replacement/retirement, explicit client including null remains fixed. Retirement cancels owned work and clears readiness; late old-client output is suppressed. Edit preserves the complete original PNG Blob/File through transport with explicit strength; timeoutMs is zero, close cancels only this accessor and explicit unload owns the shared model"
238
280
  },
239
281
  {
240
282
  "id": "core-image-service:createLocalImageService",
@@ -290,7 +332,7 @@
290
332
  "summary": "Owns selected native working-file projections and engine retain handles while original stored model files remain unchanged.",
291
333
  "availability": "Node Core with an application-selected working directory",
292
334
  "protocol": "arcane/1 modelAssets.open/write/complete/release/status and modelAssets.state",
293
- "normalization": "Returns current/retain/dispose and Core service lifecycle; final native release joins writes and closes before deleting only its working projection"
335
+ "normalization": "Returns current/prepare/retain/release/dispose and Core service lifecycle. Explicit prepare({id,workingDirectory,members:[{path,url}],signal,onProgress}) streams complete upstream members through the existing file owner and reports file/phase progress. release(id) relinquishes preparation ownership; cancellation and cleanup join fetches/writes. Native retains survive until actual engine release before deleting only the owned working projection. Startup downloads nothing."
294
336
  },
295
337
  {
296
338
  "id": "core-model-assets-service:default",
@@ -318,21 +360,21 @@
318
360
  "summary": "Owns explicitly loaded ONNX graphs and complete named tensor inference in retained native workers.",
319
361
  "availability": "Node on Windows/Linux/macOS x64/arm64 with prepared onnxruntime-node; Android needs host adaptation",
320
362
  "protocol": "Per-session worker lifecycle with structured-clone tensors and replaying state",
321
- "normalization": "Returns load/run/unload/current/subscribe/close; explicit model and session IDs; native calls may delay worker termination, and close observes actual exit"
363
+ "normalization": "Returns load/run/unload/current/subscribe/close; load accepts executionPreference gpu for advertised provider creation attempts then CPU, while explicit sessionOptions.executionProviders takes precedence. Complete execution diagnostics distinguish configured providers from physical acceleration. stopping revokes new runs while exited records actual Worker exit; recoverable run errors preserve the session. Cleanup joins exit and output delivery even when termination fails."
322
364
  },
323
365
  {
324
366
  "id": "core-onnx:createCoreONNXRuntime",
325
367
  "name": "createCoreONNXRuntime",
326
368
  "displayName": "createCoreONNXRuntime()",
327
369
  "kind": "function",
328
- "signature": "createCoreONNXRuntime({client=getInstalledCoreClient()}={})",
370
+ "signature": "createCoreONNXRuntime({client}={})",
329
371
  "entrypoints": ["arcane-os/ai/core-onnx"],
330
372
  "primaryImport": "arcane-os/ai/core-onnx",
331
373
  "group": "Core local AI",
332
374
  "summary": "Accesses local system ONNX through an existing Core client with complete tensor transport.",
333
375
  "availability": "Browser with available Core ONNX service; construction installs no runtime or model",
334
376
  "protocol": "arcane/1 onnx.status/load/run/unload and localai.state",
335
- "normalization": "Returns load/run/unload/inspect/current/subscribe/close; preserves typed and string tensors; accessor close cancels its requests without closing shared Core or implicitly unloading shared models"
377
+ "normalization": "Returns load/run/unload/inspect/current/subscribe/close; omitted client follows late installation/replacement/retirement and reads current status, while explicit client including null stays fixed. Retirement clears readiness and cancels owned work; late old-client results are suppressed. Preserves typed and string tensors; close removes subscriptions and cancels requests without closing shared Core or implicitly unloading shared models"
336
378
  },
337
379
  {
338
380
  "id": "root:createGitTextSnapshot",
@@ -409,14 +451,14 @@
409
451
  "name": "createCoreLocalAIProvider",
410
452
  "displayName": "createCoreLocalAIProvider()",
411
453
  "kind": "function",
412
- "signature": "createCoreLocalAIProvider({client=getInstalledCoreClient(),id='llama.cpp'}={})",
454
+ "signature": "createCoreLocalAIProvider({client,id='llama.cpp'}={})",
413
455
  "entrypoints": ["arcane-os/ai/core-local"],
414
456
  "primaryImport": "arcane-os/ai/core-local",
415
457
  "group": "Core local AI",
416
458
  "summary": "Browser llama.cpp provider through an explicitly connected Core, with application-owned model selection and complete response streaming.",
417
459
  "availability": "Browser with an available Core local AI service; construction installs no runtime or model",
418
460
  "protocol": "arcane-ai-provider/2 LLM lifecycle over arcane/1",
419
- "normalization": "Preserves complete payloads and original parsed chunks; waits for the exact requested model and cancels on observed readiness loss"
461
+ "normalization": "Preserves complete payloads and original parsed chunks; waits for the exact requested model and cancels on observed readiness loss. Omitted client follows installation/replacement/retirement; explicit client including null stays fixed. Inspect reports load capability separately from loaded readiness; disposal releases only an actually retained selection through its captured client. Provider/2 role state reconciles at existing operation boundaries, not through an idle state subscription."
420
462
  },
421
463
  {
422
464
  "id": "core-local-ai:createLocalAIService",
@@ -430,7 +472,7 @@
430
472
  "summary": "Composes selected native llama.cpp, Ollama and ONNX engines as a Core service with retained process/worker ownership and model lifecycle.",
431
473
  "availability": "Node with selected upstream runtime distributions or available configured system services",
432
474
  "protocol": "arcane/1 methods and events; llama.cpp OpenAI HTTP/SSE, Ollama native HTTP/NDJSON and ONNX tensor transport",
433
- "normalization": "Application-owned runtime and model requirements; optional prepare supplies installed records during this service startup; independent services, complete responses and exact owned-process cleanup"
475
+ "normalization": "Application-owned runtime and model requirements; optional prepare supplies installed records during this service startup. getONNXRuntime() returns the actual prepared ONNX owner for native composition after context.getService('local-ai'); callers reacquire after recovery and retain the acquired handle for cleanup. llama.status/models observe without starting or restarting an engine. Independent services, complete responses and exact owned-process cleanup remain unchanged."
434
476
  },
435
477
  {
436
478
  "id": "core-local-ai:default",
@@ -1849,7 +1891,7 @@
1849
1891
  "summary": "Default binding for the canonical PreferenceStore runtime class in Node and managed browsers.",
1850
1892
  "availability": "Node with injected adapters, or browser/native WebView storage",
1851
1893
  "protocol": "Node ESM / authenticated managed browser import map",
1852
- "normalization": "Binding identity and namespace come directly from the canonical runtime module"
1894
+ "normalization": "Canonical runtime binding. Default adapter recognizes only exact absent preferences namespace/matching method or existing Android unsupported capability; single operations retry once through existing app-scoped local storage after disposal/cancellation checks, preserving complete values and context. An advertised rejected batch is never retried serially; its original rejection remains before later local operations. Explicit adapters and partial-service/genuine failures retain their behavior."
1853
1895
  },
1854
1896
  {
1855
1897
  "id": "preference-store:PREFERENCE_STORE_ERROR_CODES",
@@ -4276,7 +4318,7 @@
4276
4318
  "summary": "Creates an app-neutral Core dispatcher with explicit services, request lifetimes, events and graceful drain.",
4277
4319
  "availability": "Node on Windows, Linux and macOS native hosts; Android requires its host adaptation",
4278
4320
  "protocol": "arcane/1 dispatcher and service lifecycle",
4279
- "normalization": "Starts services independently, preserves complete results/errors, cancels only request-lifetime work and drains accepted service work; runtime.replay publishes current dispatcher/service state without restart and preserves reentrant lifecycle publication order"
4321
+ "normalization": "Starts services independently; runtime.getService(name) and context.getService(name) return the same registered object after only its shared startup, without a renderer or global barrier. Lookup is readiness, not a lifetime lease; new lookups reject during shutdown. Preserves complete results/errors, cancels request-lifetime work and drains accepted service work; runtime.replay publishes current dispatcher/service state without restart and preserves reentrant lifecycle publication order. Missing dispatch retains METHOD_NOT_ALLOWED with exact method/namespace and core-namespace-unavailable or core-method-unavailable; named services, registered methods and built-in namespaces establish presence. Handler/startup/permission errors remain unchanged."
4280
4322
  },
4281
4323
  {
4282
4324
  "id": "core-stdio:encodeCoreFrame",
@@ -967,8 +967,9 @@
967
967
  {
968
968
  "file": "runtime/arcane/components/theme-switcher.html",
969
969
  "name": "theme-switcher.html",
970
- "purpose": "Selects and refreshes system, light, dark, or custom theme mode.",
970
+ "purpose": "Selects and refreshes system, light, dark, or custom theme mode with per-instance choices and labels.",
971
971
  "methods": [
972
+ "configure()",
972
973
  "setMode()",
973
974
  "refresh()"
974
975
  ],
@@ -1083,7 +1083,7 @@
1083
1083
  "summary": "Loads and updates schema-defined app preferences through native storage with a narrow browser fallback.",
1084
1084
  "availability": "Browser/native hybrid",
1085
1085
  "protocol": "Arcane.preferences or app-scoped localStorage + per-realm globalThis.arcaneEvents authority",
1086
- "normalization": "Complete ordinary values remain mutable; setAll uses one optional atomic adapter batch for every selected value when advertised, otherwise retains complete serial per-key compatibility, never retries a rejected dispatched batch serially, and only exact unsupported native capability changes future operations to the browser fallback.",
1086
+ "normalization": "Complete values and operation context retained; the default adapter recognizes only exact missing preferences namespace/matching method or existing Android unsupported capability before selecting existing app-scoped localStorage. Single operations retry once after disposal/cancellation checks; partial-service and genuine failures reject unchanged. An advertised rejected batch is never retried serially, and its original rejection is preserved before later local operations.",
1087
1087
  "surface": "Event/error constants, default `PreferenceStore`, re-exported `Preference`/schema; load/set/setAll/reset APIs, required adapter get/set/delete plus optional setMany, state-free EventTarget/on compatibility, and `dispose()`."
1088
1088
  },
1089
1089
  {
@@ -1291,10 +1291,10 @@
1291
1291
  "exports": [
1292
1292
  "default"
1293
1293
  ],
1294
- "summary": "Reads or applies native appearance, returning an explicit unsupported browser state when no bridge exists.",
1294
+ "summary": "Reads or applies native appearance, returning an explicit unsupported result when the bridge or optional namespace is absent.",
1295
1295
  "availability": "Browser/native hybrid",
1296
1296
  "protocol": "Arcane.appearance",
1297
- "normalization": "Absent bridge normalized; native result/error preserved.",
1297
+ "normalization": "Absent bridge keeps its browser result. Exact missing appearance namespace/matching method returns supported:false with the complete original diagnostic; no platform guess or cached absence. Partial-method, permission, transport, cancellation and other genuine errors reject unchanged; available() is callable bridge presence only.",
1298
1298
  "surface": "default `SystemAppearance`; `available()`, `current()`, `apply()`."
1299
1299
  },
1300
1300
  {