arcane-os 0.5.16 → 0.5.18
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.
- package/CHANGELOG.md +44 -0
- package/README.md +42 -19
- package/bin/arcane-test.mjs +16 -13
- package/browser-runtime/ai/browser-speech-artifacts.mjs +41 -38
- package/browser-runtime/ai/browser-speech-providers.mjs +53 -46
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +127 -124
- package/browser-runtime/ai/browser-wasm.mjs +6 -3
- package/browser-runtime/ai/browser-wllama-runtime.mjs +26 -23
- package/browser-runtime/ai/model-controller.mjs +94 -91
- package/browser-runtime/ai/speech-worker-client.mjs +12 -9
- package/browser-runtime/ai/speech-worker-runtime.mjs +56 -53
- package/browser-runtime/dependencies/strong-type/index.js +207 -82
- package/browser-runtime/dependencies/strong-type/package.json +15 -6
- package/browser-runtime/dom-event-instrumentation.mjs +24 -20
- package/browser-runtime/event-manager.mjs +111 -108
- package/browser-runtime/speech-text.mjs +35 -0
- package/docs/architecture.md +1 -1
- package/docs/reference/README.md +8 -8
- package/docs/reference/ai/browser-speech.md +230 -16
- package/docs/reference/ai/twin-cloud.md +1 -1
- package/docs/reference/availability-and-normalization.md +42 -1
- package/docs/reference/cli.md +1 -1
- package/docs/reference/core/arcane-ai-contracts.md +1 -1
- package/docs/reference/inventory/package-api.json +60 -4
- package/docs/reference/inventory/runtime-components.json +2 -2
- package/docs/reference/inventory/runtime-modules.json +29 -31
- package/docs/reference/protocols.md +17 -13
- package/docs/reference/runtime-components.md +6 -5
- package/docs/reference/runtime-modules.md +212 -70
- package/docs/reference/sdk-api.md +197 -11
- package/examples/wasm-ai-demo/index.html +1 -0
- package/node_modules/event-pubsub/node_modules/strong-type/README.md +408 -0
- package/node_modules/event-pubsub/node_modules/strong-type/assets/strong-type-header.png +0 -0
- package/node_modules/event-pubsub/node_modules/strong-type/index.js +1151 -0
- package/node_modules/event-pubsub/node_modules/strong-type/licence +21 -0
- package/node_modules/event-pubsub/node_modules/strong-type/node.js +125 -0
- package/node_modules/event-pubsub/node_modules/strong-type/package.json +61 -0
- package/node_modules/strong-type/README.md +42 -24
- package/node_modules/strong-type/benchmark/core.js +324 -0
- package/node_modules/strong-type/index.js +207 -82
- package/node_modules/strong-type/package.json +14 -6
- package/package.json +4 -3
- package/runtime/arcane/components/app-bar.html +5 -2
- package/runtime/arcane/components/assistant-panel.html +5 -2
- package/runtime/arcane/components/chart.html +15 -12
- package/runtime/arcane/components/chat.html +118 -141
- package/runtime/arcane/components/dashboard-config.html +6 -3
- package/runtime/arcane/components/data-view.html +4 -1
- package/runtime/arcane/components/directory-picker.html +5 -2
- package/runtime/arcane/components/document-inspector.html +6 -3
- package/runtime/arcane/components/file-drop.html +5 -2
- package/runtime/arcane/components/file-inspector.html +9 -6
- package/runtime/arcane/components/file-manager.html +16 -13
- package/runtime/arcane/components/local-ai-status.html +5 -2
- package/runtime/arcane/components/markdown-document.html +14 -11
- package/runtime/arcane/components/markdown-editor.html +4 -1
- package/runtime/arcane/components/modal.html +4 -1
- package/runtime/arcane/components/output-panel.html +6 -3
- package/runtime/arcane/components/preferences-form.html +4 -1
- package/runtime/arcane/components/record-timeline.html +8 -5
- package/runtime/arcane/components/relationship-board.html +9 -6
- package/runtime/arcane/components/source-code-viewer.html +12 -9
- package/runtime/arcane/components/source-explanation.html +8 -5
- package/runtime/arcane/components/speech.html +24 -21
- package/runtime/arcane/components/summary-strip.html +4 -1
- package/runtime/arcane/components/task-progress.html +6 -3
- package/runtime/arcane/components/terminal-workspace.html +4 -1
- package/runtime/arcane/components/voice-transcription.html +11 -8
- package/runtime/arcane/components/web-navigator.html +5 -2
- package/runtime/arcane/entities/ApiModelRecord.js +5 -2
- package/runtime/arcane/entities/Calculation.js +5 -2
- package/runtime/arcane/entities/Chat.js +33 -33
- package/runtime/arcane/entities/CommunicationMessage.js +4 -1
- package/runtime/arcane/entities/CommunicationThread.js +4 -1
- package/runtime/arcane/entities/File.js +1 -1
- package/runtime/arcane/entities/Image.js +8 -5
- package/runtime/arcane/entities/IntentEnvelope.js +20 -17
- package/runtime/arcane/entities/Preference.js +9 -6
- package/runtime/arcane/entities/Theme.js +5 -2
- package/runtime/arcane/entities/User.js +11 -11
- package/runtime/arcane/entities/Weather.js +5 -2
- package/runtime/arcane/modules/AI.js +503 -187
- package/runtime/arcane/modules/AIPreferenceRuntime.js +5 -2
- package/runtime/arcane/modules/AIPreferenceTuple.js +9 -6
- package/runtime/arcane/modules/AIProviderRuntime.js +117 -92
- package/runtime/arcane/modules/AIResponseURLPolicy.js +148 -62
- package/runtime/arcane/modules/AIRuntimeState.js +29 -26
- package/runtime/arcane/modules/AnsiText.js +4 -1
- package/runtime/arcane/modules/ApiModelDatabase.js +22 -19
- package/runtime/arcane/modules/AppDataScope.js +8 -5
- package/runtime/arcane/modules/ArcaneCommunicationBridge.js +4 -1
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +8 -5
- package/runtime/arcane/modules/ArcaneNetworkPolicy.js +18 -15
- package/runtime/arcane/modules/AsyncBoundary.js +13 -10
- package/runtime/arcane/modules/BrowserTestSuite.js +19 -16
- package/runtime/arcane/modules/CalculatorEngine.js +5 -2
- package/runtime/arcane/modules/ChatRecords.js +18 -15
- package/runtime/arcane/modules/CommunicationAppController.js +9 -6
- package/runtime/arcane/modules/CommunicationHub.js +9 -6
- package/runtime/arcane/modules/CommunicationPreferences.js +4 -1
- package/runtime/arcane/modules/CommunicationProviderRegistry.js +4 -1
- package/runtime/arcane/modules/ComponentContracts.js +56 -53
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +30 -27
- package/runtime/arcane/modules/ConversationActionItems.js +15 -12
- package/runtime/arcane/modules/ConversationClosingReport.js +11 -8
- package/runtime/arcane/modules/ConversationTimebox.js +28 -25
- package/runtime/arcane/modules/CoreLocalModelCatalog.js +17 -14
- package/runtime/arcane/modules/DBLS.js +7 -4
- package/runtime/arcane/modules/DBOPFS.js +7 -7
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +34 -31
- package/runtime/arcane/modules/DevelopmentWorkspace.js +4 -1
- package/runtime/arcane/modules/DirectoryPicker.js +8 -5
- package/runtime/arcane/modules/DocumentLexicalSearch.js +11 -8
- package/runtime/arcane/modules/DocumentNavigation.js +7 -4
- package/runtime/arcane/modules/Errors.js +28 -25
- package/runtime/arcane/modules/HTMLImport.js +7 -4
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +15 -12
- package/runtime/arcane/modules/LocalAIReadiness.js +21 -18
- package/runtime/arcane/modules/LocalAIReadinessController.js +6 -3
- package/runtime/arcane/modules/MD.js +1 -1
- package/runtime/arcane/modules/Mail.js +46 -43
- package/runtime/arcane/modules/MailOutbox.mjs +48 -45
- package/runtime/arcane/modules/MailTransport.mjs +29 -26
- package/runtime/arcane/modules/MarkdownSpeech.js +1 -50
- package/runtime/arcane/modules/MemoryRecords.js +7 -4
- package/runtime/arcane/modules/MessageAdvisory.js +6 -3
- package/runtime/arcane/modules/ModelDefinition.js +7 -4
- package/runtime/arcane/modules/Ollama.js +6 -3
- package/runtime/arcane/modules/OllamaModelIdentifier.js +4 -1
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +18 -15
- package/runtime/arcane/modules/PersistentAIChatSession.js +33 -30
- package/runtime/arcane/modules/PreferenceStore.js +20 -17
- package/runtime/arcane/modules/PreparedSpeech.js +485 -0
- package/runtime/arcane/modules/Questionnaire.js +6 -3
- package/runtime/arcane/modules/RecordLinkIndex.js +4 -1
- package/runtime/arcane/modules/RecordPassageIndex.js +9 -6
- package/runtime/arcane/modules/RecordReviewStore.js +12 -9
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +4 -1
- package/runtime/arcane/modules/ScopedOPFSCache.js +6 -3
- package/runtime/arcane/modules/ScreenCapture.js +20 -17
- package/runtime/arcane/modules/SpeechPlayback.js +61 -28
- package/runtime/arcane/modules/StaticDocumentCatalog.js +33 -30
- package/runtime/arcane/modules/SystemAppearance.js +5 -2
- package/runtime/arcane/modules/SystemToolRegistry.js +6 -3
- package/runtime/arcane/modules/TerminalClient.js +14 -11
- package/runtime/arcane/modules/TerminalCommandRegistry.js +4 -1
- package/runtime/arcane/modules/ThemeBootstrap.js +9 -6
- package/runtime/arcane/modules/ThemeManager.js +5 -2
- package/runtime/arcane/modules/TimeGuard.js +1 -1
- package/runtime/arcane/modules/ToolCallRouter.js +11 -8
- package/runtime/arcane/modules/WaitForComponent.js +19 -16
- package/runtime/arcane/modules/YouTubeMedia.js +4 -1
- package/runtime/strong-type/index.js +1276 -352
- package/runtime/strong-type/package.json +69 -45
- package/src/app-descriptor.mjs +17 -14
- package/src/application-tests.mjs +4 -1
- package/src/cli/main.mjs +8 -5
- package/src/constants.mjs +4 -1
- package/src/dev-server.mjs +8 -5
- package/src/doctor.mjs +5 -2
- package/src/dom-event-instrumentation.mjs +24 -20
- package/src/errors.mjs +7 -3
- package/src/event-manager.mjs +111 -108
- package/src/event-queue.mjs +8 -5
- package/src/events.mjs +12 -9
- package/src/import-map.mjs +36 -27
- package/src/installed-sdk-runtime.mjs +4 -1
- package/src/integrated-provider-loader.mjs +9 -6
- package/src/mail-credentials.mjs +16 -13
- package/src/mail-server.mjs +53 -50
- package/src/mail.mjs +18 -15
- package/src/native-plan.mjs +12 -9
- package/src/native-provider-loader.mjs +7 -4
- package/src/packager/core.mjs +18 -15
- package/src/process.mjs +6 -3
- package/src/release-bundle.mjs +14 -11
- package/src/runtime.mjs +4 -1
- package/src/scaffold.mjs +9 -6
- package/src/sdk-browser-runtime.mjs +4 -1
- package/src/source-server.mjs +17 -14
- package/src/targets/index.mjs +5 -2
- package/src/templates/workspace-template.mjs +13 -6
- package/src/testing-loader.mjs +7 -4
- package/src/testing.mjs +10 -7
- package/src/toolchain.mjs +13 -10
- package/src/update-check.mjs +9 -6
- package/src/workspace-operation-lock.mjs +14 -11
- package/src/workspace-runtime.mjs +4 -1
- package/src/workspace.mjs +17 -14
- package/runtime/arcane/modules/AIResponseLength.js +0 -32
|
@@ -4,6 +4,13 @@ Every file shipped under `runtime/arcane/modules/` appears here. Start with the
|
|
|
4
4
|
|
|
5
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
6
|
|
|
7
|
+
Applications own response-detail preferences, their saved values, and any
|
|
8
|
+
verbosity instruction appended to the system prompt. The former
|
|
9
|
+
`AIResponseLength.js` module and its exports have been removed. Before adopting
|
|
10
|
+
this source change, consumers must normalize preferences in their application
|
|
11
|
+
and pass their complete system prompt directly instead of calling the former
|
|
12
|
+
no-op `applyAIResponseLength()` helper. Existing saved preferences are unchanged.
|
|
13
|
+
|
|
7
14
|
## Availability shorthand
|
|
8
15
|
|
|
9
16
|
- **Cross-host** means in-process logic built from standard JavaScript/Web APIs.
|
|
@@ -44,8 +51,7 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
44
51
|
| [`AIPreferenceRuntime.js`](#aipreferenceruntimejs) | esm | Applies and reads non-persistent per-user AI preference overrides. | Cross-host | Normalized six-slot preference state. |
|
|
45
52
|
| [`AIPreferenceTuple.js`](#aipreferencetuplejs) | esm | Normalizes and compares the six provider/model preference slots. | Cross-host | Fully normalized frozen tuple. |
|
|
46
53
|
| [`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
|
-
| [`
|
|
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. |
|
|
54
|
+
| [`AIResponseURLPolicy.js`](#airesponseurlpolicyjs) | esm | Extracts and audits links from AI Markdown, rendered HTML, CSS, srcset, bare URLs, and email text. | Cross-host | Mutable audit with exact link comparison after renderer-level decoding. |
|
|
49
55
|
| [`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
56
|
| [`AnsiText.js`](#ansitextjs) | esm | Parses terminal ANSI sequences into display spans or strips them to plain text. | Cross-host | Normalized text/span output. |
|
|
51
57
|
| [`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. |
|
|
@@ -100,6 +106,7 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
100
106
|
| [`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. |
|
|
101
107
|
| [`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. |
|
|
102
108
|
| [`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. |
|
|
109
|
+
| [`PreparedSpeech.js`](#preparedspeechjs) | esm | Owns detached ordered preparation, semantic audio reuse, and per-caller cancellation behind AI.prepareTTS. | Browser / native WebView with injected synthesis and optional DBOPFS | Complete original inputs, ordered audio metadata, durable reuse, and observable preparation results. |
|
|
103
110
|
| [`QRCode.min.js`](#qrcodeminjs) | classic-script | Vendored QRCode generator for DOM, canvas, SVG, and image output. | Browser vendor script | Vendor-native. |
|
|
104
111
|
| [`Questionnaire.js`](#questionnairejs) | esm | Evaluates whether a one-time questionnaire prompt is due without performing the prompt. | Cross-host | Normalized conservative boolean. |
|
|
105
112
|
| [`RecordLinkIndex.js`](#recordlinkindexjs) | esm | Parses record links and builds their normalized index. | Cross-host | Fully normalized. |
|
|
@@ -109,7 +116,7 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
109
116
|
| [`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`. |
|
|
110
117
|
| [`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. |
|
|
111
118
|
| [`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. |
|
|
112
|
-
| [`SpeechPlayback.js`](#speechplaybackjs) | esm |
|
|
119
|
+
| [`SpeechPlayback.js`](#speechplaybackjs) | esm | Admits complete speech segments to a capacity-advertising provider immediately, retains serialized native/custom lookahead, and plays every result in exact indexed order. | Browser + native bridge | Stored part text stays exact; the outbound speech-input copy receives automatic formatting-mark cleanup; provider/media failures remain mixed. |
|
|
113
120
|
| [`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. |
|
|
114
121
|
| [`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. |
|
|
115
122
|
| [`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. |
|
|
@@ -144,6 +151,8 @@ default `AI`; read-only `providerRuntime`, `browserSpeechConfiguration`, and
|
|
|
144
151
|
`streamRequest()`, `streamMessage()`, `fetchRequest()`, `fetch()`,
|
|
145
152
|
read-only `ttsSegmentation`, `configureTTSSegmentation()`,
|
|
146
153
|
`streamTTS(text='',end=false,options={})`,
|
|
154
|
+
`prepareTTS({parts,storage,identity,signal,onState})`,
|
|
155
|
+
`playPreparedTTS(prepared,{signal,onState})`,
|
|
147
156
|
`finishTTS()`, `fetchTTS()`, `fetchSTT()`, `stopAudio()`, `resumeAudio()`,
|
|
148
157
|
`playAudio()`; consumes `user-entity-loaded` and `arcane-ollama-ready`,
|
|
149
158
|
installs `window.ai`, and emits `ai-ready` and `ai-tts-failure`.
|
|
@@ -263,7 +272,7 @@ reports `requestedDevice`, `selectedDevice`, `maxConcurrentRequests`, and
|
|
|
263
272
|
WASM fallback after a successful load. Calling `status()` without options keeps
|
|
264
273
|
the existing sticky lifecycle snapshot and does not inspect provider execution.
|
|
265
274
|
Provider inspection failures are surfaced to the caller.
|
|
266
|
-
`fetchTTS({model,voice,input,responseFormat,speed},signal)` accepts the public
|
|
275
|
+
`fetchTTS({model,voice,input,responseFormat,speed},signal,preparation={})` accepts the public
|
|
267
276
|
provider-neutral synthesis shape, requires any explicit model to match the
|
|
268
277
|
selected route, and fills an omitted voice only from the selected model
|
|
269
278
|
catalog's `defaultVoice`. An omitted response format preserves the instance's
|
|
@@ -273,9 +282,14 @@ the setting is the instance's `opus` default and the model rejects it, the catal
|
|
|
273
282
|
`speech.defaultResponseFormat` is used, while any other unsupported setting is
|
|
274
283
|
rejected. It propagates the caller-owned signal and returns a playable `Blob`;
|
|
275
284
|
it does not independently choose a provider, cloud fallback, model, runtime, or
|
|
276
|
-
voice policy for the application.
|
|
285
|
+
voice policy for the application. Every call removes repeated same formatting
|
|
286
|
+
marks from a cloned outbound input before delegation; the caller's payload stays
|
|
287
|
+
unchanged. The third `preparation` argument is reserved for SDK-internal
|
|
288
|
+
delegation, where `{speechInputPrepared:true}` prevents a second cleanup pass;
|
|
289
|
+
applications omit it. `streamTTS(text='',end=false,options={})` and
|
|
277
290
|
`finishTTS()` use this same request boundary. The third-argument options below
|
|
278
|
-
are available in SDK `0.5.12
|
|
291
|
+
are available in SDK `0.5.12`. The `textFormat` compatibility extra added in
|
|
292
|
+
SDK `0.5.16` is ignored beginning in `0.5.17`:
|
|
279
293
|
|
|
280
294
|
| Field | Default | Meaning |
|
|
281
295
|
| --- | --- | --- |
|
|
@@ -283,24 +297,23 @@ are available in SDK `0.5.12`, with `textFormat` added in SDK `0.5.16`:
|
|
|
283
297
|
| `speed` | Current `ai.voiceSpeed` | A supplied positive speed is captured for those segments and forwarded to `fetchTTS()`. It does not change `ai.voiceSpeed`. |
|
|
284
298
|
| `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. |
|
|
285
299
|
| `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. |
|
|
286
|
-
| `textFormat` |
|
|
300
|
+
| `textFormat` | Ignored compatibility extra | Repeated same formatting marks are removed automatically from every TTS call. This value no longer selects or disables cleanup. |
|
|
287
301
|
|
|
288
302
|
The voice and speed use the existing `fetchTTS()` validation and error path.
|
|
289
|
-
|
|
290
|
-
|
|
303
|
+
The automatic cleanup changes only the outbound speech-input copy; displayed,
|
|
304
|
+
stored, model, and caller-owned content remains exact. It is a narrow
|
|
291
305
|
formatting-mark filter, not a full Markdown parser: links, code contents, list
|
|
292
|
-
text, and other characters remain literal.
|
|
293
|
-
the next character so a repeated run split
|
|
294
|
-
Ordinary prose streams immediately.
|
|
295
|
-
calls, and `stopAudio()` clear
|
|
296
|
-
|
|
297
|
-
the next text. `fetchTTS()` retains its exact-text contract.
|
|
306
|
+
text, single marks, ordinary punctuation, and other characters remain literal.
|
|
307
|
+
A trailing candidate mark waits for the next character so a repeated run split
|
|
308
|
+
across chunks is still omitted. Ordinary prose streams immediately.
|
|
309
|
+
`end:true`, `finishTTS()`, muted terminal calls, and `stopAudio()` clear pending
|
|
310
|
+
formatting state. `textFormat` is not an opt-out.
|
|
298
311
|
|
|
299
312
|
Voice, speed, pause, and playback overrides belong to the segments
|
|
300
313
|
extracted in that invocation, including any text buffered by an earlier call.
|
|
301
314
|
Those overrides are not retained with an unfinished `end:false` remainder; a
|
|
302
315
|
later call supplies its own options, and `finishTTS()` uses their defaults
|
|
303
|
-
while
|
|
316
|
+
while flushing any pending formatting mark. Use `end:true`
|
|
304
317
|
for a complete passage. A call extracting no segments resolves
|
|
305
318
|
`true` without waiting for earlier jobs; `finishTTS()` remains a preparation
|
|
306
319
|
flush, not a queue-wide playback barrier. A muted call resolves `false`.
|
|
@@ -308,13 +321,63 @@ flush, not a queue-wide playback barrier. A muted call resolves `false`.
|
|
|
308
321
|
Playback completion stays pending while the browser waits for an audio-unlock
|
|
309
322
|
gesture or a recoverable resume attempt. If resuming a closed `AudioContext`
|
|
310
323
|
fails, the affected jobs terminate and their playback results settle `false`.
|
|
311
|
-
`stopAudio()` cancels
|
|
312
|
-
by this AI instance and settles pending playback promises `false
|
|
324
|
+
`stopAudio()` cancels streamed speech and prepared playback owned
|
|
325
|
+
by this AI instance and settles pending playback promises `false`; detached
|
|
326
|
+
preparation retains its own cancellation lifetime. A trailing
|
|
313
327
|
pause delays the next queued audio; the preceding promise resolves when its
|
|
314
328
|
last audio buffer ends, without waiting out that pause. Completion describes
|
|
315
329
|
the playback lifecycle, not proof that a listener heard the sound. See the
|
|
316
330
|
[complete-passage example](ai/browser-speech.md#queue-complete-passages-and-wait-for-playback).
|
|
317
331
|
|
|
332
|
+
`prepareTTS({parts,storage,identity,signal,onState})` returns an immediate
|
|
333
|
+
`{segments,state,ready,getAudio(index),cancel()}` handle for detached complete
|
|
334
|
+
speech preparation. Parts are strings or `{input,voice?,speed?,pauseAfterMs?}`
|
|
335
|
+
records. It retains the full source for semantic matching, snapshots the
|
|
336
|
+
selected speech configuration and segmentation, and applies automatic
|
|
337
|
+
formatting cleanup once to the speech copy. Generation uses the existing
|
|
338
|
+
bounded provider queue without adding playback. Optional
|
|
339
|
+
`storage:{db,table,key}` saves complete audio files and their MIME metadata in
|
|
340
|
+
the caller's ready DBOPFS instance; the separate JSON-compatible `identity`
|
|
341
|
+
adds application-owned semantic context. Reuse compares complete inputs rather
|
|
342
|
+
than an SDK version alone.
|
|
343
|
+
|
|
344
|
+
`state` is `queued`, `preparing`, `ready`, `error`, or `cancelled`.
|
|
345
|
+
`onState({state,completed,total,segments,error})` synchronously observes
|
|
346
|
+
preparation progress. `ready` resolves the complete record after every segment
|
|
347
|
+
is ready and, when storage is selected, durably saved. `getAudio(index)` waits
|
|
348
|
+
for the corresponding ordered segment and returns its complete `Blob` with
|
|
349
|
+
the retained MIME type. Preparation failure rejects; cancellation rejects as
|
|
350
|
+
`AbortError` and preserves successfully stored segments. Matching pending
|
|
351
|
+
requests share synthesis only on the same AI instance and storage group;
|
|
352
|
+
cancelling one handle does not cancel another active matching caller.
|
|
353
|
+
Preparation cancellation prevents later synthesis, but an already-started
|
|
354
|
+
shared provider load/unmute has no per-preparation signal and may finish.
|
|
355
|
+
|
|
356
|
+
`playPreparedTTS(prepared,{signal,onState})` can attach immediately. Its returned
|
|
357
|
+
`{state,error,finished,pause(),resume(),stop()}` handle schedules segments in
|
|
358
|
+
their original order using the existing AI audio clock. `finished` resolves `true` after
|
|
359
|
+
natural completion and `false` after stop, cancellation, or failure; genuine
|
|
360
|
+
failures also use the existing complete diagnostics and `ai-tts-failure` event.
|
|
361
|
+
Part pauses separate adjacent audio; the final trailing pause does not delay
|
|
362
|
+
`finished` after the final audio buffer ends. State/error getters and the
|
|
363
|
+
optional synchronous `onState({state,error})` callback expose `waiting`,
|
|
364
|
+
`waiting-for-gesture`, `scheduled`, `paused`, `complete`, `stopped`, or `error`.
|
|
365
|
+
Use `waiting-for-gesture` for audio-unlock UI; a `false` result from `resume()`
|
|
366
|
+
alone is not a first-segment-ready signal.
|
|
367
|
+
Pause and resume are asynchronous boolean controls scoped to that handle's
|
|
368
|
+
audio context; stop is synchronous. Playback completion and these controls do
|
|
369
|
+
not cancel independent preparation. One AI has one playback lane: attaching
|
|
370
|
+
prepared playback replaces its preceding streamed or prepared audio, and
|
|
371
|
+
`streamTTS()` interrupts active prepared playback. `stopAudio()` stops all
|
|
372
|
+
this AI's playback but keeps detached preparation running; `setSpeechMuted(true)` also cancels
|
|
373
|
+
provider TTS work and unloads it. Replacing the selected speech configuration
|
|
374
|
+
cancels missing generation for that earlier selection. Completed stored audio
|
|
375
|
+
remains in application storage.
|
|
376
|
+
Fully stored replay enables playback without loading the selected speech
|
|
377
|
+
model even when the AI starts muted. Missing audio alone requests the shared
|
|
378
|
+
TTS readiness path. See [prepared narration](ai/browser-speech.md#prepare-narration-once-and-replay-stored-audio)
|
|
379
|
+
for full record shapes, storage ownership, and a complete example.
|
|
380
|
+
|
|
318
381
|
Streaming speech retains sentence
|
|
319
382
|
segmentation by default. `configureTTSSegmentation({punctuation,wordCadence})`
|
|
320
383
|
accepts `punctuation:'sentence'|'any'|'none'` and a `wordCadence` that is either
|
|
@@ -324,8 +387,9 @@ commas, and hyphens remain inside a segment when they join Unicode letters or
|
|
|
324
387
|
numbers. A potentially joining mark at the current end of an incremental stream
|
|
325
388
|
waits for the next character or terminal flush before the boundary is decided;
|
|
326
389
|
`wordCadence` completes one after that many whole words. The earliest available
|
|
327
|
-
boundary wins. Segmentation preserves every character
|
|
328
|
-
and whitespace. Every completed segment
|
|
390
|
+
boundary wins. Segmentation preserves every character of the already prepared
|
|
391
|
+
speech text, including punctuation and whitespace. Every completed segment
|
|
392
|
+
enters synthesis immediately; provider
|
|
329
393
|
capacity supplies FIFO backpressure while allowing bounded TTS work to overlap.
|
|
330
394
|
A later segment may finish synthesis first, but playback schedules only the
|
|
331
395
|
contiguous ready prefix in original order. Decoded buffers with known duration
|
|
@@ -662,9 +726,11 @@ The singleton exposes read-only `protocol`, `configured`, and `speechMuted`;
|
|
|
662
726
|
`status(role=null,options={})`; `catalog(role)`;
|
|
663
727
|
`inspect(role,options={})`; `start(options)`; `load(role,options={})`;
|
|
664
728
|
`unload(role,options={})`; `dispose(role,options={})`;
|
|
665
|
-
`disposeAll(options={})`; `cancel(role)`;
|
|
729
|
+
`disposeAll(options={})`; `cancel(role)`;
|
|
730
|
+
`request(role,options={},preparation={})`;
|
|
666
731
|
`chat(payload,options={})`; `stream(payload,options={})`;
|
|
667
|
-
`transcribe(payload,options={})`;
|
|
732
|
+
`transcribe(payload,options={})`;
|
|
733
|
+
`synthesize(payload,options={},preparation={})`; and
|
|
668
734
|
`setSpeechMuted(muted)`. Provider payloads must be data-only; callbacks,
|
|
669
735
|
accessors, symbols, and cycles are rejected at the provider boundary.
|
|
670
736
|
|
|
@@ -680,6 +746,14 @@ records are the closed `{llm,stt,tts}`, `{stt,tts}`, or
|
|
|
680
746
|
`{providers,routes,expectedProviders}` shapes described below.
|
|
681
747
|
`configureFromTuple()` accepts exactly six provider/model preference entries.
|
|
682
748
|
|
|
749
|
+
Every direct TTS `request()` or `synthesize()` call removes repeated same
|
|
750
|
+
formatting marks from a cloned outbound payload's `input` or `text` field. The
|
|
751
|
+
caller's payload and request records remain unchanged. The optional
|
|
752
|
+
`preparation` argument is reserved for SDK-owned delegation;
|
|
753
|
+
`{speechInputPrepared:true}` prevents a second pass after another SDK speech
|
|
754
|
+
boundary has already cleaned the copy. Applications omit that argument. LLM
|
|
755
|
+
and STT payloads are unaffected.
|
|
756
|
+
|
|
683
757
|
`register()` returns the provider's single unregister closure; caller-
|
|
684
758
|
registered providers remain caller-owned. The high-level
|
|
685
759
|
`AI.configureBrowserSpeech()` boundary is different: AI constructs, registers,
|
|
@@ -794,35 +868,6 @@ const runtime = getAIProviderRuntime();
|
|
|
794
868
|
console.log(runtime.protocol, runtime.status());
|
|
795
869
|
```
|
|
796
870
|
|
|
797
|
-
## AIResponseLength.js
|
|
798
|
-
|
|
799
|
-
### Overview
|
|
800
|
-
|
|
801
|
-
Normalizes current low/medium/high response-preference selectors while
|
|
802
|
-
preserving complete prompts unchanged.
|
|
803
|
-
|
|
804
|
-
### Public surface
|
|
805
|
-
|
|
806
|
-
Response-preference constants plus `normalizeAIResponseLength()`,
|
|
807
|
-
`aiResponseLengthInstruction()`, and `applyAIResponseLength()`. Every option is
|
|
808
|
-
labeled `Complete`, the instruction helper returns an empty string, and the
|
|
809
|
-
application helper returns its complete `systemPrompt` unchanged.
|
|
810
|
-
|
|
811
|
-
Exact exports: `AI_RESPONSE_LENGTH_DEFAULT`, `AI_RESPONSE_LENGTH_OPTIONS`, `aiResponseLengthInstruction`, `applyAIResponseLength`, `normalizeAIResponseLength`.
|
|
812
|
-
|
|
813
|
-
### Availability and normalization
|
|
814
|
-
|
|
815
|
-
**Cross-host.** Current selector normalization with no prompt transformation.
|
|
816
|
-
Transport: In-process only. [Deep protocol details](protocols.md).
|
|
817
|
-
|
|
818
|
-
### Example
|
|
819
|
-
|
|
820
|
-
```javascript
|
|
821
|
-
import * as module from '/arcane/modules/AIResponseLength.js';
|
|
822
|
-
|
|
823
|
-
console.log(Object.keys(module));
|
|
824
|
-
```
|
|
825
|
-
|
|
826
871
|
## AIResponseURLPolicy.js
|
|
827
872
|
|
|
828
873
|
### Overview
|
|
@@ -837,7 +882,19 @@ Exact exports: `auditAIResponseLinks`, `decodeHTMLCharacterReferences`, `extract
|
|
|
837
882
|
|
|
838
883
|
### Availability and normalization
|
|
839
884
|
|
|
840
|
-
**Cross-host.**
|
|
885
|
+
**Cross-host.** Returns a mutable `{ok, links, unsupportedLinks, allowedLinks}`
|
|
886
|
+
audit. Browsers use detached native HTML elements to parse rendered markup and
|
|
887
|
+
decode character references. Hosts without a document retain lexical extraction
|
|
888
|
+
and the existing limited entity decoder. Rendered values are decoded only once.
|
|
889
|
+
Markdown destinations, CSS URLs, srcset candidates, and authored source positions
|
|
890
|
+
remain part of the audit; DOM-only attribute links use document order after
|
|
891
|
+
authored links because the DOM does not expose source offsets.
|
|
892
|
+
|
|
893
|
+
Comparison uses exact values after entity and Markdown escape decoding. URI
|
|
894
|
+
encoding, decoding, or URL canonicalization would change those values and is
|
|
895
|
+
not applied. The audit neither changes the response content nor fetches or
|
|
896
|
+
navigates to links. Transport: In-process; bundled Marked parser.
|
|
897
|
+
[Deep protocol details](protocols.md).
|
|
841
898
|
|
|
842
899
|
### Example
|
|
843
900
|
|
|
@@ -2261,11 +2318,12 @@ console.log(Object.keys(module));
|
|
|
2261
2318
|
|
|
2262
2319
|
### Overview
|
|
2263
2320
|
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2321
|
+
Re-exports the streaming `MarkdownSpeech` filter from the shared
|
|
2322
|
+
`arcane-os/speech-text` package entrypoint. The filter removes repeated runs of
|
|
2323
|
+
`*`, `#`, `_`, backtick, and `~` before speech segmentation, including runs
|
|
2324
|
+
arriving across separate chunks. Single marks, ellipses, quoted sentence
|
|
2325
|
+
endings, whitespace, and all other text remain literal. It neither interprets
|
|
2326
|
+
links nor changes language or voice.
|
|
2269
2327
|
|
|
2270
2328
|
### Public surface
|
|
2271
2329
|
|
|
@@ -2275,7 +2333,8 @@ Exact exports: `MarkdownSpeech`.
|
|
|
2275
2333
|
|
|
2276
2334
|
### Availability and normalization
|
|
2277
2335
|
|
|
2278
|
-
**Cross-host.**
|
|
2336
|
+
**Cross-host.** The runtime projection and public package entrypoint share the
|
|
2337
|
+
same implementation. `append()` returns only
|
|
2279
2338
|
the newly available narration. Only a trailing candidate marker and whether
|
|
2280
2339
|
it repeats are retained; ordinary text is emitted immediately. Terminal
|
|
2281
2340
|
`append(text,true)` flushes a single pending mark and resets state. `reset()`
|
|
@@ -2673,6 +2732,54 @@ import * as module from '/arcane/modules/PreferenceStore.js';
|
|
|
2673
2732
|
console.log(Object.keys(module));
|
|
2674
2733
|
```
|
|
2675
2734
|
|
|
2735
|
+
## PreparedSpeech.js
|
|
2736
|
+
|
|
2737
|
+
### Overview
|
|
2738
|
+
|
|
2739
|
+
Shared preparation mechanism used by `AI.prepareTTS()`. It owns ordered
|
|
2740
|
+
generation admission, same-owner request sharing, complete audio storage and
|
|
2741
|
+
semantic reuse, and each caller's preparation lifetime. It does not construct
|
|
2742
|
+
an audio context, play speech, or select application content.
|
|
2743
|
+
|
|
2744
|
+
### Public surface
|
|
2745
|
+
|
|
2746
|
+
Named `prepareSpeech({owner,parts,originalParts=parts,selection=null,
|
|
2747
|
+
segmentation=null,storage=null,identity=null,signal=null,onState,synthesize})`.
|
|
2748
|
+
The owning AI supplies already segmented speech parts, complete original parts,
|
|
2749
|
+
its selection snapshot, and its synthesis callback. The returned handle is
|
|
2750
|
+
`{segments,state,ready,getAudio(index),cancel()}`. Applications use
|
|
2751
|
+
`AI.prepareTTS()` and `AI.playPreparedTTS()` so the existing AI owner retains
|
|
2752
|
+
automatic formatting cleanup, segmentation, provider readiness/capacity, and
|
|
2753
|
+
ordered playback. See the [complete preparation contract](ai/browser-speech.md#prepare-narration-once-and-replay-stored-audio).
|
|
2754
|
+
|
|
2755
|
+
`storage:{db,table,key}` is optional; the ready DBOPFS instance supplies
|
|
2756
|
+
`get`, `set`, `readFile`, and `writeFile`. JSON-compatible semantic inputs stay
|
|
2757
|
+
complete in the version-1 manifest. Raw audio is persisted separately and its
|
|
2758
|
+
MIME type is retained in metadata. Storage mutation serializes by database,
|
|
2759
|
+
table, and key within the realm. Synthesis sharing is scoped to the same owner
|
|
2760
|
+
and matching semantic inputs/storage; playback remains outside this module.
|
|
2761
|
+
|
|
2762
|
+
Exact exports: `prepareSpeech`.
|
|
2763
|
+
|
|
2764
|
+
### Availability and normalization
|
|
2765
|
+
|
|
2766
|
+
**Browser or native WebView with Blob, AbortController, an injected synthesis
|
|
2767
|
+
callback, and optional ready DBOPFS.** Import creates no provider or
|
|
2768
|
+
playback. Calling the preparation function starts owned asynchronous work.
|
|
2769
|
+
`ready` rejects complete synthesis/storage failures or `AbortError` after
|
|
2770
|
+
cancellation; successful audio remains available for reuse. Malformed part,
|
|
2771
|
+
storage, or semantic metadata inputs throw `TypeError`; an invalid segment
|
|
2772
|
+
index rejects with `RangeError`. No Core capability is selected here.
|
|
2773
|
+
|
|
2774
|
+
### Example
|
|
2775
|
+
|
|
2776
|
+
```javascript
|
|
2777
|
+
import {prepareSpeech} from '/arcane/modules/PreparedSpeech.js';
|
|
2778
|
+
|
|
2779
|
+
// Applications use AI.prepareTTS; this import only exposes the SDK mechanism.
|
|
2780
|
+
console.log(typeof prepareSpeech); // function
|
|
2781
|
+
```
|
|
2782
|
+
|
|
2676
2783
|
## QRCode.min.js
|
|
2677
2784
|
|
|
2678
2785
|
### Overview
|
|
@@ -2899,15 +3006,17 @@ console.log(Object.keys(module));
|
|
|
2899
3006
|
|
|
2900
3007
|
Preserves exact nonblank text, admits complete speech segments according to the
|
|
2901
3008
|
selected client's advertised capacity, and plays indexed HTML audio in exact
|
|
2902
|
-
input order.
|
|
3009
|
+
input order. Stored parts remain exact; only each outbound synthesis payload
|
|
3010
|
+
copy receives automatic formatting-mark cleanup.
|
|
2903
3011
|
|
|
2904
3012
|
### Public surface
|
|
2905
3013
|
|
|
2906
|
-
`SpeechPlayback` class/default,
|
|
2907
|
-
`splitSpeechText()`,
|
|
3014
|
+
`SpeechPlayback` class/default, the shared voice compatibility catalogs,
|
|
3015
|
+
`SPEECH_PLAYBACK_STATE_EVENT`, `splitSpeechText()`, the optional constructor
|
|
3016
|
+
state callback, and playback lifecycle APIs.
|
|
2908
3017
|
|
|
2909
|
-
Exact exports: `SPEECH_PLAYBACK_STATE_EVENT`, `
|
|
2910
|
-
`splitSpeechText`.
|
|
3018
|
+
Exact exports: `SPEECH_PLAYBACK_STATE_EVENT`, `SPEECH_VOICE_ALIASES`,
|
|
3019
|
+
`SPEECH_VOICE_OPTIONS`, `SpeechPlayback`, `default`, and `splitSpeechText`.
|
|
2911
3020
|
|
|
2912
3021
|
```text
|
|
2913
3022
|
new SpeechPlayback({
|
|
@@ -2917,6 +3026,7 @@ new SpeechPlayback({
|
|
|
2917
3026
|
voice=null,
|
|
2918
3027
|
responseFormat=null,
|
|
2919
3028
|
speed=1,
|
|
3029
|
+
onState=()=>{},
|
|
2920
3030
|
createObjectURL,
|
|
2921
3031
|
revokeObjectURL,
|
|
2922
3032
|
delay,
|
|
@@ -2925,17 +3035,28 @@ new SpeechPlayback({
|
|
|
2925
3035
|
```
|
|
2926
3036
|
|
|
2927
3037
|
`speech` must expose either `fetchTTS(payload, signal)` or
|
|
2928
|
-
`synthesize(payload, {signal})`. `
|
|
3038
|
+
`synthesize(payload, {signal})`. `SpeechPlayback` also supplies a third
|
|
3039
|
+
SDK-internal preparation object; existing two-argument clients may ignore it.
|
|
3040
|
+
`prepare({key,parts,model,voice,responseFormat,
|
|
2929
3041
|
speed,autoplay=true})` uses only caller-supplied model, voice, and response-format
|
|
2930
3042
|
values; those three omitted values remain omitted so the selected AI/model
|
|
2931
3043
|
catalog may provide its documented defaults. Speed defaults to `1`, is normalized
|
|
2932
|
-
as a positive number, and is always sent.
|
|
2933
|
-
|
|
3044
|
+
as a positive number, and is always sent. `SPEECH_VOICE_OPTIONS` is the ordered
|
|
3045
|
+
mutable compatibility array `{value,label}` for `alloy`, `ash`, `ballad`,
|
|
3046
|
+
`coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, and `shimmer`;
|
|
3047
|
+
`SPEECH_VOICE_ALIASES` is the mutable `Set` of those values. The class does not
|
|
3048
|
+
select either catalog or promise that a selected provider supports its values.
|
|
3049
|
+
There is no hard-coded model, response format, voice, or cloud/browser fallback.
|
|
2934
3050
|
`splitSpeechText(value)` uses trimming only to detect blank input, then returns
|
|
2935
3051
|
the caller's exact string in one mutable array without trimming, splitting, or
|
|
2936
3052
|
freezing it. `prepare()` likewise preserves each nonblank part's exact `input`
|
|
2937
3053
|
string while normalizing its other playback fields into a new mutable record.
|
|
2938
|
-
|
|
3054
|
+
At synthesis time, `requestSpeech()` copies that record, removes repeated same
|
|
3055
|
+
formatting marks from only the outbound `input`, and delegates with the
|
|
3056
|
+
SDK-internal `{speechInputPrepared:true}` argument so downstream SDK boundaries
|
|
3057
|
+
do not apply the non-idempotent filter again. Original part objects, stored
|
|
3058
|
+
parts, displayed text, and all non-input payload fields remain unchanged. The
|
|
3059
|
+
class applies no part-count, character-count, pause, or input upper cap.
|
|
2939
3060
|
|
|
2940
3061
|
### Admission and playback order
|
|
2941
3062
|
|
|
@@ -2961,8 +3082,13 @@ Every preparation owns an operation ID and one AbortController for each active
|
|
|
2961
3082
|
synthesis segment or playback delay. Replacement,
|
|
2962
3083
|
`stop()`, `cancel()`, and `destroy()` abort their owned signals, suppress stale
|
|
2963
3084
|
settlement, release Blob URLs, and publish synchronous
|
|
2964
|
-
`speech-playback-state` occurrences through `globalThis.arcaneEvents
|
|
2965
|
-
|
|
3085
|
+
`speech-playback-state` occurrences through `globalThis.arcaneEvents` before
|
|
3086
|
+
calling the optional `onState(detail)` function synchronously. Canonical
|
|
3087
|
+
subscribers and the callback observe the same public field values at dispatch
|
|
3088
|
+
time, but object identity is not promised. Both surfaces expose mutable public
|
|
3089
|
+
state detail. A callback failure is reported through `globalThis.reportError`
|
|
3090
|
+
when available, otherwise `console.error`, and does not replace playback
|
|
3091
|
+
settlement. The detail contains
|
|
2966
3092
|
`state`, `message`, `key`, `index`, `total`, `producing`, `buffered`, `hasAudio`,
|
|
2967
3093
|
`operationId`, `code`, and `reason`; a first-segment provider rejection remains
|
|
2968
3094
|
preserved to the `prepare()` caller. Later failures surface when ordered
|
|
@@ -3004,7 +3130,10 @@ const audio = document.body.appendChild(document.createElement('audio'));
|
|
|
3004
3130
|
audio.controls = true;
|
|
3005
3131
|
const speech = new SpeechPlayback({
|
|
3006
3132
|
audio,
|
|
3007
|
-
speech: globalThis.ai
|
|
3133
|
+
speech: globalThis.ai,
|
|
3134
|
+
onState(detail) {
|
|
3135
|
+
console.log('Speech state:', detail.state);
|
|
3136
|
+
}
|
|
3008
3137
|
});
|
|
3009
3138
|
const button = document.body.appendChild(document.createElement('button'));
|
|
3010
3139
|
button.textContent = 'Speak';
|
|
@@ -3020,6 +3149,19 @@ button.addEventListener('click', async function speakCompleteSegments() {
|
|
|
3020
3149
|
});
|
|
3021
3150
|
```
|
|
3022
3151
|
|
|
3152
|
+
The shared compatibility catalogs are also available directly. They do not
|
|
3153
|
+
select a voice for `SpeechPlayback`:
|
|
3154
|
+
|
|
3155
|
+
```javascript
|
|
3156
|
+
import {
|
|
3157
|
+
SPEECH_VOICE_ALIASES,
|
|
3158
|
+
SPEECH_VOICE_OPTIONS
|
|
3159
|
+
} from '/arcane/modules/SpeechPlayback.js';
|
|
3160
|
+
|
|
3161
|
+
console.log(SPEECH_VOICE_OPTIONS[0]); // {value: 'alloy', label: 'Alloy'}
|
|
3162
|
+
console.log(SPEECH_VOICE_ALIASES.has('alloy')); // true
|
|
3163
|
+
```
|
|
3164
|
+
|
|
3023
3165
|
With the default browser speech configuration, both parts enter its capacity-4
|
|
3024
3166
|
queue immediately and still play first, then second. Inspect the selected
|
|
3025
3167
|
execution device without guessing from console warnings:
|