arcane-os 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +8 -8
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +5 -5
- package/browser-runtime/ai/browser-speech-providers.mjs +1 -0
- package/docs/architecture.md +2 -2
- package/docs/reference/README.md +79 -13
- package/docs/reference/ai/browser-speech.md +336 -0
- package/docs/reference/ai/browser-wasm.md +207 -82
- package/docs/reference/availability-and-normalization.md +33 -4
- package/docs/reference/behavioral-testing.md +4 -1
- package/docs/reference/cli.md +29 -10
- package/docs/reference/core/arcane-ai-contracts.md +43 -9
- package/docs/reference/inventory/package-api.json +110 -14
- package/docs/reference/inventory/runtime-components.json +42 -14
- package/docs/reference/inventory/runtime-modules.json +118 -13
- package/docs/reference/protocols.md +264 -38
- package/docs/reference/runtime-components.md +177 -21
- package/docs/reference/runtime-modules.md +449 -13
- package/docs/reference/sdk-api.md +626 -85
- package/package.json +1 -1
- package/runtime/ARCANE_RUNTIME_RELEASE.json +19 -19
- package/runtime/arcane/components/chat.html +17 -52
- package/runtime/arcane/components/speech.html +109 -29
- package/runtime/arcane/components/voice-transcription.html +437 -68
- package/runtime/arcane/modules/AI.js +556 -128
- package/runtime/arcane/modules/AIProviderRuntime.js +299 -30
- package/runtime/arcane/modules/AIRuntimeState.js +23 -4
- package/runtime/arcane/modules/ComponentContracts.js +272 -0
- package/runtime/arcane/modules/LocalAIReadinessController.js +1 -1
- package/schemas/arcane-lock.schema.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.3
|
|
4
|
+
|
|
5
|
+
- Made shared voice transcription consume authoritative sticky STT state,
|
|
6
|
+
expose explicit selected-unloaded activation, and keep recording disabled
|
|
7
|
+
until the selected route is genuinely ready and non-busy.
|
|
8
|
+
- Added owned cancellation and current-operation guards across microphone
|
|
9
|
+
permission, recording, transcription, save, completion, transcript
|
|
10
|
+
replacement, synchronous public events, teardown, and stale settlement.
|
|
11
|
+
- Centralized the shared STT activation control in
|
|
12
|
+
`createSTTActivationController()` without automatic downloads, hidden
|
|
13
|
+
provider selection, or application policy.
|
|
14
|
+
|
|
15
|
+
## 0.2.2
|
|
16
|
+
|
|
17
|
+
- Corrected latest-request-wins ownership so each newly admitted AI request
|
|
18
|
+
aborts and settles the prior provider operation, revalidates role readiness,
|
|
19
|
+
and prevents stale results from restoring superseded state.
|
|
20
|
+
- Made speech startup and controls explicitly lifecycle-owned: STT startup is
|
|
21
|
+
opt-in, selected-unloaded STT exposes user activation and cancellation,
|
|
22
|
+
caller abort reaches shared transcription, and TTS mute/unmute owns its load,
|
|
23
|
+
cancellation, playback, and unload sequence.
|
|
24
|
+
- Kept positive speech readiness bound to admitted sticky provider state while
|
|
25
|
+
exposing truthful capability-only legacy OpenAI, Ollama, and Core speech
|
|
26
|
+
routes without downloads, hidden provider selection, model authority, or
|
|
27
|
+
fallback.
|
|
28
|
+
- Preserved the existing shared Blob/File STT and WAV TTS request shapes at the
|
|
29
|
+
browser-provider boundary, with explicit decode/format errors and
|
|
30
|
+
provider/model-owned TTS voice defaults.
|
|
31
|
+
|
|
3
32
|
## 0.2.1
|
|
4
33
|
|
|
5
34
|
- Added explicit selected-unloaded chat activation, truthful legacy Cloud/Core
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
|
|
|
19
19
|
`arcane/` runtime. Both profiles preserve the same app URLs, theme, packaging,
|
|
20
20
|
event, cancellation, and browser run contracts.
|
|
21
21
|
|
|
22
|
-
This checkout defines the `0.2.
|
|
22
|
+
This checkout defines the `0.2.3` SDK contract. Applications pin one exact npm
|
|
23
23
|
version and lockfile; registry state is deliberately not baked into immutable
|
|
24
24
|
application artifacts.
|
|
25
25
|
|
|
@@ -132,7 +132,7 @@ uses the same controller for automatic memory extraction.
|
|
|
132
132
|
Create a new repository-shaped Arcane application with the exact stable SDK:
|
|
133
133
|
|
|
134
134
|
```bash
|
|
135
|
-
npx arcane-os@0.2.
|
|
135
|
+
npx arcane-os@0.2.3 new my-app --path ./my-app --target portable --git
|
|
136
136
|
cd my-app
|
|
137
137
|
npm install
|
|
138
138
|
npm run check
|
|
@@ -143,7 +143,7 @@ To enroll an existing repository, install the exact SDK and initialize only
|
|
|
143
143
|
missing Arcane files:
|
|
144
144
|
|
|
145
145
|
```bash
|
|
146
|
-
npm install --save-dev --save-exact arcane-os@0.2.
|
|
146
|
+
npm install --save-dev --save-exact arcane-os@0.2.3
|
|
147
147
|
npm exec -- arcane init my-app --target portable
|
|
148
148
|
```
|
|
149
149
|
|
|
@@ -159,7 +159,7 @@ npm exec -- arcane-os targets
|
|
|
159
159
|
No global SDK install or standalone Arcane CLI is required. The application
|
|
160
160
|
repository's exact npm dependency and lockfile own the CLI and toolchain version.
|
|
161
161
|
|
|
162
|
-
Use `npx arcane-os@0.2.
|
|
162
|
+
Use `npx arcane-os@0.2.3` for the initial bootstrap because it names this npm
|
|
163
163
|
package explicitly; bare `npx arcane` outside an installed project could resolve
|
|
164
164
|
a different package. Both installed commands invoke the same headless toolchain.
|
|
165
165
|
Project-local npm scripts use the SDK pinned by that app's `package-lock.json`,
|
|
@@ -180,7 +180,7 @@ node ./bin/arcane.mjs new local-app --path ../local-app --target portable --git
|
|
|
180
180
|
|
|
181
181
|
# From the generated app repository
|
|
182
182
|
cd ../local-app
|
|
183
|
-
npm install --save-dev --save-exact ../arcane-os-sdk/arcane-os-0.2.
|
|
183
|
+
npm install --save-dev --save-exact ../arcane-os-sdk/arcane-os-0.2.3.tgz
|
|
184
184
|
npm run check
|
|
185
185
|
npm ci
|
|
186
186
|
```
|
|
@@ -191,7 +191,7 @@ still verifies the installed package name and exact version, the locked runtime
|
|
|
191
191
|
identity, and the runtime bytes. Local directory `file:` dependencies are not
|
|
192
192
|
accepted because npm may install them as links; use a packed `.tgz`. A GitHub
|
|
193
193
|
runner also needs that tarball at the locked path. After publication, replace
|
|
194
|
-
the local declaration with the exact `arcane-os@0.2.
|
|
194
|
+
the local declaration with the exact `arcane-os@0.2.3` registry package and
|
|
195
195
|
commit the regenerated lock.
|
|
196
196
|
|
|
197
197
|
Generated repositories use `npm ci --ignore-scripts` in CI. Run dependency
|
|
@@ -304,7 +304,7 @@ recorded length through a final identity check; an appended byte, concurrent
|
|
|
304
304
|
growth, path replacement, or hard link fails closed. NFC paths use defined
|
|
305
305
|
UTF-8 byte ordering, covered by one pinned golden bundle digest on every
|
|
306
306
|
supported Node/runner combination. This SDK accepts only the explicitly listed
|
|
307
|
-
`0.2.
|
|
307
|
+
`0.2.3` bundle generation; structural validity does not imply cross-SDK
|
|
308
308
|
compatibility, and a release with zero payload bytes cannot be created. Portable
|
|
309
309
|
path validation rejects file/directory prefix conflicts, case-colliding prefix
|
|
310
310
|
spellings, and Windows device aliases including superscript COM/LPT digits.
|
|
@@ -350,7 +350,7 @@ package installation, or assertions.
|
|
|
350
350
|
|
|
351
351
|
## Current target support
|
|
352
352
|
|
|
353
|
-
Version `0.2.
|
|
353
|
+
Version `0.2.3` exposes one browser target and five explicitly paired
|
|
354
354
|
native development targets: a verified non-runnable portable directory, a
|
|
355
355
|
Windows x64 unsigned-local-test EXE bundle, Linux x64 and Linux ARM64
|
|
356
356
|
unsigned-local-test DEBs, and an Android development-signed APK. The
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"builder": "arcane-sdk-browser-runtime-v1",
|
|
4
|
-
"sdkVersion": "0.2.
|
|
4
|
+
"sdkVersion": "0.2.3",
|
|
5
5
|
"source": {
|
|
6
6
|
"authority": "arcane-os-sdk",
|
|
7
7
|
"repository": "https://github.com/TheWizardNexus/arcane-os-sdk.git",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
]
|
|
30
30
|
},
|
|
31
31
|
"fileCount": 25,
|
|
32
|
-
"totalBytes":
|
|
33
|
-
"contentSha256": "
|
|
32
|
+
"totalBytes": 9280047,
|
|
33
|
+
"contentSha256": "3c82ed11b24c7b7b91b62f6dc52e0b1dcd444112a29cd48413eedc008380eb61",
|
|
34
34
|
"files": [
|
|
35
35
|
{
|
|
36
36
|
"path": "ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"path": "ai/browser-speech-providers.mjs",
|
|
58
58
|
"sourcePath": "browser-runtime/ai/browser-speech-providers.mjs",
|
|
59
59
|
"provenance": "sdk-source-identity",
|
|
60
|
-
"bytes":
|
|
61
|
-
"sha256": "
|
|
60
|
+
"bytes": 26055,
|
|
61
|
+
"sha256": "6a2c0caa227d78028f42434b86231236055f0cfe0e3d6b71a4f651f7005a2614"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"path": "ai/browser-speech.mjs",
|
|
@@ -449,6 +449,7 @@ function createBrowserSpeechProvider({
|
|
|
449
449
|
providerId,
|
|
450
450
|
role,
|
|
451
451
|
localOnly: true,
|
|
452
|
+
...(role === "tts" ? { defaultVoice: authority.defaultVoice } : {}),
|
|
452
453
|
repository: authority.repository,
|
|
453
454
|
revision: authority.revision,
|
|
454
455
|
runtime: authority.runtime,
|
package/docs/architecture.md
CHANGED
|
@@ -200,7 +200,7 @@ length with an EOF growth probe, and rechecked by handle and pathname identity.
|
|
|
200
200
|
Every cumulative path prefix has one case-folded spelling and one file/directory
|
|
201
201
|
kind; prefix topology conflicts and the complete portable Windows device-name
|
|
202
202
|
set fail before creation or admission.
|
|
203
|
-
The current SDK admits only the explicitly compatible `0.2.
|
|
203
|
+
The current SDK admits only the explicitly compatible `0.2.3` bundle
|
|
204
204
|
generation and rejects zero-byte payload releases.
|
|
205
205
|
|
|
206
206
|
Promotion retains any prior output as an identity-bound backup until the new
|
|
@@ -320,7 +320,7 @@ through SDK-bound verified readers rather than accepting a mutable source path
|
|
|
320
320
|
as authority. Build completion requires provider verification, and later
|
|
321
321
|
verify/run calls receive the exact artifact receipt.
|
|
322
322
|
|
|
323
|
-
The SDK `0.2.
|
|
323
|
+
The SDK `0.2.3` runtime requires Arcane `0.8.12` or newer. Compatibility
|
|
324
324
|
is contractual rather than exact-version pinning: the prepared Core must meet
|
|
325
325
|
the highest minimum declared by the runtime, selected app, and bundled app
|
|
326
326
|
dependencies; keep each app's Arcane protocol generation; and provide every
|
package/docs/reference/README.md
CHANGED
|
@@ -26,25 +26,27 @@ high-level page links to the relevant deep section instead of repeating it.
|
|
|
26
26
|
| Load a reusable HTML component | [Runtime component catalog](runtime-components.md) |
|
|
27
27
|
| Call `globalThis.Arcane` | [Arcane Core API](core/arcane-api.md) |
|
|
28
28
|
| Subscribe to native events | [Arcane event reference](core/arcane-events.md) |
|
|
29
|
-
| Use provider-neutral AI | [
|
|
29
|
+
| Use provider-neutral AI lifecycle, chat, speech, persistence, or document context | [Normalized AI](#normalized-ai) |
|
|
30
30
|
| Run a caller-authenticated local LLM in the browser | [Browser-WASM local AI](ai/browser-wasm.md) |
|
|
31
|
+
| Run caller-authenticated Whisper or Kokoro in the browser | [Browser speech providers](ai/browser-speech.md) |
|
|
31
32
|
| Use Arcane Ollama | [Arcane Ollama guide](arcane-ollama.md) |
|
|
32
33
|
| Understand transports and protocol switching | [Protocol and host architecture](protocols.md) |
|
|
33
34
|
| Run contract and behavior tests | [Behavioral testing](behavioral-testing.md) |
|
|
34
35
|
|
|
35
36
|
## Version scope and provenance
|
|
36
37
|
|
|
37
|
-
This repository contains
|
|
38
|
+
This repository contains explicitly versioned surfaces with different owners:
|
|
38
39
|
|
|
39
40
|
| Surface | Source identity | Meaning |
|
|
40
41
|
| --- | --- | --- |
|
|
41
|
-
| SDK and CLI | `arcane-os` `0.
|
|
42
|
-
| Browser runtime |
|
|
42
|
+
| SDK and CLI | `arcane-os` `0.2.3` | The Node.js toolchain plus the browser-only `arcane-os/ai/browser-wasm` and `arcane-os/ai/browser-speech` entrypoints in this checkout. |
|
|
43
|
+
| Browser runtime | SDK source commit `f97ac4f2e7cc92a00a3a466c38a67446dd112acf`, SDK `0.2.3`, protocol `arcane/1` | The SDK-canonical exact 160-file runtime shipped under `runtime/`; Arcane OS commit `c540014afe69f14cf5ae60493b7295f36dbcec64` is legacy projection provenance, not a second source authority. |
|
|
44
|
+
| Browser SDK runtime | SDK source commit `f97ac4f2e7cc92a00a3a466c38a67446dd112acf`, SDK `0.2.3` | The exact 25-file authenticated browser closure: EventManager/DOM instrumentation and pinned event dependencies, Wllama runtime assets, and SDK browser speech provider/store/Worker mechanisms. It contains no model weights or speech adapter/model bytes. |
|
|
43
45
|
| Core reference snapshot | Arcane OS commit `567ad110bf57a1c2d4a3daa22ae93716cc5f4d7e`, protocol `arcane/1` | The application-facing Core contract derived into `docs/reference/core/`. Canonical inventory and focused-member content was verified unchanged at Arcane OS `main` commit `13f3ce0ae34f77a3495331c8b4c30b1bb105f8ed`; SDK-local provenance, link, and package-boundary annotations are added explicitly. |
|
|
44
46
|
|
|
45
|
-
The runtime receipt and Core reference
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
The SDK runtime receipt and Core reference are distinct evidence and have
|
|
48
|
+
different current authorities. A browser module's bytes come from the SDK
|
|
49
|
+
runtime receipt. A native build selects one
|
|
48
50
|
explicit Arcane OS checkout and Core. This SDK version accepts that selection
|
|
49
51
|
only after its current native plan checks the exact declared protocol, version,
|
|
50
52
|
features, capabilities, methods, provider contract, and identity-bound
|
|
@@ -56,6 +58,32 @@ See [Core reference provenance](core/README.md) for the imported inventory and
|
|
|
56
58
|
the exact distinction between a documentation snapshot and shipped runtime
|
|
57
59
|
bytes.
|
|
58
60
|
|
|
61
|
+
## Published 0.2.2
|
|
62
|
+
|
|
63
|
+
The published package is exactly `arcane-os@0.2.2` from source commit
|
|
64
|
+
`d5326d206bf0bec6ad82d53605e666841aa79899`. The npm `latest` dist-tag resolves
|
|
65
|
+
to `0.2.2`; the separate `dev` dist-tag remains `0.1.0-dev.5`.
|
|
66
|
+
|
|
67
|
+
The admission-aware `voice-transcription.html` lifecycle and shared
|
|
68
|
+
`createSTTActivationController()` contract documented below are newer canonical
|
|
69
|
+
source. They are not package authority in `0.2.2`; consumers require a fresh
|
|
70
|
+
numeric publication before relying on them.
|
|
71
|
+
|
|
72
|
+
| Evidence | Exact value |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| npm integrity | `sha512-JnLzZ4+FqX9tMgRv8HMcaCPSFx3xNNRf8BF8T03fD2ymg2g8cIGZRdD/3Tbd9PLtpx1PIKCpxz6nCP6ztnu1Nw==` |
|
|
75
|
+
| npm shasum | `0b0d314acce48dcb5518470cd45a54221589d4d4` |
|
|
76
|
+
| Immutable release tarball | `arcane-os-0.2.2.manifest.json`; artifact `9631659213`; 6,993,999 bytes; SHA-256 `e0fe1a556b603f67f5e3c142be7154b433312d3c0f3b58632df2e7fc43cc0ca7` |
|
|
77
|
+
| GitHub release | [`0.2.2`](https://github.com/TheWizardNexus/arcane-os-sdk/releases/tag/0.2.2) (tag and title are both exactly `0.2.2`) |
|
|
78
|
+
| Hosted source/artifact gate | [Check run 33034955277](https://github.com/TheWizardNexus/arcane-os-sdk/actions/runs/33034955277) |
|
|
79
|
+
| Trusted publication | [Run 33035086265](https://github.com/TheWizardNexus/arcane-os-sdk/actions/runs/33035086265) |
|
|
80
|
+
|
|
81
|
+
The npm SLSA provenance binds the published package to that exact source commit
|
|
82
|
+
and `.github/workflows/publish-dev.yml`. Hashes prove byte identity or
|
|
83
|
+
consistency; provenance establishes the recorded source/workflow relationship.
|
|
84
|
+
Neither claim alone proves browser hardware support, native admission, or a
|
|
85
|
+
particular application's provider/model policy.
|
|
86
|
+
|
|
59
87
|
## MDN-style page contract
|
|
60
88
|
|
|
61
89
|
Public reference entries follow the established Arcane documentation model:
|
|
@@ -74,11 +102,12 @@ Public reference entries follow the established Arcane documentation model:
|
|
|
74
102
|
|
|
75
103
|
## Public runtime inventory
|
|
76
104
|
|
|
77
|
-
The package exposes
|
|
105
|
+
The package exposes 169 semantic JavaScript records across 13 JavaScript
|
|
78
106
|
entrypoints, plus eight JSON Schemas, its exact runtime manifest, and package
|
|
79
107
|
metadata. Ten entrypoints are Node.js control-plane surfaces,
|
|
80
108
|
`arcane-os/event-manager` runs in Node and browsers, and
|
|
81
|
-
`arcane-os/ai/browser-wasm`
|
|
109
|
+
`arcane-os/ai/browser-wasm` plus `arcane-os/ai/browser-speech` are browser-only.
|
|
110
|
+
The [machine-readable package
|
|
82
111
|
inventory](inventory/package-api.json) and [SDK member reference](sdk-api.md)
|
|
83
112
|
are checked bidirectionally against every declared JavaScript export.
|
|
84
113
|
|
|
@@ -87,7 +116,7 @@ download, install, or self-update.
|
|
|
87
116
|
|
|
88
117
|
The synchronized browser payload exposes:
|
|
89
118
|
|
|
90
|
-
-
|
|
119
|
+
- 83 JavaScript module artifacts under `runtime/arcane/modules/`, including
|
|
91
120
|
ESM modules, classic vendor globals, one worker protocol, and one Node-oriented
|
|
92
121
|
mail transport;
|
|
93
122
|
- 15 shared entity modules under `runtime/arcane/entities/`;
|
|
@@ -100,6 +129,43 @@ vendor support files that are not ESM imports. The runtime manifest remains the
|
|
|
100
129
|
byte-level source of truth; the catalogs explain what those bytes let a
|
|
101
130
|
developer do.
|
|
102
131
|
|
|
132
|
+
## Normalized AI
|
|
133
|
+
|
|
134
|
+
Portable applications start with the provider-neutral runtime rather than an
|
|
135
|
+
Ollama, Wllama, Whisper, Kokoro, native, or cloud transport:
|
|
136
|
+
|
|
137
|
+
| Need | Public surface | Availability |
|
|
138
|
+
| --- | --- | --- |
|
|
139
|
+
| Select, load, unload, inspect, cancel, and use LLM/STT/TTS independently | [`AIProviderRuntime.js`](runtime-modules.md#aiproviderruntimejs) | Cross-host controller; each registered provider declares its own host requirements. |
|
|
140
|
+
| Observe sticky role state and startup settlement | [`AIRuntimeState.js`](runtime-modules.md#airuntimestatejs) | Cross-host EventTarget state; observation grants no authority. |
|
|
141
|
+
| Offer explicit selected-model start/cancel UI | [`chat.html`](runtime-components.md#chathtml), [`speech.html`](runtime-components.md#speechhtml), and [`voice-transcription.html`](runtime-components.md#voice-transcriptionhtml) | Browser/native WebView components; user activation emits a cancelable request before any LLM or STT load intent, and recording stays disabled without sticky ready STT. |
|
|
142
|
+
| Use Core-normalized chat | [`globalThis.Arcane.ai`](core/arcane-ai-contracts.md) | Native/Core only when separately admitted. |
|
|
143
|
+
| Run a caller-selected GGUF LLM locally | [`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) | Browser secure context with WebGPU/full-offload evidence, WebAssembly, and OPFS/DBOPFS. |
|
|
144
|
+
| Run caller-selected Whisper/Kokoro locally | [`arcane-os/ai/browser-speech`](ai/browser-speech.md) | Browser with DBOPFS, Web Locks, Workers, and caller-supplied immutable runtime/model bytes. |
|
|
145
|
+
| Add bounded persistent history and memory | [`PersistentAIChatSession.js`](runtime-modules.md#persistentaichatsessionjs) | Browser/native WebView runtime with ChatEntity/DBOPFS and a configured chat function. |
|
|
146
|
+
| Add explicit document search/context | [`DBOPFSDocumentLibrary.js`](runtime-modules.md#dbopfsdocumentlibraryjs) | Existing DBOPFS-style adapter; search occurs only after the app calls it or deliberately wires its context builder into chat. |
|
|
147
|
+
|
|
148
|
+
There is no automatic local-to-cloud, browser-to-Core, provider-to-provider, or
|
|
149
|
+
storage fallback. Tool calls remain structural data until application-owned
|
|
150
|
+
policy and code decide whether to execute them. App prompts, model defaults,
|
|
151
|
+
profiles, tools, business policy, and private data remain app-owned.
|
|
152
|
+
|
|
153
|
+
An explicitly selected but unloaded model is not “ready.” `chat.html` keeps
|
|
154
|
+
Send disabled and exposes a visible keyboard-operable LLM Start/Try again or
|
|
155
|
+
Cancel loading control. `speech.html` and `voice-transcription.html` keep their
|
|
156
|
+
recording operations unavailable and share the equivalent Start
|
|
157
|
+
transcription/Try again/Cancel loading control for STT. Applications can
|
|
158
|
+
override `requestAIActivation(intent)` or `requestSTTActivation(intent)`, or
|
|
159
|
+
cancel the corresponding activation-request event. Imports and state
|
|
160
|
+
observation emit no lifecycle intent, and default
|
|
161
|
+
`startTranscription=false` does not request an STT startup load or begin an
|
|
162
|
+
automatic model download. It does not unload a role started independently.
|
|
163
|
+
Compatibility availability never creates ready STT/TTS state without an
|
|
164
|
+
admitted, loaded provider. Shared STT cancel/destroy propagates an owned signal,
|
|
165
|
+
and TTS Mute/Unmute updates the shared lifecycle owner. The selected TTS
|
|
166
|
+
provider/model catalog owns its default voice; a saved OpenAI voice is not
|
|
167
|
+
forwarded to another provider route.
|
|
168
|
+
|
|
103
169
|
## Authority and feature detection
|
|
104
170
|
|
|
105
171
|
The presence of a JavaScript function is not permission to use it. Native
|
|
@@ -113,9 +179,9 @@ as package admission. Each method rechecks native policy at invocation time.
|
|
|
113
179
|
|
|
114
180
|
## Source, receipts, and licensing
|
|
115
181
|
|
|
116
|
-
- [
|
|
117
|
-
- [
|
|
118
|
-
- [
|
|
182
|
+
- [Exact SDK runtime release manifest](../../runtime/ARCANE_RUNTIME_RELEASE.json)
|
|
183
|
+
- [SDK runtime authority record](../../tools/runtime-source.json)
|
|
184
|
+
- [Exact browser AI runtime receipt](../../browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json)
|
|
119
185
|
- [AGPL license](../../LICENSE)
|
|
120
186
|
- [Commercial-license notice](../../COMMERCIAL-LICENSE.md)
|
|
121
187
|
- [Third-party and distribution notice](../../NOTICE)
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Browser speech providers
|
|
2
|
+
|
|
3
|
+
`arcane-os/ai/browser-speech` is the shipped browser-only provider package for
|
|
4
|
+
caller-supplied Whisper speech-to-text and Kokoro text-to-speech runtimes. It
|
|
5
|
+
implements the same provider-neutral role contract used by
|
|
6
|
+
`AIProviderRuntime.js`; it does not ship model weights, runtime adapter bytes,
|
|
7
|
+
voices, download URLs, a catalog, or a cloud fallback.
|
|
8
|
+
|
|
9
|
+
Use this page when an application deliberately owns browser-local speech model
|
|
10
|
+
and runtime selection. For ordinary application AI lifecycle and status, start
|
|
11
|
+
with the [normalized AI guide](../README.md#normalized-ai) and
|
|
12
|
+
[`AIProviderRuntime.js`](../runtime-modules.md#aiproviderruntimejs).
|
|
13
|
+
|
|
14
|
+
## Availability
|
|
15
|
+
|
|
16
|
+
| Host | Availability | Notes |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| Browser | Shipped | Requires DBOPFS/OPFS, Web Locks, Workers, Fetch or an injected fetch function, Blob/File, and object URLs. |
|
|
19
|
+
| Native WebView | Conditional | Works only when the WebView exposes the same browser APIs and the application admits every artifact. This does not invoke Core speech. |
|
|
20
|
+
| Node | Importable, execution unavailable | The ESM subpath is exported, but `0.2.2` publishes no Node speech storage, Worker, audio-decoder, or execution adapter. |
|
|
21
|
+
| Cloud | Not provided | A cloud speech provider can implement `arcane-ai-provider/2`, but this package never selects one. |
|
|
22
|
+
|
|
23
|
+
Browser speech is independent from `arcane-os/ai/browser-wasm`: the Wllama
|
|
24
|
+
entrypoint owns the LLM role, while this entrypoint owns optional STT and TTS
|
|
25
|
+
providers. Each role loads, unloads, reports status, cancels, and recovers
|
|
26
|
+
independently.
|
|
27
|
+
|
|
28
|
+
## Import
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import {
|
|
32
|
+
BROWSER_SPEECH_ARTIFACT_PROTOCOL,
|
|
33
|
+
createBrowserKokoroProvider,
|
|
34
|
+
createBrowserSpeechAuthority,
|
|
35
|
+
createBrowserWhisperProvider,
|
|
36
|
+
createDbopfsSpeechArtifactStore
|
|
37
|
+
} from 'arcane-os/ai/browser-speech';
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The entrypoint exports exactly those five names. Importing it downloads no
|
|
41
|
+
model and starts no Worker.
|
|
42
|
+
|
|
43
|
+
## `BROWSER_SPEECH_ARTIFACT_PROTOCOL`
|
|
44
|
+
|
|
45
|
+
The constant is exactly `"arcane-ai-browser-speech-artifacts/1"`. It identifies
|
|
46
|
+
an SDK-created artifact store; it is not model authority, a capability grant,
|
|
47
|
+
or evidence that a cache is complete.
|
|
48
|
+
|
|
49
|
+
## `createBrowserSpeechAuthority()`
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
createBrowserSpeechAuthority({
|
|
53
|
+
providerId,
|
|
54
|
+
role,
|
|
55
|
+
model,
|
|
56
|
+
runtime,
|
|
57
|
+
security
|
|
58
|
+
} = {})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Validates and freezes one caller-owned model/runtime declaration. Construction
|
|
62
|
+
binds the declared identities and descriptor rules; actual downloaded or cached
|
|
63
|
+
runtime-graph closure is validated by `store.prepare()` before a Worker starts.
|
|
64
|
+
|
|
65
|
+
### Authority input
|
|
66
|
+
|
|
67
|
+
| Field | Contract |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| `providerId` | Trimmed 1–128 character provider identity. |
|
|
70
|
+
| `role` | Exactly `"stt"` or `"tts"`. |
|
|
71
|
+
| `model.id` | Caller-owned model identity. |
|
|
72
|
+
| `model.repository` | Immutable logical repository identity; the SDK does not resolve it. |
|
|
73
|
+
| `model.revision` | Caller-pinned revision. Every model URL must contain this revision or its supplied SHA-256. |
|
|
74
|
+
| `model.files` | Nonempty unique `{path,url,bytes?,sha256?,mediaType?}[]`. Paths are normalized relative paths; URLs are immutable HTTPS or same-origin URLs without credentials/fragments. |
|
|
75
|
+
| `model.defaultVoice` | Required only for TTS. |
|
|
76
|
+
| `runtime.adapter` | Exactly `"transformers-whisper"` for STT or `"kokoro-js"` for TTS. |
|
|
77
|
+
| `runtime.version` / `runtime.revision` | Caller-pinned runtime identity. |
|
|
78
|
+
| `runtime.entry` | Path of one JavaScript module in `runtime.files`. |
|
|
79
|
+
| `runtime.files` | Nonempty immutable runtime closure. The entry module must be self-contained: undeclared imports, re-exports, executable strings, alternate transports, and child workers are rejected. |
|
|
80
|
+
| `security` | Closed `{secure?,checks?:{byteLength?,sha256?}}` artifact policy. Disabled checks are disclosed rather than silently claimed. |
|
|
81
|
+
|
|
82
|
+
The result is a frozen `arcane-ai-model-authority/1` record. The SDK owns the
|
|
83
|
+
validation rules; the application owns every model/runtime choice, license,
|
|
84
|
+
revision, URL, hash, voice, and business policy.
|
|
85
|
+
|
|
86
|
+
Provider security resolves each field independently in this order: SDK default,
|
|
87
|
+
`appSecurity`, provider `security`, then `load({security})`. The SDK default is
|
|
88
|
+
`secure:false`. After resolution, each omitted check defaults to the effective
|
|
89
|
+
`secure` value; an explicit `checks.byteLength` or `checks.sha256` boolean
|
|
90
|
+
overrides that default. An enabled check requires the corresponding `bytes` or
|
|
91
|
+
`sha256` field on every admitted artifact and fails closed when evidence is
|
|
92
|
+
missing or mismatched. A disabled check never becomes a claim that bytes were
|
|
93
|
+
verified. Direct `store.prepare()` has only its supplied security scope above
|
|
94
|
+
the SDK default because it is not bound to a provider.
|
|
95
|
+
|
|
96
|
+
## `createDbopfsSpeechArtifactStore()`
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
createDbopfsSpeechArtifactStore({
|
|
100
|
+
dbopfs,
|
|
101
|
+
tableName = 'arcane_ai_browser_speech',
|
|
102
|
+
fetchImpl = null,
|
|
103
|
+
objectUrlFactory = null
|
|
104
|
+
} = {})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Adapts an existing DBOPFS instance into an authority-scoped store. The returned
|
|
108
|
+
frozen object exposes `{protocol,tableName,prepare,remove}`.
|
|
109
|
+
|
|
110
|
+
`prepare(authority,{signal,onProgress,offline=false,security})`:
|
|
111
|
+
|
|
112
|
+
1. obtains an exclusive Web Lock for the exact authority;
|
|
113
|
+
2. admits a complete cached manifest when every record still matches;
|
|
114
|
+
3. otherwise, unless `offline:true`, downloads every declared file without
|
|
115
|
+
credentials;
|
|
116
|
+
4. enforces enabled byte-length and SHA-256 checks;
|
|
117
|
+
5. validates the closed runtime module graph;
|
|
118
|
+
6. commits `arcane.ai.browser-speech.assets.v1` only after every file succeeds;
|
|
119
|
+
7. returns materialized object URLs plus a `release()` callback.
|
|
120
|
+
|
|
121
|
+
An installation or cache-validation failure removes incomplete stored state for
|
|
122
|
+
that authority. A request or provider-use failure does not imply cache removal.
|
|
123
|
+
`offline:true` never falls back to network and rejects with
|
|
124
|
+
`ARCANE_AI_ARTIFACT_OFFLINE_MISS` when no admitted cache exists.
|
|
125
|
+
|
|
126
|
+
## `createBrowserWhisperProvider()`
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
createBrowserWhisperProvider({
|
|
130
|
+
id = 'arcane-browser-whisper',
|
|
131
|
+
localOnly = true,
|
|
132
|
+
model,
|
|
133
|
+
runtime,
|
|
134
|
+
appSecurity,
|
|
135
|
+
security,
|
|
136
|
+
store,
|
|
137
|
+
offline = false
|
|
138
|
+
} = {})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Returns a frozen `arcane-ai-provider/2` object for role `stt`. The provider
|
|
142
|
+
surface is `{protocol,role,id,localOnly,catalog,inspect,status,load,request,
|
|
143
|
+
unload,dispose}`.
|
|
144
|
+
|
|
145
|
+
The only request operation is `transcribe`:
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
async function transcribeAfterUserChoice(provider, pcmFloat32, signal) {
|
|
149
|
+
// The admitted Whisper provider must already be ready.
|
|
150
|
+
const result = await provider.request({
|
|
151
|
+
role: 'stt',
|
|
152
|
+
operation: 'transcribe',
|
|
153
|
+
signal,
|
|
154
|
+
payload: {
|
|
155
|
+
audio: pcmFloat32,
|
|
156
|
+
sampleRate: 16_000
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
console.log(result.text);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`audio` must be a `Float32Array` sampled at exactly 16,000 Hz. The provider-native
|
|
165
|
+
provider result is a structured `{text}` record transferred by Worker
|
|
166
|
+
`postMessage`; the client does not re-freeze that cloned record. The same
|
|
167
|
+
provider also accepts the shared AI.js STT
|
|
168
|
+
payload `{audio:Blob|File,mimeType,model}`. It verifies `model`, decodes the
|
|
169
|
+
browser audio to authoritative 16 kHz mono PCM, and then enters the same provider-native
|
|
170
|
+
provider operation. Decode support and failure remain explicit.
|
|
171
|
+
|
|
172
|
+
## `createBrowserKokoroProvider()`
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
createBrowserKokoroProvider({
|
|
176
|
+
id = 'arcane-browser-kokoro',
|
|
177
|
+
localOnly = true,
|
|
178
|
+
model,
|
|
179
|
+
runtime,
|
|
180
|
+
appSecurity,
|
|
181
|
+
security,
|
|
182
|
+
store,
|
|
183
|
+
offline = false
|
|
184
|
+
} = {})
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Returns the same provider/2 lifecycle for role `tts`. The only request
|
|
188
|
+
operation is `synthesize`:
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
async function synthesizeAfterUserChoice(provider, signal) {
|
|
192
|
+
// The admitted Kokoro provider must already be ready.
|
|
193
|
+
const result = await provider.request({
|
|
194
|
+
role: 'tts',
|
|
195
|
+
operation: 'synthesize',
|
|
196
|
+
signal,
|
|
197
|
+
payload: {
|
|
198
|
+
text: 'Hello from Arcane.',
|
|
199
|
+
voice: 'caller-owned-voice-id',
|
|
200
|
+
speed: 1
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
console.log(result.audio, result.sampleRate, result.voice);
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
`speed` must be greater than zero and at most four. Omitted `voice` selects the
|
|
209
|
+
caller-supplied `model.defaultVoice`. The provider-native result is the structured
|
|
210
|
+
`{audio:Float32Array,sampleRate:24000,voice}` record transferred by Worker
|
|
211
|
+
`postMessage`; the client does not re-freeze that cloned record. The shared
|
|
212
|
+
AI.js TTS payload is
|
|
213
|
+
`{model,input,responseFormat,voice?,speed?}`. Only `responseFormat:"wav"` is
|
|
214
|
+
admitted; the provider maps it to `{text,voice,speed}` and returns frozen
|
|
215
|
+
`{audio:Uint8Array,contentType:"audio/wav"}` containing 24 kHz mono PCM.
|
|
216
|
+
Shared AI.js synthesis reads the selected model's catalog default and never
|
|
217
|
+
replaces it with a voice saved for a different provider route.
|
|
218
|
+
|
|
219
|
+
## Lifecycle and status
|
|
220
|
+
|
|
221
|
+
Whisper and Kokoro use the same independent state machine:
|
|
222
|
+
|
|
223
|
+
| Operation | Behavior |
|
|
224
|
+
| --- | --- |
|
|
225
|
+
| `catalog()` | Returns the single caller-admitted model descriptor. TTS exposes its admitted `defaultVoice`; STT has no voice field. |
|
|
226
|
+
| `inspect(selection,{signal})` | Returns `{available:true,authority}` only for the exact provider/model/local selection; mismatch returns an unavailable record. |
|
|
227
|
+
| `status()` | Returns `{role,providerId,modelId,state,loaded,busy,generation,errorCode,cache}`. |
|
|
228
|
+
| `load(context)` | Requires `{role,selection,progress,signal?,security?}`, admits/cache-materializes artifacts, creates one role Worker, and loads the adapter. Compatible repeated loads coalesce. |
|
|
229
|
+
| `request(context)` | Runs exactly one STT or TTS operation. A provider rejects concurrent use with `ARCANE_AI_PROVIDER_BUSY`. |
|
|
230
|
+
| `unload()` | Aborts active load/use, terminates the Worker, releases object URLs, and returns `unloaded`. |
|
|
231
|
+
| `dispose()` | Completes unload and permanently returns `disposed`. |
|
|
232
|
+
|
|
233
|
+
Cancellation after a Worker request begins terminates that Worker slot and
|
|
234
|
+
returns the provider to `unloaded`; a later request requires a fresh load. A
|
|
235
|
+
shared STT request can instead be aborted while the browser is still decoding
|
|
236
|
+
its `Blob` or `File`, before Worker use begins. That request rejects with
|
|
237
|
+
`ARCANE_AI_REQUEST_ABORTED`, but the loaded Worker remains intact and the
|
|
238
|
+
provider stays `ready`. Worker crash/message failures become explicit error
|
|
239
|
+
state. No result is retried through another provider.
|
|
240
|
+
|
|
241
|
+
Register the providers with the projected
|
|
242
|
+
[`AIProviderRuntime`](../runtime-modules.md#aiproviderruntimejs) to normalize
|
|
243
|
+
selection, startup, application calls, and
|
|
244
|
+
[`AIRuntimeState`](../runtime-modules.md#airuntimestatejs) observation. The
|
|
245
|
+
provider objects themselves do not expose an event target.
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
async function loadSpeechProviderAfterUserChoice(provider) {
|
|
249
|
+
const selection = {
|
|
250
|
+
providerId: provider.id,
|
|
251
|
+
modelId: provider.catalog()[0].id,
|
|
252
|
+
localOnly: true
|
|
253
|
+
};
|
|
254
|
+
return provider.load({
|
|
255
|
+
role: provider.role,
|
|
256
|
+
selection,
|
|
257
|
+
progress(update) {
|
|
258
|
+
console.info(update.phase, update.completed, update.total);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The example only defines the operation; invoke it from an explicit user action
|
|
265
|
+
after showing the admitted runtime/model and download policy. Requests are
|
|
266
|
+
valid only after that load resolves successfully. Applications
|
|
267
|
+
register and configure browser-speech providers on the shared runtime. `AI.js`
|
|
268
|
+
obtains that singleton and translates its existing browser speech request shapes
|
|
269
|
+
at this one provider boundary; it does not register providers, choose
|
|
270
|
+
authorities, or trigger a hidden model download.
|
|
271
|
+
|
|
272
|
+
## Errors
|
|
273
|
+
|
|
274
|
+
| Code | Meaning |
|
|
275
|
+
| --- | --- |
|
|
276
|
+
| `ARCANE_AI_MODEL_AUTHORITY_REQUIRED` | Selection or authority does not match the provider. |
|
|
277
|
+
| `ARCANE_AI_INVALID_REQUEST` | Role, operation, audio, text, voice, or speed is invalid. |
|
|
278
|
+
| `ARCANE_AI_NOT_READY` | Use was requested before a successful load. |
|
|
279
|
+
| `ARCANE_AI_PROVIDER_BUSY` | The role already has an active request. |
|
|
280
|
+
| `ARCANE_AI_PROVIDER_DISPOSED` | Load/use was requested after disposal. |
|
|
281
|
+
| `ARCANE_AI_REQUEST_ABORTED` | The caller's AbortSignal cancelled work. |
|
|
282
|
+
| `ARCANE_AI_OPERATION_SUPERSEDED` | A newer unload/load/dispose generation replaced the operation. |
|
|
283
|
+
| `ARCANE_AI_ARTIFACT_SOURCE_INVALID` | Artifact bytes or body shape are not readable. |
|
|
284
|
+
| `ARCANE_AI_ARTIFACT_SOURCE_UNAVAILABLE` | Fetch is unavailable. |
|
|
285
|
+
| `ARCANE_AI_ARTIFACT_DOWNLOAD_FAILED` | Network or HTTP download failed. |
|
|
286
|
+
| `ARCANE_AI_ARTIFACT_SOURCE_CHANGED` | Redirect/final URL differs from the admitted immutable URL. |
|
|
287
|
+
| `ARCANE_AI_ARTIFACT_SIZE_MISMATCH` | Enabled byte-length evidence differs. |
|
|
288
|
+
| `ARCANE_AI_ARTIFACT_DIGEST_MISMATCH` | Enabled SHA-256 evidence differs. |
|
|
289
|
+
| `ARCANE_AI_ARTIFACT_CACHE_REJECTED` | DBOPFS did not preserve the completed file. |
|
|
290
|
+
| `ARCANE_AI_ARTIFACT_OFFLINE_MISS` | Strict offline use has no admitted complete cache. |
|
|
291
|
+
| `ARCANE_AI_STORAGE_BUSY` | Another context owns the same authority lock. |
|
|
292
|
+
| `ARCANE_AI_STORAGE_UNAVAILABLE` / `ARCANE_AI_STORAGE_READ_FAILED` / `ARCANE_AI_STORAGE_DELETE_FAILED` | The selected DBOPFS store is unavailable or could not read/delete the authority. |
|
|
293
|
+
| `ARCANE_AI_RUNTIME_MODULE_GRAPH_UNDECLARED` | Runtime code leaves the closed self-contained module grammar. |
|
|
294
|
+
| `ARCANE_AI_WORKER_CRASHED` / `ARCANE_AI_WORKER_MESSAGE_ERROR` | The isolated adapter Worker failed. |
|
|
295
|
+
| `ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH` | The Worker/client/provider protocol is not the SDK-owned contract. |
|
|
296
|
+
| `ARCANE_AI_PROVIDER_LOAD_FAILED` / `ARCANE_AI_PROVIDER_REQUEST_FAILED` / `ARCANE_AI_PROVIDER_UNAVAILABLE` | Adapter load/request failed or the admitted runtime did not expose the requested provider. |
|
|
297
|
+
| `ARCANE_AI_INVALID_PROVIDER_RESULT` | Whisper/Kokoro returned a result outside the normalized contract. |
|
|
298
|
+
| `ARCANE_AI_UNDECLARED_ARTIFACT` | The runtime requested a file outside its admitted closure. |
|
|
299
|
+
| `ARCANE_AI_AUDIO_DECODE_UNAVAILABLE` / `ARCANE_AI_AUDIO_DECODE_FAILED` | Shared Blob/File STT cannot obtain a browser decoder or cannot produce nonempty 16 kHz mono PCM. |
|
|
300
|
+
| `ARCANE_AI_UNSUPPORTED_RESPONSE_FORMAT` | Shared TTS requested a format other than `wav`. |
|
|
301
|
+
|
|
302
|
+
## Security and ownership
|
|
303
|
+
|
|
304
|
+
- The SDK contains no speech model or adapter runtime bytes in this entrypoint.
|
|
305
|
+
- The application must verify the license and authority for every supplied byte.
|
|
306
|
+
- URLs never carry credentials; fetch uses `credentials: "omit"`.
|
|
307
|
+
- Mutable `main`, `master`, and `latest` paths are rejected.
|
|
308
|
+
- The completion manifest is consistency evidence for the admitted DBOPFS
|
|
309
|
+
bytes. It is not publisher authenticity by itself.
|
|
310
|
+
- The runtime entry is isolated in a Worker and limited to its declared
|
|
311
|
+
artifact closure.
|
|
312
|
+
- Tool calls are an LLM concern; speech providers execute no application tool.
|
|
313
|
+
- A native `Arcane.speech` service is a different privileged host path. This
|
|
314
|
+
browser package neither calls it nor inherits its capability admission.
|
|
315
|
+
|
|
316
|
+
<details>
|
|
317
|
+
<summary>Protocol details</summary>
|
|
318
|
+
|
|
319
|
+
The artifact store identifies itself as
|
|
320
|
+
`arcane-ai-browser-speech-artifacts/1`. Authorities use
|
|
321
|
+
`arcane-ai-model-authority/1`. Providers implement `arcane-ai-provider/2` with
|
|
322
|
+
roles `stt` and `tts`; their only operations are `transcribe` and `synthesize`.
|
|
323
|
+
The Worker client additionally binds exact role, operation, request IDs, and
|
|
324
|
+
generation so stale or cross-role messages cannot settle current work.
|
|
325
|
+
|
|
326
|
+
</details>
|
|
327
|
+
|
|
328
|
+
## Related
|
|
329
|
+
|
|
330
|
+
- [Normalized AI](../README.md#normalized-ai)
|
|
331
|
+
- [Browser-WASM LLM](browser-wasm.md)
|
|
332
|
+
- [AIProviderRuntime.js](../runtime-modules.md#aiproviderruntimejs)
|
|
333
|
+
- [AIRuntimeState.js](../runtime-modules.md#airuntimestatejs)
|
|
334
|
+
- [PersistentAIChatSession.js](../runtime-modules.md#persistentaichatsessionjs)
|
|
335
|
+
- [Availability and normalization](../availability-and-normalization.md)
|
|
336
|
+
- [Protocol architecture](../protocols.md#portable-ai-provider-runtime)
|