arcane-os 0.5.13 → 0.5.15

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 +32 -0
  2. package/README.md +33 -8
  3. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +11 -10
  4. package/browser-runtime/ai/browser-wllama-runtime.mjs +2 -1
  5. package/browser-runtime/ai/model-controller.mjs +6 -5
  6. package/browser-runtime/ai/speech-worker-client.mjs +45 -3
  7. package/browser-runtime/event-manager.mjs +2 -1
  8. package/browser-runtime/logging.mjs +58 -0
  9. package/docs/architecture.md +1 -1
  10. package/docs/reference/README.md +9 -7
  11. package/docs/reference/ai/browser-speech.md +90 -1
  12. package/docs/reference/ai/twin-cloud.md +1 -1
  13. package/docs/reference/cli.md +1 -1
  14. package/docs/reference/core/arcane-ai-contracts.md +1 -1
  15. package/docs/reference/inventory/package-api.json +34 -6
  16. package/docs/reference/inventory/runtime-components.json +1 -1
  17. package/docs/reference/inventory/runtime-modules.json +4 -4
  18. package/docs/reference/protocols.md +5 -5
  19. package/docs/reference/runtime-modules.md +70 -15
  20. package/docs/reference/sdk-api.md +120 -11
  21. package/package.json +4 -3
  22. package/runtime/arcane/components/app-bar.html +3 -1
  23. package/runtime/arcane/components/chat.html +22 -20
  24. package/runtime/arcane/components/dashboard-config.html +3 -1
  25. package/runtime/arcane/components/data-maintenance.html +4 -2
  26. package/runtime/arcane/components/data-view.html +3 -1
  27. package/runtime/arcane/components/directory-picker.html +3 -1
  28. package/runtime/arcane/components/file-manager.html +11 -9
  29. package/runtime/arcane/components/header.html +5 -3
  30. package/runtime/arcane/components/markdown-document.html +3 -1
  31. package/runtime/arcane/components/markdown-editor.html +4 -2
  32. package/runtime/arcane/components/modal.html +3 -1
  33. package/runtime/arcane/components/screen-capture.html +4 -2
  34. package/runtime/arcane/components/speech.html +10 -8
  35. package/runtime/arcane/components/table.html +3 -1
  36. package/runtime/arcane/components/voice-transcription.html +8 -6
  37. package/runtime/arcane/entities/Chat.js +5 -4
  38. package/runtime/arcane/entities/User.js +2 -1
  39. package/runtime/arcane/modules/AI.js +442 -292
  40. package/runtime/arcane/modules/AIProviderRuntime.js +359 -82
  41. package/runtime/arcane/modules/CommunicationAppController.js +2 -1
  42. package/runtime/arcane/modules/ComponentContracts.js +3 -2
  43. package/runtime/arcane/modules/ConversationTimebox.js +2 -1
  44. package/runtime/arcane/modules/DBOPFS.js +5 -4
  45. package/runtime/arcane/modules/Errors.js +3 -14
  46. package/runtime/arcane/modules/HTMLImport.js +4 -3
  47. package/runtime/arcane/modules/LocalAIReadinessController.js +2 -1
  48. package/runtime/arcane/modules/MD.js +3 -2
  49. package/runtime/arcane/modules/MailOutbox.mjs +2 -1
  50. package/runtime/arcane/modules/PersistentAIChatSession.js +2 -1
  51. package/runtime/arcane/modules/ScreenCapture.js +2 -1
  52. package/runtime/arcane/modules/SpeechPlayback.js +206 -40
  53. package/runtime/arcane/modules/ThemeBootstrap.js +3 -2
  54. package/runtime/arcane/modules/ToolCallRouter.js +2 -1
  55. package/src/import-map.mjs +65 -10
@@ -13,7 +13,7 @@ import map resolves `arcane/AI` and `arcane/DBOPFS`. These browser modules are
13
13
  not Node inference APIs. To create an application:
14
14
 
