arcane-os 0.5.16 → 0.5.17
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 +20 -0
- package/README.md +42 -19
- package/browser-runtime/ai/browser-speech-providers.mjs +8 -4
- package/browser-runtime/speech-text.mjs +31 -0
- package/docs/architecture.md +1 -1
- package/docs/reference/README.md +8 -8
- package/docs/reference/ai/browser-speech.md +34 -13
- package/docs/reference/ai/twin-cloud.md +1 -1
- package/docs/reference/availability-and-normalization.md +2 -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 +14 -12
- package/docs/reference/protocols.md +17 -13
- package/docs/reference/runtime-components.md +6 -5
- package/docs/reference/runtime-modules.md +88 -36
- package/docs/reference/sdk-api.md +181 -11
- package/package.json +2 -1
- package/runtime/arcane/components/chat.html +1 -3
- package/runtime/arcane/modules/AI.js +13 -23
- package/runtime/arcane/modules/AIProviderRuntime.js +30 -8
- package/runtime/arcane/modules/MarkdownSpeech.js +1 -50
- package/runtime/arcane/modules/SpeechPlayback.js +33 -3
- package/src/import-map.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.5.17
|
|
6
|
+
|
|
7
|
+
- Restore the public `SPEECH_VOICE_OPTIONS` ordered records and
|
|
8
|
+
`SPEECH_VOICE_ALIASES` membership set used by existing speech controls. Both
|
|
9
|
+
remain ordinary mutable compatibility values, and `SpeechPlayback` does not
|
|
10
|
+
select a voice from them automatically.
|
|
11
|
+
- Restore the optional `SpeechPlayback` constructor `onState(detail)` callback.
|
|
12
|
+
Canonical state dispatch remains first; callback failures are reported
|
|
13
|
+
without replacing playback settlement. Preserve capability-gated eager
|
|
14
|
+
submission, the provider-owned default capacity of four, indexed playback
|
|
15
|
+
order, native/custom serialization, cancellation, and Replay behavior.
|
|
16
|
+
- Apply the shared repeated-formatting-mark cleanup automatically to every TTS
|
|
17
|
+
entry path, including direct fetch, provider-runtime synthesis, browser
|
|
18
|
+
Kokoro requests, streaming chunks, and `SpeechPlayback`. Export the shared
|
|
19
|
+
`MarkdownSpeech` and `stripSpeechFormatting()` owner from
|
|
20
|
+
`arcane-os/speech-text`; keep original caller records unchanged and use
|
|
21
|
+
operation-local SDK metadata to prevent a second cleanup pass. No application
|
|
22
|
+
option is required, and the prior `textFormat` extra no longer disables or
|
|
23
|
+
selects cleanup.
|
|
24
|
+
|
|
5
25
|
## 0.5.16
|
|
6
26
|
|
|
7
27
|
- Add optional Markdown narration filtering before `AI.streamTTS()`
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
|
|
|
19
19
|
`arcane/` runtime. Both profiles preserve the same app URLs, theme, packaging,
|
|
20
20
|
event, cancellation, and browser run contracts.
|
|
21
21
|
|
|
22
|
-
This checkout defines the `0.5.
|
|
22
|
+
This checkout defines the `0.5.17` SDK contract. Applications pin one exact npm
|
|
23
23
|
version and lockfile; registry state is deliberately not baked into application
|
|
24
24
|
artifacts.
|
|
25
25
|
|
|
@@ -35,7 +35,7 @@ Create one browser application, install its pinned SDK, and start its source
|
|
|
35
35
|
server:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
npx arcane-os@0.5.
|
|
38
|
+
npx arcane-os@0.5.17 new hello-speech --path ./hello-speech --target browser
|
|
39
39
|
cd hello-speech
|
|
40
40
|
npm install
|
|
41
41
|
npm run dev
|
|
@@ -115,7 +115,13 @@ import SpeechPlayback from 'arcane/SpeechPlayback';
|
|
|
115
115
|
|
|
116
116
|
const audio = document.body.appendChild(document.createElement('audio'));
|
|
117
117
|
audio.controls = true;
|
|
118
|
-
const narration = new SpeechPlayback({
|
|
118
|
+
const narration = new SpeechPlayback({
|
|
119
|
+
audio,
|
|
120
|
+
speech: ai,
|
|
121
|
+
onState(detail) {
|
|
122
|
+
console.log('Speech state:', detail.state);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
119
125
|
const speakAll = document.body.appendChild(document.createElement('button'));
|
|
120
126
|
speakAll.textContent = 'Speak all segments';
|
|
121
127
|
speakAll.addEventListener('click', async function speakAllSegments() {
|
|
@@ -132,6 +138,20 @@ segments enter the provider queue immediately, up to four synthesize at once,
|
|
|
132
138
|
and the audio still plays first, second, third. Native or custom speech without
|
|
133
139
|
advertised provider execution capacity stays serialized with one lookahead.
|
|
134
140
|
|
|
141
|
+
Existing speech controls can also import the shared compatibility catalogs.
|
|
142
|
+
They list the ten existing value/label choices but do not choose a voice for
|
|
143
|
+
the application or prove that a selected provider supports one:
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
import {
|
|
147
|
+
SPEECH_VOICE_ALIASES,
|
|
148
|
+
SPEECH_VOICE_OPTIONS
|
|
149
|
+
} from 'arcane/SpeechPlayback';
|
|
150
|
+
|
|
151
|
+
console.log(SPEECH_VOICE_OPTIONS[0]); // {value: 'alloy', label: 'Alloy'}
|
|
152
|
+
console.log(SPEECH_VOICE_ALIASES.has('alloy')); // true
|
|
153
|
+
```
|
|
154
|
+
|
|
135
155
|
Continue with [streaming chunks, device selection, cancellation, status, and cleanup](https://github.com/TheWizardNexus/arcane-os-sdk/blob/main/docs/reference/ai/browser-speech.md),
|
|
136
156
|
the [tiny TWiN Cloud request and saved-preference migration](https://github.com/TheWizardNexus/arcane-os-sdk/blob/main/docs/reference/ai/twin-cloud.md),
|
|
137
157
|
or the [maintained WASM voice-chat example](https://github.com/TheWizardNexus/arcane-os-sdk/tree/main/examples/wasm-ai-demo).
|
|
@@ -290,13 +310,14 @@ TTS stream without taking over synthesis or playback:
|
|
|
290
310
|
```js
|
|
291
311
|
ai.configureTTSSegmentation({
|
|
292
312
|
punctuation:'any',
|
|
293
|
-
wordCadence:
|
|
313
|
+
wordCadence:null
|
|
294
314
|
});
|
|
295
315
|
```
|
|
296
316
|
|
|
297
317
|
The compatibility default remains sentence punctuation with no word cadence.
|
|
298
|
-
|
|
299
|
-
|
|
318
|
+
Within the already prepared speech text, the configured segmentation preserves
|
|
319
|
+
every character and punctuation mark, chooses the earliest complete boundary,
|
|
320
|
+
begins synthesis as each segment becomes
|
|
300
321
|
available, and plays the completed audio in exact segment order. Ready adjacent
|
|
301
322
|
buffers are scheduled consecutively on the browser audio clock rather than
|
|
302
323
|
waiting for an `ended` callback before the next start.
|
|
@@ -305,13 +326,15 @@ keeping apostrophes, commas, and hyphens that join Unicode letters or numbers
|
|
|
305
326
|
inside the same segment.
|
|
306
327
|
Mute, stop, provider transition, and cancellation still govern the whole queue.
|
|
307
328
|
|
|
308
|
-
|
|
309
|
-
`
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
329
|
+
Every TTS call automatically removes repeated same formatting marks (`*`, `#`,
|
|
330
|
+
`_`, backtick, `~`) from its outbound speech-input copy before synthesis.
|
|
331
|
+
Streaming calls also recognize a run split across chunks. Single marks and
|
|
332
|
+
ordinary repeated punctuation remain literal. No application option is needed;
|
|
333
|
+
an existing `textFormat` extra is ignored and cannot disable cleanup. Original
|
|
334
|
+
messages and caller payloads remain unchanged for display, storage, and model
|
|
335
|
+
input. The dependency-free `arcane-os/speech-text` entrypoint exports the same
|
|
336
|
+
`MarkdownSpeech` streaming class and `stripSpeechFormatting()` one-pass helper
|
|
337
|
+
for code that needs the speech-only transformation directly.
|
|
315
338
|
|
|
316
339
|
The SDK runtime also owns `DBOPFSDocumentLibrary`,
|
|
317
340
|
`DocumentLexicalSearch`, and `PersistentAIChatSession`. Document bootstrap is
|
|
@@ -334,7 +357,7 @@ uses the same controller for automatic memory extraction.
|
|
|
334
357
|
Create a new repository-shaped Arcane application with the exact stable SDK:
|
|
335
358
|
|
|
336
359
|
```bash
|
|
337
|
-
npx arcane-os@0.5.
|
|
360
|
+
npx arcane-os@0.5.17 new my-app --path ./my-app --target portable --git
|
|
338
361
|
cd my-app
|
|
339
362
|
npm install
|
|
340
363
|
npm run dev
|
|
@@ -344,7 +367,7 @@ To enroll an existing repository, install the exact SDK and initialize only
|
|
|
344
367
|
missing Arcane files:
|
|
345
368
|
|
|
346
369
|
```bash
|
|
347
|
-
npm install --save-dev --save-exact arcane-os@0.5.
|
|
370
|
+
npm install --save-dev --save-exact arcane-os@0.5.17
|
|
348
371
|
npm exec -- arcane init my-app --target portable
|
|
349
372
|
```
|
|
350
373
|
|
|
@@ -360,7 +383,7 @@ npm exec -- arcane-os targets
|
|
|
360
383
|
No global SDK install or standalone Arcane CLI is required. The application
|
|
361
384
|
repository's exact npm dependency and lockfile own the CLI and toolchain version.
|
|
362
385
|
|
|
363
|
-
Use `npx arcane-os@0.5.
|
|
386
|
+
Use `npx arcane-os@0.5.17` for the initial bootstrap because it names this npm
|
|
364
387
|
package explicitly; bare `npx arcane` outside an installed project could resolve
|
|
365
388
|
a different package. Both installed commands invoke the same headless toolchain.
|
|
366
389
|
Project-local npm scripts use the SDK pinned by that app's `package-lock.json`,
|
|
@@ -380,7 +403,7 @@ node ./bin/arcane.mjs new local-app --path ../local-app --target portable --git
|
|
|
380
403
|
|
|
381
404
|
# From the generated app repository
|
|
382
405
|
cd ../local-app
|
|
383
|
-
npm install --save-dev --save-exact ../arcane-os-sdk/arcane-os-0.5.
|
|
406
|
+
npm install --save-dev --save-exact ../arcane-os-sdk/arcane-os-0.5.17.tgz
|
|
384
407
|
npm ci
|
|
385
408
|
```
|
|
386
409
|
|
|
@@ -389,7 +412,7 @@ same location. The lockfile retains the selected package dependency while
|
|
|
389
412
|
Arcane uses the installed package name and version. Local directory `file:` dependencies are not
|
|
390
413
|
accepted because npm may install them as links; use a packed `.tgz`. A GitHub
|
|
391
414
|
runner also needs that tarball at the locked path. After publication, replace
|
|
392
|
-
the local declaration with the exact `arcane-os@0.5.
|
|
415
|
+
the local declaration with the exact `arcane-os@0.5.17` registry package and
|
|
393
416
|
commit the regenerated lock.
|
|
394
417
|
|
|
395
418
|
Generated repositories use `npm ci --ignore-scripts` in CI. Run dependency
|
|
@@ -528,7 +551,7 @@ package installation, or assertions.
|
|
|
528
551
|
|
|
529
552
|
## Current target support
|
|
530
553
|
|
|
531
|
-
Version `0.5.
|
|
554
|
+
Version `0.5.17` exposes one browser target and five explicitly paired
|
|
532
555
|
native development targets: a non-runnable portable directory, a
|
|
533
556
|
Windows x64 unsigned-local-test EXE bundle, Linux x64 and Linux ARM64
|
|
534
557
|
unsigned-local-test DEBs, and an Android development-signed APK. The
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
isBrowserSpeechAuthority,
|
|
6
6
|
isDbopfsSpeechArtifactStore,
|
|
7
7
|
} from "./browser-speech-artifacts.mjs";
|
|
8
|
+
import { stripSpeechFormatting } from "../speech-text.mjs";
|
|
8
9
|
|
|
9
10
|
const completeValue = (value) => value;
|
|
10
11
|
import {
|
|
@@ -896,7 +897,7 @@ function cloneNativeTranscriptionPayload(payload, authority) {
|
|
|
896
897
|
});
|
|
897
898
|
}
|
|
898
899
|
|
|
899
|
-
function normalizeSynthesisPayload(payload, authority) {
|
|
900
|
+
function normalizeSynthesisPayload(payload, authority, speechInputPrepared) {
|
|
900
901
|
const shared = Object.hasOwn(payload, "input");
|
|
901
902
|
let descriptors;
|
|
902
903
|
let textValue;
|
|
@@ -932,7 +933,8 @@ function normalizeSynthesisPayload(payload, authority) {
|
|
|
932
933
|
assertPayloadModel(payload, authority, { operationSubject: "tts-synthesis" });
|
|
933
934
|
textValue = descriptors.text.value;
|
|
934
935
|
}
|
|
935
|
-
const
|
|
936
|
+
const suppliedText = typeof textValue === "string" ? textValue : "";
|
|
937
|
+
const text = speechInputPrepared === true ? suppliedText : stripSpeechFormatting(suppliedText);
|
|
936
938
|
const voiceValue = Object.hasOwn(descriptors, "voice")
|
|
937
939
|
? descriptors.voice.value
|
|
938
940
|
: authority.defaultVoice;
|
|
@@ -983,6 +985,7 @@ async function normalizeRequestPayload(
|
|
|
983
985
|
authority,
|
|
984
986
|
signal,
|
|
985
987
|
cancellationReason,
|
|
988
|
+
speechInputPrepared,
|
|
986
989
|
) {
|
|
987
990
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
988
991
|
throw providerError(
|
|
@@ -1009,7 +1012,7 @@ async function normalizeRequestPayload(
|
|
|
1009
1012
|
}
|
|
1010
1013
|
return cloneNativeTranscriptionPayload(payload, authority);
|
|
1011
1014
|
}
|
|
1012
|
-
return normalizeSynthesisPayload(payload, authority);
|
|
1015
|
+
return normalizeSynthesisPayload(payload, authority, speechInputPrepared);
|
|
1013
1016
|
}
|
|
1014
1017
|
|
|
1015
1018
|
function encodeSharedSynthesisResult(result, authority) {
|
|
@@ -1619,7 +1622,7 @@ function createBrowserSpeechProvider({
|
|
|
1619
1622
|
}, role);
|
|
1620
1623
|
},
|
|
1621
1624
|
|
|
1622
|
-
async request(context = {}) {
|
|
1625
|
+
async request(context = {}, { speechInputPrepared = false } = {}) {
|
|
1623
1626
|
let requestContext;
|
|
1624
1627
|
try {
|
|
1625
1628
|
requestContext = providerContext(context, role, "request");
|
|
@@ -1713,6 +1716,7 @@ function createBrowserSpeechProvider({
|
|
|
1713
1716
|
authority,
|
|
1714
1717
|
linked.controller.signal,
|
|
1715
1718
|
browserSpeechRequestAbortReason,
|
|
1719
|
+
speechInputPrepared,
|
|
1716
1720
|
);
|
|
1717
1721
|
throwIfAborted(
|
|
1718
1722
|
linked.controller.signal,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function stripSpeechFormatting(text=''){
|
|
2
|
+
return text.replace(/([*#_`~])\1+/g,'');
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
// Speech-only filtering; single markers and all other text remain literal.
|
|
6
|
+
class MarkdownSpeech {
|
|
7
|
+
#pending='';
|
|
8
|
+
|
|
9
|
+
append(text='',end=false){
|
|
10
|
+
if(typeof text!=='string'){
|
|
11
|
+
throw new TypeError('Markdown speech input must be text.');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const source=this.#pending+text;
|
|
15
|
+
const trailing=end?null:/([*#_`~])\1*$/u.exec(source);
|
|
16
|
+
// Two copies retain the fact that a run repeats without retaining it all.
|
|
17
|
+
this.#pending=trailing
|
|
18
|
+
?trailing[1].repeat(trailing[0].length===1?1:2)
|
|
19
|
+
:'';
|
|
20
|
+
|
|
21
|
+
return stripSpeechFormatting(
|
|
22
|
+
trailing?source.slice(0,trailing.index):source
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
reset(){
|
|
27
|
+
this.#pending='';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {MarkdownSpeech,stripSpeechFormatting};
|
package/docs/architecture.md
CHANGED
|
@@ -279,7 +279,7 @@ paths are withheld from the native provider. The provider copies the complete
|
|
|
279
279
|
selected release rather than accepting an unrelated source path. Verification
|
|
280
280
|
is a separate explicit operation for a selected release artifact.
|
|
281
281
|
|
|
282
|
-
The SDK `0.5.
|
|
282
|
+
The SDK `0.5.17` runtime requires Arcane `0.8.12` or newer. Compatibility
|
|
283
283
|
is contractual rather than exact-version pinning: the prepared Core must meet
|
|
284
284
|
the highest minimum declared by the runtime, selected app, and bundled app
|
|
285
285
|
dependencies; keep each app's Arcane protocol generation; and provide every
|
package/docs/reference/README.md
CHANGED
|
@@ -17,7 +17,7 @@ high-level page links to the relevant deep section instead of repeating it.
|
|
|
17
17
|
Install the SDK in your application:
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
npm install --save-exact arcane-os@0.5.
|
|
20
|
+
npm install --save-exact arcane-os@0.5.17
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
For your first AI call, follow the [TWiN Cloud quick start](ai/twin-cloud.md).
|
|
@@ -58,9 +58,9 @@ This repository contains explicitly versioned surfaces with different owners:
|
|
|
58
58
|
|
|
59
59
|
| Surface | Source identity | Meaning |
|
|
60
60
|
| --- | --- | --- |
|
|
61
|
-
| SDK and CLI | `arcane-os` `0.5.
|
|
62
|
-
| Browser runtime | SDK `0.5.
|
|
63
|
-
| Browser SDK runtime | SDK `0.5.
|
|
61
|
+
| SDK and CLI | `arcane-os` `0.5.17` | The Node.js toolchain, portable `arcane-os/event-manager`, `arcane-os/logging`, `arcane-os/mail`, `arcane-os/preference-store`, `arcane-os/speech-playback`, and `arcane-os/speech-text` entrypoints, plus the browser-only `arcane-os/ai/browser-wasm` and `arcane-os/ai/browser-speech` entrypoints in this checkout. |
|
|
62
|
+
| Browser runtime | SDK `0.5.17`, protocol `arcane/1`, `runtime/` | The SDK-canonical runtime tree. `listRuntimeFiles()`, `readRuntimeFile()`, and `loadRuntimeRelease()` derive its current inventory directly from the selected directory. |
|
|
63
|
+
| Browser SDK runtime | SDK `0.5.17`, `browser-runtime/` | The browser closure for events, shared logging, speech-text cleanup, Wllama, and Browser Speech mechanisms. `listSdkBrowserRuntimeFiles()`, `readSdkBrowserRuntimeFile()`, and `loadSdkBrowserRuntimeRelease()` derive its current inventory directly from the selected directory. |
|
|
64
64
|
| Core reference snapshot | Arcane OS commit `567ad110bf57a1c2d4a3daa22ae93716cc5f4d7e`, protocol `arcane/1` | The application-facing Core contract imported into `docs/reference/core/`, with SDK-local links and package-boundary notes added explicitly. |
|
|
65
65
|
|
|
66
66
|
The SDK runtime source and Core reference have different owners. A browser
|
|
@@ -75,7 +75,7 @@ and the distinction between a documentation snapshot and the selected runtime.
|
|
|
75
75
|
|
|
76
76
|
## Installed documentation and release identity
|
|
77
77
|
|
|
78
|
-
This reference accompanies `arcane-os@0.5.
|
|
78
|
+
This reference accompanies `arcane-os@0.5.17`. The installed package includes
|
|
79
79
|
the maintained `docs/` tree and `examples/wasm-ai-demo/` source alongside
|
|
80
80
|
README and CHANGELOG. Open `node_modules/arcane-os/docs/reference/README.md`
|
|
81
81
|
for the matching local reference. The generated website and test suites remain
|
|
@@ -124,11 +124,11 @@ Public reference entries follow the established Arcane documentation model:
|
|
|
124
124
|
|
|
125
125
|
## Public runtime inventory
|
|
126
126
|
|
|
127
|
-
The package exposes
|
|
127
|
+
The package exposes 202 semantic JavaScript records across 18 JavaScript
|
|
128
128
|
entrypoints, plus eight JSON Schemas and package metadata. Ten entrypoints are
|
|
129
129
|
Node.js control-plane surfaces,
|
|
130
130
|
`arcane-os/event-manager`, `arcane-os/logging`, `arcane-os/mail`, `arcane-os/preference-store`, and
|
|
131
|
-
`arcane-os/speech-playback` run in Node and browsers, and
|
|
131
|
+
`arcane-os/speech-playback` plus `arcane-os/speech-text` run in Node and browsers, and
|
|
132
132
|
`arcane-os/ai/browser-wasm` plus `arcane-os/ai/browser-speech` are browser-only.
|
|
133
133
|
The [machine-readable package
|
|
134
134
|
inventory](inventory/package-api.json) and [SDK member reference](sdk-api.md)
|
|
@@ -139,7 +139,7 @@ download, install, or self-update.
|
|
|
139
139
|
|
|
140
140
|
The synchronized browser payload exposes:
|
|
141
141
|
|
|
142
|
-
-
|
|
142
|
+
- 83 JavaScript module artifacts under `runtime/arcane/modules/`, including
|
|
143
143
|
ESM modules, classic vendor globals, one worker protocol, and one Node-oriented
|
|
144
144
|
mail transport;
|
|
145
145
|
- 14 shared entity modules under `runtime/arcane/entities/`;
|
|
@@ -13,7 +13,7 @@ import map resolves `arcane/AI` and `arcane/DBOPFS`. These browser modules are
|
|
|
13
13
|
not Node inference APIs. To create an application:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npx arcane-os@0.5.
|
|
16
|
+
npx arcane-os@0.5.17 new hello-speech --path ./hello-speech --target browser
|
|
17
17
|
cd hello-speech
|
|
18
18
|
npm install
|
|
19
19
|
npm run dev
|
|
@@ -288,7 +288,8 @@ That includes any text left in the same AI instance's partial-stream buffer;
|
|
|
288
288
|
finish the previous producer before starting a separate complete passage.
|
|
289
289
|
Voice, speed, pause, and playback options are not retained with an unfinished
|
|
290
290
|
`end:false` remainder. A later call supplies its own options, and `finishTTS()`
|
|
291
|
-
uses their defaults
|
|
291
|
+
uses their defaults while flushing any pending single formatting mark through
|
|
292
|
+
the same automatic speech-input cleanup.
|
|
292
293
|
A call extracting no segments returns `true` without waiting for earlier jobs.
|
|
293
294
|
An already muted call returns `false`.
|
|
294
295
|
|
|
@@ -343,18 +344,19 @@ if (finalPrepared === false) {
|
|
|
343
344
|
```
|
|
344
345
|
|
|
345
346
|
The segmentation default uses sentence punctuation. To submit smaller complete
|
|
346
|
-
segments, call `ai.configureTTSSegmentation({punctuation:'any',wordCadence:
|
|
347
|
+
segments, call `ai.configureTTSSegmentation({punctuation:'any',wordCadence:null})`
|
|
347
348
|
before feeding the stream. Chunk boundaries themselves do not force a sentence
|
|
348
349
|
boundary; `finishTTS()` flushes any remaining text. It is not a playback-ended
|
|
349
350
|
notification. Do not mute or dispose immediately after it if playback should
|
|
350
351
|
continue.
|
|
351
352
|
|
|
352
|
-
##
|
|
353
|
+
## Automatic speech-input formatting cleanup
|
|
353
354
|
|
|
354
|
-
|
|
355
|
+
Every TTS entrypoint removes repeated same formatting marks from the outbound
|
|
356
|
+
speech-input copy automatically. No application option is required:
|
|
355
357
|
|
|
356
358
|
```javascript
|
|
357
|
-
ai.streamTTS('## Heading\n**Hello'
|
|
359
|
+
ai.streamTTS('## Heading\n**Hello');
|
|
358
360
|
ai.streamTTS('**. Next sentence.');
|
|
359
361
|
await ai.finishTTS();
|
|
360
362
|
```
|
|
@@ -366,12 +368,30 @@ preserved. This is a small narration filter, not a full Markdown parser.
|
|
|
366
368
|
Ordinary prose is forwarded immediately; only a trailing formatting candidate
|
|
367
369
|
waits for its next character or the final flush.
|
|
368
370
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
371
|
+
`end:true`, `finishTTS()`, or cancellation clears pending streaming formatting
|
|
372
|
+
state. `fetchTTS()`, provider-runtime TTS requests, direct Kokoro provider
|
|
373
|
+
requests, and `SpeechPlayback` apply the same cleanup to complete input. An
|
|
374
|
+
existing `textFormat` extra is ignored and cannot disable or select cleanup.
|
|
375
|
+
SDK-internal delegation carries `{speechInputPrepared:true}` outside the speech
|
|
376
|
+
payload only after one cleanup pass, preventing a second non-idempotent pass.
|
|
377
|
+
Applications omit that internal metadata. Displayed messages, saved history,
|
|
378
|
+
model input, caller payload objects, language, voice, synthesis capacity, and
|
|
379
|
+
playback timing are not changed by the filter.
|
|
380
|
+
|
|
381
|
+
The dependency-free helper is public for code that needs the speech-only
|
|
382
|
+
transformation directly:
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
import {
|
|
386
|
+
MarkdownSpeech,
|
|
387
|
+
stripSpeechFormatting
|
|
388
|
+
} from 'arcane-os/speech-text';
|
|
389
|
+
|
|
390
|
+
console.log(stripSpeechFormatting('**Hello**')); // Hello
|
|
391
|
+
const speechText = new MarkdownSpeech();
|
|
392
|
+
console.log(speechText.append('## Head', false)); // ' Head'
|
|
393
|
+
console.log(speechText.append('ing', true)); // ing
|
|
394
|
+
```
|
|
375
395
|
|
|
376
396
|
## Choose a device or reduce memory use
|
|
377
397
|
|
|
@@ -476,7 +496,8 @@ in place; it does not erase the application's data.
|
|
|
476
496
|
For a cancellable individual synthesis, unmute first. A fresh browser speech
|
|
477
497
|
configuration is muted, so calling `providerRuntime.load('tts')` directly at
|
|
478
498
|
that point rejects with `ARCANE_AI_TTS_MUTED`. `fetchTTS()` accepts an
|
|
479
|
-
`AbortSignal` as its second argument
|
|
499
|
+
`AbortSignal` as its second argument, cleans repeated formatting marks from the
|
|
500
|
+
outbound input copy, and returns a WAV `Blob` without playing it:
|
|
480
501
|
|
|
481
502
|
```javascript
|
|
482
503
|
const synthesisController = new AbortController();
|
|
@@ -9,7 +9,7 @@ same managed browser imports as the [browser speech quick start](browser-speech.
|
|
|
9
9
|
Create an application and start its source server:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx arcane-os@0.5.
|
|
12
|
+
npx arcane-os@0.5.17 new hello-twin --path ./hello-twin --target browser
|
|
13
13
|
cd hello-twin
|
|
14
14
|
npm install
|
|
15
15
|
npm run dev
|
|
@@ -32,12 +32,13 @@ version; WebKitGTK availability must not be generalized to macOS.
|
|
|
32
32
|
| Select and observe independent LLM/STT/TTS roles | `/arcane/modules/AIProviderRuntime.js` and `AIRuntimeState.js` | **Cross-host** controller/state; registered providers retain their own host requirements | Required/projected provider members, route/configuration records, and status fields; per-role lifecycle, cancellation, stream cleanup, sticky state, and startup barriers are normalized. `localOnly` creates no fallback. |
|
|
33
33
|
| Run a caller-selected local LLM entirely in a browser renderer | `arcane-os/ai/browser-wasm` through `createArcaneAI()` | **Browser** only; secure context, WebAssembly, OPFS/DBOPFS, WebGPU, and requested full offload are required; no CPU fallback | The public AI API module normalizes multi-model lifecycle, status, complete all-choice streaming, cancellation, exact ordered structural tool-call visibility, and session persistence. Model sources are canonical ordered file descriptors; licenses and model choice remain application policy. |
|
|
34
34
|
| Run caller-selected Whisper or Kokoro in a browser renderer | `arcane-os/ai/browser-speech` registered with `AIProviderRuntime` | **Browser** only; DBOPFS, Web Locks, Workers, Fetch/object URLs, and a caller-supplied self-contained runtime/model closure are required | STT/TTS use independent provider/2 lifecycle and status. Kokoro adds bounded Worker/session concurrency and explicit `auto`, `webgpu`, or `wasm` execution. Complete model/runtime selection, offline behavior, cancellation, Worker teardown, and request/result shapes are normalized. No runtime/model content or cloud fallback is supplied. |
|
|
35
|
+
| Prepare ordered speech playback or reuse the speech-input formatting filter | `arcane-os/speech-playback` and `arcane-os/speech-text` | **Node** with injected media adapters, or **Browser / Native WebView** media; the text filter itself is **Cross-host** | Stored and caller-owned text stays exact. Only the outbound synthesis copy automatically loses repeated same formatting marks. A capacity-advertising provider receives complete segments immediately while retaining indexed playback; native/custom synthesis stays serialized. |
|
|
35
36
|
| Preserve complete chat history and memory | `/arcane/modules/PersistentAIChatSession.js` | **Browser / native WebView** with ChatEntity/DBOPFS and a configured chat function | Existing DBOPFS names and memory semantics are preserved. Live-context commit is atomic; durable persistence is explicit and coherent across user/assistant turns and atomic all-ID tool-result batches. |
|
|
36
37
|
| Search an app-owned document corpus for explicit chat context | `/arcane/modules/DBOPFSDocumentLibrary.js` | **Browser** or compatible injected DBOPFS adapter | Generation/manifest completion, complete lexical search, partial read failures, and untrusted context labels are normalized. Construction does not search; an explicitly wired context builder performs retrieval for each prepared chat send. |
|
|
37
38
|
| Read host identity, capabilities, storage, preferences, appearance, or platform state | `globalThis.Arcane` | **Cross-host** where the method is implemented and admitted | Promise behavior and `Arcane.Error` are normalized. Result fields are normalized unless the method explicitly documents a platform-dependent snapshot. |
|
|
38
39
|
| Use local AI without coupling app code to Ollama HTTP | `Arcane.localAI`, `Arcane.ai`, or `/arcane/modules/Ollama.js` | Primarily **Native**; Android exposes a narrower admitted inference projection | Admission, errors, and managed-operation events are normalized. Direct Ollama response envelopes remain **Provider-native**. |
|
|
39
40
|
| Use TWiN Cloud from the renderer profile | `/arcane/modules/AI.js` | **Cloud** from an allowed browser/native renderer | High-level chat behavior is normalized by the module. The TWiN access key authenticates remote LLM chat; raw provider diagnostics remain provider-specific. No automatic cloud fallback is inferred from local failure. |
|
|
40
|
-
| Use speech through one application helper | `/arcane/modules/AI.js` and `Arcane.speech` | **Browser** or **Native** | The helper keeps audio on device: Whisper owns STT and Kokoro owns TTS. It normalizes application-facing audio/text behavior while browser and native request/response plumbing differs below that boundary. |
|
|
41
|
+
| Use speech through one application helper | `/arcane/modules/AI.js` and `Arcane.speech` | **Browser** or **Native** | The helper keeps audio on device: Whisper owns STT and Kokoro owns TTS. It automatically cleans only the outbound speech-input copy and normalizes application-facing audio/text behavior while browser and native request/response plumbing differs below that boundary. |
|
|
41
42
|
| Inspect or manage raw Ollama models | `Arcane.ollama` or `/arcane/modules/Ollama.js` | **Native** desktop Core for management; narrower Android inference only | Wrapper method names, errors, streaming correlation, and admission are Arcane-controlled. Direct Ollama success envelopes are intentionally provider-native. |
|
|
42
43
|
| Use native terminal, installation, user, provisioning, or machine controls | matching `Arcane.*` namespace | **Native** and app/capability restricted | Calls and errors use the common bridge contract. Platform results can be host-specific and are marked in the method guide. |
|
|
43
44
|
|
package/docs/reference/cli.md
CHANGED
|
@@ -214,7 +214,7 @@ portable runtime subpaths such as `arcane-os/preference-store` and
|
|
|
214
214
|
modules. The result reports the complete map written to the selected
|
|
215
215
|
application; no fixed entry count is a release contract.
|
|
216
216
|
|
|
217
|
-
SDK `0.5.
|
|
217
|
+
SDK `0.5.17` preserves the physical workspace route count and ordered include
|
|
218
218
|
list. External and modern integrated routes require `components`, `css`,
|
|
219
219
|
`dependencies`, `entities`, `img`, `modules`, and `sdk`; a physical workspace
|
|
220
220
|
may omit only an optional trailing `security` include. The external license
|
|
@@ -9,7 +9,7 @@ They are not TypeScript declarations.
|
|
|
9
9
|
|
|
10
10
|
## Portable SDK AI and Core AI
|
|
11
11
|
|
|
12
|
-
The SDK `0.5.
|
|
12
|
+
The SDK `0.5.17` has two related but separate normalized boundaries:
|
|
13
13
|
|
|
14
14
|
| Boundary | Use | Host |
|
|
15
15
|
|---|---|---|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"sdkVersion": "0.5.
|
|
3
|
+
"sdkVersion": "0.5.17",
|
|
4
4
|
"environment": {
|
|
5
5
|
"runtime": "Node.js for Node entrypoints; browser for browser-only entrypoints",
|
|
6
6
|
"minimumVersion": "22.23.2 for Node entrypoints",
|
|
7
7
|
"moduleSystem": "ESM"
|
|
8
8
|
},
|
|
9
|
-
"memberCount":
|
|
9
|
+
"memberCount": 202,
|
|
10
10
|
"members": [
|
|
11
11
|
{
|
|
12
12
|
"id": "root:APP_BUNDLE_DESCRIPTOR_NAME",
|
|
@@ -1395,7 +1395,7 @@
|
|
|
1395
1395
|
"summary": "Default binding for the canonical SpeechPlayback runtime class, with capability-gated eager provider submission and exact-order playback.",
|
|
1396
1396
|
"availability": "Node with injected media adapters, or browser/native WebView media",
|
|
1397
1397
|
"protocol": "SpeechPlayback runtime contract",
|
|
1398
|
-
"normalization": "Binding identity and namespace come directly from the canonical runtime module; a fetchTTS client with positive advertised TTS execution capacity receives all complete segments immediately while its provider owns bounded admission and SpeechPlayback retains indexed order; other clients remain serialized"
|
|
1398
|
+
"normalization": "Binding identity and namespace come directly from the canonical runtime module; stored part input remains exact while only each outbound synthesis copy receives automatic repeated-formatting-mark cleanup and SDK-internal preparation metadata; a fetchTTS client with positive advertised TTS execution capacity receives all complete segments immediately while its provider owns bounded admission and SpeechPlayback retains indexed order; other clients remain serialized; canonical state dispatch precedes the optional synchronous onState callback"
|
|
1399
1399
|
},
|
|
1400
1400
|
{
|
|
1401
1401
|
"id": "speech-playback:SPEECH_PLAYBACK_STATE_EVENT",
|
|
@@ -1411,6 +1411,34 @@
|
|
|
1411
1411
|
"protocol": "SpeechPlayback runtime contract",
|
|
1412
1412
|
"normalization": "Exact immutable speech-playback-state event name"
|
|
1413
1413
|
},
|
|
1414
|
+
{
|
|
1415
|
+
"id": "speech-playback:SPEECH_VOICE_ALIASES",
|
|
1416
|
+
"name": "SPEECH_VOICE_ALIASES",
|
|
1417
|
+
"displayName": "SPEECH_VOICE_ALIASES",
|
|
1418
|
+
"kind": "constant",
|
|
1419
|
+
"signature": "const SPEECH_VOICE_ALIASES",
|
|
1420
|
+
"entrypoints": ["arcane-os/speech-playback"],
|
|
1421
|
+
"primaryImport": "arcane-os/speech-playback",
|
|
1422
|
+
"group": "Portable runtime modules",
|
|
1423
|
+
"summary": "Mutable compatibility membership set for the ten shared speech voice identifiers.",
|
|
1424
|
+
"availability": "Node and browser",
|
|
1425
|
+
"protocol": "SpeechPlayback runtime contract",
|
|
1426
|
+
"normalization": "Derived once from SPEECH_VOICE_OPTIONS in published order; ordinary mutable Set containing alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, and shimmer; SpeechPlayback does not select it automatically"
|
|
1427
|
+
},
|
|
1428
|
+
{
|
|
1429
|
+
"id": "speech-playback:SPEECH_VOICE_OPTIONS",
|
|
1430
|
+
"name": "SPEECH_VOICE_OPTIONS",
|
|
1431
|
+
"displayName": "SPEECH_VOICE_OPTIONS",
|
|
1432
|
+
"kind": "constant",
|
|
1433
|
+
"signature": "const SPEECH_VOICE_OPTIONS",
|
|
1434
|
+
"entrypoints": ["arcane-os/speech-playback"],
|
|
1435
|
+
"primaryImport": "arcane-os/speech-playback",
|
|
1436
|
+
"group": "Portable runtime modules",
|
|
1437
|
+
"summary": "Mutable ordered compatibility value/label records for existing speech controls.",
|
|
1438
|
+
"availability": "Node and browser",
|
|
1439
|
+
"protocol": "SpeechPlayback runtime contract",
|
|
1440
|
+
"normalization": "Ordinary mutable array and mutable records ordered as Alloy, Ash, Ballad, Coral, Echo, Fable, Nova, Onyx, Sage, and Shimmer; provider support and selection remain caller-owned"
|
|
1441
|
+
},
|
|
1414
1442
|
{
|
|
1415
1443
|
"id": "speech-playback:SpeechPlayback",
|
|
1416
1444
|
"name": "SpeechPlayback",
|
|
@@ -1423,7 +1451,7 @@
|
|
|
1423
1451
|
"summary": "Named binding for the same capability-aware, exact-order canonical class exposed as the subpath default.",
|
|
1424
1452
|
"availability": "Node with injected media adapters, or browser/native WebView media",
|
|
1425
1453
|
"protocol": "SpeechPlayback runtime contract",
|
|
1426
|
-
"normalization": "Binding identity equals the default export; prepare preserves each nonblank part input exactly without trimming, splitting, or freezing it; provider-advertised capacity enables eager submission while the provider owns its bound, native and custom clients remain serialized, and media availability remains host-owned"
|
|
1454
|
+
"normalization": "Binding identity equals the default export; prepare preserves each nonblank part input exactly without trimming, splitting, or freezing it; requestSpeech changes only the cloned outbound input through automatic repeated-formatting-mark cleanup and carries SDK-internal preparation metadata; provider-advertised capacity enables eager submission while the provider owns its bound, native and custom clients remain serialized, canonical state dispatch precedes optional synchronous onState delivery, and media availability remains host-owned"
|
|
1427
1455
|
},
|
|
1428
1456
|
{
|
|
1429
1457
|
"id": "speech-playback:splitSpeechText",
|
|
@@ -1439,6 +1467,34 @@
|
|
|
1439
1467
|
"protocol": "SpeechPlayback runtime contract",
|
|
1440
1468
|
"normalization": "Uses trimming only to detect blank input; nonblank text is returned unchanged in one mutable array without trimming, splitting, or freezing"
|
|
1441
1469
|
},
|
|
1470
|
+
{
|
|
1471
|
+
"id": "speech-text:MarkdownSpeech",
|
|
1472
|
+
"name": "MarkdownSpeech",
|
|
1473
|
+
"displayName": "MarkdownSpeech",
|
|
1474
|
+
"kind": "class",
|
|
1475
|
+
"signature": "new MarkdownSpeech()",
|
|
1476
|
+
"entrypoints": ["arcane-os/speech-text"],
|
|
1477
|
+
"primaryImport": "arcane-os/speech-text",
|
|
1478
|
+
"group": "Portable runtime modules",
|
|
1479
|
+
"summary": "Streams speech-only repeated-formatting-mark removal across input chunk boundaries.",
|
|
1480
|
+
"availability": "Node and browser",
|
|
1481
|
+
"protocol": "Speech text normalization",
|
|
1482
|
+
"normalization": "append(text='',end=false) emits newly available narration, retains only a trailing candidate formatting mark across chunks, and resets after a terminal append; reset() discards that pending state; caller text remains unchanged"
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
"id": "speech-text:stripSpeechFormatting",
|
|
1486
|
+
"name": "stripSpeechFormatting",
|
|
1487
|
+
"displayName": "stripSpeechFormatting()",
|
|
1488
|
+
"kind": "function",
|
|
1489
|
+
"signature": "stripSpeechFormatting(text='')",
|
|
1490
|
+
"entrypoints": ["arcane-os/speech-text"],
|
|
1491
|
+
"primaryImport": "arcane-os/speech-text",
|
|
1492
|
+
"group": "Portable runtime modules",
|
|
1493
|
+
"summary": "Removes repeated runs of speech formatting marks from one complete text value.",
|
|
1494
|
+
"availability": "Node and browser",
|
|
1495
|
+
"protocol": "Speech text normalization",
|
|
1496
|
+
"normalization": "Calls the supplied value's replace method and returns its result with runs of two or more identical *, #, _, backtick, or ~ marks removed; single marks and every other character remain literal; it does not parse Markdown or modify the supplied value; values without callable replace fail with the native TypeError"
|
|
1497
|
+
},
|
|
1442
1498
|
{
|
|
1443
1499
|
"id": "root:readRuntimeFile",
|
|
1444
1500
|
"name": "readRuntimeFile",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"repository": "https://github.com/TheWizardNexus/arcane-os-sdk.git",
|
|
6
6
|
"branch": "main",
|
|
7
7
|
"path": "runtime/arcane/components",
|
|
8
|
-
"sdkVersion": "0.5.
|
|
8
|
+
"sdkVersion": "0.5.17"
|
|
9
9
|
},
|
|
10
10
|
"componentCount": 39,
|
|
11
11
|
"loader": "/arcane/modules/HTMLImport.js",
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
],
|
|
172
172
|
"availability": "Browser and supported native WebViews",
|
|
173
173
|
"transport": "HTMLImport + DOM; injected Arcane/provider modules where listed",
|
|
174
|
-
"normalization": "UI/runtime state, honest model progress, complete timestamped transcript including ui_hidden stored records, user-facing structural arguments.message, nonblank all-ID tool-result restoration, collapsed complete raw inspection, ordered parallel-call replay validation, per-choice streamed/terminal complete-envelope correlation, complete nonstructural stream rendering, generic visible failure outcomes with complete console diagnostics, atomic executed/declined/cancelled/not-executed result batches with one continuation, plural pending-call reload recovery, reentrant terminal-event ownership, and BFCache-preserving page lifecycle are normalized; destroy aborts observation and returns true once/false thereafter; AI/storage/media behavior remains mixed"
|
|
174
|
+
"normalization": "UI/runtime state, honest model progress, complete timestamped transcript including ui_hidden stored records, user-facing structural arguments.message, nonblank all-ID tool-result restoration, collapsed complete raw inspection, ordered parallel-call replay validation, per-choice streamed/terminal complete-envelope correlation, complete nonstructural stream rendering, automatic repeated-formatting-mark removal from only the outbound speech-input copy while displayed and stored Markdown stays exact, generic visible failure outcomes with complete console diagnostics, atomic executed/declined/cancelled/not-executed result batches with one continuation, plural pending-call reload recovery, reentrant terminal-event ownership, and BFCache-preserving page lifecycle are normalized; destroy aborts observation and returns true once/false thereafter; AI/storage/media behavior remains mixed"
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
177
|
"file": "runtime/arcane/components/conversation-view.html",
|