arcane-os 0.1.1 → 0.2.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/NOTICE +5 -3
  3. package/README.md +73 -24
  4. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +67 -18
  5. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +16 -5
  6. package/browser-runtime/ai/browser-kokoro-worker.mjs +3 -0
  7. package/browser-runtime/ai/browser-speech-artifacts.mjs +1108 -0
  8. package/browser-runtime/ai/browser-speech-providers.mjs +475 -0
  9. package/browser-runtime/ai/browser-speech.mjs +9 -0
  10. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +1537 -167
  11. package/browser-runtime/ai/browser-wasm.mjs +46 -1
  12. package/browser-runtime/ai/browser-whisper-worker.mjs +3 -0
  13. package/browser-runtime/ai/browser-wllama-runtime.mjs +677 -132
  14. package/browser-runtime/ai/model-controller.mjs +138 -12
  15. package/browser-runtime/ai/speech-worker-client.mjs +207 -0
  16. package/browser-runtime/ai/speech-worker-runtime.mjs +516 -0
  17. package/browser-runtime/ai/wllama/index.mjs +389 -0
  18. package/docs/architecture.md +132 -22
  19. package/docs/reference/README.md +8 -5
  20. package/docs/reference/ai/browser-wasm.md +394 -0
  21. package/docs/reference/availability-and-normalization.md +31 -0
  22. package/docs/reference/behavioral-testing.md +21 -0
  23. package/docs/reference/cli.md +4 -4
  24. package/docs/reference/inventory/package-api.json +84 -4
  25. package/docs/reference/protocols.md +9 -8
  26. package/docs/reference/sdk-api.md +238 -4
  27. package/docs/work-amplification.md +8 -4
  28. package/package.json +7 -3
  29. package/runtime/ARCANE_RUNTIME_RELEASE.json +50 -20
  30. package/runtime/arcane/components/chat.html +280 -62
  31. package/runtime/arcane/components/speech.html +1113 -265
  32. package/runtime/arcane/entities/Chat.js +246 -43
  33. package/runtime/arcane/modules/AI.js +713 -162
  34. package/runtime/arcane/modules/AIProviderRuntime.js +2289 -0
  35. package/runtime/arcane/modules/AIRuntimeState.js +872 -0
  36. package/runtime/arcane/modules/ConfiguredAIChatSession.js +293 -27
  37. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +682 -0
  38. package/runtime/arcane/modules/DocumentLexicalSearch.js +292 -0
  39. package/runtime/arcane/modules/PersistentAIChatSession.js +268 -0
  40. package/runtime/arcane/modules/StaticDocumentCatalog.js +25 -206
  41. package/schemas/arcane-lock.schema.json +6 -4
  42. package/src/cli/main.mjs +14 -2
  43. package/src/constants.mjs +1 -1
  44. package/src/dev-server.mjs +246 -14
  45. package/src/doctor.mjs +1 -1
  46. package/src/import-map.mjs +59 -1
  47. package/src/packager/core.mjs +2 -2
  48. package/src/runtime.mjs +14 -4
  49. package/src/sdk-browser-runtime.mjs +28 -75
  50. package/src/templates/workspace-template.mjs +4 -4
  51. package/src/toolchain.mjs +3 -0
  52. package/src/workspace-runtime.mjs +1 -1
  53. package/src/workspace.mjs +1 -1
