arcane-os 0.5.10 → 0.5.12

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 (54) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +117 -26
  3. package/browser-runtime/ai/browser-speech-providers.mjs +1 -1
  4. package/docs/architecture.md +303 -0
  5. package/docs/compatibility.md +38 -0
  6. package/docs/event-manager.md +263 -0
  7. package/docs/platform-targets.md +104 -0
  8. package/docs/publishing.md +126 -0
  9. package/docs/reference/README.md +206 -0
  10. package/docs/reference/ai/browser-speech.md +879 -0
  11. package/docs/reference/ai/browser-wasm.md +637 -0
  12. package/docs/reference/ai/twin-cloud.md +156 -0
  13. package/docs/reference/arcane-ollama.md +288 -0
  14. package/docs/reference/availability-and-normalization.md +224 -0
  15. package/docs/reference/behavioral-testing.md +129 -0
  16. package/docs/reference/cli.md +820 -0
  17. package/docs/reference/core/README.md +61 -0
  18. package/docs/reference/core/arcane-ai-contracts.md +906 -0
  19. package/docs/reference/core/arcane-api.md +601 -0
  20. package/docs/reference/core/arcane-entities.md +59 -0
  21. package/docs/reference/core/arcane-events.md +134 -0
  22. package/docs/reference/core/ollama-module.md +181 -0
  23. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  24. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  25. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  26. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  27. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  28. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  29. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  30. package/docs/reference/event-manager.md +1409 -0
  31. package/docs/reference/inventory/package-api.json +3194 -0
  32. package/docs/reference/inventory/runtime-components.json +1015 -0
  33. package/docs/reference/inventory/runtime-entities.json +25 -0
  34. package/docs/reference/inventory/runtime-modules.json +1367 -0
  35. package/docs/reference/mail.md +309 -0
  36. package/docs/reference/protocols.md +749 -0
  37. package/docs/reference/runtime-components.md +1532 -0
  38. package/docs/reference/runtime-entities.md +305 -0
  39. package/docs/reference/runtime-modules.md +3310 -0
  40. package/docs/reference/sdk-api.md +6733 -0
  41. package/docs/roadmap.md +79 -0
  42. package/docs/work-amplification.md +66 -0
  43. package/examples/wasm-ai-demo/README.md +80 -0
  44. package/examples/wasm-ai-demo/app.js +787 -0
  45. package/examples/wasm-ai-demo/index.html +343 -0
  46. package/examples/wasm-ai-demo/profile-tools.js +217 -0
  47. package/examples/wasm-ai-demo/profiles/BOSS.Modelfile +106 -0
  48. package/examples/wasm-ai-demo/profiles/PreCrisis.Modelfile +693 -0
  49. package/examples/wasm-ai-demo/rag/boss-library.json +3006 -0
  50. package/examples/wasm-ai-demo/rag.js +295 -0
  51. package/examples/wasm-ai-demo/server.mjs +71 -0
  52. package/package.json +10 -1
  53. package/runtime/arcane/modules/AI.js +60 -11
  54. package/runtime/arcane/modules/AIProviderRuntime.js +26 -5