15
15
  ```bash
16
- npx arcane-os@0.5.12 new hello-speech --path ./hello-speech --target browser
16
+ npx arcane-os@0.5.15 new hello-speech --path ./hello-speech --target browser
17
17
  cd hello-speech
18
18
  npm install
19
19
  npm run dev
@@ -121,6 +121,51 @@ window.addEventListener('ai-tts-failure', function reportSpeechFailure(event) {
121
121
 
122
122
  Call `speechEvents.abort()` when disposing that interface to remove the listener.
123
123
 
124
+ ## Developer diagnostics
125
+
126
+ The shared logging API and speech traces are available in SDK `0.5.14`.
127
+
128
+ Arcane uses the existing shared `user.developer` preference for diagnostic
129
+ logging. Enable **developer mode** in the application's profile settings; the
130
+ logger reads that preference on every emission after the shared user is ready.
131
+ There is no separate speech verbosity or language setting. Ordinary warnings
132
+ and errors remain visible with developer mode disabled.
133
+
134
+ Applications can use the same owner for their complete AI requests and parsed
135
+ responses:
136
+
137
+ ```javascript
138
+ import { arcaneLogging } from 'arcane-os/logging';
139
+
140
+ arcaneLogging.info('AI request', request);
141
+ arcaneLogging.info('AI response', response);
142
+ ```
143
+
144
+ `arcaneLogging.log`, `.info`, and `.debug` use the developer preference and
145
+ appear at the browser console's normal Info level. `.warn`, `.error`, and
146
+ failure `.trace` calls remain visible in either mode. The same logger is
147
+ available as `globalThis.arcaneLogging`; it stores no diagnostic history.
148
+
149
+ Speech diagnostics include complete API inputs and results, selected provider
150
+ and model, exact segment text, voice and speed, generation queue state, Worker
151
+ request IDs and responses, and decoding/playback events. Worker requests are
152
+ copied only for developer diagnostics before native transfer detaches their
153
+ audio buffers; the original request still goes to the Worker unchanged.
154
+
155
+ Follow a speech `jobId` through `queue.add`, `generation.request`,
156
+ `generation.result`, `decode.result`, `playback.scheduled`, `playback.ended`,
157
+ and `queue.complete`. Cancellation and failure appear as `queue.cancelled`
158
+ and `queue.failed`. Each playback record includes the audio clock,
159
+ sample rate, duration, playback rate, and scheduled start/end when available.
160
+ For ready adjacent buffers, `gapSeconds` is zero on the same audio clock;
161
+ `audioEnd` marks the end of audio and `scheduledEnd` includes the caller's
162
+ requested pause. A positive gap can expose generation arriving too late to
163
+ fill the audio clock continuously. A scheduled event alone does not establish
164
+ that the buffer finished; use its `playback.ended` event.
165
+
166
+ Diagnostics do not change text, voice, speed, language selection, segmentation,
167
+ generation capacity, or playback scheduling. They stay outside chat history.
168
+
124
169
  ## Four synthesis slots and exact-order playback
125
170
 
126
171
  Capacity 4 means up to four segments synthesize at once. Segment 5 and later
@@ -135,6 +180,50 @@ Ready adjacent audio buffers use contiguous AudioContext scheduling. Browser
135
180
  audio scheduling and selected WebGPU status do not prove physical GPU kernel
136
181
  overlap or audio quality. LLM and Whisper/STT capacity remains one.
137
182
 
183
+ ## Play a complete array with `SpeechPlayback`
184
+
185
+ Use this when your application already has complete segments in an array. The
186
+ configured `ai` below is the same instance created in the quick start.
187
+
188
+ ```javascript
189
+ import SpeechPlayback from 'arcane/SpeechPlayback';
190
+
191
+ const audio = document.body.appendChild(document.createElement('audio'));
192
+ audio.controls = true;
193
+ const narration = new SpeechPlayback({audio, speech: ai});
194
+ const speakAll = document.body.appendChild(document.createElement('button'));
195
+ speakAll.textContent = 'Speak all segments';
196
+ speakAll.addEventListener('click', async function speakAllSegments() {
197
+ await ai.setSpeechMuted(false);
198
+ await narration.prepare({
199
+ parts: [
200
+ 'First complete segment.',
201
+ 'Second complete segment.',
202
+ 'Third complete segment.'
203
+ ],
204
+ autoplay: true
205
+ });
206
+ });
207
+ ```
208
+
209
+ `prepare()` submits all three parts immediately because this `ai` exposes
210
+ `fetchTTS` and advertises TTS execution capacity. With the default configuration,
211
+ the provider admits up to four synthesis requests and keeps later requests in
212
+ its FIFO queue. Completed audio remains indexed, so playback is always first,
213
+ second, third even if the third synthesis finishes first.
214
+
215
+ This eager path is capability-driven. A native `Arcane.speech.synthesize`
216
+ client, or a custom client without a positive advertised TTS execution capacity,
217
+ retains serialized synthesis with one lookahead segment. `togglePause()` pauses
218
+ and resumes the same `audio` element. `stop()` cancels all requests owned by the
219
+ playback. `replay()` keeps completed and pending provider segments and retries
220
+ only failed missing segments.
221
+
222
+ The default `{device:'auto',maxConcurrentRequests:4}` attempts the full ONNX
223
+ Worker/session pool on WebGPU, then recreates that pool on WASM only if WebGPU
224
+ loading fails. Use the status example below to read `selectedDevice`; console
225
+ node-assignment warnings alone do not identify the selected execution device.
226
+
138
227
  ## Queue complete passages and wait for playback
139
228
 
140
229
  These options are available in SDK `0.5.12`.
@@ -9,7 +9,7 @@ same managed browser imports as the [browser speech quick start](browser-speech.
9
9
  Create an application and start its source server:
10
10
 
11
11
  ```bash
12
- npx arcane-os@0.5.12 new hello-twin --path ./hello-twin --target browser
12
+ npx arcane-os@0.5.15 new hello-twin --path ./hello-twin --target browser
13
13
  cd hello-twin
14
14
  npm install
15
15
  npm run dev
@@ -214,7 +214,7 @@ portable runtime subpaths such as `arcane-os/preference-store` and
214
214
  modules. The result reports the complete map written to the selected
215
215
  application; no fixed entry count is a release contract.
216
216
 
