arcane-os 0.76.0 → 0.78.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.
@@ -121,7 +121,7 @@ own asynchronous work, cancellation, and backpressure.
121
121
  | [`OpenMeteoWeatherProvider.js`](#openmeteoweatherproviderjs) | esm | Searches and loads Open-Meteo data into complete mutable Arcane weather entities. | Browser / native WebView / server with fetch + cloud | Provider data normalized to mutable entities; transport errors mixed. |
122
122
  | [`PersistentAIChatSession.js`](#persistentaichatsessionjs) | esm | Adds explicit retained-history/memory policy to complete configured chat without changing DBOPFS or ChatEntity semantics. | Browser / native WebView with DBOPFS and configured chat | Retained context commits atomically; `persist:false` turns are one-operation-only. |
123
123
  | [`PreferenceStore.js`](#preferencestorejs) | esm | Loads and updates schema-defined app preferences through native storage with a narrow browser fallback. | Browser/native hybrid | Complete values and operation context retained; exact optional namespace absence or existing Android unsupported capability selects the existing local adapter; partial-service and genuine failures remain errors; an advertised rejected batch is never retried serially. |
124
- | [`PreparedSpeech.js`](#preparedspeechjs) | esm | Owns detached ordered preparation, semantic audio reuse, and per-caller cancellation behind AI.prepareTTS. | Browser / native WebView with injected synthesis and optional DBOPFS | Complete original inputs, ordered audio metadata, durable reuse, and observable preparation results. |
124
+ | [`PreparedSpeech.js`](#preparedspeechjs) | esm | Owns detached ordered preparation, semantic audio reuse, cache-only lookup, and per-caller cancellation behind AI.prepareTTS and AI.readPreparedTTS. | Browser / native WebView with optional DBOPFS and injected synthesis for generation | Complete original inputs, ordered audio metadata, durable reuse, and observable preparation results. |
125
125
  | [`PrintView.js`](#printviewjs) | esm | Prints current rendered content and title through one document-owned print lifecycle. | Browser / supported native WebView print implementation | Complete rendered snapshot, preparation cancellation, resource lifetime, and honest request result. |
126
126
  | [`QRCode.min.js`](#qrcodeminjs) | classic-script | Vendored QRCode generator for DOM, canvas, SVG, and image output. | Browser vendor script | Vendor-native. |
127
127
  | [`Questionnaire.js`](#questionnairejs) | esm | Evaluates whether a one-time questionnaire prompt is due without performing the prompt. | Cross-host | Normalized conservative boolean. |
@@ -171,10 +171,12 @@ default `AI`; read-only `providerRuntime`, `speechActivationPending`, `browserSp
171
171
  read-only `ttsSegmentation`, `configureTTSSegmentation()`,
172
172
  `streamTTS(text='',end=false,options={})`,
173
173
  `prepareTTS({parts,textFormat,storage,identity,signal,onState})`,
174
- `playPreparedTTS(prepared,{signal,onState})`,
174
+ `readPreparedTTS({parts,textFormat,storage,identity,signal,onState})`,
175
+ `prepareAudioOutput()`, `playPreparedTTS(prepared,{signal,onState,audioOutput})`,
175
176
  `finishTTS()`, `prepareTTSPlayback()`, `fetchTTS()`, `fetchSTT()`, `stopAudio()`, `resumeAudio()`,
176
177
  `playAudio()`; consumes `user-entity-loaded` and `arcane-ollama-ready`,
177
- installs `window.ai`, and emits `ai-ready` and `ai-tts-failure`.
178
+ installs `window.ai`, and emits `ai-ready`, `ai-tts-failure`, and
179
+ `AI_AUDIO_OUTPUT_STATE_EVENT` (`'ai-audio-output-state'`).
178
180
 
179
181
  `fetch(...)` and `fetchRequest(options)` are asynchronous complete-response
180
182
  entry points. `streamMessage(...)` and `streamRequest(options)` deliver
@@ -496,7 +498,35 @@ cancelling one handle does not cancel another active matching caller.
496
498
  Preparation cancellation prevents later synthesis and releases its activation
497
499
  interest. The provider's operation remains responsible for actual cleanup.
498
500
 
499
- `playPreparedTTS(prepared,{signal,onState})` can attach immediately. Its returned
501
+ `await readPreparedTTS({parts,textFormat,storage,identity,signal,onState})`
502
+ returns a complete ready preparation handle or `null`. It uses the same original
503
+ parts, selected speech configuration, voice/speed/pause values, text treatment,
504
+ segmentation, and application identity as `prepareTTS()` for semantic matching.
505
+ It never activates or unmutes a provider, synthesizes, starts playback, writes
506
+ storage, or repairs a partial record. With storage, it reads the existing
507
+ manifest and every ordered audio reference through the existing per-key storage
508
+ queue. It passes `{createTable:false}` to DBOPFS manifest and audio reads,
509
+ including later handle reads, so missing tables stay absent. Supplied database
510
+ adapters are responsible for honoring that read-existing contract.
511
+ No matching record or any missing audio returns `null`; unreadable
512
+ metadata and other storage errors reject. Without storage, only a completed,
513
+ matching, same-AI retained in-memory preparation can be returned; pending or
514
+ failed work returns `null`.
515
+
516
+ A hit returns `{segments,state,ready,getAudio(index),cancel()}` with `state`
517
+ and every segment already `ready`; `onState` synchronously replays that state.
518
+ A miss emits no state callback. The lookup signal rejects cancellation as
519
+ `AbortError` and detaches when lookup settles; aborting it after success does
520
+ not cancel the returned handle. An already-started non-abortable database read
521
+ may finish after cancellation; observed cancellation prevents subsequent reads
522
+ or a returned handle. The handle's explicit `cancel()` retains its
523
+ own lifetime. Durable `getAudio(index)` reopens the stored file with its retained
524
+ MIME type, so a later file removal remains an observable error. Native speech
525
+ without audio export rejects with `ARCANE_AI_TTS_AUDIO_EXPORT_UNAVAILABLE`, as
526
+ `prepareTTS()` does. Pass a returned handle to `playPreparedTTS()` only when
527
+ playback is wanted.
528
+
529
+ `playPreparedTTS(prepared,{signal,onState,audioOutput})` can attach immediately. Its returned
500
530
  `{state,error,finished,pause(),resume(),stop()}` handle schedules segments in
501
531
  their original order using the existing AI audio clock. `finished` resolves `true` after
502
532
  natural completion and `false` after stop, cancellation, or failure; genuine
@@ -521,6 +551,38 @@ model even when the AI starts muted. Missing audio alone requests the shared
521
551
  TTS readiness path. See [prepared narration](ai/browser-speech.md#prepare-narration-once-and-replay-stored-audio)
522
552
  for full record shapes, storage ownership, and a complete example.
523
553
 
554
+ `prepareAudioOutput()` synchronously creates or reuses this AI's persistent
555
+ WebAudio context and returns the same handle until disposed or closed. It is
556
+ silent: no resume, unmute, model load, source creation, test sound, or gesture
557
+ listener registration. The handle exposes `kind:'web-audio'`, current
558
+ `state`, `contextState`, and complete `error` getters, plus
559
+ `subscribe(listener)`, `resume()`, and `dispose()`.
560
+ `subscribe` immediately replays `{kind,state,contextState,error}`, observes
561
+ future changes for this output, and returns an idempotent unsubscribe function.
562
+ The named `AI_AUDIO_OUTPUT_STATE_EVENT` export identifies canonical occurrences
563
+ with that snapshot as `detail` and an output-specific `operationId`.
564
+
565
+ Output `ready` means its context is actually `running`, independently of model
566
+ readiness, HTML audio, native speech, future autoplay permission, or audible
567
+ delivery. Other states are the platform's current state (including `suspended`
568
+ or `interrupted`), `gesture-required` after an actual `NotAllowedError`,
569
+ `unavailable` when context creation fails, `error`, `disposing`, `disposed`,
570
+ or `closed`. Explicit `resume()` resolves a boolean for actual readiness;
571
+ unavailable/disposed, superseded, or paused-playback cases resolve `false`.
572
+ Platform rejection rejects with the actual error and retains observable state.
573
+
574
+ Pass `{audioOutput}` to `playPreparedTTS` to borrow that same AI's live output;
575
+ another owner's, closed, or disposing handle throws `TypeError`. Borrowed
576
+ playback leaves the context open after completion or stop. Omission or `null`
577
+ preserves the existing per-playback context and terminal context close.
578
+ Owner `dispose()` stops context-bound playback and dependent clock work,
579
+ observes cleanup, and awaits actual close without cancelling detached speech
580
+ preparation or deleting saved audio. Concurrent disposal calls share their
581
+ promise; failures remain observable and a failed close can be retried.
582
+ Disposal/closure releases handle subscriptions after their final notification.
583
+ See [silent reusable output](ai/browser-speech.md#prepare-a-silent-reusable-webaudio-output)
584
+ for state details and usage.
585
+
524
586
  Streaming speech retains sentence
525
587
  segmentation by default. `configureTTSSegmentation({punctuation,wordCadence})`
526
588
  accepts `punctuation:'sentence'|'any'|'none'` and a `wordCadence` that is either
@@ -2221,6 +2283,23 @@ default `DBOPFS`; installs `window.dbopfs`, emits `dbopfs-ready`; table/file/bac
2221
2283
 
2222
2284
  Exact exports: `DBOPFS_EVENT_TYPES`, `DBOPFS_REASONS`, `default`.
2223
2285
 
2286
+ `getTableHandle(tableName='', {create=true}={})` lazily opens or creates the
2287
+ requested table by default. `{create:false}` looks up only an existing table
2288
+ without joining a pending create request; a missing table rejects with the
2289
+ platform's `NotFoundError`. The existing `memories` / `memory` alias is retained.
2290
+ `readFile(tableName='', fileName='', {createTable=true}={})` returns the complete
2291
+ raw file. `{createTable:false}` also prevents table creation, and missing tables
2292
+ or files reject with `NotFoundError`. Its synchronous-access worker fallback
2293
+ already opens existing app/table/file handles without creating them.
2294
+
2295
+ `get(tableName='', fileName='', force=false, {createTable=true}={})` retains its
2296
+ existing parsed-value cache and `force` behavior, forwarding `createTable` when
2297
+ it reads a file. On a read, `NotFoundError` resolves `null`; other errors reject.
2298
+ Use `get(tableName,fileName,true,{createTable:false})` for an existing-storage
2299
+ lookup that does not return an earlier cached value. Omitted options preserve the previous
2300
+ lazy table-creation behavior. These options change neither write operations nor
2301
+ the owning app scope's initialization.
2302
+
2224
2303
  `subscribeChanges(listener, {signal, once})` observes
2225
2304
  `DBOPFS_EVENT_TYPES.change` (`dbopfs-change`) through the existing canonical
2226
2305
  `arcane-os/event-manager` source. It returns an idempotent unsubscribe function
@@ -3616,10 +3695,11 @@ console.log(Object.keys(module));
3616
3695
 
3617
3696
  ### Overview
3618
3697
 
3619
- Shared preparation mechanism used by `AI.prepareTTS()`. It owns ordered
3620
- generation admission, same-owner request sharing, complete audio storage and
3621
- semantic reuse, and each caller's preparation lifetime. It does not construct
3622
- an audio context, play speech, or select application content.
3698
+ Shared preparation mechanism used by `AI.prepareTTS()` and `AI.readPreparedTTS()`.
3699
+ It owns ordered generation admission, same-owner request sharing, complete audio
3700
+ storage and semantic reuse, cache-only lookup, and each caller's preparation
3701
+ lifetime. It does not construct an audio context, play speech, or select
3702
+ application content.
3623
3703
 
3624
3704
  ### Public surface
3625
3705
 
@@ -3628,10 +3708,29 @@ segmentation=null,storage=null,identity=null,signal=null,onState,synthesize})`.
3628
3708
  The owning AI supplies already segmented speech parts, complete original parts,
3629
3709
  its selection snapshot, and its synthesis callback. The returned handle is
3630
3710
  `{segments,state,ready,getAudio(index),cancel()}`. Applications use
3631
- `AI.prepareTTS()` and `AI.playPreparedTTS()` so the existing AI owner retains
3632
- automatic formatting cleanup, segmentation, provider readiness/capacity, and
3711
+ `AI.prepareTTS()`, `AI.readPreparedTTS()`, and `AI.playPreparedTTS()` so the existing
3712
+ AI owner retains automatic formatting cleanup, segmentation, provider readiness/capacity, and
3633
3713
  ordered playback. See the [complete preparation contract](ai/browser-speech.md#prepare-narration-once-and-replay-stored-audio).
3634
3714
 
3715
+ Named async `readPreparedSpeech({owner,parts,originalParts=parts,selection=null,
3716
+ segmentation=null,storage=null,identity=null,signal=null,onState=null})` uses
3717
+ the same complete semantic matcher and resolves a ready preparation handle or
3718
+ `null`. It performs no synthesis, model activation, playback, storage writes,
3719
+ or repair. A durable lookup reads the existing manifest and every audio file;
3720
+ missing matching records or audio return `null`, while malformed metadata and
3721
+ other read failures reject. Manifest, audio availability, and returned-handle
3722
+ audio reads pass `{createTable:false}` to DBOPFS so a missing table is never
3723
+ created; supplied adapters own the same read-existing behavior. Without storage
3724
+ it reads only a completed matching same-owner in-memory preparation, never
3725
+ pending or failed work. A hit replays
3726
+ ready state through `onState`; a miss emits nothing. Lookup cancellation rejects
3727
+ with `AbortError` and is detached on settlement. After success the returned
3728
+ handle's explicit `cancel()` is independent of the lookup signal; its `ready`
3729
+ resolves the complete record and `getAudio(index)` preserves the existing MIME
3730
+ and later-read error behavior. Already-started non-abortable database reads may
3731
+ settle after cancellation; no further reads or handle are returned after the
3732
+ cancellation is observed.
3733
+
3635
3734
  `storage:{db,table,key}` is optional; the ready DBOPFS instance supplies
3636
3735
  `get`, `set`, `readFile`, and `writeFile`. JSON-compatible semantic inputs stay
3637
3736
  complete in the version-1 manifest. Raw audio is persisted separately and its
@@ -3639,13 +3738,14 @@ MIME type is retained in metadata. Storage mutation serializes by database,
3639
3738
  table, and key within the realm. Synthesis sharing is scoped to the same owner
3640
3739
  and matching semantic inputs/storage; playback remains outside this module.
3641
3740
 
3642
- Exact exports: `prepareSpeech`.
3741
+ Exact exports: `prepareSpeech`, `readPreparedSpeech`.
3643
3742
 
3644
3743
  ### Availability and normalization
3645
3744
 
3646
- **Browser or native WebView with Blob, AbortController, an injected synthesis
3647
- callback, and optional ready DBOPFS.** Import creates no provider or
3648
- playback. Calling the preparation function starts owned asynchronous work.
3745
+ **Browser or native WebView with Blob, AbortController, optional ready DBOPFS,
3746
+ and an injected synthesis callback for generation.** Import creates no provider or
3747
+ playback. Calling `prepareSpeech` starts owned asynchronous generation/reuse;
3748
+ `readPreparedSpeech` only reads existing complete audio.
3649
3749
  `ready` rejects complete synthesis/storage failures or `AbortError` after
3650
3750
  cancellation; successful audio remains available for reuse. Malformed part,
3651
3751
  storage, or semantic metadata inputs throw `TypeError`; an invalid segment
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.76.0",
3
+ "version": "0.78.0",
4
4
  "description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -125,7 +125,7 @@
125
125
  "test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/app-selection.test.mjs test/contracts.test.mjs test/conversation-closing-report.test.mjs test/doctor.test.mjs test/mail-credentials.test.mjs test/mail-outbox.test.mjs test/mail-public-api.test.mjs test/mail-send.test.mjs test/mail-transport.test.mjs test/native-windows-icon.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
126
126
  "test:functional": "node ./bin/arcane-test.mjs test/ai-ollama-readiness.test.mjs test/core-ollama-lifecycle.test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-decisions.test.mjs test/browser-kokoro-complete-input.test.mjs test/browser-speech-providers.test.mjs test/browser-speech-artifacts.test.mjs test/browser-speech-resource-bridge.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/codex-app-server.test.mjs test/mcp-stdio-server.test.mjs test/core-classic-source.test.mjs test/core-client.test.mjs test/core-client-installation.test.mjs test/core-ai-installation.test.mjs test/core-llama-lifecycle.test.mjs test/core-development.test.mjs test/core-host.test.mjs test/core-shared-host.test.mjs test/core-model-assets.test.mjs test/core-native-services.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-committed-events.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-model-resources.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/local-image-editing.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/model-resource-bridge.test.mjs test/native-decisions.test.mjs test/native-onnx.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
127
127
  "test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-macos-provider.test.mjs test/native-plan.test.mjs test/native-portable-provider.test.mjs test/native-provider-loader.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
128
- "test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/html-import-packaged-script.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
128
+ "test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/html-import-packaged-script.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/ai-audio-output.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
129
129
  "check": "node tools/check-source.mjs && npm test",
130
130
  "check:release": "node tools/check-source.mjs --package-only && npm run test:release",
131
131
  "pack:local": "npm pack --ignore-scripts",