@@ -0,0 +1,394 @@
1
+ # Browser-WASM local AI
2
+
3
+ Use this browser-only entrypoint when an application deliberately owns a local
4
+ GGUF model authority and wants provider-neutral LLM lifecycle, chat, streaming,
5
+ cancellation, and structural tool-call results without an Arcane Core host.
6
+ For ordinary hosted applications, start with the [Arcane AI
7
+ contracts](../core/arcane-ai-contracts.md) and `globalThis.Arcane.ai`. This
8
+ page is the focused local-browser path beneath the normalized AI decision
9
+ guide.
10
+
11
+ The wiring example assumes a scaffolded or materialized Arcane application
12
+ with SDK `0.1.2`'s authenticated runtime tree and 86-entry browser import map.
13
+ `arcane/DBOPFS` is a managed browser-map specifier, not an npm package export.
14
+ See [browser runtime delivery](../protocols.md#browser-runtime-delivery) before
15
+ using the example in a custom host or bundler.
16
+
17
+ ```javascript
18
+ import DBOPFS from 'arcane/DBOPFS';
19
+ import {
20
+ createArcaneAI,
21
+ createBrowserModelSource,
22
+ createBrowserWasmLlmProvider,
23
+ createDbopfsModelStore
24
+ } from 'arcane-os/ai/browser-wasm';
25
+
26
+ const MODEL = Object.freeze({
27
+ id:'my-reviewed-model',
28
+ url:'https://models.example/revisions/4f7c/model-q4.gguf',
29
+ bytes:123456789,
30
+ sha256:'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
31
+ });
32
+
33
+ const dbopfs = globalThis.dbopfs || new DBOPFS({applicationId:'my-app'});
34
+ await dbopfs.readyPromise;
35
+ const source = createBrowserModelSource(MODEL);
36
+ const store = createDbopfsModelStore({dbopfs});
37
+ const provider = createBrowserWasmLlmProvider({source, store});
38
+ const ai = createArcaneAI({
39
+ provider,
40
+ loadPolicy:'manual',
41
+ security:{secure:true}
42
+ });
43
+
44
+ // Put this behind an explicit user action: it can download MODEL.bytes bytes.
45
+ async function loadReviewedModel() {
46
+ return ai.load({threads:1, contextTokens:4096, gpuLayers:0});
47
+ }
48
+ ```
49
+
50
+ The browser-WASM runtime closure packages the authenticated
51
+ `@wllama/wllama` `3.6.0` ESM and WebAssembly runtime plus the Wllama and
52
+ llama.cpp MIT license texts. It
53
+ packages no model weights, model catalog, CDN fallback, native provider, speech
54
+ synthesis, or transcription. Callers supply the exact model authority. `bytes`
55
+ is an optional expected positive byte length, not inline model data.
56
+
57
+ ## Lifecycle at a glance
58
+
59
+ `createArcaneAI()` owns one LLM controller. Its default `loadPolicy` is
60
+ `on-demand`; the first request may download and initialize the model. Use
61
+ `manual` when a user action, resource review, or progress UI must precede load.
62
+
63
+ | Operation | Result |
64
+ | --- | --- |
65
+ | `ai.status()` | Frozen `{llm: status}` wrapper. |
66
+ | `ai.load(options)` | Flat LLM status after load. |
67
+ | `ai.llm.chat(request)` / `ai.fetchRequest(request)` | Validated OpenAI-like completion. |
68
+ | `ai.llm.stream(request)` | Frozen async-iterator handle with `result` and `cancel(reason)`. |
69
+ | `ai.streamRequest(request)` | Consumes the stream and returns text or `{toolName: argumentJsonString}`. |
70
+ | `ai.unload()` | Cancels active work, releases the Wllama session, and returns flat unloaded status; the DBOPFS cache remains. |
71
+ | `ai.dispose()` | Permanently disposes the controller; explicit `store.remove(source)` is required to delete cached model bytes. |
72
+
73
+ The controller emits `statechange` and `progress` through
74
+ `addEventListener()`, `removeEventListener()`, or `on()`. Event `detail` is the
75
+ current frozen status. Provider states are `unloaded`, `loading`, `ready`,
76
+ `unloading`, and `error`.
77
+
78
+ ## Model authority, security, and cache admission
79
+
80
+ The canonical model descriptor is `{id, url, bytes?, sha256?}`. `id` and `url`
81
+ are required. The URL must be absolute HTTPS without credentials or a fragment;
82
+ revision-floating `main`, `master`, and `latest` path segments are rejected.
83
+ When supplied, `bytes` is a positive safe integer and `sha256` is exactly 64
84
+ hexadecimal characters.
85
+
86
+ App, provider/model-binding, and load-operation options use the same
87
+ plain-JavaScript shape:
88
+
89
+ ```javascript
90
+ {
91
+ security:{
92
+ secure:true,
93
+ checks:{byteLength:true, sha256:true}
94
+ }
95
+ }
96
+ ```
97
+
98
+ The SDK default is `secure:false`. Security fields resolve independently from
99
+ the load operation, then provider/model binding, then app configuration, then
100
+ the SDK default. Omitted fields inherit; they do not become `false`. After
101
+ resolution, `secure:true` makes both checks enabled by default and
102
+ `secure:false` makes both checks disabled by default. An explicit inherited or
103
+ lower-scope `checks.byteLength` or `checks.sha256` boolean overrides that secure
104
+ default for its check.
105
+
106
+ An enabled byte-length check requires descriptor `bytes` and compares it with
107
+ the actual cached or downloaded byte count. A disabled byte-length check permits
108
+ `bytes` to be absent and never rejects a cached or downloaded model by comparing
109
+ it with an expected size. The store still counts and records the observed byte
110
+ length for storage and progress metadata on every install and cache reuse.
111
+
112
+ An enabled SHA-256 check requires descriptor `sha256` and hashes the actual
113
+ stored or cached file. A disabled SHA-256 check permits `sha256` to be absent
114
+ and does not hash or reread a multi-gigabyte model solely to produce a digest.
115
+ Only enabled checks fail closed. Regardless of optional integrity checks, a
116
+ load succeeds only after Wllama reports that the model is loaded.
117
+
118
+ The DBOPFS adapter commits an `arcane.ai.browser-wasm.model.v3` completion
119
+ manifest with the observed byte length. Status reports the effective
120
+ `security.secure`, both effective check booleans, and per-check integrity
121
+ outcomes. Overall integrity is `verified` when every enabled check succeeded,
122
+ `pending` while an enabled check is running, and `unchecked` when neither check
123
+ is enabled. Before completion an enabled check reports `pending`; after a
124
+ successful load each check independently reports `verified` or `unchecked`.
125
+ `load({offline:true})` never
126
+ performs a model request; it uses a compatible cached entry or rejects with
127
+ `ARCANE_AI_MODEL_OFFLINE_MISS`.
128
+
129
+ ```javascript
130
+ const {security, integrity} = ai.status().llm;
131
+ console.log(security.secure, security.checks.byteLength, security.checks.sha256);
132
+ console.log(integrity.state); // 'unchecked' or 'verified'
133
+ console.log(integrity.byteLength.observed); // actual cached/downloaded bytes
134
+ ```
135
+
136
+ For compatibility, older descriptors can supply `immutableUrl` as the URL alias
137
+ and `name` as a cache-filename hint. If both `url` and `immutableUrl` are
138
+ present, they must match. Legacy `licenseSpdx` and `sourceRevision` properties
139
+ are not canonical descriptor fields or runtime admission checks; applications
140
+ remain responsible for model selection, provenance, and license compliance.
141
+ Version-2 cache manifests can be migrated to version 3 when their model identity
142
+ matches, without inventing an integrity result.
143
+
144
+ `localOnly:true` describes inference after load. It does not mean a cache miss
145
+ cannot download. Source downloads use CORS, omit credentials and referrer,
146
+ disable HTTP caching, and honor `AbortSignal`.
147
+
148
+ ## Streaming, cancellation, and tools
149
+
150
+ ```javascript
151
+ const abort = new AbortController();
152
+ const stream = ai.llm.stream({
153
+ localOnly:true,
154
+ signal:abort.signal,
155
+ messages:[{role:'user', content:'Summarize this text.'}],
156
+ maxTokens:128
157
+ });
158
+
159
+ const cancelButton = document.querySelector('[data-cancel-local-ai]');
160
+ const cancel = () => abort.abort('user cancelled');
161
+ cancelButton.addEventListener('click', cancel, {once:true});
162
+ try {
163
+ for await (const chunk of stream) renderChunk(chunk);
164
+ const completion = await stream.result;
165
+ renderCompletion(completion);
166
+ } catch (error) {
167
+ if (error?.code !== 'ARCANE_AI_REQUEST_ABORTED') throw error;
168
+ renderCancelled();
169
+ } finally {
170
+ cancelButton.removeEventListener('click', cancel);
171
+ }
172
+ ```
173
+
174
+ An active cancellation rejects as `ARCANE_AI_REQUEST_ABORTED`. Requests are
175
+ serialized; provider status exposes `busy` and `queued`. Supported request
176
+ generation fields include temperature, top-K, top-P, min-P, repeat penalty,
177
+ maximum tokens, seed, and stop sequences. Load settings separately include
178
+ `contextTokens`, `batchTokens`, `microBatchTokens`, `threads`, and GPU-layer
179
+ count. WebGPU is optional; cross-origin isolation and hardware fields are
180
+ observations, not readiness promises.
181
+
182
+ Tool definitions, tool choice, parallel-tool-call preference, and JSON or JSON
183
+ Schema structured-output requests are passed to Wllama. Returned tool calls are
184
+ validated and surfaced as structural data. Argument payloads remain JSON
185
+ strings. The SDK never invokes a handler or executes a tool; application code
186
+ must review policy, validate arguments, choose whether to execute, and submit a
187
+ later tool result.
188
+
189
+ ## Errors and unavailable states
190
+
191
+ Invalid configuration can throw `TypeError` or `RangeError`. Operational
192
+ failures expose a stable `.code`; the internal error class is not exported.
193
+ Handle the narrow code needed by the current operation and treat other failures
194
+ as unavailable.
195
+
196
+ | Area | Stable codes |
197
+ | --- | --- |
198
+ | 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
+ | 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` |
202
+ | Diagnostics | `ARCANE_AI_PROBE_FAILED` |
203
+
204
+ `capabilities()` reports browser observations such as WebAssembly, OPFS,
205
+ WebGPU, secure context, cross-origin isolation, and hardware concurrency.
206
+ Feature-detect them. The authoritative Chrome behavior passes without
207
+ cross-origin isolation, so that flag is not a hard gate. `probe()` exercises
208
+ packaged Wllama backend operations only while unloaded; it neither admits nor
209
+ downloads a model.
210
+
211
+ ## BROWSER_WASM_RUNTIME_AUTHORITY
212
+
213
+ ### Overview
214
+
215
+ Deep-frozen identity for the shipped browser runtime. Its protocol is
216
+ `arcane-ai-browser-wasm/2`; the provider adapter uses
217
+ `arcane-ai-adapter/1`. It records Wllama `3.6.0`, the embedded llama.cpp
218
+ revision, authenticated module/WASM byte lengths and SHA-256 values, licenses,
219
+ and the disabled compatibility-runtime and remote-model-helper policy.
220
+
221
+ ### Value and import
222
+
223
+ ```text
224
+ const BROWSER_WASM_RUNTIME_AUTHORITY
225
+ ```
226
+
227
+ ### Availability and normalization
228
+
229
+ **Browser metadata; safely inspectable without loading a model.** The value is
230
+ an immutable receipt, not a provider instance, model catalog, or capability
231
+ grant.
232
+
233
+ ### Example
234
+
235
+ ```javascript
236
+ import {BROWSER_WASM_RUNTIME_AUTHORITY} from 'arcane-os/ai/browser-wasm';
237
+
238
+ console.log(BROWSER_WASM_RUNTIME_AUTHORITY.protocol);
239
+ console.log(BROWSER_WASM_RUNTIME_AUTHORITY.package.version); // 3.6.0
240
+ ```
241
+
242
+ ## createArcaneAI()
243
+
244
+ ### Overview
245
+
246
+ Creates the application-facing facade around a provider or an existing LLM
247
+ controller. Use this as the primary browser-local API; construct the source,
248
+ store, and Wllama provider beneath it.
249
+
250
+ ### Signature and result
251
+
252
+ ```text
253
+ createArcaneAI({ llm=null, provider=null, loadPolicy='on-demand', security }={})
254
+ ```
255
+
256
+ At least one `llm` or `provider` is required; when both are supplied, `llm`
257
+ takes precedence. `loadPolicy` is `on-demand` or `manual`. The frozen result
258
+ contains `llm`, `runtime`, `status`, `load`,
259
+ `unload`, `probe`, `fetchRequest`, `streamRequest`, and `dispose`.
260
+ `security` is the app-level security configuration inherited by provider loads.
261
+ The SDK default is `secure:false`; `ai.load({security})` can override inherited
262
+ fields for that operation.
263
+
264
+ ### Availability and normalization
265
+
266
+ **Browser.** It normalizes provider lifecycle and request observation without
267
+ selecting a model, changing browser permissions, contacting Arcane Core, or
268
+ creating a fallback provider.
269
+
270
+ ### Example
271
+
272
+ ```javascript
273
+ const ai = createArcaneAI({provider, loadPolicy:'manual'});
274
+ const off = ai.llm.on('statechange', event => renderStatus(event.detail));
275
+ await ai.load({offline:true});
276
+ off();
277
+ ```
278
+
279
+ ## createBrowserModelSource()
280
+
281
+ ### Overview
282
+
283
+ Validates a caller-owned canonical `{id, url, bytes?, sha256?}` descriptor and
284
+ creates the one cancellable HTTPS download source accepted by this provider.
285
+
286
+ ### Signature and result
287
+
288
+ ```text
289
+ createBrowserModelSource(descriptor, { fetchImpl=null }={})
290
+ ```
291
+
292
+ The frozen source includes `kind`, the canonical descriptor fields,
293
+ `descriptor`, and `open({signal})`. `open()` returns a readable response body,
294
+ requested/final URLs, and `cancel()`; it does not admit bytes to the cache.
295
+
296
+ ### Availability and normalization
297
+
298
+ **Browser Fetch with CORS.** URL and optional metadata syntax are normalized.
299
+ Expected length and SHA-256 are enforced only when their effective checks are
300
+ enabled for load.
301
+
302
+ ### Example
303
+
304
+ ```javascript
305
+ const source = createBrowserModelSource(MODEL);
306
+ console.log(source.id, source.bytes, source.sha256);
307
+ ```
308
+
309
+ ## createBrowserWasmLlmProvider()
310
+
311
+ ### Overview
312
+
313
+ Creates the local-only Wllama provider from genuine source and store objects
314
+ created by this module. Structural lookalikes are rejected.
315
+
316
+ ### Signature and result
317
+
318
+ ```text
319
+ createBrowserWasmLlmProvider({ source, store, loadDefaults={}, security, logger=console }={})
320
+ ```
321
+
322
+ The frozen result exposes protocol and provider identity, model metadata,
323
+ `capabilities`, `status`, `load`, `unload`, `chat`, `stream`, `streamChat`,
324
+ `use`, `probe`, and `dispose`. Direct provider `load()` returns `{model,status}`;
325
+ the facade `ai.load()` returns the flat controller status.
326
+ Provider `security` supplies the provider/model-binding scope. Direct
327
+ `provider.load({security})` and facade `ai.load({security})` supply the
328
+ operation scope.
329
+
330
+ ### Availability and normalization
331
+
332
+ **Browser with WebAssembly and DBOPFS model bytes.** Inference is local after a
333
+ successful Wllama load. WebGPU is optional and defaults to zero GPU layers
334
+ unless the caller selects otherwise. Status discloses effective checks and
335
+ whether enabled integrity checks are pending, unchecked, or verified.
336
+
337
+ ### Example
338
+
339
+ ```javascript
340
+ const provider = createBrowserWasmLlmProvider({
341
+ source,
342
+ store,
343
+ loadDefaults:{threads:1, contextTokens:4096, gpuLayers:0}
344
+ });
345
+ console.log(provider.status().state); // unloaded
346
+ ```
347
+
348
+ ## createDbopfsModelStore()
349
+
350
+ ### Overview
351
+
352
+ Adapts an existing DBOPFS instance without renaming or replacing its public
353
+ methods. The adapter owns model-file, observed-byte, optional-check, and
354
+ completion-manifest behavior.
355
+
356
+ ### Signature and result
357
+
358
+ ```text
359
+ createDbopfsModelStore({ dbopfs, tableName='arcane_ai_browser_models' }={})
360
+ ```
361
+
362
+ The frozen result contains `kind`, `tableName`, the original `adapter`, and
363
+ `ready`, `openVerified`, `install`, `ensure`, and `remove`. `ensure()` returns a
364
+ file, completion manifest, observed byte count, integrity detail, and cache state
365
+ `cached` or `installed`. `openVerified()` remains a compatibility helper that
366
+ requires both byte-length and SHA-256 verification.
367
+
368
+ ### Availability and normalization
369
+
370
+ **Browser with a ready DBOPFS instance and OPFS.** A cache receipt reports only
371
+ the checks actually performed. Unchecked cache metadata is not integrity
372
+ evidence, and no cache receipt is a transferable capability token or proof of
373
+ model license rights.
374
+
375
+ ### Example
376
+
377
+ ```javascript
378
+ const store = createDbopfsModelStore({dbopfs});
379
+ await store.ready();
380
+ const cached = await store.openVerified(source);
381
+ console.log(cached ? 'verified cache' : 'cache miss');
382
+ ```
383
+
384
+ ## Related reference
385
+
386
+ - [Canonical `createArcaneAI()` entry](../sdk-api.md#createarcaneai) and the
387
+ sibling [`BROWSER_WASM_RUNTIME_AUTHORITY`](../sdk-api.md#browserwasmruntimeauthority),
388
+ [`createBrowserModelSource()`](../sdk-api.md#createbrowsermodelsource),
389
+ [`createBrowserWasmLlmProvider()`](../sdk-api.md#createbrowserwasmllmprovider),
390
+ and [`createDbopfsModelStore()`](../sdk-api.md#createdbopfsmodelstore) entries
391
+ - [Browser-local normalization boundary](../availability-and-normalization.md#browser-local-provider-adapter)
392
+ - [Authenticated browser runtime delivery](../protocols.md#browser-runtime-delivery)
393
+ - [Browser-WASM behavior evidence](../behavioral-testing.md#behavioral-coverage-model)
394
+ - [DBOPFS runtime module](../runtime-modules.md#dbopfsjs)
@@ -29,6 +29,7 @@ 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
+ | Run a caller-selected local LLM entirely in a browser renderer | `arcane-os/ai/browser-wasm` through `createArcaneAI()` | **Browser** only; WebAssembly and OPFS/DBOPFS are required, WebGPU is optional, and a cache miss uses the caller's HTTPS model URL unless `offline:true` | The facade normalizes lifecycle, status, security precedence, effective-check disclosure, streaming, cancellation, and structural tool-call visibility. The canonical model descriptor is `{id, url, bytes?, sha256?}`; license is application provenance policy, not a runtime admission check. |
32
33
  | 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. |
33
34
  | 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**. |
34
35
  | 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. |
@@ -77,6 +78,36 @@ deeply frozen, and strictly importable as `arcane-event-stack/1`. DOM
77
78
  instrumentation adds browser diagnostics only; it does not replay browser
78
79
  state. See [EventManager and time-travel review](event-manager.md).
79
80
 
81
+ ### Browser-local provider adapter
82
+
83
+ [`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) exposes the same
84
+ `arcane-ai-adapter/1` LLM lifecycle used by `createArcaneAI()`, while its
85
+ packaged Wllama engine and caller-supplied model run inside the browser. This
86
+ surface does not require an Arcane Core method grant because it does not call a
87
+ Core host. Browser Fetch, CORS, storage policy, secure-context behavior, and
88
+ resource limits still apply.
89
+
90
+ `localOnly:true` describes inference after load; it does not promise that load
91
+ is offline. A normal cache miss downloads from the exact caller-supplied HTTPS
92
+ URL. App, provider/model-binding, and load-operation options use
93
+ `{security:{secure?:boolean, checks?:{byteLength?:boolean, sha256?:boolean}}}`.
94
+ Fields resolve independently from load operation to provider/model binding to
95
+ app configuration to the SDK default `secure:false`; omitted fields inherit.
96
+ The resolved `secure` value supplies the default for both checks, and an
97
+ explicit per-check boolean overrides that default.
98
+
99
+ An enabled check requires and verifies its matching descriptor field. A
100
+ disabled byte-length check permits `bytes` to be absent and never compares an
101
+ expected size, although the actual downloaded or cached byte count is always
102
+ recorded for storage and progress metadata. A disabled SHA-256 check permits
103
+ `sha256` to be absent and performs no hash or digest-only reread. Status reports
104
+ the effective checks and distinguishes unchecked integrity from successful
105
+ verification of the enabled checks. Only enabled checks fail closed, while
106
+ successful Wllama model loading remains mandatory. `load({offline:true})` permits only a compatible
107
+ cache entry and otherwise rejects with `ARCANE_AI_MODEL_OFFLINE_MISS`. Tool
108
+ calls are result data for application review and dispatch; the SDK never
109
+ executes them.
110
+
80
111
  ### Arcane bridge-normalized
