arcane-os 0.2.0 → 0.2.2
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 +35 -0
- package/README.md +8 -8
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +5 -5
- package/browser-runtime/ai/browser-speech-providers.mjs +331 -25
- package/docs/architecture.md +2 -2
- package/docs/reference/README.md +79 -13
- package/docs/reference/ai/browser-speech.md +336 -0
- package/docs/reference/ai/browser-wasm.md +207 -82
- package/docs/reference/availability-and-normalization.md +30 -4
- package/docs/reference/behavioral-testing.md +4 -1
- package/docs/reference/cli.md +29 -10
- package/docs/reference/core/arcane-ai-contracts.md +43 -9
- package/docs/reference/inventory/package-api.json +110 -14
- package/docs/reference/inventory/runtime-components.json +19 -6
- package/docs/reference/inventory/runtime-modules.json +113 -9
- package/docs/reference/protocols.md +260 -38
- package/docs/reference/runtime-components.md +108 -15
- package/docs/reference/runtime-modules.md +422 -8
- package/docs/reference/sdk-api.md +626 -85
- package/package.json +1 -1
- package/runtime/ARCANE_RUNTIME_RELEASE.json +19 -19
- package/runtime/arcane/components/chat.html +288 -52
- package/runtime/arcane/components/speech.html +339 -15
- package/runtime/arcane/modules/AI.js +1245 -136
- package/runtime/arcane/modules/AIProviderRuntime.js +299 -30
- package/runtime/arcane/modules/AIRuntimeState.js +23 -4
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +93 -8
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +448 -24
- package/runtime/arcane/modules/LocalAIReadinessController.js +1 -1
- package/schemas/arcane-lock.schema.json +6 -4
- package/src/dev-server.mjs +29 -13
- package/src/doctor.mjs +1 -3
- package/src/import-map.mjs +134 -83
- package/src/packager/core.mjs +311 -39
- package/src/scaffold.mjs +45 -17
- package/src/templates/workspace-template.mjs +23 -4
- package/src/toolchain.mjs +10 -2
- package/src/workspace.mjs +177 -24
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
# Protocol and host architecture
|
|
2
2
|
|
|
3
3
|
This is the deep reference behind the compact availability notes elsewhere.
|
|
4
|
-
Application developers
|
|
5
|
-
|
|
4
|
+
Application developers should start with the
|
|
5
|
+
[availability and normalization guide](availability-and-normalization.md), call
|
|
6
|
+
one documented API, and treat the protocols below as implementation detail.
|
|
6
7
|
|
|
7
8
|
## Layer map
|
|
8
9
|
|
|
9
10
|
```text
|
|
10
11
|
application code
|
|
11
|
-
|-- Node SDK API
|
|
12
|
-
|-- EventManager
|
|
13
|
-
|
|
14
|
-
`--
|
|
15
|
-
|--
|
|
16
|
-
|--
|
|
17
|
-
|--
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`-- explicitly selected cloud APIs
|
|
12
|
+
|-- Node SDK API ----------------- arcane-cli-events/1 + SDK receipts
|
|
13
|
+
|-- EventManager ----------------- synchronous bus + arcane-event-stack/1
|
|
14
|
+
|-- browser-local AI ------------- WebGPU/WASM/Workers/DBOPFS; no Core grant
|
|
15
|
+
`-- globalThis.Arcane
|
|
16
|
+
|-- development host -------- development HTTP bridge
|
|
17
|
+
|-- Microsoft NT native ----- WebView2 host bridge
|
|
18
|
+
|-- Linux native ------------ WebKitGTK host bridge
|
|
19
|
+
`-- Android native ---------- Android WebView message bridge
|
|
20
|
+
|
|
|
21
|
+
`-- Arcane Core/provider boundary
|
|
22
|
+
|-- platform services
|
|
23
|
+
|-- ArcaneOllama loopback service
|
|
24
|
+
`-- explicitly selected cloud APIs
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
Each downward boundary can add authority and platform capability. None can be
|
|
@@ -103,25 +103,43 @@ imports such as:
|
|
|
103
103
|
import ollama from 'arcane/Ollama';
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
The authenticated physical-v1 tree lives entirely beneath `arcane/`.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
`
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
`
|
|
119
|
-
|
|
106
|
+
The authenticated physical-v1 tree lives entirely beneath `arcane/`. SDK
|
|
107
|
+
`0.2.1` projects it from two canonical release receipts:
|
|
108
|
+
|
|
109
|
+
| Canonical receipt | Source authority and protocol | Receipt inventory |
|
|
110
|
+
| --- | --- | --- |
|
|
111
|
+
| `runtime/ARCANE_RUNTIME_RELEASE.json` | `sdk-canonical`; `arcane/1`; builder `arcane-sdk-runtime-v1` | 160 files; 3,605,154 bytes; content SHA-256 `5b921d50b6a0cf36a13f7a7dedf96cd3a68104a322e5139136fd4197aa1ca7cb` |
|
|
112
|
+
| `browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json` | `arcane-os-sdk`; `arcane-sdk-browser-runtime/1`; builder `arcane-sdk-browser-runtime-v1` | 25 files; 9,279,974 bytes; content SHA-256 `a9715c4b3aef70ec4042e4738089568d6588877b29582e0f758ed83897b6814f` |
|
|
113
|
+
|
|
114
|
+
The runtime receipt is the current byte authority. Its Arcane OS
|
|
115
|
+
`c540014afe69f14cf5ae60493b7295f36dbcec64` / bundle `0.8.12` record is
|
|
116
|
+
`legacyProjection` provenance, not a second or newer runtime authority. The
|
|
117
|
+
browser receipt binds `event-pubsub` `6.1.0`, `strong-type` `2.0.0`, and
|
|
118
|
+
`@wllama/wllama` `3.6.0`, as well as the browser entry
|
|
119
|
+
`arcane-os/event-manager`. Runtime dependencies stay under
|
|
120
|
+
`arcane/dependencies/`; the SDK event and browser-AI closure stays under
|
|
121
|
+
`arcane/sdk/`. This URL-key separation prevents runtime and SDK dependency
|
|
122
|
+
versions from aliasing one another.
|
|
123
|
+
|
|
124
|
+
Those two receipt inventories contain 185 entries in total. That sum is a
|
|
125
|
+
release-inventory fact, not an import-map entry count and not an assertion about
|
|
126
|
+
one maintained example. The `0.2.1` map deterministically roots every admitted
|
|
127
|
+
top-level runtime ESM plus the authenticated SDK browser roots, then follows
|
|
128
|
+
those roots for runtime entities and dependency compatibility. Application
|
|
129
|
+
source imports do not select the 91 entries. Its public operation receipt is the
|
|
130
|
+
authority for the exact `imports`, `entryCount`, and `excludedModules`;
|
|
131
|
+
reached-file traversal is internal and is not exposed in that receipt. The
|
|
132
|
+
managed graph exposes `arcane-os/event-manager`, `arcane-os/ai/browser-wasm`,
|
|
133
|
+
and `arcane-os/ai/browser-speech`; dependency compatibility mappings are added
|
|
134
|
+
only when authenticated runtime or SDK root traversal observes them.
|
|
135
|
+
|
|
136
|
+
The focused physical targets remain stable when their bindings are reached:
|
|
120
137
|
|
|
121
138
|
| Browser specifier | Physical target |
|
|
122
139
|
| --- | --- |
|
|
123
140
|
| `arcane-os/event-manager` | `./arcane/sdk/event-manager.mjs` |
|
|
124
141
|
| `arcane-os/ai/browser-wasm` | `./arcane/sdk/ai/browser-wasm.mjs` |
|
|
142
|
+
| `arcane-os/ai/browser-speech` | `./arcane/sdk/ai/browser-speech.mjs` |
|
|
125
143
|
| `event-pubsub` | `./arcane/sdk/dependencies/event-pubsub/index.js` |
|
|
126
144
|
| `./node_modules/strong-type/index.js` | `./arcane/dependencies/strong-type/index.js` |
|
|
127
145
|
|
|
@@ -129,7 +147,50 @@ There is no `arcane-os` package-root mapping, bare `strong-type` mapping, or
|
|
|
129
147
|
catch-all `arcane/` prefix. Host-internal `CaseEvidenceIndexer.js` is explicitly
|
|
130
148
|
excluded; classic scripts, workers, stylesheets, and other non-ESM assets use
|
|
131
149
|
their documented URL or host loading contract rather than invented package
|
|
132
|
-
bindings.
|
|
150
|
+
bindings. Development serves the selected app plus the authenticated tree.
|
|
151
|
+
Packaging copies the same map, app entry, and physical bytes into `dist/<id>`;
|
|
152
|
+
targets never resolve through the consumer workspace's root `node_modules/`.
|
|
153
|
+
|
|
154
|
+
`generateImportMap()` is an internal toolchain operation, not a package export.
|
|
155
|
+
Its package path accepts the configured entry plus the deterministic included
|
|
156
|
+
`.html`/`.htm` document inventory. One transaction writes the artifact and the
|
|
157
|
+
same managed JSON into every admitted document. The receipt binds
|
|
158
|
+
`documentPaths`, `documentCount`, and `files`: artifact first, configured entry
|
|
159
|
+
second, then additional documents as `role:"document"`. The public CLI keeps
|
|
160
|
+
its existing two-option command and supplies only the selected entry; packaging
|
|
161
|
+
owns multi-page discovery.
|
|
162
|
+
|
|
163
|
+
An external package and development server expose the authenticated runtime
|
|
164
|
+
inventory at `/ARCANE_RUNTIME_PROJECTION.json`:
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
{
|
|
168
|
+
schemaVersion: 1,
|
|
169
|
+
kind: 'arcane-app-runtime-projection',
|
|
170
|
+
sdkVersion,
|
|
171
|
+
pathPrefix: 'arcane/',
|
|
172
|
+
fileCount,
|
|
173
|
+
totalBytes,
|
|
174
|
+
contentSha256,
|
|
175
|
+
files: [{path, bytes, sha256}]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The projection contains public paths relative to its declared
|
|
180
|
+
`pathPrefix:'arcane/'` (for example, `modules/...` and `sdk/...`), byte lengths,
|
|
181
|
+
and SHA-256 values and is itself bound by the packaged release inventory. It does
|
|
182
|
+
not expose the private `/ARCANE_APP_RELEASE.json` or replace the underlying
|
|
183
|
+
runtime/browser receipts. Missing, changed, forged, duplicated, or internally
|
|
184
|
+
inconsistent projection data fails `ARCANE_RUNTIME_PROJECTION_INVALID`.
|
|
185
|
+
|
|
186
|
+
External `validateWorkspace()` results also expose a frozen `sdkInstallation`
|
|
187
|
+
authority with exactly `dependencyName`, `packageSource`,
|
|
188
|
+
`canonicalPackageRoot`, `packageName`, `packageVersion`, `runtimeRoot`,
|
|
189
|
+
`browserRuntimeRoot`, `runtimeManifest`, and `browserRuntimeManifest`. A
|
|
190
|
+
workspace may use the canonical dependency name or one exact npm alias such as
|
|
191
|
+
`npm:arcane-os@0.2.1`; the physical package manifest must still identify
|
|
192
|
+
exactly as `arcane-os@0.2.1`. Canonical-plus-alias duplicates, multiple aliases,
|
|
193
|
+
links/junctions, indirect package roots, or version drift fail closed.
|
|
133
194
|
|
|
134
195
|
The imported module can be pure browser logic, standard-Web-API logic, or a
|
|
135
196
|
client of `globalThis.Arcane`. Import-map resolution is not a new Arcane wire
|
|
@@ -164,24 +225,28 @@ heartbeat is event telemetry only and never regenerates browser state.
|
|
|
164
225
|
</details>
|
|
165
226
|
|
|
166
227
|
<details>
|
|
167
|
-
<summary>SDK browser-runtime admission and exact receipt fields</summary>
|
|
228
|
+
<summary>SDK 0.2.1 browser-runtime admission and exact receipt fields</summary>
|
|
168
229
|
|
|
169
230
|
`arcane.lock.json.sdkBrowserRuntime` persists the trusted manifest path,
|
|
170
231
|
`manifestSha256`, `contentSha256`, `builder`, `sdkVersion`, and `source` record.
|
|
171
|
-
For SDK `0.1
|
|
232
|
+
For SDK `0.2.1`, the manifest itself records:
|
|
172
233
|
|
|
173
234
|
```text
|
|
174
235
|
manifest: node_modules/arcane-os/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json
|
|
175
|
-
|
|
176
|
-
|
|
236
|
+
fileCount: 25
|
|
237
|
+
totalBytes: 9279974
|
|
238
|
+
contentSha256: a9715c4b3aef70ec4042e4738089568d6588877b29582e0f758ed83897b6814f
|
|
177
239
|
builder: arcane-sdk-browser-runtime-v1
|
|
178
|
-
sdkVersion: 0.1
|
|
240
|
+
sdkVersion: 0.2.1
|
|
179
241
|
source.protocol: arcane-sdk-browser-runtime/1
|
|
180
242
|
source.browserEntry: arcane-os/event-manager
|
|
181
243
|
```
|
|
182
244
|
|
|
183
|
-
The `
|
|
184
|
-
|
|
245
|
+
The verifier computes `manifestSha256` over the exact installed manifest and
|
|
246
|
+
binds that value in its process-local receipt and the workspace lock; it must
|
|
247
|
+
not be substituted with `contentSha256`. The `source` record also binds the
|
|
248
|
+
`arcane-os-sdk` authority/repository and the exact `event-pubsub` 6.1.0,
|
|
249
|
+
`strong-type` 2.0.0, and `@wllama/wllama` 3.6.0 package identities. Before a
|
|
185
250
|
workspace tree is admitted, the same-process verifier returns
|
|
186
251
|
`schemaVersion`, `kind`, `canonicalLocation`, `rootIdentity`, `manifestPath`,
|
|
187
252
|
`manifestSha256`, `manifestIdentity`, `builder`, `sdkVersion`, `source`,
|
|
@@ -192,6 +257,163 @@ does not recreate authority.
|
|
|
192
257
|
|
|
193
258
|
</details>
|
|
194
259
|
|
|
260
|
+
## Portable AI provider runtime
|
|
261
|
+
|
|
262
|
+
Application code should select a normalized role, not an internal protocol.
|
|
263
|
+
The exported
|
|
264
|
+
[`getAIProviderRuntime()` singleton](runtime-modules.md#aiproviderruntimejs)
|
|
265
|
+
comes from authenticated runtime bytes and owns independent `llm`, `stt`, and
|
|
266
|
+
`tts` selections. Published SDK `0.2.1` ships browser-WASM LLM and browser
|
|
267
|
+
speech provider/2 adapters but predates the legacy speech correction described
|
|
268
|
+
below. Current source also adapts selected legacy OpenAI LLM/STT/TTS,
|
|
269
|
+
Core-backed Ollama LLM, and admitted Core speech STT/TTS routes into provider/2;
|
|
270
|
+
other native, Core, or cloud routes require an externally supplied compatible
|
|
271
|
+
adapter. The singleton itself is not an authentication or capability token. It
|
|
272
|
+
normalizes inspection, model authority,
|
|
273
|
+
load/unload/dispose, cancellation, stream cleanup, status, and startup
|
|
274
|
+
barriers. Each selected provider retains its real execution requirements.
|
|
275
|
+
`localOnly` fails closed, and failure in one role never authorizes a Core,
|
|
276
|
+
cloud, or different-provider fallback.
|
|
277
|
+
|
|
278
|
+
For a browser-only LLM,
|
|
279
|
+
[`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) exposes `createArcaneAI()`
|
|
280
|
+
and an adapter into the same provider-neutral lifecycle. For browser speech,
|
|
281
|
+
[`arcane-os/ai/browser-speech`](ai/browser-speech.md) creates independent
|
|
282
|
+
Whisper STT and Kokoro TTS providers that register directly with the normalized
|
|
283
|
+
runtime. The SDK supplies mechanism; applications retain model/runtime choice,
|
|
284
|
+
provenance, licenses, prompts, tools, voices, and disclosure policy.
|
|
285
|
+
|
|
286
|
+
### Browser-WASM LLM lifecycle
|
|
287
|
+
|
|
288
|
+
The shipped browser receipt contains the authenticated Wllama JavaScript/WASM
|
|
289
|
+
engine and its provider/cache/controller mechanism. It contains no model
|
|
290
|
+
weights, default model catalog, CDN fallback, native provider, speech model, or
|
|
291
|
+
application profile. The caller supplies each model as a source authority with
|
|
292
|
+
a nonempty ordered file list, so monolithic and split GGUF models use the same
|
|
293
|
+
contract. HTTPS redirects are followed and the final HTTPS URL is recorded.
|
|
294
|
+
Exact bytes are bound only by the optional expected byte lengths and SHA-256
|
|
295
|
+
values whose matching fieldwise security checks are enabled.
|
|
296
|
+
|
|
297
|
+
On load, the DBOPFS store admits all ordered members and commits the completion
|
|
298
|
+
manifest last. A normal cache miss may fetch only the caller-supplied immutable
|
|
299
|
+
HTTPS sources; `offline:true` performs no model request and admits only a
|
|
300
|
+
compatible completed cache, otherwise it rejects with
|
|
301
|
+
`ARCANE_AI_MODEL_OFFLINE_MISS`. Unload releases the active Wllama session but
|
|
302
|
+
does not silently delete the app-owned cache.
|
|
303
|
+
|
|
304
|
+
SDK `0.2.1` requires WebGPU. Load requests full offload with exactly 99,999 GPU
|
|
305
|
+
layers and admits the model only after observing an adapter, full layer offload,
|
|
306
|
+
buffer and queue work, and a settled fence. `navigator.gpu` presence alone is
|
|
307
|
+
not readiness. There is no CPU fallback, partial-offload success mode, or
|
|
308
|
+
silent switch to native/Core/cloud inference.
|
|
309
|
+
|
|
310
|
+
### Browser speech lifecycle
|
|
311
|
+
|
|
312
|
+
The browser-speech package contains plain-JavaScript authority, DBOPFS store,
|
|
313
|
+
provider, client, and Worker machinery. It supplies no Whisper or Kokoro
|
|
314
|
+
runtime adapter bytes, model weights, voice bytes, download URL, catalog, or
|
|
315
|
+
cloud fallback. The caller must provide a closed immutable runtime/model
|
|
316
|
+
declaration for each role. Construction validates and freezes its declared
|
|
317
|
+
identity; preparation validates the actual downloaded or cached closed runtime
|
|
318
|
+
graph. The SDK downloads only declared files when permitted, commits its
|
|
319
|
+
completion manifest last, and removes incomplete stored state after a
|
|
320
|
+
cache/install failure. `offline:true` never uses the
|
|
321
|
+
network and rejects a cache miss with `ARCANE_AI_ARTIFACT_OFFLINE_MISS`.
|
|
322
|
+
|
|
323
|
+
Whisper `stt` and Kokoro `tts` each own catalog, inspect, status, load, request,
|
|
324
|
+
unload, and dispose state. They load, cancel, unload, fail, and recover
|
|
325
|
+
independently from the LLM and from one another. Cancellation after Worker use
|
|
326
|
+
begins terminates that role's Worker slot and returns the provider to unloaded;
|
|
327
|
+
a later use must load it again. If shared STT `Blob` decoding is cancelled
|
|
328
|
+
before Worker use, the request rejects while the loaded provider remains ready.
|
|
329
|
+
Speech failure neither disables text chat nor retries through another local,
|
|
330
|
+
native, or cloud provider.
|
|
331
|
+
|
|
332
|
+
### Persistent chat and document context
|
|
333
|
+
|
|
334
|
+
The SDK runtime owns
|
|
335
|
+
[`DBOPFSDocumentLibrary`](runtime-modules.md#dbopfsdocumentlibraryjs),
|
|
336
|
+
[`DocumentLexicalSearch`](runtime-modules.md#documentlexicalsearchjs), and
|
|
337
|
+
[`PersistentAIChatSession`](runtime-modules.md#persistentaichatsessionjs).
|
|
338
|
+
Document bootstrap is explicit and schema-driven, commits a completed
|
|
339
|
+
generation last, and returns bounded search results with partial read failures
|
|
340
|
+
disclosed. `evaluate()` can instead score a caller-owned source set without
|
|
341
|
+
persisting its bodies, under separate corpus/scoring/output/document budgets.
|
|
342
|
+
A chat session never searches the corpus unless the application
|
|
343
|
+
deliberately wires a document context builder into the request; generated
|
|
344
|
+
document context remains labeled untrusted.
|
|
345
|
+
|
|
346
|
+
Persistent chat maintains bounded live model context plus `ChatEntity`
|
|
347
|
+
history/memory according to the caller's persistence choice. A turn with
|
|
348
|
+
`persist:false` remains coherent in the live session without entering durable
|
|
349
|
+
history or memory. `createArcaneAI(...).createChatSession(options)` binds the
|
|
350
|
+
session and automatic memory work to that same selected LLM controller; it does
|
|
351
|
+
not select a second provider or storage fallback.
|
|
352
|
+
|
|
353
|
+
### Cancellation and structural tools
|
|
354
|
+
|
|
355
|
+
Cancellation is part of the provider lifecycle, not just a UI decision.
|
|
356
|
+
`AbortSignal`, the normalized role cancel operation, and stream-handle
|
|
357
|
+
`cancel(reason)` propagate to the selected provider. Browser-WASM inference
|
|
358
|
+
requires positive llama cancellation acknowledgement when cancellation is
|
|
359
|
+
required. Browser speech cancellation terminates a Worker only after Worker use
|
|
360
|
+
has begun; cancellation during shared browser decoding leaves the loaded Worker
|
|
361
|
+
ready. Unload always cancels active role work before releasing that role's
|
|
362
|
+
execution state, and superseded late results are rejected rather than committed
|
|
363
|
+
or retried through another provider.
|
|
364
|
+
|
|
365
|
+
Interactive request ownership is latest-request-wins independently for each
|
|
366
|
+
role. A new valid request that reaches admission aborts the active role request
|
|
367
|
+
and waits for its provider promise settlement; stream replacement additionally
|
|
368
|
+
requires confirmed bounded handle cleanup. Only the newest waiting request may
|
|
369
|
+
start after settlement, and request-specific generations prevent superseded
|
|
370
|
+
callbacks from clearing or restoring newer state. The runtime revalidates
|
|
371
|
+
selected-provider readiness and never reloads, switches, or falls back
|
|
372
|
+
implicitly. Generic provider-promise settlement is not a claim that underlying
|
|
373
|
+
work stopped; only a provider's documented positive acknowledgement or
|
|
374
|
+
destructive worker teardown can prove that stronger fact.
|
|
375
|
+
|
|
376
|
+
`startAIRuntime({startTranscription:false})` is the default startup boundary for
|
|
377
|
+
STT. It declines to request a startup STT load; it does not unload a role already
|
|
378
|
+
started through another explicit lifecycle action. A selected unloaded
|
|
379
|
+
transcription provider remains selected and unloaded until a user lifecycle
|
|
380
|
+
intent or explicit `startTranscription:true` opt-in asks the provider owner to
|
|
381
|
+
load it. Neither state observation nor the shared speech component imports a
|
|
382
|
+
model or selects a fallback.
|
|
383
|
+
|
|
384
|
+
The shared speech component owns an `AbortController` for each STT request and
|
|
385
|
+
passes its signal through `AI.fetchSTT()`. Cancel, superseding capture, and
|
|
386
|
+
component teardown abort that signal and suppress late delivery. Whether the
|
|
387
|
+
provider's underlying computation stops remains governed by its own
|
|
388
|
+
cancellation contract. User TTS unmute calls `AI.setSpeechMuted(false)` before
|
|
389
|
+
or with its load intent so the runtime records the unmuted lifecycle preference;
|
|
390
|
+
mute calls `AI.setSpeechMuted(true)`, cancels active synthesis, and unloads TTS.
|
|
391
|
+
The selected TTS model catalog owns `defaultVoice`. AI.js uses a saved OpenAI
|
|
392
|
+
voice only for the OpenAI route and never forwards it to Core or browser Kokoro.
|
|
393
|
+
|
|
394
|
+
LLM tool calls are structural result data only. The SDK never executes a
|
|
395
|
+
handler. The application owns schema validation, authorization, side-effect
|
|
396
|
+
policy, dispatch, and the matching tool-result turn.
|
|
397
|
+
|
|
398
|
+
<details>
|
|
399
|
+
<summary>Portable AI protocol disclosure</summary>
|
|
400
|
+
|
|
401
|
+
The normalized runtime protocol is `arcane-ai-runtime/2`; registered adapters
|
|
402
|
+
implement `arcane-ai-provider/2` and must prove matching
|
|
403
|
+
`arcane-ai-model-authority/1` inspection before load. The browser-WASM component
|
|
404
|
+
receipt is `arcane-ai-browser-wasm/2`; its direct controller adapter uses
|
|
405
|
+
`arcane-ai-adapter/1`, and `adaptV1LlmProvider()` projects that surface into the
|
|
406
|
+
provider/2 LLM role. Browser speech stores identify themselves as
|
|
407
|
+
`arcane-ai-browser-speech-artifacts/1`; that identifier describes the store
|
|
408
|
+
contract, not a model authority, capability grant, or complete-cache receipt.
|
|
409
|
+
|
|
410
|
+
These identifiers normalize lifecycle records. They do not erase provider
|
|
411
|
+
availability: browser providers still require their browser capabilities,
|
|
412
|
+
native providers still require an admitted host and Core method, and cloud
|
|
413
|
+
providers still require explicit selection, network policy, and credentials.
|
|
414
|
+
|
|
415
|
+
</details>
|
|
416
|
+
|
|
195
417
|
## Arcane application protocol
|
|
196
418
|
|
|
197
419
|
`globalThis.Arcane.protocol` is `arcane/1`. The shared API wraps transport
|
|
@@ -29,7 +29,7 @@ A component file does not register its own custom element. The `<html-import>` h
|
|
|
29
29
|
| [`assistant-panel.html`](#assistant-panelhtml) | Reusable assistant drawer, message area, composer, pending/streaming/empty/error state, and actions. | `open()`<br>`close()`<br>`toggle()`<br>`send()`<br>`clear()`<br>`setState()`<br>`focusComposer()`<br>`scrollToEnd()` | `assistant-ready`<br>`assistant-send`<br>`assistant-clear` | DOM-normalized; caller/provider results remain external |
|
|
30
30
|
| [`calculator.html`](#calculatorhtml) | Calculator keypad and result/error event surface backed by CalculatorEngine. | `calculate()` | `calculator-ready`<br>`calculation-complete`<br>`calculation-error` | Normalized Calculation/error events |
|
|
31
31
|
| [`chart.html`](#charthtml) | Accessible uPlot line, area, or point chart with normalized options and rows. | `configure()`<br>`populate()`<br>`setData()`<br>`addData()`<br>`update()`<br>`destroy()` | `chart-ready`<br>`chart-remove` | Options/rows normalized; uPlot rendering is vendor-native |
|
|
32
|
-
| [`chat.html`](#chathtml) | Shared chat, file upload, streaming, speech, language, availability, and conversation-timebox surface. | `streamMessage()`<br>`setMessageProgress()`<br>`setAIAvailability()`<br>`setInitialSpeechMuted()`<br>`setConversationComplete()`<br>`bindConversationTimebox()`<br>`submitMessage()`<br>`sendMessage()`<br>`languageChanged()` | `chat-ready`<br>`chat-send-message`<br>`chat-send-error`<br>`chat-file-uploaded`<br>`chat-language-changed`<br>`conversation-timebox-error` | UI state normalized; AI/storage/media behavior mixed |
|
|
32
|
+
| [`chat.html`](#chathtml) | Shared chat, visible selected-model activation request, file upload, streaming, speech, language, availability, and conversation-timebox surface. | `streamMessage()`<br>`setMessageProgress()`<br>`setAIAvailability()`<br>`setInitialSpeechMuted()`<br>`setConversationComplete()`<br>`bindConversationTimebox()`<br>`submitMessage()`<br>`sendMessage()`<br>`languageChanged()`<br>`requestAIActivation()`<br>`destroy()` | `chat-ready`<br>`chat-send-message`<br>`chat-send-error`<br>`chat-file-uploaded`<br>`chat-language-changed`<br>`chat-ai-activation-request`<br>`chat-ai-activation-error`<br>`conversation-timebox-error` | UI/runtime state and explicit user activation intent normalized; AI/storage/media behavior mixed |
|
|
33
33
|
| [`conversation-view.html`](#conversation-viewhtml) | Provider-neutral conversation display, advisory actions, composer, busy state, and status. | `setConversation()`<br>`setBusy()`<br>`setStatus()`<br>`clearComposer()` | `conversation-view-ready`<br>`communication-send`<br>`communication-advisory-action` | DOM-normalized |
|
|
34
34
|
| [`dashboard-config.html`](#dashboard-confightml) | Selects which normalized chart definitions are visible on a dashboard. | `configure()`<br>`setDefinitions()`<br>`setVisibility()`<br>`getChartOptions()`<br>`getEffectiveVisibility()`<br>`open()`<br>`close()` | `dashboard-config-ready`<br>`dashboard-config-opened`<br>`dashboard-config-closed`<br>`dashboard-config-change` | Fully normalized definitions and visibility |
|
|
35
35
|
| [`data-maintenance.html`](#data-maintenancehtml) | Runs destructive cleanup of empty chats and memories inside the current app data scope. | `open()` | `data-maintenance-ready`<br>`data-maintenance-complete` | Normalized counts; DBOPFS failures mixed |
|
|
@@ -53,7 +53,7 @@ A component file does not register its own custom element. The `<html-import>` h
|
|
|
53
53
|
| [`screen-capture.html`](#screen-capturehtml) | Presents image, video, or GIF display-capture workflow. | `capture()` | `screen-capture-ready`<br>`screen-capture-result` | State/result normalized; media permission/codec failures mixed |
|
|
54
54
|
| [`source-code-viewer.html`](#source-code-viewerhtml) | Renders line-addressable source code with load, error, focus, and state behavior. | `configure()`<br>`load()`<br>`render()`<br>`clear()`<br>`fail()`<br>`focus()`<br>`focusLine()` | `source-code-viewer-ready`<br>`source-code-viewer-state` | Normalized source/state |
|
|
55
55
|
| [`source-explanation.html`](#source-explanationhtml) | Presents an evidence finding, source selection, explanation, and save state. | `showFinding()`<br>`populate()`<br>`selectSource()`<br>`markSaved()` | `source-explanation-ready`<br>`source-explanation-save`<br>`source-explanation-source-selected` | DOM-normalized |
|
|
56
|
-
| [`speech.html`](#speechhtml) | Coordinates speech controls, transcription completion, mute state, and microphone availability. | `configure()`<br>`setAvailability()`<br>`setMuted()
|
|
56
|
+
| [`speech.html`](#speechhtml) | Coordinates explicit STT activation, speech controls, transcription completion, mute state, and microphone availability. | `configure()`<br>`setAvailability()`<br>`setMuted()`<br>`requestSTTActivation()`<br>`destroy()`<br>`availability`<br>`muted`<br>`initialMuted`<br>`componentReady` | `speech-ready`<br>`speech-transcription-complete`<br>`speech-transcription-error`<br>`speech-transcription-cancelled`<br>`speech-microphone-unavailable`<br>`speech-stt-activation-request`<br>`speech-stt-activation-error`<br>`speech-tts-lifecycle-error` | Sticky runtime speech readiness, explicit STT activation, request cancellation, and TTS mute lifecycle intent normalized; provider/model authority and media behavior remain external |
|
|
57
57
|
| [`summary-strip.html`](#summary-striphtml) | Displays compact selectable KPI or summary items. | `configure()`<br>`setItems()`<br>`updateItem()`<br>`clear()` | `summary-strip-ready`<br>`summary-strip-change`<br>`summary-strip-select` | DOM-normalized |
|
|
58
58
|
| [`table.html`](#tablehtml) | Builds and updates a simple header/body table. | `buildHeader()`<br>`buildTable()` | `table-ready`<br>`header-update`<br>`body-update` | DOM-normalized |
|
|
59
59
|
| [`task-progress.html`](#task-progresshtml) | Runs and displays a task list with started/change/complete/error state. | `configure()`<br>`setTasks()`<br>`updateTask()`<br>`runTasks()`<br>`clear()` | `task-progress-ready`<br>`task-progress-started`<br>`task-progress-change`<br>`task-progress-complete`<br>`task-progress-error` | Task state normalized; injected task results mixed |
|
|
@@ -177,24 +177,63 @@ Shared dependencies: [`ChartLibrary.js`](runtime-modules.md#chartlibraryjs), [`C
|
|
|
177
177
|
|
|
178
178
|
### Overview
|
|
179
179
|
|
|
180
|
-
Shared chat,
|
|
180
|
+
Shared chat, visible selected-model activation request, file upload, streaming,
|
|
181
|
+
speech, language, availability, and conversation-timebox surface.
|
|
181
182
|
|
|
182
183
|
### Public surface
|
|
183
184
|
|
|
184
|
-
Methods/properties: `streamMessage()`, `setMessageProgress()`,
|
|
185
|
+
Methods/properties: `streamMessage()`, `setMessageProgress()`,
|
|
186
|
+
`setAIAvailability()`, `setInitialSpeechMuted()`,
|
|
187
|
+
`setConversationComplete()`, `bindConversationTimebox()`, `submitMessage()`,
|
|
188
|
+
`sendMessage()`, `languageChanged()`, `requestAIActivation()`, and `destroy()`.
|
|
185
189
|
|
|
186
190
|
`sendMessage(text)` and `languageChanged(text)` are host-overridable async
|
|
187
191
|
extension callbacks. The component installs warning-only defaults when the host
|
|
188
192
|
does not supply them; applications may instead consume the corresponding
|
|
189
193
|
`chat-send-message` and `chat-language-changed` events.
|
|
190
194
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
`setAIAvailability()` remains an LLM compatibility input, but selected sticky
|
|
196
|
+
`AIRuntimeState` LLM state wins over that boolean. STT and TTS readiness always
|
|
197
|
+
comes from sticky runtime role state; the method never forwards compatibility
|
|
198
|
+
speech booleans or synthesizes ready speech roles without an admitted, loaded
|
|
199
|
+
provider.
|
|
200
|
+
|
|
201
|
+
When a selected LLM route is `unloaded` or in `error`, the component exposes a
|
|
202
|
+
keyboard-operable Start/Try again control while Send stays disabled. During
|
|
203
|
+
`loading`, the control becomes Cancel loading and reflects sticky progress.
|
|
204
|
+
The default `requestAIActivation(intent)` forwards frozen
|
|
205
|
+
`{role:'llm',action:'load'|'unload',reason:'user'}` to
|
|
206
|
+
`requestAIRuntimeIntent()`. A host may replace that callback.
|
|
207
|
+
|
|
208
|
+
Before the callback, the component dispatches the bubbles/composed/cancelable
|
|
209
|
+
`chat-ai-activation-request` event with frozen `{intent,state}` detail.
|
|
210
|
+
`preventDefault()` suppresses the callback. A callback failure dispatches the
|
|
211
|
+
bubbles/composed, noncancelable `chat-ai-activation-error` event with frozen
|
|
212
|
+
`{request,error,message}`. A recognized canceled load whose current route is
|
|
213
|
+
`unloaded` or `unloading` is not reported as an activation error.
|
|
214
|
+
|
|
215
|
+
`destroy()` aborts the component's AI-runtime-state subscription, destroys the
|
|
216
|
+
activation controller, removes its `pagehide` listener, calls the optional
|
|
217
|
+
speech controller's `destroy()`, sets `ready` to `false`, and returns
|
|
218
|
+
`undefined`. It does not initiate a provider load or unload.
|
|
219
|
+
|
|
220
|
+
Events: `chat-ready`, `chat-send-message`, `chat-send-error`,
|
|
221
|
+
`chat-file-uploaded`, `chat-language-changed`,
|
|
222
|
+
`chat-ai-activation-request`, `chat-ai-activation-error`, and
|
|
223
|
+
`conversation-timebox-error`.
|
|
224
|
+
|
|
225
|
+
Shared dependencies: [`MD.js`](runtime-modules.md#mdjs), [`File.js`](runtime-entities.md#filejs), [`ConversationTimebox.js`](runtime-modules.md#conversationtimeboxjs), [`AIRuntimeState.js`](runtime-modules.md#airuntimestatejs).
|
|
194
226
|
|
|
195
227
|
### Availability and normalization
|
|
196
228
|
|
|
197
|
-
**Browser and supported native WebViews.** UI
|
|
229
|
+
**Browser and supported native WebViews.** UI and provider-runtime state are
|
|
230
|
+
normalized; AI/storage/media behavior remains mixed. The component emits no
|
|
231
|
+
activation request on import or startup. After the user operates the visible
|
|
232
|
+
control and the component event is not canceled, it publishes a
|
|
233
|
+
capability-neutral user intent; a provider/runtime owner decides whether and
|
|
234
|
+
how to execute the requested load or unload. HTMLImport + DOM; injected
|
|
235
|
+
Arcane/provider modules where listed. Native methods remain subject to the
|
|
236
|
+
bound app's capabilities. [Deep protocol details](protocols.md).
|
|
198
237
|
|
|
199
238
|
### Example
|
|
200
239
|
|
|
@@ -812,19 +851,73 @@ Events: `source-explanation-ready`, `source-explanation-save`, `source-explanati
|
|
|
812
851
|
|
|
813
852
|
### Overview
|
|
814
853
|
|
|
815
|
-
Coordinates speech
|
|
854
|
+
Coordinates explicit speech-to-text activation, speech controls, transcription
|
|
855
|
+
completion, mute state, and microphone availability.
|
|
816
856
|
|
|
817
857
|
### Public surface
|
|
818
858
|
|
|
819
|
-
Methods/properties: `configure()`, `setAvailability()`, `setMuted()
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
859
|
+
Methods/properties: `configure()`, `setAvailability()`, `setMuted()`,
|
|
860
|
+
`requestSTTActivation()`, `destroy()`, `availability`, `muted`, `initialMuted`,
|
|
861
|
+
and `componentReady`.
|
|
862
|
+
|
|
863
|
+
Events: `speech-ready`, `speech-transcription-complete`,
|
|
864
|
+
`speech-transcription-error`, `speech-transcription-cancelled`,
|
|
865
|
+
`speech-microphone-unavailable`, `speech-stt-activation-request`,
|
|
866
|
+
`speech-stt-activation-error`, and `speech-tts-lifecycle-error`.
|
|
867
|
+
|
|
868
|
+
Shared dependencies: [`AI.js`](runtime-modules.md#aijs),
|
|
869
|
+
[`AIRuntimeState.js`](runtime-modules.md#airuntimestatejs), and
|
|
870
|
+
[`DBLS.js`](runtime-modules.md#dblsjs).
|
|
871
|
+
|
|
872
|
+
The Hold to talk control remains disabled unless sticky STT state is `ready`,
|
|
873
|
+
the role is not busy, and microphone capture is available. For an explicitly
|
|
874
|
+
selected STT route, a separate keyboard-operable control presents Start
|
|
875
|
+
transcription while `unloaded`, Cancel loading while `loading`, a disabled
|
|
876
|
+
Canceling state while `unloading`, and Try again with the sticky error while
|
|
877
|
+
`error`. Selected-unloaded, busy, and error states are shown as distinct facts;
|
|
878
|
+
none is treated as ready.
|
|
879
|
+
|
|
880
|
+
The default `requestSTTActivation(intent)` forwards the frozen
|
|
881
|
+
`{role:'stt',action:'load'|'unload',reason:'user'}` record to
|
|
882
|
+
`requestAIRuntimeIntent()`. Before calling it, the component emits a bubbling,
|
|
883
|
+
composed, cancelable `speech-stt-activation-request` event with frozen
|
|
884
|
+
`{intent,state}` detail. `preventDefault()` suppresses the callback and intent.
|
|
885
|
+
Callback failure emits `speech-stt-activation-error` with frozen
|
|
886
|
+
`{request,error,message}` detail. Cancel loading publishes an `unload` intent;
|
|
887
|
+
only subsequent sticky `unloading` or `unloaded` state confirms lifecycle
|
|
888
|
+
progress, and callback return never proves provider work stopped.
|
|
889
|
+
|
|
890
|
+
The component emits no activation request on import or state observation.
|
|
891
|
+
Provider registration and selection remain inert, and default
|
|
892
|
+
`startTranscription=false` does not request STT during runtime startup. The
|
|
893
|
+
provider/runtime owner decides whether and how to execute a user intent; the
|
|
894
|
+
component never selects a runtime or model, downloads artifacts, reloads after
|
|
895
|
+
failure, or falls back to another provider.
|
|
896
|
+
|
|
897
|
+
`setAvailability()` is compatibility-only for microphone and negative
|
|
898
|
+
unselected-role reports. Positive STT/TTS booleans cannot manufacture a ready
|
|
899
|
+
role, and no compatibility value can replace a selected sticky role. Hold to
|
|
900
|
+
talk stays disabled without sticky ready STT, and compatibility input cannot
|
|
901
|
+
enable a no-selection TTS role or bypass explicit TTS activation.
|
|
902
|
+
|
|
903
|
+
Each transcription request owns an `AbortController`; its signal is passed as
|
|
904
|
+
the third argument to `AI.fetchSTT()`. Cancel, a newer capture, and `destroy()`
|
|
905
|
+
abort that controller and suppress late results. This proves request delivery
|
|
906
|
+
was canceled, not that an uncooperative provider stopped underlying work.
|
|
907
|
+
|
|
908
|
+
User Unmute calls the shared `AI.setSpeechMuted(false)` lifecycle owner before
|
|
909
|
+
or with publishing the TTS load intent, so the runtime can legally load TTS.
|
|
910
|
+
Mute calls `AI.setSpeechMuted(true)`, stops playback, cancels active TTS work,
|
|
911
|
+
and unloads the selected TTS role. Lifecycle failures remain visible through
|
|
912
|
+
`speech-tts-lifecycle-error` and sticky role state.
|
|
824
913
|
|
|
825
914
|
### Availability and normalization
|
|
826
915
|
|
|
827
|
-
**Browser and supported native WebViews.** UI state
|
|
916
|
+
**Browser and supported native WebViews.** UI/runtime state and explicit user
|
|
917
|
+
STT activation intent are normalized; provider/model authority and media
|
|
918
|
+
behavior remain external. HTMLImport + DOM; injected Arcane/provider modules
|
|
919
|
+
where listed. Native methods remain subject to the bound app's capabilities.
|
|
920
|
+
[Deep protocol details](protocols.md).
|
|
828
921
|
|
|
829
922
|
### Example
|
|
830
923
|
|