arcane-os 0.51.1 → 0.52.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.
@@ -2,7 +2,17 @@
2
2
 
3
3
  Every file shipped under `runtime/arcane/modules/` appears here. Start with the capability and example; expand into [protocol and host architecture](protocols.md) only when transport detail matters.
4
4
 
5
- Apps import renderer ESM from `/arcane/modules/<file>`. Classic scripts, the OPFS worker, uPlot stylesheet, and vendor license are called out explicitly. Importing a module does not grant a native capability.
5
+ Apps import renderer ESM with `arcane-os/modules/<file>`, including the `.js`
6
+ or `.mjs` extension. The SDK-managed import map resolves that name through the
7
+ application's selected runtime routes. Root applications use the installed
8
+ npm package directly by default. Absolute `/arcane/modules/<file>` examples
9
+ below describe an explicitly configured physical or virtual `/arcane` route;
10
+ that directory is not required by a direct npm layout.
11
+
12
+ Classic scripts, the OPFS worker, uPlot stylesheet, and vendor license use
13
+ their actual configured asset URLs and are called out separately. Importing a
14
+ module does not grant a native capability. See [installed-package browser
15
+ routes](protocols.md#installed-package-browser-routes) for route selection.
6
16
 
7
17
  Applications own response-detail preferences, their saved values, and any
8
18
  verbosity instruction appended to the system prompt. The former
@@ -94,6 +104,7 @@ own asynchronous work, cancellation, and backpressure.
94
104
  | [`LocalAIReadiness.js`](#localaireadinessjs) | esm | Derives selected AI requirements and returns a complete readiness/recovery report across browser, desktop, and Android modes. | Browser/native hybrid | Fully normalized report and stable error codes; browsers never probe Ollama. |
95
105
  | [`LocalAIReadinessController.js`](#localaireadinesscontrollerjs) | esm | Coordinates local-AI status component checks, ensured recovery, availability projection, and teardown. | Browser/native hybrid | Normalized controller state and change events. |
96
106
  | [`Mail.js`](#mailjs) | esm | Builds complete reports and prefers the native mail capability with an explicit HTTP transport fallback. | Browser/native hybrid + cloud | Mail inputs/results normalized; transport failures mixed. |
107
+ | [`MailApi.mjs`](#mailapimjs) | esm | Public renderer entrypoint for Mail, durable outbox, and HTTP transport APIs. | Browser/native renderer | Re-exports preserve their owning module's contracts. |
97
108
  | [`MailOutbox.mjs`](#mailoutboxmjs) | esm | Persists complete mail reports before delivery and normalizes idempotent enqueue, retry, reconciliation, and invalid-record maintenance. | Browser/native WebView or compatible injected host | Complete records, full work, cancellation, and lifecycle states normalized; storage, lock, and delivery failures coded. |
98
109
  | [`MailTransport.mjs`](#mailtransportmjs) | esm | Sends one complete mail report to a normalized HTTP(S) endpoint. | Browser/server with fetch + cloud | Normalized endpoint and transport errors; remote detail preserved. |
99
110
  | [`MarkdownMedia.js`](#markdownmediajs) | esm | Saves local Markdown images separately, decodes complete stored records, and resolves stable references in rendered views. | Browser / supported native WebView | Complete image records, concurrent display reads, cancellation, and print-owned URL lifetime. |
@@ -184,6 +195,14 @@ payload; an omitted value remains absent. The provider owns interpretation.
184
195
  This option does not switch a loaded browser-WASM model or its lifecycle:
185
196
  explicit provider/model selection and activation remain necessary there.
186
197
 
198
+ Both object-form methods also forward an optional request-local `temperature`
199
+ unchanged to built-in TWiN Cloud, including through its provider-runtime
200
+ adapter. Explicit `0` is preserved; omission or `undefined` leaves the outbound
201
+ field absent and preserves the provider default. The value is not clamped or
202
+ saved as a preference, concurrent calls remain independent, and retries reuse
203
+ the same value. This adds no output limit or native Ollama option mapping;
204
+ other registered providers retain their existing interpretation of the option.
205
+
187
206
  Built-in cloud chat decodes an HTTP error body once as JSON or text and rejects
188
207
  with that complete value unchanged. It does not reconstruct an Error, replace
189
208
  the message, or add `providerMessage`, `status`, or an SDK failure code to the
@@ -2485,7 +2504,11 @@ Defines the same-origin `<html-import>` loader with open shadow root, inline scr
2485
2504
 
2486
2505
  ### Public surface
2487
2506
 
2488
- default `HTMLImport`; registers `html-import`; `connectedCallback()` and `ready`.
2507
+ Default export: the constructor registered for `html-import`. When no
2508
+ constructor is registered, the module registers its SDK loader, whose
2509
+ `connectedCallback()` owns fragment loading and whose `ready` property reports
2510
+ completion. The browser invokes the connection callback when the host enters
2511
+ the document.
2489
2512
 
2490
2513
  Registration occurs once per custom-element registry. Imports through different
2491
2514
  module URLs reuse and export the registered constructor, including overlapping
@@ -2648,6 +2671,40 @@ import * as module from '/arcane/modules/Mail.js';
2648
2671
  console.log(Object.keys(module));
2649
2672
  ```
2650
2673
 
2674
+ ## MailApi.mjs
2675
+
2676
+ ### Overview
2677
+
2678
+ The managed-browser `arcane-os/mail` entrypoint re-exports the existing
2679
+ [`Mail.js`](#mailjs), [`MailOutbox.mjs`](#mailoutboxmjs), and
2680
+ [`MailTransport.mjs`](#mailtransportmjs) APIs. Their configuration, storage,
2681
+ delivery, errors, and lifecycle remain owned by those modules.
2682
+
2683
+ ### Public surface
2684
+
2685
+ Exact exports: `default`, `Mail`, `resolveMailConfig`,
2686
+ `MAIL_OUTBOX_IDEMPOTENCY_WINDOW_MS`, `MAIL_OUTBOX_PROTOCOL`,
2687
+ `MAIL_OUTBOX_STATES`, `MAIL_OUTBOX_TABLE`, `MailOutbox`, `createMailOutbox`,
2688
+ `MailTransportError`, `normalizeMailEndpoint`, `sendMailReport`, and
2689
+ `serializeMailReport`.
2690
+
2691
+ `default` and `Mail` refer to the same renderer Mail class. Import retains
2692
+ `Mail.js`'s browser singleton installation; it creates no additional queue or
2693
+ transport. Node resolves `arcane-os/mail` through the separate
2694
+ [Node mail entrypoint](mail.md).
2695
+
2696
+ ### Example
2697
+
2698
+ ```javascript
2699
+ import {resolveMailConfig} from 'arcane-os/mail';
2700
+
2701
+ const mailConfig = resolveMailConfig(
2702
+ {appName:'dragon-dispatch', endpoint:'https://mail.example.com/v1/mail'},
2703
+ {document:null, location:new URL('https://dispatch.example.com/')}
2704
+ );
2705
+ console.log(mailConfig.endpoint);
2706
+ ```
2707
+
2651
2708
  ## MailOutbox.mjs
2652
2709
 
2653
2710
  ### Overview
@@ -4,7 +4,9 @@ The npm package exposes a Node.js ESM control plane, the portable
4
4
  `arcane-os/event-manager`, `arcane-os/logging`, `arcane-os/mail`,
5
5
  `arcane-os/preference-store`, `arcane-os/speech-playback`,
6
6
  `arcane-os/speech-text`, `arcane-os/ai/tool-text-stream`, `arcane-os/ai/twin-cloud`, and `arcane-os/browser-device` entrypoints, and the browser-only
7
- `arcane-os/pwa`, `arcane-os/ai/browser-wasm` and `arcane-os/ai/browser-speech` entrypoints.
7
+ `arcane-os/pwa` and `arcane-os/ai/browser-wasm` entrypoints. The
8
+ `arcane-os/ai/browser-speech` entrypoint includes local and native browser
9
+ providers plus a cloud TTS adapter usable in Node with Fetch and Blob.
8
10
  The `arcane-os/modules/<filename>` and `arcane-os/entities/<filename>` paths
9
11
  resolve directly to the existing runtime files, with their actual extension.
10
12
  They are public Node package exports and managed browser keys, without a wrapper.
@@ -17,14 +19,20 @@ browser names such as `arcane/AIProviderRuntime`, `arcane/AIRuntimeState`, and
17
19
  direct-installed root maps use the package namespace instead. Applications call `globalThis.Arcane` for capability-gated host
18
20
  behavior.
19
21
 
20
- This page is the canonical inventory for every JavaScript name reachable through `package.json#exports`. The same binding can appear at the root and a focused subpath; those entrypoints are listed together. The root workspace `discoverApps` and the low-level packager `discoverApps` are intentionally separate records because they are different functions.
22
+ This page documents the focused package APIs. The same binding can appear at
23
+ the root and a focused subpath; those entrypoints are listed together. Direct
24
+ runtime-module aliases and filename patterns expose the complete namespaces in
25
+ the [runtime module](runtime-modules.md) and [entity](runtime-entities.md)
26
+ catalogs. The root workspace `discoverApps` and low-level packager
27
+ `discoverApps` are separate functions with separate records.
21
28
 
22
29
  ## Import map
23
30
 
24
31
  This table is the Node `package.json#exports` map: it defines package
25
32
  entrypoints for SDK/tooling code. It is distinct from the generated browser
26
- import map that resolves application-facing `arcane/*` modules and the focused
27
- EventManager entry. See [browser runtime delivery](protocols.md#browser-runtime-delivery)
33
+ import map that resolves application-facing `arcane-os/*` names for root/direct
34
+ layouts and `arcane/*` compatibility names for physical/nested layouts.
35
+ See [browser runtime delivery](protocols.md#browser-runtime-delivery)
28
36
  for the shared browser destinations used by installed-package and physical
29
37
  runtime layouts.
30
38
 
@@ -66,8 +74,8 @@ runtime layouts.
66
74
  | `arcane-os/pwa` | Nonblocking PWA registration, worker updates, native installation state and a dismissible installation component. |
67
75
  | `arcane-os/ai/browser-wasm` | Caller-selected browser-local Wllama inference, complete DBOPFS model storage, streaming, cancellation, and structural tool-call results. |
68
76
  | `arcane-os/ai/tool-text-stream` | Shared selected tool-argument text observer for provider integration. |
69
- | `arcane-os/ai/twin-cloud` | Complete TWiN Cloud requests from Node or a browser with an explicit key/model and shared retry/cancellation behavior. |
70
- | `arcane-os/ai/browser-speech` | Caller-selected browser-local Whisper STT and Kokoro TTS, explicit TWiN Cloud remote TTS, ordinary upstream assets, role lifecycle, and cancellation. |
77
+ | `arcane-os/ai/twin-cloud` | Stateless chat, System One state/questions and image generation with explicit key/model, complete results and operation-specific retry/cancellation. |
78
+ | `arcane-os/ai/browser-speech` | Caller-selected Whisper/Kokoro, native browser recognition/synthesis, cloud TTS, upstream assets, role lifecycle and cancellation. |
71
79
  | `arcane-os/mail` | Portable Mail runtime, durable outbox, complete transport responses, and provider-neutral acceptance contracts. |
72
80
 
73
81
  These lowercase runtime-module entrypoints expose their existing exports; they
@@ -86,7 +94,10 @@ Eight JSON schemas and `package.json` are data-only export subpaths. In Node ESM
86
94
 
87
95
  ### Managed AI narration
88
96
 
89
- Applications import `AI` through `arcane/AI` in the managed browser map.
97
+ Root applications import `AI` through `arcane-os/ai` in the managed browser map.
98
+ `ai.prepareTTSPlayback(payload,signal)` silently prepares real Blob audio or a
99
+ native speech descriptor for playback. Native browser voices expose no audio
100
+ file; use this path or shared streaming/SpeechPlayback for native output.
90
101
  `ai.prepareTTS({parts,storage,identity,signal,onState})` prepares complete
91
102
  punctuation segments without playing them and optionally saves/reuses their
92
103
  audio through application-owned DBOPFS. Its immediate handle exposes ordered
@@ -111,19 +122,18 @@ Protocol mechanics are intentionally kept in the [deep protocol guide](protocols
111
122
 
112
123
  ## Canonical member inventory
113
124
 
114
- The current JavaScript member total is derived mechanically from every JavaScript
115
- entrypoint in `package.json#exports`. Records are grouped by export name and
116
- `Object.is()` binding identity, then retain the sorted entrypoints that expose
117
- that binding; `memberCount` in
118
- [`inventory/package-api.json`](inventory/package-api.json) is the resulting
119
- graph-node count. The remaining data-only subpaths are eight JSON Schemas and
120
- package metadata. Runtime projection modules in the managed
121
- browser map are cataloged separately in [Runtime modules](runtime-modules.md).
125
+ `memberCount` in [`inventory/package-api.json`](inventory/package-api.json)
126
+ counts the authored focused API records below. Shared bindings retain their
127
+ entrypoints together. Runtime aliases and filename patterns are documented in
128
+ [Runtime modules](runtime-modules.md) and [Runtime entities](runtime-entities.md).
129
+ The remaining data-only subpaths are eight JSON Schemas and package metadata.
122
130
 
123
131
  | Member | Kind | Import | Group | Availability |
124
132
  | --- | --- | --- | --- | --- |
125
133
  | `fetchRequest()` | function | `arcane-os/ai/twin-cloud` | TWiN Cloud requests | Node and Browser; remote HTTPS provider |
126
134
  | `fetchSystemOneRequest()` | function | `arcane-os/ai/twin-cloud` | TWiN Cloud state-and-questions requests | Node and Browser; remote HTTPS provider |
135
+ | `generateImages()` | function | `arcane-os/ai/twin-cloud` | TWiN Cloud image generation | Node and Browser with Fetch and Blob; remote HTTPS provider |
136
+ | `createBrowserSpeechSynthesisProvider()` | function | `arcane-os/ai/browser-speech` | Native browser speech | Browser with speechSynthesis and SpeechSynthesisUtterance |
127
137
  | `fetchHTTPResponse()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
128
138
  | `fetchJSONResponse()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
129
139
  | `structuredOutputFormat()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
@@ -769,12 +779,22 @@ async inspectApp({workspaceRoot, appId, signal}={})
769
779
  ```
770
780
 
771
781
  Import it from `arcane-os` or `arcane-os/packager`. The result includes the
772
- configured `entry`, `include`, and `exclude` values plus `browserDocuments`, the
773
- entry-first ordered `.html`/`.htm` paths selected by the same package traversal
774
- used by import-map refresh and packaging. Current pages declare exactly one
775
- matching `meta[name="arcane-app-id"]`; unmarked pages with an active `base`
776
- remain selected for patch compatibility. Included HTML with neither signal is
777
- retained as a package fragment rather than rewritten as a document.
782
+ configured `entry`, `include`, and `exclude` values, the optional `documents`
783
+ declaration when authored, and `browserDocuments`, the entry-first ordered
784
+ `.html`/`.htm` paths shared by import-map refresh, development and packaging.
785
+ `package.documents` in an authored descriptor, or `documents` in a schema-1
786
+ package, selects literal app-root-relative paths already included and not
787
+ excluded. Other selected paths follow the entry in deterministic lexical order
788
+ without duplicates. The authored `documents` declaration remains as supplied,
789
+ including `[]`, which selects only the entry. Omitting the property retains
790
+ automatic discovery of the entry and included secondary pages with an active `<base>`. App identity
791
+ meta tags do not select documents.
792
+
793
+ Selected pages retain their existing base requirements. Explicit selection
794
+ leaves other included HTML documents unchanged, including iframe-referenced
795
+ originals, while preserving package, serving and offline resource membership.
796
+ Component processing and shared runtime-resource traversal retain their existing
797
+ behavior. See [application document selection](protocols.md#application-document-selection).
778
798
 
779
799
  `entry` and each app browser document's `path` stay relative to the app
780
800
  directory. Each browser document also reports `packagePath`, the emitted path
@@ -855,12 +875,14 @@ selected input, or required control paths fail before output writes. Source
855
875
  layout, app identity, OPFS scope, and internal package paths remain unchanged.
856
876
  See [app-selected package output](protocols.md#app-selected-package-output).
857
877
 
858
- Selected app files are emitted beneath `apps/<id>/`; shared files retain their
859
- configured route destinations. When selected shared content supplies no root
860
- `index.html`, the SDK generates one that opens the selected app page. The result
878
+ Root app files retain their paths at the output root; explicitly nested apps
879
+ retain their `apps/<id>/` paths. Shared files retain their configured route
880
+ destinations. When the selected content supplies no root `index.html`, the SDK
881
+ generates one that opens the selected app page. The result
861
882
  contains `outputRoot`, `manifest`, and the complete `files` inventory.
862
883
  `manifest.app.entry` stays app-relative, while `manifest.app.start`
863
- is the package launch URL, such as `./apps/hello-world/index.html`. Release
884
+ is the package launch URL, such as `./index.html` for a root app or
885
+ `./apps/hello-world/index.html` for a nested app. Release
864
886
  schema `1`, kind `arcane-app-release`, and packager identity
865
887
  `arcane-app-packager-v1` remain unchanged. A dry run returns the planned output
866
888
  and file inventory without writing source or output.
@@ -1260,7 +1282,7 @@ Import it from `arcane-os`.
1260
1282
  | `documentRoot` | Required filesystem directory containing the selected documents. Returned root paths are absolute. |
1261
1283
  | `runtimeRoot` | Existing materialized runtime directory containing `modules/`, `entities/`, `sdk/`, and its other selected content. Defaults to `arcane/` under `documentRoot`. Pass an absolute path when selecting another directory; relative root arguments resolve from the current working directory. |
1262
1284
  | `documents` | Required nonempty array of document-root-relative file paths, such as `['shell/home.html', 'settings.html']`. Use forward slashes and normalized paths without a leading `./` or parent traversal. Duplicate paths are processed once, in first-selected order. |
1263
- | `version` | Version used in generated import-map targets and URL compatibility keys. Defaults to the installed SDK's `SDK_VERSION`; `null` selects unversioned map URLs. Authored resource URLs outside the managed map stay unchanged. |
1285
+ | `version` | Retained argument with default `SDK_VERSION`; generated local URLs stay clean and retired `arcaneVersion` fields are removed regardless of this value. Other authored query values and fragments remain unchanged. |
1264
1286
  | `deploymentUrl` | Optional absolute directory URL ending in `/` that corresponds to `documentRoot`, such as `https://example.com/control/`. Required when a selected document has an absolute or root-relative base URL, or a relative base that traverses above `documentRoot`. |
1265
1287
  | `signal` | Optional `AbortSignal`, observed during inventory, document preparation, and before each write. |
1266
1288
  | `onEvent` | Optional named callback receiving the ordered events below. An asynchronous callback is awaited before the operation continues. |
@@ -1292,7 +1314,8 @@ The first `<base>` with an `href` determines each document's effective base.
1292
1314
  A target-only base, such as `<base target="_blank">`, does not change URL
1293
1315
  resolution. With no base, `shell/home.html` resolves the default runtime through
1294
1316
  `../arcane/`. With `<base href="../">`, the same page resolves it through
1295
- `./arcane/`. Generated URLs include the selected version when one is supplied.
1317
+ `./arcane/`. Generated local URLs stay clean regardless of the retained
1318
+ `version` argument.
1296
1319
 
1297
1320
  The host serves the runtime at the same relative location as `runtimeRoot`
1298
1321
  has to `documentRoot`. `deploymentUrl` supplies that directory's public URL
@@ -1783,14 +1806,16 @@ const schema=preferenceSchema([]);
1783
1806
 
1784
1807
  Default binding for the canonical SpeechPlayback runtime class. The static
1785
1808
  specifier `arcane-os/speech-playback` works in Node package consumers and maps
1786
- to the same runtime module in managed browsers. `arcane/SpeechPlayback` is the
1787
- direct browser runtime name generated into the managed import map.
1809
+ to the same runtime module in managed browsers. Physical/nested maps also
1810
+ retain the `arcane/SpeechPlayback` compatibility name.
1788
1811
 
1789
- When the supplied `speech` client has `fetchTTS` and reports a positive
1812
+ When the supplied `speech` client has `prepareTTSPlayback` or `fetchTTS` and reports a positive
1790
1813
  `providerRuntime.status('tts', {execution:true}).execution.maxConcurrentRequests`,
1791
1814
  `prepare()` submits every complete part immediately. The provider owns its
1792
- bounded FIFO queue (browser Kokoro defaults to four), while Blob URLs and
1793
- playback remain in exact input order. A native or custom client without that
1815
+ bounded FIFO queue (browser Kokoro defaults to four), while Blob audio or native
1816
+ playback descriptors remain in exact input order. Preparation prefers
1817
+ `prepareTTSPlayback` when available. Native playback owns pause, resume, stop
1818
+ and release without creating an audio-file URL. A native or custom client without that
1794
1819
  advertised capacity stays serialized with one lookahead. Replay keeps completed
1795
1820
  URLs and pending requests while retrying failed missing provider segments.
1796
1821
  The optional constructor `onState(detail)` callback runs synchronously after
@@ -2096,6 +2121,11 @@ async function useprojectNativeDescriptor(...arguments_) {
2096
2121
 
2097
2122
  Projects a schema-2 descriptor into the compatible schema-1 application package contract.
2098
2123
 
2124
+ Optional `package.documents` becomes top-level `documents`. Omission stays
2125
+ omitted and an authored empty list stays `[]`, so projection preserves automatic
2126
+ discovery versus entry-only selection. See
2127
+ [application document selection](protocols.md#application-document-selection).
2128
+
2099
2129
  ### Signature and result
2100
2130
 
2101
2131
  ```text
@@ -4183,7 +4213,7 @@ const toolchain = createToolchain({
4183
4213
 
4184
4214
  // Only this explicit call refreshes the managed map and selected HTML documents.
4185
4215
  const result = await toolchain.importMap();
4186
- console.log(result.importMap.entryCount); // derived from installed inventories
4216
+ console.log(Object.keys(result.importMap.imports).length);
4187
4217
  console.log(result.importMap.documentPaths, result.importMap.documentCount);
4188
4218
  ```
4189
4219
 
@@ -4262,13 +4292,15 @@ async function usedevelopApplication(...arguments_) {
4262
4292
 
4263
4293
  Dispatches one named headless SDK operation with normalized acceptance, events, cancellation, and failure.
4264
4294
 
4265
- The exact command `'import-map'` dispatches one app-scoped refresh
4266
- across every `.html`/`.htm` file selected by the descriptor's existing
4267
- include/exclude rules and returns `{workspaceRoot, workspaceMode, appId,
4295
+ The exact command `'import-map'` dispatches one app-scoped refresh across the
4296
+ `.html`/`.htm` documents selected by
4297
+ [`package.documents` or automatic discovery](protocols.md#application-document-selection), and returns
4298
+ `{workspaceRoot, workspaceMode, appId,
4268
4299
  importMap}`. The `importMap` value reports the generated imports and complete
4269
4300
  ordered `documentPaths`. This route mutates the map artifact and selected managed HTML
4270
- documents as one atomic refresh and has no
4271
- supported dry-run.
4301
+ documents through sequential writes and has no supported dry-run or
4302
+ all-file transaction. An error or cancellation can leave completed writes in
4303
+ place; rerun the operation after resolving the cause.
4272
4304
 
4273
4305
  The exact command `'upgrade'` dispatches `upgradeApplication(options)`. It is
4274
4306
  external-workspace-only and runs that application's ordinary `npm upgrade`
@@ -4303,7 +4335,7 @@ const result = await executeOperation('import-map', {
4303
4335
  workspaceRoot:process.cwd(),
4304
4336
  appId:'hello-world'
4305
4337
  });
4306
- console.log(result.importMap.committed, result.importMap.entryCount);
4338
+ console.log(result.importMap.committed, Object.keys(result.importMap.imports).length);
4307
4339
  console.log(result.importMap.documentPaths, result.importMap.documentCount);
4308
4340
  ```
4309
4341
 
@@ -4315,8 +4347,9 @@ Runs the high-level package operation for one selected application. It reads
4315
4347
  the installed SDK/runtime selection and packages the saved source and managed
4316
4348
  import maps through `packageApp()`. Map generation remains the explicit
4317
4349
  `arcane import-map` operation and the ordinary `arcane dev` startup refresh.
4318
- Selected app files retain their `apps/<id>/` paths alongside the shared routes
4319
- and root launcher described by `packageApp()`.
4350
+ Root app files retain their paths at the output root, while explicitly nested
4351
+ apps retain `apps/<id>/` paths alongside the shared routes and any root launcher
4352
+ described by `packageApp()`.
4320
4353
 
4321
4354
  The same low-level operation resolves the app's optional `outputDirectory`;
4322
4355
  there is no separate high-level destination override. `release.outputRoot`
@@ -6123,11 +6156,14 @@ console.log(stack.sessionId, stack.events.length);
6123
6156
 
6124
6157
  Mutable metadata for the browser-only runtime behind
6125
6158
  `arcane-os/ai/browser-wasm`. It records protocol
6126
- `arcane-ai-browser-wasm/2`, `@wllama/wllama` `3.6.0`, the embedded llama.cpp
6127
- revision, the exact packaged JavaScript and WebAssembly assets, retained MIT
6128
- licenses, and the disabled compatibility-runtime/remote-model-helper policy.
6129
- Its execution policy requires WebGPU, proves full model offload, and declares
6130
- `cpuFallback:false`. It contains no model weights or default model catalog.
6159
+ `arcane-ai-browser-wasm/2`, `@wllama/wllama` `3.6.0`, the packaged JavaScript
6160
+ and WebAssembly asset locations, MIT license identifiers for Wllama and
6161
+ llama.cpp, and the disabled compatibility-runtime/remote-model-helper policy.
6162
+ Its execution policy declares `webgpuRequired:false`,
6163
+ `defaultGpuLayers:99999`, `cpuGpuLayers:0`, and `cpuFallback:false`. The default
6164
+ requests full GPU offload; `gpuLayers:0` explicitly selects CPU. A failed GPU
6165
+ load never silently switches to CPU. The metadata contains no model weights
6166
+ or default model catalog and does not establish that a model has loaded.
6131
6167
 
6132
6168
  ### Value and import
6133
6169
 
@@ -6237,7 +6273,7 @@ applies the supplied `loadPolicy`.
6237
6273
  `Promise<PersistentAIChatSession>`, and binds its AI API to this exact
6238
6274
  controller. Applications continue to use this public controller method rather
6239
6275
  than importing that private specifier. `options` must be a plain object and cannot contain
6240
- `chat`. The resulting session preserves coherent complete live context while
6276
+ `ai` or `chat`. The resulting session preserves coherent complete live context while
6241
6277
  letting each user/assistant/tool turn choose matching durable ChatEntity/DBOPFS
6242
6278
  persistence. A `persist:false` turn participates in one request and response,
6243
6279
  then retains neither side in subsequent model context, the transcript, durable
@@ -6649,7 +6685,7 @@ Direct `load()` selects a catalog model and returns `{model,status}`; the
6649
6685
  public AI API module's `ai.load()` returns the flat controller status. Load settings include
6650
6686
  offline mode, `AbortSignal`, progress, threads, and context/batch/micro-batch
6651
6687
  tokens. `loadDefaults:{gpuLayers:0}` or `load({gpuLayers:0})` explicitly selects
6652
- CPU. Omission retains full GPU offload (`gpuLayers:99999`); GPU failures never
6688
+ CPU. Omission requests full GPU offload (`gpuLayers:99999`); GPU failures never
6653
6689
  silently switch to CPU.
6654
6690
 
6655
6691
  Chat supports OpenAI-like message/generation fields, tools, tool choice,
@@ -6670,18 +6706,20 @@ turn.
6670
6706
 
6671
6707
  ### Availability and normalization
6672
6708
 
6673
- **Browser context with WebAssembly and OPFS/DBOPFS.** The default GPU route
6709
+ **Browser secure context with WebAssembly and OPFS/DBOPFS.** The default GPU route
6674
6710
  also requires WebGPU; explicit `gpuLayers:0` CPU loading skips GPU requirements
6675
6711
  and adapter work. A load succeeds after Wllama confirms the complete model is
6676
- loaded. There is no automatic CPU fallback.
6712
+ loaded and its context was created. There is no automatic CPU fallback.
6677
6713
  Cross-origin isolation and coarse hardware fields remain observations rather
6678
6714
  than hard gates. Ordinary status reports complete catalog compatibility and
6679
- lifecycle state. GPU adapter selection is instrumented as
6715
+ lifecycle state. `capabilities()` reports `executionDevice:'cpu'|'webgpu'` and
6716
+ `webgpuRequired` for the active load plan. GPU adapter selection is instrumented as
6680
6717
  `arcane.ai.browser-wasm.webgpu.adapter.selected`.
6681
6718
  Cancellation normalizes to `ARCANE_AI_REQUEST_ABORTED`; load or availability failures
6682
6719
  surface stable `ARCANE_AI_*` codes such as `ARCANE_AI_WEBGPU_REQUIRED`,
6683
6720
  `ARCANE_AI_MODEL_FULL_OFFLOAD_UNPROVEN`, and
6684
- `ARCANE_AI_MODEL_GPU_MEMORY_INSUFFICIENT`. Concurrent runtime inference can fail
6721
+ `ARCANE_AI_MODEL_GPU_MEMORY_INSUFFICIENT` on the GPU route, or
6722
+ `ARCANE_AI_MODEL_CPU_MEMORY_INSUFFICIENT` on the CPU route. Concurrent runtime inference can fail
6685
6723
  `ARCANE_AI_RUNTIME_BUSY`; inspection and status can report
6686
6724
  `ARCANE_AI_PROVIDER_UNAVAILABLE` or fallback `ARCANE_AI_RUNTIME_FAILED` without
6687
6725
  misrepresenting those observations as a successful load.
@@ -6783,8 +6821,8 @@ async function openCachedModel() {
6783
6821
  ### Overview
6784
6822
 
6785
6823
  Projects one compatible v1 browser-WASM provider into the provider-neutral
6786
- LLM role consumed by the managed `arcane/AIProviderRuntime` projection. The
6787
- runtime checks the v1 protocol, required identity/methods, and local-only
6824
+ LLM role consumed by `arcane-os/ai-provider-runtime`. The
6825
+ runtime checks protocol `arcane-ai-adapter/1`, required identity/methods, and local-only
6788
6826
  capability; it does not establish ownership for an arbitrary compatible
6789
6827
  object. The adapter does not
6790
6828
  change the wrapped provider, download a model, create a fallback, or execute a
@@ -6825,7 +6863,7 @@ or CPU fallback behavior.
6825
6863
 
6826
6864
  ```javascript
6827
6865
  import {adaptV1LlmProvider} from 'arcane-os/ai/browser-wasm';
6828
- import {getAIProviderRuntime} from 'arcane/AIProviderRuntime';
6866
+ import {getAIProviderRuntime} from 'arcane-os/ai-provider-runtime';
6829
6867
 
6830
6868
  const runtime = getAIProviderRuntime();
6831
6869
  const releaseProvider = runtime.register(adaptV1LlmProvider(provider));
@@ -7249,6 +7287,72 @@ async function selectNativeRecognition(ai, signal) {
7249
7287
  }
7250
7288
  ```
7251
7289
 
7290
+ ## createBrowserSpeechSynthesisProvider()
7291
+
7292
+ ### Overview
7293
+
7294
+ Creates a provider/2 TTS adapter for native `speechSynthesis`. Construction,
7295
+ voice discovery and preparation are silent. Applications choose when to play
7296
+ and retain ownership of voice preferences. Browser voices may use remote
7297
+ services, so the provider declares `localOnly:false`.
7298
+
7299
+ ### Signature and result
7300
+
7301
+ ```text
7302
+ createBrowserSpeechSynthesisProvider({id,model,language}={})
7303
+ ```
7304
+
7305
+ Supply `id` and `model:{id,name?,defaultVoice?}`; optional `language` is a
7306
+ browser language tag. The provider exposes ordinary `catalog`, `inspect`,
7307
+ `status`, `load`, `request`, `unload` and `dispose` methods, plus:
7308
+
7309
+ - `catalog()` returns the selected model with `speech:{playback:'native'}`
7310
+ and actual `voices` records `{id,name,lang,default,localService}`. Voice `id`
7311
+ is the browser's exact `voiceURI`.
7312
+ - `subscribeCatalog(callback)` immediately delivers the current catalog and
7313
+ observes `voiceschanged`; its returned function removes that subscription.
7314
+ - `setDefaultVoice(voiceURI|null)` synchronously changes the default for future
7315
+ preparations and returns the selected value. An empty string selects `null`.
7316
+ Repeating a value is silent; changing it publishes the catalog. Explicit
7317
+ choices and prepared, queued or active speech keep their captured voice.
7318
+ - `prepare({input,model?,voice?,language?,speed?},{signal?})` returns a
7319
+ `{kind:'native-speech',input,voice,language,speed,play}` descriptor. Preparation
7320
+ preserves complete text and starts no speech. `play({signal,onState})`
7321
+ returns an owned handle with `finished`, `released`, `pause()`, `resume()`
7322
+ and `stop()`, plus observable state and errors.
7323
+
7324
+ `AI.prepareTTSPlayback(payload,signal)` returns this native descriptor or real
7325
+ Blob audio from a speech request. Streaming TTS and `SpeechPlayback` consume
7326
+ those prepared results. Audio-file methods `fetchTTS` and durable `prepareTTS`
7327
+ require real audio and report `ARCANE_AI_TTS_AUDIO_EXPORT_UNAVAILABLE` for native output.
7328
+ Unload and disposal cancel owned playback and wait for native release.
7329
+
7330
+ ### Availability, errors and example
7331
+
7332
+ The actual browser must provide synthesis, utterance and voice-event APIs.
7333
+ No SDK model, Worker, Core or DBOPFS is required. Missing native synthesis
7334
+ reports `ARCANE_AI_SPEECH_SYNTHESIS_UNAVAILABLE`; an unavailable selected voice
7335
+ reports `ARCANE_AI_SPEECH_VOICE_UNAVAILABLE`. Activation and playback remain
7336
+ subject to browser behavior. A resolved playback operation describes its
7337
+ observed native lifecycle, not proof that a person heard it.
7338
+
7339
+ ```javascript
7340
+ import {createBrowserSpeechSynthesisProvider} from 'arcane-os/ai/browser-speech';
7341
+
7342
+ // Call from the application's speech-selection action. This stays silent.
7343
+ async function selectNativeVoice(ai) {
7344
+ const provider = createBrowserSpeechSynthesisProvider({
7345
+ id: 'browser-voice',
7346
+ model: {id: 'browser-voice'}
7347
+ });
7348
+ await ai.configureSpeechProvider('tts', provider, {modelId: 'browser-voice'});
7349
+ return provider;
7350
+ }
7351
+ ```
7352
+
7353
+ See [native speech and voice selection](ai/browser-speech.md) for live catalogs,
7354
+ explicit playback, cancellation and language handling.
7355
+
7252
7356
  ## createTwinCloudTTSProvider()
7253
7357
 
7254
7358
  ### Overview
@@ -7291,21 +7395,22 @@ instead of clamping. Returned media is fetched without the inference key.
7291
7395
  Cancelling a credential wait leaves the application's shared refresh alone
7292
7396
  and prevents a late result from starting this cancelled operation.
7293
7397
 
7294
- The SDK sends each initial synthesis POST immediately after credential readiness,
7295
- outside the follow-up queue. One queue handles only status/result GETs and the
7296
- final audio download. Its defaults are four in-flight follow-ups and 250 ms
7297
- between dispatch starts, with each slot held through complete JSON, Blob, or
7298
- error-body consumption. Each job awaits its response and body before enqueueing
7299
- its next incomplete-status check; there is no per-job polling delay.
7300
-
7301
- A readable `Retry-After` postpones only the affected job's next eligibility.
7302
- Other jobs and initial submissions remain independent. One readable HTTP 429
7303
- retry is allowed per submission or status read; POST retries retain a one-second minimum, and
7304
- follow-up retries use the configured queue cadence plus any longer readable
7305
- `Retry-After`. An accepted job's failed status Fetch may retry once after a
7306
- network failure, not after a JSON parsing failure. Repeated failures surface
7307
- complete developer diagnostics without cancelling sibling jobs. An ambiguous
7308
- paid POST network failure is never automatically replayed.
7398
+ The whole-job queue holds each slot through credential readiness, submission,
7399
+ remote completion and the complete audio response. Excess jobs wait in FIFO
7400
+ order; cancellation removes waiting work before submission. A separate queue
7401
+ owns initial POST attempts and eligible retries. Follow-up status/result GETs
7402
+ and audio downloads retain independent configurable capacity and cadence,
7403
+ defaulting to four requests and 250 ms between starts. Slots remain held
7404
+ through complete response-body consumption.
7405
+
7406
+ Readable HTTP 429 responses set a provider-wide cooldown observed by submissions
7407
+ and follow-ups. One readable rate-limit retry is allowed per submission or
7408
+ status read, respecting its applicable minimum delay and longer `Retry-After`.
7409
+ An accepted job's failed status Fetch may retry once after a network failure.
7410
+ Ambiguous POST network, JSON or error-body failures are surfaced without
7411
+ replaying a potentially accepted paid job. A failed job leaves sibling jobs
7412
+ intact. See the [cloud speech queue contract](ai/browser-speech.md#twin-cloud-text-to-speech)
7413
+ for full scheduling, retry and cancellation behavior.
7309
7414
 
7310
7415
  Each provider/2 `tts/synthesize` request returns one complete audio Blob.
7311
7416
  Request cancellation, unload, and disposal stop local polling/downloads and
@@ -7354,7 +7459,7 @@ Accepts the same options and returns the same provider as
7354
7459
  ### Availability and normalization
7355
7460
 
7356
7461
  The alias shares the canonical factory's Browser and Node requirements,
7357
- immediate submission, queued follow-ups, cancellation, and result contract.
7462
+ whole-job and submission queues, queued follow-ups, cancellation and result contract.
7358
7463
  Existing caller imports, stored provider IDs, and credentials remain valid;
7359
7464
  renaming a caller's import requires no saved-data migration.
7360
7465
 
@@ -7377,6 +7482,12 @@ Creates a local-only Kokoro text-to-speech provider for the provider-neutral AI
7377
7482
  runtime. It owns one independent, bounded Worker/session pool and never selects
7378
7483
  a cloud, native, or LLM fallback.
7379
7484
 
7485
+ An ordinary `model.voices` array supplies optional display metadata for the
7486
+ application's voice selector. `catalog()` retains each complete record without
7487
+ loading or fetching a model. This metadata neither restricts synthesis voice
7488
+ values nor proves playback availability. Artifact-graph voice paths remain a
7489
+ separate asset-routing contract.
7490
+
7380
7491
  ### Signature and result
7381
7492
 
7382
7493
  ```text
@@ -7912,11 +8023,15 @@ it reads no browser preference or default-model selection. Optional
7912
8023
  A supplied JSON Schema sends `response_format:{type:'json_schema',
7913
8024
  json_schema:{name:'structured_response',strict:true,schema:...}}`. Omission
7914
8025
  leaves structured output off. Optional `tools`, `toolChoice`,
7915
- `parallelToolCalls`, and `reasoningEffort` map to their existing TWiN wire
8026
+ `parallelToolCalls`, `reasoningEffort`, and `temperature` map to their existing TWiN wire
7916
8027
  fields. Tool fields are sent when `tools` is nonempty; a nonempty
7917
8028
  `reasoningEffort` is forwarded without selecting a default. No default output
7918
8029
  cap, tool execution, or provider-response envelope validation is added.
7919
8030
 
8031
+ `temperature` is forwarded unchanged when supplied, including `0`. Omission or
8032
+ `undefined` leaves it out of the request, preserving the provider's default.
8033
+ The SDK adds no clamp or saved preference, and retries retain the same value.
8034
+
7920
8035
  The return value is the entire parsed provider JSON, not only one choice or
7921
8036
  message. Optional callbacks are `onRequest(request,id,metadata)` before
7922
8037
  dispatch and `onResponse(response,id,false)` before successful return;
@@ -8013,6 +8128,66 @@ application. The JEV identifier is an explicit caller choice, not a default.
8013
8128
  See [TWiN Cloud](ai/twin-cloud.md#evaluate-caller-owned-state-with-system-one)
8014
8129
  for the complete transport and callback contract.
8015
8130
 
8131
+ ## generateImages()
8132
+
8133
+ ### Overview
8134
+
8135
+ Generates images through TWiN Cloud with a caller-selected model and complete
8136
+ prompt. Returns every image as a Blob in provider order. The application owns
8137
+ display, filenames, storage, credentials and model choice.
8138
+
8139
+ ### Signature and result
8140
+
8141
+ ```text
8142
+ async generateImages({model,prompt,parameters={},twinKey,getApiKey,signal=null,id=Date.now(),onRequest,onResponse,onProgress}={})
8143
+ ```
8144
+
8145
+ Supported models are `fal-ai/flux/schnell` through async invocation and
8146
+ `stable-diffusion-3.5-large` through image generation. `prompt` is a string;
8147
+ `parameters` carries the selected provider's additional fields. Supply the
8148
+ prompt through its named argument, and the model through `model`. An explicit
8149
+ `twinKey` takes precedence over `getApiKey()`; the latter may return a promise.
8150
+
8151
+ The result is `{images:[{blob,mediaType,width?,height?},...]}`. Media metadata is
8152
+ retained when the provider supplies it. `onRequest(request,id,metadata)` and
8153
+ `onResponse(result,id,false)` receive complete diagnostic records;
8154
+ `onProgress({stage,model,id,requestId?})` reports credentials, requesting,
8155
+ queued, generating, downloading and complete stages as applicable. Keep these
8156
+ diagnostics outside durable conversation history.
8157
+
8158
+ The operation submits once. Async jobs are polled using their returned request
8159
+ ID; a readable `Retry-After` controls the wait. Ambiguous submission failures
8160
+ are surfaced without automatic resubmission. Cancellation covers credentials,
8161
+ observers, requests, response bodies and media downloads; it cannot promise
8162
+ that an accepted remote job was cancelled. Media downloads omit the inference
8163
+ credential. The SDK writes no image or conversation records.
8164
+
8165
+ ### Availability, errors and example
8166
+
8167
+ Node or browser with Fetch, Blob and AbortController; browser requests also
8168
+ depend on endpoint CORS. Missing credentials report `AI_PROVIDER_NOT_CONFIGURED`,
8169
+ unsupported models `ARCANE_AI_IMAGE_MODEL_UNSUPPORTED`, malformed returned
8170
+ media `ARCANE_AI_INVALID_PROVIDER_RESULT`, and cancellation
8171
+ `ARCANE_AI_REQUEST_ABORTED`. HTTP/provider failures preserve their returned
8172
+ detail. Call only from the application's explicit generation action:
8173
+
8174
+ ```javascript
8175
+ import {generateImages} from 'arcane-os/ai/twin-cloud';
8176
+
8177
+ async function drawLunarGarden(twinKey, signal) {
8178
+ return generateImages({
8179
+ twinKey,
8180
+ model: 'fal-ai/flux/schnell',
8181
+ prompt: 'A moon gardener watering a single enormous radish.',
8182
+ signal
8183
+ });
8184
+ }
8185
+ ```
8186
+
8187
+ See [image generation](ai/twin-cloud.md#generate-images-with-an-application-selected-model)
8188
+ and [MarkdownMedia](runtime-modules.md#markdownmediajs) for application-owned
8189
+ image storage and document references.
8190
+
8016
8191
  ## fetchHTTPResponse()
8017
8192
 
8018
8193
  ### Overview