On this page
Overview
Provider-neutral selection, lifecycle, routing, startup, request, streaming, cancellation, and independent LLM/STT/TTS state.
- Artifact
AIProviderRuntime.js· esm - Classification
public first party - Availability
Cross-host in-process runtime; registered providers remain browser, native, or cloud specific - Normalization
Normalizes mutable complete per-role routes, lifecycle/status, cancellation, streaming cleanup, capacity-1 FIFO LLM/STT lanes, bounded provider-declared parallel TTS requests with FIFO overflow, default repeated-formatting-mark removal from cloned direct TTS payloads or explicit textFormat:'plain' preservation with the control consumed before engine dispatch, local-only selection, direct LLM history/declaration/terminal structural contracts, complete all-choice content/reasoning FIFO iteration, private automatic provider draining with result-first buffering, terminal-only structural calls, exact per-choice observed/terminal correlation, and a separate complete validated terminal result without creating a fallback.
Import and lifecycle
import * as module from '/node_modules/arcane-os/runtime/arcane/modules/AIProviderRuntime.js';
The exported singleton owns registered providers and independent llm, stt, and tts lifecycle slots. Configuration, start, load, unload, request, cancellation, disposal, and mute operations publish complete mutable role state; importing alone performs no model download or provider selection. Requests enter a FIFO lane with capacity 1 for LLM/STT and provider-declared concurrent capacity for TTS; synthesis may settle out of order while AI playback preserves segment order. Each caller signal cancels only its own request.
Application-facing behavior: supportsTranscriptionCapture(providerId=null) reports the provider capture capability; createTranscriptionCapture(options) returns null or an owned start/stop/cancel/destroy/done handle with optional forceEndpoint. Start requires an idle ready selected STT role, remains in the initiating user gesture and is never queued. Capture holds that role until done joins cleanup; cancellation/retirement uses the same role owner. Native streaming TTS uses the existing request lane with ordered awaited PCM callbacks. Protocol constants; singleton-only AIProviderRuntime; aiProviderRuntime; getAIProviderRuntime(); provider registration/identity/selection, closed three-role and STT/TTS-only validation/configuration/replacement, status/catalog/inspection, startup, per-role load/unload/dispose/cancel, dispose-all, request/stream/speech aliases, SDK-internal speech-input preparation metadata, and setSpeechMuted(muted,{signal}={}) controls. Each pending unmute caller owns its abortable interest; the final interest aborts the owned activation while other preparation/playback or joining direct TTS-load interests preserve it. A pre-aborted unmute starts no activation. Explicit mute retains global cancellation and joined unload even with an aborted observer signal.
Protocol and host implementation
arcane-ai-runtime/2, arcane-ai-provider/2, arcane-ai-model-authority/1 This detail does not widen the application-facing API or grant authority.
Exports, signatures, parameters, and results
| Binding | Form | Declaration or signature | Parameter syntax |
|---|---|---|---|
AI_PROVIDER_PROTOCOL | variable · value | variable AI_PROVIDER_PROTOCOL | — |
AI_PROVIDER_RUNTIME_PROTOCOL | variable · value | variable AI_PROVIDER_RUNTIME_PROTOCOL | — |
AI_MODEL_AUTHORITY_PROTOCOL | variable · value | variable AI_MODEL_AUTHORITY_PROTOCOL | — |
AIProviderRuntime | class | class AIProviderRuntime | — |
aiProviderRuntime | class · value | variable aiProviderRuntime | — |
getAIProviderRuntime | function | function getAIProviderRuntime() | — |
| Callable | Kind | Exact public signature | Parameter syntax |
|---|---|---|---|
getAIProviderRuntime | exported-function | function getAIProviderRuntime() | — |
AIProviderRuntime.register | public-member | register(provider) | provider |
AIProviderRuntime.unregister | public-member | unregister(role, providerId, expectedProvider = null) | role, providerId, expectedProvider = null |
AIProviderRuntime.hasProvider | public-member | hasProvider(role, providerId) | role, providerId |
AIProviderRuntime.providerIdentity | public-member | providerIdentity(role, providerId) | role, providerId |
AIProviderRuntime.selection | public-member | selection(role, options = {}) | role, options = {} |
AIProviderRuntime.ownsSelection | public-member | ownsSelection(role, providerId, options = {}) | role, providerId, options = {} |
AIProviderRuntime.validateConfiguration | public-member | validateConfiguration(value) | value |
AIProviderRuntime.configure | public-member | configure(value) | value |
AIProviderRuntime.configureFromTuple | public-member | configureFromTuple(tuple) | tuple |
AIProviderRuntime.status | public-member | status(role = null, options = {}) | role = null, options = {} |
AIProviderRuntime.catalog | public-member | catalog(role) | role |
AIProviderRuntime.inspect | public-member | async inspect(role, options = {}) | role, options = {} |
AIProviderRuntime.start | public-member | async start(options) | options |
AIProviderRuntime.load | public-member | load(role, options = {}) | role, options = {} |
AIProviderRuntime.unload | public-member | unload(role, options = {}) | role, options = {} |
AIProviderRuntime.dispose | public-member | dispose(role, options = {}) | role, options = {} |
AIProviderRuntime.disposeAll | public-member | disposeAll(options = {}) | options = {} |
AIProviderRuntime.request | public-member | request(role, options = {}, {speechInputPrepared = false, observeToolText = null, onRetry = null, speechStream = null} = {}) | role, options = {}, {speechInputPrepared = false, observeToolText = null, onRetry = null, speechStream = null} = {} |
AIProviderRuntime.chat | public-member | chat(payload, options = {}) | payload, options = {} |
AIProviderRuntime.stream | public-member | stream(payload, options = {}) | payload, options = {} |
AIProviderRuntime.supportsTranscriptionCapture | public-member | supportsTranscriptionCapture(providerId = null) | providerId = null |
AIProviderRuntime.createTranscriptionCapture | public-member | createTranscriptionCapture(options = {}) | options = {} |
AIProviderRuntime.transcribe | public-member | transcribe(payload, options = {}) | payload, options = {} |
AIProviderRuntime.synthesize | public-member | synthesize(payload, options = {}, preparation = {}) | payload, options = {}, preparation = {} |
AIProviderRuntime.cancel | public-member | cancel(role) | role |
AIProviderRuntime.setSpeechMuted | public-member | async setSpeechMuted(muted, {signal = null} = {}) | muted, {signal = null} = {} |
| Member | Kind | Exact public declaration | Parameter syntax |
|---|---|---|---|
AIProviderRuntime.constructor | constructor | constructor(authority) | authority |
AIProviderRuntime.protocol | get | get protocol() | — |
AIProviderRuntime.speechMuted | get | get speechMuted() | — |
AIProviderRuntime.configured | get | get configured() | — |
AIProviderRuntime.register | method | register(provider) | provider |
AIProviderRuntime.unregister | method | unregister(role, providerId, expectedProvider = null) | role, providerId, expectedProvider = null |
AIProviderRuntime.hasProvider | method | hasProvider(role, providerId) | role, providerId |
AIProviderRuntime.ownsProvider | method | ownsProvider(role, expectedProvider) | role, expectedProvider |
AIProviderRuntime.providerIdentity | method | providerIdentity(role, providerId) | role, providerId |
AIProviderRuntime.selection | method | selection(role, options = {}) | role, options = {} |
AIProviderRuntime.ownsSelection | method | ownsSelection(role, providerId, options = {}) | role, providerId, options = {} |
AIProviderRuntime.validateConfiguration | method | validateConfiguration(value) | value |
AIProviderRuntime.validateSpeechConfiguration | method | validateSpeechConfiguration(value) | value |
AIProviderRuntime.configure | method | configure(value) | value |
AIProviderRuntime.configureSpeech | method | configureSpeech(value) | value |
AIProviderRuntime.replaceSpeechProvider | method | replaceSpeechProvider(role, value) | role, value |
AIProviderRuntime.replaceSpeechProviders | method | replaceSpeechProviders(value) | value |
AIProviderRuntime.configureFromTuple | method | configureFromTuple(tuple) | tuple |
AIProviderRuntime.status | method | status(role = null, options = {}) | role = null, options = {} |
AIProviderRuntime.catalog | method | catalog(role) | role |
AIProviderRuntime.inspect | async method | async inspect(role, options = {}) | role, options = {} |
AIProviderRuntime.start | async method | async start(options) | options |
AIProviderRuntime.load | method | load(role, options = {}) | role, options = {} |
AIProviderRuntime.unload | method | unload(role, options = {}) | role, options = {} |
AIProviderRuntime.dispose | method | dispose(role, options = {}) | role, options = {} |
AIProviderRuntime.disposeAll | method | disposeAll(options = {}) | options = {} |
AIProviderRuntime.request | method | request(role, options = {}, {speechInputPrepared = false, observeToolText = null, onRetry = null, speechStream = null} = {}) | role, options = {}, {speechInputPrepared = false, observeToolText = null, onRetry = null, speechStream = null} = {} |
AIProviderRuntime.chat | method | chat(payload, options = {}) | payload, options = {} |
AIProviderRuntime.stream | method | stream(payload, options = {}) | payload, options = {} |
AIProviderRuntime.supportsTranscriptionCapture | method | supportsTranscriptionCapture(providerId = null) | providerId = null |
AIProviderRuntime.createTranscriptionCapture | method | createTranscriptionCapture(options = {}) | options = {} |
AIProviderRuntime.transcribe | method | transcribe(payload, options = {}) | payload, options = {} |
AIProviderRuntime.synthesize | method | synthesize(payload, options = {}, preparation = {}) | payload, options = {}, preparation = {} |
AIProviderRuntime.cancel | method | cancel(role) | role |
AIProviderRuntime.setSpeechMuted | async method | async setSpeechMuted(muted, {signal = null} = {}) | muted, {signal = null} = {} |
Parameter meanings and results
AIProviderRuntime is singleton-only. supportsTranscriptionCapture(providerId=null) checks createCapture and its optional supportsCapture predicate. createTranscriptionCapture(options) returns null or a start/stop/cancel/destroy/done wrapper plus forceEndpoint when supplied. Start owns the initiating user gesture and requires an idle ready selected STT role; capture is never queued. The role remains owned until done joins actual cleanup. Slot cancellation and provider retirement cancel that capture through its retained request. Native streaming TTS uses the existing request lane, preserving ordered awaited PCM callbacks and native cleanup. Applications use AI.prepareTTSPlayback instead of its internal speechStream preparation seam. getAIProviderRuntime() returns aiProviderRuntime. status(role=null,options={}) returns the unchanged sticky lifecycle snapshot by default. Explicit options.execution=true copies that snapshot and adds the selected provider-supplied execution record when available; aggregate results place it under roles. It neither loads providers nor emits sticky-state events, and inspection errors propagate. Register a provider/2 object with required protocol, role, id, localOnly, catalog, inspect, status, load, request, unload, and dispose members; additional provider keys are accepted. Configuration is a closed {llm,stt,tts} record of {default,localOnly} routes. start({startMuted=true,startTranscription=false,signal=null}={}) waits for prior speech/unload work, declines a startup STT load unless explicitly requested, applies initial mute state, and returns the mutable startAIRuntime control {barrier,settled,cancel}. setSpeechMuted(muted,{signal}={}) gives each pending unmute caller its own abortable activation interest. The final pending interest aborts the owned activation, while other preparation/playback or joining direct TTS-load interests preserve it. A pre-aborted unmute starts no activation. Explicit mute retains global cancellation and joined unload even when its observer signal is aborted; actual provider cleanup remains provider-owned. request(role,options={},preparation={}) and synthesize(payload,options={},preparation={}) remove repeated same formatting marks from only a cloned direct-TTS payload input/text field by default. Explicit payload textFormat:'plain' preserves complete input/text, including repeated marks and surrounding whitespace; the SDK consumes textFormat before queued provider/engine dispatch. Omitted or other values retain default cleanup. This complete-call control does not change streaming behavior or upstream engine capacity. Their optional preparation argument is SDK-internal; {speechInputPrepared:true} prevents a second non-idempotent cleanup pass after an SDK owner has already prepared the outbound copy, and applications omit it. Caller payload and request objects remain unchanged. chat/stream/transcribe accept complete payloads plus {localOnly=false,signal=null}; per-role requests enter a FIFO lane without superseding or discarding earlier content; optional provider maxConcurrentRequests defaults to 1 and only TTS may declare a greater capacity. Direct LLM ingress validates tool declarations, exact all-ID pending-call history, and nonblank tool-result content. Structured terminals use exactly one message or choices envelope; ordinary iteration exposes complete nonstructural content/reasoning data from every choice in provider order, data callbacks retain complete chunks, and the separate result retains the complete validated terminal response.
Events, side effects, and errors
Source-literal CustomEvent dispatches
No source-literal CustomEvent dispatch is part of this artifact.
Lifecycle and event flow
- publishes arcane-ai-runtime-state through AIRuntimeState
- consumes arcane-ai-runtime-intent through AIRuntimeState
Direct coded failures
This artifact directly assigns no stable coded failure.
Exported Error subclasses
This artifact exports no Error subclass.
Documented failure behavior
- ARCANE_AI_RUNTIME_SINGLETON_REQUIRED
- ARCANE_AI_RUNTIME_NOT_CONFIGURED
- ARCANE_AI_RUNTIME_CONFIGURING
- ARCANE_AI_RUNTIME_DISPOSING
- ARCANE_AI_RUNTIME_DISPOSED
- ARCANE_AI_CONFIGURATION_REENTRANT
- ARCANE_AI_OPERATION_SEQUENCE_EXHAUSTED
- ARCANE_AI_PROVIDER_ALREADY_REGISTERED
- ARCANE_AI_PROVIDER_RUNTIME_INVALID
- ARCANE_AI_PROVIDER_LOCALITY_MISMATCH
- ARCANE_AI_PROVIDER_SELECTED
- ARCANE_AI_PROVIDER_AUTHORITY_BLOCKED
- ARCANE_AI_PROVIDER_CALLBACK_BOUNDARY
- ARCANE_AI_PROVIDER_STATUS_INVALID
- ARCANE_AI_PROVIDER_STREAM_INVALID
- ARCANE_AI_PROVIDER_UNAVAILABLE
- ARCANE_AI_PROVIDER_NOT_READY
- ARCANE_AI_PROVIDER_OPERATION_FAILED
- ARCANE_AI_PROVIDER_UNLOAD_INCOMPLETE
- ARCANE_AI_PROVIDER_DISPOSE_INCOMPLETE
- ARCANE_AI_SELECTION_INCOMPLETE
- ARCANE_AI_MODEL_AUTHORITY_REQUIRED
- ARCANE_AI_LOCAL_PROVIDER_REQUIRED
- AI_LOCAL_MODEL_REQUIRED
- ARCANE_AI_ROLE_NOT_SELECTED
- ARCANE_AI_ROLE_NOT_READY
- ARCANE_AI_ROLE_BUSY
- ARCANE_AI_ROLE_DISPOSED
- ARCANE_AI_ROUTE_NOT_READY
- ARCANE_AI_ROUTE_SWITCH_REQUIRES_UNLOAD
- ARCANE_AI_OPERATION_SUPERSEDED
- ARCANE_AI_REQUEST_ABORTED
- ARCANE_AI_STREAM_CLEANUP_INCOMPLETE
- ARCANE_AI_TTS_MUTED
Availability and capabilities
Cross-host in-process runtime; registered providers remain browser, native, or cloud specific. Normalizes mutable complete per-role routes, lifecycle/status, cancellation, streaming cleanup, capacity-1 FIFO LLM/STT lanes, bounded provider-declared parallel TTS requests with FIFO overflow, default repeated-formatting-mark removal from cloned direct TTS payloads or explicit textFormat:'plain' preservation with the control consumed before engine dispatch, local-only selection, direct LLM history/declaration/terminal structural contracts, complete all-choice content/reasoning FIFO iteration, private automatic provider draining with result-first buffering, terminal-only structural calls, exact per-choice observed/terminal correlation, and a separate complete validated terminal result without creating a fallback.
Provider-neutral in-process lifecycle. Browser, native, and cloud providers retain separate availability and authority; localOnly selects a matching route and never creates a fallback.
Contract example
import {getAIProviderRuntime} from '/node_modules/arcane-os/runtime/arcane/modules/AIProviderRuntime.js';
const runtime=getAIProviderRuntime();
console.log(runtime.protocol,runtime.status());
Related reference
No direct Core call is claimed for this artifact. Any injected provider or consuming module retains its own documented authority.