81
112
 
82
113
  Core-backed calls return promises and reject with `Arcane.Error`. Transport
@@ -37,6 +37,7 @@ 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
+ | Browser-WASM local AI | The exact exported namespace, canonical `{id, url, bytes?, sha256?}` descriptor, fieldwise app/provider/load security precedence, default-unchecked and secure-check paths, observed-byte persistence, honest status, 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`. |
40
41
  | 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. |
41
42
  | 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. |
42
43
  | 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. |
@@ -53,6 +54,26 @@ client contract. They must assert the exact request sent to the fake and the
53
54
  normalized result returned to the application. A fake provider never counts as
54
55
  native host, artifact, installation, or model-service evidence.
55
56
 
57
+ The browser-WASM guide follows the same rule: it shows exact model authority
58
+ and wiring, but leaves the download/load call behind an explicit user action.
59
+ Focused contracts cover the plain security shape and fieldwise precedence from
60
+ load operation to provider/model binding to app configuration to SDK default
61
+ `secure:false`. They prove that omitted values inherit, the resolved `secure`
62
+ value defaults both checks, and explicit per-check booleans override that
63
+ default.
64
+
65
+ The default path proves actual bytes are counted and persisted and Wllama
66
+ confirms a loaded model without requiring descriptor `bytes` or `sha256`.
67
+ Disabled byte-length checks never compare an expected count; disabled SHA-256
68
+ checks never instantiate hashing or reread a multi-gigabyte file solely for a
69
+ digest. Enabled-check cases prove the matching descriptor field is required and
70
+ fail closed on mismatch. Status cases distinguish effective checks, per-check
71
+ outcomes, and unchecked versus enabled-check-verified integrity. The authoritative
72
+ browser contract separately proves the enabled secure path hashes stored and
73
+ cached bytes, `AbortSignal` settles as `ARCANE_AI_REQUEST_ABORTED`, and tool-call
74
+ arguments are surfaced without invoking application handlers. Model license
75
+ metadata is never treated as runtime admission evidence.
76
+
56
77
  ## Host and normalization cases
57
78
 
58
79
  Cross-host APIs should cover at least these cases at their owning layer:
@@ -183,8 +183,8 @@ identical executable alias.
183
183
  The generated artifact is
184
184
  `apps/<id>/modules/arcane.importmap.json`. Its exact JSON is also installed in
185
185
  the app entry as `<script type="importmap" data-arcane-import-map>` before
186
- module loading. In SDK `0.1.0`, the authenticated physical-v1 runtime produces
187
- 85 entries and intentionally has no package-root mapping.
186
+ module loading. In SDK `0.1.2`, the authenticated physical-v1 runtime produces
187
+ 86 entries and intentionally has no package-root mapping.
188
188
 
189
189
  ### Result and safety
190
190
 
@@ -201,7 +201,7 @@ Success returns the normal selected-workspace wrapper:
201
201
  artifactRelativePath,
202
202
  entryPath,
203
203
  imports,
204
- entryCount:85,
204
+ entryCount:86,
205
205
  excludedModules:['modules/CaseEvidenceIndexer.js'],
206
206
  files:[
207
207
  {role:'artifact',path,bytes,sha256},
@@ -555,7 +555,7 @@ Success returns:
555
555
  {
556
556
  packageName:'arcane-os',
557
557
  currentVersion:'0.1.0',
558
- registryVersion:'0.1.1',
558
+ registryVersion:'0.1.2',
559
559
  tag:'latest',
560
560
  status:'update-available', // or 'current' or 'ahead'
561
561
  updateAvailable:true,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "sdkVersion": "0.1.0",
3
+ "sdkVersion": "0.2.0",
4
4
  "environment": {
5
- "runtime": "Node.js",
6
- "minimumVersion": "22.23.2",
5
+ "runtime": "Node.js for Node entrypoints; browser for browser-only entrypoints",
6
+ "minimumVersion": "22.23.2 for Node entrypoints",
7
7
  "moduleSystem": "ESM"
8
8
  },
9
- "memberCount": 158,
9
+ "memberCount": 163,
10
10
  "members": [
11
11
  {
12
12
  "id": "root:APP_BUNDLE_DESCRIPTOR_NAME",
@@ -2627,6 +2627,86 @@
2627
2627
  "availability": "Node; on-demand CLI or maintainer check only",
2628
2628
  "protocol": "Approved credential-free HTTPS registry origin",
2629
2629
  "normalization": "Returns a normalized URL object only for an exact allowed root origin"
2630
+ },
2631
+ {
2632
+ "id": "browser-wasm:BROWSER_WASM_RUNTIME_AUTHORITY",
2633
+ "name": "BROWSER_WASM_RUNTIME_AUTHORITY",
2634
+ "displayName": "BROWSER_WASM_RUNTIME_AUTHORITY",
2635
+ "kind": "constant",
2636
+ "signature": "const BROWSER_WASM_RUNTIME_AUTHORITY",
2637
+ "entrypoints": [
2638
+ "arcane-os/ai/browser-wasm"
2639
+ ],
2640
+ "primaryImport": "arcane-os/ai/browser-wasm",
2641
+ "group": "Browser-WASM local AI",
2642
+ "summary": "Deep-frozen authority for the packaged Wllama and llama.cpp runtime, authenticated JS and WASM assets, licensing, and disabled compatibility-network policy.",
2643
+ "availability": "Browser metadata; import and inspection require neither DBOPFS nor a loaded model",
2644
+ "protocol": "arcane-ai-browser-wasm/2 over the provider-neutral arcane-ai-adapter/1 boundary",
2645
+ "normalization": "Exact immutable runtime and component identity; it contains no model weights or model catalog"
2646
+ },
2647
+ {
2648
+ "id": "browser-wasm:createArcaneAI",
2649
+ "name": "createArcaneAI",
2650
+ "displayName": "createArcaneAI()",
2651
+ "kind": "function",
2652
+ "signature": "createArcaneAI({ llm=null, provider=null, loadPolicy='on-demand', security }={})",
2653
+ "entrypoints": [
2654
+ "arcane-os/ai/browser-wasm"
2655
+ ],
2656
+ "primaryImport": "arcane-os/ai/browser-wasm",
2657
+ "group": "Browser-WASM local AI",
2658
+ "summary": "Creates the provider-neutral browser AI facade and LLM lifecycle controller around one compatible provider or controller.",
2659
+ "availability": "Browser; the selected provider observes its own WebAssembly, storage, and model readiness",
2660
+ "protocol": "arcane-ai-adapter/1",
2661
+ "normalization": "Normalizes lazy or manual load, fieldwise app/provider/load security inheritance from SDK secure:false, lifecycle status, cancellation, streaming completion, and structural tool-call visibility without executing tools"
2662
+ },
2663
+ {
2664
+ "id": "browser-wasm:createBrowserModelSource",
2665
+ "name": "createBrowserModelSource",
2666
+ "displayName": "createBrowserModelSource()",
2667
+ "kind": "function",
2668
+ "signature": "createBrowserModelSource(descriptor, { fetchImpl=null }={})",
2669
+ "entrypoints": [
2670
+ "arcane-os/ai/browser-wasm"
2671
+ ],
2672
+ "primaryImport": "arcane-os/ai/browser-wasm",
2673
+ "group": "Browser-WASM local AI",
2674
+ "summary": "Validates a canonical caller-supplied {id, url, bytes?, sha256?} descriptor and creates its cancellable no-credentials HTTPS download source.",
2675
+ "availability": "Browser with Fetch and a readable response body; each direct open call performs its configured HTTPS fetch",
2676
+ "protocol": "Caller-supplied immutable HTTPS model URL with optional expected byte length and SHA-256",
2677
+ "normalization": "Canonical frozen descriptor and download handle; expected fields are required and enforced only for their effective enabled checks, and model license is not runtime admission"
2678
+ },
2679
+ {
2680
+ "id": "browser-wasm:createBrowserWasmLlmProvider",
2681
+ "name": "createBrowserWasmLlmProvider",
2682
+ "displayName": "createBrowserWasmLlmProvider()",
2683
+ "kind": "function",
2684
+ "signature": "createBrowserWasmLlmProvider({ source, store, loadDefaults={}, security, logger=console }={})",
2685
+ "entrypoints": [
2686
+ "arcane-os/ai/browser-wasm"
2687
+ ],
2688
+ "primaryImport": "arcane-os/ai/browser-wasm",
2689
+ "group": "Browser-WASM local AI",
2690
+ "summary": "Creates the packaged Wllama browser provider with effective-check disclosure, honest integrity status, serialized inference, streaming, abort, unload, and probe operations.",
2691
+ "availability": "Browser; WebAssembly required, WebGPU optional, enabled checks fail closed, and successful Wllama loading is always required",
2692
+ "protocol": "arcane-ai-adapter/1 with OpenAI-like chat completion and streaming envelopes",
2693
+ "normalization": "Frozen lifecycle/status/security/integrity records and structured tool-call data; security fields inherit by scope and the SDK never invokes application tools"
2694
+ },
2695
+ {
2696
+ "id": "browser-wasm:createDbopfsModelStore",
2697
+ "name": "createDbopfsModelStore",
2698
+ "displayName": "createDbopfsModelStore()",
2699
+ "kind": "function",
2700
+ "signature": "createDbopfsModelStore({ dbopfs, tableName='arcane_ai_browser_models' }={})",
2701
+ "entrypoints": [
2702
+ "arcane-os/ai/browser-wasm"
2703
+ ],
2704
+ "primaryImport": "arcane-os/ai/browser-wasm",
2705
+ "group": "Browser-WASM local AI",
2706
+ "summary": "Adapts an existing DBOPFS instance into a model cache that records observed bytes, commits metadata last, and hashes only when SHA-256 checking is enabled.",
2707
+ "availability": "Browser with a ready DBOPFS instance and OPFS support",
2708
+ "protocol": "arcane.ai.browser-wasm.model.v3 completion manifests over existing DBOPFS method semantics",
2709
+ "normalization": "Returns cached or installed receipts with observed byte count and per-check outcomes; disabled expected-length and SHA-256 checks do not compare or hash, while enabled checks fail closed"
2630
2710
  }
2631
2711
  ]
2632
2712
  }
@@ -104,8 +104,8 @@ import ollama from 'arcane/Ollama';
104
104
  ```