@@ -0,0 +1,3310 @@
1
+ # Arcane runtime module catalog
2
+
3
+ Every file shipped under `runtime/arcane/modules/` appears here. Start with the capability and example; expand into [protocol and host architecture](protocols.md) only when transport detail matters.
4
+
5
+ Apps import renderer ESM from `/arcane/modules/<file>`. Classic scripts, the OPFS worker, uPlot stylesheet, and vendor license are called out explicitly. Importing a module does not grant a native capability.
6
+
7
+ ## Availability shorthand
8
+
9
+ - **Cross-host** means in-process logic built from standard JavaScript/Web APIs.
10
+ - **Browser / native WebView** means DOM, storage, media, or component behavior available in a browser renderer and in supported native WebViews.
11
+ - **Native bridge** means the module requires an available `globalThis.Arcane` method.
12
+ - **Hybrid** means one public helper deliberately selects a documented native or browser/provider path.
13
+ - **Cloud** means the module can call an explicitly configured remote provider; it never implies automatic local-to-cloud fallback.
14
+ - **Node**, **worker**, and **vendor** identify specialized runtimes.
15
+
16
+ ## Runtime semantic events and teardown
17
+
18
+ SDK runtime modules publish semantic state and lifecycle occurrences through the
19
+ one branded, versioned `globalThis.arcaneEvents` authority in each JavaScript
20
+ realm. A class can retain its existing `EventTarget` or `on()` listener surface,
21
+ but that surface delegates to a `createArcaneEventSource()` view scoped
22
+ by the module's source and instance identifiers; it does not own a second event
23
+ bus, listener `Map`, or listener `Set`. Every canonical occurrence and every
24
+ one-way DOM projection carries an occurrence ID. DOM input events
25
+ remain local UI/platform input, and projected DOM `CustomEvent`s must not be
26
+ mirrored back into the canonical source.
27
+
28
+ `arcaneEvents.subscribe(type,handler,{once,signal})` and source-scoped
29
+ `subscribe()`/`on()` registrations return one idempotent unsubscribe function
30
+ (also exposed as `.dispose`). The singleton's convenience `on()`/`once()` methods are
31
+ chainable listener APIs that return the manager; lifecycle-owned consumers
32
+ use `subscribe()`. Instance `dispose()`/`destroy()` methods remove owned
33
+ listeners, abort owned work, suppress stale settlement, and dispose the instance
34
+ source. Module-lifetime singleton sources instead expose a focused module
35
+ teardown function where teardown is supported. Event publication is synchronous
36
+ and observational; promises, `AbortSignal`, and `createEventQueue` continue to
37
+ own asynchronous work, cancellation, and backpressure.
38
+
39
+ ## Canonical inventory
40
+
41
+ | Module | Kind | Capability | Availability | Normalization |
42
+ | --- | --- | --- | --- | --- |
43
+ | [`AI.js`](#aijs) | esm | Provider-selectable chat, speech-to-text, text-to-speech, tool calling, structured output, streaming, bounded synthesis, and ordered audio-clock playback. | Browser + native bridge + cloud | High-level chat/speech behavior and active TTS operation failures are normalized; provider diagnostics remain mixed. |
44
+ | [`AIPreferenceRuntime.js`](#aipreferenceruntimejs) | esm | Applies and reads non-persistent per-user AI preference overrides. | Cross-host | Normalized six-slot preference state. |
45
+ | [`AIPreferenceTuple.js`](#aipreferencetuplejs) | esm | Normalizes and compares the six provider/model preference slots. | Cross-host | Fully normalized frozen tuple. |
46
+ | [`AIProviderRuntime.js`](#aiproviderruntimejs) | esm | Owns provider-neutral selection, lifecycle, routing, startup, requests, streaming, cancellation, and independent LLM/STT/TTS state. | Cross-host runtime; provider-specific availability | Normalized required provider members plus route/status contracts, with explicit local-only selection and no implicit fallback. |
47
+ | [`AIResponseLength.js`](#airesponselengthjs) | esm | Normalizes current low/medium/high response-preference selectors while preserving complete prompts. | Cross-host | Current selector normalization; prompt content remains unchanged. |
48
+ | [`AIResponseURLPolicy.js`](#airesponseurlpolicyjs) | esm | Extracts and audits links from AI Markdown, rendered HTML, CSS, srcset, bare URLs, and email text. | Cross-host | Normalized frozen allowlist audit. |
49
+ | [`AIRuntimeState.js`](#airuntimestatejs) | esm | Publishes sticky mutable role snapshots, lifecycle intents, and startup-settlement barriers. | Cross-host state contract | Closed monotonic state records; events report state but grant no authority. |
50
+ | [`AnsiText.js`](#ansitextjs) | esm | Parses terminal ANSI sequences into display spans or strips them to plain text. | Cross-host | Normalized text/span output. |
51
+ | [`ApiModelDatabase.js`](#apimodeldatabasejs) | esm | Fetches an injectable HTTP JSON model with parser, cache, redacted public endpoint records, and request lifecycle events. | Browser / native WebView / server with fetch | Request records are normalized; fetch/provider failures remain mixed. |
52
+ | [`AppDataScope.js`](#appdatascopejs) | esm | Reconciles declared and native application identity and scopes OPFS/localStorage ownership fail-closed. | Browser / native WebView hybrid | Strict normalized identifiers and coded mismatch failures. |
53
+ | [`AppearancePreferences.js`](#appearancepreferencesjs) | esm | Defines, stores, and applies color scheme, density, reduced motion, and large-text preferences. | Browser / native WebView hybrid | Normalized values; storage/host failures remain mixed. |
54
+ | [`ArcaneCommunicationBridge.js`](#arcanecommunicationbridgejs) | esm | Maps provider HTTP threads/messages/connect/disconnect endpoints to normalized communication entities. | Browser / native WebView / server with fetch | Entity results are normalized; provider/transport failures remain mixed. |
55
+ | [`ArcaneNavigationPolicy.js`](#arcanenavigationpolicyjs) | esm | Creates an HTTP(S) navigation guard with explicit secure-mode domain and CIDR policy decisions. | Cross-host | Complete mutable decisions; ordinary mode warns and continues, while explicitly selected `secure: true` fails closed. |
56
+ | [`ArcaneNetworkPolicy.js`](#arcanenetworkpolicyjs) | esm | Validates the Arcane domain/network deny policy and matches domain, IPv4/IPv6 CIDR, protocol, and port rules. | Cross-host | Strict coded normalization. |
57
+ | [`AsyncBoundary.js`](#asyncboundaryjs) | esm | Runs one asynchronous operation with timeout, abort, result validation, and stable boundary errors. | Cross-host | Fully normalized timeout/abort errors. |
58
+ | [`BrowserTestSuite.js`](#browsertestsuitejs) | esm | Runs a complete sequential browser test list with explicit cancellation and full-detail lifecycle events. | Browser / standard Web APIs | Mutable results and skip/assertion errors normalized without suite-created caps or timers. |
59
+ | [`CalculatorEngine.js`](#calculatorenginejs) | esm | Evaluates arithmetic, powers, constants, and common functions without `eval`. | Cross-host | Normalized `Calculation` result and parser errors. |
60
+ | [`ChartLibrary.js`](#chartlibraryjs) | esm | Loads the bundled uPlot classic script once and returns its global constructor. | Browser / native WebView | Load state/errors normalized; uPlot result is vendor-native. |
61
+ | [`ChatRecords.js`](#chatrecordsjs) | esm | Detects conversation entries and projects retained state into recurring provider context. | Cross-host | Boolean entry results and recurring context are normalized. |
62
+ | [`CommunicationAppController.js`](#communicationappcontrollerjs) | esm | Binds shared inbox, conversation, settings, theme, and provider workflows into one UI controller. | Browser / native WebView hybrid | Controller state normalized; provider/DOM failures mixed. |
63
+ | [`CommunicationHub.js`](#communicationhubjs) | esm | Fans out provider refresh/send operations and aggregates normalized threads/messages. | Cross-host with injected providers | Normalized aggregates; refresh contains per-provider failures. |
64
+ | [`CommunicationPreferences.js`](#communicationpreferencesjs) | esm | Stores app-scoped, non-secret communication provider preferences. | Browser / native WebView hybrid | Normalized preference record; storage failures mixed. |
65
+ | [`CommunicationProviderRegistry.js`](#communicationproviderregistryjs) | esm | Registers and queries validated provider definitions, channels, and required methods. | Cross-host | Strict normalized registry. |
66
+ | [`ComponentContracts.js`](#componentcontractsjs) | esm | Owns normalized configuration/value contracts and shared explicit STT activation behavior for chart, dashboard, Markdown, and voice components. | Cross-host | Fully normalized labels, rows, definitions, visibility, formats, editor and voice options, plus capability-neutral STT activation intent and presentation state. Complete finite progress measures remain visible, including fractional and over-total values. |
67
+ | [`ConfiguredAIChatSession.js`](#configuredaichatsessionjs) | esm | Owns ordinary visible recurring AI turns, one active structural continuation, context construction, provider-response preservation, and atomic history commit. | Native bridge by default; cross-host with injected chat | Normalized session/result; provider rejection preserved. |
68
+ | [`ConversationActionItems.js`](#conversationactionitemsjs) | esm | Normalizes, creates, updates, remembers, selects, and formats complete conversation action items. | Cross-host | Fully normalized status/base/presentation contract. |
69
+ | [`ConversationClosingReport.js`](#conversationclosingreportjs) | esm | Defines the closing-report tool, instruction, result normalizer, call classifier, and formatter. | Cross-host | Fully normalized report contract. |
70
+ | [`ConversationTimebox.js`](#conversationtimeboxjs) | esm | Owns conversation limits, control messages, submission barriers, elapsed formatting, and delivery proof. | Cross-host | Fully normalized state/command/delivery errors. |
71
+ | [`CoreLocalModelCatalog.js`](#corelocalmodelcatalogjs) | esm | Projects Core local-AI status into UI-safe model and speech availability catalogs. | Cross-host | Fully normalized descriptors and stable availability labels. |
72
+ | [`DataMaintenance.js`](#datamaintenancejs) | esm | Deletes empty chats and associated/empty memory records inside the current app data scope. | Browser / native WebView | Normalized counts; destructive storage failures preserved. |
73
+ | [`DBLS.js`](#dblsjs) | esm | Provides app-scoped localStorage tables, batch reads/writes, filtering, deletion, and counts. | Browser / native WebView | Scoped keys and values normalized; storage failures mixed. |
74
+ | [`DBOPFS.js`](#dbopfsjs) | esm | Provides app-scoped OPFS tables, worker I/O, backup/restore, compression, and CRUD/batch APIs. | Browser / native WebView | App scope and recognized file parsing normalized; nonblank unreadable JSONL rows and DOM/storage errors are preserved. |
75
+ | [`DBOPFSDocumentLibrary.js`](#dbopfsdocumentlibraryjs) | esm | Bootstraps and searches an app-defined DBOPFS corpus and builds complete chat context. | Browser or compatible DBOPFS host | Existing DBOPFS semantics; generation completion and complete search only after the app calls it or wires its context builder. |
76
+ | [`DBOPFSWorker.js`](#dbopfsworkerjs) | worker | Serializes OPFS sync-handle read/write requests from a MessagePort. | Dedicated worker | Responses normalize to `{success,fileData?}` or `{error:{name,message}}`. |
77
+ | [`DevelopmentWorkspace.js`](#developmentworkspacejs) | esm | Provides complete workspace inspection, context, setup task, and Node installer clients without arbitrary command execution. | Native bridge | Complete plain-text inputs and provider result/error preserved. |
78
+ | [`DirectoryPicker.js`](#directorypickerjs) | esm | Wraps the provider-owned native directory chooser and normalizes selected/cancelled/error results. | Native bridge | Complete mutable caller options and provider result fields; coded cancellation and malformed-result errors. |
79
+ | [`DocumentLexicalSearch.js`](#documentlexicalsearchjs) | esm | Provides dependency-free deterministic metadata/body ranking and complete excerpts. | Cross-host | Mutable complete results with no storage, provider, or network side effects. |
80
+ | [`DocumentNavigation.js`](#documentnavigationjs) | esm | Binds document navigation, filtering, history, current-item reveal, and load initialization. | Browser / native WebView | Normalized filter/navigation state; DOM effects preserved. |
81
+ | [`Errors.js`](#errorsjs) | esm | Normalizes global errors/rejections, fingerprints and deduplicates incidents, persists a complete ledger, and performs complete delivery. | Browser / native WebView hybrid | Incident records normalized; storage/mail failures isolated. |
82
+ | [`GifEncoder.js`](#gifencoderjs) | esm | Encodes indexed frames into a complete animated GIF using palette mapping and LZW. | Cross-host | Normalized complete binary output. |
83
+ | [`HTMLImport.js`](#htmlimportjs) | esm | Defines the same-origin `<html-import>` loader with open shadow root, inline script execution, and readiness/error events. | Browser / native WebView | Public error detail normalized; fetch/DOM failure preserved. |
84
+ | [`InMemoryCommunicationProvider.js`](#inmemorycommunicationproviderjs) | esm | Implements deterministic in-memory thread/message/send behavior for demos and tests. | Cross-host | Normalized communication entities. |
85
+ | [`IsolatedModelQuestionRunner.js`](#isolatedmodelquestionrunnerjs) | esm | Inspects one selected model and runs one isolated question while preserving the complete answer. | Native bridge or injected provider | Normalized model/result and coded errors. |
86
+ | [`LocalAIReadiness.js`](#localaireadinessjs) | esm | Derives selected AI requirements and returns a complete readiness/recovery report across browser, desktop, and Android modes. | Browser/native hybrid | Fully normalized report and stable error codes; browsers never probe Ollama. |
87
+ | [`LocalAIReadinessController.js`](#localaireadinesscontrollerjs) | esm | Coordinates local-AI status component checks, ensured recovery, availability projection, and teardown. | Browser/native hybrid | Normalized controller state and change events. |
88
+ | [`Mail.js`](#mailjs) | esm | Builds complete reports and prefers the native mail capability with an explicit HTTP transport fallback. | Browser/native hybrid + cloud | Mail inputs/results normalized; transport failures mixed. |
89
+ | [`MailOutbox.mjs`](#mailoutboxmjs) | esm | Persists complete mail reports before delivery and normalizes idempotent enqueue, retry, reconciliation, and invalid-record maintenance. | Browser/native WebView or compatible injected host | Complete records, full work, cancellation, and lifecycle states normalized; storage, lock, and delivery failures coded. |
90
+ | [`MailTransport.mjs`](#mailtransportmjs) | esm | Sends one complete mail report to a normalized HTTP(S) endpoint. | Browser/server with fetch + cloud | Normalized endpoint and transport errors; remote detail preserved. |
91
+ | [`Marked.min.js`](#markedminjs) | esm | Vendored Marked 18.0.5 Markdown lexer, parser, renderer, extension, and walk-token API. | Cross-host vendor module | Vendor-native Marked contract. |
92
+ | [`MD.js`](#mdjs) | esm | Renders complete Markdown with Marked and exposes the complete rendered markup. | Browser / native WebView | Complete raw and rendered Marked values; parse errors vendor-native. |
93
+ | [`MemoryRecords.js`](#memoryrecordsjs) | esm | Normalizes memory content and detects meaningful stored memory. | Cross-host | Fully normalized string/boolean results. |
94
+ | [`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. |
95
+ | [`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. |
96
+ | [`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. |
97
+ | [`OllamaModelIdentifier.js`](#ollamamodelidentifierjs) | esm | Validates and canonicalizes the syntax of Ollama model identifiers without granting model admission. | Cross-host | Fully normalized string/boolean result. |
98
+ | [`OllamaSettings.js`](#ollamasettingsjs) | esm | Defines complete runtime/service preference schemas and deterministic Arcane brain alias names. | Cross-host | Fully normalized settings/name contract. |
99
+ | [`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. |
100
+ | [`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. |
101
+ | [`PreferenceStore.js`](#preferencestorejs) | esm | Loads and updates schema-defined app preferences through native storage with a narrow browser fallback. | Browser/native hybrid | Complete ordinary values remain mutable; setAll uses one optional atomic adapter batch for every selected value when advertised, otherwise performs complete ordered serial writes, and only exact unsupported native capability changes future operations to the browser fallback. |
102
+ | [`QRCode.min.js`](#qrcodeminjs) | classic-script | Vendored QRCode generator for DOM, canvas, SVG, and image output. | Browser vendor script | Vendor-native. |
103
+ | [`Questionnaire.js`](#questionnairejs) | esm | Evaluates whether a one-time questionnaire prompt is due without performing the prompt. | Cross-host | Normalized conservative boolean. |
104
+ | [`RecordLinkIndex.js`](#recordlinkindexjs) | esm | Parses record links and builds their normalized index. | Cross-host | Fully normalized. |
105
+ | [`RecordPassageIndex.js`](#recordpassageindexjs) | esm | Indexes text lines, page markers, dates, rules, and excerpts for record review. | Cross-host | Fully normalized. |
106
+ | [`RecordReviewStore.js`](#recordreviewstorejs) | esm | Stores normalized record-review decisions through native storage or app-scoped local fallback. | Browser/native hybrid | Complete records preserved; unreadable stored content fails observably. |
107
+ | [`RiskSignalAnalyzer.js`](#risksignalanalyzerjs) | esm | Matches configured risk signals and levels against complete text. | Cross-host | Fully normalized. |
108
+ | [`ScamRiskPolicy.js`](#scamriskpolicyjs) | esm | Combines deterministic scam signals with optional Arcane blocked-domain evidence and safety guidance. | Cross-host | Complete mutable results; blocked-domain policy requires `secure:true`. |
109
+ | [`ScopedOPFSCache.js`](#scopedopfscachejs) | esm | Provides a narrow exact-key JSON cache inside one app-owned OPFS namespace. | Browser / native WebView | Filename-safe keys, complete JSON values, and malformed-cache cleanup normalized; storage errors mixed. |
110
+ | [`ScreenCapture.js`](#screencapturejs) | esm | Captures a display surface as image, video, or GIF with explicit lifecycle events. | Browser / native WebView | State/events normalized; permission and codec errors mixed. |
111
+ | [`SpeechPlayback.js`](#speechplaybackjs) | esm | Preserves exact nonblank text as one speech segment, queues latest-request synthesis, and controls lookahead HTML audio playback. | Browser + native bridge | Exact input text and state normalized; provider/media failures mixed. |
112
+ | [`StaticDocumentCatalog.js`](#staticdocumentcatalogjs) | esm | Loads a positive static document inventory with cache, search, and complete context. | Browser / native WebView / server with fetch | Mutable complete catalog/content normalization; malformed data and transport failures remain visible. |
113
+ | [`SystemAppearance.js`](#systemappearancejs) | esm | Reads or applies native appearance, returning an explicit unsupported browser state when no bridge exists. | Browser/native hybrid | Absent bridge normalized; native result/error preserved. |
114
+ | [`SystemPlatformPresentation.js`](#systemplatformpresentationjs) | classic-script | Maps kernel names to presentation labels/classes without granting platform authority. | Browser / native WebView classic script | Fully normalized presentation only. |
115
+ | [`SystemToolRegistry.js`](#systemtoolregistryjs) | esm | Registers validated command builders and constructs command strings without executing them. | Cross-host | Fully normalized definitions/quoting. |
116
+ | [`TerminalClient.js`](#terminalclientjs) | esm | Maps native terminal sessions and Arcane events into an EventTarget client. | Native bridge | Client events/state normalized; native result/error mixed. |
117
+ | [`TerminalCommandRegistry.js`](#terminalcommandregistryjs) | esm | Routes parsed command lines to injected handlers and provides definitions/completions. | Cross-host | Parsing/routing normalized; handler result/error preserved. |
118
+ | [`ThemeBootstrap.js`](#themebootstrapjs) | esm | Performs import-time Arcane theme loading and subscribes to native appearance changes. | Browser/native hybrid | Theme state normalized; storage/native errors mixed. |
119
+ | [`ThemeManager.js`](#thememanagerjs) | esm | Loads, applies, previews, saves, resets, and synchronizes semantic Arcane themes. | Browser/native hybrid | Theme values/events normalized; storage/native failures mixed. |
120
+ | [`TimeGuard.js`](#timeguardjs) | esm | Persists and evaluates clock rollback and grace-period state. | Browser / native WebView | Time decisions normalized; storage lifecycle mixed. |
121
+ | [`ToolCallRouter.js`](#toolcallrouterjs) | esm | Parses OpenAI-style tool calls and dispatches complete or streamed calls to injected handlers. | Cross-host | Argument records validated; handler results returned or all-settled. |
122
+ | [`uPlot.iife.min.js`](#uplotiifeminjs) | classic-script | Vendored uPlot chart constructor and rendering runtime. | Browser vendor script | Vendor-native. |
123
+ | [`uPlot.LICENSE.txt`](#uplotlicensetxt) | license | License companion for the bundled uPlot vendor runtime. | Documentation asset | Not executable. |
124
+ | [`uPlot.min.css`](#uplotmincss) | stylesheet | Bundled uPlot presentation stylesheet. | Browser stylesheet | Presentation only. |
125
+ | [`WaitForComponent.js`](#waitforcomponentjs) | esm | Waits for a component property, method, or readiness event with optional error event and bounded timeout. | Cross-host EventTarget / browser component | Normalized coded readiness, error, and timeout results. |
126
+ | [`YouTubeMedia.js`](#youtubemediajs) | esm | Parses YouTube video/playlist locators and constructs ordinary embed URLs with opt-in privacy enhancement. | Cross-host | Fully normalized mutable locators. |
127
+
128
+ ## AI.js
129
+
130
+ ### Overview
131
+
132
+ Provider-selectable chat, speech-to-text, text-to-speech, tool calling,
133
+ structured output, streaming, bounded synthesis, and ordered audio-clock
134
+ playback.
135
+
136
+ ### Public surface
137
+
138
+ default `AI`; read-only `providerRuntime`, `browserSpeechConfiguration`, and
139
+ `browserSpeechDescriptor`; `configureBrowserSpeech(configuration,{signal})`,
140
+ `disposeBrowserSpeech({signal})`, `setAI()`, `configureProviders()`,
141
+ `configureSpeechProviders()`, `transitionAI()`, `transitionProviders()`,
142
+ `transitionSpeechProviders()`, `startProviders()`, `setSpeechMuted()`,
143
+ `streamRequest()`, `streamMessage()`, `fetchRequest()`, `fetch()`,
144
+ read-only `ttsSegmentation`, `configureTTSSegmentation()`,
145
+ `streamTTS(text='',end=false,options={})`,
146
+ `finishTTS()`, `fetchTTS()`, `fetchSTT()`, `stopAudio()`, `resumeAudio()`,
147
+ `playAudio()`; consumes `user-entity-loaded` and `arcane-ollama-ready`,
148
+ installs `window.ai`, and emits `ai-ready` and `ai-tts-failure`.
149
+
150
+ `fetch(...)` and `fetchRequest(options)` are asynchronous complete-response
151
+ entry points. `streamMessage(...)` and `streamRequest(options)` deliver
152
+ incremental responses. The positional and object forms share the existing
153
+ provider implementations; neither form is a retired compatibility API.
154
+
155
+ Initialization uses the canonical realm user's actual readiness state. If
156
+ `window.user?.ready` is already true, AI initializes immediately. Otherwise one
157
+ shared registration observes `user-entity-loaded`, then rechecks readiness
158
+ after registration so an event that occurred between the initial check and the
159
+ subscription cannot strand initialization. Source event projections do
160
+ not need to preserve object identity with `window.user`; the event only prompts
161
+ the readiness recheck. This boundary uses no timer or polling fallback.
162
+
163
+ The provider-runtime methods keep LLM, STT, and TTS selection explicit. They do
164
+ not reinterpret one provider's failure as permission to select another
165
+ provider. `transitionAI()` and `transitionProviders()` are deliberate
166
+ cross-role transitions: each stops queued audio, unloads the current LLM, STT,
167
+ and TTS roles, then applies the replacement configuration. `transitionAI()`
168
+ returns aggregate runtime status; `transitionProviders()` returns the configured
169
+ three-role route configuration. Selected TWiN Cloud `TWIN` LLM, `OLLAMA` LLM,
170
+ and Core `LOCAL_SPEACH` STT/TTS built-in routes expose truthful capability-only
171
+ readiness through internal provider/2 adapters without probing, downloading, or
172
+ hiding a load. Configured `OPENAI` speech preferences migrate to on-device
173
+ `LOCAL_SPEACH`, with Whisper for STT and Kokoro for TTS. TWiN Cloud availability
174
+ requires the selected LLM route, its model, a credential, and `fetch`; Core speech
175
+ availability requires the exact selected `Arcane.speech.transcribe` or
176
+ `synthesize` method. `fetchRequest()`
177
+ keeps the selected provider's public response shape. Browser speech routes
178
+ translate the existing AI.js STT `{audio:Blob|File,mimeType,model}` and TTS
179
+ `{model,input,responseFormat,voice?,speed?}` requests at the provider boundary;
180
+ only WAV is accepted for the shared TTS result. TTS voice selection comes from
181
+ the exact selected local provider/model catalog `defaultVoice`; a saved
182
+ OpenAI-route voice is never forwarded to another provider route.
183
+
184
+ The TWiN Cloud built-in provider and default-model preference sentinel are
185
+ `TWIN`. Applications upgrading saved `OPENAI` LLM selections must explicitly
186
+ replace only the exact uppercase `OPENAI` value in tuple slot 0 (LLM provider)
187
+ and slot 3 (default-model sentinel) with `TWIN`, before importing `AI.js` or any module that imports it,
188
+ hydrating a ready `window.user`, applying saved preferences, or starting
189
+ providers. Importing `AI.js` can immediately consume a ready user's saved tuple.
190
+ Keep every other tuple value unchanged.
191
+ The SDK supplies no built-in alias and does not rewrite persisted preferences.
192
+ Preserve `openai-gpt-oss-120b`, `openai-gpt-oss-20b`, OpenAI-compatible wire
193
+ terminology, and the separate Core `provider:'openai'` contract. See the
194
+ [complete migration example](ai/twin-cloud.md).
195
+
196
+ `fetchRequest()` and `streamRequest()` accept `reasoningEffort` as a
197
+ provider-neutral request option. Its exact values are `none`, `low`, `medium`,
198
+ `high`, and `max`; an omitted value leaves the provider default unchanged.
199
+ TWiN Cloud translates the selected value to the DigitalOcean Serverless
200
+ Inference `reasoning_effort` field. Its default model remains
201
+ `openai-gpt-oss-120b`, while an explicitly selected `openai-gpt-oss-20b` is
202
+ preserved. Reasoning effort does not alter complete streaming data, structural
203
+ tool declarations, emitted tool calls, or callback ordering.
204
+
205
+ `configureSpeechProviders({stt,tts})` commits only the two speech routes and
206
+ leaves the current LLM route and sticky lifecycle record unchanged. Both speech
207
+ roles must be unloaded, use local-only selections, and own no request, load,
208
+ unload, or dispose operation. Non-local STT and TTS selections reject with
209
+ `AI_STT_DEVICE_ONLY` and `AI_TTS_DEVICE_ONLY`, respectively.
210
+ `transitionSpeechProviders({stt,tts})` stops queued audio, explicitly unloads
211
+ only STT and TTS, then commits that same closed speech route record. Neither
212
+ method loads a model, selects a fallback, or changes caller-owned model or voice
213
+ policy.
214
+
215
+ `startProviders({startLanguageModel=true,startMuted=true,startTranscription=false,signal=null}={})`
216
+ starts provider-owned text chat without requesting an STT load by default.
217
+ Callers selecting a browser-WASM LLM pass `startLanguageModel:false` so it
218
+ remains selected and unloaded until the user uses the shared chat activation
219
+ control or the application publishes an equivalent explicit user load intent.
220
+ The default preserves startup behavior for existing Cloud/Core routes. Startup
221
+ does not undo an already ready or independently loading LLM or STT role. Its default
222
+ `startMuted:true` path cancels active TTS work and unloads TTS. Callers must opt
223
+ into eager STT startup with `startTranscription:true` or publish the explicit
224
+ user activation intent exposed by the shared speech component.
225
+ `setSpeechMuted(false)` records the public unmuted state only after the selected
226
+ TTS route reaches ready; a failed load leaves the public state muted. In contrast,
227
+ `setSpeechMuted(true)` cancels active TTS work and unloads that role.
228
+ The optional browser-speech `tts.execution` record selects
229
+ `device:'auto'|'webgpu'|'wasm'` and a `maxConcurrentRequests` integer from 1
230
+ through 4. Omission uses GPU-first automatic selection with four bounded Kokoro
231
+ Worker/session slots; STT remains one WASM Worker.
232
+ Capacity 4 means up to four segments synthesize at once. Segment 5 and later
233
+ wait in the SDK's FIFO queue; they are not dropped. Synthesis may finish out
234
+ of order, but playback waits for earlier segments and plays exact input order.
235
+ Each slot owns a Worker/model session, so raising capacity trades memory for
236
+ latency. This capacity does not establish physical GPU kernel overlap.
237
+
238
+ After configuration, explicitly inspect execution through
239
+ `ai.providerRuntime.status('tts', {execution:true}).execution`. When supplied
240
+ by the selected provider, this read returns its execution snapshot. Kokoro
241
+ reports `requestedDevice`, `selectedDevice`, `maxConcurrentRequests`, and
242
+ `activeRequestCount`. `selectedDevice` is `null` before load and after unload.
243
+ `requestedDevice === 'auto' && selectedDevice === 'wasm'` identifies automatic
244
+ WASM fallback after a successful load. Calling `status()` without options keeps
245
+ the existing sticky lifecycle snapshot and does not inspect provider execution.
246
+ Provider inspection failures are surfaced to the caller.
247
+ `fetchTTS({model,voice,input,responseFormat,speed},signal)` accepts the public
248
+ provider-neutral synthesis shape, requires any explicit model to match the
249
+ selected route, and fills an omitted voice only from the selected model
250
+ catalog's `defaultVoice`. An omitted response format preserves the instance's
251
+ existing `audioFormat` when the catalog does not declare response formats. When
252
+ the selected model declares `speech.responseFormats`, that setting is used only when supported; if
253
+ the setting is the instance's `opus` default and the model rejects it, the catalog's
254
+ `speech.defaultResponseFormat` is used, while any other unsupported setting is
255
+ rejected. It propagates the caller-owned signal and returns a playable `Blob`;
256
+ it does not independently choose a provider, cloud fallback, model, runtime, or
257
+ voice policy for the application. `streamTTS(text='',end=false,options={})` and
258
+ `finishTTS()` use this same request boundary. The third-argument options below
259
+ are available in SDK `0.5.12`:
260
+
261
+ | Field | Default | Meaning |
262
+ | --- | --- | --- |
263
+ | `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. |
264
+ | `speed` | Current `ai.voiceSpeed` | A supplied positive speed is captured for those segments and forwarded to `fetchTTS()`. It does not change `ai.voiceSpeed`. |
265
+ | `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. |
266
+ | `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. |
267
+
268
+ The voice and speed use the existing `fetchTTS()` validation and error path.
269
+ No option rewrites the submitted text. Overrides belong to the segments
270
+ extracted in that invocation, including any text buffered by an earlier call.
271
+ Options are not retained with an unfinished `end:false` remainder; a later
272
+ call supplies its own options, and `finishTTS()` uses defaults. Use `end:true`
273
+ for a complete passage. A call extracting no segments resolves
274
+ `true` without waiting for earlier jobs; `finishTTS()` remains a preparation
275
+ flush, not a queue-wide playback barrier. A muted call resolves `false`.
276
+
277
+ Playback completion stays pending while the browser waits for an audio-unlock
278
+ gesture or a recoverable resume attempt. If resuming a closed `AudioContext`
279
+ fails, the affected jobs terminate and their playback results settle `false`.
280
+ `stopAudio()` cancels all speech owned
281
+ by this AI instance and settles pending playback promises `false`. A trailing
282
+ pause delays the next queued audio; the preceding promise resolves when its
283
+ last audio buffer ends, without waiting out that pause. Completion describes
284
+ the playback lifecycle, not proof that a listener heard the sound. See the
285
+ [complete-passage example](ai/browser-speech.md#queue-complete-passages-and-wait-for-playback).
286
+
287
+ Streaming speech retains sentence
288
+ segmentation by default. `configureTTSSegmentation({punctuation,wordCadence})`
289
+ accepts `punctuation:'sentence'|'any'|'none'` and a `wordCadence` that is either
290
+ `null` or a positive integer. `punctuation:'any'` completes a segment at a
291
+ Unicode punctuation run without requiring following whitespace. Apostrophes,
292
+ commas, and hyphens remain inside a segment when they join Unicode letters or
293
+ numbers. A potentially joining mark at the current end of an incremental stream
294
+ waits for the next character or terminal flush before the boundary is decided;
295
+ `wordCadence` completes one after that many whole words. The earliest available
296
+ boundary wins. Segmentation preserves every character, including punctuation
297
+ and whitespace. Every completed segment enters synthesis immediately; provider
298
+ capacity supplies FIFO backpressure while allowing bounded TTS work to overlap.
299
+ A later segment may finish synthesis first, but playback schedules only the
300
+ contiguous ready prefix in original order. Decoded buffers with known duration
301
+ are placed consecutively on the `AudioContext` clock, so callback latency does
302
+ not add a seam between ready chunks. A genuine synthesis underrun begins the
303
+ next buffer at the current audio time. Mute, stop, provider transition, and
304
+ cancellation retain authority over the complete queue and already scheduled
305
+ sources.
306
+ Every active-generation, non-abort synthesis, decode, playback-start, or
307
+ playback-resume failure emits `ai-tts-failure` with the complete `Error`, exact
308
+ operation boundary, generation, and stable reason. Muting, explicit
309
+ cancellation, permission waiting, and superseded generations do not emit a
310
+ failure. The operation event does not rewrite provider readiness; the consuming
311
+ Chat/Speech surface owns its visible mute and recovery state.
312
+ `fetchSTT(audioFile,signal)` propagates the caller-owned signal;
313
+ provider routes accept a `Blob` or `File` directly and leave media decoding,
314
+ PCM normalization, and WAV construction to the selected shared provider;
315
+ delivery suppression is guaranteed after abort, while underlying provider-stop
316
+ claims remain limited to that provider's cancellation contract.
317
+
318
+ Every function declaration accepted by the chat and streaming APIs must define
319
+ `function.parameters.properties.message` as a string with `minLength:1` and
320
+ include `message` in the declaration's `required` list. Every emitted structural
321
+ call must preserve its exact nonempty `id`, function name, and JSON argument
322
+ string; that JSON must encode an object with a nonempty user-facing `message`.
323
+ The message is ordinary progress or next-step text. Complete argument envelopes
324
+ remain available to an explicitly opened inspection surface or developer
325
+ console, but are not substituted for conversational text. A visible call is
326
+ still pending until a matching `role:'tool'` message records an executed,
327
+ declined, cancelled, or not-executed result.
328
+ That tool-result content must be a nonblank string and is preserved exactly.
329
+
330
+ `streamRequest()` owns the complete terminal callback sequence. `onDataChunk`
331
+ receives each complete provider chunk before ordinary projection, while
332
+ `onChunk` receives every nonstructural content or reasoning value from every
333
+ choice in provider order. After the stream settles, `onDataResult` receives the
334
+ complete terminal completion, `onResponse` receives that same unprojected
335
+ provider response, `onToolCall` runs exactly once for each complete normalized
336
+ structural call, and `onComplete` receives the application-facing output. That
337
+ output is the ordered structural-call array when the selected result contains
338
+ tools, the complete completion object when it contains multiple choices, or
339
+ the ordinary single-result text/completion otherwise; later choices are never
340
+ discarded.
341
+ Partial structural deltas remain private until the matching terminal envelope
342
+ validates. Request observers receive
343
+ `onRequest(request,id,metadata)` and any transport metadata supplied by the
344
+ selected route is forwarded unchanged. Every async native, HTTP, provider, and
345
+ built-in callback is observed before the next callback or terminal settlement.
346
+
347
+ Native Ollama responses are adapted before the shared structural validator:
348
+ provider-native calls may omit `id` and `type` or provide object arguments, so
349
+ the adapter assigns a deterministic request-local call ID when needed, sets
350
+ `type:'function'`, and JSON-encodes complete object arguments. This adaptation
351
+ never invents the required user-facing `arguments.message`. Every response
352
+ choice is scanned; a structural call outside the selected result or a streamed
353
+ call that changes or disappears at terminal settlement is rejected with
354
+ `AI_CHAT_STREAM_TOOL_CALL_MISMATCH` before public tool-call delivery.
355
+
356
+ #### Browser speech configuration
357
+
358
+ The caller constructs a mutable authority record for one or both roles and
359
+ retains ownership of it. Start with the [complete beginner speech example](ai/browser-speech.md)
360
+ to define your DBOPFS, runtime, model, and voice selections. In this advanced
361
+ example, `applicationSpeech` is the application-supplied object containing its
362
+ `dbopfs`, `sttGraph`, and `ttsGraph`; every other variable is defined below.
363
+
364
+ ```javascript
365
+ import AI, {
366
+ AI_BROWSER_SPEECH_CONFIGURATION_PROTOCOL
367
+ } from '/arcane/modules/AI.js';
368
+
369
+ const {dbopfs, sttGraph, ttsGraph} = applicationSpeech;
370
+ const controller = new AbortController();
371
+ const signal = controller.signal;
372
+ const speechConfiguration = {
373
+ protocol: AI_BROWSER_SPEECH_CONFIGURATION_PROTOCOL,
374
+ id: 'app-speech-authority',
375
+ dbopfs,
376
+ tableName: 'browser-speech-artifacts', // optional
377
+ stt: {
378
+ providerId: 'app-whisper',
379
+ graph: sttGraph,
380
+ offline: false
381
+ },
382
+ tts: {
383
+ providerId: 'app-kokoro',
384
+ graph: ttsGraph,
385
+ offline: false,
386
+ execution: {
387
+ device: 'auto',
388
+ maxConcurrentRequests: 4
389
+ }
390
+ }
391
+ };
392
+
393
+ const ai = new AI();
394
+ const descriptor = await ai.configureBrowserSpeech(
395
+ speechConfiguration,
396
+ {signal}
397
+ );
398
+
399
+ // Configuration does not load either role. Activate only from an explicit UI.
400
+ await ai.providerRuntime.load('stt', {signal});
401
+ await ai.setSpeechMuted(false); // loads the selected TTS role, then unmutes
402
+
403
+ // Teardown unloads, unregisters, and disposes only this SDK-owned configuration.
404
+ await ai.disposeBrowserSpeech({signal});
405
+ ```
406
+
407
+ The record is a mutable plain data record with exactly
408
+ `{protocol,id,dbopfs,tableName?,stt?,tts?}` and at least one role. Each supplied
409
+ mutable STT role is exactly `{providerId,graph,security?,offline}` or
410
+ `{providerId,model,runtime,security?,offline}`. TTS accepts the corresponding
411
+ shape plus optional `execution:{device,maxConcurrentRequests}`. The graph and
412
+ direct authority forms are mutually exclusive; `providerId` and `id` are nonblank exact strings,
413
+ `graph` is the role-matching graph returned by the SDK browser
414
+ speech artifact API, and `offline` is boolean. The direct form forwards its
415
+ caller-selected model and runtime descriptors to the shared
416
+ provider. In ordinary mode it may use an empty `model.files` inventory and a
417
+ caller-selected upstream `runtime.wasmPaths`. The application
418
+ chooses every artifact, graph or direct model/runtime authority, provider ID, offline policy,
419
+ sample rate, and TTS default voice. `configureBrowserSpeech()` imports the shared
420
+ browser-speech module, creates one DBOPFS store, constructs and registers the
421
+ supplied Whisper and/or Kokoro provider/2 instances, atomically replaces only
422
+ the supplied STT/TTS routes, and returns a mutable descriptor. An initial or
423
+ later call may supply only `stt` or only `tts`; the omitted unmanaged or Core
424
+ role remains unchanged and is not claimed as SDK browser-provider ownership.
425
+ A partial replacement of an existing browser-managed record retains the same
426
+ `dbopfs` and `tableName`, carries every omitted managed browser provider and
427
+ route unchanged, and unregisters and disposes only the replaced provider after
428
+ commit. Supplying both roles remains one atomic replacement. Applications do not register those
429
+ providers, decode `Blob`/`File` data into PCM, construct WAV, select Worker URLs,
430
+ or reproduce DBOPFS cache logic.
431
+
432
+ The returned descriptor is exactly `{protocol,configurationId,stt,tts}`; an
433
+ external, unmanaged role is `null`. A managed STT descriptor is
434
+ `{role:'stt',providerId,modelId,artifactGraphId?,offline}`; TTS adds
435
+ `defaultVoice` and the normalized `execution` record. `artifactGraphId` is present only for the graph form.
436
+ `browserSpeechConfiguration` returns the exact caller-owned record when no
437
+ managed role is carried. After a partial replacement that carries another
438
+ managed role, it returns a mutable merged record with the replacement call's
439
+ `id` and the carried role's unchanged authority. It is non-null only while the
440
+ SDK still owns every represented browser provider and route;
441
+ `browserSpeechDescriptor` returns that descriptor on the same condition.
442
+ Configuration never loads a role, auto-downloads, selects an alternative
443
+ provider/model/runtime/voice, or falls back to an unmanaged or alternative
444
+ browser-speech route.
445
+
446
+ Calling `configureBrowserSpeech()` again with the same active record for every
447
+ supplied role is an idempotent descriptor read. A different call is serialized,
448
+ aborts the prior owned operation, unloads only the replaced speech roles, atomically
449
+ replaces provider ownership/routes, and suppresses stale settlement. A
450
+ single-role replacement does not reconstruct, unregister, dispose, or reroute
451
+ the omitted role or change its ready/selected state, provider identity,
452
+ operation generation, or lifecycle. STT-only replacement also preserves TTS
453
+ mute and playback state; TTS replacement invalidates current TTS speech control
454
+ before replacing that role. The caller's signal is
455
+ forwarded and detached on settlement. Cancellation proves delivery suppression,
456
+ not that provider work stopped beyond the provider's own cancellation contract.
457
+ Once SDK-owned browser speech is active, synchronous route mutation fails with
458
+ `ARCANE_AI_BROWSER_SPEECH_ASYNC_TRANSITION_REQUIRED`; use an asynchronous
459
+ transition method or await `disposeBrowserSpeech()`.
460
+
461
+ Browser speech publishes these exact event values through the AI instance's
462
+ canonical event source. Public consumers use
463
+ `arcaneEvents.subscribe(type,handler,{signal})`; `handler(occurrence)` receives
464
+ the mutable complete canonical occurrence and can correlate `source:'ai'`, `instanceId`,
465
+ and `operationId`:
466
+
467
+ | Constant member | Stable value |
468
+ | --- | --- |
469
+ | `configurationStarted` | `ai-browser-speech-configuration-started` |
470
+ | `configured` | `ai-browser-speech-configured` |
471
+ | `configurationCancelled` | `ai-browser-speech-configuration-cancelled` |
472
+ | `configurationError` | `ai-browser-speech-configuration-error` |
473
+ | `disposed` | `ai-browser-speech-disposed` |
474
+
475
+ Canonical public details are mutable and contain `configurationId`, optional
476
+ `descriptor`, optional exact `code`, and `reason`. The private source-local
477
+ view also carries the caller-owned configuration and optional
478
+ error, but `AI` does not expose that source handle and the global occurrence
479
+ does not publish those private values. Reasons are exactly `speech-configuration-added`,
480
+ `speech-configuration-replaced`, `speech-configuration-cancelled`,
481
+ `speech-configuration-disposed`, `speech-configuration-contract-mismatch`,
482
+ `speech-configuration-async-transition-required`,
483
+ `speech-operation-options-contract-mismatch`,
484
+ `speech-operation-sequence-exhausted`, `speech-module-import-rejected`,
485
+ `speech-artifact-store-construction-rejected`,
486
+ `speech-provider-construction-rejected`, `speech-provider-disposal-rejected`,
487
+ `speech-provider-route-ownership-mismatch`,
488
+ `speech-provider-unregistration-rejected`, `speech-route-commit-rejected`,
489
+ `speech-route-rollback-rejected`, and `speech-route-view-update-rejected`.
490
+ Their corresponding exact public codes are the values of
491
+ `AI_BROWSER_SPEECH_ERROR_CODES`: `ARCANE_AI_BROWSER_SPEECH_CONFIGURATION_CANCELLED`,
492
+ `ARCANE_AI_BROWSER_SPEECH_CONFIGURATION_SUPERSEDED`,
493
+ `ARCANE_AI_BROWSER_SPEECH_CONFIGURATION_CONTRACT_MISMATCH`,
494
+ `ARCANE_AI_BROWSER_SPEECH_ASYNC_TRANSITION_REQUIRED`,
495
+ `ARCANE_AI_BROWSER_SPEECH_OPERATION_OPTIONS_CONTRACT_MISMATCH`,
496
+ `ARCANE_AI_BROWSER_SPEECH_OPERATION_SEQUENCE_EXHAUSTED`,
497
+ `ARCANE_AI_BROWSER_SPEECH_MODULE_IMPORT_REJECTED`,
498
+ `ARCANE_AI_BROWSER_SPEECH_ARTIFACT_STORE_CONSTRUCTION_REJECTED`,
499
+ `ARCANE_AI_BROWSER_SPEECH_PROVIDER_CONSTRUCTION_REJECTED`,
500
+ `ARCANE_AI_BROWSER_SPEECH_PROVIDER_DISPOSAL_REJECTED`,
501
+ `ARCANE_AI_BROWSER_SPEECH_PROVIDER_ROUTE_OWNERSHIP_MISMATCH`,
502
+ `ARCANE_AI_BROWSER_SPEECH_PROVIDER_UNREGISTRATION_REJECTED`,
503
+ `ARCANE_AI_BROWSER_SPEECH_ROUTE_COMMIT_REJECTED`,
504
+ `ARCANE_AI_BROWSER_SPEECH_ROUTE_ROLLBACK_REJECTED`, and
505
+ `ARCANE_AI_BROWSER_SPEECH_ROUTE_VIEW_UPDATE_REJECTED`.
506
+
507
+ `fetchTTS()` rejects malformed request/signal/input/model/voice/format/speed
508
+ boundaries with `ARCANE_AI_TTS_REQUEST_INVALID`,
509
+ `ARCANE_AI_TTS_SIGNAL_INVALID`, `ARCANE_AI_TTS_INPUT_INVALID`,
510
+ `ARCANE_AI_TTS_MODEL_INVALID`, `ARCANE_AI_TTS_MODEL_REQUIRED`,
511
+ `ARCANE_AI_TTS_MODEL_SELECTION_MISMATCH`, `ARCANE_AI_TTS_VOICE_INVALID`,
512
+ `ARCANE_AI_TTS_VOICE_REQUIRED`, `ARCANE_AI_TTS_RESPONSE_FORMAT_INVALID`, or
513
+ `ARCANE_AI_TTS_SPEED_INVALID`; a non-playable provider result is
514
+ `ARCANE_AI_TTS_PROVIDER_AUDIO_INVALID`. `fetchSTT()` uses
515
+ `ARCANE_AI_STT_SIGNAL_INVALID` and `ARCANE_AI_STT_PROVIDER_TRANSCRIPT_INVALID`
516
+ at those exact boundaries. Owned
517
+ request abortion is `ARCANE_AI_REQUEST_ABORTED`.
518
+
519
+ Exact exports: `AI_BROWSER_SPEECH_CONFIGURATION_PROTOCOL`,
520
+ `AI_BROWSER_SPEECH_ERROR_CODES`, `AI_BROWSER_SPEECH_EVENT_TYPES`,
521
+ `AI_BROWSER_SPEECH_REASONS`, `AI_INITIALIZATION_ERROR_CODES`,
522
+ `AI_INITIALIZATION_REASONS`, `AI_READY_EVENT`, and `default`.
523
+
524
+ ### Availability and normalization
525
+
526
+ **Browser + native bridge + TWiN Cloud.** High-level chat/speech behavior is
527
+ normalized; provider diagnostics and media errors remain mixed. Transport:
528
+ AIProviderRuntime `arcane-ai-provider/2` routes, TWiN Cloud HTTPS, Arcane.ollama,
529
+ Arcane.speech, and the Android WebView bridge. [Deep protocol details](protocols.md).
530
+
531
+ ### Example
532
+
533
+ This function sends one TWiN request. `applicationRuntime` is the one
534
+ application-supplied argument: it provides a runtime `twinKey`. Call the
535
+ function from your application's send action; do not commit a key in source.
536
+
537
+ ```javascript
538
+ import AI from '/arcane/modules/AI.js';
539
+
540
+ async function sayHello(applicationRuntime) {
541
+ const ai = new AI();
542
+ ai.twinKey = applicationRuntime.twinKey;
543
+ try {
544
+ const response = await ai.fetchRequest(
545
+ {
546
+ messages: [{role: 'user', content: 'Hello!'}]
547
+ }
548
+ );
549
+ console.log(JSON.stringify(response, null, 2));
550
+ } catch (error) {
551
+ console.error(error.code, error.message);
552
+ }
553
+ }
554
+ ```
555
+
556
+ For on-device TTS, use the [browser speech quick start](ai/browser-speech.md).
557
+
558
+ ## AIPreferenceRuntime.js
559
+
560
+ ### Overview
561
+
562
+ Applies and reads non-persistent per-user AI preference overrides.
563
+
564
+ ### Public surface
565
+
566
+ `setAIPreferenceRuntimeOverride()`, `getAIPreferencesForRuntime()`.
567
+
568
+ Exact exports: `getAIPreferencesForRuntime`, `setAIPreferenceRuntimeOverride`.
569
+
570
+ ### Availability and normalization
571
+
572
+ **Cross-host.** Normalized six-slot preference state. Transport: In-process only. [Deep protocol details](protocols.md).
573
+
574
+ ### Example
575
+
576
+ ```javascript
577
+ import * as module from '/arcane/modules/AIPreferenceRuntime.js';
578
+
579
+ console.log(Object.keys(module));
580
+ ```
581
+
582
+ ## AIPreferenceTuple.js
583
+
584
+ ### Overview
585
+
586
+ Normalizes and compares the six provider/model preference slots.
587
+
588
+ ### Public surface
589
+
590
+ `AI_PREFERENCE_SLOT_KEYS`, `normalizeAIPreferenceTuple()`, `aiPreferenceTuplesEqual()`.
591
+
592
+ Exact exports: `AI_PREFERENCE_SLOT_KEYS`, `aiPreferenceTuplesEqual`, `normalizeAIPreferenceTuple`.
593
+
594
+ ### Availability and normalization
595
+
596
+ **Cross-host.** Fully normalized frozen tuple. Transport: In-process only. [Deep protocol details](protocols.md).
597
+
598
+ ### Example
599
+
600
+ ```javascript
601
+ import * as module from '/arcane/modules/AIPreferenceTuple.js';
602
+
603
+ console.log(Object.keys(module));
604
+ ```
605
+
606
+ ## AIProviderRuntime.js
607
+
608
+ ### Overview
609
+
610
+ Owns the portable provider-neutral runtime for independently selected LLM,
611
+ speech-to-text, and text-to-speech providers. The exported class documents the
612
+ shape, but application code uses the exported singleton returned by
613
+ `getAIProviderRuntime()`; direct construction fails with
614
+ `ARCANE_AI_RUNTIME_SINGLETON_REQUIRED`.
615
+
616
+ ### Public surface
617
+
618
+ Exact exports: `AI_MODEL_AUTHORITY_PROTOCOL`, `AI_PROVIDER_PROTOCOL`,
619
+ `AI_PROVIDER_RUNTIME_PROTOCOL`, `AIProviderRuntime`, `aiProviderRuntime`, and
620
+ `getAIProviderRuntime`.
621
+
622
+ The singleton exposes read-only `protocol`, `configured`, and `speechMuted`;
623
+ `register(provider)`; `unregister(role,providerId,expectedProvider=null)`;
624
+ `hasProvider(role,providerId)`; `ownsProvider(role,expectedProvider)`;
625
+ `providerIdentity(role,providerId)`; `selection(role,options={})`;
626
+ `ownsSelection(role,providerId,options={})`;
627
+ `validateConfiguration(value)`; `validateSpeechConfiguration(value)`;
628
+ `configure(value)`; `configureSpeech(value)`;
629
+ `replaceSpeechProvider(role,value)`; `replaceSpeechProviders(value)`;
630
+ `configureFromTuple(tuple)`;
631
+ `status(role=null,options={})`; `catalog(role)`;
632
+ `inspect(role,options={})`; `start(options)`; `load(role,options={})`;
633
+ `unload(role,options={})`; `dispose(role,options={})`;
634
+ `disposeAll(options={})`; `cancel(role)`; `request(role,options={})`;
635
+ `chat(payload,options={})`; `stream(payload,options={})`;
636
+ `transcribe(payload,options={})`; `synthesize(payload,options={})`; and
637
+ `setSpeechMuted(muted)`. Provider payloads must be data-only; callbacks,
638
+ accessors, symbols, and cycles are rejected at the provider boundary.
639
+
640
+ Selection options admit `localOnly=false`; inspection admits
641
+ `{localOnly=false,signal=null}`; startup admits
642
+ `{startLanguageModel=true,startMuted=true,startTranscription=false,signal=null}` (including an omitted
643
+ `options` value); load admits `{signal=null,localOnly=false}`; unload, dispose,
644
+ and dispose-all admit `{signal=null}`. Request requires the exact
645
+ `{operation,payload,localOnly,signal}` options record; the four role-specific
646
+ request helpers admit `{localOnly=false,signal=null}`. Configuration `value`
647
+ records are the closed `{llm,stt,tts}`, `{stt,tts}`, or
648
+ `{provider,routes,expectedProvider}` and
649
+ `{providers,routes,expectedProviders}` shapes described below.
650
+ `configureFromTuple()` accepts exactly six provider/model preference entries.
651
+
652
+ `register()` returns the provider's single unregister closure; caller-
653
+ registered providers remain caller-owned. The high-level
654
+ `AI.configureBrowserSpeech()` boundary is different: AI constructs, registers,
655
+ atomically replaces, unregisters, and disposes those two SDK-owned providers.
656
+ `status()` is the sticky mutable AIRuntimeState snapshot (or one role record),
657
+ while `catalog()` synchronously returns mutable provider/model entries and
658
+ never loads or downloads a model. `load()` forwards provider progress into the
659
+ sticky role record; `unload()` and `dispose()` abort owned work, await exposed
660
+ settlement, and verify provider status before publishing terminal state.
661
+
662
+ `status('tts', {execution:true})` explicitly reads the selected provider and
663
+ adds its optional `execution` snapshot to a copy of the role record.
664
+ `status(null, {execution:true})` provides the equivalent projection under
665
+ `roles.llm`, `roles.stt`, and `roles.tts`. Providers that do not supply execution
666
+ omit that field. No provider load or sticky-state event is triggered; default
667
+ `status()` keeps its existing identity and behavior. A provider inspection
668
+ error propagates. Kokoro's execution contains `requestedDevice`,
669
+ `selectedDevice` (`null` while unloaded), `maxConcurrentRequests`, and
670
+ `activeRequestCount`; these describe provider execution, not physical GPU
671
+ kernel overlap.
672
+
673
+ `validateSpeechConfiguration(value)` returns one mutable two-role selection
674
+ record without committing it, where `value` is the closed `{stt,tts}` record.
675
+ `configureSpeech(value)` accepts the same record, requires both speech roles to
676
+ own no ready/load/unload/dispose or request work, commits only STT/TTS, restores
677
+ muted speech selection, and returns the mutable selection record. The current LLM
678
+ routes, selection, readiness, operation generation, and sticky state remain
679
+ unchanged. A malformed top-level, route, or selection record preserves the
680
+ current error code
681
+ `ARCANE_AI_PROVIDER_RUNTIME_INVALID` and adds exact reason
682
+ `speech-configuration-contract-mismatch`; runtime-disposed, reentrant,
683
+ role-busy, and provider-locality failures retain their existing exact codes.
684
+
685
+ `replaceSpeechProvider(role,value)` accepts only `stt` or `tts` and atomically
686
+ replaces exactly that unloaded role using the closed
687
+ `{provider,routes,expectedProvider}` record. A null `provider` with empty routes
688
+ removes that role and requires its exact non-null expected provider. The method preserves the omitted role's
689
+ provider registration, routes, selection, readiness, generation, sticky state,
690
+ owned lifecycle work, and TTS mute state. `replaceSpeechProviders(value)` keeps
691
+ the existing atomic two-role boundary for a coordinated STT/TTS replacement.
692
+ Either replacement may replace a selected-but-unregistered pending speech
693
+ placeholder whose saved locality is still `null`. Every existing pending route
694
+ must agree with that saved placeholder; the replacement provider and routes
695
+ then define the actual selected provider and model. Registration and route
696
+ publication remain one commit without loading either provider; an already
697
+ registered, local-only, busy, or partially divergent selection rejects without
698
+ changing either role.
699
+
700
+ `start(options)` waits for prior speech-state and role unload work, applies the
701
+ requested initial mute state, and returns the `startAIRuntime()` control handle
702
+ `{barrier,settled,cancel}`. With `startLanguageModel:false`, startup does not
703
+ request the selected LLM and its barrier may therefore resolve with `chatReady:false` and
704
+ `roles.llm.requested:false` while the explicit activation UI remains available.
705
+ Startup does not request selected STT unless the caller explicitly opts in; it
706
+ does not force an independently active STT role back to unloaded. The barrier
707
+ and settled promises describe only requested provider-startup work;
708
+ cancellation remains cooperative through the supplied signal and returned
709
+ control.
710
+
711
+ Interactive requests enter a FIFO lane per role. Providers omit
712
+ `maxConcurrentRequests` to retain capacity 1. A TTS provider may declare a
713
+ positive safe-integer capacity; the runtime starts that many oldest requests
714
+ and retains later work in FIFO order. LLM and STT remain capacity 1. A newer
715
+ request does not abort or discard earlier work. A caller `AbortSignal` cancels
716
+ only its own queued or active request, while `cancel(role)` targets the oldest
717
+ active request. Explicit unload and dispose reject queued work, cancel every
718
+ active request, await settlement, and then clean the provider. Load and
719
+ configuration remain unavailable while that role owns active or queued request
720
+ work. Promise settlement proves only that the provider's exposed request promise
721
+ completed; provider-specific cancellation acknowledgement remains the selected
722
+ provider's boundary.
723
+
724
+ Direct LLM `request()`, `chat()`, and `stream()` use the same message history,
725
+ tool-declaration, emitted-call, all-choice, and ordered parallel-call contracts
726
+ as the high-level AI API module, including one nonblank matching result for
727
+ every pending tool-call ID. A complete text-only terminal string remains
728
+ compatible; structured terminals must use exactly one message or choices
729
+ envelope. An ordinary stream iterator exposes complete nonstructural content
730
+ and reasoning projections from every choice in FIFO order; provider-native
731
+ tool deltas remain private until the complete terminal result validates. The
732
+ runtime drains private provider streams even when `result` is awaited before
733
+ iteration, buffers projected chunks for later consumption, and retains the
734
+ complete validated terminal provider response on `result`. A terminal-only
735
+ tool call is valid; any tool call observed during streaming must retain the
736
+ same choice, ID, type, function name, argument string, and extension fields at
737
+ terminal settlement. Consumer `return()` starts observed cancellation
738
+ immediately and returns promptly; provider cleanup and any failure remain
739
+ observable through the terminal result or complete developer-console
740
+ diagnostics rather than blocking iterator return.
741
+
742
+ ### Availability and normalization
743
+
744
+ **Cross-host runtime with provider-specific execution.** The SDK source ships
745
+ the browser-WASM LLM and browser Whisper/Kokoro adapters and supplies the
746
+ narrow AI.js TWiN Cloud LLM, Ollama, and local Core-speech adapters; other
747
+ native, Core, or cloud adapters may be supplied externally only when they implement the same
748
+ `arcane-ai-provider/2` boundary. A
749
+ provider must prove a matching `arcane-ai-model-authority/1` inspection before load.
750
+ `localOnly` routing fails closed; it never selects a cloud or non-local route as
751
+ a fallback. A missing or mismatched explicit local-only route rejects load or
752
+ request selection with `AI_LOCAL_MODEL_REQUIRED`. Role lifecycle and stream
753
+ cleanup are normalized, while the
754
+ selected provider retains its own capability, permission, download, and model
755
+ requirements. [Deep protocol details](protocols.md#portable-ai-provider-runtime).
756
+
757
+ ### Example
758
+
759
+ ```javascript
760
+ import {getAIProviderRuntime} from '/arcane/modules/AIProviderRuntime.js';
761
+
762
+ const runtime = getAIProviderRuntime();
763
+ console.log(runtime.protocol, runtime.status());
764
+ ```
765
+
766
+ ## AIResponseLength.js
767
+
768
+ ### Overview
769
+
770
+ Normalizes current low/medium/high response-preference selectors while
771
+ preserving complete prompts unchanged.
772
+
773
+ ### Public surface
774
+
775
+ Response-preference constants plus `normalizeAIResponseLength()`,
776
+ `aiResponseLengthInstruction()`, and `applyAIResponseLength()`. Every option is
777
+ labeled `Complete`, the instruction helper returns an empty string, and the
778
+ application helper returns its complete `systemPrompt` unchanged.
779
+
780
+ Exact exports: `AI_RESPONSE_LENGTH_DEFAULT`, `AI_RESPONSE_LENGTH_OPTIONS`, `aiResponseLengthInstruction`, `applyAIResponseLength`, `normalizeAIResponseLength`.
781
+
782
+ ### Availability and normalization
783
+
784
+ **Cross-host.** Current selector normalization with no prompt transformation.
785
+ Transport: In-process only. [Deep protocol details](protocols.md).
786
+
787
+ ### Example
788
+
789
+ ```javascript
790
+ import * as module from '/arcane/modules/AIResponseLength.js';
791
+
792
+ console.log(Object.keys(module));
793
+ ```
794
+
795
+ ## AIResponseURLPolicy.js
796
+
797
+ ### Overview
798
+
799
+ Extracts and audits links from AI Markdown, rendered HTML, CSS, srcset, bare URLs, and email text.
800
+
801
+ ### Public surface
802
+
803
+ `auditAIResponseLinks()`, `extractAIResponseLinks()`, `normalizeAIResponseLink()`, `decodeHTMLCharacterReferences()`.
804
+
805
+ Exact exports: `auditAIResponseLinks`, `decodeHTMLCharacterReferences`, `extractAIResponseLinks`, `normalizeAIResponseLink`.
806
+
807
+ ### Availability and normalization
808
+
809
+ **Cross-host.** Normalized frozen allowlist audit. Transport: In-process; bundled Marked parser. [Deep protocol details](protocols.md).
810
+
811
+ ### Example
812
+
813
+ ```javascript
814
+ import * as module from '/arcane/modules/AIResponseURLPolicy.js';
815
+
816
+ console.log(Object.keys(module));
817
+ ```
818
+
819
+ ## AIRuntimeState.js
820
+
821
+ ### Overview
822
+
823
+ Publishes one sticky mutable state tree for `llm`, `stt`, and `tts`, transient
824
+ load/unload/dispose intents, and a startup-settlement report. It makes lifecycle
825
+ observable without exposing provider transports in application code.
826
+
827
+ ### Public surface
828
+
829
+ Exact exports: `AI_RUNTIME_INTENT_EVENT`, `AI_RUNTIME_PROTOCOL`,
830
+ `AI_RUNTIME_ROLES`, `AI_RUNTIME_STARTUP_EVENT`, `AI_RUNTIME_STATES`,
831
+ `AI_RUNTIME_STATE_EVENT`, `getAIRuntimeState`,
832
+ `publishAIRuntimeRoleState`, `publishAIRuntimeRolesState`,
833
+ `requestAIRuntimeIntent`, `startAIRuntime`, `subscribeAIRuntimeIntents`, and
834
+ `subscribeAIRuntimeState`.
835
+
836
+ Each role record is exactly `{role,state,providerId,modelId,localOnly,loaded,
837
+ busy,operationId,progress,error}`.
838
+ `subscribeAIRuntimeState(listener,{signal=null,emitCurrent=true})` installs its
839
+ subscription and synchronously replays the current mutable snapshot by default;
840
+ `subscribeAIRuntimeIntents(listener,{signal=null})` is future-only. Both return
841
+ one idempotent unsubscribe/dispose closure.
842
+ `startAIRuntime({startLanguageModel=true,startMuted=true,startTranscription=false,signal})` returns
843
+ `{barrier,settled,cancel}`: `barrier` settles for requested text-chat startup,
844
+ while `settled` covers every requested role. With `startLanguageModel:false`, a
845
+ selected LLM remains unloaded for explicit user activation, so the barrier can settle honestly with
846
+ `chatReady:false` and `roles.llm.requested:false`. Muted startup does not request
847
+ TTS, and STT startup is opt-in so selection and state observation do not begin a
848
+ transcription-model load.
849
+
850
+ ### Availability and normalization
851
+
852
+ **Cross-host state contract.** States are `unavailable`, `unloaded`, `loading`,
853
+ `ready`, `unloading`, `error`, and `disposed`. Revisions increase monotonically.
854
+ The events `arcane-ai-runtime-state`, `arcane-ai-runtime-intent`, and
855
+ `arcane-ai-runtime-startup-settled` normalize observation only: receiving one
856
+ does not grant a native capability, prove browser support, or load a provider.
857
+ `arcane-ai-runtime-startup-settled` reports the LLM/text-chat `barrier`.
858
+ Await the returned `handle.settled` promise for every role requested by that
859
+ startup; the all-role settlement has no separate public event.
860
+ Intent records are exactly `{role,action,reason}` where roles are `llm`, `stt`,
861
+ or `tts`; actions are `load`, `unload`, or `dispose`; and reasons are `startup`,
862
+ `user`, or `teardown`. Invalid closed records fail with the stable prefix
863
+ `ARCANE_AI_RUNTIME_STATE_INVALID`; startup cancellation is an `AbortError` with
864
+ code `ARCANE_AI_REQUEST_ABORTED`.
865
+
866
+ ### Example
867
+
868
+ ```javascript
869
+ import {
870
+ getAIRuntimeState,
871
+ subscribeAIRuntimeState
872
+ } from '/arcane/modules/AIRuntimeState.js';
873
+
874
+ const unsubscribe = subscribeAIRuntimeState(snapshot => {
875
+ console.log(snapshot.roles.llm.state);
876
+ });
877
+ console.log(getAIRuntimeState().protocol);
878
+ unsubscribe();
879
+ ```
880
+
881
+ ## AnsiText.js
882
+
883
+ ### Overview
884
+
885
+ Parses terminal ANSI sequences into display spans or strips them to plain text.
886
+
887
+ ### Public surface
888
+
889
+ `parseAnsi()`, `stripAnsi()`.
890
+
891
+ Exact exports: `parseAnsi`, `stripAnsi`.
892
+
893
+ ### Availability and normalization
894
+
895
+ **Cross-host.** Normalized text/span output. Transport: In-process only. [Deep protocol details](protocols.md).
896
+
897
+ ### Example
898
+
899
+ ```javascript
900
+ import * as module from '/arcane/modules/AnsiText.js';
901
+
902
+ console.log(Object.keys(module));
903
+ ```
904
+
905
+ ## ApiModelDatabase.js
906
+
907
+ ### Overview
908
+
909
+ Fetches an injectable HTTP JSON model with parser, cache, redacted public endpoint records, and request lifecycle events.
910
+
911
+ ### Public surface
912
+
913
+ default `ApiModelDatabase`; `setEndpoint()`, `fetch()`, `cached()`; emits `api-model-request`, `api-model-success`, and `api-model-error`.
914
+
915
+ Exact exports: `API_MODEL_ERRORS`, `API_MODEL_EVENTS`, `appendParameters`,
916
+ `default`, `publicEndpoint`.
917
+
918
+ ### Availability and normalization
919
+
920
+ **Browser / native WebView / server with fetch.** Request records are normalized; fetch/provider failures remain mixed. Transport: HTTP(S) fetch. [Deep protocol details](protocols.md).
921
+
922
+ ### Example
923
+
924
+ ```javascript
925
+ import * as module from '/arcane/modules/ApiModelDatabase.js';
926
+
927
+ console.log(Object.keys(module));
928
+ ```
929
+
930
+ ## AppDataScope.js
931
+
932
+ ### Overview
933
+
934
+ Reconciles declared and native application identity and scopes OPFS/localStorage ownership fail-closed.
935
+
936
+ ### Public surface
937
+
938
+ Identity constants and `canonicalApplicationId()`, `resolveApplicationId()`, `resolveApplicationLocalStorageKey()`, `openApplicationDataDirectory()`.
939
+
940
+ Exact exports: `APPLICATION_ID_MAX_LENGTH`, `APPLICATION_ID_PATTERN`, `APP_DATA_DIRECTORY`, `APP_LOCAL_STORAGE_PREFIX`, `canonicalApplicationId`, `declaredApplicationId`, `openApplicationDataDirectory`, `resolveApplicationId`, `resolveApplicationLocalStorageKey`, `resolveBrowserApplicationId`.
941
+
942
+ ### Availability and normalization
943
+
944
+ **Browser / native WebView hybrid.** Strict normalized identifiers and coded mismatch failures. Transport: Arcane.app.current, DOM declaration, OPFS. [Deep protocol details](protocols.md).
945
+
946
+ ### Example
947
+
948
+ ```javascript
949
+ import * as module from '/arcane/modules/AppDataScope.js';
950
+
951
+ console.log(Object.keys(module));
952
+ ```
953
+
954
+ ## AppearancePreferences.js
955
+
956
+ ### Overview
957
+
958
+ Defines, stores, and applies color scheme, density, reduced motion, and large-text preferences.
959
+
960
+ ### Public surface
961
+
962
+ `appearancePreferenceSchema`, `createAppearancePreferenceStore()`, `applyAppearancePreferences()`, `loadAndApplyAppearancePreferences()`.
963
+
964
+ Exact exports: `appearancePreferenceSchema`, `applyAppearancePreferences`, `createAppearancePreferenceStore`, `loadAndApplyAppearancePreferences`.
965
+
966
+ ### Availability and normalization
967
+
968
+ **Browser / native WebView hybrid.** Normalized values; storage/host failures remain mixed. Transport: PreferenceStore, DOM, optional Arcane preferences. [Deep protocol details](protocols.md).
969
+
970
+ ### Example
971
+
972
+ ```javascript
973
+ import * as module from '/arcane/modules/AppearancePreferences.js';
974
+
975
+ console.log(Object.keys(module));
976
+ ```
977
+
978
+ ## ArcaneCommunicationBridge.js
979
+
980
+ ### Overview
981
+
982
+ Maps provider HTTP threads/messages/connect/disconnect endpoints to normalized communication entities.
983
+
984
+ ### Public surface
985
+
986
+ default `ArcaneCommunicationBridge`; `request()`, `listThreads()`, `getMessages()`, `send()`, `connect()`, `disconnect()`.
987
+
988
+ Exact exports: `default`.
989
+
990
+ ### Availability and normalization
991
+
992
+ **Browser / native WebView / server with fetch.** Entity results are normalized; provider/transport failures remain mixed. Transport: JSON HTTP(S), default loopback 127.0.0.1:8020. [Deep protocol details](protocols.md).
993
+
994
+ ### Example
995
+
996
+ ```javascript
997
+ import * as module from '/arcane/modules/ArcaneCommunicationBridge.js';
998
+
999
+ console.log(Object.keys(module));
1000
+ ```
1001
+
1002
+ ## ArcaneNavigationPolicy.js
1003
+
1004
+ ### Overview
1005
+
1006
+ Creates an HTTP(S) navigation guard whose optional domain and CIDR hardening runs only when the caller explicitly selects `secure: true`. The ordinary default returns a complete allow decision with a warning and does not load policy.
1007
+
1008
+ ### Public surface
1009
+
1010
+ `createArcaneNavigationGuard({ secure })`.
1011
+
1012
+ Exact exports: `createArcaneNavigationGuard`.
1013
+
1014
+ ### Availability and normalization
1015
+
1016
+ **Cross-host.** Complete mutable allow/block decision. Ordinary mode warns and
1017
+ continues; explicitly selected `secure: true` loads the Arcane network-policy
1018
+ document and fails closed when that selected policy cannot be evaluated. [Deep protocol details](protocols.md).
1019
+
1020
+ ### Example
1021
+
1022
+ ```javascript
1023
+ import {createArcaneNavigationGuard} from '/arcane/modules/ArcaneNavigationPolicy.js';
1024
+
1025
+ const guard=createArcaneNavigationGuard();
1026
+ console.log(await guard('https://example.com/docs',{intent:'external'}));
1027
+ ```
1028
+
1029
+ ## ArcaneNetworkPolicy.js
1030
+
1031
+ ### Overview
1032
+
1033
+ Validates the Arcane domain/network deny policy and matches domain, IPv4/IPv6 CIDR, protocol, and port rules.
1034
+
1035
+ ### Public surface
1036
+
1037
+ Policy constants plus validate/load/cache/match helpers.
1038
+
1039
+ Exact exports: `ARCANE_NETWORK_POLICY_SCHEMA_VERSION`, `ARCANE_NETWORK_POLICY_URL`, `canonicalNetworkHostname`, `emptyArcaneNetworkPolicy`, `findDeniedDomainRule`, `findDeniedNetworkRule`, `invalidateArcaneNetworkPolicyCache`, `loadArcaneNetworkPolicy`, `validateArcaneNetworkPolicy`.
1040
+
1041
+ ### Availability and normalization
1042
+
1043
+ **Cross-host.** Strict coded normalization. Transport: Same-origin policy fetch. [Deep protocol details](protocols.md).
1044
+
1045
+ ### Example
1046
+
1047
+ ```javascript
1048
+ import * as module from '/arcane/modules/ArcaneNetworkPolicy.js';
1049
+
1050
+ console.log(Object.keys(module));
1051
+ ```
1052
+
1053
+ ## AsyncBoundary.js
1054
+
1055
+ ### Overview
1056
+
1057
+ Runs one asynchronous operation with timeout, abort, result validation, and stable boundary errors.
1058
+
1059
+ ### Public surface
1060
+
1061
+ `AsyncBoundaryTimeoutError`, `AsyncBoundaryAbortError`, defaults, `runAsyncBoundary()`, and default alias.
1062
+
1063
+ Exact exports: `AsyncBoundaryAbortError`, `AsyncBoundaryTimeoutError`, `asyncBoundaryDefaults`, `default`, `runAsyncBoundary`.
1064
+
1065
+ ### Availability and normalization
1066
+
1067
+ **Cross-host.** Fully normalized timeout/abort errors. Transport: AbortController and timers. [Deep protocol details](protocols.md).
1068
+
1069
+ ### Example
1070
+
1071
+ ```javascript
1072
+ import * as module from '/arcane/modules/AsyncBoundary.js';
1073
+
1074
+ console.log(Object.keys(module));
1075
+ ```
1076
+
1077
+ ## BrowserTestSuite.js
1078
+
1079
+ ### Overview
1080
+
1081
+ Runs a complete sequential browser test list with explicit cancellation and full-detail lifecycle events.
1082
+
1083
+ ### Public surface
1084
+
1085
+ default `BrowserTestSuite`; `list()`, `run()`, `dispose()`/`destroy()`; emits
1086
+ complete suite/test start/result/complete events. Caller metadata does not limit
1087
+ execution or create a timer. Caller `AbortSignal` or disposal is the only
1088
+ suite-owned stop.
1089
+
1090
+ Exact exports: `BROWSER_TEST_SUITE_ERROR_CODES`,
1091
+ `BROWSER_TEST_SUITE_EVENT_TYPES`, `BROWSER_TEST_SUITE_REASONS`,
1092
+ `assertionError`, `default`, `skipError`.
1093
+
1094
+ ### Availability and normalization
1095
+
1096
+ **Browser / standard Web APIs.** Mutable full-detail results and events with
1097
+ normalized malformed-result and skip/assertion errors. Transport: EventTarget
1098
+ and explicit AbortSignal cancellation. [Deep protocol details](protocols.md).
1099
+
1100
+ ### Example
1101
+
1102
+ ```javascript
1103
+ import * as module from '/arcane/modules/BrowserTestSuite.js';
1104
+
1105
+ console.log(Object.keys(module));
1106
+ ```
1107
+
1108
+ ## CalculatorEngine.js
1109
+
1110
+ ### Overview
1111
+
1112
+ Evaluates complete arithmetic expressions, powers, constants, and common functions without `eval`.
1113
+
1114
+ ### Public surface
1115
+
1116
+ `new CalculatorEngine()` exposes synchronous
1117
+ `calculate(expression): Calculation` and idempotent
1118
+ `dispose(): boolean` / `destroy(): boolean`. `evaluateExpression(input): number`
1119
+ remains the parser-only helper. `CALCULATOR_ENGINE_ERROR_CODES` is one mutable
1120
+ record containing the stable `disposed`, `input`, `syntax`, `domain`, and
1121
+ `evaluation` codes.
1122
+
1123
+ Exact exports: `CALCULATOR_ENGINE_ERROR_CODES`, `default`,
1124
+ `evaluateExpression`.
1125
+
1126
+ ### Availability and normalization
1127
+
1128
+ **Cross-host.** Each engine owns one `calculator-engine` source on the realm's
1129
+ branded `globalThis.arcaneEvents`. `calculator-result` publishes mutable public
1130
+ detail `{result}`. `calculator-error` publishes mutable public detail
1131
+ `{code,error,expression}` while `calculate()` rethrows that same complete
1132
+ `Error`. Both occurrences carry one
1133
+ source-instance `operationId`. Canonical listener callbacks are synchronous
1134
+ observations; their failures are reported by the central event authority and do
1135
+ not rewrite calculation settlement. Disposal rejects later calculations with
1136
+ `ARCANE_CALCULATOR_ENGINE_DISPOSED`. Invalid expression input, syntax, numeric
1137
+ domain, and unexpected evaluation boundaries use
1138
+ `ARCANE_CALCULATOR_EXPRESSION_INPUT_INVALID`,
1139
+ `ARCANE_CALCULATOR_EXPRESSION_SYNTAX_INVALID`,
1140
+ `ARCANE_CALCULATOR_EXPRESSION_DOMAIN_INVALID`, and
1141
+ `ARCANE_CALCULATOR_EXPRESSION_EVALUATION_FAILED`. Transport: in-process only.
1142
+ [Deep protocol details](protocols.md).
1143
+
1144
+ ### Example
1145
+
1146
+ ```javascript
1147
+ import * as module from '/arcane/modules/CalculatorEngine.js';
1148
+
1149
+ console.log(Object.keys(module));
1150
+ ```
1151
+
1152
+ ## ChartLibrary.js
1153
+
1154
+ ### Overview
1155
+
1156
+ Loads the bundled uPlot classic script once and returns its global constructor.
1157
+
1158
+ ### Public surface
1159
+
1160
+ default `loadChartLibrary()`.
1161
+
1162
+ Exact exports: `default`.
1163
+
1164
+ ### Availability and normalization
1165
+
1166
+ **Browser / native WebView.** Load state/errors normalized; uPlot result is vendor-native. Transport: DOM script injection. [Deep protocol details](protocols.md).
1167
+
1168
+ ### Example
1169
+
1170
+ ```javascript
1171
+ import * as module from '/arcane/modules/ChartLibrary.js';
1172
+
1173
+ console.log(Object.keys(module));
1174
+ ```
1175
+
1176
+ ## ChatRecords.js
1177
+
1178
+ ### Overview
1179
+
1180
+ Detects whether a chat record contains a user entry or durable conversation
1181
+ entry, and projects retained chat state into recurring provider context. That
1182
+ projection preserves an unresolved structural-call tail for its one active
1183
+ continuation, then replaces the settled protocol with complete ordinary visible
1184
+ messages.
1185
+
1186
+ ### Public surface
1187
+
1188
+ `hasUserEntry()`, `hasConversationEntry()`, and
1189
+ `recurringChatMessages(chat,{settleCompleteToolTail=false}={})`. The optional
1190
+ settlement flag is for restoring a configured session that has no active
1191
+ provider continuation; unresolved calls remain raw regardless.
1192
+
1193
+ Exact exports: `hasConversationEntry`, `hasUserEntry`,
1194
+ `recurringChatMessages`.
1195
+
1196
+ ### Availability and normalization
1197
+
1198
+ **Cross-host.** Boolean conversation-entry results and recurring provider
1199
+ context are normalized. Transport: In-process only. [Deep protocol details](protocols.md).
1200
+
1201
+ ### Example
1202
+
1203
+ ```javascript
1204
+ import * as module from '/arcane/modules/ChatRecords.js';
1205
+
1206
+ console.log(Object.keys(module));
1207
+ ```
1208
+
1209
+ ## CommunicationAppController.js
1210
+
1211
+ ### Overview
1212
+
1213
+ Binds shared inbox, conversation, settings, theme, and provider workflows into one UI controller.
1214
+
1215
+ ### Public surface
1216
+
1217
+ default controller with `start()`, `bind()`, `configure()`, `refresh()`, `select()`, `send()`, and settings actions.
1218
+
1219
+ Exact exports: `COMMUNICATION_APP_CONTROLLER_ERROR_CODES`, `default`.
1220
+
1221
+ ### Availability and normalization
1222
+
1223
+ **Browser / native WebView hybrid.** Controller state normalized; provider/DOM failures mixed. Transport: DOM plus communication providers. [Deep protocol details](protocols.md).
1224
+
1225
+ ### Example
1226
+
1227
+ ```javascript
1228
+ import * as module from '/arcane/modules/CommunicationAppController.js';
1229
+
1230
+ console.log(Object.keys(module));
1231
+ ```
1232
+
1233
+ ## CommunicationHub.js
1234
+
1235
+ ### Overview
1236
+
1237
+ Fans out provider refresh/send operations and aggregates normalized threads/messages.
1238
+
1239
+ ### Public surface
1240
+
1241
+ default `CommunicationHub`; provider enablement, `refresh()`, `messages()`, and `send()`.
1242
+
1243
+ Exact exports: `COMMUNICATION_HUB_ERROR_CODES`, `COMMUNICATION_HUB_EVENTS`,
1244
+ `COMMUNICATION_HUB_REFRESH_REASONS`, `COMMUNICATION_HUB_REFRESH_STATES`, and
1245
+ `default`.
1246
+
1247
+ ### Availability and normalization
1248
+
1249
+ **Cross-host with injected providers.** Normalized aggregates; refresh contains per-provider failures. Transport: Injected provider contract. [Deep protocol details](protocols.md).
1250
+
1251
+ ### Example
1252
+
1253
+ ```javascript
1254
+ import * as module from '/arcane/modules/CommunicationHub.js';
1255
+
1256
+ console.log(Object.keys(module));
1257
+ ```
1258
+
1259
+ ## CommunicationPreferences.js
1260
+
1261
+ ### Overview
1262
+
1263
+ Stores app-scoped, non-secret communication provider preferences.
1264
+
1265
+ ### Public surface
1266
+
1267
+ default `CommunicationPreferences`; `load()`, `save()`.
1268
+
1269
+ Exact exports: `default`.
1270
+
1271
+ ### Availability and normalization
1272
+
1273
+ **Browser / native WebView hybrid.** Normalized preference record; storage failures mixed. Transport: Arcane.preferences or localStorage. [Deep protocol details](protocols.md).
1274
+
1275
+ ### Example
1276
+
1277
+ ```javascript
1278
+ import * as module from '/arcane/modules/CommunicationPreferences.js';
1279
+
1280
+ console.log(Object.keys(module));
1281
+ ```
1282
+
1283
+ ## CommunicationProviderRegistry.js
1284
+
1285
+ ### Overview
1286
+
1287
+ Registers and queries validated provider definitions, channels, and required methods.
1288
+
1289
+ ### Public surface
1290
+
1291
+ default registry with `register()`, `get()`, `has()`, `list()`.
1292
+
1293
+ Exact exports: `default`.
1294
+
1295
+ ### Availability and normalization
1296
+
1297
+ **Cross-host.** Strict normalized registry. Transport: In-process only. [Deep protocol details](protocols.md).
1298
+
1299
+ ### Example
1300
+
1301
+ ```javascript
1302
+ import * as module from '/arcane/modules/CommunicationProviderRegistry.js';
1303
+
1304
+ console.log(Object.keys(module));
1305
+ ```
1306
+
1307
+ ## ComponentContracts.js
1308
+
1309
+ ### Overview
1310
+
1311
+ Owns normalized configuration/value contracts and shared explicit STT activation
1312
+ behavior for chart, dashboard, Markdown, and voice components.
1313
+
1314
+ ### Public surface
1315
+
1316
+ Constant sets plus normalization, formatting, and explicit STT activation
1317
+ helpers. `createSTTActivationController({host,button,onChange,EventClass=CustomEvent})`
1318
+ consumes only normalized
1319
+ [`AIRuntimeState`](#airuntimestatejs) `stt` role records. Its mutable controller
1320
+ exposes `action`, `error`, `label`, `pending`, `selected`, `status`, `title`, and
1321
+ `visible` getters plus `request(action)`, `synchronize(role)`, and `destroy()`.
1322
+ `host` supplies `dispatchEvent(event)` and `requestSTTActivation(intent)`;
1323
+ `button` supplies `addEventListener()` and `removeEventListener()`; and
1324
+ `onChange()` is called whenever presentation should be rendered again. Browser
1325
+ callers use the default `CustomEvent`; non-DOM callers must inject a compatible
1326
+ `EventClass` constructor.
1327
+
1328
+ `request('load'|'unload')` emits the cancelable
1329
+ `speech-stt-activation-request` event with mutable `{intent,state}` before it
1330
+ invokes `host.requestSTTActivation(intent)`. Callback failure emits
1331
+ `speech-stt-activation-error` with mutable `{request,error,message}`. Syncing
1332
+ sticky state only changes the controller's observation and presentation; it
1333
+ never emits a lifecycle intent, chooses a provider, or starts a download.
1334
+ `destroy()` removes its button listener and suppresses late callback effects.
1335
+
1336
+ Exact exports: `CHART_LABELS`, `DASHBOARD_LABELS`, `MARKDOWN_FORMATS`,
1337
+ `MARKDOWN_LABELS`, `STT_ACTIVATION_ERROR_CODES`,
1338
+ `STT_ACTIVATION_EVENT_TYPES`, `STT_ACTIVATION_REASONS`, `VOICE_LABELS`,
1339
+ `VOICE_MESSAGES`, `appendTranscription`, `applyMarkdownFormat`,
1340
+ `createSTTActivationController`, `effectiveDashboardVisibility`,
1341
+ `formatAIRuntimeProgress`,
1342
+ `normalizeChartOptions`, `normalizeChartRows`, `normalizeDashboardDefinitions`,
1343
+ `normalizeDashboardOptions`, `normalizeDashboardVisibility`,
1344
+ `normalizeMarkdownFormats`, `normalizeMarkdownOptions`, and
1345
+ `normalizeVoiceOptions`.
1346
+
1347
+ ### Availability and normalization
1348
+
1349
+ **Cross-host with an injected event constructor outside DOM hosts.** Fully
1350
+ normalized labels, rows, definitions, visibility, formats, editor and voice
1351
+ options, capability-neutral STT activation intent and presentation state, and
1352
+ complete informational provider progress whenever a finite measure is present.
1353
+ Fractional and over-total measures remain visible rather than being replaced by
1354
+ their phase label.
1355
+ Provider authority and lifecycle execution remain with the configured runtime
1356
+ owner. Transport: In-process only. [Deep protocol details](protocols.md).
1357
+
1358
+ ### Example
1359
+
1360
+ ```javascript
1361
+ import * as module from '/arcane/modules/ComponentContracts.js';
1362
+
1363
+ console.log(Object.keys(module));
1364
+ ```
1365
+
1366
+ ## ConfiguredAIChatSession.js
1367
+
1368
+ ### Overview
1369
+
1370
+ Owns complete ordinary visible recurring AI turns, one active structural
1371
+ continuation, context construction, provider-response preservation, and atomic
1372
+ history commit.
1373
+
1374
+ ### Public surface
1375
+
1376
+ Default `ConfiguredAIChatSession`; named
1377
+ `normalizeStructuralToolCall(call,label)`; instance methods `history()`,
1378
+ `clear()`, `prepareOpening()`, `prepare()`, and `send()`.
1379
+
1380
+ `new ConfiguredAIChatSession(options={})` uses `chat`, `contextBuilder`,
1381
+ `initialMessages`, `request`, `responseLength`, and `systemPrompt`.
1382
+ `responseLength` is caller preference metadata and does not alter or limit content.
1383
+ `initialMessages` is an array of complete `user`, `assistant`, or `tool`
1384
+ messages. It excludes `system`, accepts one unresolved structural assistant
1385
+ tool-call tail, and requires its tracked result before another user turn or
1386
+ tool-call sequence; `systemPrompt` owns the separate system message. Settled
1387
+ structural protocol is projected immediately into ordinary visible recurring
1388
+ messages.
1389
+
1390
+ Each assistant structural tool call is one complete function call with an exact
1391
+ nonempty string `id`, `type:'function'`, a nonempty `function.name`, and
1392
+ `function.arguments` as a JSON string encoding an object containing a nonempty
1393
+ user-facing `message`. One assistant message may contain an ordered array of
1394
+ calls with unique IDs; every call and every extension field is preserved in the
1395
+ returned response and its active matching continuation, but not settled
1396
+ recurring history.
1397
+ Validation does not trim or reserialize an accepted ID, name, or argument
1398
+ string. A pending call set is settled atomically only by one request batch that
1399
+ contains exactly one `role:'tool'` message with nonempty content for every
1400
+ pending ID. A user turn, duplicate or mismatched result, partial result batch,
1401
+ or overlapping structural call is rejected until the complete set settles.
1402
+
1403
+ `prepare(input,{request,signal})` performs the complete request but does not
1404
+ commit history immediately. It returns mutable `{response,commit,rollback}`;
1405
+ exactly one terminal settlement is permitted. Plain-object per-turn `request`
1406
+ options merge over constructor defaults, while session-owned `messages` and
1407
+ `signal` are applied last. `messages`, `signal`, `stream`, `onChunk`,
1408
+ `onToolCall`, and `onResponse` cannot be supplied through either request layer.
1409
+ A matching tool result may include a complete public `message`, `name`, and
1410
+ `status`; those fields are excluded from the raw provider continuation. The
1411
+ public `message` becomes ordinary visible recurring content after settlement,
1412
+ while `name` and `status` remain optional durable transcript metadata. Raw
1413
+ call/result protocol is retained only until that one continuation commits.
1414
+ `send()` is the convenience path that prepares and then commits the turn.
1415
+
1416
+ `prepareOpening(input,{request,signal})` is the dedicated transaction for an
1417
+ automatic model-authored opening. It sends one application-authored user
1418
+ bootstrap only when retained history contains no conversation turn, requires a
1419
+ complete nonblank assistant response without structural calls, and prepares
1420
+ only that assistant content for commit. The bootstrap never enters history.
1421
+ An existing retained turn rejects as `AI_CHAT_OPENING_EXISTS`; an empty or
1422
+ structural response rejects as `AI_CHAT_INVALID_OPENING_RESPONSE`.
1423
+
1424
+ An optional async `contextBuilder({input,history,signal})` receives a mutable,
1425
+ complete request snapshot and the same cancellation signal. Its complete
1426
+ returned context applies only to the current request and is never committed to
1427
+ history.
1428
+
1429
+ An injected `chat(request)` may return the prior normalized session result or a
1430
+ non-stream OpenAI-compatible response whose first choice supplies the assistant
1431
+ message. The prior form preserves its explicit `done` boolean;
1432
+ OpenAI-compatible choice normalization sets `done:true`. Both return mutable
1433
+ `{provider,model,message:{role:'assistant',content,tool_calls?},providerResponse,
1434
+ done,doneReason,promptEvalCount,evalCount}` and preserve the complete provider
1435
+ response in `providerResponse`. Tool calls remain structural data and are never
1436
+ executed. General malformed responses fail `AI_CHAT_INVALID_RESPONSE`;
1437
+ malformed structural envelopes or argument JSON fail
1438
+ `AI_CHAT_INVALID_TOOL_CALL`, and a missing or blank argument `message` fails
1439
+ `AI_CHAT_TOOL_MESSAGE_REQUIRED`. Caller cancellation is `AbortError` with code
1440
+ `AI_CHAT_ABORTED`. A new user
1441
+ turn cannot bypass a pending structural tool call
1442
+ (`AI_CHAT_TOOL_RESULT_REQUIRED`), a mismatched tool result fails
1443
+ `AI_CHAT_INVALID_TOOL_MESSAGE`, and a second terminal settlement of one
1444
+ prepared transaction fails `AI_CHAT_TRANSACTION_SETTLED`. Incoherent initial or
1445
+ persisted sequencing fails `AI_CHAT_INCOHERENT_PERSISTENCE`.
1446
+
1447
+ Exact exports: `normalizeStructuralToolCall`, `default`.
1448
+
1449
+ ### Availability and normalization
1450
+
1451
+ **Native bridge by default; cross-host with injected chat.** Normalized session/result; provider rejection preserved. Transport: Arcane.ai.chat or injected provider. [Deep protocol details](protocols.md).
1452
+
1453
+ ### Example
1454
+
1455
+ ```javascript
1456
+ import ConfiguredAIChatSession from '/arcane/modules/ConfiguredAIChatSession.js';
1457
+
1458
+ const session = new ConfiguredAIChatSession({
1459
+ chat: async request => ({
1460
+ provider: 'demo',
1461
+ model: 'echo',
1462
+ message: {
1463
+ role: 'assistant',
1464
+ content: `Received ${request.messages.length} messages.`
1465
+ }
1466
+ })
1467
+ });
1468
+ console.log(await session.send('Hello'));
1469
+ ```
1470
+
1471
+ ## ConversationActionItems.js
1472
+
1473
+ ### Overview
1474
+
1475
+ Normalizes, creates, updates, remembers, selects, and formats complete conversation action items.
1476
+
1477
+ ### Public surface
1478
+
1479
+ Action-item constants and lifecycle/formatting helpers.
1480
+
1481
+ Exact exports: `CONVERSATION_ACTION_ITEM_BASES`, `CONVERSATION_ACTION_ITEM_PRESENTATION_COOLDOWN_MS`, `CONVERSATION_ACTION_ITEM_STATUSES`, `conversationActionItemsInstruction`, `createConversationActionItem`, `formatConversationActionItemCheckIn`, `markConversationActionItemsPresented`, `normalizeConversationActionItem`, `normalizeConversationActionItems`, `normalizeRememberedConversationActions`, `outstandingConversationActionItems`, `rememberConversationActionItems`, `removeConversationActionItem`, `selectConversationActionItemsForPresentation`, `updateConversationActionItem`.
1482
+
1483
+ ### Availability and normalization
1484
+
1485
+ **Cross-host.** Fully normalized status/base/presentation contract. Transport: In-process only. [Deep protocol details](protocols.md).
1486
+
1487
+ ### Example
1488
+
1489
+ ```javascript
1490
+ import * as module from '/arcane/modules/ConversationActionItems.js';
1491
+
1492
+ console.log(Object.keys(module));
1493
+ ```
1494
+
1495
+ ## ConversationClosingReport.js
1496
+
1497
+ ### Overview
1498
+
1499
+ Defines the closing-report tool, instruction, result normalizer, call classifier, and formatter.
1500
+
1501
+ ### Public surface
1502
+
1503
+ Six constants/helpers for closing reports.
1504
+
1505
+ The generated sole-call schema requires both `message` and `final_message`.
1506
+ `message` is brief user-facing progress shown while the application accepts and
1507
+ renders the call. `final_message` remains the complete terminal closeout and is
1508
+ never replaced by or duplicated into `message`; `remembered_actions` remains
1509
+ optional. `normalizeConversationClosingReport()` returns
1510
+ `{message,finalMessage,rememberedActions}`, while
1511
+ `formatConversationClosingReport()` escapes and renders only `finalMessage`.
1512
+
1513
+ Exact exports: `CONVERSATION_CLOSING_REPORT_TOOL_NAME`, `classifyConversationClosingReportCalls`, `conversationClosingReportInstruction`, `createConversationClosingReportTool`, `formatConversationClosingReport`, `normalizeConversationClosingReport`.
1514
+
1515
+ ### Availability and normalization
1516
+
1517
+ **Cross-host.** Fully normalized report contract. Transport: In-process only. [Deep protocol details](protocols.md).
1518
+
1519
+ ### Example
1520
+
1521
+ ```javascript
1522
+ import * as module from '/arcane/modules/ConversationClosingReport.js';
1523
+
1524
+ console.log(Object.keys(module));
1525
+ ```
1526
+
1527
+ ## ConversationTimebox.js
1528
+
1529
+ ### Overview
1530
+
1531
+ Owns conversation limits, control messages, submission barriers, elapsed formatting, and delivery proof.
1532
+
1533
+ ### Public surface
1534
+
1535
+ default `ConversationTimebox`, `ConversationSubmissionBarrier`, constants and control helpers.
1536
+
1537
+ Exact exports: `CONVERSATION_TIMEBOX_ERROR_CODES`,
1538
+ `CONVERSATION_TIMEBOX_EVENT_TYPES`, `CONVERSATION_TIMEBOX_LIMIT_MESSAGE`,
1539
+ `CONVERSATION_TIMEBOX_OPENING_INSTRUCTION`, `CONVERSATION_TIMEBOX_REASONS`,
1540
+ `CONVERSATION_TIMEBOX_TOOL_NAME`, `ConversationSubmissionBarrier`,
1541
+ `appendConversationTimeboxOpeningInstruction`, `consumeConversationTimeboxCall`,
1542
+ `conversationTimeboxSubmissionKey`, `conversationTimeboxTool`,
1543
+ `createConversationTimeboxControlMessage`, `default`,
1544
+ `formatConversationElapsed`, `normalizeConversationTimeboxCommand`, and
1545
+ `requireConversationTimeboxDelivery`.
1546
+
1547
+ `conversationTimeboxTool` is a sole-call function schema with
1548
+ `additionalProperties:false`. Every call requires `action` and a nonempty
1549
+ user-facing `message`; `set` and `adjust` also require an explicit positive
1550
+ `duration_milliseconds`, while `clear` ignores duration.
1551
+ `normalizeConversationTimeboxCommand()` preserves the exact message, and
1552
+ `ConversationTimebox.applyCommand()` returns the resulting state snapshot plus
1553
+ that message after applying the command. `consumeConversationTimeboxCall()`
1554
+ retains this producer result inside its fulfilled result record.
1555
+
1556
+ ### Availability and normalization
1557
+
1558
+ **Cross-host.** Fully normalized state/command/delivery errors. Transport: Clock/timers and callbacks. [Deep protocol details](protocols.md).
1559
+
1560
+ ### Example
1561
+
1562
+ ```javascript
1563
+ import * as module from '/arcane/modules/ConversationTimebox.js';
1564
+
1565
+ console.log(Object.keys(module));
1566
+ ```
1567
+
1568
+ ## CoreLocalModelCatalog.js
1569
+
1570
+ ### Overview
1571
+
1572
+ Projects Core local-AI status into UI-safe admitted model and speech availability catalogs.
1573
+
1574
+ ### Public surface
1575
+
1576
+ Provider-mode constant and four catalog/availability helpers.
1577
+
1578
+ Exact exports: `USER_MANAGED_LOOPBACK_PROVIDER_MODE`, `getCoreLocalModelCatalog`, `getCoreLocalModelCatalogWithAdmissionFailures`, `getCoreLocalSpeechAvailability`, `isUserManagedLoopbackLocalAIStatus`.
1579
+
1580
+ ### Availability and normalization
1581
+
1582
+ **Cross-host.** Fully normalized descriptors and stable availability labels. Transport: In-process projection of Core status. [Deep protocol details](protocols.md).
1583
+
1584
+ ### Example
1585
+
1586
+ ```javascript
1587
+ import * as module from '/arcane/modules/CoreLocalModelCatalog.js';
1588
+
1589
+ console.log(Object.keys(module));
1590
+ ```
1591
+
1592
+ ## DataMaintenance.js
1593
+
1594
+ ### Overview
1595
+
1596
+ Deletes empty chats and associated/empty memory records inside the current app data scope.
1597
+
1598
+ ### Public surface
1599
+
1600
+ `clearEmptyChatsAndMemories()` plus content predicates.
1601
+
1602
+ Exact exports: `clearEmptyChatsAndMemories`, `hasConversationEntry`,
1603
+ `hasMemoryContent`, `hasUserEntry`.
1604
+
1605
+ ### Availability and normalization
1606
+
1607
+ **Browser / native WebView.** Normalized counts; destructive storage failures preserved. Transport: Global DBOPFS. [Deep protocol details](protocols.md).
1608
+
1609
+ ### Example
1610
+
1611
+ ```javascript
1612
+ import * as module from '/arcane/modules/DataMaintenance.js';
1613
+
1614
+ console.log(Object.keys(module));
1615
+ ```
1616
+
1617
+ ## DBLS.js
1618
+
1619
+ ### Overview
1620
+
1621
+ Provides app-scoped localStorage tables, batch reads/writes, filtering, deletion, and counts.
1622
+
1623
+ ### Public surface
1624
+
1625
+ default `DBLS`; installs `window.dbls`, emits `dbls-ready`; CRUD/batch/key APIs.
1626
+
1627
+ Exact exports: `DBLS_EVENT_TYPES`, `DBLS_REASONS`, `default`.
1628
+
1629
+ ### Availability and normalization
1630
+
1631
+ **Browser / native WebView.** Scoped keys and values normalized; storage failures mixed. Transport: localStorage + AppDataScope. [Deep protocol details](protocols.md).
1632
+
1633
+ ### Example
1634
+
1635
+ ```javascript
1636
+ import * as module from '/arcane/modules/DBLS.js';
1637
+
1638
+ console.log(Object.keys(module));
1639
+ ```
1640
+
1641
+ ## DBOPFS.js
1642
+
1643
+ ### Overview
1644
+
1645
+ Provides app-scoped OPFS tables, worker I/O, backup/restore, compression, and CRUD/batch APIs.
1646
+
1647
+ ### Public surface
1648
+
1649
+ default `DBOPFS`; installs `window.dbopfs`, emits `dbopfs-ready`; table/file/backup APIs.
1650
+
1651
+ Exact exports: `DBOPFS_EVENT_TYPES`, `DBOPFS_REASONS`, `default`.
1652
+
1653
+ ### Availability and normalization
1654
+
1655
+ **Browser / native WebView.** App scope and recognized JSON/JSONL file parsing
1656
+ are normalized. Each readable JSONL row becomes its parsed value; a nonblank
1657
+ unreadable row remains in its original string form so the owning application
1658
+ can display, diagnose, or recover it without silent data loss. DOM and storage
1659
+ errors remain observable. Transport: OPFS, DBOPFSWorker, Compression Streams.
1660
+ [Deep protocol details](protocols.md).
1661
+
1662
+ ### Example
1663
+
1664
+ ```javascript
1665
+ import * as module from '/arcane/modules/DBOPFS.js';
1666
+
1667
+ console.log(Object.keys(module));
1668
+ ```
1669
+
1670
+ ## DBOPFSDocumentLibrary.js
1671
+
1672
+ ### Overview
1673
+
1674
+ Stores one application-defined document corpus through an existing DBOPFS-style
1675
+ adapter, searches only a completed generation, and builds complete context.
1676
+ Construction performs no read, write, fetch, or search; applications call
1677
+ `bootstrap()` deliberately.
1678
+
1679
+ ### Public surface
1680
+
1681
+ Exact exports: `DBOPFSDocumentLibrary`, `createDBOPFSDocumentLibrary`,
1682
+ `default`, and `normalizeDBOPFSDocumentSchema`.
1683
+
1684
+ `new DBOPFSDocumentLibrary({concurrency,db,schema})` exposes `schema`,
1685
+ `bootstrap({files,onProgress,read,readFailurePolicy,signal})`,
1686
+ `search(query,{kinds,signal,tags})`,
1687
+ `evaluate(query,{sources,read,kinds?,tags?,readFailurePolicy?,onProgress?,signal?})`,
1688
+ `buildContext(query,{signal})`, and `createContextBuilder()`.
1689
+
1690
+ `evaluate()` requires `sources`
1691
+ and `read`, filters source metadata before calling
1692
+ `read(source,{ordinal,signal})`, and never persists a caller-owned body.
1693
+
1694
+ ### Availability and normalization
1695
+
1696
+ **Browser or compatible host with an injected DBOPFS adapter.** The adapter
1697
+ keeps the existing `get`, `set`, `getAllKeys`, and `delete` method names; Node
1698
+ can use the same class only through an explicitly imported runtime module and a
1699
+ compatible storage adapter; SDK `0.5.12` publishes no Node package subpath or
1700
+ Node storage implementation for it. Bootstrap uses a concurrent
1701
+ generation, commits its manifest last, cleans partial data on failure, and
1702
+ rejects case-colliding IDs. Search
1703
+ returns `{failures,matches,total}` so one malformed record remains visible
1704
+ without hiding readable results. `bootstrap()` and `evaluate()` default to
1705
+ `readFailurePolicy:'preserve-readable'`; explicit `reject` stops on a read
1706
+ failure. Preserve-readable mode returns the readable records plus the complete
1707
+ failure and coverage details (`readCoverage` for bootstrap, `coverage` for
1708
+ evaluation). Evaluation reads a caller-owned source list without persisting its
1709
+ bodies and returns complete documents and text.
1710
+ Read failure remains `DBOPFS_DOCUMENT_READ_FAILED`; invalid public input uses
1711
+ `DBOPFS_DOCUMENT_INVALID`, invalid concurrency uses
1712
+ `DBOPFS_DOCUMENT_INVALID_LIMIT`, and a preserved read failure without a usable
1713
+ source code is reported as `failures[].code:'DBOPFS_DOCUMENT_ERROR'`.
1714
+ Cancellation is `AbortError` with code `DBOPFS_DOCUMENT_ABORTED`. Construction
1715
+ does not search.
1716
+ When an application explicitly supplies the library's context builder, each
1717
+ prepared chat send performs that complete retrieval.
1718
+
1719
+ ### Example
1720
+
1721
+ ```javascript
1722
+ import {
1723
+ createDBOPFSDocumentLibrary
1724
+ } from '/arcane/modules/DBOPFSDocumentLibrary.js';
1725
+
1726
+ const documents = createDBOPFSDocumentLibrary({
1727
+ db: globalThis.dbopfs,
1728
+ schema: {id: 'help', version: '1', table: 'help_documents'}
1729
+ });
1730
+ async function replaceHelpCorpusAfterUserChoice() {
1731
+ await documents.bootstrap({files: [{
1732
+ id: 'welcome',
1733
+ path: 'welcome.md',
1734
+ title: 'Welcome',
1735
+ body: 'Arcane applications are portable.'
1736
+ }]});
1737
+ console.log(await documents.search('portable'));
1738
+
1739
+ const preview = await documents.evaluate('portable', {
1740
+ sources: [{id:'draft', path:'draft.md', title:'Draft'}],
1741
+ read: async source => source.id === 'draft' ? 'Portable app notes.' : ''
1742
+ });
1743
+ console.log(preview.coverage, preview.text);
1744
+ }
1745
+ ```
1746
+
1747
+ ## DBOPFSWorker.js
1748
+
1749
+ ### Overview
1750
+
1751
+ Serializes OPFS sync-handle read/write requests from a MessagePort.
1752
+
1753
+ ### Public surface
1754
+
1755
+ No ESM exports; accepts `read` and `write` port requests.
1756
+
1757
+ This is a dedicated worker protocol and has no ESM exports.
1758
+
1759
+ ### Availability and normalization
1760
+
1761
+ **Dedicated worker.** Responses normalize to `{success,fileData?}` or `{error:{name,message}}`. Transport: MessageChannel + OPFS sync access handle. [Deep protocol details](protocols.md).
1762
+
1763
+ ### Example
1764
+
1765
+ ```javascript
1766
+ const worker = new Worker('/arcane/modules/DBOPFSWorker.js', {type: 'module'});
1767
+ ```
1768
+
1769
+ ## DevelopmentWorkspace.js
1770
+
1771
+ ### Overview
1772
+
1773
+ Provides complete workspace inspection, context, setup task, and Node installer clients without arbitrary command execution.
1774
+
1775
+ ### Public surface
1776
+
1777
+ default `DevelopmentWorkspace` and input validators; `inspect()`, `context()`, `setup()`, `installNode()`.
1778
+
1779
+ Exact exports: `contextQuery`, `default`, `setupTaskId`, `workspaceRoot`.
1780
+
1781
+ ### Availability and normalization
1782
+
1783
+ **Native bridge.** Complete plain-text roots, queries, and application-owned task identifiers reach the provider without application length or task allowlist gates; provider result/error content is preserved. Transport: Arcane.development. [Deep protocol details](protocols.md).
1784
+
1785
+ ### Example
1786
+
1787
+ ```javascript
1788
+ import * as module from '/arcane/modules/DevelopmentWorkspace.js';
1789
+
1790
+ console.log(Object.keys(module));
1791
+ ```
1792
+
1793
+ ## DirectoryPicker.js
1794
+
1795
+ ### Overview
1796
+
1797
+ Wraps the provider-owned native directory chooser and normalizes selected/cancelled/error results.
1798
+
1799
+ ### Public surface
1800
+
1801
+ default `DirectoryPicker`, `normalizeDirectoryPickerOptions()`, `normalizeDirectorySelection()`.
1802
+
1803
+ Exact exports: `default`, `normalizeDirectoryPickerOptions`, `normalizeDirectorySelection`.
1804
+
1805
+ ### Availability and normalization
1806
+
1807
+ **Native bridge.** Every caller option and provider result field is preserved.
1808
+ `title`, `initialPath`, and a selected `path` remain complete strings without
1809
+ trimming or application character gates, and returned records remain mutable.
1810
+ The provider or operating system owns any platform-specific path failure.
1811
+ Cancellation and malformed provider results retain coded errors. Transport:
1812
+ Arcane.filesystem.selectDirectory. [Deep protocol details](protocols.md).
1813
+
1814
+ ### Example
1815
+
1816
+ ```javascript
1817
+ import * as module from '/arcane/modules/DirectoryPicker.js';
1818
+
1819
+ console.log(Object.keys(module));
1820
+ ```
1821
+
1822
+ ## DocumentLexicalSearch.js
1823
+
1824
+ ### Overview
1825
+
1826
+ Provides deterministic, dependency-free metadata/body ranking and complete
1827
+ context excerpts for caller-owned document records.
1828
+
1829
+ ### Public surface
1830
+
1831
+ Exact exports: `DOCUMENT_SEARCH_FIELD_ORDER`, `DocumentLexicalSearch`,
1832
+ `createDocumentLexicalIndex`, `default`, `documentContextExcerpt`,
1833
+ `documentSearchTokens`, `normalizedDocumentSearchText`, `scoreDocumentBody`,
1834
+ and `scoreDocumentLexicalIndex`.
1835
+
1836
+ `new DocumentLexicalSearch(records)` exposes
1837
+ `rank(query,{kinds,tags})` and `search(query,{kinds,tags})`.
1838
+
1839
+ ### Availability and normalization
1840
+
1841
+ **Cross-host.** Indexing and search are in-process only. Text, tags, kinds,
1842
+ scores, field ordering, complete excerpts, and tie-breaking are normalized into
1843
+ mutable records. This module performs no storage, network, model, Core, or DOM
1844
+ action. The caller decides how a result is used.
1845
+
1846
+ ### Example
1847
+
1848
+ ```javascript
1849
+ import DocumentLexicalSearch from '/arcane/modules/DocumentLexicalSearch.js';
1850
+
1851
+ const search = new DocumentLexicalSearch([{
1852
+ id: 'welcome',
1853
+ path: 'welcome.md',
1854
+ title: 'Welcome',
1855
+ body: 'Arcane applications are portable.',
1856
+ kind: 'guide',
1857
+ tags: ['intro']
1858
+ }]);
1859
+ console.log(search.search('portable', {limit: 5}));
1860
+ ```
1861
+
1862
+ ## DocumentNavigation.js
1863
+
1864
+ ### Overview
1865
+
1866
+ Binds document navigation, filtering, history, current-item reveal, and load initialization.
1867
+
1868
+ ### Public surface
1869
+
1870
+ Five binding/filter/reveal helpers.
1871
+
1872
+ Exact exports: `applyDocumentNavigationFilter`, `bindDocumentNavigation`, `clearDocumentNavigationFilter`, `initializeDocumentNavigation`, `revealCurrentDocumentNavigationItem`.
1873
+
1874
+ ### Availability and normalization
1875
+
1876
+ **Browser / native WebView.** Normalized filter/navigation state; DOM effects preserved. Transport: DOM and history. [Deep protocol details](protocols.md).
1877
+
1878
+ ### Example
1879
+
1880
+ ```javascript
1881
+ import * as module from '/arcane/modules/DocumentNavigation.js';
1882
+
1883
+ console.log(Object.keys(module));
1884
+ ```
1885
+
1886
+ ## Errors.js
1887
+
1888
+ ### Overview
1889
+
1890
+ Normalizes global errors/rejections, assigns occurrence identifiers, persists a complete ledger, and performs complete delivery.
1891
+
1892
+ ### Public surface
1893
+
1894
+ default `Errors`; event normalizers plus lifecycle, capture, delivery and teardown methods.
1895
+
1896
+ Exact exports: `GLOBAL_ERROR_EVENT_CODES`, `GLOBAL_ERROR_EVENT_TYPES`,
1897
+ `GLOBAL_ERROR_REASONS`, `default`, `normalizeErrorEvent`, and
1898
+ `normalizeRejectionEvent`.
1899
+
1900
+ ### Availability and normalization
1901
+
1902
+ **Browser / native WebView hybrid.** Incident records normalized; storage/mail failures isolated. Transport: Window events, DBOPFS, Mail. [Deep protocol details](protocols.md).
1903
+
1904
+ ### Example
1905
+
1906
+ ```javascript
1907
+ import * as module from '/arcane/modules/Errors.js';
1908
+
1909
+ console.log(Object.keys(module));
1910
+ ```
1911
+
1912
+ ## GifEncoder.js
1913
+
1914
+ ### Overview
1915
+
1916
+ Encodes indexed frames into a complete animated GIF using palette mapping and LZW.
1917
+
1918
+ ### Public surface
1919
+
1920
+ default `GifEncoder`, `indexPixels()`, `lzw()`.
1921
+
1922
+ Exact exports: `default`, `indexPixels`, `lzw`.
1923
+
1924
+ ### Availability and normalization
1925
+
1926
+ **Cross-host.** Normalized complete binary output. Transport: In-process only. [Deep protocol details](protocols.md).
1927
+
1928
+ ### Example
1929
+
1930
+ ```javascript
1931
+ import * as module from '/arcane/modules/GifEncoder.js';
1932
+
1933
+ console.log(Object.keys(module));
1934
+ ```
1935
+
1936
+ ## HTMLImport.js
1937
+
1938
+ ### Overview
1939
+
1940
+ Defines the same-origin `<html-import>` loader with open shadow root, inline script execution, and readiness/error events.
1941
+
1942
+ ### Public surface
1943
+
1944
+ default `HTMLImport`; registers `html-import`; `connectedCallback()` and `ready`.
1945
+
1946
+ Exact exports: `default`.
1947
+
1948
+ ### Availability and normalization
1949
+
1950
+ **Browser / native WebView.** Public error detail normalized; fetch/DOM failure preserved. Transport: Same-origin fetch + DOM. [Deep protocol details](protocols.md).
1951
+
1952
+ ### Example
1953
+
1954
+ ```javascript
1955
+ import * as module from '/arcane/modules/HTMLImport.js';
1956
+
1957
+ console.log(Object.keys(module));
1958
+ ```
1959
+
1960
+ ## InMemoryCommunicationProvider.js
1961
+
1962
+ ### Overview
1963
+
1964
+ Implements deterministic in-memory thread/message/send behavior for demos and tests.
1965
+
1966
+ ### Public surface
1967
+
1968
+ default provider with `listThreads()`, `getMessages()`, `send()`.
1969
+
1970
+ Exact exports: `default`.
1971
+
1972
+ ### Availability and normalization
1973
+
1974
+ **Cross-host.** Normalized communication entities. Transport: In-process only. [Deep protocol details](protocols.md).
1975
+
1976
+ ### Example
1977
+
1978
+ ```javascript
1979
+ import * as module from '/arcane/modules/InMemoryCommunicationProvider.js';
1980
+
1981
+ console.log(Object.keys(module));
1982
+ ```
1983
+
1984
+ ## IsolatedModelQuestionRunner.js
1985
+
1986
+ ### Overview
1987
+
1988
+ Inspects one selected model and runs one isolated question while preserving the
1989
+ complete answer.
1990
+
1991
+ ### Public surface
1992
+
1993
+ default/named runner, `countSentences()`, `inspectModel()`, `runQuestion()`.
1994
+ `inspectModel(model,expectedModel,contextTokens)` accepts any positive safe
1995
+ integer context-token value and forwards the complete selected request.
1996
+ `runQuestion()` returns the provider's full result plus informative
1997
+ `sentenceCount`; it has no `maxSentences` input or `sentenceLimitExceeded`
1998
+ output.
1999
+
2000
+ Exact exports: `IsolatedModelQuestionRunner`, `countSentences`, `default`.
2001
+
2002
+ ### Availability and normalization
2003
+
2004
+ **Native bridge or injected provider.** Normalized model/result and coded errors. Transport: localAI isolated-model methods. [Deep protocol details](protocols.md).
2005
+
2006
+ ### Example
2007
+
2008
+ ```javascript
2009
+ import * as module from '/arcane/modules/IsolatedModelQuestionRunner.js';
2010
+
2011
+ console.log(Object.keys(module));
2012
+ ```
2013
+
2014
+ ## LocalAIReadiness.js
2015
+
2016
+ ### Overview
2017
+
2018
+ Derives selected AI requirements and returns a complete readiness/recovery report across browser, desktop, and Android modes.
2019
+
2020
+ ### Public surface
2021
+
2022
+ Endpoint constant plus requirements, speech-health, and readiness helpers.
2023
+
2024
+ Exact exports: `LOCAL_AI_BROWSER_ENDPOINTS`, `checkLocalAIReadiness`, `deriveLocalAIRequirements`, `evaluateLocalSpeechHealth`.
2025
+
2026
+ ### Availability and normalization
2027
+
2028
+ **Browser/native hybrid.** Fully normalized report and stable error codes; browsers never probe Ollama. Transport: Arcane.localAI, Arcane.speech, complete browser speech health. [Deep protocol details](protocols.md).
2029
+
2030
+ ### Example
2031
+
2032
+ ```javascript
2033
+ import * as module from '/arcane/modules/LocalAIReadiness.js';
2034
+
2035
+ console.log(Object.keys(module));
2036
+ ```
2037
+
2038
+ ## LocalAIReadinessController.js
2039
+
2040
+ ### Overview
2041
+
2042
+ Coordinates local-AI status component checks, ensured recovery, availability projection, and teardown.
2043
+
2044
+ ### Public surface
2045
+
2046
+ `createLocalAIReadinessController()`, `availabilityFromReport()`.
2047
+
2048
+ Exact exports: `LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES`,
2049
+ `LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES`,
2050
+ `LOCAL_AI_READINESS_CONTROLLER_REASONS`, `availabilityFromReport`, and
2051
+ `createLocalAIReadinessController`.
2052
+
2053
+ ### Availability and normalization
2054
+
2055
+ `availabilityFromReport()` returns `true` only for a slot whose local
2056
+ requirement is explicitly `required:true` and whose report is explicitly
2057
+ `ready:true`. Missing and non-local-required slots remain false: this projection
2058
+ does not attest provider registration, selection, credentials, browser speech
2059
+ authority, or model load state. Components must preserve selected sticky
2060
+ `AIRuntimeState` roles as the readiness authority.
2061
+
2062
+ **Browser/native hybrid.** Normalized controller state and change events.
2063
+ Transport: LocalAIReadiness + component events. [Deep protocol details](protocols.md).
2064
+
2065
+ ### Example
2066
+
2067
+ ```javascript
2068
+ import * as module from '/arcane/modules/LocalAIReadinessController.js';
2069
+
2070
+ console.log(Object.keys(module));
2071
+ ```
2072
+
2073
+ ## Mail.js
2074
+
2075
+ ### Overview
2076
+
2077
+ Builds complete reports and prefers the native mail capability with an explicit HTTP transport fallback. Report text, HTML, and serialized content are preserved exactly and delivered complete.
2078
+
2079
+ ### Public surface
2080
+
2081
+ default `Mail`, `resolveMailConfig()`; installs `window.mail`; `send()`.
2082
+
2083
+ Exact exports: `default`, `resolveMailConfig`.
2084
+
2085
+ ### Availability and normalization
2086
+
2087
+ **Browser/native hybrid + cloud.** Mail inputs/results normalized; transport failures mixed. Transport: Arcane.mail.send or MailTransport HTTP(S). [Deep protocol details](protocols.md).
2088
+
2089
+ ### Example
2090
+
2091
+ ```javascript
2092
+ import * as module from '/arcane/modules/Mail.js';
2093
+
2094
+ console.log(Object.keys(module));
2095
+ ```
2096
+
2097
+ ## MailOutbox.mjs
2098
+
2099
+ ### Overview
2100
+
2101
+ Persists each complete provider-neutral mail report before delivery and owns its
2102
+ idempotent enqueue, FIFO drain, retry-window, terminal-state, reconciliation,
2103
+ and explicit invalid-record maintenance lifecycle. It selects no mail provider,
2104
+ recipient, retention policy, retry timer, or transport fallback.
2105
+
2106
+ ### Public surface
2107
+
2108
+ Exact exports: `MAIL_OUTBOX_IDEMPOTENCY_WINDOW_MS`, `MAIL_OUTBOX_PROTOCOL`,
2109
+ `MAIL_OUTBOX_STATES`, `MAIL_OUTBOX_TABLE`, `MailOutbox`, `createMailOutbox`, and
2110
+ `default`.
2111
+
2112
+ ```text
2113
+ new MailOutbox({
2114
+ storage,
2115
+ deliver,
2116
+ clock=Date.now,
2117
+ isOnline=()=>globalThis.navigator?.onLine!==false,
2118
+ lockManager=undefined,
2119
+ onlineTarget=typeof globalThis.addEventListener==='function'?globalThis:null,
2120
+ onRecordCommitted=null,
2121
+ quarantineTable='mail_outbox_quarantine',
2122
+ table=MAIL_OUTBOX_TABLE
2123
+ }={})
2124
+ ```
2125
+
2126
+ `storage` must expose `get()`, `set()`, and `getAllKeys()`; explicit deletion or
2127
+ quarantine additionally requires `delete()`. `lockManager` must expose the Web
2128
+ Locks-compatible `request()` contract. The injected
2129
+ `deliver({report,reportKey,serializedReport,signal})` callback receives the
2130
+ complete parsed report, its stable idempotency key, the exact stored JSON string,
2131
+ and the caller-owned signal. Omitted `lockManager` resolves first from storage
2132
+ and then from `navigator.locks`. A delivery result must identify a valid
2133
+ `requestId` and one of `accepted`, `delivery_uncertain`,
2134
+ `retryable`, `permanently_rejected`, or `partially_accepted`;
2135
+ `providerId` and `acceptanceAuthority` are optional transport-owned metadata,
2136
+ and an acceptance authority is valid only on an `accepted` result.
2137
+
2138
+ Read-only getters are `started`, `invalidRecords`, and `lastBackgroundError`.
2139
+ Methods are `get(key)`, `list()`, `audit()`, `deleteInvalid(fileName)`,
2140
+ `repairInvalid(fileName,replacement)`,
2141
+ `quarantineInvalid()`,
2142
+ `enqueue({report,reportKey}={}, {attempt=true,signal=null}={})`,
2143
+ `drain({reason='manual',signal=null}={})`, `start({signal=null}={})`, and
2144
+ `stop()`. `createMailOutbox(options)` returns `new MailOutbox(options)`.
2145
+
2146
+ Every returned durable record contains exactly
2147
+ `{protocol,reportKey,serializedReport,state,createdAt,updatedAt,firstAttemptAt,
2148
+ lastAttemptAt,nextAttemptAt,attempts,result,failure}`. Protocol is
2149
+ `arcane-mail-outbox/1`; the default table is `mail_outbox`; the idempotency
2150
+ window is 86,400,000 milliseconds. States are exactly `queued`, `sending`,
2151
+ `retry_wait`, `accepted`, `failed`, and `reconciliation_required`. Accepted
2152
+ means the selected transport returned `accepted` with a valid request ID, not
2153
+ that the message reached an inbox.
2154
+
2155
+ `enqueue()` serializes same-instance persistence and binds one report key to one
2156
+ complete serialized body. It preserves the complete queued content without
2157
+ truncation, clipping, tailing, or elision.
2158
+ `drain()` runs or joins one instance drain under an exclusive shared lock. Startup,
2159
+ an owned `online` listener, or an explicit call may trigger work; there is no
2160
+ polling or retry timer. Abort before the delivery call prevents that call, and a
2161
+ caller joining an existing drain may stop waiting without cancelling the shared
2162
+ drain. Once an accepted result is committed, it outranks a racing cancellation;
2163
+ cancellation never claims an admitted provider attempt stopped. An interrupted
2164
+ or ambiguous attempt remains a same-key retry inside the 24-hour window and
2165
+ becomes `reconciliation_required` when automatic retry would risk a duplicate.
2166
+ `stop()` aborts only the owned online drain, removes its listener, preserves
2167
+ durable records, and returns the instance.
2168
+
2169
+ `audit()` reports valid records plus complete invalid-file metadata. Repair,
2170
+ deletion, and quarantine are explicit, revalidate the selected file under the
2171
+ table lock, and never infer destructive authority from a storage read failure.
2172
+ `onRecordCommitted(record)` is an observational callback after each durable
2173
+ write; callback failure cannot change the committed operation result.
2174
+
2175
+ ### Availability and normalization
2176
+
2177
+ **Browser/native WebView or compatible injected host.** The default application
2178
+ integration uses DBOPFS-compatible durable storage and `navigator.locks`; an
2179
+ alternate adapter owns its own durability claim and must provide equivalent
2180
+ storage and shared-lock semantics. Complete records, state transitions,
2181
+ retry/reconciliation classification, invalid-record maintenance, and
2182
+ AbortSignal admission/join cancellation are normalized. Storage, lock,
2183
+ online-check, and injected-delivery failures remain visible through concrete
2184
+ `MAIL_OUTBOX_*` codes. Transport: injected durable storage, Web Locks,
2185
+ AbortSignal, optional online EventTarget, and an injected delivery callback.
2186
+ [Deep protocol details](mail.md#durable-send-semantics).
2187
+
2188
+ ### Example
2189
+
2190
+ ```javascript
2191
+ import {createMailOutbox} from '/arcane/modules/MailOutbox.mjs';
2192
+
2193
+ const outbox = createMailOutbox({storage, deliver});
2194
+ await outbox.start({signal});
2195
+ const record = await outbox.enqueue(
2196
+ {report, reportKey: 'report-20260827-001'},
2197
+ {attempt: true, signal}
2198
+ );
2199
+ console.log(record.state);
2200
+ outbox.stop();
2201
+ ```
2202
+
2203
+ ## MailTransport.mjs
2204
+
2205
+ ### Overview
2206
+
2207
+ Sends one complete mail report to a normalized HTTP(S) endpoint.
2208
+
2209
+ ### Public surface
2210
+
2211
+ `MailTransportError`, `normalizeMailEndpoint()`, `serializeMailReport()`, and
2212
+ `sendMailReport()`.
2213
+
2214
+ Exact exports: `MailTransportError`, `normalizeMailEndpoint`,
2215
+ `serializeMailReport`, `sendMailReport`.
2216
+
2217
+ ### Availability and normalization
2218
+
2219
+ **Browser/server with fetch + cloud.** Normalized endpoint/transport errors; complete remote detail is preserved subject only to unavoidable HTTP framing. Transport: HTTP(S) fetch + AbortController. [Deep protocol details](protocols.md).
2220
+
2221
+ ### Example
2222
+
2223
+ ```javascript
2224
+ import * as module from '/arcane/modules/MailTransport.mjs';
2225
+
2226
+ console.log(Object.keys(module));
2227
+ ```
2228
+
2229
+ ## Marked.min.js
2230
+
2231
+ ### Overview
2232
+
2233
+ Vendored Marked 18.0.5 Markdown lexer, parser, renderer, extension, and walk-token API.
2234
+
2235
+ ### Public surface
2236
+
2237
+ Twenty named/default-style Marked exports; see bundled license notice.
2238
+
2239
+ Exact exports: `Hooks`, `Lexer`, `Marked`, `Parser`, `Renderer`, `TextRenderer`, `Tokenizer`, `defaults`, `getDefaults`, `lexer`, `marked`, `options`, `parse`, `parseInline`, `parser`, `setOptions`, `use`, `walkTokens`.
2240
+
2241
+ ### Availability and normalization
2242
+
2243
+ **Cross-host vendor module.** Vendor-native Marked contract. Transport: In-process only. [Deep protocol details](protocols.md).
2244
+
2245
+ ### Example
2246
+
2247
+ ```javascript
2248
+ import * as module from '/arcane/modules/Marked.min.js';
2249
+
2250
+ console.log(Object.keys(module));
2251
+ ```
2252
+
2253
+ ## MD.js
2254
+
2255
+ ### Overview
2256
+
2257
+ Renders complete Markdown with Marked and exposes the same complete rendered
2258
+ markup through `rendered` and `safeRendered`.
2259
+
2260
+ ### Public surface
2261
+
2262
+ default `MD`; `raw`, `rendered`, `safeRendered`, `append()`.
2263
+
2264
+ Exact exports: `default`.
2265
+
2266
+ ### Availability and normalization
2267
+
2268
+ **Browser / native WebView.** Raw Marked behavior is preserved; parse errors are
2269
+ vendor-native. Transport: Marked. [Deep protocol details](protocols.md).
2270
+
2271
+ ### Example
2272
+
2273
+ ```javascript
2274
+ import * as module from '/arcane/modules/MD.js';
2275
+
2276
+ console.log(Object.keys(module));
2277
+ ```
2278
+
2279
+ ## MemoryRecords.js
2280
+
2281
+ ### Overview
2282
+
2283
+ Normalizes memory content and detects meaningful stored memory.
2284
+
2285
+ ### Public surface
2286
+
2287
+ `normalizeMemoryContent()`, `hasMemoryContent()`.
2288
+
2289
+ Exact exports: `hasMemoryContent`, `normalizeMemoryContent`.
2290
+
2291
+ ### Availability and normalization
2292
+
2293
+ **Cross-host.** Fully normalized string/boolean results. Transport: In-process only. [Deep protocol details](protocols.md).
2294
+
2295
+ ### Example
2296
+
2297
+ ```javascript
2298
+ import * as module from '/arcane/modules/MemoryRecords.js';
2299
+
2300
+ console.log(Object.keys(module));
2301
+ ```
2302
+
2303
+ ## MessageAdvisory.js
2304
+
2305
+ ### Overview
2306
+
2307
+ Normalizes message content advisories and contains per-message inspection failures.
2308
+
2309
+ ### Public surface
2310
+
2311
+ Three advisory/inspection helpers.
2312
+
2313
+ Exact exports: `inspectMessageRecords`, `normalizeContentAdvisory`, `unavailableMessageInspection`.
2314
+
2315
+ ### Availability and normalization
2316
+
2317
+ **Cross-host.** Complete mutable advisory records preserve all supplied text and signals; inspector failures are converted to unavailable results. Transport: Injected inspector. [Deep protocol details](protocols.md).
2318
+
2319
+ ### Example
2320
+
2321
+ ```javascript
2322
+ import * as module from '/arcane/modules/MessageAdvisory.js';
2323
+
2324
+ console.log(Object.keys(module));
2325
+ ```
2326
+
2327
+ ## ModelDefinition.js
2328
+
2329
+ ### Overview
2330
+
2331
+ Parses the deterministic packaged Modelfile subset and extracts the SYSTEM prompt.
2332
+
2333
+ ### Public surface
2334
+
2335
+ `parseModelDefinition()`, `loadModelDefinitionSystemPrompt()`.
2336
+
2337
+ Exact exports: `loadModelDefinitionSystemPrompt`, `parseModelDefinition`.
2338
+
2339
+ ### Availability and normalization
2340
+
2341
+ **Cross-host.** Complete mutable definition data with coded syntax errors for malformed input. Transport: Optional ordinary read-only fetch using the fetch implementation's redirect, credentials, and cache behavior. [Deep protocol details](protocols.md).
2342
+
2343
+ ### Example
2344
+
2345
+ ```javascript
2346
+ import * as module from '/arcane/modules/ModelDefinition.js';
2347
+
2348
+ console.log(Object.keys(module));
2349
+ ```
2350
+
2351
+ ## Ollama.js
2352
+
2353
+ ### Overview
2354
+
2355
+ Provides the first-class Arcane Ollama client without direct access to localhost:11434.
2356
+
2357
+ ### Public surface
2358
+
2359
+ `Ollama`, singleton/default `ollama`; 24 methods; installs `globalThis.arcaneOllama`, emits `arcane-ollama-ready`.
2360
+
2361
+ Exact exports: `OLLAMA_EVENT_TYPES`, `OLLAMA_REASONS`, `Ollama`, `default`,
2362
+ and `ollama`.
2363
+
2364
+ ### Availability and normalization
2365
+
2366
+ **Native bridge.** Principal methods preserve provider-native envelopes; readiness/text/unload helpers normalize. Transport: Arcane.ollama through Core. [Deep protocol details](protocols.md).
2367
+
2368
+ ### Example
2369
+
2370
+ ```javascript
2371
+ import * as module from '/arcane/modules/Ollama.js';
2372
+
2373
+ console.log(Object.keys(module));
2374
+ ```
2375
+
2376
+ ## OllamaModelIdentifier.js
2377
+
2378
+ ### Overview
2379
+
2380
+ Validates and canonicalizes the syntax of Ollama model identifiers without granting model admission.
2381
+
2382
+ ### Public surface
2383
+
2384
+ `normalizeOllamaModelIdentifier()`, `isOllamaModelIdentifier()`.
2385
+
2386
+ Exact exports: `isOllamaModelIdentifier`, `normalizeOllamaModelIdentifier`.
2387
+
2388
+ ### Availability and normalization
2389
+
2390
+ **Cross-host.** Fully normalized string/boolean result. Transport: In-process only. [Deep protocol details](protocols.md).
2391
+
2392
+ ### Example
2393
+
2394
+ ```javascript
2395
+ import * as module from '/arcane/modules/OllamaModelIdentifier.js';
2396
+
2397
+ console.log(Object.keys(module));
2398
+ ```
2399
+
2400
+ ## OllamaSettings.js
2401
+
2402
+ ### Overview
2403
+
2404
+ Defines complete runtime/service preference schemas and deterministic Arcane brain alias names.
2405
+
2406
+ ### Public surface
2407
+
2408
+ `ollamaRuntimeSchema`, `ollamaServiceSchema`, `arcaneBrainModelName()`.
2409
+
2410
+ Exact exports: `arcaneBrainModelName`, `ollamaRuntimeSchema`, `ollamaServiceSchema`.
2411
+
2412
+ ### Availability and normalization
2413
+
2414
+ **Cross-host.** Fully normalized settings/name contract. Transport: In-process only. [Deep protocol details](protocols.md).
2415
+
2416
+ ### Example
2417
+
2418
+ ```javascript
2419
+ import * as module from '/arcane/modules/OllamaSettings.js';
2420
+
2421
+ console.log(Object.keys(module));
2422
+ ```
2423
+
2424
+ ## OpenMeteoWeatherProvider.js
2425
+
2426
+ ### Overview
2427
+
2428
+ Searches and loads Open-Meteo data into mutable Arcane weather entities.
2429
+
2430
+ ### Public surface
2431
+
2432
+ Endpoint constants, default provider, `mapForecast()`; search/load methods and lifecycle events.
2433
+
2434
+ Exact exports: `OPEN_METEO_ENDPOINTS`, `OPEN_METEO_WEATHER_ERRORS`,
2435
+ `OPEN_METEO_WEATHER_EVENTS`, `default`, and `mapForecast`.
2436
+
2437
+ ### Availability and normalization
2438
+
2439
+ **Browser / native WebView / server with fetch + cloud.** Provider data normalized to entities; transport errors mixed. Transport: Open-Meteo HTTPS. [Deep protocol details](protocols.md).
2440
+
2441
+ ### Example
2442
+
2443
+ ```javascript
2444
+ import * as module from '/arcane/modules/OpenMeteoWeatherProvider.js';
2445
+
2446
+ console.log(Object.keys(module));
2447
+ ```
2448
+
2449
+ ## PersistentAIChatSession.js
2450
+
2451
+ ### Overview
2452
+
2453
+ Composes `ConfiguredAIChatSession` with one `ChatEntity` so every user,
2454
+ assistant, and structural tool-result turn has an explicit durable-persistence
2455
+ choice. It preserves the existing DBOPFS method names and ChatEntity memory
2456
+ semantics; it does not define a new storage protocol.
2457
+
2458
+ ### Public surface
2459
+
2460
+ Exact exports: `PersistentAIChatSession`, `createPersistentAIChatSession`, and
2461
+ `default`.
2462
+
2463
+ Constructor and factory options are `{ai,chat,chatEntity,chatFileName,
2464
+ contextBuilder,loadExisting,memory,request,responseLength,systemPrompt}`. Public members are
2465
+ static `create()`, getters `ai`, `chatEntity`, and `fileName`, and `ready()`,
2466
+ `history()`, `transcript()`, `settleMemory()`, `open(input)`, `send(input)`, and
2467
+ `stream(input,handlers)`.
2468
+ `ready()` waits for initialization and resolves the same session instance.
2469
+
2470
+ `open({message:{content,persist:false?},request?,signal?})` performs one
2471
+ application-authored bootstrap request only when the retained conversation is
2472
+ otherwise empty. The bootstrap is never committed. After a complete nonblank
2473
+ model response succeeds, the operation atomically retains only the sanitized
2474
+ assistant content in configured model context and ChatEntity/DBOPFS history.
2475
+ That assistant-only opening survives reload and empty-chat maintenance without
2476
+ a fabricated user turn. A second opening rejects as `AI_CHAT_OPENING_EXISTS`;
2477
+ an unavailable durable ChatEntity rejects as `AI_CHAT_PERSISTENCE_UNAVAILABLE`.
2478
+
2479
+ `send()` accepts either
2480
+ `{message:{content,role:'user'|'tool',tool_call_id?,message?,name?,status?,persist},...}`
2481
+ or an atomic tool-result batch with the same fields,
2482
+ plus `request?`, `response:{persist}`, and `signal?`. Every message and the
2483
+ response must use the same persistence choice. Plain-object `request` supplies
2484
+ per-turn generation options such as
2485
+ `toolChoice:'none'`; it cannot replace session-owned `messages`, `signal`, or
2486
+ streaming/lifecycle callback state.
2487
+ `persist:false` makes the input and response available only to that one request.
2488
+ After the response is returned, neither remains in subsequent model context,
2489
+ the retained transcript, memory extraction, or DBOPFS. A nonpersistent response
2490
+ therefore does not open a retained structural-tool continuation. A retained
2491
+ structural tool result must use the persistence choice captured by its matching
2492
+ assistant tool call.
2493
+
2494
+ `history()` returns provider-safe configured model context, including the
2495
+ system prompt and every complete ordinary visible committed turn. Only a
2496
+ currently unresolved structural-call tail remains raw for its matching active
2497
+ continuation. `transcript()` returns the sanitized human-readable ChatEntity
2498
+ projection.
2499
+ User and assistant records retain only role, complete visible content, and the
2500
+ real timestamp. Tool records retain only role, the required user-facing
2501
+ `message` as content, and optional public `name` and result `status`.
2502
+
2503
+ `stream()` accepts the same input as `send()` and optional
2504
+ `{onChunk,onDataChunk,onDataResult,onToolCall}` handlers. When
2505
+ `ai.streamRequest()` is available, it forwards complete provider data through
2506
+ the data callbacks and ordinary live text/reasoning through `onChunk`. It
2507
+ buffers every observed structural call until the ordered call array exactly
2508
+ matches the terminal response and the complete response passes
2509
+ configured-session validation, and only then publishes each call and uses the
2510
+ same atomic ChatEntity append/configured session commit as `send()`. A
2511
+ terminal-only call is valid; omission or divergence of any observed call
2512
+ rejects with
2513
+ `AI_CHAT_STREAM_TOOL_CALL_MISMATCH` before persistence or commit. When streaming
2514
+ is unavailable, `stream()` uses the
2515
+ configured non-stream chat request and still returns, validates, persists, and
2516
+ renders the complete terminal response and tool calls; optional streaming is
2517
+ not a session failure. The same caller signal and transaction rollback govern
2518
+ both paths.
2519
+
2520
+ When an assistant response opens structural calls, the response persistence
2521
+ choice is retained under every exact call ID only in the active session. One
2522
+ ordered `role:'tool'` request batch must settle all pending IDs with that same
2523
+ persistence choice before a new user or provider turn. That one provider
2524
+ continuation receives the raw calls, IDs, arguments, and results. Once it
2525
+ commits, recurring context replaces them with complete ordinary visible call,
2526
+ assistant, and any supplied public result messages. Raw protocol is never
2527
+ included in new durable records. Existing stored records are not rewritten on
2528
+ load.
2529
+
2530
+ ### Availability and normalization
2531
+
2532
+ **Browser or native WebView with ChatEntity/DBOPFS and a configured chat
2533
+ function.** The default chat calls normalized `Arcane.ai.chat()`; callers can
2534
+ inject the browser-WASM controller, another provider-neutral adapter, or a
2535
+ cloud chat function. There is no automatic provider or storage fallback.
2536
+ Context builders are request-only, and document context remains explicitly
2537
+ untrusted. Errors include `AI_CHAT_BUSY`, `AI_CHAT_TOOL_RESULT_REQUIRED`,
2538
+ `AI_CHAT_INVALID_TOOL_MESSAGE`, `AI_CHAT_TOOL_MESSAGE_REQUIRED`, and
2539
+ `AI_CHAT_INCOHERENT_PERSISTENCE`, plus
2540
+ `AI_CHAT_STREAM_TOOL_CALL_MISMATCH` for a streamed/terminal envelope mismatch,
2541
+ and `AI_CHAT_INVALID_OPENING_RESPONSE`, `AI_CHAT_OPENING_EXISTS`, or
2542
+ `AI_CHAT_PERSISTENCE_UNAVAILABLE` for the dedicated opening lifecycle.
2543
+
2544
+ ### Example
2545
+
2546
+ ```javascript
2547
+ import {
2548
+ createPersistentAIChatSession
2549
+ } from '/arcane/modules/PersistentAIChatSession.js';
2550
+
2551
+ async function sendPersistentSupportTurnAfterUserChoice(documents) {
2552
+ const session = await createPersistentAIChatSession({
2553
+ chatFileName: 'support.jsonl',
2554
+ loadExisting: true,
2555
+ contextBuilder: documents.createContextBuilder()
2556
+ });
2557
+ const response = await session.send({
2558
+ message: {role: 'user', content: 'Summarize the documents.', persist: true},
2559
+ response: {persist: true}
2560
+ });
2561
+ console.log(response.message.content);
2562
+ }
2563
+ ```
2564
+
2565
+ ## PreferenceStore.js
2566
+
2567
+ ### Overview
2568
+
2569
+ Loads and updates schema-defined app preferences through native storage with a narrow browser fallback.
2570
+
2571
+ ### Public surface
2572
+
2573
+ default `PreferenceStore`, re-exported `Preference`/schema; load/set/setAll/reset APIs and events.
2574
+
2575
+ Adapters provide `get(key, context)`, `set(key, value, context)`, and
2576
+ `delete(key, context)`. An adapter may also provide
2577
+ `setMany(entries, context)`, where `entries` is one mutable plain object keyed by
2578
+ the store's namespaced storage keys. `setAll(values, {signal})` normalizes every
2579
+ selected schema value before storage work. For every selected value it calls an
2580
+ advertised `setMany()` once and publishes the existing per-key change events
2581
+ only after that batch succeeds. A dispatched batch rejection propagates without
2582
+ a serial retry, in-memory state change, or change event. Adapters without
2583
+ `setMany()` retain ordered complete serial storage behavior inside
2584
+ one queued operation, including state and events for each successful write before
2585
+ a later write fails.
2586
+
2587
+ Exact exports: `PREFERENCE_STORE_ERROR_CODES`,
2588
+ `PREFERENCE_STORE_EVENT_TYPES`, `Preference`, `default`, and
2589
+ `preferenceSchema`.
2590
+
2591
+ ### Availability and normalization
2592
+
2593
+ **Browser/native hybrid.** Complete ordinary values and returned snapshots remain
2594
+ mutable after schema normalization. Non-Android
2595
+ `Arcane.preferences.setMany()` supplies the optional atomic batch. Only exact
2596
+ unsupported native capability changes future operations to app-scoped
2597
+ localStorage; an in-flight advertised batch is never downgraded after rejection.
2598
+ If cancellation settles after a native batch was dispatched, reload the store to
2599
+ reconcile any atomic host commit that completed before cancellation. Transport:
2600
+ Arcane.preferences or app-scoped localStorage. [Deep protocol details](protocols.md).
2601
+
2602
+ ### Example
2603
+
2604
+ ```javascript
2605
+ import * as module from '/arcane/modules/PreferenceStore.js';
2606
+
2607
+ console.log(Object.keys(module));
2608
+ ```
2609
+
2610
+ ## QRCode.min.js
2611
+
2612
+ ### Overview
2613
+
2614
+ Vendored QRCode generator for DOM, canvas, SVG, and image output.
2615
+
2616
+ ### Public surface
2617
+
2618
+ No ESM exports; global `QRCode`, `makeCode()`, `makeImage()`, `clear()`, `CorrectLevel`.
2619
+
2620
+ This is a classic global script and has no ESM exports.
2621
+
2622
+ ### Availability and normalization
2623
+
2624
+ **Browser vendor script.** Vendor-native. Transport: Classic script global + DOM/canvas/SVG. [Deep protocol details](protocols.md).
2625
+
2626
+ ### Example
2627
+
2628
+ ```html
2629
+ <script src="/arcane/modules/QRCode.min.js"></script>
2630
+ ```
2631
+
2632
+ ## Questionnaire.js
2633
+
2634
+ ### Overview
2635
+
2636
+ Evaluates whether a one-time questionnaire prompt is due without performing the prompt.
2637
+
2638
+ ### Public surface
2639
+
2640
+ Notification default and `Questionnaire` with timing/check methods.
2641
+
2642
+ Exact exports: `DEFAULT_QUESTIONNAIRE_NOTIFICATION_TIME_MS`, `Questionnaire`.
2643
+
2644
+ ### Availability and normalization
2645
+
2646
+ **Cross-host.** Normalized conservative boolean. Transport: In-process clock only. [Deep protocol details](protocols.md).
2647
+
2648
+ ### Example
2649
+
2650
+ ```javascript
2651
+ import * as module from '/arcane/modules/Questionnaire.js';
2652
+
2653
+ console.log(Object.keys(module));
2654
+ ```
2655
+
2656
+ ## RecordLinkIndex.js
2657
+
2658
+ ### Overview
2659
+
2660
+ Parses record links and builds their normalized index.
2661
+
2662
+ ### Public surface
2663
+
2664
+ `parseRecordLinks()`, `buildRecordLinkIndex()`.
2665
+
2666
+ Exact exports: `buildRecordLinkIndex`, `parseRecordLinks`.
2667
+
2668
+ ### Availability and normalization
2669
+
2670
+ **Cross-host.** Fully normalized. Transport: In-process only. [Deep protocol details](protocols.md).
2671
+
2672
+ ### Example
2673
+
2674
+ ```javascript
2675
+ import * as module from '/arcane/modules/RecordLinkIndex.js';
2676
+
2677
+ console.log(Object.keys(module));
2678
+ ```
2679
+
2680
+ ## RecordPassageIndex.js
2681
+
2682
+ ### Overview
2683
+
2684
+ Indexes text lines, page markers, dates, rules, and excerpts for record review.
2685
+
2686
+ ### Public surface
2687
+
2688
+ Eight text/page/date/rule helper exports.
2689
+
2690
+ Exact exports: `cleanExcerpt`, `extractDateMentions`, `findRulePassages`, `pageAtLine`, `pageMarkers`, `parseDateMention`, `textLines`, `validIsoDate`.
2691
+
2692
+ ### Availability and normalization
2693
+
2694
+ **Cross-host.** Complete selected excerpts and every unique date/rule finding are preserved without character or result-count caps. Transport: In-process only. [Deep protocol details](protocols.md).
2695
+
2696
+ ### Example
2697
+
2698
+ ```javascript
2699
+ import * as module from '/arcane/modules/RecordPassageIndex.js';
2700
+
2701
+ console.log(Object.keys(module));
2702
+ ```
2703
+
2704
+ ## RecordReviewStore.js
2705
+
2706
+ ### Overview
2707
+
2708
+ Stores normalized record-review decisions through native storage or app-scoped local fallback.
2709
+
2710
+ ### Public surface
2711
+
2712
+ default store, record/review normalizers; `load()`, `get()`, `set()`, `snapshot()`, change event.
2713
+
2714
+ Exact exports: `RECORD_REVIEW_STORE_ERROR_CODES`,
2715
+ `RECORD_REVIEW_STORE_EVENT_TYPES`, `default`, `normalizeRecordId`, and
2716
+ `normalizeReview`.
2717
+
2718
+ ### Availability and normalization
2719
+
2720
+ **Browser/native hybrid.** Complete normalized ids, reviews, and snapshots are preserved; unreadable stored records fail with `ARCANE_RECORD_REVIEW_STORED_RECORDS_INVALID` rather than silently becoming an empty store. Transport: Arcane.storage or localStorage. [Deep protocol details](protocols.md).
2721
+
2722
+ ### Example
2723
+
2724
+ ```javascript
2725
+ import * as module from '/arcane/modules/RecordReviewStore.js';
2726
+
2727
+ console.log(Object.keys(module));
2728
+ ```
2729
+
2730
+ ## RiskSignalAnalyzer.js
2731
+
2732
+ ### Overview
2733
+
2734
+ Matches configured risk signals and levels against complete text.
2735
+
2736
+ ### Public surface
2737
+
2738
+ `DEFAULT_LEVELS`, `analyzeRiskSignals()`.
2739
+
2740
+ Exact exports: `DEFAULT_LEVELS`, `analyzeRiskSignals`.
2741
+
2742
+ ### Availability and normalization
2743
+
2744
+ **Cross-host.** Fully normalized. Transport: In-process only. [Deep protocol details](protocols.md).
2745
+
2746
+ ### Example
2747
+
2748
+ ```javascript
2749
+ import * as module from '/arcane/modules/RiskSignalAnalyzer.js';
2750
+
2751
+ console.log(Object.keys(module));
2752
+ ```
2753
+
2754
+ ## ScamRiskPolicy.js
2755
+
2756
+ ### Overview
2757
+
2758
+ Combines deterministic scam signals with optional Arcane blocked-domain evidence and safety guidance.
2759
+
2760
+ ### Public surface
2761
+
2762
+ Signals plus load, assess, and guidance helpers.
2763
+
2764
+ Exact exports: `assessScamRisk`, `loadScamNetworkPolicy`, `scamRiskSignals`, `scamSafetyGuidance`.
2765
+
2766
+ ### Availability and normalization
2767
+
2768
+ **Cross-host.** Complete mutable signal results are returned. Blocked-domain policy inspection is inactive by default and runs only when the caller explicitly selects `secure:true`. Transport: In-process + optional caller-selected Arcane network policy fetch. [Deep protocol details](protocols.md).
2769
+
2770
+ ### Example
2771
+
2772
+ ```javascript
2773
+ import * as module from '/arcane/modules/ScamRiskPolicy.js';
2774
+
2775
+ console.log(Object.keys(module));
2776
+ ```
2777
+
2778
+ ## ScopedOPFSCache.js
2779
+
2780
+ ### Overview
2781
+
2782
+ Provides a narrow exact-key JSON cache inside one app-owned OPFS namespace.
2783
+
2784
+ ### Public surface
2785
+
2786
+ default `ScopedOPFSCache`; support check and get/set/delete APIs.
2787
+
2788
+ Exact exports: `default`.
2789
+
2790
+ ### Availability and normalization
2791
+
2792
+ **Browser / native WebView.** Exact-key options and malformed-JSON handling are
2793
+ normalized; complete JSON values are preserved and storage errors remain
2794
+ visible. Transport: OPFS + AppDataScope. [Deep protocol details](protocols.md).
2795
+
2796
+ ### Example
2797
+
2798
+ ```javascript
2799
+ import * as module from '/arcane/modules/ScopedOPFSCache.js';
2800
+
2801
+ console.log(Object.keys(module));
2802
+ ```
2803
+
2804
+ ## ScreenCapture.js
2805
+
2806
+ ### Overview
2807
+
2808
+ Captures a display surface as image, video, or GIF with explicit lifecycle events.
2809
+
2810
+ ### Public surface
2811
+
2812
+ default `ScreenCapture`; acquire/capture/start/stop/reset methods.
2813
+
2814
+ Exact exports: `SCREEN_CAPTURE_ERROR_CODES`, `SCREEN_CAPTURE_ERRORS`,
2815
+ `SCREEN_CAPTURE_EVENT_TYPES`, `SCREEN_CAPTURE_IMAGE_TYPE_FALLBACK`,
2816
+ `SCREEN_CAPTURE_REASONS`, `SCREEN_CAPTURE_STATUSES`, and `default`.
2817
+
2818
+ ### Availability and normalization
2819
+
2820
+ **Browser / native WebView.** State/events normalized; permission and codec errors mixed. Transport: getDisplayMedia, MediaRecorder, canvas, GifEncoder. [Deep protocol details](protocols.md).
2821
+
2822
+ ### Example
2823
+
2824
+ ```javascript
2825
+ import * as module from '/arcane/modules/ScreenCapture.js';
2826
+
2827
+ console.log(Object.keys(module));
2828
+ ```
2829
+
2830
+ ## SpeechPlayback.js
2831
+
2832
+ ### Overview
2833
+
2834
+ Preserves exact nonblank text as one segment, queues latest-request speech
2835
+ synthesis, and controls lookahead HTML audio playback.
2836
+
2837
+ ### Public surface
2838
+
2839
+ `SpeechPlayback` class/default, `SPEECH_PLAYBACK_STATE_EVENT`,
2840
+ `splitSpeechText()`, and playback lifecycle APIs.
2841
+
2842
+ Exact exports: `SPEECH_PLAYBACK_STATE_EVENT`, `SpeechPlayback`, `default`, and
2843
+ `splitSpeechText`.
2844
+
2845
+ ```text
2846
+ new SpeechPlayback({
2847
+ audio,
2848
+ speech=globalThis.Arcane?.speech,
2849
+ model=null,
2850
+ voice=null,
2851
+ responseFormat=null,
2852
+ speed=1,
2853
+ createObjectURL,
2854
+ revokeObjectURL,
2855
+ delay,
2856
+ messages={}
2857
+ })
2858
+ ```
2859
+
2860
+ `speech` must expose either `fetchTTS(payload, signal)` or
2861
+ `synthesize(payload, {signal})`. `prepare({key,parts,model,voice,responseFormat,
2862
+ speed,autoplay=true})` uses only caller-supplied model, voice, and response-format
2863
+ values; those three omitted values remain omitted so the selected AI/model
2864
+ catalog may provide its documented defaults. Speed defaults to `1`, is normalized
2865
+ as a positive number, and is always sent. There is no
2866
+ hard-coded model, response format, voice, or cloud/browser fallback.
2867
+ `splitSpeechText(value)` uses trimming only to detect blank input, then returns
2868
+ the caller's exact string in one mutable array without trimming, splitting, or
2869
+ freezing it. `prepare()` likewise preserves each nonblank part's exact `input`
2870
+ string while normalizing its other playback fields into a new mutable record.
2871
+ The class applies no part-count, character-count, pause, or input upper cap.
2872
+
2873
+ Every preparation owns an operation ID and one AbortController for each active
2874
+ synthesis segment or playback delay. Replacement,
2875
+ `stop()`, `cancel()`, and `destroy()` abort their owned signals, suppress stale
2876
+ settlement, release Blob URLs, and publish synchronous
2877
+ `speech-playback-state` occurrences through `globalThis.arcaneEvents`.
2878
+ Subscribers receive mutable public state detail. The detail contains
2879
+ `state`, `message`, `key`, `index`, `total`, `producing`, `buffered`, `hasAudio`,
2880
+ `operationId`, `code`, and `reason`; provider rejection remains preserved to the
2881
+ `prepare()` caller. `destroy()` also removes every audio listener and disposes
2882
+ its per-instance canonical source handle; repeated destroy returns
2883
+ `false`. Signal abortion proves delivery suppression; whether provider work
2884
+ actually stops remains the selected provider's cancellation boundary.
2885
+
2886
+ Stable error codes are `ARCANE_SPEECH_PLAYBACK_DESTROYED`,
2887
+ `ARCANE_SPEECH_PLAYBACK_OPERATION_SEQUENCE_EXHAUSTED`,
2888
+ `ARCANE_SPEECH_PLAYBACK_SYNTHESIZER_UNAVAILABLE`,
2889
+ `ARCANE_SPEECH_PLAYBACK_SYNTHESIZED_AUDIO_CONTRACT_MISMATCH`,
2890
+ `ARCANE_SPEECH_PLAYBACK_AUDIO_PLAYBACK_REJECTED`,
2891
+ `ARCANE_SPEECH_PLAYBACK_REQUEST_CONTRACT_MISMATCH`, and
2892
+ `ARCANE_SPEECH_PLAYBACK_SYNTHESIS_REQUEST_REJECTED`, plus propagated
2893
+ `ARCANE_AI_OPERATION_SUPERSEDED` and `ARCANE_AI_REQUEST_ABORTED`.
2894
+ Exact lifecycle reasons are `playback-replaced`, `playback-stopped`,
2895
+ `playback-destroyed`, `speech-playback-cancelled`,
2896
+ `speech-synthesis-superseded`, `speech-synthesis-cancelled`,
2897
+ `speech-synthesizer-unavailable`, `synthesized-audio-contract-mismatch`,
2898
+ `audio-playback-rejected`, `audio-autoplay-rejected`,
2899
+ `speech-playback-request-contract-mismatch`, and
2900
+ `speech-synthesis-rejected`, as applicable to the emitted state.
2901
+
2902
+ ### Availability and normalization
2903
+
2904
+ **Browser + compatible AI/native bridge.** State, cancellation, lifecycle, and
2905
+ playable Blob normalization are shared. Provider/model/runtime/voice selection
2906
+ remains caller- and catalog-owned. Transport: `AI.fetchTTS`, compatible
2907
+ `Arcane.speech.synthesize`, Blob URLs, audio element, and the singleton event
2908
+ authority. [Deep protocol details](protocols.md).
2909
+
2910
+ ### Example
2911
+
2912
+ ```javascript
2913
+ import SpeechPlayback from '/arcane/modules/SpeechPlayback.js';
2914
+
2915
+ const audio = document.body.appendChild(document.createElement('audio'));
2916
+ audio.controls = true;
2917
+ const speech = new SpeechPlayback({
2918
+ audio,
2919
+ speech: globalThis.ai,
2920
+ model: 'caller-selected-model',
2921
+ voice: 'caller-selected-voice',
2922
+ responseFormat: 'wav'
2923
+ });
2924
+ const speakButton = document.body.appendChild(document.createElement('button'));
2925
+ speakButton.type = 'button';
2926
+ speakButton.textContent = 'Speak';
2927
+ speakButton.addEventListener('click', async () => {
2928
+ await speech.prepare({
2929
+ key: 'ready',
2930
+ parts: ['Arcane is ready.'],
2931
+ autoplay: true
2932
+ });
2933
+ });
2934
+ ```
2935
+
2936
+ ## StaticDocumentCatalog.js
2937
+
2938
+ ### Overview
2939
+
2940
+ Loads a positive static document inventory with cache, search, and complete context.
2941
+
2942
+ ### Public surface
2943
+
2944
+ default catalog, schema constant, catalog normalizer/cache-key; list/get/search/hydrate/context APIs.
2945
+
2946
+ Exact exports: `CATALOG_SCHEMA_VERSION`, `default`, `normalizeStaticDocumentCatalog`, `staticDocumentCacheKey`.
2947
+
2948
+ ### Availability and normalization
2949
+
2950
+ **Browser / native WebView / server with fetch.** Catalog/content normalization
2951
+ preserves complete mutable documents; malformed catalog/content and transport
2952
+ failures remain visible. Transport: HTTP(S) and optional cache. [Deep protocol details](protocols.md).
2953
+
2954
+ ### Example
2955
+
2956
+ ```javascript
2957
+ import * as module from '/arcane/modules/StaticDocumentCatalog.js';
2958
+
2959
+ console.log(Object.keys(module));
2960
+ ```
2961
+
2962
+ ## SystemAppearance.js
2963
+
2964
+ ### Overview
2965
+
2966
+ Reads or applies native appearance, returning an explicit unsupported browser state when no bridge exists.
2967
+
2968
+ ### Public surface
2969
+
2970
+ default `SystemAppearance`; `available()`, `current()`, `apply()`.
2971
+
2972
+ Exact exports: `default`.
2973
+
2974
+ ### Availability and normalization
2975
+
2976
+ **Browser/native hybrid.** Absent bridge normalized; native result/error preserved. Transport: Arcane.appearance. [Deep protocol details](protocols.md).
2977
+
2978
+ ### Example
2979
+
2980
+ ```javascript
2981
+ import * as module from '/arcane/modules/SystemAppearance.js';
2982
+
2983
+ console.log(Object.keys(module));
2984
+ ```
2985
+
2986
+ ## SystemPlatformPresentation.js
2987
+
2988
+ ### Overview
2989
+
2990
+ Maps kernel names to presentation labels/classes without granting platform authority.
2991
+
2992
+ ### Public surface
2993
+
2994
+ No ESM exports; global `ArcaneSystemPlatformPresentation` with `kernelType()`, `displayName()`, `apply()`.
2995
+
2996
+ This is a classic global script and has no ESM exports.
2997
+
2998
+ ### Availability and normalization
2999
+
3000
+ **Browser / native WebView classic script.** Fully normalized presentation only. Transport: DOM. [Deep protocol details](protocols.md).
3001
+
3002
+ ### Example
3003
+
3004
+ ```html
3005
+ <script src="/arcane/modules/SystemPlatformPresentation.js"></script>
3006
+ ```
3007
+
3008
+ ## SystemToolRegistry.js
3009
+
3010
+ ### Overview
3011
+
3012
+ Registers validated command builders and constructs command strings without executing them.
3013
+
3014
+ ### Public surface
3015
+
3016
+ default registry, `quoteArgument()`, register/list/get/build APIs.
3017
+
3018
+ Exact exports: `default`, `quoteArgument`.
3019
+
3020
+ ### Availability and normalization
3021
+
3022
+ **Cross-host.** Fully normalized definitions/quoting. Transport: In-process only. [Deep protocol details](protocols.md).
3023
+
3024
+ ### Example
3025
+
3026
+ ```javascript
3027
+ import * as module from '/arcane/modules/SystemToolRegistry.js';
3028
+
3029
+ console.log(Object.keys(module));
3030
+ ```
3031
+
3032
+ ## TerminalClient.js
3033
+
3034
+ ### Overview
3035
+
3036
+ Maps native terminal sessions and Arcane events into an EventTarget client.
3037
+
3038
+ ### Public surface
3039
+
3040
+ default `TerminalClient`; start/write/resize/signal/close/receive/destroy APIs and terminal events.
3041
+
3042
+ Exact exports: `TERMINAL_CLIENT_ERROR_CODES`, `TERMINAL_CLIENT_EVENT_TYPES`,
3043
+ `TERMINAL_CLIENT_REASONS`, and `default`.
3044
+
3045
+ ### Availability and normalization
3046
+
3047
+ **Native bridge.** Client events/state normalized; native result/error mixed. Transport: Arcane.terminal + Arcane.events. [Deep protocol details](protocols.md).
3048
+
3049
+ ### Example
3050
+
3051
+ ```javascript
3052
+ import * as module from '/arcane/modules/TerminalClient.js';
3053
+
3054
+ console.log(Object.keys(module));
3055
+ ```
3056
+
3057
+ ## TerminalCommandRegistry.js
3058
+
3059
+ ### Overview
3060
+
3061
+ Routes parsed command lines to injected handlers and provides definitions/completions.
3062
+
3063
+ ### Public surface
3064
+
3065
+ default registry, `splitCommandLine()`, register/resolve/definitions/completions/execute APIs.
3066
+
3067
+ Exact exports: `default`, `splitCommandLine`.
3068
+
3069
+ ### Availability and normalization
3070
+
3071
+ **Cross-host.** Parsing/routing normalized; handler result/error preserved. Transport: Injected handlers. [Deep protocol details](protocols.md).
3072
+
3073
+ ### Example
3074
+
3075
+ ```javascript
3076
+ import * as module from '/arcane/modules/TerminalCommandRegistry.js';
3077
+
3078
+ console.log(Object.keys(module));
3079
+ ```
3080
+
3081
+ ## ThemeBootstrap.js
3082
+
3083
+ ### Overview
3084
+
3085
+ Performs import-time Arcane theme loading and subscribes to native appearance changes.
3086
+
3087
+ ### Public surface
3088
+
3089
+ `bootstrapArcaneTheme()`, `arcaneThemeReady`, default ready promise.
3090
+
3091
+ Exact exports: `arcaneThemeReady`, `bootstrapArcaneTheme`, `default`, and
3092
+ `disposeArcaneThemeBootstrap`.
3093
+
3094
+ ### Availability and normalization
3095
+
3096
+ **Browser/native hybrid.** Theme state normalized; storage/native errors mixed. Transport: ThemeManager + Arcane.events. [Deep protocol details](protocols.md).
3097
+
3098
+ ### Example
3099
+
3100
+ ```javascript
3101
+ import * as module from '/arcane/modules/ThemeBootstrap.js';
3102
+
3103
+ console.log(Object.keys(module));
3104
+ ```
3105
+
3106
+ ## ThemeManager.js
3107
+
3108
+ ### Overview
3109
+
3110
+ Loads, applies, previews, saves, resets, and synchronizes semantic Arcane themes.
3111
+
3112
+ ### Public surface
3113
+
3114
+ default `ThemeManager`, `loadAndApplyTheme()`; scheme/custom/system APIs and `arcane-theme-change`.
3115
+
3116
+ Exact exports: `default`, `loadAndApplyTheme`.
3117
+
3118
+ ### Availability and normalization
3119
+
3120
+ **Browser/native hybrid.** Theme values/events normalized; storage/native failures mixed. Transport: PreferenceStore, DOM, Arcane.appearance. [Deep protocol details](protocols.md).
3121
+
3122
+ ### Example
3123
+
3124
+ ```javascript
3125
+ import * as module from '/arcane/modules/ThemeManager.js';
3126
+
3127
+ console.log(Object.keys(module));
3128
+ ```
3129
+
3130
+ ## TimeGuard.js
3131
+
3132
+ ### Overview
3133
+
3134
+ Persists and evaluates clock rollback and grace-period state.
3135
+
3136
+ ### Public surface
3137
+
3138
+ default `TimeGuard`; installs `window.timeguard`, emits `time-guard-ready`; clock methods.
3139
+
3140
+ Exact exports: `default`.
3141
+
3142
+ ### Availability and normalization
3143
+
3144
+ **Browser / native WebView.** Time decisions normalized; storage lifecycle mixed. Transport: User + DBOPFS. [Deep protocol details](protocols.md).
3145
+
3146
+ ### Example
3147
+
3148
+ ```javascript
3149
+ import * as module from '/arcane/modules/TimeGuard.js';
3150
+
3151
+ console.log(Object.keys(module));
3152
+ ```
3153
+
3154
+ ## ToolCallRouter.js
3155
+
3156
+ ### Overview
3157
+
3158
+ Parses OpenAI-style complete responses or streamed name-keyed call records,
3159
+ validates each argument record, and dispatches it to an injected handler.
3160
+
3161
+ ### Public surface
3162
+
3163
+ `parseArguments()`, `handleResponse()`, `handleStreamedCalls()`.
3164
+
3165
+ `parseArguments()` accepts JSON text or a plain argument object whose prototype
3166
+ is `Object.prototype` or `null`, requires a nonempty user-facing `message`, and
3167
+ returns the parsed object without cloning, freezing, or reserialization.
3168
+ Missing, blank, null, array, custom-prototype, or otherwise invalid argument
3169
+ records fail with `AI_TOOL_MESSAGE_REQUIRED`. Complete-response handlers run
3170
+ sequentially and return one result or an array; streamed handlers return
3171
+ `Promise.allSettled()` results. A routed call is not settled merely because it
3172
+ was displayed: the conversation owner must still append the exact matching
3173
+ executed, declined, cancelled, or not-executed `role:'tool'` result before the
3174
+ next user turn.
3175
+
3176
+ Exact exports: `handleResponse`, `handleStreamedCalls`, `parseArguments`.
3177
+
3178
+ ### Availability and normalization
3179
+
3180
+ **Cross-host.** Argument records validated; handler results returned or
3181
+ all-settled. Transport: Injected handlers. [Deep protocol details](protocols.md).
3182
+
3183
+ ### Example
3184
+
3185
+ ```javascript
3186
+ import * as module from '/arcane/modules/ToolCallRouter.js';
3187
+
3188
+ console.log(Object.keys(module));
3189
+ ```
3190
+
3191
+ ## uPlot.iife.min.js
3192
+
3193
+ ### Overview
3194
+
3195
+ Vendored uPlot chart constructor and rendering runtime.
3196
+
3197
+ ### Public surface
3198
+
3199
+ No ESM exports; global `uPlot` with data/series/scale/cursor/hook/selection/destroy APIs.
3200
+
3201
+ This is a classic global script and has no ESM exports.
3202
+
3203
+ ### Availability and normalization
3204
+
3205
+ **Browser vendor script.** Vendor-native. Transport: Classic script + canvas/DOM. [Deep protocol details](protocols.md).
3206
+
3207
+ ### Example
3208
+
3209
+ ```html
3210
+ <script src="/arcane/modules/uPlot.iife.min.js"></script>
3211
+ ```
3212
+
3213
+ ## uPlot.LICENSE.txt
3214
+
3215
+ ### Overview
3216
+
3217
+ License companion for the bundled uPlot vendor runtime.
3218
+
3219
+ ### Public surface
3220
+
3221
+ MIT license text.
3222
+
3223
+ ### Availability and normalization
3224
+
3225
+ **Documentation asset.** Not executable. Transport: None. [Deep protocol details](protocols.md).
3226
+
3227
+ ### Example
3228
+
3229
+ ```text
3230
+ /arcane/modules/uPlot.LICENSE.txt
3231
+ ```
3232
+
3233
+ ## uPlot.min.css
3234
+
3235
+ ### Overview
3236
+
3237
+ Bundled uPlot presentation stylesheet.
3238
+
3239
+ ### Public surface
3240
+
3241
+ Load with a stylesheet link before rendering uPlot charts.
3242
+
3243
+ ### Availability and normalization
3244
+
3245
+ **Browser stylesheet.** Presentation only. Transport: CSS. [Deep protocol details](protocols.md).
3246
+
3247
+ ### Example
3248
+
3249
+ ```html
3250
+ <link rel="stylesheet" href="/arcane/modules/uPlot.min.css">
3251
+ ```
3252
+
3253
+ ## WaitForComponent.js
3254
+
3255
+ ### Overview
3256
+
3257
+ Waits for a component property, method, or readiness event with optional error event and bounded timeout.
3258
+
3259
+ ### Public surface
3260
+
3261
+ default `waitForComponent()`.
3262
+
3263
+ Exact exports: `COMPONENT_WAIT_ERROR_CODES`, `COMPONENT_WAIT_REASONS`, and
3264
+ `default`.
3265
+
3266
+ ### Availability and normalization
3267
+
3268
+ **Cross-host EventTarget / browser component.** Normalized coded readiness, error, and timeout results. Transport: EventTarget + timers. [Deep protocol details](protocols.md).
3269
+
3270
+ ### Example
3271
+
3272
+ ```javascript
3273
+ import * as module from '/arcane/modules/WaitForComponent.js';
3274
+
3275
+ console.log(Object.keys(module));
3276
+ ```
3277
+
3278
+ ## YouTubeMedia.js
3279
+
3280
+ ### Overview
3281
+
3282
+ Parses YouTube video/playlist locators and constructs ordinary embed URLs by
3283
+ default, with privacy enhancement only when the caller selects it.
3284
+
3285
+ ### Public surface
3286
+
3287
+ `parseYouTubeMedia()`, `youtubeEmbedUrl()`.
3288
+
3289
+ Exact exports: `parseYouTubeMedia`, `youtubeEmbedUrl`.
3290
+
3291
+ ### Availability and normalization
3292
+
3293
+ **Cross-host.** Bare video IDs and supported URLs normalize to mutable locators;
3294
+ `youtubeEmbedUrl(locator,{privacyEnhanced:false})` is the default and
3295
+ `privacyEnhanced:true` explicitly selects the privacy-enhanced host. Transport:
3296
+ URL construction only. [Deep protocol details](protocols.md).
3297
+
3298
+ ### Example
3299
+
3300
+ ```javascript
3301
+ import * as module from '/arcane/modules/YouTubeMedia.js';
3302
+
3303
+ console.log(Object.keys(module));
3304
+ ```
3305
+
3306
+ ## Entity and component continuations
3307
+
3308
+ - [Runtime entity modules](runtime-entities.md) explains all 14 modules, and [shared entity contracts](core/arcane-entities.md) owns all 29 exports.
3309
+ - [Runtime components](runtime-components.md) owns all 39 HTML-import fragments, methods, slots, and events.
3310
+ - [Arcane Ollama](arcane-ollama.md) expands the raw-versus-normalized behavior of `Ollama.js`.