arcane-os 0.3.0 → 0.3.2
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 +27 -0
- package/README.md +86 -117
- package/bin/arcane-test.mjs +170 -46
- package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
- package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
- package/browser-runtime/ai/browser-wasm.mjs +24 -35
- package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
- package/browser-runtime/ai/model-controller.mjs +584 -181
- package/browser-runtime/ai/speech-worker-client.mjs +8 -146
- package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
- package/browser-runtime/dom-event-instrumentation.mjs +55 -147
- package/browser-runtime/event-manager.mjs +239 -624
- package/package.json +5 -6
- package/runtime/arcane/components/app-bar.html +3 -15
- package/runtime/arcane/components/assistant-panel.html +10 -10
- package/runtime/arcane/components/calculator.html +1 -1
- package/runtime/arcane/components/chat.html +1359 -135
- package/runtime/arcane/components/conversation-view.html +2 -2
- package/runtime/arcane/components/document-inspector.html +11 -17
- package/runtime/arcane/components/file-manager.html +13 -56
- package/runtime/arcane/components/markdown-document.html +82 -281
- package/runtime/arcane/components/markdown-editor.html +7 -10
- package/runtime/arcane/components/media-embed.html +6 -6
- package/runtime/arcane/components/screen-capture.html +4 -4
- package/runtime/arcane/components/source-explanation.html +2 -2
- package/runtime/arcane/components/speech.html +112 -68
- package/runtime/arcane/components/terminal-workspace.html +4 -4
- package/runtime/arcane/components/theme-editor.html +1 -1
- package/runtime/arcane/components/unified-inbox.html +2 -2
- package/runtime/arcane/components/voice-transcription.html +31 -21
- package/runtime/arcane/entities/Calculation.js +2 -3
- package/runtime/arcane/entities/Chat.js +228 -43
- package/runtime/arcane/entities/Preference.js +3 -5
- package/runtime/arcane/entities/Weather.js +5 -5
- package/runtime/arcane/modules/AI.js +1050 -427
- package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
- package/runtime/arcane/modules/AIResponseLength.js +9 -19
- package/runtime/arcane/modules/AIRuntimeState.js +109 -72
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
- package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
- package/runtime/arcane/modules/CalculatorEngine.js +9 -9
- package/runtime/arcane/modules/CommunicationAppController.js +3 -7
- package/runtime/arcane/modules/ComponentContracts.js +30 -32
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
- package/runtime/arcane/modules/ConversationActionItems.js +26 -59
- package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
- package/runtime/arcane/modules/ConversationTimebox.js +27 -15
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
- package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
- package/runtime/arcane/modules/HTMLImport.js +54 -1
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
- package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
- package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
- package/runtime/arcane/modules/MD.js +1 -45
- package/runtime/arcane/modules/Mail.js +51 -103
- package/runtime/arcane/modules/MailOutbox.mjs +95 -193
- package/runtime/arcane/modules/MailTransport.mjs +36 -57
- package/runtime/arcane/modules/ModelDefinition.js +22 -106
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
- package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
- package/runtime/arcane/modules/PreferenceStore.js +102 -30
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
- package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
- package/runtime/arcane/modules/ScreenCapture.js +175 -128
- package/runtime/arcane/modules/SpeechPlayback.js +46 -149
- package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
- package/runtime/arcane/modules/ToolCallRouter.js +25 -12
- package/runtime/arcane/modules/YouTubeMedia.js +6 -5
- package/schemas/arcane-app-bundle.schema.json +13 -78
- package/schemas/arcane-app.schema.json +9 -25
- package/schemas/arcane-lock.schema.json +18 -151
- package/schemas/arcane-package.schema.json +2 -16
- package/schemas/native-build-plan.schema.json +119 -122
- package/src/app-descriptor.mjs +75 -132
- package/src/application-tests.mjs +200 -0
- package/src/cli/main.mjs +27 -46
- package/src/constants.mjs +3 -4
- package/src/dev-server.mjs +30 -324
- package/src/doctor.mjs +92 -154
- package/src/dom-event-instrumentation.mjs +55 -147
- package/src/errors.mjs +2 -3
- package/src/event-manager.mjs +239 -624
- package/src/event-queue.mjs +3 -3
- package/src/import-map.mjs +273 -1028
- package/src/index.mjs +14 -16
- package/src/installed-sdk-runtime.mjs +40 -62
- package/src/integrated-provider-loader.mjs +53 -382
- package/src/mail-api.mjs +0 -2
- package/src/mail-server.mjs +224 -580
- package/src/mail.mjs +4 -10
- package/src/native-plan.mjs +163 -598
- package/src/native-provider-loader.mjs +104 -1063
- package/src/packager/core.mjs +485 -3229
- package/src/process.mjs +5 -10
- package/src/release-bundle.mjs +292 -2405
- package/src/runtime.mjs +76 -396
- package/src/scaffold.mjs +30 -80
- package/src/sdk-browser-runtime.mjs +70 -626
- package/src/source-server.mjs +588 -0
- package/src/targets/index.mjs +78 -188
- package/src/templates/workspace-template.mjs +19 -135
- package/src/testing-loader.mjs +164 -0
- package/src/testing.mjs +1 -1
- package/src/toolchain.mjs +131 -544
- package/src/update-check.mjs +26 -64
- package/src/workspace-operation-lock.mjs +139 -430
- package/src/workspace-runtime.mjs +112 -779
- package/src/workspace.mjs +40 -302
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
- package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
- package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
- package/browser-runtime/ai/internal/sha256.mjs +0 -166
- package/docs/architecture.md +0 -344
- package/docs/compatibility.md +0 -36
- package/docs/event-manager.md +0 -294
- package/docs/platform-targets.md +0 -108
- package/docs/publishing.md +0 -201
- package/docs/reference/README.md +0 -187
- package/docs/reference/ai/browser-speech-package-authority.json +0 -835
- package/docs/reference/ai/browser-speech.md +0 -1252
- package/docs/reference/ai/browser-wasm.md +0 -530
- package/docs/reference/arcane-ollama.md +0 -288
- package/docs/reference/availability-and-normalization.md +0 -183
- package/docs/reference/behavioral-testing.md +0 -133
- package/docs/reference/cli.md +0 -779
- package/docs/reference/core/README.md +0 -62
- package/docs/reference/core/arcane-ai-contracts.md +0 -907
- package/docs/reference/core/arcane-api.md +0 -601
- package/docs/reference/core/arcane-entities.md +0 -65
- package/docs/reference/core/arcane-events.md +0 -134
- package/docs/reference/core/ollama-module.md +0 -181
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
- package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
- package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
- package/docs/reference/event-manager.md +0 -1511
- package/docs/reference/inventory/package-api.json +0 -3284
- package/docs/reference/inventory/runtime-components.json +0 -1011
- package/docs/reference/inventory/runtime-entities.json +0 -26
- package/docs/reference/inventory/runtime-modules.json +0 -1431
- package/docs/reference/mail.md +0 -316
- package/docs/reference/protocols.md +0 -677
- package/docs/reference/runtime-components.md +0 -1366
- package/docs/reference/runtime-entities.md +0 -303
- package/docs/reference/runtime-modules.md +0 -2960
- package/docs/reference/sdk-api.md +0 -6694
- package/docs/roadmap.md +0 -79
- package/docs/work-amplification.md +0 -129
- package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
|
@@ -1,158 +1,69 @@
|
|
|
1
1
|
import {createArcaneEventSource} from 'arcane-os/event-manager';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Object.freeze({value:'sage',label:'Sage'}),
|
|
17
|
-
Object.freeze({value:'shimmer',label:'Shimmer'})
|
|
18
|
-
]);
|
|
19
|
-
const SUPERSEDED=Object.freeze({superseded:true});
|
|
3
|
+
const SPEECH_VOICE_OPTIONS=[
|
|
4
|
+
{value:'alloy',label:'Alloy'},
|
|
5
|
+
{value:'ash',label:'Ash'},
|
|
6
|
+
{value:'ballad',label:'Ballad'},
|
|
7
|
+
{value:'coral',label:'Coral'},
|
|
8
|
+
{value:'echo',label:'Echo'},
|
|
9
|
+
{value:'fable',label:'Fable'},
|
|
10
|
+
{value:'nova',label:'Nova'},
|
|
11
|
+
{value:'onyx',label:'Onyx'},
|
|
12
|
+
{value:'sage',label:'Sage'},
|
|
13
|
+
{value:'shimmer',label:'Shimmer'}
|
|
14
|
+
];
|
|
15
|
+
const SUPERSEDED={superseded:true};
|
|
20
16
|
const SPEECH_PLAYBACK_STATE_EVENT='speech-playback-state';
|
|
21
|
-
const SPEECH_PLAYBACK_FAILURE_REASONS=
|
|
17
|
+
const SPEECH_PLAYBACK_FAILURE_REASONS={
|
|
22
18
|
ARCANE_AI_OPERATION_SUPERSEDED:'speech-synthesis-superseded',
|
|
23
19
|
ARCANE_AI_REQUEST_ABORTED:'speech-synthesis-cancelled',
|
|
24
20
|
ARCANE_SPEECH_PLAYBACK_AUDIO_PLAYBACK_REJECTED:'audio-playback-rejected',
|
|
25
21
|
ARCANE_SPEECH_PLAYBACK_SYNTHESIZED_AUDIO_CONTRACT_MISMATCH:'synthesized-audio-contract-mismatch',
|
|
26
22
|
ARCANE_SPEECH_PLAYBACK_SYNTHESIZER_UNAVAILABLE:'speech-synthesizer-unavailable'
|
|
27
|
-
}
|
|
28
|
-
const WAV_AUDIO_CONTENT_TYPES=
|
|
23
|
+
};
|
|
24
|
+
const WAV_AUDIO_CONTENT_TYPES=new Set([
|
|
29
25
|
'audio/vnd.wave',
|
|
30
26
|
'audio/wav',
|
|
31
27
|
'audio/wave',
|
|
32
28
|
'audio/x-wav'
|
|
33
|
-
])
|
|
29
|
+
]);
|
|
34
30
|
const queuesBySpeechClient=new WeakMap();
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
#values;
|
|
38
|
-
|
|
39
|
-
constructor(values){
|
|
40
|
-
this.#values=new Set(values);
|
|
41
|
-
Object.freeze(this);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get size(){return this.#values.size;}
|
|
45
|
-
get [Symbol.toStringTag](){return 'Set';}
|
|
46
|
-
has(value){return this.#values.has(value);}
|
|
47
|
-
entries(){return this.#values.entries();}
|
|
48
|
-
keys(){return this.#values.keys();}
|
|
49
|
-
values(){return this.#values.values();}
|
|
50
|
-
[Symbol.iterator](){return this.values();}
|
|
51
|
-
|
|
52
|
-
forEach(callback,thisArgument){
|
|
53
|
-
for(const value of this.#values)callback.call(thisArgument,value,value,this);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const SPEECH_VOICE_ALIASES=new ReadonlyAliasSet(
|
|
32
|
+
const SPEECH_VOICE_ALIASES=new Set(
|
|
58
33
|
SPEECH_VOICE_OPTIONS.map(function voiceAlias(option){return option.value;})
|
|
59
34
|
);
|
|
60
35
|
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
function speechBoundary(value,limit,minimum){
|
|
66
|
-
const candidates=[
|
|
67
|
-
value.lastIndexOf('\n\n',limit),
|
|
68
|
-
value.lastIndexOf('. ',limit),
|
|
69
|
-
value.lastIndexOf('? ',limit),
|
|
70
|
-
value.lastIndexOf('! ',limit),
|
|
71
|
-
value.lastIndexOf('; ',limit),
|
|
72
|
-
value.lastIndexOf(', ',limit),
|
|
73
|
-
value.lastIndexOf(' ',limit)
|
|
74
|
-
];
|
|
75
|
-
const boundary=Math.max(...candidates);
|
|
76
|
-
return boundary>=minimum
|
|
77
|
-
?Math.min(limit,boundary+(/^[.!?;,]$/.test(value[boundary]||'')?1:0))
|
|
78
|
-
:limit;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function splitSpeechText(
|
|
82
|
-
value='',
|
|
83
|
-
maximum=MAX_SPEECH_INPUT,
|
|
84
|
-
maximumChunks=MAX_SPEECH_CHUNKS,
|
|
85
|
-
{
|
|
86
|
-
tooLongMessage='Speech text is too long for bounded playback. The full visual content remains available.',
|
|
87
|
-
queueLimitMessage='Speech text exceeds the bounded playback queue. The full visual content remains available.'
|
|
88
|
-
}={}
|
|
89
|
-
){
|
|
90
|
-
const text=String(value??'').trim();
|
|
91
|
-
if(!text)return [];
|
|
92
|
-
if(!Number.isInteger(maximum)||maximum<100||maximum>4000){
|
|
93
|
-
throw new RangeError('Speech chunk size must be between 100 and 4,000 characters.');
|
|
94
|
-
}
|
|
95
|
-
if(!Number.isInteger(maximumChunks)||maximumChunks<1||maximumChunks>MAX_SPEECH_CHUNKS){
|
|
96
|
-
throw new RangeError(`Speech chunk count must be between 1 and ${MAX_SPEECH_CHUNKS}.`);
|
|
97
|
-
}
|
|
98
|
-
if(text.length>maximum*maximumChunks)throw speechLimitError(tooLongMessage);
|
|
99
|
-
const chunks=[];
|
|
100
|
-
let remaining=text;
|
|
101
|
-
while(remaining.length){
|
|
102
|
-
const slots=maximumChunks-chunks.length;
|
|
103
|
-
if(slots<1)throw speechLimitError(queueLimitMessage);
|
|
104
|
-
if(remaining.length<=maximum&&remaining.length<=PREFERRED_STREAM_SEGMENT){
|
|
105
|
-
chunks.push(remaining);
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
const minimum=Math.ceil(remaining.length/slots);
|
|
109
|
-
const preferred=chunks.length===0?PREFERRED_STREAM_SEGMENT:maximum;
|
|
110
|
-
const target=Math.min(maximum,Math.max(preferred,minimum));
|
|
111
|
-
if(remaining.length<=target){
|
|
112
|
-
chunks.push(remaining);
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
const boundary=speechBoundary(remaining,target,Math.max(minimum,Math.floor(target*0.55)));
|
|
116
|
-
chunks.push(remaining.slice(0,boundary).trim());
|
|
117
|
-
remaining=remaining.slice(boundary).trimStart();
|
|
118
|
-
}
|
|
119
|
-
return chunks;
|
|
36
|
+
function splitSpeechText(value=''){
|
|
37
|
+
const text=String(value??'');
|
|
38
|
+
return text.trim()?[text]:[];
|
|
120
39
|
}
|
|
121
40
|
|
|
122
41
|
function normalizeParts(parts,defaultVoice=null,defaultSpeed=1){
|
|
123
42
|
if(!Array.isArray(parts)||!parts.length){
|
|
124
43
|
throw new TypeError('Narration text cannot be blank. The full visual content remains available.');
|
|
125
44
|
}
|
|
126
|
-
if(parts.length>MAX_SPEECH_CHUNKS){
|
|
127
|
-
throw speechLimitError('Speech text exceeds the bounded playback queue. The full visual content remains available.');
|
|
128
|
-
}
|
|
129
45
|
return parts.map(function normalizePart(part){
|
|
130
46
|
const candidate=typeof part==='string'?{input:part}:part;
|
|
131
|
-
const input=String(candidate?.input??'')
|
|
132
|
-
if(!input)throw new TypeError('Speech segments cannot be blank. The full visual content remains available.');
|
|
133
|
-
if(input.length>MAX_SPEECH_INPUT){
|
|
134
|
-
throw speechLimitError('A speech segment exceeds the local service limit. The full visual content remains available.');
|
|
135
|
-
}
|
|
47
|
+
const input=String(candidate?.input??'');
|
|
48
|
+
if(!input.trim())throw new TypeError('Speech segments cannot be blank. The full visual content remains available.');
|
|
136
49
|
const pauseAfterMs=Number(candidate?.pauseAfterMs??0);
|
|
137
|
-
if(!Number.isFinite(pauseAfterMs)||pauseAfterMs<0
|
|
138
|
-
throw new RangeError('Speech segment pauses must be
|
|
50
|
+
if(!Number.isFinite(pauseAfterMs)||pauseAfterMs<0){
|
|
51
|
+
throw new RangeError('Speech segment pauses must be a nonnegative number of milliseconds.');
|
|
139
52
|
}
|
|
140
53
|
const voiceValue=candidate?.voice??defaultVoice;
|
|
141
|
-
const voice=voiceValue===null||voiceValue===undefined
|
|
142
|
-
?null
|
|
143
|
-
:String(voiceValue).trim();
|
|
54
|
+
const voice=voiceValue===null||voiceValue===undefined?null:String(voiceValue);
|
|
144
55
|
const speed=Number(candidate?.speed??defaultSpeed);
|
|
145
|
-
if(voiceValue!==null&&voiceValue!==undefined&&!voice){
|
|
56
|
+
if(voiceValue!==null&&voiceValue!==undefined&&!voice.trim()){
|
|
146
57
|
throw new TypeError('Speech segment voice cannot be blank.');
|
|
147
58
|
}
|
|
148
59
|
if(!Number.isFinite(speed)||speed<=0)throw new RangeError('Every speech segment requires a positive speech speed.');
|
|
149
|
-
return
|
|
60
|
+
return {
|
|
150
61
|
input,
|
|
151
62
|
pauseAfterMs,
|
|
152
63
|
role:String(candidate?.role||'narration'),
|
|
153
64
|
speed,
|
|
154
65
|
voice
|
|
155
|
-
}
|
|
66
|
+
};
|
|
156
67
|
});
|
|
157
68
|
}
|
|
158
69
|
|
|
@@ -394,7 +305,7 @@ function queueFor(speech){
|
|
|
394
305
|
return queue;
|
|
395
306
|
}
|
|
396
307
|
|
|
397
|
-
const DEFAULT_MESSAGES=
|
|
308
|
+
const DEFAULT_MESSAGES={
|
|
398
309
|
idle:'Speech is ready when visual content is available.',
|
|
399
310
|
queued:'Waiting for the current local speech request. The latest narration will begin next.',
|
|
400
311
|
preparing:function preparing({count}){return `Preparing ${count===1?'the narration':`${count} speech segments`}.`;},
|
|
@@ -412,7 +323,7 @@ const DEFAULT_MESSAGES=Object.freeze({
|
|
|
412
323
|
invalidAudio:'Arcane returned invalid synthesized audio.',
|
|
413
324
|
playbackError:'The synthesized narration could not be played. The visual content remains available.',
|
|
414
325
|
fallbackError:'Speech is unavailable. The visual content remains available.'
|
|
415
|
-
}
|
|
326
|
+
};
|
|
416
327
|
|
|
417
328
|
class SpeechPlayback{
|
|
418
329
|
constructor({
|
|
@@ -441,7 +352,7 @@ class SpeechPlayback{
|
|
|
441
352
|
this,
|
|
442
353
|
{
|
|
443
354
|
source:'speech-playback',
|
|
444
|
-
eventTypes:
|
|
355
|
+
eventTypes:[SPEECH_PLAYBACK_STATE_EVENT]
|
|
445
356
|
}
|
|
446
357
|
);
|
|
447
358
|
this.onState=onState;
|
|
@@ -463,7 +374,7 @@ class SpeechPlayback{
|
|
|
463
374
|
timer=globalThis.setTimeout(finish,duration);
|
|
464
375
|
});
|
|
465
376
|
};
|
|
466
|
-
this.messages=
|
|
377
|
+
this.messages={...DEFAULT_MESSAGES,...messages};
|
|
467
378
|
this.urls=[];
|
|
468
379
|
this.parts=[];
|
|
469
380
|
this.index=0;
|
|
@@ -471,11 +382,11 @@ class SpeechPlayback{
|
|
|
471
382
|
this.pendingGenerations=new Set();
|
|
472
383
|
this.lookahead=null;
|
|
473
384
|
this.lookaheadError=null;
|
|
474
|
-
this.model=model===null||model===undefined?null:String(model)
|
|
475
|
-
this.voice=voice===null||voice===undefined?null:String(voice)
|
|
385
|
+
this.model=model===null||model===undefined?null:String(model);
|
|
386
|
+
this.voice=voice===null||voice===undefined?null:String(voice);
|
|
476
387
|
this.responseFormat=responseFormat===null||responseFormat===undefined
|
|
477
388
|
?null
|
|
478
|
-
:String(responseFormat)
|
|
389
|
+
:String(responseFormat);
|
|
479
390
|
this.speed=normalizedSpeed;
|
|
480
391
|
this.key='';
|
|
481
392
|
this.state='idle';
|
|
@@ -512,7 +423,7 @@ class SpeechPlayback{
|
|
|
512
423
|
|
|
513
424
|
emit(state,message,key=this.key,{code=null,reason=null}={}){
|
|
514
425
|
this.state=state;
|
|
515
|
-
const detail=
|
|
426
|
+
const detail={
|
|
516
427
|
state,
|
|
517
428
|
message,
|
|
518
429
|
key,
|
|
@@ -524,24 +435,14 @@ class SpeechPlayback{
|
|
|
524
435
|
operationId:this.operationId,
|
|
525
436
|
code,
|
|
526
437
|
reason
|
|
527
|
-
}
|
|
438
|
+
};
|
|
528
439
|
if(!this.destroyed){
|
|
529
440
|
this.events.dispatch(
|
|
530
441
|
SPEECH_PLAYBACK_STATE_EVENT,
|
|
531
442
|
detail,
|
|
532
443
|
{
|
|
533
444
|
operationId:this.operationId,
|
|
534
|
-
publicDetail:
|
|
535
|
-
state,
|
|
536
|
-
key,
|
|
537
|
-
index:detail.index,
|
|
538
|
-
total:detail.total,
|
|
539
|
-
producing:detail.producing,
|
|
540
|
-
buffered:detail.buffered,
|
|
541
|
-
hasAudio:detail.hasAudio,
|
|
542
|
-
code,
|
|
543
|
-
reason
|
|
544
|
-
}
|
|
445
|
+
publicDetail:detail
|
|
545
446
|
}
|
|
546
447
|
);
|
|
547
448
|
}
|
|
@@ -622,7 +523,7 @@ class SpeechPlayback{
|
|
|
622
523
|
async synthesizeSegment(index,generation,announce=false){
|
|
623
524
|
const playback=this;
|
|
624
525
|
const controller=new AbortController();
|
|
625
|
-
const token=
|
|
526
|
+
const token={generation,index,controller};
|
|
626
527
|
const queue=queueFor(this.speech);
|
|
627
528
|
this.pendingGenerations.add(token);
|
|
628
529
|
this.abortControllers.add(controller);
|
|
@@ -758,20 +659,20 @@ class SpeechPlayback{
|
|
|
758
659
|
if(!Number.isFinite(numericSpeed)||numericSpeed<=0)throw new RangeError('Speech speed must be a positive number.');
|
|
759
660
|
const selectedModel=model===null||model===undefined
|
|
760
661
|
?null
|
|
761
|
-
:String(model)
|
|
662
|
+
:String(model);
|
|
762
663
|
const selectedVoice=voice===null||voice===undefined
|
|
763
664
|
?null
|
|
764
|
-
:String(voice)
|
|
665
|
+
:String(voice);
|
|
765
666
|
const selectedResponseFormat=responseFormat===null||responseFormat===undefined
|
|
766
667
|
?null
|
|
767
|
-
:String(responseFormat)
|
|
768
|
-
if(model!==null&&model!==undefined&&!selectedModel){
|
|
668
|
+
:String(responseFormat);
|
|
669
|
+
if(model!==null&&model!==undefined&&!selectedModel.trim()){
|
|
769
670
|
throw new TypeError('Speech model cannot be blank.');
|
|
770
671
|
}
|
|
771
|
-
if(voice!==null&&voice!==undefined&&!selectedVoice){
|
|
672
|
+
if(voice!==null&&voice!==undefined&&!selectedVoice.trim()){
|
|
772
673
|
throw new TypeError('Speech voice cannot be blank.');
|
|
773
674
|
}
|
|
774
|
-
if(responseFormat!==null&&responseFormat!==undefined&&!selectedResponseFormat){
|
|
675
|
+
if(responseFormat!==null&&responseFormat!==undefined&&!selectedResponseFormat.trim()){
|
|
775
676
|
throw new TypeError('Speech response format cannot be blank.');
|
|
776
677
|
}
|
|
777
678
|
this.speed=numericSpeed;
|
|
@@ -965,10 +866,6 @@ class SpeechPlayback{
|
|
|
965
866
|
}
|
|
966
867
|
|
|
967
868
|
export {
|
|
968
|
-
MAX_SPEECH_CHARACTERS,
|
|
969
|
-
MAX_SPEECH_CHUNKS,
|
|
970
|
-
MAX_SPEECH_INPUT,
|
|
971
|
-
PREFERRED_STREAM_SEGMENT,
|
|
972
869
|
SPEECH_VOICE_ALIASES,
|
|
973
870
|
SPEECH_VOICE_OPTIONS,
|
|
974
871
|
SPEECH_PLAYBACK_STATE_EVENT,
|