arcane-os 0.2.1 → 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 +17 -0
- package/README.md +8 -8
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +5 -5
- package/browser-runtime/ai/browser-speech-providers.mjs +1 -0
- package/docs/architecture.md +2 -2
- package/docs/reference/README.md +79 -13
- package/docs/reference/ai/browser-speech.md +336 -0
- package/docs/reference/ai/browser-wasm.md +207 -82
- package/docs/reference/availability-and-normalization.md +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 +15 -15
- package/runtime/arcane/components/chat.html +17 -52
- package/runtime/arcane/components/speech.html +339 -15
- package/runtime/arcane/modules/AI.js +556 -128
- package/runtime/arcane/modules/AIProviderRuntime.js +299 -30
- package/runtime/arcane/modules/AIRuntimeState.js +23 -4
- package/runtime/arcane/modules/LocalAIReadinessController.js +1 -1
- package/schemas/arcane-lock.schema.json +2 -2
|
@@ -9,7 +9,7 @@ page is the focused local-browser path beneath the normalized AI decision
|
|
|
9
9
|
guide.
|
|
10
10
|
|
|
11
11
|
The wiring example assumes a scaffolded or materialized Arcane application
|
|
12
|
-
with SDK `0.1
|
|
12
|
+
with SDK `0.2.1`'s authenticated runtime tree and generated browser import map.
|
|
13
13
|
`arcane/DBOPFS` is a managed browser-map specifier, not an npm package export.
|
|
14
14
|
See [browser runtime delivery](../protocols.md#browser-runtime-delivery) before
|
|
15
15
|
using the example in a custom host or bundler.
|
|
@@ -25,9 +25,17 @@ import {
|
|
|
25
25
|
|
|
26
26
|
const MODEL = Object.freeze({
|
|
27
27
|
id:'my-reviewed-model',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
files:Object.freeze([{
|
|
29
|
+
name:'model-q4-00001-of-00002.gguf',
|
|
30
|
+
url:'https://models.example/revisions/4f7c/model-q4-00001-of-00002.gguf',
|
|
31
|
+
bytes:123456789,
|
|
32
|
+
sha256:'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
|
|
33
|
+
},{
|
|
34
|
+
name:'model-q4-00002-of-00002.gguf',
|
|
35
|
+
url:'https://models.example/revisions/4f7c/model-q4-00002-of-00002.gguf',
|
|
36
|
+
bytes:98765432,
|
|
37
|
+
sha256:'abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789'
|
|
38
|
+
}])
|
|
31
39
|
});
|
|
32
40
|
|
|
33
41
|
const dbopfs = globalThis.dbopfs || new DBOPFS({applicationId:'my-app'});
|
|
@@ -41,18 +49,23 @@ const ai = createArcaneAI({
|
|
|
41
49
|
security:{secure:true}
|
|
42
50
|
});
|
|
43
51
|
|
|
44
|
-
// Put this behind an explicit user action: it can download
|
|
52
|
+
// Put this behind an explicit user action: it can download every declared file.
|
|
45
53
|
async function loadReviewedModel() {
|
|
46
|
-
return ai.load({threads:1, contextTokens:4096
|
|
54
|
+
return ai.load({threads:1, contextTokens:4096});
|
|
47
55
|
}
|
|
48
56
|
```
|
|
49
57
|
|
|
50
58
|
The browser-WASM runtime closure packages the authenticated
|
|
51
59
|
`@wllama/wllama` `3.6.0` ESM and WebAssembly runtime plus the Wllama and
|
|
52
60
|
llama.cpp MIT license texts. It
|
|
53
|
-
packages no model weights, model catalog, CDN fallback, native
|
|
54
|
-
synthesis, or transcription.
|
|
55
|
-
|
|
61
|
+
packages no model weights, default model catalog, CDN fallback, native
|
|
62
|
+
provider, speech synthesis, or transcription. The sibling
|
|
63
|
+
[`arcane-os/ai/browser-speech`](browser-speech.md) entrypoint supplies speech
|
|
64
|
+
provider mechanisms but still no runtime/model bytes. Callers supply every
|
|
65
|
+
model-source authority. Each file's `bytes` is an optional expected positive
|
|
66
|
+
byte length, not inline model data. The declared URL binds selection identity;
|
|
67
|
+
exact byte identity is established only by the checks the caller enables and
|
|
68
|
+
supplies.
|
|
56
69
|
|
|
57
70
|
## Lifecycle at a glance
|
|
58
71
|
|
|
@@ -67,6 +80,7 @@ is an optional expected positive byte length, not inline model data.
|
|
|
67
80
|
| `ai.llm.chat(request)` / `ai.fetchRequest(request)` | Validated OpenAI-like completion. |
|
|
68
81
|
| `ai.llm.stream(request)` | Frozen async-iterator handle with `result` and `cancel(reason)`. |
|
|
69
82
|
| `ai.streamRequest(request)` | Consumes the stream and returns text or `{toolName: argumentJsonString}`. |
|
|
83
|
+
| `ai.createChatSession(options)` | Asynchronously resolves `Promise<PersistentAIChatSession>` bound to this exact controller; caller-supplied `chat` is rejected. |
|
|
70
84
|
| `ai.unload()` | Cancels active work, releases the Wllama session, and returns flat unloaded status; the DBOPFS cache remains. |
|
|
71
85
|
| `ai.dispose()` | Permanently disposes the controller; explicit `store.remove(source)` is required to delete cached model bytes. |
|
|
72
86
|
|
|
@@ -77,11 +91,19 @@ current frozen status. Provider states are `unloaded`, `loading`, `ready`,
|
|
|
77
91
|
|
|
78
92
|
## Model authority, security, and cache admission
|
|
79
93
|
|
|
80
|
-
The canonical model descriptor is `{id, url,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
hexadecimal characters.
|
|
94
|
+
The canonical model descriptor is `{id, files:[{name?,url,bytes?,sha256?},...]}`.
|
|
95
|
+
The ordered `files` array is nonempty; names and URLs are unique. Each URL must
|
|
96
|
+
be absolute HTTPS without credentials or a fragment; revision-floating `main`,
|
|
97
|
+
`master`, and `latest` path segments are rejected. When supplied, `bytes` is a
|
|
98
|
+
positive safe integer and `sha256` is exactly 64 hexadecimal characters. The
|
|
99
|
+
legacy one-file `{id,url,bytes?,sha256?}` shape remains accepted and normalizes
|
|
100
|
+
to one ordered member.
|
|
101
|
+
|
|
102
|
+
Fetch follows HTTPS redirects and records the requested and final HTTPS URL in
|
|
103
|
+
the completion evidence. A redirect that leaves HTTPS is rejected. A declared
|
|
104
|
+
URL, revision-looking path, or recorded final URL is not a byte digest: only an
|
|
105
|
+
enabled byte-length or SHA-256 check establishes that corresponding integrity
|
|
106
|
+
fact. When a check is disabled, status reports it as `unchecked`.
|
|
85
107
|
|
|
86
108
|
App, provider/model-binding, and load-operation options use the same
|
|
87
109
|
plain-JavaScript shape:
|
|
@@ -115,8 +137,8 @@ and does not hash or reread a multi-gigabyte model solely to produce a digest.
|
|
|
115
137
|
Only enabled checks fail closed. Regardless of optional integrity checks, a
|
|
116
138
|
load succeeds only after Wllama reports that the model is loaded.
|
|
117
139
|
|
|
118
|
-
The DBOPFS adapter commits an `arcane.ai.browser-wasm.model.
|
|
119
|
-
manifest
|
|
140
|
+
The DBOPFS adapter commits an `arcane.ai.browser-wasm.model.v4` completion
|
|
141
|
+
manifest only after every ordered file succeeds. Status reports the effective
|
|
120
142
|
`security.secure`, both effective check booleans, and per-check integrity
|
|
121
143
|
outcomes. Overall integrity is `verified` when every enabled check succeeded,
|
|
122
144
|
`pending` while an enabled check is running, and `unchecked` when neither check
|
|
@@ -133,41 +155,53 @@ console.log(integrity.state); // 'unchecked' or 'verified'
|
|
|
133
155
|
console.log(integrity.byteLength.observed); // actual cached/downloaded bytes
|
|
134
156
|
```
|
|
135
157
|
|
|
136
|
-
For compatibility, older descriptors can supply `immutableUrl` as the
|
|
137
|
-
and `name` as a cache-filename hint. If both `url` and
|
|
138
|
-
present, they must match. Legacy `licenseSpdx` and
|
|
139
|
-
are not canonical descriptor fields or runtime
|
|
140
|
-
remain responsible for model selection,
|
|
141
|
-
|
|
142
|
-
|
|
158
|
+
For one-file compatibility, older descriptors can supply `immutableUrl` as the
|
|
159
|
+
URL alias and `name` as a cache-filename hint. If both `url` and
|
|
160
|
+
`immutableUrl` are present, they must match. Legacy `licenseSpdx` and
|
|
161
|
+
`sourceRevision` properties are not canonical descriptor fields or runtime
|
|
162
|
+
admission checks; applications remain responsible for model selection,
|
|
163
|
+
provenance, and license compliance. Version-2/3 compatibility is internal; a
|
|
164
|
+
new successful completion is always recorded as version 4 without inventing an
|
|
165
|
+
integrity result.
|
|
143
166
|
|
|
144
167
|
`localOnly:true` describes inference after load. It does not mean a cache miss
|
|
145
168
|
cannot download. Source downloads use CORS, omit credentials and referrer,
|
|
146
169
|
disable HTTP caching, and honor `AbortSignal`.
|
|
147
170
|
|
|
171
|
+
On Chrome, observing a lower-power Intel WebGPU adapter may open
|
|
172
|
+
`chrome://flags/#force-high-performance-gpu` in a new tab and show an alert
|
|
173
|
+
explaining that Chrome must be completely restarted after changing the flag.
|
|
174
|
+
The notice is advisory; it does not change browser settings, prove a faster
|
|
175
|
+
adapter exists, or make a failed load succeed.
|
|
176
|
+
|
|
148
177
|
## Streaming, cancellation, and tools
|
|
149
178
|
|
|
150
179
|
```javascript
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
180
|
+
async function streamLocalSummaryAfterUserChoice(cancelButton) {
|
|
181
|
+
// The selected browser-WASM model must already be ready.
|
|
182
|
+
if (!cancelButton?.addEventListener) {
|
|
183
|
+
throw new TypeError('A cancel button is required.');
|
|
184
|
+
}
|
|
185
|
+
const abort = new AbortController();
|
|
186
|
+
const stream = ai.llm.stream({
|
|
187
|
+
localOnly:true,
|
|
188
|
+
signal:abort.signal,
|
|
189
|
+
messages:[{role:'user', content:'Summarize this text.'}],
|
|
190
|
+
maxTokens:128
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const cancel = () => abort.abort('user cancelled');
|
|
194
|
+
cancelButton.addEventListener('click', cancel, {once:true});
|
|
195
|
+
try {
|
|
196
|
+
for await (const chunk of stream) renderChunk(chunk);
|
|
197
|
+
const completion = await stream.result;
|
|
198
|
+
renderCompletion(completion);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (error?.code !== 'ARCANE_AI_REQUEST_ABORTED') throw error;
|
|
201
|
+
renderCancelled();
|
|
202
|
+
} finally {
|
|
203
|
+
cancelButton.removeEventListener('click', cancel);
|
|
204
|
+
}
|
|
171
205
|
}
|
|
172
206
|
```
|
|
173
207
|
|
|
@@ -176,8 +210,11 @@ serialized; provider status exposes `busy` and `queued`. Supported request
|
|
|
176
210
|
generation fields include temperature, top-K, top-P, min-P, repeat penalty,
|
|
177
211
|
maximum tokens, seed, and stop sequences. Load settings separately include
|
|
178
212
|
`contextTokens`, `batchTokens`, `microBatchTokens`, `threads`, and GPU-layer
|
|
179
|
-
count.
|
|
180
|
-
|
|
213
|
+
count. The shipped runtime always sets `gpuLayers: 99999`: WebGPU and proved
|
|
214
|
+
full offload are mandatory, and there is no CPU fallback. Secure context,
|
|
215
|
+
adapter selection, full-offload, logical-buffer, queue-submission, and
|
|
216
|
+
settled-fence evidence are load admission; cross-origin isolation and coarse
|
|
217
|
+
hardware fields remain observations.
|
|
181
218
|
|
|
182
219
|
Tool definitions, tool choice, parallel-tool-call preference, and JSON or JSON
|
|
183
220
|
Schema structured-output requests are passed to Wllama. Returned tool calls are
|
|
@@ -197,24 +234,41 @@ as unavailable.
|
|
|
197
234
|
| --- | --- |
|
|
198
235
|
| Source and download | `ARCANE_AI_MODEL_SOURCE_INVALID`, `ARCANE_AI_MODEL_SOURCE_UNAVAILABLE`, `ARCANE_AI_MODEL_DOWNLOAD_FAILED`, `ARCANE_AI_MODEL_REDIRECT_BLOCKED`, `ARCANE_AI_MODEL_SIZE_MISMATCH`, `ARCANE_AI_MODEL_DIGEST_MISMATCH` |
|
|
199
236
|
| Cache and storage | `ARCANE_AI_MODEL_CACHE_REJECTED`, `ARCANE_AI_MODEL_OFFLINE_MISS`, `ARCANE_AI_STORAGE_UNAVAILABLE`, `ARCANE_AI_STORAGE_READ_FAILED`, `ARCANE_AI_STORAGE_DELETE_FAILED` |
|
|
200
|
-
| Lifecycle | `ARCANE_AI_UNAVAILABLE`, `ARCANE_AI_NOT_READY`, `ARCANE_AI_LOAD_FAILED`, `ARCANE_AI_UNLOAD_FAILED`, `ARCANE_AI_DISPOSE_FAILED`, `ARCANE_AI_DISPOSED`, `ARCANE_AI_OPERATION_SUPERSEDED`, `ARCANE_AI_SECURITY_RELOAD_REQUIRED` |
|
|
201
|
-
| Requests | `ARCANE_AI_REQUEST_ABORTED`, `ARCANE_AI_REQUEST_FAILED`, `ARCANE_AI_INVALID_PROVIDER_RESULT`, `ARCANE_AI_LOCAL_ONLY_UNAVAILABLE`, `ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH` |
|
|
237
|
+
| Lifecycle | `ARCANE_AI_UNAVAILABLE`, `ARCANE_AI_NOT_READY`, `ARCANE_AI_MODEL_NOT_READY`, `ARCANE_AI_LOAD_FAILED`, `ARCANE_AI_UNLOAD_FAILED`, `ARCANE_AI_DISPOSE_FAILED`, `ARCANE_AI_DISPOSED`, `ARCANE_AI_OPERATION_SUPERSEDED`, `ARCANE_AI_SECURITY_RELOAD_REQUIRED` |
|
|
238
|
+
| Requests | `ARCANE_AI_REQUEST_ABORTED`, `ARCANE_AI_REQUEST_FAILED`, `ARCANE_AI_RUNTIME_BUSY`, `ARCANE_AI_INVALID_PROVIDER_RESULT`, `ARCANE_AI_LOCAL_ONLY_UNAVAILABLE`, `ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH` |
|
|
239
|
+
| Provider/2 adapter | `ARCANE_AI_MODEL_AUTHORITY_REQUIRED`, `ARCANE_AI_PROVIDER_ROLE_MISMATCH`, `ARCANE_AI_PROVIDER_PROGRESS_INVALID`, `ARCANE_AI_PROVIDER_STATUS_INVALID`, `ARCANE_AI_PROVIDER_OPERATION_UNAVAILABLE` |
|
|
240
|
+
| WebGPU and model admission | `ARCANE_AI_WEBGPU_REQUIRED`, `ARCANE_AI_WEBGPU_API_UNAVAILABLE`, `ARCANE_AI_WEBGPU_EVIDENCE_INVALID`, `ARCANE_AI_MODEL_FULL_OFFLOAD_UNPROVEN`, `ARCANE_AI_MODEL_WEBGPU_REQUIREMENT_FAILED`, `ARCANE_AI_MODEL_GPU_MEMORY_INSUFFICIENT`, `ARCANE_AI_MODEL_SHARD_TOO_LARGE`, `ARCANE_AI_MODEL_RELOAD_REQUIRED`, `ARCANE_AI_LOAD_PLAN_RELOAD_REQUIRED` |
|
|
241
|
+
| Worker cleanup and recovery | `ARCANE_AI_WORKER_TERMINATION_UNCONFIRMED`, `ARCANE_AI_COMPLETION_RECOVERY_UNCONFIRMED` |
|
|
202
242
|
| Diagnostics | `ARCANE_AI_PROBE_FAILED` |
|
|
203
243
|
|
|
244
|
+
Capability and status records also carry stable reason codes. These observations
|
|
245
|
+
are not all thrown errors: positive and unknown states let an application
|
|
246
|
+
explain why load is available, blocked, or not yet measured without guessing.
|
|
247
|
+
|
|
248
|
+
| Observation | Status/reason codes |
|
|
249
|
+
| --- | --- |
|
|
250
|
+
| Browser prerequisites | `ARCANE_AI_WEBASSEMBLY_UNAVAILABLE`, `ARCANE_AI_OPFS_UNAVAILABLE`, `ARCANE_AI_SECURE_CONTEXT_REQUIRED` |
|
|
251
|
+
| Model/storage sizing | `ARCANE_AI_MODEL_STORAGE_REQUIREMENT_UNBOUNDED`, `ARCANE_AI_MODEL_STORAGE_REQUIREMENT_UNKNOWN`, `ARCANE_AI_STORAGE_ESTIMATE_UNAVAILABLE`, `ARCANE_AI_STORAGE_ESTIMATE_FAILED`, `ARCANE_AI_STORAGE_ESTIMATE_INVALID`, `ARCANE_AI_STORAGE_NOT_MEASURED`, `ARCANE_AI_STORAGE_CAPACITY_INSUFFICIENT` |
|
|
252
|
+
| Positive cache/storage state | `ARCANE_AI_MODEL_CACHE_COMPLETE`, `ARCANE_AI_STORAGE_CAPACITY_AVAILABLE` |
|
|
253
|
+
| WebGPU execution evidence | `ARCANE_AI_WEBGPU_EXECUTION_OBSERVED`, `ARCANE_AI_WEBGPU_EXECUTION_UNOBSERVED` |
|
|
254
|
+
| Provider and runtime failure state | `ARCANE_AI_PROVIDER_UNAVAILABLE`, `ARCANE_AI_RUNTIME_FAILED` |
|
|
255
|
+
|
|
204
256
|
`capabilities()` reports browser observations such as WebAssembly, OPFS,
|
|
205
|
-
WebGPU, secure context, cross-origin
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
257
|
+
WebGPU API presence, admitted WebGPU operation, secure context, cross-origin
|
|
258
|
+
isolation, and hardware concurrency. `navigator.gpu` alone is not operational
|
|
259
|
+
evidence. The authoritative runtime can operate without cross-origin isolation,
|
|
260
|
+
so that flag is not a hard gate; secure context and WebGPU/full-offload evidence
|
|
261
|
+
are. `probe()` exercises packaged Wllama backend operations only while unloaded;
|
|
262
|
+
it neither admits nor downloads a model.
|
|
210
263
|
|
|
211
264
|
## BROWSER_WASM_RUNTIME_AUTHORITY
|
|
212
265
|
|
|
213
266
|
### Overview
|
|
214
267
|
|
|
215
268
|
Deep-frozen identity for the shipped browser runtime. Its protocol is
|
|
216
|
-
`arcane-ai-browser-wasm/2`; the provider
|
|
217
|
-
`arcane-ai-adapter/1
|
|
269
|
+
`arcane-ai-browser-wasm/2`; the direct provider uses
|
|
270
|
+
`arcane-ai-adapter/1` and `adaptV1LlmProvider()` projects it into
|
|
271
|
+
`arcane-ai-provider/2`. It records Wllama `3.6.0`, the embedded llama.cpp
|
|
218
272
|
revision, authenticated module/WASM byte lengths and SHA-256 values, licenses,
|
|
219
273
|
and the disabled compatibility-runtime and remote-model-helper policy.
|
|
220
274
|
|
|
@@ -255,12 +309,18 @@ createArcaneAI({ llm=null, provider=null, loadPolicy='on-demand', security }={})
|
|
|
255
309
|
|
|
256
310
|
At least one `llm` or `provider` is required; when both are supplied, `llm`
|
|
257
311
|
takes precedence. `loadPolicy` is `on-demand` or `manual`. The frozen result
|
|
258
|
-
contains `llm`, `runtime`, `status`, `load`,
|
|
312
|
+
contains `llm`, `runtime`, `createChatSession`, `status`, `load`,
|
|
259
313
|
`unload`, `probe`, `fetchRequest`, `streamRequest`, and `dispose`.
|
|
260
314
|
`security` is the app-level security configuration inherited by provider loads.
|
|
261
315
|
The SDK default is `secure:false`; `ai.load({security})` can override inherited
|
|
262
316
|
fields for that operation.
|
|
263
317
|
|
|
318
|
+
When `llm` is an existing `ModelController`, that controller keeps the security
|
|
319
|
+
and load policy with which it was created. This function does not reapply its
|
|
320
|
+
`loadPolicy` argument in that case, and supplying `security` alongside the
|
|
321
|
+
existing controller throws `TypeError`. Passing a provider instead creates a
|
|
322
|
+
new controller with the requested policy and security.
|
|
323
|
+
|
|
264
324
|
### Availability and normalization
|
|
265
325
|
|
|
266
326
|
**Browser.** It normalizes provider lifecycle and request observation without
|
|
@@ -271,17 +331,30 @@ creating a fallback provider.
|
|
|
271
331
|
|
|
272
332
|
```javascript
|
|
273
333
|
const ai = createArcaneAI({provider, loadPolicy:'manual'});
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
334
|
+
async function loadCachedModelAfterUserChoice() {
|
|
335
|
+
const off = ai.llm.on('statechange', event => renderStatus(event.detail));
|
|
336
|
+
try {
|
|
337
|
+
return await ai.load({offline:true});
|
|
338
|
+
} finally {
|
|
339
|
+
off();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
277
342
|
```
|
|
278
343
|
|
|
344
|
+
`await ai.createChatSession(options)` dynamically creates a
|
|
345
|
+
[`PersistentAIChatSession`](../runtime-modules.md#persistentaichatsessionjs)
|
|
346
|
+
whose `chat` function is permanently bound to this controller. `options` must
|
|
347
|
+
be a plain object and must not contain `chat`; this prevents a session from
|
|
348
|
+
claiming the controller's lifecycle while sending its turns through another
|
|
349
|
+
provider.
|
|
350
|
+
|
|
279
351
|
## createBrowserModelSource()
|
|
280
352
|
|
|
281
353
|
### Overview
|
|
282
354
|
|
|
283
|
-
Validates a caller-owned canonical
|
|
284
|
-
|
|
355
|
+
Validates a caller-owned canonical ordered multi-file descriptor and creates
|
|
356
|
+
the cancellable HTTPS download source accepted by this provider. A legacy
|
|
357
|
+
one-file descriptor normalizes to one ordered member.
|
|
285
358
|
|
|
286
359
|
### Signature and result
|
|
287
360
|
|
|
@@ -290,8 +363,10 @@ createBrowserModelSource(descriptor, { fetchImpl=null }={})
|
|
|
290
363
|
```
|
|
291
364
|
|
|
292
365
|
The frozen source includes `kind`, the canonical descriptor fields,
|
|
293
|
-
`descriptor`, and `open({signal})`. `open()`
|
|
294
|
-
|
|
366
|
+
`descriptor`, and `open(memberIndex,{signal})`. `open()` requires a member
|
|
367
|
+
index for multi-file sources and returns a readable response body,
|
|
368
|
+
requested/final URLs, reported byte length, and `cancel()`; it does not admit
|
|
369
|
+
bytes to the cache.
|
|
295
370
|
|
|
296
371
|
### Availability and normalization
|
|
297
372
|
|
|
@@ -303,7 +378,7 @@ enabled for load.
|
|
|
303
378
|
|
|
304
379
|
```javascript
|
|
305
380
|
const source = createBrowserModelSource(MODEL);
|
|
306
|
-
console.log(source.id, source.
|
|
381
|
+
console.log(source.id, source.files);
|
|
307
382
|
```
|
|
308
383
|
|
|
309
384
|
## createBrowserWasmLlmProvider()
|
|
@@ -316,12 +391,16 @@ created by this module. Structural lookalikes are rejected.
|
|
|
316
391
|
### Signature and result
|
|
317
392
|
|
|
318
393
|
```text
|
|
319
|
-
createBrowserWasmLlmProvider({ source, store, loadDefaults={}, security, logger=console }={})
|
|
394
|
+
createBrowserWasmLlmProvider({ source, sources, store, loadDefaults={}, security, logger=console }={})
|
|
320
395
|
```
|
|
321
396
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
`
|
|
397
|
+
`sources` is a nonempty array of unique SDK-created model sources. Optional
|
|
398
|
+
legacy `source` identifies the default and must be one member of `sources`; when
|
|
399
|
+
`sources` is omitted, `source` supplies the one-model catalog. The frozen
|
|
400
|
+
result exposes protocol and provider identity, default model metadata,
|
|
401
|
+
`catalog`, `capabilities`, `status`, `load`, `unload`, `chat`, `stream`,
|
|
402
|
+
`streamChat`, `use`, `probe`, and `dispose`. Direct provider `load()` selects a
|
|
403
|
+
catalog model and returns `{model,status}`;
|
|
325
404
|
the facade `ai.load()` returns the flat controller status.
|
|
326
405
|
Provider `security` supplies the provider/model-binding scope. Direct
|
|
327
406
|
`provider.load({security})` and facade `ai.load({security})` supply the
|
|
@@ -329,18 +408,20 @@ operation scope.
|
|
|
329
408
|
|
|
330
409
|
### Availability and normalization
|
|
331
410
|
|
|
332
|
-
**Browser with WebAssembly
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
411
|
+
**Browser secure context with WebAssembly, OPFS/DBOPFS, WebGPU, and admitted
|
|
412
|
+
full-offload evidence.** Inference is local after a successful Wllama load.
|
|
413
|
+
The runtime forces `gpuLayers: 99999`; callers cannot select CPU or partial
|
|
414
|
+
offload. Status discloses effective checks, capability policy, storage/model
|
|
415
|
+
compatibility, and whether enabled integrity checks are pending, unchecked, or
|
|
416
|
+
verified.
|
|
336
417
|
|
|
337
418
|
### Example
|
|
338
419
|
|
|
339
420
|
```javascript
|
|
340
421
|
const provider = createBrowserWasmLlmProvider({
|
|
341
|
-
source,
|
|
422
|
+
sources:[source],
|
|
342
423
|
store,
|
|
343
|
-
loadDefaults:{threads:1, contextTokens:4096
|
|
424
|
+
loadDefaults:{threads:1, contextTokens:4096}
|
|
344
425
|
});
|
|
345
426
|
console.log(provider.status().state); // unloaded
|
|
346
427
|
```
|
|
@@ -356,14 +437,18 @@ completion-manifest behavior.
|
|
|
356
437
|
### Signature and result
|
|
357
438
|
|
|
358
439
|
```text
|
|
359
|
-
createDbopfsModelStore({ dbopfs, tableName='arcane_ai_browser_models' }={})
|
|
440
|
+
createDbopfsModelStore({ dbopfs, tableName='arcane_ai_browser_models', estimateStorage=null }={})
|
|
360
441
|
```
|
|
361
442
|
|
|
362
|
-
The
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
`
|
|
366
|
-
|
|
443
|
+
The optional `estimateStorage()` function supplies bounded storage evidence
|
|
444
|
+
when the browser's default estimator is unavailable or an application owns a
|
|
445
|
+
more precise quota view. The frozen result contains `kind`, `tableName`, the
|
|
446
|
+
original `adapter`, and `ready`, `openVerified`, `install`, `ensure`, and
|
|
447
|
+
`remove`. `ensure()` returns
|
|
448
|
+
`{files,file,manifest,observedBytes,integrity,cache}`: `files` preserves the
|
|
449
|
+
ordered model set, while the one-file compatibility field `file` is that sole
|
|
450
|
+
member or `null`. `cache` is `cached` or `installed`. `openVerified()` remains
|
|
451
|
+
a compatibility helper that requires both byte-length and SHA-256 verification.
|
|
367
452
|
|
|
368
453
|
### Availability and normalization
|
|
369
454
|
|
|
@@ -376,15 +461,52 @@ model license rights.
|
|
|
376
461
|
|
|
377
462
|
```javascript
|
|
378
463
|
const store = createDbopfsModelStore({dbopfs});
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
464
|
+
async function verifyCachedModelAfterUserChoice() {
|
|
465
|
+
await store.ready();
|
|
466
|
+
const cached = await store.openVerified(source);
|
|
467
|
+
console.log(cached ? 'verified cache' : 'cache miss');
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## adaptV1LlmProvider()
|
|
472
|
+
|
|
473
|
+
### Overview
|
|
474
|
+
|
|
475
|
+
Projects one compatible admitted v1 browser-WASM provider into the same
|
|
476
|
+
provider/2 LLM role used by `AIProviderRuntime.js`. Admission checks the v1
|
|
477
|
+
protocol, required identity/methods, and local-only capability; it does not
|
|
478
|
+
establish SDK provenance for an arbitrary compatible object. The adapter does
|
|
479
|
+
not change the wrapped provider, download a model, execute a tool, or create a
|
|
480
|
+
fallback.
|
|
481
|
+
|
|
482
|
+
### Signature and result
|
|
483
|
+
|
|
484
|
+
```text
|
|
485
|
+
adaptV1LlmProvider(provider)
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
The frozen result exposes `{protocol:'arcane-ai-provider/2',role:'llm',id,
|
|
489
|
+
localOnly:true,catalog,inspect,status,load,request,unload,dispose}`. Inspection
|
|
490
|
+
returns `arcane-ai-model-authority/1` only for an exact catalog selection.
|
|
491
|
+
`request()` admits only `chat` and `stream` and preserves structural tool data.
|
|
492
|
+
|
|
493
|
+
### Example
|
|
494
|
+
|
|
495
|
+
```javascript
|
|
496
|
+
import {adaptV1LlmProvider} from 'arcane-os/ai/browser-wasm';
|
|
497
|
+
import {getAIProviderRuntime} from 'arcane/AIProviderRuntime';
|
|
498
|
+
|
|
499
|
+
const runtime = getAIProviderRuntime();
|
|
500
|
+
const release = runtime.register(adaptV1LlmProvider(provider));
|
|
501
|
+
// Configure an exact llm route before load/use. Release registration at teardown.
|
|
502
|
+
release();
|
|
382
503
|
```
|
|
383
504
|
|
|
384
505
|
## Related reference
|
|
385
506
|
|
|
386
507
|
- [Canonical `createArcaneAI()` entry](../sdk-api.md#createarcaneai) and the
|
|
387
508
|
sibling [`BROWSER_WASM_RUNTIME_AUTHORITY`](../sdk-api.md#browserwasmruntimeauthority),
|
|
509
|
+
[`adaptV1LlmProvider()`](../sdk-api.md#adaptv1llmprovider),
|
|
388
510
|
[`createBrowserModelSource()`](../sdk-api.md#createbrowsermodelsource),
|
|
389
511
|
[`createBrowserWasmLlmProvider()`](../sdk-api.md#createbrowserwasmllmprovider),
|
|
390
512
|
and [`createDbopfsModelStore()`](../sdk-api.md#createdbopfsmodelstore) entries
|
|
@@ -392,3 +514,6 @@ console.log(cached ? 'verified cache' : 'cache miss');
|
|
|
392
514
|
- [Authenticated browser runtime delivery](../protocols.md#browser-runtime-delivery)
|
|
393
515
|
- [Browser-WASM behavior evidence](../behavioral-testing.md#behavioral-coverage-model)
|
|
394
516
|
- [DBOPFS runtime module](../runtime-modules.md#dbopfsjs)
|
|
517
|
+
- [Browser speech providers](browser-speech.md)
|
|
518
|
+
- [Provider-neutral AI runtime](../runtime-modules.md#aiproviderruntimejs)
|
|
519
|
+
- [Persistent chat](../runtime-modules.md#persistentaichatsessionjs)
|
|
@@ -11,7 +11,7 @@ it runs; the [protocol guide](protocols.md) contains the implementation detail.
|
|
|
11
11
|
| **Browser** | Uses standard browser APIs and can run without a native host when its own dependencies are available. |
|
|
12
12
|
| **Native** | Requires an admitted `globalThis.Arcane` host method or a native target provider. |
|
|
13
13
|
| **Cloud** | Calls a remote provider over HTTPS and needs provider configuration and network policy. |
|
|
14
|
-
| **Cross-host** | Keeps one application
|
|
14
|
+
| **Cross-host** | Keeps one application contract usable across supported hosts. Execution may stay in-process, use a registered provider, or cross a documented Arcane WebView2, WebKitGTK, Android WebView, or development HTTP transport. |
|
|
15
15
|
| **Provider-native** | Intentionally returns the underlying provider's bounded envelope instead of an Arcane-normalized entity. |
|
|
16
16
|
|
|
17
17
|
“Available” never means “authorized.” App grants, method allowlists, host
|
|
@@ -29,7 +29,11 @@ version; WebKitGTK availability must not be generalized to macOS.
|
|
|
29
29
|
| Scaffold, inspect, test, package, bundle, build, verify, or run an app | `arcane` CLI or `arcane-os` package functions | **Node**; native targets invoke one explicit provider | CLI events and SDK errors/results are normalized by versioned SDK contracts. Native artifact receipts remain target-specific inside a common receipt lifecycle. |
|
|
30
30
|
| Publish application events or review a bounded event history | `arcane-os/event-manager` | **Node** and **Browser**; optional DOM capture needs a browser DOM or compatible host | Live listeners receive original arguments. Recorded payloads and metadata become bounded, redacted, deeply frozen `arcane-event-stack/1` snapshots. The stack format is local diagnostic data, not a host transport. |
|
|
31
31
|
| Build browser UI and app-local behavior | `/arcane/modules/*.js`, shared entities, and components | **Browser**; many modules also run inside every native renderer | Pure modules own their result contracts. Modules that call `Arcane` inherit the bridge boundary described below. |
|
|
32
|
-
|
|
|
32
|
+
| Select and observe independent LLM/STT/TTS roles | `/arcane/modules/AIProviderRuntime.js` and `AIRuntimeState.js` | **Cross-host** controller/state; registered providers retain their own host requirements | Required/projected provider members, closed route/configuration records, and validated authority/status fields; per-role lifecycle, cancellation, stream cleanup, sticky state, and startup barriers are normalized. `localOnly` fails closed and creates no fallback. |
|
|
33
|
+
| Run a caller-selected local LLM entirely in a browser renderer | `arcane-os/ai/browser-wasm` through `createArcaneAI()` | **Browser** only; secure context, WebAssembly, OPFS/DBOPFS, WebGPU, requested full offload, and admitted adapter/buffer/queue/fence evidence are required; no CPU fallback | The facade normalizes multi-model lifecycle, status, security precedence, effective-check disclosure, streaming, cancellation, and structural tool-call visibility. Model sources are canonical ordered file descriptors; licenses and model choice remain application policy. |
|
|
34
|
+
| Run caller-selected Whisper or Kokoro in a browser renderer | `arcane-os/ai/browser-speech` registered with `AIProviderRuntime` | **Browser** only; DBOPFS, Web Locks, Workers, Fetch/object URLs, and a caller-supplied self-contained runtime/model closure are required | STT/TTS use independent provider/2 lifecycle and status. Immutable artifact authority, manifest-last cache, strict offline admission, cancellation, Worker teardown, and request/result shapes are normalized. No runtime/model bytes or cloud fallback are supplied. |
|
|
35
|
+
| Preserve bounded chat history and memory | `/arcane/modules/PersistentAIChatSession.js` | **Browser / native WebView** with ChatEntity/DBOPFS and a configured chat function | Existing DBOPFS names and memory semantics are preserved. Live-context commit is atomic; durable persistence is explicit and coherent across user/assistant/tool turns. |
|
|
36
|
+
| Search an app-owned document corpus for explicit chat context | `/arcane/modules/DBOPFSDocumentLibrary.js` | **Browser** or compatible injected DBOPFS adapter | Generation/manifest completion, bounded lexical search, partial read failures, and untrusted context labels are normalized. Construction does not search; an explicitly wired context builder performs bounded retrieval for each prepared chat send. |
|
|
33
37
|
| Read host identity, capabilities, storage, preferences, appearance, or platform state | `globalThis.Arcane` | **Cross-host** where the method is implemented and admitted | Promise behavior and `Arcane.Error` are normalized. Result fields are normalized unless the method explicitly documents a platform-dependent snapshot. |
|
|
34
38
|
| Use local AI without coupling app code to Ollama HTTP | `Arcane.localAI`, `Arcane.ai`, or `/arcane/modules/Ollama.js` | Primarily **Native**; Android exposes a narrower admitted inference projection | Admission, errors, and managed-operation events are normalized. Direct Ollama response envelopes remain **Provider-native**. |
|
|
35
39
|
| Use OpenAI from the renderer profile | `/arcane/modules/AI.js` | **Cloud** from an allowed browser/native renderer | High-level AI chat/text behavior is normalized by the module; raw provider diagnostics and some response detail remain provider-specific. No automatic cloud fallback is inferred from local failure. |
|
|
@@ -81,12 +85,19 @@ state. See [EventManager and time-travel review](event-manager.md).
|
|
|
81
85
|
### Browser-local provider adapter
|
|
82
86
|
|
|
83
87
|
[`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) exposes the same
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
provider-neutral lifecycle used by `createArcaneAI()`, while its packaged
|
|
89
|
+
Wllama engine and caller-supplied model run inside the browser. This
|
|
86
90
|
surface does not require an Arcane Core method grant because it does not call a
|
|
87
91
|
Core host. Browser Fetch, CORS, storage policy, secure-context behavior, and
|
|
88
92
|
resource limits still apply.
|
|
89
93
|
|
|
94
|
+
The shipped `0.2.1` runtime requires WebGPU and has no CPU fallback. A successful
|
|
95
|
+
load requests full GPU offload (`gpuLayers: 99999`) and admits actual adapter,
|
|
96
|
+
full-offload, buffer, queue, and settled-fence evidence. `navigator.gpu`
|
|
97
|
+
presence by itself is not readiness. The provider emits the instrumented
|
|
98
|
+
`arcane.ai.browser-wasm.webgpu.adapter.selected` capability event only after
|
|
99
|
+
admitted adapter selection evidence.
|
|
100
|
+
|
|
90
101
|
`localOnly:true` describes inference after load; it does not promise that load
|
|
91
102
|
is offline. A normal cache miss downloads from the exact caller-supplied HTTPS
|
|
92
103
|
URL. App, provider/model-binding, and load-operation options use
|
|
@@ -108,6 +119,21 @@ cache entry and otherwise rejects with `ARCANE_AI_MODEL_OFFLINE_MISS`. Tool
|
|
|
108
119
|
calls are result data for application review and dispatch; the SDK never
|
|
109
120
|
executes them.
|
|
110
121
|
|
|
122
|
+
[`arcane-os/ai/browser-speech`](ai/browser-speech.md) implements the sibling
|
|
123
|
+
`stt` and `tts` provider/2 roles. Each caller-authenticated Whisper or Kokoro
|
|
124
|
+
provider has its own load, use, cancellation, unload, dispose, cache, Worker,
|
|
125
|
+
status, and error state. The SDK supplies neither speech adapter runtime bytes
|
|
126
|
+
nor model/voice bytes; every immutable file is application-owned and admitted
|
|
127
|
+
through an SDK-created authority and DBOPFS artifact store.
|
|
128
|
+
|
|
129
|
+
The projected [`AIProviderRuntime`](runtime-modules.md#aiproviderruntimejs)
|
|
130
|
+
normalizes those browser providers and can admit an externally supplied native
|
|
131
|
+
or cloud provider/2 adapter. SDK `0.2.1` does not publish a native, Core, or
|
|
132
|
+
cloud provider/2 adapter. The sticky
|
|
133
|
+
[`AIRuntimeState`](runtime-modules.md#airuntimestatejs) surface keeps
|
|
134
|
+
application UI independent of transport. A selected route remains explicit:
|
|
135
|
+
browser failure is not permission to invoke Core or cloud.
|
|
136
|
+
|
|
111
137
|
### Arcane bridge-normalized
|
|
112
138
|
|
|
113
139
|
Core-backed calls return promises and reject with `Arcane.Error`. Transport
|
|
@@ -37,7 +37,10 @@ release acceptance.
|
|
|
37
37
|
| EventManager and event stacks | Live pub/sub ordering and payload identity, nested causation, immutable/redacted snapshots, strict import, bounded overflow, seek, all playback modes/lifecycle outcomes, cancellation, and DOM start/stop/privacy behavior. | Real user journeys and browser layout belong in a browser harness; event-stack review never proves that external side effects can be replayed. |
|
|
38
38
|
| CLI | Commands parse, acknowledge, select one scope, produce normalized human/JSON/NDJSON output, propagate cancellation/failure, and reject invalid cardinality. | Native build/run requires the selected real provider and host. |
|
|
39
39
|
| Browser runtime modules | Every shipped ESM module parses and its export inventory matches the catalog; pure helpers run focused success/error cases. | DOM, OPFS, media, and Web Component journeys use a browser harness. |
|
|
40
|
-
|
|
|
40
|
+
| Provider-neutral AI runtime and chat/speech activation | Provider/2 registration, closed three-role configuration, opt-in STT startup, legacy Cloud/Core speech readiness, independent LLM/STT/TTS load/unload/status, latest-request-wins settlement, owned STT signals, TTS mute lifecycle, route-owned voice defaults, sticky-state-only speech readiness, selected-unloaded activation request/cancellation/error events, stale-callback suppression, and absence of silent provider fallback are exercised against bounded providers and host callbacks. | Real model/runtime admission remains the selected provider's evidence boundary; provider-promise settlement, state, an abort signal, or an activation event does not by itself prove underlying provider work stopped or native, cloud, or browser-model availability. |
|
|
41
|
+
| Browser-WASM local AI | The exact exported namespace, canonical ordered `{id, files:[{name?,url,bytes?,sha256?},...]}` descriptor plus its one-file compatibility input, fieldwise app/provider/load security precedence, default-unchecked and secure-check paths, observed-byte persistence, honest capability/status reasons, provider/facade lifecycle, lazy/manual policy, successful Wllama-load requirement, abort normalization, and structural-only tool behavior run with bounded deterministic providers. | The publication gate installs the packed SDK into a real Chrome app, loads the authenticated Wllama 3.6.0 JS/WASM assets, configures `secure:true`, performs a cold exact-length/SHA-256 model install, real inference, in-flight cancellation, unload, and a verified offline reload with zero model requests. It is an explicit heavyweight capability gate, not an implicit model download in every local `npm run check`. |
|
|
42
|
+
| Browser speech | Caller-owned Whisper/Kokoro authority, closed runtime graph, app/provider/load security precedence, manifest-last DBOPFS cache, strict offline admission, independent Worker lifecycle, pre-Worker versus in-Worker cancellation, Blob/File STT conversion, WAV TTS conversion, and no cloud fallback are exercised with bounded synthetic artifacts and adapters. | A real runtime/model/voice download and actual transcription or synthesis require the application's admitted immutable artifacts, licenses, browser media support, and explicit user action. |
|
|
43
|
+
| Persistent chat and document context | Atomic in-memory/history commit, explicit per-turn persistence, single structural tool-call sequencing, bounded bootstrap/search/context, caller-source `evaluate()` budgets, cancellation, and reject versus `preserve-readable` partial coverage are exercised with app-scoped adapters. | Live Core/provider inference and durable browser storage remain separate authorities; tests never treat a fake chat function or in-memory adapter as host/storage proof. |
|
|
41
44
|
| Core bridge docs | Canonical namespace/method/event/entity inventories match their one-per-member guides and required sections. | Live Core conformance belongs in Arcane OS because Core implementation is not shipped as SDK source. |
|
|
42
45
|
| Arcane Ollama wrapper | Missing-host error, method forwarding, text/readiness normalization, unload request, and stream-option forwarding run against a deterministic fake `Arcane.ollama`. | Real managed-service, model download/create, GPU/resource admission, and service restart require an admitted Arcane host. |
|
|
43
46
|
| Native providers | Plan/provider protocol, explicit target, receipt authentication, artifact reader, and unavailable-path honesty are tested with bounded fixtures. | Exact Windows, Linux, or Android artifact verification and launch must run on that actual platform/architecture. |
|