217
- SDK `0.5.12` preserves the physical workspace route count and ordered include
217
+ SDK `0.5.15` preserves the physical workspace route count and ordered include
218
218
  list. External and modern integrated routes require `components`, `css`,
219
219
  `dependencies`, `entities`, `img`, `modules`, and `sdk`; a physical workspace
220
220
  may omit only an optional trailing `security` include. The external license
@@ -9,7 +9,7 @@ They are not TypeScript declarations.
9
9
 
10
10
  ## Portable SDK AI and Core AI
11
11
 
12
- The SDK `0.5.12` has two related but separate normalized boundaries:
12
+ The SDK `0.5.15` has two related but separate normalized boundaries:
13
13
 
14
14
  | Boundary | Use | Host |
15
15
  |---|---|---|
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "sdkVersion": "0.5.12",
3
+ "sdkVersion": "0.5.15",
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": 204,
9
+ "memberCount": 198,
10
10
  "members": [
11
11
  {
12
12
  "id": "root:APP_BUNDLE_DESCRIPTOR_NAME",
@@ -1392,10 +1392,10 @@
1392
1392
  "entrypoints": ["arcane-os/speech-playback"],
1393
1393
  "primaryImport": "arcane-os/speech-playback",
1394
1394
  "group": "Portable runtime modules",
1395
- "summary": "Default binding for the canonical SpeechPlayback runtime class in Node and managed browsers.",
1395
+ "summary": "Default binding for the canonical SpeechPlayback runtime class, with capability-gated eager provider submission and exact-order playback.",
1396
1396
  "availability": "Node with injected media adapters, or browser/native WebView media",
1397
1397
  "protocol": "SpeechPlayback runtime contract",
1398
- "normalization": "Binding identity and namespace come directly from the canonical runtime module"
1398
+ "normalization": "Binding identity and namespace come directly from the canonical runtime module; a fetchTTS client with positive advertised TTS execution capacity receives all complete segments immediately while its provider owns bounded admission and SpeechPlayback retains indexed order; other clients remain serialized"
1399
1399
  },
1400
1400
  {
1401
1401
  "id": "speech-playback:SPEECH_PLAYBACK_STATE_EVENT",
@@ -1420,10 +1420,10 @@
1420
1420
  "entrypoints": ["arcane-os/speech-playback"],
1421
1421
  "primaryImport": "arcane-os/speech-playback",
1422
1422
  "group": "Portable runtime modules",
1423
- "summary": "Named binding for the same canonical class exposed as the subpath default.",
1423
+ "summary": "Named binding for the same capability-aware, exact-order canonical class exposed as the subpath default.",
1424
1424
  "availability": "Node with injected media adapters, or browser/native WebView media",
1425
1425
  "protocol": "SpeechPlayback runtime contract",
1426
- "normalization": "Binding identity equals the default export; prepare preserves each nonblank part input exactly without trimming, splitting, or freezing it; provider and media availability remain host-owned"
1426
+ "normalization": "Binding identity equals the default export; prepare preserves each nonblank part input exactly without trimming, splitting, or freezing it; provider-advertised capacity enables eager submission while the provider owns its bound, native and custom clients remain serialized, and media availability remains host-owned"
1427
1427
  },
1428
1428
  {
1429
1429
  "id": "speech-playback:splitSpeechText",
@@ -3189,6 +3189,34 @@
3189
3189
  "availability": "Node and browser",
3190
3190
  "protocol": "Arcane Mail HTTP transport",
3191
3191
  "normalization": "Returns compact JSON and rejects non-object or non-serializable reports"
3192
+ },
3193
+ {
3194
+ "id": "logging:arcaneLogging",
3195
+ "name": "arcaneLogging",
3196
+ "displayName": "arcaneLogging",
3197
+ "kind": "singleton",
3198
+ "signature": "const arcaneLogging",
3199
+ "entrypoints": ["arcane-os/logging"],
3200
+ "primaryImport": "arcane-os/logging",
3201
+ "group": "Shared logging",
3202
+ "summary": "Shared console owner controlled by the existing user.developer preference.",
3203
+ "availability": "Node and browser",
3204
+ "protocol": "Shared user.developer preference and host console",
3205
+ "normalization": "Reads developer mode on every diagnostic emission; log, info, and debug use console.info only when enabled; warn, error, and failure trace remain visible in either mode; arguments pass through unchanged without retained history"
3206
+ },
3207
+ {
3208
+ "id": "logging:readArcaneDeveloperMode",
3209
+ "name": "readArcaneDeveloperMode",
3210
+ "displayName": "readArcaneDeveloperMode()",
3211
+ "kind": "function",
3212
+ "signature": "readArcaneDeveloperMode(target=globalThis)",
3213
+ "entrypoints": ["arcane-os/logging"],
3214
+ "primaryImport": "arcane-os/logging",
3215
+ "group": "Shared logging",
3216
+ "summary": "Reads the existing developer-mode preference without creating or changing a setting.",
3217
+ "availability": "Node and browser",
3218
+ "protocol": "Shared user.developer preference",
3219
+ "normalization": "Returns null until target.user.ready is true, then whether target.user.developer is exactly true; returns false if preference access throws"
3192
3220
  }
3193
3221
  ]