105
105
 
106
106
  The authenticated physical-v1 tree lives entirely beneath `arcane/`. It
107
- contains 155 pinned Arcane runtime files plus eight SDK browser-runtime files:
108
- 163 files in all. Runtime `strong-type` 1.1 stays under
107
+ contains 155 pinned Arcane runtime files plus 18 SDK browser-runtime files:
108
+ 173 files in all. Runtime `strong-type` 1.1 stays under
109
109
  `arcane/dependencies/strong-type/`; the focused SDK event surface lives under
110
110
  `arcane/sdk/`, with `event-pubsub` 6.1 and its sibling `strong-type` 2.0 under
111
111
  `arcane/sdk/dependencies/`. This URL-key separation prevents the runtime and SDK
@@ -114,13 +114,14 @@ app plus that authenticated tree. Packaging copies the same map, app entry, and
114
114
  physical bytes into `dist/<id>`; targets never resolve through the consumer
115
115
  workspace's root `node_modules/`.
116
116
 
117
- In SDK `0.1.0`, the generated map has exactly 85 entries: 73 named
118
- `arcane/*` modules, nine `arcane/entities/*` modules, and these three focused or
117
+ In SDK `0.1.2`, the generated map has exactly 86 entries: 73 named
118
+ `arcane/*` modules, nine `arcane/entities/*` modules, and these four focused or
119
119
  compatibility mappings:
