arcane-os 0.95.0 → 0.97.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.
@@ -115,6 +115,8 @@ own asynchronous work, cancellation, and backpressure.
115
115
  | [`MemoryRecords.js`](#memoryrecordsjs) | esm | Normalizes memory content and detects meaningful stored memory. | Cross-host | Fully normalized string/boolean results. |
116
116
  | [`MessageAdvisory.js`](#messageadvisoryjs) | esm | Normalizes message content advisories and contains per-message inspection failures. | Cross-host | Normalized advisory records; inspector failures converted to unavailable results. |
117
117
  | [`ModelDefinition.js`](#modeldefinitionjs) | esm | Parses the deterministic packaged Modelfile subset and extracts the SYSTEM prompt. | Cross-host | Complete mutable definition with coded malformed-input errors. |
118
+ | [`NativeSpeechCapture.js`](#nativespeechcapturejs) | esm | Connects microphone PCM to one retained Core recognition stream. | Browser / native WebView with streaming Core speech | Complete snapshots, retained endpoint scope and joined capture/native cleanup. |
119
+ | [`NativeSpeechPlayback.js`](#nativespeechplaybackjs) | esm | Prepares and plays ordered native PCM using shared Web Audio. | Browser / native WebView with streaming speech | Inert preparation, exact audio order and separate playback/release completion. |
118
120
  | [`Ollama.js`](#ollamajs) | esm | Provides the first-class Arcane Ollama client without direct access to localhost:11434. | Native bridge | Principal methods preserve provider-native envelopes; readiness/text/unload helpers normalize. |
119
121
  | [`OllamaModelIdentifier.js`](#ollamamodelidentifierjs) | esm | Validates and canonicalizes the syntax of Ollama model identifiers without granting model admission. | Cross-host | Fully normalized string/boolean result. |
120
122
  | [`OllamaSettings.js`](#ollamasettingsjs) | esm | Defines complete runtime/service preference schemas and deterministic Arcane brain alias names. | Cross-host | Fully normalized settings/name contract. |
@@ -155,6 +157,12 @@ own asynchronous work, cancellation, and backpressure.
155
157
 
156
158
  ### Overview
157
159
 
160
+ Explicit speech-only construction uses
161
+ `new AI(null, 'LOCAL_SPEACH', 'LOCAL_SPEACH', null, ttsModel, sttModel)`.
162
+ Both LLM arguments must be `null`; no default LLM is selected or activated.
163
+ Omitted or empty arguments retain historical defaults, and an existing
164
+ `window.ai` singleton is reused. Later `configureProviders` can select an LLM.
165
+
158
166
  Provider-selectable chat, speech-to-text, text-to-speech, tool calling,
159
167
  structured output, streaming, bounded synthesis, and ordered audio-clock
160
168
  playback.
@@ -174,6 +182,7 @@ read-only `ttsSegmentation`, `configureTTSSegmentation()`,
174
182
  `readPreparedTTS({parts,textFormat,storage,identity,signal,onState})`,
175
183
  `prepareAudioOutput()`, `playPreparedTTS(prepared,{signal,onState,audioOutput})`,
176
184
  `finishTTS()`, `prepareTTSPlayback()`, `fetchTTS()`, `fetchSTT()`, `stopAudio()`, `resumeAudio()`,
185
+ `supportsTranscriptionCapture()`, `createTranscriptionCapture(options={})`,
177
186
  `playAudio()`; consumes `user-entity-loaded` and `arcane-ollama-ready`,
178
187
  installs `window.ai`, and emits `ai-ready`, `ai-tts-failure`, and
179
188
  `AI_AUDIO_OUTPUT_STATE_EVENT` (`'ai-audio-output-state'`).
@@ -415,7 +424,7 @@ physical accelerator; WebNN may execute unsupported operations through WASM.
415
424
  Calling `status()` without options keeps
416
425
  the existing sticky lifecycle snapshot and does not inspect provider execution.
417
426
  Provider inspection failures are surfaced to the caller.
418
- `fetchTTS({model,voice,input,responseFormat,speed},signal,preparation={})` accepts the public
427
+ `fetchTTS({model,voice,input,responseFormat,languageCode,speed},signal,preparation={})` accepts the public
419
428
  provider-neutral synthesis shape, requires any explicit model to match the
420
429
  selected route, and fills an omitted voice only from the selected model
421
430
  catalog's `defaultVoice`. An omitted response format preserves the instance's
@@ -438,13 +447,15 @@ default cleanup. The third `preparation` argument is reserved for SDK-internal
438
447
  delegation, where `{speechInputPrepared:true}` prevents a second cleanup pass;
439
448
  applications omit it. `streamTTS(text='',end=false,options={})` and
440
449
  `finishTTS()` use the selected playback boundary. The third-argument options below
441
- are available in SDK `0.5.12`. In these streaming options, the `textFormat`
450
+ are available from SDK `0.5.12`, with `languageCode` added in `0.95.0`.
451
+ In these streaming options, the `textFormat`
442
452
  compatibility extra added in SDK `0.5.16` remains ignored:
443
453
 
444
454
  | Field | Default | Meaning |
445
455
  | --- | --- | --- |
446
456
  | `voice` | Current selected model's default voice | A supplied voice is captured for every segment extracted by this call and forwarded unchanged to `fetchTTS()`. It does not change the instance or provider default. |
447
457
  | `speed` | Current `ai.voiceSpeed` | A supplied positive speed is captured for those segments and forwarded to `fetchTTS()`. It does not change `ai.voiceSpeed`. |
458
+ | `languageCode` | Selected engine's language default | Per-utterance language control, separate from the unchanged text. Support belongs to the selected engine/tokenizer; Magpie uses natural speed `1`. |
448
459
  | `pauseAfterMs` | `0` | Finite, nonnegative milliseconds placed after the final extracted segment on the existing audio clock. Invalid values throw `RangeError`; no pause is inserted between this call's other segments. |
449
460
  | `waitForPlayback` | `false` | Omission retains the preparation promise. With `true`, the promise resolves after every extracted segment reaches a terminal playback state: `true` when all naturally end, or `false` after terminal cancellation or failure. |
450
461
  | `textFormat` | Ignored streaming compatibility extra | Streaming narration retains automatic cleanup. The public plain selection belongs to complete synthesis payloads or `prepareTTS` options. |
@@ -461,13 +472,24 @@ formatting state. Streaming `textFormat` is not an opt-out.
461
472
 
462
473
  Voice, speed, pause, and playback overrides belong to the segments
463
474
  extracted in that invocation, including any text buffered by an earlier call.
464
- Those overrides are not retained with an unfinished `end:false` remainder; a
465
- later call supplies its own options, and `finishTTS()` uses their defaults
466
- while flushing any pending formatting mark. Use `end:true`
467
- for a complete passage. A call extracting no segments resolves
468
- `true` without waiting for earlier jobs; `finishTTS()` remains a preparation
475
+ Voice, speed and languageCode are retained with an unfinished `end:false`
476
+ utterance through continuation and `finishTTS()`. Explicitly changed language
477
+ first queues the old remainder under its prior selection, then accepts new text.
478
+ End, mute and stop clear the retained selection. Pause and waitForPlayback
479
+ remain per-call controls.
480
+
481
+ Use `end:true` for a complete passage. A call extracting no segments resolves
482
+ `true` without waiting for earlier jobs, except that a language-change call also
483
+ joins its preceding remainder preparation. `finishTTS()` remains a preparation
469
484
  flush, not a queue-wide playback barrier. A muted call resolves `false`.
470
485
 
486
+ A native engine catalog with `speech.streaming:true` selects an inert PCM
487
+ playback descriptor through `prepareTTSPlayback`. Explicit play uses the shared
488
+ provider lane and Web Audio output; `released` joins native cleanup independently
489
+ of `finished`. Magpie also retains complete-audio `fetchTTS`; browser-native
490
+ voices without audio export retain their existing unsupported result. See
491
+ [shared native capture/playback](native-speech.md#shared-ai-capture-and-playback).
492
+
471
493
  `prepareTTSPlayback(payload,signal,preparation={})` is the silent playback-oriented
472
494
  request. Audio-file providers retain the `fetchTTS()` Blob contract; a selected
473
495
  model with `speech.playback:'native'` returns an inert `native-speech` descriptor.
@@ -1130,6 +1152,17 @@ The singleton exposes read-only `protocol`, `configured`, and `speechMuted`;
1130
1152
  `setSpeechMuted(muted,{signal}={})`. Provider payloads must be data-only; callbacks,
1131
1153
  accessors, symbols, and cycles are rejected at the provider boundary.
1132
1154
 
1155
+ `supportsTranscriptionCapture(providerId=null)` checks the selected provider's
1156
+ capture implementation and optional capability predicate. Construction of
1157
+ `createTranscriptionCapture(options)` performs no capture; it returns null or
1158
+ an owned `start/stop/cancel/destroy/done` wrapper with `forceEndpoint` when the
1159
+ provider supplies it. Start must originate in the user's capture action and
1160
+ requires an idle ready STT role; it is never queued. The role remains owned
1161
+ until `done` joins cleanup, including on cancellation or provider retirement.
1162
+ Native streaming TTS likewise uses the existing provider request lane rather
1163
+ than an application-owned synthesis queue. See
1164
+ [shared native capture/playback](native-speech.md#shared-ai-capture-and-playback).
1165
+
1133
1166
  `setSpeechMuted(false,{signal})` shares pending activation while retaining an
1134
1167
  independent interest for each caller. Aborting one signal rejects only that
1135
1168
  caller's wait. When no pending interests remain, abort reaches the owned load.
@@ -2046,11 +2079,22 @@ component adds ordered STT, persistence, retry, and presentation.
2046
2079
  ### Public surface
2047
2080
 
2048
2081
  Default export `ContinuousVoiceCapture` accepts
2049
- `{preRollMs=1500,quietMs=2000,chunkMs=30000,activityThreshold=0.02,onSegment,onError,onState}`.
2050
- `start({mediaConstraints={audio:true},signal}={})` acquires microphone input and
2082
+ `{preRollMs=1500,quietMs=2000,chunkMs=30000,activityThreshold=0.02,mode='segments',pcmChunkMs=100,onPCM,onActivity,onSegment,onError,onState}`.
2083
+ `start({mediaConstraints={audio:true},sampleRate,signal}={})` acquires microphone input and
2051
2084
  resolves `true` once capture starts, or `false` after cancellation or a
2052
2085
  reported start failure. Starting capture is an explicit caller action.
2053
2086
 
2087
+ Select `mode:'pcm'` to deliver every captured sample through ordered awaited
2088
+ `onPCM({samples:Float32Array,sampleRate,channels:1,sequence})` callbacks.
2089
+ The record reports the actual AudioContext rate. `pcmChunkMs` is transport
2090
+ scheduling, never a recording limit. `onActivity({active,audioTime})` reports
2091
+ amplitude changes without gating PCM or interpreting speech. `flush()` sends
2092
+ pending samples and awaits preceding delivery while leaving capture open.
2093
+ Stop drains accepted PCM and joins actual AudioContext closure. Cancel/destroy
2094
+ suppress queued delivery and join in-flight delivery and close; genuine delivery
2095
+ and cleanup failures reject rather than being reported as success.
2096
+
2097
+ In the default `mode:'segments'`:
2054
2098
  `onSegment({audio,sequence,reason,durationMs})` receives a complete
2055
2099
  `audio/wav` Blob containing mono Float32 audio. Sequence starts at one for
2056
2100
  each capture session; reason is `pause`, `periodic`, or `stop`. The detector
@@ -2073,7 +2117,8 @@ cancellation boundary. The optional signal cancels this capture session.
2073
2117
  flushes the active clip before reporting interruption while the worklet remains
2074
2118
  available. A failed audio context or processor reports interruption directly;
2075
2119
  audio still inside an unavailable processor cannot be recovered. Callback
2076
- promises are observed without delaying capture or stop acknowledgement.
2120
+ promises for segment/state/activity observers are observed without delaying
2121
+ capture; ordered PCM delivery and actual context closure are joined at stop.
2077
2122
  Capture state is independent
2078
2123
  of model readiness, STT processing, and application save state.
2079
2124
 
@@ -3411,6 +3456,100 @@ import * as module from '/arcane/modules/ModelDefinition.js';
3411
3456
  console.log(Object.keys(module));
3412
3457
  ```
3413
3458
 
3459
+ ## NativeSpeechCapture.js
3460
+
3461
+ ### Overview
3462
+
3463
+ Default `createNativeSpeechCapture({speech,model,...options})` connects one
3464
+ microphone lifetime to one retained Core ASR stream. Construction opens no
3465
+ microphone or model. Applications normally use `ai.createTranscriptionCapture`,
3466
+ which also owns the selected provider slot.
3467
+
3468
+ ### Public surface and lifetime
3469
+
3470
+ Options are `sampleRate=16000`, `pcmChunkMs=100`, `activityThreshold=0.02`,
3471
+ `streamOptions`, `mediaConstraints`, `onUpdate`, `onInterim`, `onSegment`,
3472
+ `onActivity`, `onState`, `onError`, `onProgress` and `onRequest`.
3473
+ The handle exposes `start({signal,mediaConstraints})` (boolean promise),
3474
+ `forceEndpoint()`, `stop()`, `requestStop()`, `cancel(reason)`,
3475
+ `destroy(reason)`, `done`, and `current()`. Capture uses the actual selected
3476
+ sample rate; `streamOptions.sampleRate` overrides the factory rate. Every PCM
3477
+ contribution is retained in order.
3478
+
3479
+ Recognition callbacks receive `(result,{requestStop})`; `onUpdate` precedes
3480
+ the appropriate final `onSegment` or provisional `onInterim`. Partials replace,
3481
+ finals preserve complete native segments and speaker scope. Call `requestStop()`
3482
+ without awaiting it, return from the callback, then join `stop()` or `done`
3483
+ externally. Never await those or `forceEndpoint()` from their own callback.
3484
+ External endpoint flushes pending audio and recognition while keeping capture
3485
+ and the stream open. Stop closes capture and drains terminally. Cancel/destroy
3486
+ join both cleanup owners without claiming a complete transcript. `current()`
3487
+ returns the latest snapshot or null. Actual failures remain in `done` and
3488
+ `onError`. No snapshot or control sends chat or decides conversational meaning.
3489
+
3490
+ ### Availability and example
3491
+
3492
+ Requires microphone, Web Audio and AudioWorklet in a browser/native WebView,
3493
+ plus an explicitly selected ready streaming Core speech engine.
3494
+
3495
+ ```javascript
3496
+ import createNativeSpeechCapture from 'arcane-os/modules/NativeSpeechCapture.js';
3497
+
3498
+ function prepareDragonInterpreter(speech, model, showSnapshot) {
3499
+ return createNativeSpeechCapture({speech, model, onUpdate: showSnapshot});
3500
+ }
3501
+ // Start from the application's capture action; its owner joins stop/done.
3502
+ ```
3503
+
3504
+ See [Core speech](native-speech.md) and [Nemotron](native-nemotron.md) for complete
3505
+ native formats, results, callback constraints, reset and platform prerequisites.
3506
+
3507
+ ## NativeSpeechPlayback.js
3508
+
3509
+ ### Overview
3510
+
3511
+ Default `prepareNativeSpeechPlayback({speech,request,getAudioContext,signal=null})`
3512
+ prepares an inert native speech descriptor. It creates no model, microphone or
3513
+ separate utterance queue. Applications normally use `ai.prepareTTSPlayback`.
3514
+
3515
+ ### Public surface and lifetime
3516
+
3517
+ The result is `{kind:'native-speech',input,voice,language,speed,play}`.
3518
+ `play({signal,onState})` returns `finished`, `released`, live `state` and
3519
+ `error`, plus boolean `pause()`, `resume()` and `stop()` controls.
3520
+ Preparation performs no synthesis/playback. Play consumes ordered signed
3521
+ 16-bit little-endian PCM at its supplied rate and channel count through the
3522
+ caller-owned AudioContext, with awaited audio-clock backpressure.
3523
+ Pause retains unplayed audio; stop cancels only this utterance.
3524
+
3525
+ `finished` resolves true after natural playback or false after stop, and
3526
+ rejects actual failure. `released` additionally joins native synthesis and
3527
+ cleanup. Both preparation and play signals can cancel. The shared output
3528
+ context remains open for its owner. `onState({state,error})` observes queued,
3529
+ waiting-for-audio, playing, paused, complete, stopped or error.
3530
+ Missing callable dependencies throw TypeError; unusable PCM or a closed context
3531
+ reports `ARCANE_AI_SPEECH_PLAYBACK_FAILED`. Native, playback and cleanup
3532
+ failures remain observable, including combined causes.
3533
+
3534
+ ### Availability and example
3535
+
3536
+ Requires browser Web Audio plus a supplied streaming speech API.
3537
+
3538
+ ```javascript
3539
+ import prepareNativeSpeechPlayback from 'arcane-os/modules/NativeSpeechPlayback.js';
3540
+
3541
+ function prepareDragonAnnouncement(speech, getAudioContext, signal) {
3542
+ return prepareNativeSpeechPlayback({
3543
+ speech, getAudioContext, signal,
3544
+ request: {input: 'The dragon has landed.', languageCode: 'en-US'}
3545
+ });
3546
+ }
3547
+ // Play from the owning action, then join the control's released promise.
3548
+ ```
3549
+
3550
+ See [Magpie](native-magpie.md) and
3551
+ [shared native playback](native-speech.md#shared-ai-capture-and-playback).
3552
+
3414
3553
  ## Ollama.js
3415
3554
 
3416
3555
  ### Overview
@@ -4826,7 +4965,7 @@ the audio rendering thread. It performs no semantic speech detection or STT.
4826
4965
  No ESM exports. The capture owner loads this static file with
4827
4966
  `audioContext.audioWorklet.addModule()` and creates the
4828
4967
  `arcane-continuous-voice-capture` processor with
4829
- `{preRollMs,quietMs,chunkMs,activityThreshold}` in `processorOptions`.
4968
+ `{preRollMs,quietMs,chunkMs,activityThreshold,mode,pcmChunkMs}` in `processorOptions`.
4830
4969
  `activityThreshold` measures root-mean-square amplitude over fixed 20 ms
4831
4970
  windows counted from the audio sample rate, independently of browser callback
4832
4971
  lengths. Brief peaks do not reset the quiet duration when the window's RMS
@@ -4843,6 +4982,13 @@ trailing audio before the quiet boundary. Analysis adds at most one 20 ms
4843
4982
  window of capture-to-segmentation delay; model processing is independently
4844
4983
  owned by the transcription queue.
4845
4984
 
4985
+ In `mode:'pcm'`, the processor transfers every sample through
4986
+ `{type:'pcm',audio:ArrayBuffer,sampleRate,sequence}` and reports
4987
+ `{type:'activity',active,audioTime}` on amplitude-state changes. It keeps no
4988
+ semantic classifier and does not omit quiet audio. `{type:'flush',id}` sends
4989
+ pending PCM then `{type:'flushed',id}` without stopping. The capture owner
4990
+ adds `channels:1` and joins ordered delivery before resolving its flush.
4991
+
4846
4992
  The owner sends `{type:'stop'}`. The processor transfers each complete
4847
4993
  `{type:'segment',audio:ArrayBuffer,sampleRate,sequence,reason,durationMs}`
4848
4994
  and finally `{type:'stopped'}`. Each complete WAV includes its own format,