arcane-os 0.5.9 → 0.5.11

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +117 -26
  3. package/browser-runtime/ai/browser-speech-providers.mjs +1 -1
  4. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +63 -39
  5. package/docs/architecture.md +303 -0
  6. package/docs/compatibility.md +38 -0
  7. package/docs/event-manager.md +263 -0
  8. package/docs/platform-targets.md +104 -0
  9. package/docs/publishing.md +126 -0
  10. package/docs/reference/README.md +206 -0
  11. package/docs/reference/ai/browser-speech.md +813 -0
  12. package/docs/reference/ai/browser-wasm.md +637 -0
  13. package/docs/reference/ai/twin-cloud.md +156 -0
  14. package/docs/reference/arcane-ollama.md +288 -0
  15. package/docs/reference/availability-and-normalization.md +224 -0
  16. package/docs/reference/behavioral-testing.md +129 -0
  17. package/docs/reference/cli.md +820 -0
  18. package/docs/reference/core/README.md +61 -0
  19. package/docs/reference/core/arcane-ai-contracts.md +907 -0
  20. package/docs/reference/core/arcane-api.md +601 -0
  21. package/docs/reference/core/arcane-entities.md +59 -0
  22. package/docs/reference/core/arcane-events.md +134 -0
  23. package/docs/reference/core/ollama-module.md +181 -0
  24. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  25. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  26. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  27. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  28. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  29. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  30. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  31. package/docs/reference/event-manager.md +1409 -0
  32. package/docs/reference/inventory/package-api.json +3194 -0
  33. package/docs/reference/inventory/runtime-components.json +1015 -0
  34. package/docs/reference/inventory/runtime-entities.json +25 -0
  35. package/docs/reference/inventory/runtime-modules.json +1367 -0
  36. package/docs/reference/mail.md +309 -0
  37. package/docs/reference/protocols.md +749 -0
  38. package/docs/reference/runtime-components.md +1529 -0
  39. package/docs/reference/runtime-entities.md +305 -0
  40. package/docs/reference/runtime-modules.md +3275 -0
  41. package/docs/reference/sdk-api.md +6733 -0
  42. package/docs/roadmap.md +79 -0
  43. package/docs/work-amplification.md +66 -0
  44. package/examples/wasm-ai-demo/README.md +80 -0
  45. package/examples/wasm-ai-demo/app.js +787 -0
  46. package/examples/wasm-ai-demo/index.html +343 -0
  47. package/examples/wasm-ai-demo/profile-tools.js +217 -0
  48. package/examples/wasm-ai-demo/profiles/BOSS.Modelfile +106 -0
  49. package/examples/wasm-ai-demo/profiles/PreCrisis.Modelfile +693 -0
  50. package/examples/wasm-ai-demo/rag/boss-library.json +3006 -0
  51. package/examples/wasm-ai-demo/rag.js +295 -0
  52. package/examples/wasm-ai-demo/server.mjs +71 -0
  53. package/package.json +11 -2
  54. package/runtime/arcane/modules/AI.js +1 -1
  55. package/runtime/arcane/modules/AIProviderRuntime.js +26 -5