120
120
 
121
121
  | Browser specifier | Physical target |
122
122
  | --- | --- |
123
123
  | `arcane-os/event-manager` | `./arcane/sdk/event-manager.mjs` |
124
+ | `arcane-os/ai/browser-wasm` | `./arcane/sdk/ai/browser-wasm.mjs` |
124
125
  | `event-pubsub` | `./arcane/sdk/dependencies/event-pubsub/index.js` |
125
126
  | `./node_modules/strong-type/index.js` | `./arcane/dependencies/strong-type/index.js` |
126
127
 
@@ -167,14 +168,14 @@ heartbeat is event telemetry only and never regenerates browser state.
167
168
 
168
169
  `arcane.lock.json.sdkBrowserRuntime` persists the trusted manifest path,
169
170
  `manifestSha256`, `contentSha256`, `builder`, `sdkVersion`, and `source` record.
170
- For SDK `0.1.0` those identities are:
171
+ For SDK `0.1.2` those identities are:
171
172
 
172
173
  ```text
173
174
  manifest: node_modules/arcane-os/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json
174
- manifestSha256: 43baaec850291c28795f6c194001deb5febab88ccab1b033bce6597dd6f6f08f
175
- contentSha256: 0caa302bc07d4a45f5290504ec62ddce98fdf5e3412f916c10aae3d51b1e5f7c
175
+ manifestSha256: 88395493b411fd5461fbb2bb065ae2b745f6d1672f796583fd248ec97f71f4f7
176
+ contentSha256: 5e03f45a732db51cb5a2b2193cc79ecda34501d07a9b2e82e794e5fa37d55d00
176
177
  builder: arcane-sdk-browser-runtime-v1
177
- sdkVersion: 0.1.0
178
+ sdkVersion: 0.1.2
178
179
  source.protocol: arcane-sdk-browser-runtime/1
179
180
  source.browserEntry: arcane-os/event-manager
180
181
  ```