3194
3222
  }
@@ -5,7 +5,7 @@
5
5
  "repository": "https://github.com/TheWizardNexus/arcane-os-sdk.git",
6
6
  "branch": "main",
7
7
  "path": "runtime/arcane/components",
8
- "sdkVersion": "0.5.12"
8
+ "sdkVersion": "0.5.15"
9
9
  },
10
10
  "componentCount": 39,
11
11
  "loader": "/arcane/modules/HTMLImport.js",
@@ -5,7 +5,7 @@
5
5
  "repository": "https://github.com/TheWizardNexus/arcane-os-sdk.git",
6
6
  "branch": "main",
7
7
  "path": "runtime/arcane",
8
- "sdkVersion": "0.5.12",
8
+ "sdkVersion": "0.5.15",
9
9
  "protocol": "arcane/1"
10
10
  },
11
11
  "artifactCount": 84,
@@ -1153,10 +1153,10 @@
1153
1153
  "default",
1154
1154
  "splitSpeechText"
1155
1155
  ],
1156
- "summary": "Preserves exact nonblank text as one segment without trimming, splitting, or freezing it; queues latest-request synthesis and controls lookahead HTML audio playback.",
1156
+ "summary": "Preserves exact nonblank segment text without trimming, splitting, or freezing it; eagerly submits complete parts to a capacity-advertising fetchTTS provider while keeping playback indexed, and retains serialized one-segment lookahead for other clients.",
1157
1157
  "availability": "Browser + compatible AI/native bridge",
1158
- "protocol": "AI.fetchTTS or compatible Arcane.speech.synthesize, globalThis.arcaneEvents, Blob URLs, audio element",
1159
- "normalization": "Exact nonblank split/part input strings are preserved in mutable records while playback policy, cancellation, Blob results, and lifecycle state are normalized; provider failures remain external.",
1158
+ "protocol": "AI.fetchTTS plus providerRuntime TTS execution capacity, or compatible serialized Arcane.speech.synthesize; globalThis.arcaneEvents, Blob URLs, audio element",
1159
+ "normalization": "Exact nonblank split/part input strings are preserved in mutable records. A capable provider receives complete segments immediately and owns bounded FIFO admission; URLs and playback stay in exact input order. Native/custom clients remain serialized. Cancellation, Replay recovery, Blob results, and lifecycle state are normalized; provider failures remain external.",
1160
1160
  "surface": "SpeechPlayback class/default, `SPEECH_PLAYBACK_STATE_EVENT`, `splitSpeechText()`, canonical playback lifecycle events, cancellation, and destroy APIs."
1161
1161
  },