@@ -0,0 +1,749 @@
1
+ # Protocol and host architecture
2
+
3
+ This is the deep reference behind the compact availability notes elsewhere.
4
+ Application developers should start with the
5
+ [availability and normalization guide](availability-and-normalization.md), call
6
+ one documented API, and treat the protocols below as implementation detail.
7
+
8
+ ## Layer map
9
+
10
+ ```text
11
+ application code
12
+ |-- Node SDK API ----------------- arcane-cli-events/1 + SDK results
13
+ |-- EventManager ----------------- synchronous bus + arcane-event-stack/1
14
+ |-- browser-local AI ------------- WebGPU/WASM/Workers/DBOPFS; no Core grant
15
+ `-- globalThis.Arcane
16
+ |-- development host -------- development HTTP bridge
17
+ |-- Microsoft NT native ----- WebView2 host bridge
18
+ |-- Linux native ------------ WebKitGTK host bridge
19
+ `-- Android native ---------- Android WebView message bridge
20
+ |
21
+ `-- Arcane Core/provider boundary
22
+ |-- platform services
23
+ |-- ArcaneOllama loopback service
24
+ `-- explicitly selected cloud APIs
25
+ ```
26
+
27
+ Each downward boundary can add authority and platform capability. None can be
28
+ inferred merely from a function existing in shared JavaScript.
29
+
30
+ ## SDK package and CLI protocols
31
+
32
+ The npm package API is ordinary Node.js ESM. The CLI and programmatic toolchain
33
+ share one headless operation implementation. Long-running operations accept
34
+ before blocking work, own their task, stream structured events with bounded
35
+ backpressure, emit progress or heartbeats, support cancellation where the
36
+ underlying operation can do so safely, and surface failure through rejection or
37
+ a nonzero CLI status.
38
+
39
+ Machine output uses `arcane-cli-events/1`. Native planning and providers use:
40
+
41
+ - `arcane-target-adapter/1` for target adapters;
42
+ - `arcane-native-build-plan/1` for single-attempt native plans;
43
+ - `arcane-native-builder/1` for injected native builders;
44
+ - `arcane-integrated-toolchain/1` for the fixed integrated shared/Core provider.
45
+
46
+ These protocols normalize orchestration and results. They do not normalize a
47
+ Windows EXE, Linux DEB, Android APK, and portable directory into the same
48
+ artifact kind.
49
+
50
+ Managed browser imports have three supported control-plane entrypoints. The CLI
51
+ uses `arcane import-map`; Node callers use
52
+ `executeOperation('import-map', options)` or
53
+ `createToolchain(defaults).importMap(options)`. These are three routes to the
54
+ same app-scoped operation, not three import-map formats. Each route discovers
55
+ the selected descriptor's directly navigable admitted `.html`/`.htm` documents
56
+ through the package include/exclude rules and writes one canonical map to the
57
+ artifact plus every such document. The current marker is exactly one matching
58
+ `meta[name="arcane-app-id"]`; an unmarked secondary page with an active `base`
59
+ remains admitted under the current secondary-document rule. Wrong or duplicate
60
+ explicit identity fails, and the selected page then must pass exact path-relative
61
+ base validation.
62
+ Included HTML with neither signal is a component fragment and remains a
63
+ complete package file.
64
+ `arcane-os/preference-store` and
65
+ `arcane-os/speech-playback` are the two portable runtime subpaths: Node package
66
+ exports and managed browser keys both resolve directly to the canonical runtime
67
+ module namespaces, while `arcane/PreferenceStore` and
68
+ `arcane/SpeechPlayback` are the established browser import-map names. There is
69
+ no exported `importMapApplication()` function, `generateImportMap()` function, or
70
+ `arcane-os/import-map` package subpath.
71
+
72
+ The application dependency boundary is conditional. Only an application that
73
+ actually consumes Arcane declares one exact published `arcane-os` version in
74
+ its own `package.json` and resolves it through that project's normal install
75
+ into its own `node_modules`. An application that does not currently consume
76
+ Arcane adds no `arcane-os` dependency solely because of this rule; the user or
77
+ governing task may direct that application to adopt Arcane later, at which point
78
+ the same app-owned package, install, projection, and artifact boundary applies.
79
+ An Arcane consumer never depends on a global install, link or symlink, or
80
+ another Arcane OS/SDK checkout. The explicit `--sdk-runtime-source` checkout is
81
+ a temporary development server input only: its path and mutable authority are
82
+ not persisted in application package metadata, lockfiles, managed import maps,
83
+ or `dist`. Distribution instead uses the app's installed package and
84
+ materializes the complete required SDK runtime,
85
+ browser-runtime, and managed-import-map closure inside that app's own artifact.
86
+ No application polls for SDK changes.
87
+
88
+ ## Installed SDK runtime materialization
89
+
90
+ `materializeInstalledSdkRuntime()` is the Node entrypoint for refreshing one
91
+ external workspace's checked-in `arcane/` projection from its one exact
92
+ installed SDK declaration. Import the function through the dependency key that
93
+ the workspace actually declares: `arcane-os` for the canonical package name or,
94
+ for example, `arcane-sdk` for the exact `npm:arcane-os@<version>` alias. No
95
+ application- or Arcane OS-local copier owns this operation.
96
+
97
+ The operation resolves that declaration while holding the shared
98
+ workspace-operation lock, copies the complete runtime and browser-runtime
99
+ content, and returns the installed-package location plus the materialized
100
+ workspace runtime paths. After the complete runtime replacement, it writes or
101
+ replaces semantic `arcane.lock.json` metadata from the actual installed
102
+ dependency name, package name, package version, and alias source.
103
+
104
+ Materialization writes a complete staging tree before the commit boundary,
105
+ moves any prior runtime to an owned backup, installs the new tree, and restores
106
+ the prior tree if commit fails. Cancellation remains effective through the last
107
+ pre-commit check. Successful whole-tree replacement removes paths absent from
108
+ the selected runtime content. The lock document describes the selected
109
+ installation and projected roots; it is not a content-identity or admission
110
+ record.
111
+
112
+ `upgradeApplication()` and `arcane upgrade` run the application's ordinary
113
+ `npm upgrade` command. They do not independently reconcile the installed SDK
114
+ projection, semantic Arcane lock, or managed import map.
115
+
116
+ ## Central events and time-travel data
117
+
118
+ `arcane-os/event-manager` is host-neutral JavaScript. Its live event path is
119
+ synchronous, in-process `event-pubsub`; it does not select WebView2,
120
+ WebKitGTK, Android, HTTP, Core, or a kernel boundary. Optional history uses the
121
+ `arcane-event-stack/1` data format. That protocol names a diagnostic document,
122
+ not a network channel and not the `arcane/1` Core RPC
123
+ protocol.
124
+
125
+ Live listeners receive the original arguments. Recording separately snapshots
126
+ complete payloads and metadata while redacting credentials and explicitly
127
+ protected private fields. Exported stacks can be moved between Node and browser
128
+ hosts because `parseEventStack()` rejects genuinely malformed data before
129
+ playback. Review mode emits records, events mode deliberately
130
+ re-emits recorded event types, and neither mode restores external host side
131
+ effects or DOM state.
132
+
133
+ <details>
134
+ <summary>Event-stack structure and privacy boundary</summary>
135
+
136
+ Each document carries `protocol`, `sessionId`, `createdAt`, and ordered
137
+ `events`. Each record repeats the protocol/session and carries sequence,
138
+ timing, nesting/causation, source/category, payload, metadata, status, and
139
+ failure evidence. Recording retains the complete selected session until the
140
+ caller clears it or disables recording. Import rejects genuinely malformed or
141
+ unsafe structure and grants no Core capability or provider authority.
142
+
143
+ </details>
144
+
145
+ See [EventManager and time-travel review](event-manager.md) for the callable
146
+ surface, DOM privacy defaults, playback modes, and recovery behavior.
147
+
148
+ ## Browser runtime delivery
149
+
150
+ External and modern integrated workspaces keep the same application URLs and a
151
+ browser-standard import map. Each selected app owns
152
+ `apps/<id>/modules/arcane.importmap.json`; the exact canonical JSON is also
153
+ embedded in its HTML entry as a managed `<script type="importmap"
154
+ data-arcane-import-map>`. The map follows `<base>` and precedes module scripts,
155
+ classic scripts, and module preloads, so application code can use stable named
156
+ imports such as:
157
+
158
+ ```javascript
159
+ import ollama from 'arcane/Ollama';
160
+ ```
161
+
162
+ The physical-v1 tree lives entirely beneath `arcane/`. SDK `0.5.11` projects the
163
+ complete canonical runtime and browser runtime selected by the installed SDK
164
+ package. Runtime dependencies stay under
165
+ `arcane/dependencies/`; the SDK event and browser-AI closure stays under
166
+ `arcane/sdk/`. This URL-key separation prevents runtime and SDK dependency
167
+ versions from aliasing one another.
168
+
169
+ The physical workspace route keeps its established route count and order. The
170
+ external route includes `components`, `css`, `dependencies`, `entities`, `img`,
171
+ `modules`, and `sdk`, followed by optional trailing `security` when that
172
+ directory exists; its external license route remains second. The modern
173
+ integrated physical route uses the same ordered include list in its one route.
174
+ Omitting only that final optional entry is compatible. Removing, reordering, or
175
+ renaming any preceding entry changes the physical contract.
176
+
177
+ The `0.5.11` map derives its complete entries from the selected runtime graph;
178
+ application source imports do not select a fixed entry count. The operation
179
+ result reports `imports`, `entryCount`, and `excludedModules`; reached-file
180
+ traversal remains internal. The
181
+ managed graph exposes `arcane-os/event-manager`, `arcane-os/ai/browser-wasm`,
182
+ `arcane-os/ai/browser-speech`, `arcane-os/preference-store`, and
183
+ `arcane-os/speech-playback`; dependency compatibility mappings are added when
184
+ runtime or SDK root traversal observes them.
185
+
186
+ The focused physical targets remain stable when their bindings are reached:
187
+
188
+ | Browser specifier | Physical target |
189
+ | --- | --- |
190
+ | `arcane-os/event-manager` | `./arcane/sdk/event-manager.mjs` |
191
+ | `arcane-os/ai/browser-wasm` | `./arcane/sdk/ai/browser-wasm.mjs` |
192
+ | `arcane-os/ai/browser-speech` | `./arcane/sdk/ai/browser-speech.mjs` |
193
+ | `arcane-os/preference-store` | `./arcane/modules/PreferenceStore.js` |
194
+ | `arcane-os/speech-playback` | `./arcane/modules/SpeechPlayback.js` |
195
+ | `event-pubsub` | `./arcane/sdk/dependencies/event-pubsub/index.js` |
196
+ | `./node_modules/strong-type/index.js` | `./arcane/dependencies/strong-type/index.js` |
197
+
198
+ There is no `arcane-os` package-root mapping, bare `strong-type` mapping, or
199
+ catch-all `arcane/` prefix. Classic scripts, workers, stylesheets, and other
200
+ non-ESM assets use their documented URL or host loading contract rather than
201
+ invented package bindings. Development serves the selected app plus the
202
+ complete selected tree.
203
+ Packaging copies the same map, app entry, and physical content into `dist/<id>`;
204
+ targets never resolve through the consumer workspace's root `node_modules/`.
205
+ The two lowercase static runtime package specifiers above are also exact npm
206
+ package exports, so Node and managed-browser source can share those specifiers
207
+ without data URLs, copied modules, or a consumer-owned loader.
208
+
209
+ `generateImportMap()` is an internal toolchain operation, not a package export.
210
+ The shared app-document owner derives the configured entry plus the
211
+ deterministic admitted `.html`/`.htm` inventory from the descriptor's package
212
+ include/exclude rules. `import-map`, development, and packaging all reuse that
213
+ discovery. One transaction writes the artifact and the same managed
214
+ JSON into every selected document. The result reports
215
+ `documentPaths`, `documentCount`, and `files`: artifact first, configured entry
216
+ second, then additional documents as `role:"document"`. The public CLI keeps
217
+ its existing two-option command; callers never maintain a separate page list.
218
+
219
+ An external package and development server expose the runtime
220
+ inventory at `/ARCANE_RUNTIME_PROJECTION.json`:
221
+
222
+ ```javascript
223
+ {
224
+ schemaVersion: 1,
225
+ kind: 'arcane-app-runtime-projection',
226
+ sdkVersion,
227
+ pathPrefix: 'arcane/',
228
+ files: [{path}]
229
+ }
230
+ ```
231
+
232
+ The projection contains the complete public paths relative to its declared
233
+ `pathPrefix:'arcane/'` (for example, `modules/...` and `sdk/...`). It does not
234
+ expose the private `/ARCANE_APP_RELEASE.json`. Genuinely malformed projection
235
+ data fails `ARCANE_RUNTIME_PROJECTION_INVALID`.
236
+
237
+ External `validateWorkspace()` results also expose `sdkInstallation` with
238
+ exactly `dependencyName`, `packageSource`,
239
+ `canonicalPackageRoot`, `packageName`, `packageVersion`, `runtimeRoot`,
240
+ and `browserRuntimeRoot`. A
241
+ workspace may use the canonical dependency name or one exact npm alias such as
242
+ `npm:arcane-os@0.5.11`; the physical package manifest must still identify
243
+ exactly as `arcane-os@0.5.11`. Canonical-plus-alias duplicates, multiple aliases,
244
+ links/junctions, indirect package roots, or version drift are reported.
245
+
246
+ For external workspaces, `arcane dev` serves the projected `arcane/` root,
247
+ including `arcane/sdk` and `arcane/dependencies`, alongside the selected
248
+ application. Integrated workspaces retain their configured physical routes.
249
+ The explicit live-source development mapping remains a separate development
250
+ path and does not rewrite the installed projection.
251
+
252
+ The imported module can be pure browser logic, standard-Web-API logic, or a
253
+ client of `globalThis.Arcane`. Import-map resolution is not a new Arcane wire
254
+ protocol, Core capability, network authority, or provider fallback. Import
255
+ transport and host RPC remain separate layers.
256
+
257
+ <details>
258
+ <summary>Refresh lifecycle and managed-file commit behavior</summary>
259
+
260
+ Scaffolding (`new` and `init`) creates the map. `dev` refreshes once before
261
+ binding. `import-map` refreshes every admitted document explicitly.
262
+ Non-dry-run `package`, browser `build`, and paired native packaging refresh
263
+ before collecting source. Packaging does not run tests or checks automatically.
264
+ Explicit `test` and `check` operations read the existing map without rewriting it;
265
+ `verify`, `bundle`, and browser `run` do not refresh. Dry-run packaging/build
266
+ validates an existing map without rewriting it, and `import-map` itself has no
267
+ supported dry-run.
268
+
269
+ Generation stages the artifact and every selected HTML document beside their
270
+ destinations and uses backups to restore the prior managed files after a
271
+ handled pre-commit failure. Success reports `committed: true` and the complete
272
+ managed path inventory. Cleanup failures after commit remain warnings. This is
273
+ a handled-error transaction, not a claim of one filesystem-atomic rename for
274
+ all files and not a durable crash journal.
275
+
276
+ When tests are explicitly selected, external app tests receive an
277
+ `arcane-test-import-map/1` context for that app's managed map. Each isolated
278
+ Node child uses the existing loader for managed names and URL-like compatibility
279
+ keys. Materialized
280
+ modules such as `arcane/TimeGuard` and `arcane/DBOPFS` resolve their canonical
281
+ `arcane-os/event-manager` self-import through this managed map; raw Node import
282
+ of projected `arcane/**` files is not a separate public resolution contract.
283
+ Unmapped `arcane/*` and `#arcane/*` names fail
284
+ `ARCANE_IMPORT_MAP_UNRESOLVED`; ordinary Node exports and test runs without an
285
+ app context retain their existing resolution.
286
+
287
+ No app watches, polls, downloads, or self-updates this map. An active operation's
288
+ heartbeat is event telemetry only and never regenerates browser state.
289
+
290
+ </details>
291
+
292
+ ## Portable AI provider runtime
293
+
294
+ Application code should select a normalized role, not an internal protocol.
295
+ The exported
296
+ [`getAIProviderRuntime()` singleton](runtime-modules.md#aiproviderruntimejs)
297
+ comes from the selected runtime and owns independent `llm`, `stt`, and
298
+ `tts` selections. This SDK release ships browser-WASM LLM and browser
299
+ speech provider/2 adapters and also adapts selected TWiN Cloud LLM,
300
+ Core-backed Ollama LLM, on-device Whisper STT, and on-device Kokoro TTS routes
301
+ into provider/2. There is no cloud speech route;
302
+ other native, Core, or cloud routes require an externally supplied compatible
303
+ adapter. The singleton itself is not an authentication or capability token. It
304
+ normalizes inspection, model authority,
305
+ load/unload/dispose, cancellation, stream cleanup, status, and startup
306
+ barriers. Each selected provider retains its real execution requirements.
307
+ `localOnly` creates no fallback, and failure in one role never authorizes a Core,
308
+ cloud, or different-provider fallback.
309
+
310
+ For a browser-only LLM,
311
+ [`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) exposes `createArcaneAI()`
312
+ and an adapter into the same provider-neutral lifecycle. For browser speech,
313
+ [`arcane-os/ai/browser-speech`](ai/browser-speech.md) creates independent
314
+ Whisper STT and Kokoro TTS providers that register directly with the normalized
315
+ runtime. The SDK supplies mechanism; applications retain model/runtime choice,
316
+ licenses, prompts, tools, voices, and disclosure policy.
317
+
318
+ ### Browser-WASM LLM lifecycle
319
+
320
+ The shipped browser runtime contains the Wllama JavaScript/WASM engine and its
321
+ provider/cache/controller mechanism. It contains no model
322
+ weights, default model catalog, CDN fallback, native provider, speech model, or
323
+ application profile. The caller supplies each model as a source with
324
+ a nonempty ordered file list, so monolithic and split GGUF models use the same
325
+ contract. HTTPS redirects are followed and the final HTTPS URL is recorded.
326
+ Each member may optionally declare positive `bytes` for progress reporting and
327
+ HTTP Range planning. Declared and observed byte measures remain transfer-local
328
+ telemetry; they never validate, admit, identify, hash, or decide cache reuse for
329
+ model content.
330
+
331
+ On load, the DBOPFS store preserves descriptor order while one bounded worker
332
+ pool fetches split members or ranges within the selected member. A split member
333
+ may use one Range worker, allowing an interrupted shard to resume without
334
+ multiplying the configured concurrency. Download progress
335
+ retains its existing completed-file fields and adds raw aggregate bytes,
336
+ remaining bytes, rolling bytes per second, ETA seconds, active transfer
337
+ workers, the transfer limit, and the active transfer mode. Chunk-driven changes
338
+ are coalesced on a 250 ms cadence; start, plan/total, active-worker, and
339
+ completion boundaries may publish immediately. A source member that receives a redirected `200` probes the final URL
340
+ directly before reusing the original response as its single-fetch fallback.
341
+ Confirmed support uses deterministic OPFS Range parts of roughly 4 MB each, up
342
+ to 4,096 parts per member, with bounded active workers; completed parts and
343
+ split-model members survive interruption so a retry fetches only missing work.
344
+ Only unfinished active parts restart after refresh. Without usable range support
345
+ or an observable or declared total it falls back to one full fetch. A normal
346
+ cache miss may fetch only the
347
+ caller-supplied HTTPS sources; `offline:true` performs no model request and uses
348
+ only a compatible completed cache, otherwise it rejects with
349
+ `ARCANE_AI_MODEL_OFFLINE_MISS`. Unload releases the active Wllama session but
350
+ does not silently delete the app-owned cache. A complete whole member supersedes
351
+ its current resumable fragments. Cleanup failure is warned without hiding the
352
+ usable model.
353
+
354
+ SDK `0.5.11` requires WebGPU. Load requests full offload and waits for the runtime
355
+ to report a loaded model. `navigator.gpu` presence alone is
356
+ not readiness. There is no CPU fallback, partial-offload success mode, or
357
+ silent switch to native/Core/cloud inference.
358
+
359
+ ### Browser speech lifecycle
360
+
361
+ The browser-speech package contains plain-JavaScript authority, DBOPFS store,
362
+ provider, client, and Worker machinery. It redistributes no Whisper, Kokoro,
363
+ ONNX, model, voice, third-party license, or corresponding-source payload.
364
+ Default upstream integrations use `createBrowserSpeechAuthority()` with a
365
+ version-pinned npm/package runtime entry and optional upstream `wasmPaths`;
366
+ the selected runtime then downloads models and voices through its normal
367
+ provider fetch and browser cache behavior after explicit `load()`.
368
+
369
+ `createBrowserSpeechArtifactGraph()` is an ordinary materialization descriptor.
370
+ Browser speech uses the caller-selected upstream runtime, model, voice, Fetch,
371
+ cache, and Worker behavior.
372
+
373
+ Ordinary module routing preserves bare import specifiers for native import-map
374
+ resolution and leaves bare `fetch`, `caches`, and `Worker` calls unchanged when
375
+ the module declares a shadowing binding with the same name. Explicit
376
+ `globalThis` or `self` calls continue through the materialized-file router.
377
+
378
+ The speech Worker uses its ordinary global Worker message boundary directly for
379
+ requests, results, errors, and cancellation. It creates no private
380
+ `MessageChannel` and publishes no Worker progress transport.
381
+
382
+ Worker operations use `arcane-ai-speech-worker/1`. The public Worker client
383
+ supports `load`, `use`, `status`, `unload`, and `dispose`; the transport host
384
+ additionally supports its internal `cancel` control. Every other operation
385
+ rejects with code `ARCANE_AI_INVALID_REQUEST`, message
386
+ `The speech worker operation is not part of its protocol.`, and role-specific
387
+ reason `stt-worker-operation-unknown` or `tts-worker-operation-unknown`.
388
+ Failures use the separate
389
+ `arcane-ai-speech-worker-error/1` envelope. Its cause-free form has the four data
390
+ properties `code,message,protocol,reason`; the diagnostic form may add one `cause`
391
+ data property containing the complete serialized diagnostic, including cycles.
392
+ The protocol, registered code, nonempty message, reason, role, and operation
393
+ must agree. A foreign, incomplete, extra-keyed, accessor-bearing, cross-role,
394
+ or cross-operation error envelope is rejected and terminates that role Worker.
395
+ Nested module Workers use
396
+ `arcane-ai-browser-speech-artifact-module-worker/1` and report bootstrap
397
+ rejection only as `artifact-module-worker-bootstrap-rejected`.
398
+
399
+ If the platform cannot clone an exotic `cause`, the Worker keeps the complete
400
+ raw failure in its console diagnostics and retries settlement with the
401
+ cause-free four-field envelope. Nested Workers are terminated during role teardown.
402
+
403
+ Kokoro receives the exact selected `webgpu` or `wasm` device through
404
+ `KokoroTTS.from_pretrained()` and retains the caller-selected dtype. Its WASM
405
+ path is configured through `namespace.env.wasmPaths`; Transformers is configured
406
+ through `namespace.env.backends.onnx.wasm.wasmPaths`. Ordinary mode may use a
407
+ caller-selected version-pinned upstream directory and preserves the runtime's
408
+ browser cache. Optional `numThreads` is caller-owned and
409
+ Transformers-STT-only; a Kokoro declaration rejects with
410
+ `ARCANE_AI_KOKORO_ENV_NUM_THREADS_FIELD_NOT_EXPOSED` /
411
+ `kokoro-env-num-threads-field-not-exposed`. Missing or rejected namespace
412
+ shapes report distinct `*-unavailable` and
413
+ `*-assignment-rejected` reasons for each setting; the Worker never
414
+ substitutes a different namespace. The caller also owns dtype, STT input sample
415
+ rate, TTS output sample rate, default voice, and the complete voice inventory.
416
+ Kokoro execution defaults to `{device:'auto',maxConcurrentRequests:4}` and may
417
+ be overridden with `webgpu` or `wasm` and an integer capacity from 1 through 4.
418
+ Automatic selection attempts a complete WebGPU pool only when WebGPU is exposed,
419
+ then tears it down and forms a complete WASM pool if WebGPU loading rejects. It
420
+ does not change the selected runtime, model, dtype, or voice.
421
+
422
+ Each capacity slot owns one Worker/model session. The provider-neutral runtime
423
+ admits the first four requests and retains segment 5 and later in its FIFO
424
+ queue without dropping content. Synthesis may finish out of order; high-level
425
+ AI playback waits for earlier segments and schedules the contiguous ready
426
+ prefix in exact input order. More sessions trade memory for latency, without
427
+ promising physical GPU kernel overlap.
428
+
429
+ Applications using `AI.configureBrowserSpeech()` can read
430
+ `ai.providerRuntime.status('tts', {execution:true}).execution` instead of
431
+ reaching into provider internals. The optional provider snapshot exposes
432
+ Kokoro's `requestedDevice`, `selectedDevice`, `maxConcurrentRequests`, and
433
+ `activeRequestCount`. The default `status()` retains its original sticky-state
434
+ behavior; explicit execution inspection does not load a provider or emit a
435
+ state event. See [browser speech](ai/browser-speech.md) for complete examples.
436
+
437
+ The SDK is not the distributor of the selected upstream speech packages or
438
+ provider assets and does not republish their legal/source payloads. Package,
439
+ model, voice, and version selection belongs to each consuming application, not
440
+ to a shared SDK component ledger or execution/publication gate.
441
+
442
+ Whisper `stt` and Kokoro `tts` each own catalog, inspect, status, load, request,
443
+ unload, and dispose state. They load, cancel, unload, fail, and recover
444
+ independently from the LLM and from one another. Whisper owns one Worker and one
445
+ request. Kokoro owns a bounded pool of distinct Workers and loaded model
446
+ sessions because the selected browser adapter serializes inference inside one
447
+ JavaScript isolate. Pool loading first completes one model session, then loads
448
+ the remaining Worker sessions concurrently against the same prepared artifact
449
+ selection. One Kokoro request cancellation suppresses only that result and
450
+ sends the targeted Worker cancel control; upstream may still finish work
451
+ already inside `generate()`. Kokoro unload terminates the whole pool. Whisper
452
+ cancellation after Worker use begins retains destructive Worker teardown. If
453
+ shared STT `Blob` decoding is cancelled before Worker use, the request rejects
454
+ while the loaded provider remains ready.
455
+ Speech failure neither disables text chat nor retries through another local,
456
+ native, or cloud provider. The provider/Worker layer is event-neutral: it
457
+ exposes promises, `AbortSignal`, and precise lifecycle/status records, but owns
458
+ no event bus or listener registry. The provider/2 load context accepts an
459
+ optional progress callback for interface compatibility; the current
460
+ browser-speech artifact and Worker transport publishes no progress records.
461
+
462
+ ### Persistent chat and document context
463
+
464
+ The SDK runtime owns
465
+ [`DBOPFSDocumentLibrary`](runtime-modules.md#dbopfsdocumentlibraryjs),
466
+ [`DocumentLexicalSearch`](runtime-modules.md#documentlexicalsearchjs), and
467
+ [`PersistentAIChatSession`](runtime-modules.md#persistentaichatsessionjs).
468
+ DBOPFS JSONL parsing preserves every nonblank unreadable row as its original
469
+ string. Persistent chat can therefore expose the complete saved transcript for
470
+ application-owned inspection and recovery while rejecting that row from
471
+ provider-facing history with a coded persistence error.
472
+ Document bootstrap is explicit and schema-driven, commits a completed
473
+ generation last, and returns complete search results with partial read failures
474
+ disclosed. `evaluate()` can instead score a caller-owned source set without
475
+ persisting its bodies.
476
+ A chat session never searches the corpus unless the application
477
+ deliberately wires a document context builder into the request; generated
478
+ document context remains labeled untrusted.
479
+
480
+ Persistent chat maintains recurring model context plus a sanitized `ChatEntity`
481
+ transcript according to the caller's persistence choice. Structural calls, IDs,
482
+ argument envelopes, and raw results exist only through the one active provider
483
+ continuation that requires them. When that continuation settles, recurring
484
+ model context replaces the protocol exchange with its complete user-facing call
485
+ messages, any supplied public result messages, and the model's visible response.
486
+ Reasoning, request metadata, raw protocol, and raw tool returns do not recur.
487
+ Durable user and assistant turns retain only role, complete visible content, and
488
+ timestamp.
489
+ Durable tool turns retain only role, the required user-facing message as
490
+ content, and optional public name and result status. System prompts remain in
491
+ the live session only. Existing stored files are not rewritten on load. A turn
492
+ with `persist:false` participates in its one request and response only, then
493
+ remains absent from subsequent model context, the retained transcript, memory
494
+ extraction, and DBOPFS.
495
+
496
+ For an automatic model-authored conversation opening, the application calls the
497
+ persistent session's `open()` operation with its internal bootstrap message.
498
+ That bootstrap participates in the one provider request only. The operation
499
+ durably appends only the complete nonblank assistant response, so the opening
500
+ survives reload without a fabricated or retained user turn. A system prompt by
501
+ itself is not a retained conversation turn; an existing retained user,
502
+ assistant, or tool sequence prevents another opening.
503
+
504
+ ### Cancellation and structural tools
505
+
506
+ Cancellation is part of the provider lifecycle, not just a UI decision.
507
+ `AbortSignal`, the normalized role cancel operation, and stream-handle
508
+ `cancel(reason)` propagate to the selected provider. Browser-WASM inference
509
+ requires positive llama cancellation acknowledgement when cancellation is
510
+ required. Browser Whisper cancellation terminates its Worker after Worker use
511
+ begins. Browser Kokoro uses request-targeted cancellation so one synthesis does
512
+ not terminate sibling pool slots; delivery suppression is immediate, while
513
+ engine preemption remains upstream-cooperative. Cancellation during shared
514
+ browser decoding leaves the loaded Worker ready. Unload always cancels every
515
+ active role request before releasing that role's execution state, and
516
+ superseded late results are rejected rather than committed or retried through
517
+ another provider.
518
+
519
+ Interactive requests enter a FIFO lane independently for each role. Provider
520
+ capacity defaults to 1. A TTS provider may declare a positive safe-integer
521
+ `maxConcurrentRequests`; the runtime admits that many oldest requests and queues
522
+ overflow without discarding content. LLM and STT remain capacity 1. A caller
523
+ signal cancels only its own queued or active request, while explicit role
524
+ cancellation targets the oldest active request. Request-specific ownership
525
+ prevents canceled or superseded callbacks from clearing or restoring sibling
526
+ state. The runtime revalidates selected-provider readiness and never reloads,
527
+ switches, or falls back implicitly. Generic provider-promise settlement is not
528
+ a claim that underlying work stopped; only a provider's documented positive
529
+ acknowledgement or destructive worker teardown can prove that stronger fact.
530
+
531
+ `startAIRuntime({startLanguageModel:false,startTranscription:false})` is the
532
+ explicit startup boundary for browser-WASM LLM and default STT activation. It
533
+ leaves the selected LLM unloaded until the shared chat control publishes an
534
+ explicit user load intent; the
535
+ startup barrier then reports `chatReady:false` and `roles.llm.requested:false`
536
+ instead of beginning a browser-WASM download. The omitted/default
537
+ `startLanguageModel:true` preserves existing provider startup behavior. The
538
+ default `startTranscription:false` also declines to request a startup STT load
539
+ and does not unload a role already started through another
540
+ explicit lifecycle action. A selected unloaded
541
+ transcription provider remains selected and unloaded until a user lifecycle
542
+ intent or explicit `startTranscription:true` opt-in asks the provider owner to
543
+ load it. Neither state observation nor either shared speech component imports a
544
+ model or selects a fallback. `speech.html` and `voice-transcription.html` consume
545
+ one shared `createSTTActivationController()` contract for selected, unloaded,
546
+ loading, unloading, error, and ready presentation plus cancelable user intent.
547
+ Both keep capture unavailable until sticky STT state is exactly ready.
548
+
549
+ Each shared speech component owns an `AbortController` for its STT request and
550
+ passes its signal through `AI.fetchSTT()`. `voice-transcription.html` also adds
551
+ that signal to the existing injected `transcribe(file,context)` callback
552
+ context. Cancel, readiness loss, superseding capture, and component teardown
553
+ abort the owned signal and suppress late delivery. Whether the provider's
554
+ underlying computation stops remains governed by its own cancellation contract.
555
+ User TTS unmute calls `AI.setSpeechMuted(false)` before
556
+ or with its load intent so the runtime records the unmuted lifecycle preference;
557
+ an `initialMuted:false` component configuration preserves that intent across an
558
+ unselected or loading TTS route and exposes unmuted state only after readiness;
559
+ mute calls `AI.setSpeechMuted(true)`, cancels active synthesis, and unloads TTS.
560
+ The selected local TTS model catalog owns `defaultVoice`. AI.js never forwards
561
+ a saved OpenAI-route voice to Core or browser Kokoro.
562
+
563
+ LLM tool calls are structural result data only. The SDK never executes a
564
+ handler. The application owns schema validation, authorization, side-effect
565
+ policy, dispatch, and the matching tool-result turn.
566
+
567
+ Ordinary streaming publishes complete nonstructural content and reasoning from
568
+ every provider choice in order. Complete provider chunks and terminal records
569
+ remain independently available through the data callbacks. Structural deltas
570
+ stay private until terminal validation; terminal-only calls are valid, while
571
+ any observed call must keep the same choice, order, identity, exact argument
572
+ string, and extension fields at settlement. Awaiting a terminal result before
573
+ iterating does not stall the private provider stream; projected chunks remain
574
+ available to the later consumer.
575
+
576
+ Every first-party function-tool declaration includes
577
+ `function.parameters.properties.message` as a required nonempty string, and
578
+ every emitted call includes that plain-language user-facing value in the JSON
579
+ encoded by `function.arguments.message`. The application uses `message` for the
580
+ call's progress, question, or next step; it does not treat raw tool envelopes,
581
+ arguments, internal sequencing state, or protocol failures as ordinary
582
+ transcript content. An explicitly selected developer inspection surface may
583
+ show the raw structure separately. This `message` does not replace domain
584
+ fields such as a closing report's `final_message`. One assistant response may
585
+ contain an ordered array of calls with unique IDs. Display does not settle any
586
+ call: one atomic result batch must provide exactly one matching nonblank
587
+ executed, declined, cancelled, or not-executed `role:'tool'` turn for every
588
+ pending ID before another user or provider turn.
589
+
590
+ <details>
591
+ <summary>Portable AI protocol disclosure</summary>
592
+
593
+ The normalized runtime protocol is `arcane-ai-runtime/2`; registered adapters
594
+ implement `arcane-ai-provider/2` and select a model before load. The
595
+ browser-WASM component protocol is `arcane-ai-browser-wasm/2`; its
596
+ direct controller adapter uses `arcane-ai-adapter/1`, and
597
+ `adaptV1LlmProvider()` projects that surface into the provider/2 LLM role.
598
+ Browser speech stores identify themselves as
599
+ `arcane-ai-browser-speech-artifacts/1`. Direct authorities use
600
+ `arcane-ai-model-authority/1`. Optional browser-speech graphs use
601
+ `arcane-ai-browser-speech-artifact-graph/1`, kind
602
+ `browser-speech-authenticated-artifact-graph`. Those identifiers describe
603
+ lifecycle contracts; none is by itself a capability grant.
604
+
605
+ These identifiers normalize lifecycle records. They do not erase provider
606
+ availability: browser providers still require their browser capabilities,
607
+ native providers still require an admitted host and Core method, and cloud
608
+ providers still require explicit selection, network policy, and credentials.
609
+
610
+ </details>
611
+
612
+ ## Arcane application protocol
613
+
614
+ `globalThis.Arcane.protocol` is `arcane/1`. The shared API wraps transport
615
+ selection, request ids, JSON-safe values, promise settlement, `Arcane.Error`,
616
+ and renderer events. The current transport snapshot is synchronous:
617
+
618
+ ```javascript
619
+ const {connected, transport, native, managedLocalAI} =
620
+ globalThis.Arcane.runtime.current();
621
+ ```
622
+
623
+ Transport values are `webview2`, `webkitgtk`, `android-webview`,
624
+ `development-http`, and `standalone`. `connected` means a callable transport
625
+ was initialized. It does not prove that Core answered, the method is admitted,
626
+ or a dependency is ready.
627
+
628
+ ## Native host transports
629
+
630
+ ### Microsoft NT / WebView2
631
+
632
+ The renderer uses the WebView2 host messaging surface. The host binds one app
633
+ identity and native policy to the session before Core dispatch. Microsoft NT
634
+ can expose managed-service and privileged platform operations that do not exist
635
+ in an ordinary browser.
636
+
637
+ ### Linux / WebKitGTK
638
+
639
+ The renderer uses the WebKitGTK host bridge with the same application-facing
640
+ `Arcane` protocol. Linux can implement the same normalized methods through
641
+ different host code. Some administrator-owned service settings intentionally
642
+ return unsupported/manual guidance rather than imitating Microsoft NT mutation.
643
+
644
+ ### Android / Android WebView
645
+
646
+ Android injects a main-frame, origin-bound bridge for the packaged application.
647
+ Its generated registry binds application identity, package version, entry,
648
+ grants, and method policy. Android exposes a narrower surface, including an
649
+ admitted user-managed local-AI chat projection where configured. Desktop model
650
+ management is not projected merely because a user-managed Ollama listener is
651
+ reachable.
652
+
653
+ ### macOS
654
+
655
+ No macOS target, native bridge, Core host, artifact, or run contract is exposed
656
+ by this SDK version. A browser may still run browser-only application code, but
657
+ that does not create a native Arcane host or satisfy a native capability.
658
+
659
+ ## Development and remote HTTP transport
660
+
661
+ The development HTTP bridge makes the same application-facing request shape
662
+ available without pretending the browser is a native host. It is a development
663
+ transport, not a production isolation or authority boundary. A remotely
664
+ operated client can use an expressly configured web transport only when the
665
+ host, origin, application identity, and policy admit it; Arcane does not silently
666
+ swap native calls to arbitrary remote HTTP endpoints.
667
+
668
+ When transport changes while the public method remains the same, request
669
+ settlement and public errors stay normalized. Host-specific availability and
670
+ result detail remain documented by the method.
671
+
672
+ ## Core dispatch and capability admission
673
+
674
+ The host binds the caller's application identity. Core checks the exact method,
675
+ required capability, allowed application type/id, privilege, mutation
676
+ exclusivity, request bounds, and relevant package policy. Renderer-supplied app
677
+ ids or grants never replace that bound identity.
678
+
679
+ `Arcane.capabilities.list()` is the Core-side application preflight. It reports
680
+ current grants and admitted methods but does not reserve authority for a later
681
+ call. Each call is checked again.
682
+
683
+ ## Arcane Ollama protocol path
684
+
685
+ The safe application path is:
686
+
687
+ ```text
688
+ renderer Ollama.js or Arcane.ollama
689
+ -> arcane/1 host request
690
+ -> Core capability and package-policy admission
691
+ -> managed ArcaneOllama loopback service
692
+ -> complete Ollama HTTP operation
693
+ ```
694
+
695
+ Applications never connect directly to `localhost:11434`. Core owns loopback
696
+ endpoint selection, method policy, stream ids,
697
+ chunk events, model-policy checks, native resource admission, and managed
698
+ mutation workflows.
699
+
700
+ Direct Ollama methods preserve the complete provider-native success envelope.
701
+ Arcane normalizes the outer promise/error and stream lifecycle. `chatText`,
702
+ `generateText`, and `readiness` are helper-level normalizers.
703
+
704
+ ## Explicit cloud provider path
705
+
706
+ `arcane/AI` can use an explicitly selected and configured cloud
707
+ profile over HTTPS. That path is not Core transport fallback. The module adapts
708
+ the selected provider into its high-level application behavior, while provider
709
+ diagnostics and optional fields can remain provider-specific. Native policy and
710
+ network policy still govern a native renderer's outbound access.
711
+
712
+ Local failure never authorizes cloud disclosure. The user or owning application
713
+ must select and configure the cloud provider explicitly.
714
+
715
+ ## Events, streaming, and cancellation
716
+
717
+ Renderer-visible Core events are listed in
718
+ [the Arcane event reference](core/arcane-events.md). Durable
719
+ `transport.ready` and `core.ready` completions can be observed after the fact
720
+ with `Arcane.events.when()`. Ordinary progress, stream, terminal, and appearance
721
+ events are future-only.
722
+
723
+ Ollama streaming correlates chunks to the originating request. A renderer
724
+ abort or timeout can stop observation without proving that a non-cooperative
725
+ host mutation stopped. Method guides state whether Core cooperatively cancels,
726
+ whether partial provider state can remain, and which status call must be
727
+ refreshed before retry.
728
+
729
+ ## Cross-kernel normalization boundary
730
+
731
+ The common contract ends where platform truth must remain different:
732
+
733
+ - API names, promise/error behavior, host capability policy, and public
734
+ operation events are normalized;
735
+ - host availability, privilege model, installation/service mechanism, native
736
+ artifact kind, and some diagnostic/result fields remain platform-specific;
737
+ - unsupported platforms fail or return a documented unsupported state; they do
738
+ not run an unrelated browser implementation as a substitute;
739
+ - this SDK version requires a selected checkout and Core to provide the current
740
+ native plan's protocol, version, feature, capability, method, and provider;
741
+ - that current-build compatibility does not promise that a future SDK will accept
742
+ this Core or that this SDK will accept a future Core.
743
+
744
+ ## Complete-content boundary
745
+
746
+ SDK runtime, app releases, import-map files, bundles, native plans, providers,
747
+ and artifacts preserve their complete selected content. Required credential
748
+ protection, genuinely malformed input rejection, applicable law, external
749
+ protocol requirements, and host platform safety remain in effect.