arcane-os 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +8 -8
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +29 -22
- package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +203 -0
- package/browser-runtime/ai/browser-kokoro-worker.mjs +11 -2
- package/browser-runtime/ai/browser-speech-artifacts.mjs +3230 -397
- package/browser-runtime/ai/browser-speech-providers.mjs +1141 -157
- package/browser-runtime/ai/browser-speech.mjs +2 -0
- package/browser-runtime/ai/browser-whisper-worker.mjs +11 -2
- package/browser-runtime/ai/model-controller.mjs +285 -95
- package/browser-runtime/ai/speech-worker-client.mjs +247 -32
- package/browser-runtime/ai/speech-worker-runtime.mjs +2310 -167
- package/browser-runtime/event-manager.mjs +1097 -1
- package/docs/architecture.md +2 -2
- package/docs/event-manager.md +155 -27
- package/docs/reference/README.md +27 -27
- package/docs/reference/ai/browser-speech-package-authority.json +835 -0
- package/docs/reference/ai/browser-speech.md +1162 -246
- package/docs/reference/ai/browser-wasm.md +18 -7
- package/docs/reference/availability-and-normalization.md +6 -3
- package/docs/reference/behavioral-testing.md +29 -6
- package/docs/reference/cli.md +117 -9
- package/docs/reference/core/arcane-ai-contracts.md +1 -1
- package/docs/reference/event-manager.md +577 -32
- package/docs/reference/inventory/package-api.json +478 -2
- package/docs/reference/inventory/runtime-components.json +108 -44
- package/docs/reference/inventory/runtime-modules.json +131 -53
- package/docs/reference/mail.md +316 -0
- package/docs/reference/protocols.md +157 -43
- package/docs/reference/runtime-components.md +258 -83
- package/docs/reference/runtime-modules.md +613 -77
- package/docs/reference/sdk-api.md +1014 -25
- package/package.json +5 -4
- package/runtime/ARCANE_RUNTIME_RELEASE.json +145 -140
- package/runtime/arcane/components/app-bar.html +34 -13
- package/runtime/arcane/components/assistant-panel.html +110 -57
- package/runtime/arcane/components/calculator.html +7 -4
- package/runtime/arcane/components/chart.html +58 -17
- package/runtime/arcane/components/chat.html +606 -136
- package/runtime/arcane/components/conversation-view.html +13 -6
- package/runtime/arcane/components/dashboard-config.html +96 -59
- package/runtime/arcane/components/data-maintenance.html +69 -14
- package/runtime/arcane/components/data-view.html +53 -7
- package/runtime/arcane/components/directory-picker.html +118 -32
- package/runtime/arcane/components/document-inspector.html +47 -10
- package/runtime/arcane/components/file-drop.html +81 -35
- package/runtime/arcane/components/file-inspector.html +72 -22
- package/runtime/arcane/components/file-manager.html +374 -79
- package/runtime/arcane/components/integration-settings.html +12 -5
- package/runtime/arcane/components/local-ai-status.html +48 -19
- package/runtime/arcane/components/markdown-document.html +161 -68
- package/runtime/arcane/components/markdown-editor.html +110 -33
- package/runtime/arcane/components/media-embed.html +8 -5
- package/runtime/arcane/components/modal.html +15 -5
- package/runtime/arcane/components/output-panel.html +28 -23
- package/runtime/arcane/components/preferences-form.html +22 -4
- package/runtime/arcane/components/record-timeline.html +18 -2
- package/runtime/arcane/components/relationship-board.html +23 -3
- package/runtime/arcane/components/screen-capture.html +10 -4
- package/runtime/arcane/components/source-code-viewer.html +76 -9
- package/runtime/arcane/components/source-explanation.html +23 -3
- package/runtime/arcane/components/speech.html +462 -384
- package/runtime/arcane/components/summary-strip.html +22 -11
- package/runtime/arcane/components/table.html +39 -21
- package/runtime/arcane/components/task-progress.html +79 -21
- package/runtime/arcane/components/terminal-workspace.html +7 -4
- package/runtime/arcane/components/theme-editor.html +7 -3
- package/runtime/arcane/components/unified-inbox.html +9 -4
- package/runtime/arcane/components/voice-transcription.html +639 -98
- package/runtime/arcane/components/weather-widget.html +5 -3
- package/runtime/arcane/components/web-navigator.html +48 -8
- package/runtime/arcane/entities/Chat.js +1 -1
- package/runtime/arcane/entities/User.js +110 -23
- package/runtime/arcane/modules/AI.js +2109 -130
- package/runtime/arcane/modules/AIProviderRuntime.js +720 -13
- package/runtime/arcane/modules/AIRuntimeState.js +109 -52
- package/runtime/arcane/modules/ApiModelDatabase.js +390 -17
- package/runtime/arcane/modules/BrowserTestSuite.js +205 -28
- package/runtime/arcane/modules/CalculatorEngine.js +63 -3
- package/runtime/arcane/modules/CommunicationAppController.js +588 -28
- package/runtime/arcane/modules/CommunicationHub.js +590 -10
- package/runtime/arcane/modules/ComponentContracts.js +470 -0
- package/runtime/arcane/modules/ConversationTimebox.js +152 -33
- package/runtime/arcane/modules/DBLS.js +40 -7
- package/runtime/arcane/modules/DBOPFS.js +35 -11
- package/runtime/arcane/modules/DataMaintenance.js +12 -2
- package/runtime/arcane/modules/Errors.js +65 -7
- package/runtime/arcane/modules/HTMLImport.js +198 -14
- package/runtime/arcane/modules/LocalAIReadinessController.js +208 -29
- package/runtime/arcane/modules/Mail.js +738 -115
- package/runtime/arcane/modules/MailOutbox.mjs +1395 -0
- package/runtime/arcane/modules/MailTransport.mjs +197 -39
- package/runtime/arcane/modules/Ollama.js +36 -1
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +583 -7
- package/runtime/arcane/modules/PreferenceStore.js +367 -33
- package/runtime/arcane/modules/RecordReviewStore.js +322 -23
- package/runtime/arcane/modules/ScreenCapture.js +1397 -15
- package/runtime/arcane/modules/SpeechPlayback.js +438 -41
- package/runtime/arcane/modules/TerminalClient.js +277 -12
- package/runtime/arcane/modules/ThemeBootstrap.js +80 -6
- package/runtime/arcane/modules/ThemeManager.js +39 -7
- package/runtime/arcane/modules/TimeGuard.js +131 -20
- package/runtime/arcane/modules/WaitForComponent.js +386 -33
- package/schemas/arcane-lock.schema.json +2 -2
- package/src/cli/main.mjs +435 -9
- package/src/event-manager.mjs +1097 -1
- package/src/import-map.mjs +21 -3
- package/src/index.mjs +13 -0
- package/src/installed-sdk-runtime.mjs +112 -0
- package/src/mail-api.mjs +22 -0
- package/src/mail-credentials.mjs +667 -0
- package/src/mail-server.mjs +1769 -0
- package/src/mail.mjs +261 -0
- package/src/sdk-browser-runtime.mjs +85 -41
- package/src/testing-loader.mjs +7 -0
- package/src/toolchain.mjs +3 -0
- package/src/workspace.mjs +1 -1
|
@@ -1,97 +1,228 @@
|
|
|
1
1
|
# Browser speech providers
|
|
2
2
|
|
|
3
|
-
`arcane-os/ai/browser-speech` is the
|
|
4
|
-
caller-supplied Whisper speech-to-text and Kokoro text-to-speech runtimes.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
`arcane-os/ai/browser-speech` is the browser-only, event-neutral SDK boundary
|
|
4
|
+
for caller-supplied Whisper speech-to-text and Kokoro text-to-speech runtimes.
|
|
5
|
+
It supplies immutable artifact-graph validation, DBOPFS admission, role Workers,
|
|
6
|
+
provider/2 adapters, audio normalization, cancellation, and cleanup. It does
|
|
7
|
+
not ship or select runtime modules, model weights, voice bytes, a default
|
|
8
|
+
catalog, credentials, a native provider, or a cloud fallback.
|
|
9
|
+
The package contains no speech runtime, model, or voice payload and
|
|
10
|
+
never downloads one before explicit `load()`.
|
|
8
11
|
|
|
9
|
-
Use this
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
Use this entrypoint when an application deliberately owns every browser-local
|
|
13
|
+
speech choice. Higher-level selection, startup policy, shared state, and event
|
|
14
|
+
projection belong to the application runtime; this package exposes only
|
|
15
|
+
promises, `AbortSignal`, and the caller's progress callback.
|
|
13
16
|
|
|
14
17
|
## Availability
|
|
15
18
|
|
|
16
19
|
| Host | Availability | Notes |
|
|
17
20
|
| --- | --- | --- |
|
|
18
|
-
| Browser | Shipped | Requires DBOPFS/OPFS, Web Locks, Workers, Fetch
|
|
19
|
-
| Native WebView | Conditional |
|
|
20
|
-
| Node | Importable, execution unavailable | The ESM subpath
|
|
21
|
-
| Cloud | Not provided | A cloud speech
|
|
21
|
+
| Browser | Shipped | Requires DBOPFS/OPFS, Web Locks, Workers, Fetch, Blob/File, and object URLs. Authenticated graphs additionally require `MessageChannel`; shared Blob/File STT requests require the browser audio decoder. |
|
|
22
|
+
| Native WebView | Conditional | Available only when the WebView exposes the same browser APIs and the application admits every artifact. It does not invoke Core speech. |
|
|
23
|
+
| Node | Importable, execution unavailable | The ESM subpath can be imported, but the SDK supplies no Node speech storage, Worker, or audio-decoder host. |
|
|
24
|
+
| Cloud | Not provided | A cloud speech adapter may separately implement `arcane-ai-provider/2`; this package never selects it. |
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
independently.
|
|
26
|
+
Whisper `stt` and Kokoro `tts` each own an independent provider lifecycle. A
|
|
27
|
+
failure or cancellation in either role does not disable LLM use and never
|
|
28
|
+
authorizes a different local, native, Core, or cloud provider.
|
|
27
29
|
|
|
28
|
-
##
|
|
30
|
+
## Public exports
|
|
29
31
|
|
|
30
32
|
```javascript
|
|
31
33
|
import {
|
|
34
|
+
BROWSER_SPEECH_ARTIFACT_GRAPH_PROTOCOL,
|
|
32
35
|
BROWSER_SPEECH_ARTIFACT_PROTOCOL,
|
|
33
36
|
createBrowserKokoroProvider,
|
|
37
|
+
createBrowserSpeechArtifactGraph,
|
|
34
38
|
createBrowserSpeechAuthority,
|
|
35
39
|
createBrowserWhisperProvider,
|
|
36
40
|
createDbopfsSpeechArtifactStore
|
|
37
41
|
} from 'arcane-os/ai/browser-speech';
|
|
38
42
|
```
|
|
39
43
|
|
|
40
|
-
The entrypoint exports exactly those
|
|
41
|
-
|
|
44
|
+
The entrypoint exports exactly those seven names. Importing it downloads no
|
|
45
|
+
artifact, opens no cache, creates no Worker, and publishes no event.
|
|
42
46
|
|
|
43
|
-
##
|
|
47
|
+
## Protocol and enum registry
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
| Subject | Exact value or closed set |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| Artifact-store protocol | `arcane-ai-browser-speech-artifacts/1` |
|
|
52
|
+
| Authenticated artifact-graph protocol | `arcane-ai-browser-speech-artifact-graph/1` |
|
|
53
|
+
| Graph `kind` and prepared `runtime.moduleGraph` | `browser-speech-authenticated-artifact-graph` |
|
|
54
|
+
| Legacy prepared `runtime.moduleGraph` | `self-contained` |
|
|
55
|
+
| Legacy authority protocol | `arcane-ai-model-authority/1` |
|
|
56
|
+
| Provider protocol | `arcane-ai-provider/2` |
|
|
57
|
+
| Worker protocol | `arcane-ai-speech-worker/1` |
|
|
58
|
+
| Worker error-envelope protocol | `arcane-ai-speech-worker-error/1` |
|
|
59
|
+
| Nested artifact module-Worker protocol | `arcane-ai-browser-speech-artifact-module-worker/1` |
|
|
60
|
+
| Nested module-Worker rejection event | `artifact-module-worker-bootstrap-rejected` |
|
|
61
|
+
| Runtime graph-guard protocol | `arcane-ai-browser-speech-artifact-graph-runtime/1` |
|
|
62
|
+
| Roles | `stt`, `tts` |
|
|
63
|
+
| Role operations | `transcribe` for `stt`; `synthesize` for `tts` |
|
|
64
|
+
| Public Worker operations | `load`, `use`, `status`, `unload`, `dispose` |
|
|
65
|
+
| Worker transport-only control operation | `cancel` |
|
|
66
|
+
| TTS response format | `wav` |
|
|
67
|
+
| Runtime adapters | `transformers-whisper` for `stt`; `kokoro-js` for `tts` |
|
|
68
|
+
| ONNX namespace identifiers | `transformers-env-backends-onnx-wasm` for `stt`; `kokoro-env-wasm-paths` for `tts` |
|
|
69
|
+
| Edge policies | `artifact-targets-admitted`, `inactive-runtime-branch-rejected` |
|
|
70
|
+
| Import target matches | `exact-runtime-specifier`, `materialized-module-url`; module-Worker targets additionally admit `self-module-url` |
|
|
71
|
+
| Transform kinds | `function-return-this-to-global-this`, `typed-array-constructor` |
|
|
72
|
+
| Graph descriptor status | `artifact-graph-descriptor-verified` |
|
|
73
|
+
| Graph admission | `artifact-graph-network-dbopfs-verified`, `artifact-graph-dbopfs-cache-verified`, `artifact-graph-offline-dbopfs-cache-verified` |
|
|
74
|
+
|
|
75
|
+
These values are exact, case-sensitive public contract values. Unknown values
|
|
76
|
+
fail closed; a newer-looking value is not treated as compatible.
|
|
77
|
+
|
|
78
|
+
## `createBrowserSpeechArtifactGraph()`
|
|
48
79
|
|
|
49
|
-
|
|
80
|
+
This is the operational authority for a real auxiliary ESM/WASM/model/voice
|
|
81
|
+
closure. It creates one frozen, caller-selected graph and computes its SHA-256
|
|
82
|
+
identity from a canonical JSON projection. The inventory is dynamic and has no
|
|
83
|
+
fixed file or edge count; every declared member must still belong to the one
|
|
84
|
+
complete reachable closure.
|
|
85
|
+
|
|
86
|
+
The top-level shape is:
|
|
50
87
|
|
|
51
88
|
```text
|
|
52
|
-
|
|
53
|
-
|
|
89
|
+
createBrowserSpeechArtifactGraph({
|
|
90
|
+
kind?,
|
|
91
|
+
identitySha256?,
|
|
92
|
+
providerId?,
|
|
54
93
|
role,
|
|
55
|
-
model,
|
|
56
|
-
runtime,
|
|
57
|
-
|
|
58
|
-
|
|
94
|
+
model: { ... },
|
|
95
|
+
runtime: { ... },
|
|
96
|
+
files: [fileDescriptor, ...],
|
|
97
|
+
edges: {
|
|
98
|
+
staticImports: [...],
|
|
99
|
+
dynamicImports: [...],
|
|
100
|
+
moduleWorkers: [...],
|
|
101
|
+
fetches: [...],
|
|
102
|
+
cacheOpens: [...]
|
|
103
|
+
},
|
|
104
|
+
transforms: [...]
|
|
105
|
+
})
|
|
59
106
|
```
|
|
60
107
|
|
|
61
|
-
|
|
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.
|
|
108
|
+
### Top-level and model fields
|
|
64
109
|
|
|
65
|
-
|
|
110
|
+
| Field | Contract |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| `kind` | Omit it or use exactly `browser-speech-authenticated-artifact-graph`. |
|
|
113
|
+
| `identitySha256` | Optional 64-character lowercase SHA-256 assertion. If supplied, it must equal the SDK's canonical descriptor digest. The returned graph always contains the computed value. |
|
|
114
|
+
| `providerId` | `null`/omitted, or one trimmed 1–128 character identity. A non-null value must equal the provider constructor's `id`. |
|
|
115
|
+
| `role` | Exactly `stt` or `tts`. |
|
|
116
|
+
| `model.id` | Trimmed 1–128 character caller-owned model identity. |
|
|
117
|
+
| `model.repository` | Trimmed 1–128 character logical repository identity. The SDK passes it to the admitted adapter but does not resolve it independently. |
|
|
118
|
+
| `model.revision` | Trimmed 1–128 character immutable revision. Every model and voice file must use this same revision. |
|
|
119
|
+
| `model.dtype` | Trimmed 1–128 character caller-owned dtype. There is no SDK-selected graph default. |
|
|
120
|
+
| `model.inputSampleRate` | Required positive safe integer for `stt`; caller-owned. STT must not declare voices. |
|
|
121
|
+
| `model.outputSampleRate` | Required positive safe integer for `tts`; caller-owned. |
|
|
122
|
+
| `model.defaultVoice` | Required for `tts`; must name one declared `voices[].id`. |
|
|
123
|
+
| `model.voices` | Required nonempty TTS array of unique `{id,path}` records. Every path must name one unique `voice-style-binary`, and every such file must be in this inventory. |
|
|
124
|
+
|
|
125
|
+
### Runtime fields
|
|
126
|
+
|
|
127
|
+
| Field | Contract |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `runtime.adapter` | `transformers-whisper` for `stt`; `kokoro-js` for `tts`. |
|
|
130
|
+
| `runtime.version` / `runtime.revision` | Trimmed 1–128 character caller-pinned identities. The sole entrypoint file revision must equal `runtime.revision`. |
|
|
131
|
+
| `runtime.entrypoint` | Canonical path of the sole `runtime-entrypoint-javascript`. `runtime.entry` is accepted as an input alias; the normalized graph exposes `runtime.entry`. |
|
|
132
|
+
| `runtime.onnxWasm.namespace` | `transformers-env-backends-onnx-wasm` for STT or `kokoro-env-wasm-paths` for TTS. |
|
|
133
|
+
| `runtime.onnxWasm.mjsPath` | Path of a declared `runtime-auxiliary-javascript`. |
|
|
134
|
+
| `runtime.onnxWasm.wasmPath` | Path of a declared `runtime-wasm-binary`. |
|
|
135
|
+
| `runtime.onnxWasm.numThreads` | Optional positive safe integer for Transformers STT only. Kokoro does not expose a verified thread setting and rejects this field with reason `kokoro-env-num-threads-field-not-exposed`. No hardware-derived default is chosen. |
|
|
136
|
+
| `runtime.negativeRuntimeRequestUrls` | Optional unique absolute HTTPS routes that a declared fetch edge may intentionally resolve as a local `404`. They may not overlap a positive source or runtime route and must be referenced by an edge. |
|
|
137
|
+
|
|
138
|
+
### File descriptor
|
|
139
|
+
|
|
140
|
+
Every `files[]` entry contains all of these fields:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
{
|
|
144
|
+
kind,
|
|
145
|
+
path,
|
|
146
|
+
sourceUrl,
|
|
147
|
+
revision,
|
|
148
|
+
license,
|
|
149
|
+
mediaType,
|
|
150
|
+
sourceMediaType?,
|
|
151
|
+
bytes,
|
|
152
|
+
sha256,
|
|
153
|
+
runtimeRequestUrls?,
|
|
154
|
+
redirectFinalOrigins?
|
|
155
|
+
}
|
|
156
|
+
```
|
|
66
157
|
|
|
67
158
|
| Field | Contract |
|
|
68
159
|
| --- | --- |
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
160
|
+
| `kind` | One exact kind from the table below. |
|
|
161
|
+
| `path` | Nonempty NFC-normalized relative path. Leading/trailing slash, backslash, empty/`.`/`..` segment, percent escape, query/fragment delimiter, control character, duplicate spelling, or case-folded collision is rejected. |
|
|
162
|
+
| `sourceUrl` | Immutable starting HTTPS or same-origin authority without credentials or fragment. The pathname must not name `main`, `master`, `latest`, `refs/heads/main`, `refs/heads/master`, `resolve/main`, or `resolve/master`, or an `@latest`/`@next` channel. The URL must contain the declared revision or SHA-256 and remains authoritative even when redirect following is opted in. `url` is accepted as an input alias. |
|
|
163
|
+
| `revision` | Nonempty 1–128 character immutable file revision. Runtime entry revision equals the runtime revision; all model/voice revisions equal the model revision. |
|
|
164
|
+
| `license` | Nonempty declaration up to 256 characters. It is part of graph identity and the DBOPFS manifest authority, but it is only a declaration: it is not provenance, a composite notice, corresponding-source evidence, or a license inferred from bytes. The caller remains responsible for complete immutable license/notice evidence. |
|
|
165
|
+
| `mediaType` | Exact lowercase `type/subtype` without parameters. JavaScript is `application/javascript` or `text/javascript`; WASM is `application/wasm`; `*-json` kinds are `application/json`. |
|
|
166
|
+
| `sourceMediaType` | Optional exact lowercase `type/subtype` without parameters for the cold HTTP response. It defaults to `mediaType`; when different, it is exposed in the normalized descriptor and graph identity while `mediaType` remains the authenticated materialized Blob type. |
|
|
167
|
+
| `bytes` | Positive safe integer; always required and always verified for graphs. |
|
|
168
|
+
| `sha256` | Exactly 64 lowercase hexadecimal characters; always required and always verified for graphs. |
|
|
169
|
+
| `runtimeRequestUrls` | Optional unique absolute HTTPS aliases used only inside the authenticated Worker. An alias may describe a third-party runtime's hard-coded mutable request, but it is never a download authority: the Worker maps it to this already verified local file. |
|
|
170
|
+
| `redirectFinalOrigins` | Optional nonempty array that opts this file into Fetch redirect following. Every member must canonicalize to a unique HTTPS origin with no credentials, path, query, or fragment. The normalized array is lexically sorted, frozen, and graph-identity-bound. Omit the field for redirect rejection; an empty array is rejected. |
|
|
171
|
+
|
|
172
|
+
The closed file kinds are:
|
|
173
|
+
|
|
174
|
+
| Runtime kinds | Model/data kinds |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `runtime-entrypoint-javascript` | `model-configuration-json` |
|
|
177
|
+
| `runtime-auxiliary-javascript` | `model-generation-configuration-json` |
|
|
178
|
+
| `runtime-wasm-binary` | `model-onnx-binary` |
|
|
179
|
+
| `runtime-opaque-data` | `model-onnx-external-data` |
|
|
180
|
+
| | `model-preprocessor-json` |
|
|
181
|
+
| | `model-tokenizer-json` |
|
|
182
|
+
| | `model-opaque-data` |
|
|
183
|
+
| | `voice-style-binary` |
|
|
184
|
+
|
|
185
|
+
Paths and immutable source URLs are globally unique within a graph. Positive
|
|
186
|
+
runtime request aliases are also unique and cannot overlap a source URL or a
|
|
187
|
+
negative route. Every non-entry file must be reachable from the declared ONNX
|
|
188
|
+
pair, TTS voice inventory, or one exact edge; unreachable files and routes are
|
|
189
|
+
rejected rather than silently retained.
|
|
190
|
+
|
|
191
|
+
### Edge and transform descriptors
|
|
192
|
+
|
|
193
|
+
Edge `occurrence` values are positive, one-based occurrences in the named
|
|
194
|
+
`modulePath`. A declaration must match the scanner's exact source occurrence;
|
|
195
|
+
missing, duplicate, extra, occurrence-mismatched, or undeclared runtime edges
|
|
196
|
+
fail closed. Descriptor collections are canonically sorted for graph identity,
|
|
197
|
+
so caller array order is not semantic.
|
|
198
|
+
|
|
199
|
+
| Collection | Exact record |
|
|
200
|
+
| --- | --- |
|
|
201
|
+
| `edges.staticImports` | `{modulePath,occurrence,specifier,targetPath}`. The literal specifier and declared JavaScript target must match. |
|
|
202
|
+
| `edges.dynamicImports` | `{modulePath,occurrence,edgePolicy,targets}`. Each target is `{match,targetPath,exactSpecifier?}`. `exactSpecifier` is required only for `exact-runtime-specifier`. |
|
|
203
|
+
| `edges.moduleWorkers` | Same shape as dynamic imports; `self-module-url` is additionally available and must target the declaring module. Only module Workers are admitted. |
|
|
204
|
+
| `edges.fetches` | `{modulePath,occurrence,edgePolicy,methods:["GET"],targetPaths,negativeRuntimeRequestUrls,allowMaterializedUrls}`. `methods` defaults to the same one-element `GET` array; the two target arrays default empty; `allowMaterializedUrls` is `true` only when explicitly set and otherwise normalizes to `false`. No other method is admitted, and a fetch target cannot be JavaScript. |
|
|
205
|
+
| `edges.cacheOpens` | `{modulePath,occurrence,edgePolicy,cacheName,targetPaths}`. `artifact-targets-admitted` requires at least one exact non-JavaScript file path; `inactive-runtime-branch-rejected` requires none. The returned cache can read only those files. |
|
|
206
|
+
| `transforms` | `{kind,modulePath,occurrence}`. `function-return-this-to-global-this` replaces the one audited `Function("return this")()` pattern. `typed-array-constructor` rewrites only a scanner-recognized typed-array `.constructor(...)` call and later proves the receiver uses an intrinsic typed-array prototype. |
|
|
207
|
+
|
|
208
|
+
An omitted `edgePolicy` normalizes to `artifact-targets-admitted`, which
|
|
209
|
+
requires a declared target. An
|
|
210
|
+
`inactive-runtime-branch-rejected` edge has no target and proves only that the
|
|
211
|
+
branch must remain inactive; execution of that occurrence rejects. The source
|
|
212
|
+
scanner rejects undeclared imports, fetches, Workers, executable-string
|
|
213
|
+
construction or constructor access, Cache Storage access outside a direct
|
|
214
|
+
declared `caches.open(...)`, computed capability access, ambiguous tokens, and
|
|
215
|
+
unmatched transforms. It also reserves the SDK guard name so artifact code
|
|
216
|
+
cannot address the guard directly. Static import cycles are rejected so
|
|
217
|
+
materialization order remains deterministic; runtime isolation separately
|
|
218
|
+
denies every raw transport listed below.
|
|
219
|
+
|
|
220
|
+
The returned graph is deeply frozen and has exactly
|
|
221
|
+
`{protocol,kind,providerId,role,model,runtime,files,edges,transforms,identitySha256,artifactGraphStatus}`.
|
|
222
|
+
The status is `artifact-graph-descriptor-verified`. Its computed identity binds
|
|
223
|
+
every preceding descriptor field, including paths, revisions, licenses,
|
|
224
|
+
runtime aliases, edge policy, and transform occurrences; the status itself is
|
|
225
|
+
the result of that computation rather than identity input.
|
|
95
226
|
|
|
96
227
|
## `createDbopfsSpeechArtifactStore()`
|
|
97
228
|
|
|
@@ -104,226 +235,1012 @@ createDbopfsSpeechArtifactStore({
|
|
|
104
235
|
} = {})
|
|
105
236
|
```
|
|
106
237
|
|
|
107
|
-
|
|
108
|
-
|
|
238
|
+
The frozen store exposes `{protocol,tableName,prepare,remove}`. It accepts both
|
|
239
|
+
the authenticated graph above and an SDK-created legacy authority.
|
|
240
|
+
`objectUrlFactory` remains a legacy compatibility seam. Graph preparation
|
|
241
|
+
ignores it and uses module-captured native Blob URL creation, revocation, and
|
|
242
|
+
fetch so a caller cannot substitute the executable materialization boundary.
|
|
109
243
|
|
|
110
|
-
`prepare(
|
|
244
|
+
For a graph, `prepare(graph,{signal,onProgress,offline=false,security})` follows
|
|
245
|
+
the shared model-security flag and requires explicit `secure:true`. The graph is
|
|
246
|
+
the opt-in strict path: it enables byte-length, SHA-256, and undeclared-
|
|
247
|
+
capability enforcement. Ordinary warn-first operation uses the direct
|
|
248
|
+
`model`/`runtime` authority described below and does not construct or admit an
|
|
249
|
+
artifact graph.
|
|
111
250
|
|
|
112
|
-
|
|
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.
|
|
251
|
+
### Cold admission
|
|
120
252
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
`
|
|
253
|
+
1. Acquire the exact authority's exclusive Web Lock.
|
|
254
|
+
2. Delete incomplete prior state.
|
|
255
|
+
3. Fetch only each declared immutable `sourceUrl` using `credentials:"omit"`,
|
|
256
|
+
`cache:"no-store"`, `mode:"cors"`, and `referrerPolicy:"no-referrer"`.
|
|
257
|
+
The default is `redirect:"error"`; only a file with declared
|
|
258
|
+
`redirectFinalOrigins` uses `redirect:"follow"`.
|
|
259
|
+
4. Without a followed redirect, require the response URL to remain exactly the
|
|
260
|
+
immutable `sourceUrl`. After a followed redirect, require a readable final
|
|
261
|
+
HTTPS URL without credentials or a fragment and require its canonical origin
|
|
262
|
+
to occur in that file's declared final-origin inventory.
|
|
263
|
+
5. Require the response Content-Type to equal `sourceMediaType` (which defaults
|
|
264
|
+
to `mediaType`), then stream exact byte-length and SHA-256 verification into
|
|
265
|
+
DBOPFS.
|
|
266
|
+
6. Reopen and rehash every persisted file.
|
|
267
|
+
7. Decode and scan every runtime JavaScript file and prove exact edge/transform
|
|
268
|
+
closure.
|
|
269
|
+
8. Persist `arcane.ai.browser-speech.authenticated-artifact-graph.v1` only
|
|
270
|
+
after every file and the complete runtime graph pass.
|
|
125
271
|
|
|
126
|
-
|
|
272
|
+
The returned admission is
|
|
273
|
+
`artifact-graph-network-dbopfs-verified`. A failure before manifest completion
|
|
274
|
+
removes the graph's incomplete records.
|
|
127
275
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
appSecurity,
|
|
135
|
-
security,
|
|
136
|
-
store,
|
|
137
|
-
offline = false
|
|
138
|
-
} = {})
|
|
139
|
-
```
|
|
276
|
+
`redirectFinalOrigins` admits only a final origin, not a final path, query, or
|
|
277
|
+
signed/expiring URL. The browser may follow such an implementation-specific
|
|
278
|
+
final URL, but that URL is neither persisted nor accepted as source, revision,
|
|
279
|
+
signature, graph identity, or future download authority. Trust remains bound to
|
|
280
|
+
the immutable starting `sourceUrl` and the exact authenticated length and
|
|
281
|
+
SHA-256 of the received bytes.
|
|
140
282
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
283
|
+
Browser Fetch exposes the final CORS response, not an inspectable list of every
|
|
284
|
+
intermediate redirect hop. The SDK therefore cannot authenticate intermediate
|
|
285
|
+
hop origins or headers. CORS must succeed for the browser-managed chain, and
|
|
286
|
+
the SDK can enforce only the immutable start, the declared final HTTPS origin,
|
|
287
|
+
the final response metadata, and the end-to-end bytes. A caller that requires
|
|
288
|
+
every hop to be independently pinned must use a direct immutable source rather
|
|
289
|
+
than this redirect opt-in.
|
|
144
290
|
|
|
145
|
-
|
|
291
|
+
### Warm and offline admission
|
|
146
292
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
293
|
+
A warm prepare requires the exact manifest authority and file count, reopens
|
|
294
|
+
every DBOPFS record, checks the manifest's observed bytes and declared SHA-256,
|
|
295
|
+
rehashes every file, and rescans the runtime graph before returning
|
|
296
|
+
`artifact-graph-dbopfs-cache-verified`.
|
|
297
|
+
|
|
298
|
+
`offline:true` runs the same cache verification and never calls the source
|
|
299
|
+
fetch function. It returns
|
|
300
|
+
`artifact-graph-offline-dbopfs-cache-verified`, or rejects with code
|
|
301
|
+
`ARCANE_AI_ARTIFACT_GRAPH_OFFLINE_CACHE_MISS` and reason
|
|
302
|
+
`artifact-graph-offline-cache-miss`. There is no network repair, runtime CDN,
|
|
303
|
+
private Cache Storage fallback, or partial-cache admission.
|
|
304
|
+
|
|
305
|
+
The manifest authority binds each file's `sourceMediaType` and
|
|
306
|
+
`redirectFinalOrigins` through the graph identity. A valid warm or offline
|
|
307
|
+
admission does not resolve the starting URL again, follow a redirect, or reuse a
|
|
308
|
+
prior final URL; it authenticates only the complete cached bytes and graph.
|
|
309
|
+
|
|
310
|
+
After every cold, warm, or offline admission, the store materializes a fresh
|
|
311
|
+
set of unique native `blob:` URLs. Each URL is fetched back with omitted
|
|
312
|
+
credentials and redirect rejection, and its exact URL identity, media type,
|
|
313
|
+
byte length, and SHA-256 are compared with the Blob that was created. Only then
|
|
314
|
+
does the SDK apply the already-scanned deterministic module rewrites. A fresh
|
|
315
|
+
cryptographically random 32-byte lowercase-hex guard capability binds every
|
|
316
|
+
rewritten dynamic import, fetch, cache-open, child-Worker, and typed-array call
|
|
317
|
+
for that materialization. The capability is ephemeral: it is neither supplied
|
|
318
|
+
by the caller nor persisted in the manifest or graph identity.
|
|
319
|
+
|
|
320
|
+
Successful graph preparation returns:
|
|
321
|
+
|
|
322
|
+
```text
|
|
323
|
+
{
|
|
324
|
+
cache, // the exact graph admission value
|
|
325
|
+
artifactGraphId,
|
|
326
|
+
artifactGraphAdmission,
|
|
327
|
+
runtime: {
|
|
328
|
+
...normalizedRuntime,
|
|
329
|
+
files, edges, transforms,
|
|
330
|
+
guardCapability,
|
|
331
|
+
artifactGraphId,
|
|
332
|
+
artifactGraphAdmission
|
|
333
|
+
},
|
|
334
|
+
model: {...normalizedModel, files},
|
|
335
|
+
release
|
|
161
336
|
}
|
|
162
337
|
```
|
|
163
338
|
|
|
164
|
-
`
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
339
|
+
`release()` revokes the materialized object URLs after Worker termination. It
|
|
340
|
+
does not delete the caller-owned DBOPFS cache. `remove(graph)` is the explicit
|
|
341
|
+
cache-deletion operation.
|
|
342
|
+
|
|
343
|
+
## Authenticated Worker host
|
|
344
|
+
|
|
345
|
+
Graph loading creates one dedicated Worker for the selected role. Its first
|
|
346
|
+
load envelope transfers a new private `MessagePort`; all graph responses,
|
|
347
|
+
progress, cancellation settlement, and later operations stay on that port.
|
|
348
|
+
Graph loading rejects if `MessageChannel`/`MessagePort` is unavailable, if a
|
|
349
|
+
legacy global transport was already selected, or if the Worker receives a graph
|
|
350
|
+
load without the private port. The published single-module compatibility path
|
|
351
|
+
continues to use the original Worker-global message transport.
|
|
352
|
+
|
|
353
|
+
Before importing the entrypoint, the graph Worker installs these fail-closed
|
|
354
|
+
boundaries:
|
|
355
|
+
|
|
356
|
+
- exact graph routes map declared source URLs, runtime aliases, and materialized
|
|
357
|
+
URLs to already authenticated object URLs;
|
|
358
|
+
- the ephemeral guard capability must match at every rewritten call;
|
|
359
|
+
- global `fetch` rejects unless the scanned source was rewritten to one
|
|
360
|
+
declared fetch edge;
|
|
361
|
+
- global Cache Storage `open` and `match` reject unless the scanned
|
|
362
|
+
`caches.open(...)` was rewritten to one exact declared cache-open edge; its
|
|
363
|
+
returned read-only cache serves only `targetPaths`, while `put`, `add`, and
|
|
364
|
+
`addAll` reject, so DBOPFS remains the sole durable store;
|
|
365
|
+
- a `typed-array-constructor` rewrite returns only the intrinsic constructor of
|
|
366
|
+
a verified typed-array receiver; an own or non-intrinsic `constructor`
|
|
367
|
+
rejects;
|
|
368
|
+
- the `Function`, `AsyncFunction`, `GeneratorFunction`, and
|
|
369
|
+
`AsyncGeneratorFunction` prototype constructor escape is replaced before
|
|
370
|
+
import, and string callbacks to `setTimeout` or `setInterval` reject;
|
|
371
|
+
- `indexedDB` and `navigator.storage`/OPFS are made unavailable;
|
|
372
|
+
- raw `BroadcastChannel`, `EventSource`, `Function`, `RTCPeerConnection`,
|
|
373
|
+
`ShadowRealm`, `SharedWorker`, `WebSocket`, `WebSocketStream`, `WebTransport`,
|
|
374
|
+
`Worker`, `XMLHttpRequest`, `eval`, and `importScripts` capabilities are
|
|
375
|
+
denied; and
|
|
376
|
+
- an admitted child module Worker is created through the SDK's role Worker,
|
|
377
|
+
receives the authenticated graph configuration, installs the same guard, and
|
|
378
|
+
imports only its declared materialized target.
|
|
379
|
+
|
|
380
|
+
An immutable `sourceUrl` may be an explicitly caller-selected HTTPS origin,
|
|
381
|
+
but runtime execution cannot escalate to that or another network origin. Its
|
|
382
|
+
declared request is answered from authenticated local object bytes, and any
|
|
383
|
+
other request or import edge rejects.
|
|
384
|
+
|
|
385
|
+
### ONNX Runtime Web configuration
|
|
386
|
+
|
|
387
|
+
The Worker accepts only the two mechanically verified namespace shapes:
|
|
171
388
|
|
|
172
|
-
|
|
389
|
+
- Kokoro: `namespace.env.wasmPaths = {mjs,wasm}`. No Kokoro cache setting or
|
|
390
|
+
thread setting is invented. A missing property rejects as
|
|
391
|
+
`kokoro-env-wasm-paths-unavailable`; a property that rejects or does not
|
|
392
|
+
retain the exact assignment rejects as
|
|
393
|
+
`kokoro-env-wasm-paths-assignment-rejected`.
|
|
394
|
+
- Transformers: `namespace.env.backends.onnx.wasm.wasmPaths = {mjs,wasm}`.
|
|
395
|
+
The Worker also requires the verified outer `env` fields, sets
|
|
396
|
+
`allowLocalModels:false`, `allowRemoteModels:true`, `useBrowserCache:false`,
|
|
397
|
+
and `useFSCache:false`. With no admitted `cacheOpens` edge named exactly
|
|
398
|
+
`transformers-cache`, it assigns `useCustomCache:false` and `customCache:null`.
|
|
399
|
+
With exactly one such edge it assigns `useCustomCache:true` and the
|
|
400
|
+
target-limited read-only graph facade; more than one rejects as ambiguous.
|
|
401
|
+
Only a caller-declared STT `numThreads` is assigned. The
|
|
402
|
+
`allowRemoteModels` value permits the audited library code path to issue its
|
|
403
|
+
declared request; the graph guard still prevents network access and serves
|
|
404
|
+
only exact local graph routes.
|
|
405
|
+
|
|
406
|
+
For Transformers, the exact missing-field reasons are
|
|
407
|
+
`transformers-env-backends-onnx-wasm-unavailable`,
|
|
408
|
+
`transformers-env-allow-local-models-unavailable`,
|
|
409
|
+
`transformers-env-allow-remote-models-unavailable`,
|
|
410
|
+
`transformers-env-browser-cache-unavailable`,
|
|
411
|
+
`transformers-env-fs-cache-unavailable`,
|
|
412
|
+
`transformers-env-custom-cache-toggle-unavailable`, and
|
|
413
|
+
`transformers-env-custom-cache-unavailable`. The corresponding exact
|
|
414
|
+
assignment-rejection reasons are
|
|
415
|
+
`transformers-env-allow-local-models-assignment-rejected`,
|
|
416
|
+
`transformers-env-allow-remote-models-assignment-rejected`,
|
|
417
|
+
`transformers-env-browser-cache-assignment-rejected`,
|
|
418
|
+
`transformers-env-fs-cache-assignment-rejected`,
|
|
419
|
+
`transformers-env-custom-cache-toggle-assignment-rejected`, and
|
|
420
|
+
`transformers-env-custom-cache-assignment-rejected`. The optional, creatable
|
|
421
|
+
ONNX fields fail assignment as
|
|
422
|
+
`transformers-env-wasm-paths-assignment-rejected` or
|
|
423
|
+
`transformers-env-num-threads-assignment-rejected`; their defensive
|
|
424
|
+
unavailable reasons are `transformers-env-wasm-paths-unavailable` and
|
|
425
|
+
`transformers-env-num-threads-unavailable`. Every case rejects with
|
|
426
|
+
`ARCANE_AI_PROVIDER_UNAVAILABLE`; the Worker never guesses a different
|
|
427
|
+
namespace shape.
|
|
428
|
+
|
|
429
|
+
Kokoro's audited bundle hard-codes a mutable
|
|
430
|
+
`.../resolve/main/voices/${voice}.bin` request and opens `kokoro-voices` Cache
|
|
431
|
+
Storage. That URL is never accepted as `sourceUrl`. An operational graph must
|
|
432
|
+
declare the exact resolved voice file as an immutable authenticated source,
|
|
433
|
+
bind the hard-coded URL only as that file's `runtimeRequestUrls` alias, and
|
|
434
|
+
declare the exact `cacheOpens` occurrence with `cacheName:"kokoro-voices"` and
|
|
435
|
+
the caller-owned voice paths. Every scanned fetch occurrence still requires its
|
|
436
|
+
own explicit admitted or inactive policy. The Worker satisfies the cache read
|
|
437
|
+
from verified local voice bytes; it never opens Kokoro's private durable cache.
|
|
438
|
+
If the graph does not prove those exact edges, Kokoro fails closed before the
|
|
439
|
+
mutable request can reach the network.
|
|
440
|
+
|
|
441
|
+
That graph closure is an optional caller-owned secure/offline configuration,
|
|
442
|
+
not the public runtime's default and not a publication gate. In warn-first mode
|
|
443
|
+
the SDK loads the caller-selected version-pinned upstream package and provider
|
|
444
|
+
assets from their publishers. The SDK neither republishes those bytes nor
|
|
445
|
+
requires their optional provenance or legal metadata before the provider can
|
|
446
|
+
operate. When `secure:true` is selected, incomplete graph metadata rejects that
|
|
447
|
+
specific secure load without disabling ordinary warn-first operation.
|
|
448
|
+
|
|
449
|
+
## Providers
|
|
173
450
|
|
|
174
451
|
```text
|
|
452
|
+
createBrowserWhisperProvider({
|
|
453
|
+
id = 'arcane-browser-whisper',
|
|
454
|
+
localOnly = true,
|
|
455
|
+
graph?,
|
|
456
|
+
model?, runtime?,
|
|
457
|
+
store,
|
|
458
|
+
offline = false,
|
|
459
|
+
appSecurity,
|
|
460
|
+
security
|
|
461
|
+
} = {})
|
|
462
|
+
|
|
175
463
|
createBrowserKokoroProvider({
|
|
176
464
|
id = 'arcane-browser-kokoro',
|
|
177
465
|
localOnly = true,
|
|
178
|
-
|
|
179
|
-
runtime
|
|
180
|
-
appSecurity,
|
|
181
|
-
security,
|
|
466
|
+
graph?,
|
|
467
|
+
model?, runtime?,
|
|
182
468
|
store,
|
|
183
|
-
offline = false
|
|
469
|
+
offline = false,
|
|
470
|
+
appSecurity,
|
|
471
|
+
security
|
|
184
472
|
} = {})
|
|
185
473
|
```
|
|
186
474
|
|
|
187
|
-
|
|
188
|
-
|
|
475
|
+
`graph` is mutually exclusive with the legacy `model`/`runtime` options and may
|
|
476
|
+
load only when effective security explicitly selects `secure:true`. Both
|
|
477
|
+
constructors require an SDK-created DBOPFS speech store and return one frozen
|
|
478
|
+
`arcane-ai-provider/2` object:
|
|
189
479
|
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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);
|
|
480
|
+
```text
|
|
481
|
+
{
|
|
482
|
+
protocol, role, id, localOnly,
|
|
483
|
+
catalog, inspect, status, load, request, unload, dispose
|
|
205
484
|
}
|
|
206
485
|
```
|
|
207
486
|
|
|
208
|
-
`
|
|
209
|
-
|
|
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.
|
|
487
|
+
`localOnly` must remain `true`. `offline:true` makes every later explicit load
|
|
488
|
+
use strict offline graph/cache admission; it does not trigger a load itself.
|
|
218
489
|
|
|
219
|
-
|
|
490
|
+
`catalog()` exposes only the caller's selected model/runtime/files. A graph
|
|
491
|
+
catalog also reports `artifactGraphId`, caller dtype, exact sample rate, and the
|
|
492
|
+
caller voice inventory. Its one exact catalog record is
|
|
493
|
+
`{id,providerId,role,localOnly,defaultVoice?,repository,revision,dtype?,runtime,files,artifactGraphId?,voices?,speech}`;
|
|
494
|
+
the `speech` record is `{inputSampleRate}` for STT or
|
|
495
|
+
`{outputSampleRate,responseFormats:["wav"],defaultResponseFormat:"wav"}` for
|
|
496
|
+
TTS.
|
|
220
497
|
|
|
221
|
-
|
|
498
|
+
`inspect()` admits only the exact provider/model/local selection and, when
|
|
499
|
+
supplied, the matching role. A successful graph inspection returns
|
|
500
|
+
`{available:true,authority}`. Its frozen authority has exactly
|
|
501
|
+
`{protocol,admitted,graph,artifactGraphProtocol,providerId,role,modelId,repository,revision,dtype,defaultVoice,voices,inputSampleRate,outputSampleRate,runtime,files,security,artifactGraphId}`;
|
|
502
|
+
`protocol` is `arcane-ai-model-authority/1` and `artifactGraphId` is the graph
|
|
503
|
+
identity. An unavailable record uses
|
|
504
|
+
`ARCANE_AI_MODEL_AUTHORITY_REQUIRED` and the exact role-specific reason
|
|
505
|
+
`stt-provider-inspection-selection-authority-mismatch` or
|
|
506
|
+
`tts-provider-inspection-selection-authority-mismatch`. `load()` is explicit;
|
|
507
|
+
construction, catalog, status, and inspection never start a download or Worker.
|
|
222
508
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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.
|
|
509
|
+
### Whisper STT
|
|
510
|
+
|
|
511
|
+
The provider-native operation is:
|
|
246
512
|
|
|
247
513
|
```javascript
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
514
|
+
const result = await whisper.request({
|
|
515
|
+
role: 'stt',
|
|
516
|
+
operation: 'transcribe',
|
|
517
|
+
signal,
|
|
518
|
+
payload: {
|
|
519
|
+
audio: pcmFloat32,
|
|
520
|
+
sampleRate: graph.model.inputSampleRate
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
The native payload is exact `Float32Array` mono PCM at the graph's
|
|
526
|
+
caller-selected input sample rate. The result is `{text}`. The shared AI
|
|
527
|
+
payload `{audio:Blob|File,mimeType,model}` verifies the exact model, uses the
|
|
528
|
+
browser decoder to normalize to that same rate, and then enters the same Worker
|
|
529
|
+
operation. Multi-channel decoded audio is averaged to one mono `Float32Array`.
|
|
530
|
+
Cancellation during Blob/audio decoding rejects with
|
|
531
|
+
`ARCANE_AI_REQUEST_ABORTED` / `stt-transcription-cancelled` while the already
|
|
532
|
+
loaded Worker remains ready.
|
|
533
|
+
|
|
534
|
+
### Kokoro TTS
|
|
535
|
+
|
|
536
|
+
```javascript
|
|
537
|
+
const result = await kokoro.request({
|
|
538
|
+
role: 'tts',
|
|
539
|
+
operation: 'synthesize',
|
|
540
|
+
signal,
|
|
541
|
+
payload: {
|
|
542
|
+
text: 'Hello from Arcane.',
|
|
543
|
+
voice: 'caller-voice-id',
|
|
544
|
+
speed: 1
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
`voice` must belong to the graph's caller-declared inventory; omission uses
|
|
550
|
+
only that graph's `model.defaultVoice`. `speed` must be greater than zero and at
|
|
551
|
+
most four. The provider-native result is
|
|
552
|
+
`{audio:Float32Array,sampleRate,voice}` at the caller-selected output sample
|
|
553
|
+
rate. The shared AI payload `{model,input,responseFormat,voice?,speed?}` accepts
|
|
554
|
+
only `responseFormat:"wav"` and returns frozen
|
|
555
|
+
`{audio:Uint8Array,contentType:"audio/wav"}` containing mono signed 16-bit PCM
|
|
556
|
+
at the caller-selected output rate. No saved voice from another route is
|
|
557
|
+
substituted.
|
|
558
|
+
|
|
559
|
+
## Lifecycle, progress, cancellation, and cleanup
|
|
560
|
+
|
|
561
|
+
Provider `status()` returns:
|
|
562
|
+
|
|
563
|
+
```text
|
|
564
|
+
{
|
|
565
|
+
role,
|
|
566
|
+
providerId,
|
|
567
|
+
modelId,
|
|
568
|
+
state,
|
|
569
|
+
lifecycleStatus,
|
|
570
|
+
lifecycleReason,
|
|
571
|
+
activeOperation,
|
|
572
|
+
loaded,
|
|
573
|
+
busy,
|
|
574
|
+
generation,
|
|
575
|
+
errorCode,
|
|
576
|
+
cache,
|
|
577
|
+
artifactGraphId,
|
|
578
|
+
artifactGraphAdmission
|
|
261
579
|
}
|
|
262
580
|
```
|
|
263
581
|
|
|
264
|
-
The
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
582
|
+
The provider states are exactly `unloaded`, `loading`, `ready`, `unloading`,
|
|
583
|
+
`error`, and `disposed`. `lifecycleStatus` is therefore exactly one of
|
|
584
|
+
`stt-provider-unloaded`, `stt-provider-loading`, `stt-provider-ready`,
|
|
585
|
+
`stt-provider-unloading`, `stt-provider-error`, `stt-provider-disposed`,
|
|
586
|
+
`tts-provider-unloaded`, `tts-provider-loading`, `tts-provider-ready`,
|
|
587
|
+
`tts-provider-unloading`, `tts-provider-error`, or `tts-provider-disposed`.
|
|
588
|
+
|
|
589
|
+
`activeOperation` is `null` or one of `stt-provider-load`,
|
|
590
|
+
`tts-provider-load`, `stt-provider-transcription`, `tts-provider-synthesis`,
|
|
591
|
+
`stt-provider-unload`, `tts-provider-unload`, `stt-provider-dispose`, and
|
|
592
|
+
`tts-provider-dispose`.
|
|
593
|
+
|
|
594
|
+
`loaded` is true only for `ready`. `busy` reports an active transcription or
|
|
595
|
+
synthesis request; load, unload, and dispose remain visible through `state` and
|
|
596
|
+
`activeOperation`. `cache` is `null`, a graph admission value, or the legacy
|
|
597
|
+
`installed`/`cached` value. Graph identity and admission are otherwise `null`.
|
|
598
|
+
|
|
599
|
+
Provider-owned lifecycle reasons are:
|
|
600
|
+
|
|
601
|
+
- creation and load: `stt-provider-created`, `tts-provider-created`,
|
|
602
|
+
`stt-load-started`, `tts-load-started`, `stt-load-completed`,
|
|
603
|
+
`tts-load-completed`, `stt-load-cancelled`, `tts-load-cancelled`,
|
|
604
|
+
`stt-provider-load-rejected`, `tts-provider-load-rejected`,
|
|
605
|
+
`stt-load-rejected-during-unload`,
|
|
606
|
+
`tts-load-rejected-during-unload`,
|
|
607
|
+
`stt-load-superseded-by-security-change`,
|
|
608
|
+
`tts-load-superseded-by-security-change`,
|
|
609
|
+
`stt-load-superseded-by-unload`, `tts-load-superseded-by-unload`,
|
|
610
|
+
`stt-load-progress-callback-threw`, and
|
|
611
|
+
`tts-load-progress-callback-threw`;
|
|
612
|
+
- use: `stt-transcription-started`, `stt-transcription-completed`,
|
|
613
|
+
`stt-transcription-cancelled`,
|
|
614
|
+
`stt-transcription-engine-operation-rejected`,
|
|
615
|
+
`tts-synthesis-started`, `tts-synthesis-completed`,
|
|
616
|
+
`tts-synthesis-cancelled`, `tts-synthesis-engine-operation-rejected`,
|
|
617
|
+
`stt-transcription-superseded-by-unload`, and
|
|
618
|
+
`tts-synthesis-superseded-by-unload`;
|
|
619
|
+
- teardown: `stt-unload-started`, `tts-unload-started`,
|
|
620
|
+
`stt-unload-completed`, `tts-unload-completed`, `stt-dispose-started`,
|
|
621
|
+
`tts-dispose-started`, `stt-dispose-completed`, `tts-dispose-completed`,
|
|
622
|
+
`stt-worker-terminated-by-unload`, `tts-worker-terminated-by-unload`,
|
|
623
|
+
`stt-worker-terminated`, and `tts-worker-terminated`; and
|
|
624
|
+
- Worker failure: `stt-worker-crashed`, `tts-worker-crashed`,
|
|
625
|
+
`stt-worker-message-rejected`, `tts-worker-message-rejected`,
|
|
626
|
+
`stt-worker-private-message-rejected`,
|
|
627
|
+
`tts-worker-private-message-rejected`,
|
|
628
|
+
`stt-worker-progress-envelope-rejected`,
|
|
629
|
+
`tts-worker-progress-envelope-rejected`,
|
|
630
|
+
`stt-worker-response-envelope-shape-rejected`,
|
|
631
|
+
`tts-worker-response-envelope-shape-rejected`,
|
|
632
|
+
`stt-worker-error-envelope-rejected`, `tts-worker-error-envelope-rejected`,
|
|
633
|
+
`stt-worker-protocol-mismatch`, and
|
|
634
|
+
`tts-worker-protocol-mismatch`.
|
|
635
|
+
|
|
636
|
+
When an active load or use fails with one of the stable reasons below, the
|
|
637
|
+
provider preserves that exact reason as `lifecycleReason`; it does not collapse
|
|
638
|
+
the boundary to a generic failure label.
|
|
639
|
+
|
|
640
|
+
Worker statuses use exactly `stt-worker-unloaded`, `stt-worker-ready`,
|
|
641
|
+
`stt-worker-disposed`, `tts-worker-unloaded`, `tts-worker-ready`, and
|
|
642
|
+
`tts-worker-disposed`. The nested bootstrap status is exactly
|
|
643
|
+
`stt-artifact-module-worker-awaiting-initialization` or
|
|
644
|
+
`tts-artifact-module-worker-awaiting-initialization`.
|
|
645
|
+
|
|
646
|
+
Worker `activeOperation` is `null`, `stt-load`, `tts-load`,
|
|
647
|
+
`stt-transcription`, `tts-synthesis`, `stt-status`, `tts-status`, `stt-unload`,
|
|
648
|
+
`tts-unload`, `stt-dispose`, or `tts-dispose`. Its own lifecycle starts with
|
|
649
|
+
`stt-worker-created` or `tts-worker-created`. Load uses exactly
|
|
650
|
+
`stt-load-started`, `stt-load-completed`, `stt-load-cancelled`,
|
|
651
|
+
`stt-worker-runtime-configuration-rejected`,
|
|
652
|
+
`stt-worker-runtime-import-rejected`, `stt-worker-model-load-rejected`,
|
|
653
|
+
`tts-load-started`, `tts-load-completed`, `tts-load-cancelled`,
|
|
654
|
+
`tts-worker-runtime-configuration-rejected`,
|
|
655
|
+
`tts-worker-runtime-import-rejected`, and
|
|
656
|
+
`tts-worker-model-load-rejected`. Use uses exactly
|
|
657
|
+
`stt-transcription-started`, `stt-transcription-completed`,
|
|
658
|
+
`stt-transcription-cancelled`, `stt-transcription-engine-operation-rejected`,
|
|
659
|
+
`tts-synthesis-started`, `tts-synthesis-completed`,
|
|
660
|
+
`tts-synthesis-cancelled`, and `tts-synthesis-engine-operation-rejected`; a stable underlying
|
|
661
|
+
reason replaces only the matching failure fallback. Orderly Worker teardown
|
|
662
|
+
additionally uses `stt-unload-completed`,
|
|
663
|
+
`tts-unload-completed`, `stt-worker-engine-dispose-rejected`,
|
|
664
|
+
`tts-worker-engine-dispose-rejected`, `stt-dispose-unloaded-worker`,
|
|
665
|
+
`tts-dispose-unloaded-worker`, `stt-dispose-completed`, and
|
|
666
|
+
`tts-dispose-completed`. A Worker protocol cancel result is
|
|
667
|
+
`stt-cancel-target-not-active` or `tts-cancel-target-not-active` when its target
|
|
668
|
+
is already settled; otherwise it names the exact cancelled load, transcription,
|
|
669
|
+
synthesis, status, unload, or dispose operation.
|
|
670
|
+
|
|
671
|
+
The Worker client admits only `load`, `use`, `status`, `unload`, and `dispose`.
|
|
672
|
+
The transport host additionally admits only its internal `cancel` control
|
|
673
|
+
message. Any other `op` rejects as `ARCANE_AI_INVALID_REQUEST` with
|
|
674
|
+
message `The speech worker operation is not part of its protocol.` and reason
|
|
675
|
+
`stt-worker-operation-unknown` or `tts-worker-operation-unknown` before it can
|
|
676
|
+
enter active-operation, cancellation, or serialized-error naming.
|
|
677
|
+
|
|
678
|
+
Progress records have exactly `{phase,completed,total,unit,heartbeat}`. They do
|
|
679
|
+
not add a `role` field; Worker phase names carry the role and the provider
|
|
680
|
+
forwards the same provider-neutral record. Graph store phases are exactly
|
|
681
|
+
`artifact-graph-network-download`,
|
|
682
|
+
`artifact-graph-dbopfs-persisted-rehash`, and
|
|
683
|
+
`artifact-graph-dbopfs-cache-rehash`. Worker phases are
|
|
684
|
+
`stt-runtime-import-started`, `tts-runtime-import-started`,
|
|
685
|
+
`stt-model-load-started`, `tts-model-load-started`,
|
|
686
|
+
`stt-model-load-progress`, `tts-model-load-progress`,
|
|
687
|
+
`stt-provider-ready`, and `tts-provider-ready`.
|
|
688
|
+
|
|
689
|
+
`load(context)` requires the exact role/selection and a `progress` function.
|
|
690
|
+
Compatible concurrent loads coalesce behind one underlying preparation/Worker
|
|
691
|
+
operation while each caller keeps its own progress callback and cancellation
|
|
692
|
+
observation. Cancelling or throwing from the last observer aborts that shared
|
|
693
|
+
load; one observer cannot cancel another observer that remains attached. A
|
|
694
|
+
security change unloads and reloads; graph verification itself can never be
|
|
695
|
+
weakened. `request(context)` admits one role operation at a time and otherwise
|
|
696
|
+
rejects with `ARCANE_AI_PROVIDER_BUSY`.
|
|
697
|
+
|
|
698
|
+
An `AbortSignal` before or during graph preparation/load rejects that exact
|
|
699
|
+
operation. Once a Worker request has started, cancellation terminates the whole
|
|
700
|
+
role Worker, rejects every pending operation, closes private ports, terminates
|
|
701
|
+
nested Workers, discards that isolated Worker's guards and runtime settings,
|
|
702
|
+
revokes object URLs, and returns the provider to `unloaded`; a later request
|
|
703
|
+
requires explicit load. `unload()` uses the same destructive boundary for
|
|
704
|
+
active load/use before
|
|
705
|
+
releasing state. `dispose()` completes unload and permanently enters
|
|
706
|
+
`disposed`. Cancelling an `unload()` or `dispose()` caller rejects only that
|
|
707
|
+
caller's wait with the corresponding stable reason; the already-started shared
|
|
708
|
+
teardown continues to its terminal state. Late results are generation-checked
|
|
709
|
+
and cannot settle a superseded operation.
|
|
710
|
+
|
|
711
|
+
The provider owns no listener registry or event source. Applications may
|
|
712
|
+
project its promises, status, and progress records into the one SDK event/state
|
|
713
|
+
authority, and DOM components may project presentation/intent events, but this
|
|
714
|
+
package creates no `EventPubSub`, exposes no public `EventTarget` lifecycle
|
|
715
|
+
source, and owns no competing listener registry or event bus.
|
|
716
|
+
|
|
717
|
+
The provider also has no implicit mute flag. A higher-level shared state owner
|
|
718
|
+
can implement mute by awaiting the role's explicit `unload()` and unmute by
|
|
719
|
+
performing an explicit `load()`; it projects the returned status and progress
|
|
720
|
+
without inventing a second provider, listener registry, or background load.
|
|
721
|
+
|
|
722
|
+
## Stable errors and reasons
|
|
723
|
+
|
|
724
|
+
Operational graph, provider, client, and Worker rejections expose a stable
|
|
725
|
+
`code` and a concise `reason` naming the failed operation or boundary.
|
|
726
|
+
`ARCANE_AI_REQUEST_ABORTED` errors use `name:"AbortError"`; an arbitrary
|
|
727
|
+
caller `AbortSignal.reason` is retained only as `cause` and cannot replace the
|
|
728
|
+
stable public reason. Immediate JavaScript API-shape misuse can instead throw a
|
|
729
|
+
plain `TypeError` before an operation exists.
|
|
730
|
+
|
|
731
|
+
### Compatibility and provider codes
|
|
732
|
+
|
|
733
|
+
Worker failures cross the private port only in the exact envelope
|
|
734
|
+
`{protocol:"arcane-ai-speech-worker-error/1",code,message,reason}`. Its own-key
|
|
735
|
+
set must be exactly `code,message,protocol,reason`, every field must be a data
|
|
736
|
+
property rather than an accessor, `protocol` and `message` must match the
|
|
737
|
+
registered code, and the finite registered code/reason pair must match the
|
|
738
|
+
pending role and operation. A missing field, extra string or symbol key,
|
|
739
|
+
foreign value, accessor, or cross-role/cross-operation pairing is rejected and
|
|
740
|
+
the role Worker is terminated; arbitrary third-party error fields never become
|
|
741
|
+
public authority.
|
|
742
|
+
|
|
743
|
+
| Code | Exact caller-visible reasons |
|
|
744
|
+
| --- | --- |
|
|
745
|
+
| `ARCANE_AI_MODEL_AUTHORITY_REQUIRED` | `stt-provider-inspection-selection-authority-mismatch`, `tts-provider-inspection-selection-authority-mismatch`, `stt-load-selection-authority-mismatch`, `tts-load-selection-authority-mismatch`, `stt-provider-request-selection-authority-mismatch`, `tts-provider-request-selection-authority-mismatch`, `stt-provider-unload-selection-authority-mismatch`, `tts-provider-unload-selection-authority-mismatch`, `stt-provider-dispose-selection-authority-mismatch`, `tts-provider-dispose-selection-authority-mismatch`, `stt-transcription-model-authority-missing`, `stt-transcription-model-authority-mismatch`, `tts-synthesis-model-authority-missing`, `tts-synthesis-model-authority-mismatch`, `tts-synthesis-voice-not-declared` |
|
|
746
|
+
| `ARCANE_AI_INVALID_REQUEST` | The exact context/payload and Worker reasons enumerated immediately below this table. |
|
|
747
|
+
| `ARCANE_AI_NOT_READY` | `stt-provider-request-not-ready`, `tts-provider-request-not-ready`, `stt-transcription-rejected-before-load`, `tts-synthesis-rejected-before-load` |
|
|
748
|
+
| `ARCANE_AI_PROVIDER_BUSY` | `stt-provider-request-already-active`, `tts-provider-request-already-active` |
|
|
749
|
+
| `ARCANE_AI_PROVIDER_DISPOSED` | `stt-provider-load-rejected-after-dispose`, `tts-provider-load-rejected-after-dispose`, `stt-load-rejected-after-dispose`, `tts-load-rejected-after-dispose` |
|
|
750
|
+
| `ARCANE_AI_REQUEST_ABORTED` | `stt-provider-inspection-cancelled`, `tts-provider-inspection-cancelled`, `stt-load-cancelled`, `tts-load-cancelled`, `stt-transcription-cancelled`, `tts-synthesis-cancelled`, `stt-unload-cancelled`, `tts-unload-cancelled`, `stt-dispose-cancelled`, `tts-dispose-cancelled`, `stt-status-cancelled`, `tts-status-cancelled`, `artifact-graph-preparation-cancelled` |
|
|
751
|
+
| `ARCANE_AI_OPERATION_SUPERSEDED` | `stt-load-rejected-during-unload`, `tts-load-rejected-during-unload`, `stt-load-superseded-by-security-change`, `tts-load-superseded-by-security-change`, `stt-load-superseded-by-unload`, `tts-load-superseded-by-unload`, `stt-transcription-superseded-by-unload`, `tts-synthesis-superseded-by-unload`, `stt-worker-terminated-by-unload`, `tts-worker-terminated-by-unload`, `stt-worker-terminated`, `tts-worker-terminated`, `stt-worker-already-terminated`, `tts-worker-already-terminated` |
|
|
752
|
+
| `ARCANE_AI_AUDIO_DECODE_UNAVAILABLE` | `stt-browser-offline-audio-context-unavailable`, `stt-browser-offline-audio-context-construction-rejected`, `stt-browser-audio-decode-method-unavailable` |
|
|
753
|
+
| `ARCANE_AI_AUDIO_DECODE_FAILED` | `stt-browser-audio-decode-operation-rejected`, `stt-browser-decoded-audio-not-object`, `stt-browser-decoded-audio-sample-rate-mismatch`, `stt-browser-decoded-audio-frame-length-not-safe-integer`, `stt-browser-decoded-audio-empty`, `stt-browser-decoded-audio-channel-count-not-safe-integer`, `stt-browser-decoded-audio-channel-count-zero`, `stt-browser-decoded-audio-get-channel-data-not-function`, `stt-browser-decoded-audio-channel-read-rejected`, `stt-browser-decoded-audio-channel-not-float32-array`, `stt-browser-decoded-audio-channel-length-mismatch`, `stt-browser-decoded-audio-sample-non-finite` |
|
|
754
|
+
| `ARCANE_AI_UNSUPPORTED_RESPONSE_FORMAT` | `tts-synthesis-response-format-not-wav` |
|
|
755
|
+
| `ARCANE_AI_INVALID_PROVIDER_RESULT` | `stt-transcription-result-text-not-string`, `tts-synthesis-result-not-object`, `tts-synthesis-result-audio-not-float32-array`, `tts-synthesis-result-sample-rate-mismatch`, `tts-synthesis-result-audio-empty`, `tts-synthesis-result-wav-byte-length-overflow`, `tts-synthesis-pcm-result-not-float32array`, `tts-synthesis-pcm-sample-non-finite` |
|
|
756
|
+
| `ARCANE_AI_PROVIDER_LOAD_FAILED` | `stt-provider-load-rejected`, `tts-provider-load-rejected` |
|
|
757
|
+
| `ARCANE_AI_PROVIDER_REQUEST_FAILED` | `stt-worker-runtime-configuration-rejected`, `tts-worker-runtime-configuration-rejected`, `stt-worker-runtime-import-rejected`, `tts-worker-runtime-import-rejected`, `stt-worker-model-load-rejected`, `tts-worker-model-load-rejected`, `stt-transcription-engine-operation-rejected`, `tts-synthesis-engine-operation-rejected`, `stt-worker-engine-dispose-rejected`, `tts-worker-engine-dispose-rejected`, `stt-worker-dispose-rejected`, `tts-worker-dispose-rejected`, `stt-worker-status-rejected`, `tts-worker-status-rejected` |
|
|
758
|
+
| `ARCANE_AI_PROVIDER_UNAVAILABLE` | `speech-worker-fetch-unavailable`, `artifact-graph-fetch-constructor-unavailable`, `artifact-graph-negative-response-constructor-unavailable`, `artifact-graph-module-worker-constructor-unavailable`, `artifact-graph-onnx-wasm-pair-not-materialized`, `transformers-env-backends-onnx-wasm-unavailable`, `transformers-env-allow-local-models-unavailable`, `transformers-env-allow-local-models-assignment-rejected`, `transformers-env-allow-remote-models-unavailable`, `transformers-env-allow-remote-models-assignment-rejected`, `transformers-env-browser-cache-unavailable`, `transformers-env-browser-cache-assignment-rejected`, `transformers-env-fs-cache-unavailable`, `transformers-env-fs-cache-assignment-rejected`, `transformers-env-custom-cache-toggle-unavailable`, `transformers-env-custom-cache-toggle-assignment-rejected`, `transformers-env-custom-cache-unavailable`, `transformers-env-custom-cache-assignment-rejected`, `transformers-env-wasm-paths-unavailable`, `transformers-env-wasm-paths-assignment-rejected`, `transformers-env-num-threads-unavailable`, `transformers-env-num-threads-assignment-rejected`, `transformers-whisper-pipeline-export-missing`, `stt-transcription-method-unavailable`, `kokoro-env-wasm-paths-unavailable`, `kokoro-env-wasm-paths-assignment-rejected`, `kokoro-tts-constructor-export-missing`, `tts-synthesis-method-unavailable` |
|
|
759
|
+
| `ARCANE_AI_LOAD_PROGRESS_CALLBACK_THREW` | `stt-load-progress-callback-threw`, `tts-load-progress-callback-threw` at the public provider observer boundary |
|
|
760
|
+
| `ARCANE_AI_PROGRESS_CALLBACK_THREW` | `stt-load-progress-callback-threw`, `tts-load-progress-callback-threw` at the internal Worker-client callback boundary |
|
|
761
|
+
| `ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH` | `stt-worker-client-authority-mismatch`, `tts-worker-client-authority-mismatch`, `stt-worker-protocol-mismatch`, `tts-worker-protocol-mismatch`, `artifact-graph-private-message-port-established-too-late`, `stt-worker-runtime-transport-mode-mismatch`, `tts-worker-runtime-transport-mode-mismatch` |
|
|
762
|
+
| `ARCANE_AI_WORKER_CRASHED` | `stt-worker-crashed`, `tts-worker-crashed` |
|
|
763
|
+
| `ARCANE_AI_WORKER_MESSAGE_ERROR` | `stt-worker-message-rejected`, `tts-worker-message-rejected`, `stt-worker-private-message-rejected`, `tts-worker-private-message-rejected`, `stt-worker-progress-envelope-rejected`, `tts-worker-progress-envelope-rejected`, `stt-worker-response-envelope-shape-rejected`, `tts-worker-response-envelope-shape-rejected`, `stt-worker-error-envelope-rejected`, `tts-worker-error-envelope-rejected`, `stt-load-message-rejected`, `tts-load-message-rejected`, `stt-transcription-message-rejected`, `tts-synthesis-message-rejected`, `stt-status-message-rejected`, `tts-status-message-rejected`, `stt-unload-message-rejected`, `tts-unload-message-rejected`, `stt-dispose-message-rejected`, `tts-dispose-message-rejected`, `artifact-graph-private-message-channel-unavailable`, `artifact-graph-private-message-port-unavailable`, `artifact-graph-module-worker-error-envelope-rejected`, `artifact-graph-module-worker-initialization-message-rejected` |
|
|
764
|
+
| `ARCANE_AI_WORKER_MESSAGE_REJECTED` | `stt-worker-error-envelope-rejected`, `tts-worker-error-envelope-rejected` when the provider rejects a foreign or missing SDK error brand |
|
|
765
|
+
| `ARCANE_AI_UNDECLARED_ARTIFACT` | `speech-worker-artifact-request-method-rejected`, `speech-worker-artifact-request-undeclared`, `speech-worker-cache-open-rejected`, `speech-worker-cache-match-rejected`, `artifact-graph-cache-write-rejected`, `artifact-graph-runtime-request-url-malformed` |
|
|
766
|
+
| `ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID` | The exact Worker graph-configuration reasons enumerated below. |
|
|
767
|
+
| `ARCANE_AI_ARTIFACT_GRAPH_FETCH_EDGE_UNDECLARED` | `artifact-graph-fetch-edge-undeclared`, `artifact-graph-fetch-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-fetch-method-undeclared`, `artifact-graph-fetch-target-undeclared`, `artifact-graph-fetch-guard-bypassed` |
|
|
768
|
+
| `ARCANE_AI_ARTIFACT_GRAPH_IMPORT_EDGE_UNDECLARED` | `artifact-graph-dynamic-import-edge-undeclared`, `artifact-graph-dynamic-import-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-dynamic-import-target-undeclared` |
|
|
769
|
+
| `ARCANE_AI_ARTIFACT_GRAPH_CACHE_EDGE_UNDECLARED` | `artifact-graph-cache-open-edge-undeclared`, `artifact-graph-cache-open-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-cache-name-mismatch`, `artifact-graph-cache-read-target-undeclared`, `artifact-graph-cache-open-guard-bypassed`, `artifact-graph-cache-match-guard-bypassed` |
|
|
770
|
+
| `ARCANE_AI_ARTIFACT_GRAPH_WORKER_EDGE_UNDECLARED` | `artifact-graph-module-worker-edge-undeclared`, `artifact-graph-module-worker-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-module-worker-target-undeclared`, `artifact-graph-module-worker-type-mismatch` |
|
|
771
|
+
| `ARCANE_AI_ARTIFACT_GRAPH_ISOLATION_UNAVAILABLE` | The exact guard, typed-array, dynamic-code, timer, storage, and denied-capability reasons enumerated below. |
|
|
772
|
+
|
|
773
|
+
The exact provider context reasons under `ARCANE_AI_INVALID_REQUEST` are:
|
|
774
|
+
|
|
775
|
+
| Boundary | Exact reasons |
|
|
776
|
+
| --- | --- |
|
|
777
|
+
| Context is not an object | `stt-provider-inspection-context-not-object`, `tts-provider-inspection-context-not-object`, `stt-provider-load-context-not-object`, `tts-provider-load-context-not-object`, `stt-provider-request-context-not-object`, `tts-provider-request-context-not-object`, `stt-provider-unload-context-not-object`, `tts-provider-unload-context-not-object`, `stt-provider-dispose-context-not-object`, `tts-provider-dispose-context-not-object` |
|
|
778
|
+
| Role does not match | `stt-provider-inspection-role-mismatch`, `tts-provider-inspection-role-mismatch`, `stt-provider-load-role-mismatch`, `tts-provider-load-role-mismatch`, `stt-provider-request-role-mismatch`, `tts-provider-request-role-mismatch`, `stt-provider-unload-role-mismatch`, `tts-provider-unload-role-mismatch`, `stt-provider-dispose-role-mismatch`, `tts-provider-dispose-role-mismatch` |
|
|
779
|
+
| Signal is not an `AbortSignal` | `stt-provider-inspection-signal-not-abort-signal`, `tts-provider-inspection-signal-not-abort-signal`, `stt-provider-load-signal-not-abort-signal`, `tts-provider-load-signal-not-abort-signal`, `stt-provider-request-signal-not-abort-signal`, `tts-provider-request-signal-not-abort-signal`, `stt-provider-unload-signal-not-abort-signal`, `tts-provider-unload-signal-not-abort-signal`, `stt-provider-dispose-signal-not-abort-signal`, `tts-provider-dispose-signal-not-abort-signal` |
|
|
780
|
+
| Lifecycle context property read rejects | `stt-provider-unload-context-read-rejected`, `tts-provider-unload-context-read-rejected`, `stt-provider-dispose-context-read-rejected`, `tts-provider-dispose-context-read-rejected` |
|
|
781
|
+
|
|
782
|
+
The other exact provider request reasons under `ARCANE_AI_INVALID_REQUEST` are
|
|
783
|
+
`stt-load-progress-callback-not-function`,
|
|
784
|
+
`tts-load-progress-callback-not-function`, `stt-provider-operation-mismatch`,
|
|
785
|
+
`tts-provider-operation-mismatch`, `stt-transcription-payload-not-object`,
|
|
786
|
+
`tts-synthesis-payload-not-object`, and these eight structural payload reasons:
|
|
787
|
+
`stt-transcription-payload-not-plain-object`,
|
|
788
|
+
`stt-transcription-payload-field-unknown`,
|
|
789
|
+
`stt-transcription-payload-accessor-rejected`,
|
|
790
|
+
`stt-transcription-payload-required-field-missing`,
|
|
791
|
+
`tts-synthesis-payload-not-plain-object`,
|
|
792
|
+
`tts-synthesis-payload-field-unknown`,
|
|
793
|
+
`tts-synthesis-payload-accessor-rejected`, and
|
|
794
|
+
`tts-synthesis-payload-required-field-missing`.
|
|
795
|
+
|
|
796
|
+
The remaining exact provider input reasons are
|
|
797
|
+
`stt-transcription-blob-constructor-unavailable`,
|
|
798
|
+
`stt-transcription-audio-not-blob-or-file`,
|
|
799
|
+
`stt-transcription-audio-blob-empty`,
|
|
800
|
+
`stt-transcription-mime-type-not-string`,
|
|
801
|
+
`stt-transcription-mime-type-malformed`,
|
|
802
|
+
`stt-transcription-audio-blob-mime-type-not-string`,
|
|
803
|
+
`stt-transcription-audio-blob-mime-type-malformed`,
|
|
804
|
+
`stt-transcription-audio-blob-mime-type-mismatch`,
|
|
805
|
+
`stt-transcription-audio-not-float32-array`,
|
|
806
|
+
`stt-transcription-pcm-input-empty`,
|
|
807
|
+
`stt-transcription-sample-rate-mismatch`,
|
|
808
|
+
`stt-transcription-pcm-sample-non-finite`, `tts-synthesis-text-empty`,
|
|
809
|
+
`tts-synthesis-voice-empty`, and `tts-synthesis-speed-out-of-range`.
|
|
271
810
|
|
|
272
|
-
|
|
811
|
+
The exact Worker configuration/input reasons under
|
|
812
|
+
`ARCANE_AI_INVALID_REQUEST` are `speech-worker-configuration-missing`,
|
|
813
|
+
`speech-worker-runtime-selection-mismatch`, `speech-worker-model-id-empty`,
|
|
814
|
+
`speech-worker-model-repository-empty`, `speech-worker-model-revision-empty`,
|
|
815
|
+
`speech-worker-model-dtype-empty`, `speech-worker-runtime-entry-empty`,
|
|
816
|
+
`speech-worker-materialized-files-missing`,
|
|
817
|
+
`speech-runtime-entrypoint-not-materialized`,
|
|
818
|
+
`speech-model-sample-rate-not-positive-safe-integer`,
|
|
819
|
+
`tts-default-voice-empty`, `artifact-graph-materialized-file-not-object`,
|
|
820
|
+
`artifact-graph-materialized-path-empty`,
|
|
821
|
+
`artifact-graph-materialized-source-url-empty`,
|
|
822
|
+
`artifact-graph-materialized-module-url-empty`,
|
|
823
|
+
`artifact-graph-materialized-media-type-empty`,
|
|
824
|
+
`artifact-graph-runtime-request-routes-not-array`,
|
|
825
|
+
`artifact-graph-materialized-path-ambiguous`,
|
|
826
|
+
`artifact-graph-entrypoint-not-materialized`,
|
|
827
|
+
`stt-worker-message-envelope-shape-rejected`,
|
|
828
|
+
`tts-worker-message-envelope-shape-rejected`,
|
|
829
|
+
`stt-worker-operation-unknown`, `tts-worker-operation-unknown`,
|
|
830
|
+
`stt-transcription-audio-not-float32array`,
|
|
831
|
+
`stt-transcription-sample-rate-mismatch`, `tts-synthesis-text-empty`,
|
|
832
|
+
`tts-synthesis-voice-empty`, `tts-synthesis-voice-not-declared`, and
|
|
833
|
+
`tts-synthesis-speed-out-of-range`.
|
|
273
834
|
|
|
274
|
-
|
|
835
|
+
The exact `ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID` reasons are
|
|
836
|
+
`artifact-graph-worker-configuration-incomplete`,
|
|
837
|
+
`artifact-graph-onnx-wasm-configuration-mismatch`,
|
|
838
|
+
`artifact-graph-kokoro-voice-inventory-missing`,
|
|
839
|
+
`artifact-graph-negative-request-routes-not-array`,
|
|
840
|
+
`artifact-graph-runtime-request-route-ambiguous`,
|
|
841
|
+
`artifact-graph-module-worker-target-not-materialized`,
|
|
842
|
+
`artifact-graph-transform-kind-not-admitted`,
|
|
843
|
+
`artifact-graph-transform-module-path-empty`,
|
|
844
|
+
`artifact-graph-transform-occurrence-not-positive-safe-integer`,
|
|
845
|
+
`artifact-graph-transform-identity-ambiguous`,
|
|
846
|
+
`artifact-graph-typed-array-constructor-transform-undeclared`,
|
|
847
|
+
`artifact-graph-transformers-cache-edge-ambiguous`,
|
|
848
|
+
`kokoro-env-num-threads-field-not-exposed`, and
|
|
849
|
+
`transformers-env-num-threads-not-positive-safe-integer`. For each exact edge
|
|
850
|
+
subject `cache-open`, `dynamic-import`, `fetch`, and `module-worker`, that code
|
|
851
|
+
also admits the six exact endings `edges-not-array`, `edge-not-object`,
|
|
852
|
+
`edge-module-path-empty`, `edge-occurrence-not-positive-safe-integer`,
|
|
853
|
+
`edge-policy-not-admitted`, and `edge-identity-ambiguous`, joined as
|
|
854
|
+
`artifact-graph-{subject}-{ending}`.
|
|
855
|
+
|
|
856
|
+
`browser-speech-provider-error-reason-unmapped` is a fail-closed internal
|
|
857
|
+
sentinel for a provider error constructed without a mapped reason. No current
|
|
858
|
+
public operation deliberately selects it.
|
|
859
|
+
|
|
860
|
+
The published legacy authority/store code-to-reason pairs remain:
|
|
861
|
+
|
|
862
|
+
| Code | Exact compatibility reason |
|
|
275
863
|
| --- | --- |
|
|
276
|
-
| `
|
|
277
|
-
| `
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
281
|
-
| `
|
|
282
|
-
| `
|
|
283
|
-
| `
|
|
284
|
-
| `
|
|
285
|
-
| `
|
|
286
|
-
| `
|
|
287
|
-
| `
|
|
288
|
-
| `
|
|
289
|
-
| `
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
|
300
|
-
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
-
|
|
305
|
-
-
|
|
306
|
-
-
|
|
307
|
-
|
|
308
|
-
-
|
|
309
|
-
|
|
310
|
-
-
|
|
311
|
-
|
|
312
|
-
-
|
|
313
|
-
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
`
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
864
|
+
| `ARCANE_AI_REQUEST_ABORTED` | `browser-speech-artifact-preparation-cancelled` |
|
|
865
|
+
| `ARCANE_AI_STORAGE_BUSY` | `browser-speech-artifact-dbopfs-write-lock-unavailable` |
|
|
866
|
+
| `ARCANE_AI_STORAGE_UNAVAILABLE` | `browser-speech-artifact-dbopfs-table-unavailable` |
|
|
867
|
+
| `ARCANE_AI_STORAGE_DELETE_FAILED` | `browser-speech-artifact-dbopfs-delete-rejected` |
|
|
868
|
+
| `ARCANE_AI_STORAGE_READ_FAILED` | `browser-speech-artifact-dbopfs-read-rejected` |
|
|
869
|
+
| `ARCANE_AI_ARTIFACT_SOURCE_INVALID` | `browser-speech-artifact-source-body-unreadable` |
|
|
870
|
+
| `ARCANE_AI_RUNTIME_MODULE_GRAPH_UNDECLARED` | `browser-speech-runtime-module-graph-undeclared` |
|
|
871
|
+
| `ARCANE_AI_ARTIFACT_SOURCE_UNAVAILABLE` | `browser-speech-artifact-fetch-unavailable` |
|
|
872
|
+
| `ARCANE_AI_ARTIFACT_DOWNLOAD_FAILED` | `browser-speech-artifact-fetch-rejected` |
|
|
873
|
+
| `ARCANE_AI_ARTIFACT_SOURCE_CHANGED` | `browser-speech-artifact-source-redirected` |
|
|
874
|
+
| `ARCANE_AI_ARTIFACT_SIZE_MISMATCH` | `browser-speech-artifact-byte-length-mismatch` |
|
|
875
|
+
| `ARCANE_AI_ARTIFACT_DIGEST_MISMATCH` | `browser-speech-artifact-sha256-mismatch` |
|
|
876
|
+
| `ARCANE_AI_ARTIFACT_CACHE_REJECTED` | `browser-speech-artifact-dbopfs-cache-rejected` |
|
|
877
|
+
| `ARCANE_AI_ARTIFACT_OFFLINE_MISS` | `browser-speech-artifact-offline-cache-miss` |
|
|
878
|
+
|
|
879
|
+
### Graph reason/code rule
|
|
880
|
+
|
|
881
|
+
Graph construction and store errors use
|
|
882
|
+
`code = "ARCANE_AI_" + reason.toUpperCase().replaceAll("-", "_")`. The
|
|
883
|
+
following closed reason groups therefore define their exact matching codes.
|
|
884
|
+
|
|
885
|
+
The redirect and source-response descriptor/runtime pairs are exactly:
|
|
886
|
+
|
|
887
|
+
| Reason | Code |
|
|
888
|
+
| --- | --- |
|
|
889
|
+
| `artifact-graph-file-source-media-type-missing` | `ARCANE_AI_ARTIFACT_GRAPH_FILE_SOURCE_MEDIA_TYPE_MISSING` |
|
|
890
|
+
| `artifact-graph-file-source-media-type-format-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_FILE_SOURCE_MEDIA_TYPE_FORMAT_MISMATCH` |
|
|
891
|
+
| `artifact-graph-source-redirect-final-origins-not-array` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGINS_NOT_ARRAY` |
|
|
892
|
+
| `artifact-graph-source-redirect-final-origin-inventory-empty` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_INVENTORY_EMPTY` |
|
|
893
|
+
| `artifact-graph-source-redirect-final-origin-text-required` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_TEXT_REQUIRED` |
|
|
894
|
+
| `artifact-graph-source-redirect-final-origin-whitespace-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_WHITESPACE_REJECTED` |
|
|
895
|
+
| `artifact-graph-source-redirect-final-origin-not-absolute` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_NOT_ABSOLUTE` |
|
|
896
|
+
| `artifact-graph-source-redirect-final-origin-protocol-not-https` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_PROTOCOL_NOT_HTTPS` |
|
|
897
|
+
| `artifact-graph-source-redirect-final-origin-credentials-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_CREDENTIALS_REJECTED` |
|
|
898
|
+
| `artifact-graph-source-redirect-final-origin-path-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_PATH_REJECTED` |
|
|
899
|
+
| `artifact-graph-source-redirect-final-origin-query-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_QUERY_REJECTED` |
|
|
900
|
+
| `artifact-graph-source-redirect-final-origin-fragment-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_FRAGMENT_REJECTED` |
|
|
901
|
+
| `artifact-graph-source-redirect-final-origin-duplicate` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_DUPLICATE` |
|
|
902
|
+
| `artifact-graph-source-response-url-unreadable` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_UNREADABLE` |
|
|
903
|
+
| `artifact-graph-source-redirected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECTED` |
|
|
904
|
+
| `artifact-graph-source-response-url-protocol-not-https` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_PROTOCOL_NOT_HTTPS` |
|
|
905
|
+
| `artifact-graph-source-response-url-credentials-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_CREDENTIALS_REJECTED` |
|
|
906
|
+
| `artifact-graph-source-response-url-fragment-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_FRAGMENT_REJECTED` |
|
|
907
|
+
| `artifact-graph-source-redirect-final-origin-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_MISMATCH` |
|
|
908
|
+
| `artifact-graph-source-response-url-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_MISMATCH` |
|
|
909
|
+
|
|
910
|
+
When an explicit `sourceMediaType` differs from `mediaType`, a cold response
|
|
911
|
+
mismatch uses the exact file-kind-specific pair below. When the two fields are
|
|
912
|
+
equal, the existing `*-media-type-mismatch` pair applies instead.
|
|
913
|
+
|
|
914
|
+
| Reason | Code |
|
|
915
|
+
| --- | --- |
|
|
916
|
+
| `artifact-graph-entrypoint-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_ENTRYPOINT_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
917
|
+
| `artifact-graph-runtime-auxiliary-javascript-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_RUNTIME_AUXILIARY_JAVASCRIPT_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
918
|
+
| `artifact-graph-runtime-wasm-binary-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_RUNTIME_WASM_BINARY_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
919
|
+
| `artifact-graph-runtime-opaque-data-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_RUNTIME_OPAQUE_DATA_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
920
|
+
| `artifact-graph-model-configuration-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_CONFIGURATION_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
921
|
+
| `artifact-graph-model-generation-configuration-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_GENERATION_CONFIGURATION_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
922
|
+
| `artifact-graph-model-onnx-binary-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_ONNX_BINARY_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
923
|
+
| `artifact-graph-model-onnx-external-data-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_ONNX_EXTERNAL_DATA_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
924
|
+
| `artifact-graph-model-opaque-data-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_OPAQUE_DATA_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
925
|
+
| `artifact-graph-model-preprocessor-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_PREPROCESSOR_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
926
|
+
| `artifact-graph-model-tokenizer-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_TOKENIZER_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
927
|
+
| `artifact-graph-voice-style-binary-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_VOICE_STYLE_BINARY_SOURCE_MEDIA_TYPE_MISMATCH` |
|
|
928
|
+
|
|
929
|
+
Descriptor and identity reasons:
|
|
930
|
+
|
|
931
|
+
- `artifact-graph-kind-mismatch`, `artifact-graph-role-not-stt-or-tts`,
|
|
932
|
+
`artifact-graph-provider-id-missing`,
|
|
933
|
+
`artifact-graph-provider-id-length-exceeded`,
|
|
934
|
+
`artifact-graph-model-descriptor-missing`,
|
|
935
|
+
`artifact-graph-runtime-descriptor-missing`,
|
|
936
|
+
`artifact-graph-file-inventory-missing`,
|
|
937
|
+
`artifact-graph-file-descriptor-not-object`,
|
|
938
|
+
`artifact-graph-file-kind-missing`,
|
|
939
|
+
`artifact-graph-file-kind-not-admitted`,
|
|
940
|
+
`artifact-graph-file-path-missing`,
|
|
941
|
+
`artifact-graph-file-path-noncanonical`,
|
|
942
|
+
`artifact-graph-file-revision-missing`,
|
|
943
|
+
`artifact-graph-file-revision-length-exceeded`,
|
|
944
|
+
`artifact-graph-file-byte-length-positive-safe-integer-required`,
|
|
945
|
+
`artifact-graph-file-sha256-missing`,
|
|
946
|
+
`artifact-graph-file-sha256-format-mismatch`,
|
|
947
|
+
`artifact-graph-file-license-missing`,
|
|
948
|
+
`artifact-graph-file-license-whitespace-rejected`,
|
|
949
|
+
`artifact-graph-file-license-not-nfc`,
|
|
950
|
+
`artifact-graph-file-license-control-character-rejected`,
|
|
951
|
+
`artifact-graph-file-license-length-exceeded`,
|
|
952
|
+
`artifact-graph-file-media-type-missing`,
|
|
953
|
+
`artifact-graph-file-media-type-format-mismatch`,
|
|
954
|
+
`artifact-graph-file-source-media-type-missing`,
|
|
955
|
+
`artifact-graph-file-source-media-type-format-mismatch`,
|
|
956
|
+
`artifact-graph-file-identity-ambiguous`,
|
|
957
|
+
`artifact-graph-source-url-missing`,
|
|
958
|
+
`artifact-graph-source-url-mutable`,
|
|
959
|
+
`artifact-graph-source-revision-unbound`,
|
|
960
|
+
`artifact-graph-source-redirect-final-origins-not-array`,
|
|
961
|
+
`artifact-graph-source-redirect-final-origin-inventory-empty`,
|
|
962
|
+
`artifact-graph-source-redirect-final-origin-text-required`,
|
|
963
|
+
`artifact-graph-source-redirect-final-origin-whitespace-rejected`,
|
|
964
|
+
`artifact-graph-source-redirect-final-origin-not-absolute`,
|
|
965
|
+
`artifact-graph-source-redirect-final-origin-protocol-not-https`,
|
|
966
|
+
`artifact-graph-source-redirect-final-origin-credentials-rejected`,
|
|
967
|
+
`artifact-graph-source-redirect-final-origin-path-rejected`,
|
|
968
|
+
`artifact-graph-source-redirect-final-origin-query-rejected`,
|
|
969
|
+
`artifact-graph-source-redirect-final-origin-fragment-rejected`,
|
|
970
|
+
`artifact-graph-source-redirect-final-origin-duplicate`,
|
|
971
|
+
`artifact-graph-javascript-media-type-mismatch`,
|
|
972
|
+
`artifact-graph-wasm-media-type-mismatch`,
|
|
973
|
+
`artifact-graph-json-media-type-mismatch`,
|
|
974
|
+
`artifact-graph-entrypoint-path-missing`,
|
|
975
|
+
`artifact-graph-entrypoint-path-noncanonical`,
|
|
976
|
+
`artifact-graph-entrypoint-file-kind-mismatch`,
|
|
977
|
+
`artifact-graph-entrypoint-count-mismatch`,
|
|
978
|
+
`artifact-graph-entrypoint-revision-mismatch`,
|
|
979
|
+
`artifact-graph-runtime-adapter-missing`,
|
|
980
|
+
`artifact-graph-runtime-adapter-role-mismatch`,
|
|
981
|
+
`artifact-graph-runtime-version-missing`,
|
|
982
|
+
`artifact-graph-runtime-version-length-exceeded`,
|
|
983
|
+
`artifact-graph-runtime-revision-missing`,
|
|
984
|
+
`artifact-graph-runtime-revision-length-exceeded`,
|
|
985
|
+
`artifact-graph-onnx-wasm-descriptor-missing`,
|
|
986
|
+
`artifact-graph-onnx-wasm-namespace-missing`,
|
|
987
|
+
`artifact-graph-onnx-wasm-namespace-role-mismatch`,
|
|
988
|
+
`artifact-graph-onnx-wasm-file-kind-mismatch`,
|
|
989
|
+
`artifact-graph-onnx-wasm-num-threads-positive-safe-integer-required`,
|
|
990
|
+
`artifact-graph-negative-runtime-routes-not-array`,
|
|
991
|
+
`artifact-graph-negative-runtime-route-duplicate`,
|
|
992
|
+
`artifact-graph-negative-runtime-route-ambiguous`,
|
|
993
|
+
`artifact-graph-model-id-missing`,
|
|
994
|
+
`artifact-graph-model-id-length-exceeded`,
|
|
995
|
+
`artifact-graph-model-repository-missing`,
|
|
996
|
+
`artifact-graph-model-repository-length-exceeded`,
|
|
997
|
+
`artifact-graph-model-revision-missing`,
|
|
998
|
+
`artifact-graph-model-revision-length-exceeded`,
|
|
999
|
+
`artifact-graph-model-dtype-missing`,
|
|
1000
|
+
`artifact-graph-model-dtype-length-exceeded`,
|
|
1001
|
+
`artifact-graph-sample-rate-missing`,
|
|
1002
|
+
`artifact-graph-sample-rate-positive-safe-integer-required`,
|
|
1003
|
+
`artifact-graph-default-voice-missing`,
|
|
1004
|
+
`artifact-graph-default-voice-length-exceeded`,
|
|
1005
|
+
`artifact-graph-default-voice-undeclared`,
|
|
1006
|
+
`artifact-graph-stt-voice-authority-declared`,
|
|
1007
|
+
`artifact-graph-stt-voice-file-declared`,
|
|
1008
|
+
`artifact-graph-voice-inventory-missing`,
|
|
1009
|
+
`artifact-graph-voice-descriptor-not-object`,
|
|
1010
|
+
`artifact-graph-voice-id-missing`,
|
|
1011
|
+
`artifact-graph-voice-id-length-exceeded`,
|
|
1012
|
+
`artifact-graph-voice-file-kind-mismatch`,
|
|
1013
|
+
`artifact-graph-voice-inventory-ambiguous`,
|
|
1014
|
+
`artifact-graph-voice-file-undeclared`,
|
|
1015
|
+
`artifact-graph-model-file-inventory-missing`,
|
|
1016
|
+
`artifact-graph-model-file-revision-mismatch`,
|
|
1017
|
+
`artifact-graph-file-unreachable`,
|
|
1018
|
+
`artifact-graph-runtime-request-routes-not-array`,
|
|
1019
|
+
`artifact-graph-runtime-request-url-text-required`,
|
|
1020
|
+
`artifact-graph-runtime-request-url-not-absolute`,
|
|
1021
|
+
`artifact-graph-runtime-request-url-protocol-not-https`,
|
|
1022
|
+
`artifact-graph-runtime-request-url-credentials-rejected`,
|
|
1023
|
+
`artifact-graph-runtime-request-url-fragment-rejected`,
|
|
1024
|
+
`artifact-graph-runtime-request-route-duplicate`,
|
|
1025
|
+
`artifact-graph-runtime-request-route-ambiguous`,
|
|
1026
|
+
`artifact-graph-runtime-request-route-unreachable`,
|
|
1027
|
+
`artifact-graph-negative-runtime-route-unreachable`,
|
|
1028
|
+
`artifact-graph-identity-sha256-text-required`,
|
|
1029
|
+
`artifact-graph-identity-sha256-format-mismatch`, and
|
|
1030
|
+
`artifact-graph-identity-sha256-mismatch`.
|
|
1031
|
+
|
|
1032
|
+
The lower-level field helpers retain the exact reasons
|
|
1033
|
+
`artifact-graph-field-text-required`, `artifact-graph-identifier-missing`,
|
|
1034
|
+
`artifact-graph-identifier-length-exceeded`, and
|
|
1035
|
+
`artifact-graph-positive-safe-integer-required`. A Kokoro thread declaration
|
|
1036
|
+
raises `kokoro-env-num-threads-field-not-exposed` at graph construction; the
|
|
1037
|
+
Worker retains that same reason under its defensive graph-configuration
|
|
1038
|
+
boundary if construction is bypassed.
|
|
1039
|
+
|
|
1040
|
+
Edge and transform reasons:
|
|
1041
|
+
|
|
1042
|
+
- `artifact-graph-edges-not-object`, `artifact-graph-edge-kind-not-admitted`,
|
|
1043
|
+
`artifact-graph-edge-list-not-array`,
|
|
1044
|
+
`artifact-graph-edge-not-object`, `artifact-graph-edge-module-path-missing`,
|
|
1045
|
+
`artifact-graph-edge-module-path-noncanonical`,
|
|
1046
|
+
`artifact-graph-edge-module-path-not-runtime-javascript`,
|
|
1047
|
+
`artifact-graph-edge-occurrence-positive-safe-integer-required`,
|
|
1048
|
+
`artifact-graph-edge-occurrence-duplicate`,
|
|
1049
|
+
`artifact-graph-edge-policy-not-admitted`,
|
|
1050
|
+
`artifact-graph-edge-targets-not-array`,
|
|
1051
|
+
`artifact-graph-edge-target-not-object`,
|
|
1052
|
+
`artifact-graph-edge-target-match-missing`,
|
|
1053
|
+
`artifact-graph-edge-target-match-not-admitted`,
|
|
1054
|
+
`artifact-graph-edge-target-path-missing`,
|
|
1055
|
+
`artifact-graph-edge-target-path-noncanonical`,
|
|
1056
|
+
`artifact-graph-edge-target-path-undeclared`,
|
|
1057
|
+
`artifact-graph-edge-target-specifier-missing`,
|
|
1058
|
+
`artifact-graph-edge-target-duplicate`,
|
|
1059
|
+
`artifact-graph-static-import-specifier-missing`,
|
|
1060
|
+
`artifact-graph-dynamic-import-policy-target-mismatch`,
|
|
1061
|
+
`artifact-graph-module-worker-policy-target-mismatch`,
|
|
1062
|
+
`artifact-graph-module-worker-self-target-mismatch`,
|
|
1063
|
+
`artifact-graph-fetch-method-not-get`,
|
|
1064
|
+
`artifact-graph-fetch-targets-not-array`,
|
|
1065
|
+
`artifact-graph-fetch-target-duplicate`,
|
|
1066
|
+
`artifact-graph-fetch-javascript-target-rejected`,
|
|
1067
|
+
`artifact-graph-fetch-negative-routes-not-array`,
|
|
1068
|
+
`artifact-graph-fetch-negative-route-undeclared`,
|
|
1069
|
+
`artifact-graph-fetch-targets-incomplete`,
|
|
1070
|
+
`artifact-graph-fetch-policy-target-mismatch`,
|
|
1071
|
+
`artifact-graph-cache-name-missing`,
|
|
1072
|
+
`artifact-graph-cache-targets-not-array`,
|
|
1073
|
+
`artifact-graph-cache-target-duplicate`,
|
|
1074
|
+
`artifact-graph-cache-javascript-target-rejected`,
|
|
1075
|
+
`artifact-graph-cache-policy-target-mismatch`,
|
|
1076
|
+
`artifact-graph-transforms-not-array`,
|
|
1077
|
+
`artifact-graph-transform-not-object`,
|
|
1078
|
+
`artifact-graph-transform-kind-not-admitted`, and
|
|
1079
|
+
`artifact-graph-transform-occurrence-duplicate`.
|
|
1080
|
+
|
|
1081
|
+
Runtime scan and materialization reasons:
|
|
1082
|
+
|
|
1083
|
+
- `artifact-graph-runtime-javascript-file-missing`,
|
|
1084
|
+
`artifact-graph-runtime-javascript-utf8-decode-rejected`,
|
|
1085
|
+
`artifact-graph-javascript-block-comment-unterminated`,
|
|
1086
|
+
`artifact-graph-javascript-escape-unterminated`,
|
|
1087
|
+
`artifact-graph-javascript-hexadecimal-escape-malformed`,
|
|
1088
|
+
`artifact-graph-javascript-unicode-code-point-escape-malformed`,
|
|
1089
|
+
`artifact-graph-javascript-unicode-code-point-out-of-range`,
|
|
1090
|
+
`artifact-graph-javascript-unicode-escape-malformed`,
|
|
1091
|
+
`artifact-graph-javascript-quoted-string-line-break-rejected`,
|
|
1092
|
+
`artifact-graph-javascript-quoted-string-unterminated`,
|
|
1093
|
+
`artifact-graph-javascript-regexp-line-break-rejected`,
|
|
1094
|
+
`artifact-graph-javascript-regexp-unterminated`,
|
|
1095
|
+
`artifact-graph-javascript-template-expression-unterminated`,
|
|
1096
|
+
`artifact-graph-javascript-template-literal-unterminated`,
|
|
1097
|
+
`artifact-graph-javascript-escaped-identifier-rejected`,
|
|
1098
|
+
`artifact-graph-runtime-fetch-direct-call-required`,
|
|
1099
|
+
`artifact-graph-runtime-fetch-receiver-not-global`,
|
|
1100
|
+
`artifact-graph-runtime-cache-open-direct-call-required`,
|
|
1101
|
+
`artifact-graph-runtime-cache-open-receiver-not-global`,
|
|
1102
|
+
`artifact-graph-runtime-worker-constructor-call-required`,
|
|
1103
|
+
`artifact-graph-runtime-worker-receiver-not-global`,
|
|
1104
|
+
`artifact-graph-runtime-guard-reference-reserved`,
|
|
1105
|
+
`artifact-graph-runtime-dynamic-code-undeclared`,
|
|
1106
|
+
`artifact-graph-runtime-computed-dynamic-code-undeclared`,
|
|
1107
|
+
`artifact-graph-runtime-constructor-dynamic-code-undeclared`,
|
|
1108
|
+
`artifact-graph-runtime-edge-undeclared`,
|
|
1109
|
+
`artifact-graph-runtime-edge-declaration-unmatched`,
|
|
1110
|
+
`artifact-graph-runtime-edge-occurrence-noncanonical`,
|
|
1111
|
+
`artifact-graph-static-import-specifier-mismatch`,
|
|
1112
|
+
`artifact-graph-static-import-specifier-unresolved`,
|
|
1113
|
+
`artifact-graph-static-import-target-unmaterialized`,
|
|
1114
|
+
`artifact-graph-runtime-static-import-cycle`,
|
|
1115
|
+
`artifact-graph-module-transform-overlap`,
|
|
1116
|
+
`artifact-graph-guard-capability-unavailable`,
|
|
1117
|
+
`artifact-graph-object-url-platform-unavailable`,
|
|
1118
|
+
`artifact-graph-object-url-scheme-not-blob`,
|
|
1119
|
+
`artifact-graph-object-url-identity-ambiguous`,
|
|
1120
|
+
`artifact-graph-object-url-readback-unavailable`,
|
|
1121
|
+
`artifact-graph-object-url-readback-http-status-rejected`,
|
|
1122
|
+
`artifact-graph-object-url-readback-identity-mismatch`,
|
|
1123
|
+
`artifact-graph-object-url-media-type-mismatch`,
|
|
1124
|
+
`artifact-graph-object-url-byte-length-mismatch`, and
|
|
1125
|
+
`artifact-graph-object-url-sha256-mismatch`.
|
|
1126
|
+
|
|
1127
|
+
Source, cache, and security reasons:
|
|
1128
|
+
|
|
1129
|
+
- `artifact-graph-load-security-contract-rejected`,
|
|
1130
|
+
`artifact-graph-source-fetch-rejected`,
|
|
1131
|
+
`artifact-graph-source-http-response-rejected`,
|
|
1132
|
+
`artifact-graph-source-redirected`,
|
|
1133
|
+
`artifact-graph-source-response-url-unreadable`,
|
|
1134
|
+
`artifact-graph-source-response-url-protocol-not-https`,
|
|
1135
|
+
`artifact-graph-source-response-url-credentials-rejected`,
|
|
1136
|
+
`artifact-graph-source-response-url-fragment-rejected`,
|
|
1137
|
+
`artifact-graph-source-redirect-final-origin-mismatch`,
|
|
1138
|
+
`artifact-graph-source-response-url-mismatch`,
|
|
1139
|
+
`artifact-graph-offline-cache-miss`, and
|
|
1140
|
+
`artifact-graph-preparation-cancelled`.
|
|
1141
|
+
|
|
1142
|
+
For an exact file verification failure, `reason` is
|
|
1143
|
+
`artifact-graph-{subject}-{boundary}`. `{subject}` is `entrypoint` for
|
|
1144
|
+
`runtime-entrypoint-javascript`; otherwise it is the exact file kind from the
|
|
1145
|
+
closed kind table. `{boundary}` is one of `media-type-mismatch`,
|
|
1146
|
+
`source-media-type-mismatch`, `byte-length-mismatch`, `sha256-mismatch`,
|
|
1147
|
+
`dbopfs-persisted-byte-length-mismatch`, or
|
|
1148
|
+
`dbopfs-persisted-sha256-mismatch`. `source-media-type-mismatch` occurs only
|
|
1149
|
+
when an explicit `sourceMediaType` differs from `mediaType`; otherwise a source
|
|
1150
|
+
Content-Type mismatch uses `media-type-mismatch`. This expansion produces the
|
|
1151
|
+
exact public code by the rule above; for example,
|
|
1152
|
+
`artifact-graph-entrypoint-sha256-mismatch` becomes
|
|
1153
|
+
`ARCANE_AI_ARTIFACT_GRAPH_ENTRYPOINT_SHA256_MISMATCH`.
|
|
1154
|
+
|
|
1155
|
+
The other exact isolation reasons are
|
|
1156
|
+
`artifact-graph-private-message-port-missing`,
|
|
1157
|
+
`artifact-graph-guard-global-collision`,
|
|
1158
|
+
`artifact-graph-guard-global-definition-rejected`,
|
|
1159
|
+
`artifact-graph-guard-capability-mismatch`,
|
|
1160
|
+
`artifact-graph-fetch-isolation-unavailable`,
|
|
1161
|
+
`artifact-graph-cache-isolation-unavailable`,
|
|
1162
|
+
`speech-worker-fetch-isolation-unavailable`,
|
|
1163
|
+
`speech-worker-cache-isolation-unavailable`,
|
|
1164
|
+
`artifact-graph-typed-array-validation-unavailable`,
|
|
1165
|
+
`artifact-graph-typed-array-constructor-receiver-not-typed-array`,
|
|
1166
|
+
`artifact-graph-typed-array-constructor-intrinsic-mismatch`,
|
|
1167
|
+
`artifact-graph-dynamic-code-constructor-rejected`,
|
|
1168
|
+
`artifact-graph-dynamic-code-constructor-isolation-unavailable`,
|
|
1169
|
+
`artifact-graph-setinterval-isolation-unavailable`,
|
|
1170
|
+
`artifact-graph-settimeout-isolation-unavailable`,
|
|
1171
|
+
`artifact-graph-setinterval-string-callback-rejected`,
|
|
1172
|
+
`artifact-graph-settimeout-string-callback-rejected`,
|
|
1173
|
+
`artifact-graph-indexeddb-isolation-unavailable`, and
|
|
1174
|
+
`artifact-graph-opfs-isolation-unavailable`.
|
|
1175
|
+
|
|
1176
|
+
The denied-capability Worker reasons are
|
|
1177
|
+
`artifact-graph-{capability}-capability-undeclared` and
|
|
1178
|
+
`artifact-graph-{capability}-isolation-unavailable`, where `{capability}` is
|
|
1179
|
+
exactly `broadcastchannel`, `eventsource`, `function`, `rtcpeerconnection`,
|
|
1180
|
+
`shadowrealm`, `sharedworker`, `websocket`, `websocketstream`, `webtransport`,
|
|
1181
|
+
`worker`, `xmlhttprequest`, `eval`, or `importscripts`.
|
|
1182
|
+
|
|
1183
|
+
## `createBrowserSpeechAuthority()` upstream package mode
|
|
1184
|
+
|
|
1185
|
+
`BROWSER_SPEECH_ARTIFACT_PROTOCOL` remains exactly
|
|
1186
|
+
`arcane-ai-browser-speech-artifacts/1`, and
|
|
1187
|
+
`createBrowserSpeechAuthority({providerId,role,model,runtime,security})`
|
|
1188
|
+
loads a caller-selected browser bundle from npm or another upstream package
|
|
1189
|
+
authority. The SDK stores only the downloaded application-selected entrypoint;
|
|
1190
|
+
the runtime uses its normal provider fetch and browser cache behavior. Its
|
|
1191
|
+
optional byte/SHA checks still resolve independently from SDK default to app,
|
|
1192
|
+
provider, and load scopes. Its cache values remain `installed` and `cached`,
|
|
1193
|
+
and its offline miss remains `ARCANE_AI_ARTIFACT_OFFLINE_MISS`.
|
|
1194
|
+
|
|
1195
|
+
The model descriptor is
|
|
1196
|
+
`{id,repository,revision,defaultVoice?,files?}`; `defaultVoice` is required only
|
|
1197
|
+
for `tts`. In default warn-first mode `files` may be omitted so the selected
|
|
1198
|
+
provider downloads its own model and voice assets. The runtime descriptor is
|
|
1199
|
+
`{adapter,version,revision,entry,wasmPaths?,files}` and its adapter is exactly
|
|
1200
|
+
`transformers-whisper` for `stt` or `kokoro-js` for `tts`. Every legacy file is
|
|
1201
|
+
`{path,url,bytes?,sha256?,mediaType?}` with a normalized relative path, a
|
|
1202
|
+
unique immutable URL containing the descriptor revision or SHA-256 identity,
|
|
1203
|
+
and optional positive byte length and SHA-256. Legacy SHA input is normalized
|
|
1204
|
+
to lowercase before validation and projection. `runtime.entry` must
|
|
1205
|
+
name the one `text/javascript` `.js` or `.mjs` runtime file. The frozen result
|
|
1206
|
+
is
|
|
1207
|
+
`{protocol,providerId,modelId,admitted,role,repository,revision,defaultVoice,runtime,files,security}`.
|
|
1208
|
+
|
|
1209
|
+
`runtime.wasmPaths` may name a version-pinned upstream npm CDN directory in
|
|
1210
|
+
warn-first mode. `secure:true` rejects remote `wasmPaths`, requires explicit
|
|
1211
|
+
model files, applies the closed-module scan, and replaces ordinary fetch/cache
|
|
1212
|
+
access with the admitted file map. The authenticated artifact graph remains an
|
|
1213
|
+
advanced strict-control option; it is not required for normal speech use.
|
|
1214
|
+
|
|
1215
|
+
## Security and ownership summary
|
|
1216
|
+
|
|
1217
|
+
- The SDK redistributes no speech runtime, model, voice, third-party license,
|
|
1218
|
+
or corresponding-source payload. Explicit `load()` resolves them from the
|
|
1219
|
+
caller-selected npm/package/provider authorities.
|
|
1220
|
+
- Default direct-authority operation is warn-first and preserves ordinary
|
|
1221
|
+
upstream fetch/cache behavior. An artifact graph is admitted only when
|
|
1222
|
+
`secure:true` explicitly opts into strict graph/file verification and
|
|
1223
|
+
capability isolation.
|
|
1224
|
+
- Every graph byte is caller-selected, immutable, exact-length, SHA-256 bound,
|
|
1225
|
+
revision bound, media-type bound, license-declaration bound, and reachable
|
|
1226
|
+
through one closed graph identity.
|
|
1227
|
+
- Redirects are rejected by default. An undeclared redirect, an undeclared or
|
|
1228
|
+
non-HTTPS final origin, a mutable starting source authority, an ambiguous
|
|
1229
|
+
path/route, an undeclared code/data edge, a raw network transport, a cache
|
|
1230
|
+
write, or an incomplete offline closure fails closed.
|
|
1231
|
+
- DBOPFS is the sole durable artifact store; the Worker sees only authenticated
|
|
1232
|
+
local object bytes and an exact read-only cache facade.
|
|
1233
|
+
- Runtime/model/sample-rate/default-voice/voice inventory and optional
|
|
1234
|
+
Transformers thread count remain caller authority. No hardware heuristic,
|
|
1235
|
+
hidden fallback, startup download, native/Core call, or cloud retry is added.
|
|
1236
|
+
- A completion manifest and SHA-256 prove consistency with the caller's graph;
|
|
1237
|
+
they are not independent publisher authenticity or complete license evidence.
|
|
1238
|
+
- The component resolution record is
|
|
1239
|
+
`browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json`; the detailed
|
|
1240
|
+
package/model audit is `docs/reference/ai/browser-speech-package-authority.json`.
|
|
1241
|
+
- Upstream publishers remain responsible for their distributed package and
|
|
1242
|
+
provider assets. Applications own selected model/voice policy and integration
|
|
1243
|
+
with the one shared SDK state/event owner.
|
|
327
1244
|
|
|
328
1245
|
## Related
|
|
329
1246
|
|
|
@@ -331,6 +1248,5 @@ generation so stale or cross-role messages cannot settle current work.
|
|
|
331
1248
|
- [Browser-WASM LLM](browser-wasm.md)
|
|
332
1249
|
- [AIProviderRuntime.js](../runtime-modules.md#aiproviderruntimejs)
|
|
333
1250
|
- [AIRuntimeState.js](../runtime-modules.md#airuntimestatejs)
|
|
334
|
-
- [PersistentAIChatSession.js](../runtime-modules.md#persistentaichatsessionjs)
|
|
335
1251
|
- [Availability and normalization](../availability-and-normalization.md)
|
|
336
1252
|
- [Protocol architecture](../protocols.md#portable-ai-provider-runtime)
|