1162
1162
  {
@@ -159,7 +159,7 @@ imports such as:
159
159
  import ollama from 'arcane/Ollama';
160
160
  ```
161
161
 
162
- The physical-v1 tree lives entirely beneath `arcane/`. SDK `0.5.12` projects the
162
+ The physical-v1 tree lives entirely beneath `arcane/`. SDK `0.5.15` projects the
163
163
  complete canonical runtime and browser runtime selected by the installed SDK
164
164
  package. Runtime dependencies stay under
165
165
  `arcane/dependencies/`; the SDK event and browser-AI closure stays under
@@ -174,7 +174,7 @@ integrated physical route uses the same ordered include list in its one route.
174
174
  Omitting only that final optional entry is compatible. Removing, reordering, or
175
175
  renaming any preceding entry changes the physical contract.
176
176
 
177
- The `0.5.12` map derives its complete entries from the selected runtime graph;
177
+ The `0.5.15` map derives its complete entries from the selected runtime graph;
178
178
  application source imports do not select a fixed entry count. The operation
179
179
  result reports `imports`, `entryCount`, and `excludedModules`; reached-file
180
180
  traversal remains internal. The
@@ -239,8 +239,8 @@ exactly `dependencyName`, `packageSource`,
239
239
  `canonicalPackageRoot`, `packageName`, `packageVersion`, `runtimeRoot`,
240
240
  and `browserRuntimeRoot`. A
241
241
  workspace may use the canonical dependency name or one exact npm alias such as
242
- `npm:arcane-os@0.5.12`; the physical package manifest must still identify
243
- exactly as `arcane-os@0.5.12`. Canonical-plus-alias duplicates, multiple aliases,
242
+ `npm:arcane-os@0.5.15`; the physical package manifest must still identify
243
+ exactly as `arcane-os@0.5.15`. Canonical-plus-alias duplicates, multiple aliases,
244
244
  links/junctions, indirect package roots, or version drift are reported.
245
245
 
246
246
  For external workspaces, `arcane dev` serves the projected `arcane/` root,
@@ -351,7 +351,7 @@ does not silently delete the app-owned cache. A complete whole member supersedes
351
351
  its current resumable fragments. Cleanup failure is warned without hiding the
352
352
  usable model.
353
353
 
354
- SDK `0.5.12` requires WebGPU. Load requests full offload and waits for the runtime
354
+ SDK `0.5.15` requires WebGPU. Load requests full offload and waits for the runtime
355
355
  to report a loaded model. `navigator.gpu` presence alone is
356
356
  not readiness. There is no CPU fallback, partial-offload success mode, or
357
357
  silent switch to native/Core/cloud inference.
@@ -152,6 +152,24 @@ entry points. `streamMessage(...)` and `streamRequest(options)` deliver
152
152
  incremental responses. The positional and object forms share the existing
153
153
  provider implementations; neither form is a retired compatibility API.
154
154
 
155
+ Built-in cloud chat decodes an HTTP error body once as JSON or text and rejects
156
+ with that complete value unchanged. It does not reconstruct an Error, replace
157
+ the message, or add `providerMessage`, `status`, or an SDK failure code to the
158
+ provider body. Network and decoding errors also pass through; cancellation
159
+ retains the existing `ARCANE_AI_REQUEST_ABORTED` contract.
160
+
161
+ When the HTTP status is `429` and the existing `error.message`, `message`, or
162
+ plain-text body contains `overload`, ignoring case, the request retries after
163
+ three seconds without a retry-count limit. Each warning shows the complete
164
+ message followed by `Retrying in ${retryDelayMs / 1000} seconds` through the
165
+ shared console logger, separately from the provider error. Every attempt uses
166
+ the same destination, headers, complete serialized body, and cancellation
167
+ signal; `onRequest` runs once for the logical request. Cancellation stops the
168
+ delay and prevents another attempt. Retrying happens before a successful
169
+ response is consumed, so partial streams and tool callbacks are never replayed.
170
+ Native Ollama and externally supplied provider adapters retain their own
171
+ transport behavior.
172
+
155
173
  Initialization uses the canonical realm user's actual readiness state. If
156
174
  `window.user?.ready` is already true, AI initializes immediately. Otherwise one
157
175
  shared registration observes `user-entity-loaded`, then rechecks readiness
@@ -2831,8 +2849,9 @@ console.log(Object.keys(module));
2831
2849
 
2832
2850
  ### Overview
2833
2851
 
2834
- Preserves exact nonblank text as one segment, queues latest-request speech
2835
- synthesis, and controls lookahead HTML audio playback.
2852
+ Preserves exact nonblank text, admits complete speech segments according to the
2853
+ selected client's advertised capacity, and plays indexed HTML audio in exact
2854
+ input order.
2836
2855
 
2837
2856
  ### Public surface
2838
2857
 
@@ -2870,6 +2889,26 @@ freezing it. `prepare()` likewise preserves each nonblank part's exact `input`
2870
2889
  string while normalizing its other playback fields into a new mutable record.
2871
2890
  The class applies no part-count, character-count, pause, or input upper cap.
2872
2891
 
2892
+ ### Admission and playback order
2893
+
2894
+ When `speech` exposes both `fetchTTS(payload, signal)` and
2895
+ `providerRuntime.status('tts', {execution:true}).execution.maxConcurrentRequests`
2896
+ as a positive safe integer, `prepare()` submits every complete `parts` entry
2897
+ immediately. `SpeechPlayback` does not create a second limiter: the provider
2898
+ runtime owns bounded FIFO admission. Browser Kokoro defaults that capacity to
2899
+ four, so up to four segments can synthesize while later submissions wait in the
2900
+ provider queue. A later segment may finish first, but its Blob URL stays at its
2901
+ original index and is never played ahead of an earlier segment.
2902
+
2903
+ If that capacity is absent, invalid, or unavailable, `SpeechPlayback` retains
2904
+ the compatible serialized path and prepares only one lookahead segment. This is
2905
+ the default for `Arcane.speech.synthesize` and custom clients, so native hosts
2906
+ with one synthesis lock are not driven concurrently. Pause and Resume control
2907
+ the same supplied `audio` element. Stop aborts every owned synthesis signal and
2908
+ releases prepared URLs. Replay keeps completed URLs and still-pending provider
2909
+ work, then re-submits only failed missing provider segments before starting
2910
+ again from index zero.
2911
+
2873
2912
  Every preparation owns an operation ID and one AbortController for each active
2874
2913
  synthesis segment or playback delay. Replacement,
2875
2914
  `stop()`, `cancel()`, and `destroy()` abort their owned signals, suppress stale
@@ -2877,9 +2916,10 @@ settlement, release Blob URLs, and publish synchronous
2877
2916
  `speech-playback-state` occurrences through `globalThis.arcaneEvents`.
2878
2917
  Subscribers receive mutable public state detail. The detail contains
2879
2918
  `state`, `message`, `key`, `index`, `total`, `producing`, `buffered`, `hasAudio`,
2880
- `operationId`, `code`, and `reason`; provider rejection remains preserved to the
2881
- `prepare()` caller. `destroy()` also removes every audio listener and disposes
2882
- its per-instance canonical source handle; repeated destroy returns
2919
+ `operationId`, `code`, and `reason`; a first-segment provider rejection remains
2920
+ preserved to the `prepare()` caller. Later failures surface when ordered
2921
+ playback reaches that segment. `destroy()` also removes every audio listener
2922
+ and disposes its per-instance canonical source handle; repeated destroy returns
2883
2923
  `false`. Signal abortion proves delivery suppression; whether provider work
2884
2924
  actually stops remains the selected provider's cancellation boundary.
2885
2925
 
@@ -2916,23 +2956,38 @@ const audio = document.body.appendChild(document.createElement('audio'));
2916
2956
  audio.controls = true;
2917
2957
  const speech = new SpeechPlayback({
2918
2958
  audio,
2919
- speech: globalThis.ai,
2920
- model: 'caller-selected-model',
2921
- voice: 'caller-selected-voice',
2922
- responseFormat: 'wav'
2959
+ speech: globalThis.ai
2923
2960
  });
2924
- const speakButton = document.body.appendChild(document.createElement('button'));
2925
- speakButton.type = 'button';
2926
- speakButton.textContent = 'Speak';
2927
- speakButton.addEventListener('click', async () => {
2961
+ const button = document.body.appendChild(document.createElement('button'));
2962
+ button.textContent = 'Speak';
2963
+ button.addEventListener('click', async function speakCompleteSegments() {
2964
+ await globalThis.ai.setSpeechMuted(false);
2928
2965
  await speech.prepare({
2929
- key: 'ready',
2930
- parts: ['Arcane is ready.'],
2966
+ parts: [
2967
+ 'First complete segment.',
2968
+ 'Second complete segment.'
2969
+ ],
2931
2970
  autoplay: true
2932
2971
  });
2933
2972
  });
2934
2973
  ```
2935
2974
 
2975
+ With the default browser speech configuration, both parts enter its capacity-4
2976
+ queue immediately and still play first, then second. Inspect the selected
2977
+ execution device without guessing from console warnings:
2978
+
2979
+ ```javascript
2980
+ const execution = globalThis.ai.providerRuntime.status(
2981
+ 'tts',
2982
+ { execution: true }
2983
+ ).execution;
2984
+ console.log(execution.selectedDevice, execution.maxConcurrentRequests);
2985
+ ```
2986
+
2987
+ `requestedDevice:'auto'` attempts the complete ONNX Worker/session pool on
2988
+ WebGPU and recreates it on WASM if WebGPU loading fails. The reported selected
2989
+ device proves provider selection, not physical GPU kernel overlap.
2990
+
2936
2991
  ## StaticDocumentCatalog.js
2937
2992
 
2938
2993
  ### Overview
@@ -1,7 +1,7 @@
1
1
  # Arcane OS SDK JavaScript API
2
2
 
3
3
  The npm package exposes a Node.js ESM control plane, the portable
4
- `arcane-os/event-manager`, `arcane-os/mail`, `arcane-os/preference-store`, and
4
+ `arcane-os/event-manager`, `arcane-os/logging`, `arcane-os/mail`, `arcane-os/preference-store`, and
5
5
  `arcane-os/speech-playback` entrypoints, and the browser-only
6
6
  `arcane-os/ai/browser-wasm` and `arcane-os/ai/browser-speech` entrypoints.
7
7
  Those package subpaths are distinct from application-facing projection modules
@@ -18,7 +18,7 @@ This table is the Node `package.json#exports` map: it defines package
18
18
  entrypoints for SDK/tooling code. It is distinct from the generated browser
19
19
  import map that resolves application-facing `arcane/*` modules and the focused
20
20
  EventManager entry. See [browser runtime delivery](protocols.md#browser-runtime-delivery)
21
- for the installed-inventory-derived physical-runtime contract in SDK `0.5.12`.
21
+ for the installed-inventory-derived physical-runtime contract in SDK `0.5.15`.
22
22
 
23
23
  | Specifier | Purpose |
24
24
  | --- | --- |
@@ -33,6 +33,7 @@ for the installed-inventory-derived physical-runtime contract in SDK `0.5.12`.
33
33
  | `arcane-os/packager` | Low-level browser app packager. |
34
34
  | `arcane-os/release-bundle` | Deterministic external release bundles. |
35
35
  | `arcane-os/event-manager` | Central synchronous events, complete time-travel history, playback, and optional DOM instrumentation. |
36
+ | `arcane-os/logging` | Shared console diagnostics controlled by the existing `user.developer` preference. |
36
37
  | `arcane-os/preference-store` | Portable preference records and injected storage adapters. |
37
38
  | `arcane-os/speech-playback` | Portable speech preparation, playback state, and injected media adapters. |
38
39
  | `arcane-os/ai/browser-wasm` | Caller-selected browser-local Wllama inference, complete DBOPFS model storage, streaming, cancellation, and structural tool-call results. |
@@ -52,7 +53,7 @@ Protocol mechanics are intentionally kept in the [deep protocol guide](protocols
52
53
 
53
54
  ## Canonical member inventory
54
55
 
55
- The current JavaScript member total is derived mechanically from every `.mjs`
56
+ The current JavaScript member total is derived mechanically from every JavaScript
56
57
  entrypoint in `package.json#exports`. Records are grouped by export name and
57
58
  `Object.is()` binding identity, then retain the sorted entrypoints that expose
58
59
  that binding; `memberCount` in
@@ -259,6 +260,8 @@ browser map are cataloged separately in [Runtime modules](runtime-modules.md).
259
260
  | `resolveMailConfig()` | function | `arcane-os/mail` | Portable Mail | Node with explicit configuration, or browser/native WebView with optional document and location defaults |
260
261
  | `sendMailReport()` | function | `arcane-os/mail` | Portable Mail | Node and browser with Fetch and AbortController, or an explicit fetch implementation |
261
262
  | `serializeMailReport()` | function | `arcane-os/mail` | Portable Mail | Node and browser |
263
+ | `arcaneLogging` | singleton | `arcane-os/logging` | Shared logging | Node and browser |
264
+ | `readArcaneDeveloperMode()` | function | `arcane-os/logging` | Shared logging | Node and browser |
262
265
 
263
266
  # Packaging and release bundles
264
267
 
@@ -748,7 +751,7 @@ deterministic map. The package root also contains the public
748
751
  {
749
752
  schemaVersion: 1,
750
753
  kind: 'arcane-app-runtime-projection',
751
- sdkVersion: '0.5.12',
754
+ sdkVersion: '0.5.15',
752
755
  pathPrefix: 'arcane/',
753
756
  files: [{path}]
754
757
  }
@@ -1497,6 +1500,14 @@ specifier `arcane-os/speech-playback` works in Node package consumers and maps
1497
1500
  to the same runtime module in managed browsers. `arcane/SpeechPlayback` is the
1498
1501
  direct browser runtime name generated into the managed import map.
1499
1502
 
1503
+ When the supplied `speech` client has `fetchTTS` and reports a positive
1504
+ `providerRuntime.status('tts', {execution:true}).execution.maxConcurrentRequests`,
1505
+ `prepare()` submits every complete part immediately. The provider owns its
1506
+ bounded FIFO queue (browser Kokoro defaults to four), while Blob URLs and
1507
+ playback remain in exact input order. A native or custom client without that
1508
+ advertised capacity stays serialized with one lookahead. Replay keeps completed
1509
+ URLs and pending requests while retrying failed missing provider segments.
1510
+
1500
1511
  ### Signature and result
1501
1512
 
1502
1513
  ```text
@@ -1513,7 +1524,18 @@ runtime module; provider and media availability remain host-owned.
1513
1524
 
1514
1525
  ```javascript
1515
1526
  import SpeechPlayback from 'arcane-os/speech-playback';
1516
- const playback=new SpeechPlayback({audio,speech});
1527
+
1528
+ const audio=document.body.appendChild(document.createElement('audio'));
1529
+ const playback=new SpeechPlayback({audio,speech:globalThis.ai});
1530
+ const button=document.body.appendChild(document.createElement('button'));
1531
+ button.textContent='Speak';
1532
+ button.addEventListener('click',async function speakCompleteSegments(){
1533
+ await globalThis.ai.setSpeechMuted(false);
1534
+ await playback.prepare({
1535
+ parts:['First complete segment.','Second complete segment.'],
1536
+ autoplay:true
1537
+ });
1538
+ });
1517
1539
  ```
1518
1540
 
1519
1541
  ## SPEECH_PLAYBACK_STATE_EVENT
@@ -1543,7 +1565,9 @@ console.log(SPEECH_PLAYBACK_STATE_EVENT);
1543
1565
 
1544
1566
  ### Overview
1545
1567
 
1546
- Named binding for the same canonical class exposed as the speech-playback default. `prepare()` preserves each nonblank part's exact input string without trimming, splitting, or freezing that content.
1568
+ Named binding for the same capability-aware, exact-order canonical class exposed
1569
+ as the speech-playback default. `prepare()` preserves each nonblank part's exact
1570
+ input string without trimming, splitting, or freezing that content.
1547
1571
 
1548
1572
  ### Signature and result
1549
1573
 
@@ -1554,7 +1578,9 @@ new SpeechPlayback(options={})
1554
1578
  ### Availability and normalization
1555
1579
 
1556
1580
  **Node with injected media adapters, or browser/native WebView media.** Binding
1557
- identity equals the default export; provider and media availability remain host-owned.
1581
+ identity equals the default export. Provider-advertised capacity enables eager
1582
+ submission while that provider owns its bound; native and custom speech stays
1583
+ serialized, and media availability remains host-owned.
1558
1584
 
1559
1585
  ### Example
1560
1586
 
@@ -2667,7 +2693,7 @@ The import-map operation also reports the stable operation-specific strings
2667
2693
  `ARCANE_IMPORT_MAP_INVALID`, `ARCANE_IMPORT_MAP_UNRESOLVED`, and
2668
2694
  `ARCANE_IMPORT_MAP_COLLISION`; package assembly can additionally report
2669
2695
  `ARCANE_IMPORT_MAP_CLEANUP_FAILED`. They are normalized `ArcaneError.code`
2670
- values, but are not properties added to this general registry in SDK `0.5.12`.
2696
+ values, but are not properties added to this general registry in SDK `0.5.14`.
2671
2697
 
2672
2698
  ### Value and import
2673
2699
 
@@ -3437,7 +3463,7 @@ workspace it additionally returns the exact installed package authority:
3437
3463
  packageSource,
3438
3464
  canonicalPackageRoot,
3439
3465
  packageName: 'arcane-os',
3440
- packageVersion: '0.5.12',
3466
+ packageVersion: '0.5.15',
3441
3467
  runtimeRoot,
3442
3468
  browserRuntimeRoot
3443
3469
  }
@@ -3445,9 +3471,9 @@ workspace it additionally returns the exact installed package authority:
3445
3471
  ```
3446
3472
 
3447
3473
  The dependency can be named `arcane-os` or be one exact npm alias for
3448
- `npm:arcane-os@0.5.12`. The selected installation must still be one direct,
3474
+ `npm:arcane-os@0.5.15`. The selected installation must still be one direct,
3449
3475
  physical, non-link package directory whose manifest identifies exactly as
3450
- `arcane-os@0.5.12`; duplicate canonical/alias declarations reject.
3476
+ `arcane-os@0.5.15`; duplicate canonical/alias declarations reject.
3451
3477
  `allowMissingManagedImportMap` is an internal packaging/development seam. An
3452
3478
  ordinary caller should leave it `false`.
3453
3479
 
@@ -6728,6 +6754,89 @@ import {serializeMailReport} from 'arcane-os/mail';
6728
6754
  const body = serializeMailReport(report);
6729
6755
  ```
6730
6756
 
6757
+ # Shared logging
6758
+
6759
+ ## arcaneLogging
6760
+
6761
+ ### Overview
6762
+
6763
+ Shared console owner for Arcane runtime and application diagnostics. Available
6764
+ in SDK `0.5.14`, it reads the existing `user.developer` preference on every
6765
+ diagnostic emission after the shared user is ready. Enable developer mode in
6766
+ the application's profile settings. There is no separate verbosity setting.
6767
+ See [speech developer diagnostics](ai/browser-speech.md#developer-diagnostics)
6768
+ for API calls, generation queue state, and playback events.
6769
+
6770
+ ### Signature and result
6771
+
6772
+ ```text
6773
+ const arcaneLogging
6774
+ arcaneLogging.enabled
6775
+ arcaneLogging.log(...args)
6776
+ arcaneLogging.info(...args)
6777
+ arcaneLogging.debug(...args)
6778
+ arcaneLogging.warn(...args)
6779
+ arcaneLogging.error(...args)
6780
+ arcaneLogging.trace(...args)
6781
+ ```
6782
+
6783
+ `enabled` is a boolean getter for the current shared preference, not another
6784
+ setting. `log`, `info`, and `debug` forward to `console.info` when enabled, so
6785
+ diagnostics appear at the console's normal Info level. `warn`, `error`, and
6786
+ failure `trace` calls forward to their corresponding console methods in either
6787
+ mode. Each method returns `undefined`; a console failure does not change the
6788
+ operation being observed.
6789
+
6790
+ ### Availability and normalization
6791
+
6792
+ **Node and browser.** Imports reuse the same realm-local owner through
6793
+ `Symbol.for('arcane.logging')`, also exposed as `globalThis.arcaneLogging`.
6794
+ Arguments pass to the host console unchanged, including complete object
6795
+ references. The logger does not serialize content, retain diagnostic history,
6796
+ write storage, or send network requests. Diagnostics remain disabled while
6797
+ the shared user is not ready. The logger does not select a language or change
6798
+ speech generation and playback behavior.
6799
+
6800
+ ### Example
6801
+
6802
+ ```javascript
6803
+ import {arcaneLogging} from 'arcane-os/logging';
6804
+
6805
+ arcaneLogging.info('AI request', request);
6806
+ arcaneLogging.info('AI response', parsedResponse);
6807
+ ```
6808
+
6809
+ ## readArcaneDeveloperMode()
6810
+
6811
+ ### Overview
6812
+
6813
+ Reads the same developer-mode preference used by `arcaneLogging`, preserving
6814
+ the unloaded-user state without creating or changing a setting.
6815
+
6816
+ ### Signature and result
6817
+
6818
+ ```text
6819
+ readArcaneDeveloperMode(target=globalThis)
6820
+ ```
6821
+
6822
+ `target` supplies the shared `user`. The result is `null` until
6823
+ `target.user.ready === true`, then `true` only when
6824
+ `target.user.developer === true`; other loaded preference values return
6825
+ `false`. If preference access throws, the reader returns `false`.
6826
+
6827
+ ### Availability and normalization
6828
+
6829
+ **Node and browser.** Reads the supplied target synchronously. It performs no
6830
+ subscription, write, or logging, and does not cache the preference.
6831
+
6832
+ ### Example
6833
+
6834
+ ```javascript
6835
+ import {readArcaneDeveloperMode} from 'arcane-os/logging';
6836
+
6837
+ const developerMode=readArcaneDeveloperMode();
6838
+ ```
6839
+
6731
6840
  ## Data export subpaths
6732
6841
 
6733
6842
  The package also exposes eight JSON Schemas (including `arcane-os/schemas/event-stack.json`) and its package manifest. These are data contracts, not callable JavaScript members. See [schema contracts](../architecture.md) and the files under `schemas/`.