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
|
@@ -538,59 +538,35 @@
|
|
|
538
538
|
}
|
|
539
539
|
}
|
|
540
540
|
|
|
541
|
-
table
|
|
542
|
-
|
|
543
|
-
|
|
541
|
+
/* Native table layout shares columns across rows and grows with complete cell content. */
|
|
542
|
+
.chat_output table {
|
|
543
|
+
width: 100%;
|
|
544
|
+
margin: .75em 0;
|
|
544
545
|
border-collapse: collapse;
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
box-shadow: 0 0 0.7em var(--border-color);
|
|
549
|
-
border-radius: 0.5em 0.5em 0.5em 0.5em;
|
|
550
|
-
border-spacing: unset;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
thead, tbody {
|
|
554
|
-
display: table; /* These elements behave like table rows */
|
|
555
|
-
width: 100%; /* Table rows take full available space */
|
|
556
|
-
table-layout: fixed; /* Ensures the table layout respects the width settings */
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
tbody tr{
|
|
560
|
-
height: 130px;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
thead tr{
|
|
564
|
-
background: var(--background);
|
|
565
|
-
color: var(--platinum);
|
|
566
|
-
border-radius: .5em .5em 0 0;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
tr{
|
|
570
|
-
display: grid;
|
|
571
|
-
grid-template-columns:
|
|
572
|
-
6em 1fr 1fr 1fr;
|
|
546
|
+
border-spacing: 0;
|
|
547
|
+
background: var(--arcane-surface, var(--background));
|
|
548
|
+
color: var(--text-color);
|
|
573
549
|
}
|
|
574
550
|
|
|
575
|
-
|
|
576
|
-
|
|
551
|
+
.chat_output th,
|
|
552
|
+
.chat_output td {
|
|
553
|
+
padding: .6em .75em;
|
|
554
|
+
border: 1px solid var(--arcane-border, var(--border-color));
|
|
555
|
+
vertical-align: top;
|
|
556
|
+
overflow-wrap: anywhere;
|
|
577
557
|
}
|
|
578
558
|
|
|
579
|
-
th,
|
|
580
|
-
|
|
581
|
-
|
|
559
|
+
.chat_output th:not([align]),
|
|
560
|
+
.chat_output td:not([align]) {
|
|
561
|
+
text-align: start;
|
|
582
562
|
}
|
|
583
563
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
padding:.4em;
|
|
564
|
+
.chat_output thead {
|
|
565
|
+
background: var(--arcane-surface-muted, var(--secondary-color));
|
|
587
566
|
}
|
|
588
567
|
|
|
589
|
-
|
|
590
|
-
background: var(--
|
|
591
|
-
padding:.4em;
|
|
592
|
-
border: 1px solid var(--accent-color);
|
|
593
|
-
overflow: visible;
|
|
568
|
+
.chat_output tbody tr:hover {
|
|
569
|
+
background: var(--arcane-surface-muted, var(--secondary-color));
|
|
594
570
|
}
|
|
595
571
|
</style>
|
|
596
572
|
|
|
@@ -833,6 +809,9 @@
|
|
|
833
809
|
</section>
|
|
834
810
|
|
|
835
811
|
<script type="module">
|
|
812
|
+
const {default:Is}=await import('strong-type');
|
|
813
|
+
const is=new Is(false);
|
|
814
|
+
|
|
836
815
|
const {arcaneLogging}=await import('arcane-os/logging');
|
|
837
816
|
|
|
838
817
|
const {
|
|
@@ -909,7 +888,7 @@
|
|
|
909
888
|
host.language=host.language||'English';
|
|
910
889
|
host.name = host.name||'User';
|
|
911
890
|
host.aiName='AI';
|
|
912
|
-
let requestedInitialSpeechMuted=
|
|
891
|
+
let requestedInitialSpeechMuted=is.boolean(speech.initialMuted)
|
|
913
892
|
?speech.initialMuted
|
|
914
893
|
:true;
|
|
915
894
|
let initialSpeechMuteListenerInstalled=false;
|
|
@@ -1017,8 +996,8 @@
|
|
|
1017
996
|
let causeCode='';
|
|
1018
997
|
let message='';
|
|
1019
998
|
try{
|
|
1020
|
-
causeCode=
|
|
1021
|
-
message=
|
|
999
|
+
causeCode=is.string(error?.code)?error.code:'';
|
|
1000
|
+
message=is.string(error?.message)?error.message:'';
|
|
1022
1001
|
}catch{}
|
|
1023
1002
|
return {
|
|
1024
1003
|
error,
|
|
@@ -1035,7 +1014,7 @@
|
|
|
1035
1014
|
}
|
|
1036
1015
|
|
|
1037
1016
|
function isPlainRecord(value){
|
|
1038
|
-
if(!value
|
|
1017
|
+
if(!value||!is.object(value)||is.array(value))return false;
|
|
1039
1018
|
const prototype=Object.getPrototypeOf(value);
|
|
1040
1019
|
return prototype===Object.prototype||prototype===null;
|
|
1041
1020
|
}
|
|
@@ -1045,10 +1024,10 @@
|
|
|
1045
1024
|
// Only errors deliberately classified by their owner may provide UI copy.
|
|
1046
1025
|
// Provider and protocol diagnostics remain complete in console/events.
|
|
1047
1026
|
if(error?.userSafe===true){
|
|
1048
|
-
const message=
|
|
1027
|
+
const message=is.string(error.userMessage)
|
|
1049
1028
|
?error.userMessage
|
|
1050
1029
|
:error.message;
|
|
1051
|
-
if(
|
|
1030
|
+
if(is.string(message)&&message.trim()){
|
|
1052
1031
|
return message;
|
|
1053
1032
|
}
|
|
1054
1033
|
}
|
|
@@ -1057,10 +1036,10 @@
|
|
|
1057
1036
|
}
|
|
1058
1037
|
|
|
1059
1038
|
function visibleProgressText(value,fallback,field){
|
|
1060
|
-
if(
|
|
1039
|
+
if(is.string(value)){
|
|
1061
1040
|
return value||fallback;
|
|
1062
1041
|
}
|
|
1063
|
-
if(value&&
|
|
1042
|
+
if(value&&is.object(value)){
|
|
1064
1043
|
arcaneLogging.error(`Arcane chat progress ${field} is not text.`,value);
|
|
1065
1044
|
return visibleErrorMessage(value,fallback);
|
|
1066
1045
|
}
|
|
@@ -1085,10 +1064,10 @@
|
|
|
1085
1064
|
|
|
1086
1065
|
function compatibleChatSession(session){
|
|
1087
1066
|
return Boolean(session)
|
|
1088
|
-
&&
|
|
1089
|
-
&&
|
|
1090
|
-
&&
|
|
1091
|
-
&&
|
|
1067
|
+
&&is.object(session)
|
|
1068
|
+
&&is.function(session.ready)
|
|
1069
|
+
&&is.function(session.history)
|
|
1070
|
+
&&is.function(session.send);
|
|
1092
1071
|
}
|
|
1093
1072
|
|
|
1094
1073
|
function scrollTranscriptToBottom(){
|
|
@@ -1102,7 +1081,7 @@
|
|
|
1102
1081
|
const value=timestamp instanceof Date
|
|
1103
1082
|
?timestamp
|
|
1104
1083
|
:new Date(timestamp);
|
|
1105
|
-
if(timestamp!==undefined&×tamp!==null&&
|
|
1084
|
+
if(timestamp!==undefined&×tamp!==null&&is.finite(value.getTime())){
|
|
1106
1085
|
time.dateTime=value.toISOString();
|
|
1107
1086
|
time.textContent=value.toLocaleTimeString([],{
|
|
1108
1087
|
hour:'2-digit',
|
|
@@ -1119,7 +1098,7 @@
|
|
|
1119
1098
|
|
|
1120
1099
|
function normalizeVisibleToolCalls(value){
|
|
1121
1100
|
if(value===undefined) return [];
|
|
1122
|
-
if(!
|
|
1101
|
+
if(!is.array(value)){
|
|
1123
1102
|
const failure=new TypeError('Chat session tool calls must be an array.');
|
|
1124
1103
|
failure.code='AI_CHAT_INVALID_TOOL_CALL';
|
|
1125
1104
|
throw failure;
|
|
@@ -1128,18 +1107,18 @@
|
|
|
1128
1107
|
return value.map((call,index)=>{
|
|
1129
1108
|
if(
|
|
1130
1109
|
!call
|
|
1131
|
-
|
|
1132
|
-
||
|
|
1110
|
+
||!is.object(call)
|
|
1111
|
+
||is.array(call)
|
|
1133
1112
|
||call.type!=='function'
|
|
1134
1113
|
||!call.function
|
|
1135
|
-
|
|
1136
|
-
||
|
|
1137
|
-
|
|
1114
|
+
||!is.object(call.function)
|
|
1115
|
+
||is.array(call.function)
|
|
1116
|
+
||!is.string(call.id)
|
|
1138
1117
|
||!call.id.trim()
|
|
1139
1118
|
||ids.has(call.id)
|
|
1140
|
-
|
|
1119
|
+
||!is.string(call.function.name)
|
|
1141
1120
|
||!call.function.name.trim()
|
|
1142
|
-
|
|
1121
|
+
||!is.string(call.function.arguments)
|
|
1143
1122
|
){
|
|
1144
1123
|
const failure=new TypeError(`Chat session tool call ${index+1} is invalid.`);
|
|
1145
1124
|
failure.code='AI_CHAT_INVALID_TOOL_CALL';
|
|
@@ -1157,9 +1136,9 @@
|
|
|
1157
1136
|
}
|
|
1158
1137
|
|
|
1159
1138
|
function copyCompleteChatData(value,seen=new Map()){
|
|
1160
|
-
if(value===null
|
|
1139
|
+
if(value===null||!is.object(value)) return value;
|
|
1161
1140
|
if(seen.has(value)) return seen.get(value);
|
|
1162
|
-
if(
|
|
1141
|
+
if(is.array(value)){
|
|
1163
1142
|
const result=[];
|
|
1164
1143
|
seen.set(value,result);
|
|
1165
1144
|
for(const item of value) result.push(copyCompleteChatData(item,seen));
|
|
@@ -1177,12 +1156,12 @@
|
|
|
1177
1156
|
|
|
1178
1157
|
function sameCompleteChatData(left,right,seen=new Map()){
|
|
1179
1158
|
if(Object.is(left,right)) return true;
|
|
1180
|
-
if(!left||!right
|
|
1181
|
-
if(
|
|
1159
|
+
if(!left||!right||!is.object(left)||!is.object(right)) return false;
|
|
1160
|
+
if(is.array(left)!==is.array(right)) return false;
|
|
1182
1161
|
const matched=seen.get(left);
|
|
1183
1162
|
if(matched!==undefined) return matched===right;
|
|
1184
1163
|
seen.set(left,right);
|
|
1185
|
-
if(
|
|
1164
|
+
if(is.array(left)){
|
|
1186
1165
|
return left.length===right.length
|
|
1187
1166
|
&&left.every((value,index)=>sameCompleteChatData(value,right[index],seen));
|
|
1188
1167
|
}
|
|
@@ -1216,7 +1195,7 @@
|
|
|
1216
1195
|
failure.code='AI_CHAT_INVALID_TOOL_CALL';
|
|
1217
1196
|
throw failure;
|
|
1218
1197
|
}
|
|
1219
|
-
if(
|
|
1198
|
+
if(!is.string(argumentsRecord.message)||!argumentsRecord.message.trim()){
|
|
1220
1199
|
const failure=new TypeError(
|
|
1221
1200
|
'Structural tool call arguments must include a nonempty user-facing message.'
|
|
1222
1201
|
);
|
|
@@ -1227,7 +1206,7 @@
|
|
|
1227
1206
|
}
|
|
1228
1207
|
|
|
1229
1208
|
function setPendingStructuralToolCalls(calls=[]){
|
|
1230
|
-
if(!
|
|
1209
|
+
if(!is.array(calls)||calls.length===0){
|
|
1231
1210
|
pendingStructuralToolCalls=[];
|
|
1232
1211
|
pendingStructuralToolMessage='';
|
|
1233
1212
|
return [];
|
|
@@ -1244,8 +1223,8 @@
|
|
|
1244
1223
|
}
|
|
1245
1224
|
|
|
1246
1225
|
function sameStructuralToolCalls(left,right){
|
|
1247
|
-
return
|
|
1248
|
-
&&
|
|
1226
|
+
return is.array(left)
|
|
1227
|
+
&&is.array(right)
|
|
1249
1228
|
&&left.length===right.length
|
|
1250
1229
|
&&left.every((call,index)=>sameStructuralToolCall(call,right[index]));
|
|
1251
1230
|
}
|
|
@@ -1308,7 +1287,7 @@
|
|
|
1308
1287
|
}
|
|
1309
1288
|
|
|
1310
1289
|
function setTranscriptMessageContent(item,content,timestamp){
|
|
1311
|
-
if(
|
|
1290
|
+
if(!is.string(content)){
|
|
1312
1291
|
throw new TypeError('Chat session message content must be a string.');
|
|
1313
1292
|
}
|
|
1314
1293
|
item.querySelector('.thinking')?.remove();
|
|
@@ -1345,8 +1324,8 @@
|
|
|
1345
1324
|
}
|
|
1346
1325
|
|
|
1347
1326
|
function latestCommittedTranscriptTurn(transcript,requestMessages){
|
|
1348
|
-
if(!
|
|
1349
|
-
const expected=
|
|
1327
|
+
if(!is.array(transcript)) return null;
|
|
1328
|
+
const expected=is.array(requestMessages)
|
|
1350
1329
|
?requestMessages
|
|
1351
1330
|
:[requestMessages];
|
|
1352
1331
|
if(!expected.length) return null;
|
|
@@ -1362,7 +1341,7 @@
|
|
|
1362
1341
|
}
|
|
1363
1342
|
|
|
1364
1343
|
function createTranscriptMessage(role,content,name,{timestamp,toolCalls}={}){
|
|
1365
|
-
if(
|
|
1344
|
+
if(!is.string(content)){
|
|
1366
1345
|
throw new TypeError('Chat session message content must be a string.');
|
|
1367
1346
|
}
|
|
1368
1347
|
const item=chatOutput.ownerDocument.createElement('li');
|
|
@@ -1402,7 +1381,7 @@
|
|
|
1402
1381
|
}
|
|
1403
1382
|
|
|
1404
1383
|
function createSavedRecordFallback(message,index){
|
|
1405
|
-
const content=isPlainRecord(message)&&
|
|
1384
|
+
const content=isPlainRecord(message)&&is.string(message.content)
|
|
1406
1385
|
?message.content
|
|
1407
1386
|
:'Saved record content is available in details.';
|
|
1408
1387
|
const item=createTranscriptMessage(
|
|
@@ -1425,7 +1404,7 @@
|
|
|
1425
1404
|
}
|
|
1426
1405
|
|
|
1427
1406
|
function renderSessionHistory(history){
|
|
1428
|
-
if(!
|
|
1407
|
+
if(!is.array(history)){
|
|
1429
1408
|
throw new TypeError('Chat session history must be an array.');
|
|
1430
1409
|
}
|
|
1431
1410
|
const fragment=chatOutput.ownerDocument.createDocumentFragment();
|
|
@@ -1442,7 +1421,7 @@
|
|
|
1442
1421
|
'AI_CHAT_INCOHERENT_PERSISTENCE'
|
|
1443
1422
|
);
|
|
1444
1423
|
}
|
|
1445
|
-
if(
|
|
1424
|
+
if(!is.string(message.content)){
|
|
1446
1425
|
throw chatError(
|
|
1447
1426
|
'Saved chat contains a record without text content.',
|
|
1448
1427
|
'AI_CHAT_INCOHERENT_PERSISTENCE'
|
|
@@ -1465,7 +1444,7 @@
|
|
|
1465
1444
|
if(message.role==='tool'){
|
|
1466
1445
|
if(message.tool_call_id!==undefined){
|
|
1467
1446
|
if(
|
|
1468
|
-
|
|
1447
|
+
!is.string(message.tool_call_id)
|
|
1469
1448
|
||!message.tool_call_id.trim()
|
|
1470
1449
|
||!message.content.trim()
|
|
1471
1450
|
||!restoredPendingToolCalls.has(message.tool_call_id)
|
|
@@ -1494,7 +1473,7 @@
|
|
|
1494
1473
|
const name=message.role==='user'
|
|
1495
1474
|
?host.name
|
|
1496
1475
|
:message.role==='tool'
|
|
1497
|
-
?
|
|
1476
|
+
?is.string(message.name)&&message.name.trim()
|
|
1498
1477
|
?`Tool · ${message.name}`
|
|
1499
1478
|
:'Tool'
|
|
1500
1479
|
:message.role==='system'
|
|
@@ -1573,7 +1552,7 @@
|
|
|
1573
1552
|
ai
|
|
1574
1553
|
});
|
|
1575
1554
|
await session.ready();
|
|
1576
|
-
const history=
|
|
1555
|
+
const history=is.function(session.transcript)
|
|
1577
1556
|
?await session.transcript()
|
|
1578
1557
|
:await session.history();
|
|
1579
1558
|
if(destroyed||generation!==sessionBindingGeneration){
|
|
@@ -1653,10 +1632,10 @@
|
|
|
1653
1632
|
|
|
1654
1633
|
function isAbortSignal(value){
|
|
1655
1634
|
return value!==null
|
|
1656
|
-
&&
|
|
1657
|
-
&&
|
|
1658
|
-
&&
|
|
1659
|
-
&&
|
|
1635
|
+
&&is.object(value)
|
|
1636
|
+
&&is.boolean(value.aborted)
|
|
1637
|
+
&&is.function(value.addEventListener)
|
|
1638
|
+
&&is.function(value.removeEventListener);
|
|
1660
1639
|
}
|
|
1661
1640
|
|
|
1662
1641
|
function createChatSubmissionAbort(reason,message){
|
|
@@ -1793,7 +1772,7 @@
|
|
|
1793
1772
|
host.destroy=destroy;
|
|
1794
1773
|
host.session=null;
|
|
1795
1774
|
host.sessionStatus={state:'idle',message:'Chat session is not connected.'};
|
|
1796
|
-
host.modelName=
|
|
1775
|
+
host.modelName=is.string(host.modelName)?host.modelName:'';
|
|
1797
1776
|
host.aiAvailability={llm:false,stt:false,tts:false};
|
|
1798
1777
|
host.conversationComplete=false;
|
|
1799
1778
|
applyAIAvailability(host.aiAvailability);
|
|
@@ -1826,7 +1805,7 @@
|
|
|
1826
1805
|
);
|
|
1827
1806
|
|
|
1828
1807
|
function setConversationComplete(complete=true){
|
|
1829
|
-
if(
|
|
1808
|
+
if(!is.boolean(complete)){
|
|
1830
1809
|
throw new TypeError('Conversation completion state must be boolean.');
|
|
1831
1810
|
}
|
|
1832
1811
|
|
|
@@ -1847,7 +1826,7 @@
|
|
|
1847
1826
|
}
|
|
1848
1827
|
|
|
1849
1828
|
function setInitialSpeechMuted(initialMuted){
|
|
1850
|
-
if(
|
|
1829
|
+
if(!is.boolean(initialMuted)){
|
|
1851
1830
|
throw new TypeError('initialMuted must be boolean');
|
|
1852
1831
|
}
|
|
1853
1832
|
|
|
@@ -1883,13 +1862,13 @@
|
|
|
1883
1862
|
}={}
|
|
1884
1863
|
){
|
|
1885
1864
|
const messageId=String(id);
|
|
1886
|
-
const normalizedTotal=
|
|
1865
|
+
const normalizedTotal=is.finite(Number(total))
|
|
1887
1866
|
?Number(total)
|
|
1888
1867
|
:0;
|
|
1889
|
-
const normalizedCurrent=
|
|
1868
|
+
const normalizedCurrent=is.finite(Number(current))
|
|
1890
1869
|
?Number(current)
|
|
1891
1870
|
:0;
|
|
1892
|
-
const normalizedFailed=
|
|
1871
|
+
const normalizedFailed=is.finite(Number(failed))
|
|
1893
1872
|
?Number(failed)
|
|
1894
1873
|
:0;
|
|
1895
1874
|
const message=messageId
|
|
@@ -1998,9 +1977,9 @@
|
|
|
1998
1977
|
|
|
1999
1978
|
function hasSelectedAIRuntimeRole(role){
|
|
2000
1979
|
const record=latestAIRuntimeRoles?.[role];
|
|
2001
|
-
return
|
|
1980
|
+
return is.string(record?.providerId)
|
|
2002
1981
|
&&record.providerId.length>0
|
|
2003
|
-
&&
|
|
1982
|
+
&&is.string(record?.modelId)
|
|
2004
1983
|
&&record.modelId.length>0;
|
|
2005
1984
|
}
|
|
2006
1985
|
|
|
@@ -2046,14 +2025,14 @@
|
|
|
2046
2025
|
}
|
|
2047
2026
|
|
|
2048
2027
|
function selected(){
|
|
2049
|
-
return
|
|
2028
|
+
return is.string(role?.providerId)
|
|
2050
2029
|
&&role.providerId.length>0
|
|
2051
|
-
&&
|
|
2030
|
+
&&is.string(role?.modelId)
|
|
2052
2031
|
&&role.modelId.length>0;
|
|
2053
2032
|
}
|
|
2054
2033
|
|
|
2055
2034
|
function modelDisplayName(){
|
|
2056
|
-
const configured=
|
|
2035
|
+
const configured=is.string(host.modelName)
|
|
2057
2036
|
?host.modelName.trim()
|
|
2058
2037
|
:'';
|
|
2059
2038
|
return configured||role?.modelId||'the selected language model';
|
|
@@ -2063,9 +2042,9 @@
|
|
|
2063
2042
|
const totalBytes=role?.progress?.totalBytes;
|
|
2064
2043
|
const loadedBytes=role?.progress?.loadedBytes;
|
|
2065
2044
|
if(
|
|
2066
|
-
|
|
2045
|
+
is.finite(totalBytes)
|
|
2067
2046
|
&&totalBytes>0
|
|
2068
|
-
&&
|
|
2047
|
+
&&is.finite(loadedBytes)
|
|
2069
2048
|
&&loadedBytes>=0
|
|
2070
2049
|
){
|
|
2071
2050
|
return {
|
|
@@ -2077,13 +2056,13 @@
|
|
|
2077
2056
|
}
|
|
2078
2057
|
const total=Number(role?.progress?.total);
|
|
2079
2058
|
const completed=Number(role?.progress?.completed);
|
|
2080
|
-
const unit=
|
|
2059
|
+
const unit=is.string(role?.progress?.unit)&&role.progress.unit
|
|
2081
2060
|
?role.progress.unit
|
|
2082
2061
|
:'items';
|
|
2083
2062
|
if(
|
|
2084
|
-
!
|
|
2063
|
+
!is.finite(total)
|
|
2085
2064
|
||total<=0
|
|
2086
|
-
||!
|
|
2065
|
+
||!is.finite(completed)
|
|
2087
2066
|
){
|
|
2088
2067
|
return null;
|
|
2089
2068
|
}
|
|
@@ -2096,7 +2075,7 @@
|
|
|
2096
2075
|
}
|
|
2097
2076
|
|
|
2098
2077
|
function formatBytes(value){
|
|
2099
|
-
if(!
|
|
2078
|
+
if(!is.finite(value)||value<0){
|
|
2100
2079
|
return '';
|
|
2101
2080
|
}
|
|
2102
2081
|
const bytes=value;
|
|
@@ -2127,7 +2106,7 @@
|
|
|
2127
2106
|
}
|
|
2128
2107
|
|
|
2129
2108
|
function approximateDuration(value){
|
|
2130
|
-
if(!
|
|
2109
|
+
if(!is.finite(value)||value<0){
|
|
2131
2110
|
return '';
|
|
2132
2111
|
}
|
|
2133
2112
|
const suppliedSeconds=value;
|
|
@@ -2151,13 +2130,13 @@
|
|
|
2151
2130
|
function activeTransferText(){
|
|
2152
2131
|
const active=role?.progress?.activeTransfers;
|
|
2153
2132
|
const limit=role?.progress?.transferLimit;
|
|
2154
|
-
const mode=
|
|
2133
|
+
const mode=is.string(role?.progress?.transferMode)
|
|
2155
2134
|
?role.progress.transferMode.trim().toLowerCase()
|
|
2156
2135
|
:'';
|
|
2157
2136
|
if(
|
|
2158
|
-
!
|
|
2137
|
+
!is.safeInteger(active)
|
|
2159
2138
|
||active<0
|
|
2160
|
-
||!
|
|
2139
|
+
||!is.safeInteger(limit)
|
|
2161
2140
|
||limit<1
|
|
2162
2141
|
||!mode
|
|
2163
2142
|
){
|
|
@@ -2183,7 +2162,7 @@
|
|
|
2183
2162
|
|
|
2184
2163
|
function progressElapsedText(){
|
|
2185
2164
|
const elapsedMilliseconds=Number(role?.progress?.elapsedMs);
|
|
2186
|
-
if(!
|
|
2165
|
+
if(!is.finite(elapsedMilliseconds)||elapsedMilliseconds<0){
|
|
2187
2166
|
return '';
|
|
2188
2167
|
}
|
|
2189
2168
|
const elapsedSeconds=Math.floor(elapsedMilliseconds/1000);
|
|
@@ -2201,7 +2180,7 @@
|
|
|
2201
2180
|
|
|
2202
2181
|
function progressMessage(){
|
|
2203
2182
|
const measured=determinateProgress();
|
|
2204
|
-
const phaseValue=
|
|
2183
|
+
const phaseValue=is.string(role?.progress?.phase)&&role.progress.phase
|
|
2205
2184
|
?role.progress.phase
|
|
2206
2185
|
:'loading';
|
|
2207
2186
|
const phase=phaseValue.replaceAll('-',' ');
|
|
@@ -2217,7 +2196,7 @@
|
|
|
2217
2196
|
);
|
|
2218
2197
|
parts.push(`${formatBytes(remainingBytes)} remaining`);
|
|
2219
2198
|
const bytesPerSecond=role?.progress?.bytesPerSecond;
|
|
2220
|
-
if(
|
|
2199
|
+
if(is.finite(bytesPerSecond)&&bytesPerSecond>=0){
|
|
2221
2200
|
parts.push(`${formatBytes(bytesPerSecond)}/s`);
|
|
2222
2201
|
}else{
|
|
2223
2202
|
parts.push('Calculating speed');
|
|
@@ -2342,7 +2321,7 @@
|
|
|
2342
2321
|
requestError='';
|
|
2343
2322
|
const intent={role:'llm',action,reason:'user'};
|
|
2344
2323
|
const request={intent,state:role};
|
|
2345
|
-
const operationId=
|
|
2324
|
+
const operationId=is.string(role?.operationId)&&role.operationId
|
|
2346
2325
|
?role.operationId
|
|
2347
2326
|
:createOperationId('llm-activation');
|
|
2348
2327
|
const generation=++requestGeneration;
|
|
@@ -2480,9 +2459,9 @@
|
|
|
2480
2459
|
if(
|
|
2481
2460
|
!controller
|
|
2482
2461
|
||requiredMethods.some(function missingConversationTimeboxMethod(name){
|
|
2483
|
-
return
|
|
2462
|
+
return !is.function(controller[name]);
|
|
2484
2463
|
})
|
|
2485
|
-
|
|
2464
|
+
||!is.string(controller.limitReachedMessage)
|
|
2486
2465
|
){
|
|
2487
2466
|
throw new TypeError('A compatible conversation timebox controller is required.');
|
|
2488
2467
|
}
|
|
@@ -2583,7 +2562,7 @@
|
|
|
2583
2562
|
}
|
|
2584
2563
|
|
|
2585
2564
|
function queueConversationTimeboxMessage(message,context,guard){
|
|
2586
|
-
const operationId=
|
|
2565
|
+
const operationId=is.string(context?.operationId)&&context.operationId
|
|
2587
2566
|
?context.operationId
|
|
2588
2567
|
:nextChatOperationId('conversation-timebox');
|
|
2589
2568
|
const deliveryContext={...context,operationId};
|
|
@@ -2597,7 +2576,7 @@
|
|
|
2597
2576
|
if(destroyed||aiRuntimeStateAbortController.signal.aborted){
|
|
2598
2577
|
return false;
|
|
2599
2578
|
}
|
|
2600
|
-
if(
|
|
2579
|
+
if(is.function(guard)&&!guard()){
|
|
2601
2580
|
return false;
|
|
2602
2581
|
}
|
|
2603
2582
|
let lastError;
|
|
@@ -2615,7 +2594,7 @@
|
|
|
2615
2594
|
if(destroyed||aiRuntimeStateAbortController.signal.aborted){
|
|
2616
2595
|
return false;
|
|
2617
2596
|
}
|
|
2618
|
-
if(
|
|
2597
|
+
if(is.function(guard)&&!guard()){
|
|
2619
2598
|
return false;
|
|
2620
2599
|
}
|
|
2621
2600
|
if(
|
|
@@ -2638,7 +2617,7 @@
|
|
|
2638
2617
|
if(destroyed||aiRuntimeStateAbortController.signal.aborted){
|
|
2639
2618
|
return false;
|
|
2640
2619
|
}
|
|
2641
|
-
if(
|
|
2620
|
+
if(is.function(guard)&&!guard()){
|
|
2642
2621
|
return false;
|
|
2643
2622
|
}
|
|
2644
2623
|
return requireConversationTimeboxDelivery(delivered);
|
|
@@ -2657,7 +2636,7 @@
|
|
|
2657
2636
|
if(destroyed||aiRuntimeStateAbortController.signal.aborted){
|
|
2658
2637
|
return false;
|
|
2659
2638
|
}
|
|
2660
|
-
if(
|
|
2639
|
+
if(is.function(guard)&&!guard()){
|
|
2661
2640
|
return false;
|
|
2662
2641
|
}
|
|
2663
2642
|
if(result!==false){
|
|
@@ -2673,7 +2652,7 @@
|
|
|
2673
2652
|
if(destroyed||aiRuntimeStateAbortController.signal.aborted){
|
|
2674
2653
|
return false;
|
|
2675
2654
|
}
|
|
2676
|
-
if(
|
|
2655
|
+
if(is.function(guard)&&!guard()){
|
|
2677
2656
|
return false;
|
|
2678
2657
|
}
|
|
2679
2658
|
setConversationTimeboxError(
|
|
@@ -2746,7 +2725,7 @@
|
|
|
2746
2725
|
);
|
|
2747
2726
|
|
|
2748
2727
|
async function streamMessage(text='', id='', isThinking){
|
|
2749
|
-
if(
|
|
2728
|
+
if(!is.string(text)){
|
|
2750
2729
|
if(text instanceof Error){
|
|
2751
2730
|
arcaneLogging.error('Arcane chat stream delivered an Error as content.',text);
|
|
2752
2731
|
throw text;
|
|
@@ -2816,10 +2795,8 @@
|
|
|
2816
2795
|
&&speech.muted===false
|
|
2817
2796
|
){
|
|
2818
2797
|
const aiRuntime=boundChatAI??globalThis.ai;
|
|
2819
|
-
if(
|
|
2820
|
-
void Promise.resolve(aiRuntime.streamTTS(
|
|
2821
|
-
text,false,{textFormat:'markdown'}
|
|
2822
|
-
)).catch(
|
|
2798
|
+
if(is.function(aiRuntime?.streamTTS)){
|
|
2799
|
+
void Promise.resolve(aiRuntime.streamTTS(text)).catch(
|
|
2823
2800
|
reportTTSError
|
|
2824
2801
|
);
|
|
2825
2802
|
}else{
|
|
@@ -3072,7 +3049,7 @@
|
|
|
3072
3049
|
);
|
|
3073
3050
|
}
|
|
3074
3051
|
|
|
3075
|
-
const sessionRequestMessages=
|
|
3052
|
+
const sessionRequestMessages=is.array(sessionRequest)
|
|
3076
3053
|
?sessionRequest
|
|
3077
3054
|
:[sessionRequest];
|
|
3078
3055
|
if(!sessionRequestMessages.length){
|
|
@@ -3105,7 +3082,7 @@
|
|
|
3105
3082
|
status:'Working'
|
|
3106
3083
|
}
|
|
3107
3084
|
);
|
|
3108
|
-
const result=
|
|
3085
|
+
const result=is.function(session.stream)
|
|
3109
3086
|
?await session.stream(
|
|
3110
3087
|
request,
|
|
3111
3088
|
{
|
|
@@ -3156,13 +3133,13 @@
|
|
|
3156
3133
|
){
|
|
3157
3134
|
return false;
|
|
3158
3135
|
}
|
|
3159
|
-
if(!result
|
|
3136
|
+
if(!result||!is.object(result)||is.array(result)){
|
|
3160
3137
|
throw new TypeError('The chat session returned an invalid result.');
|
|
3161
3138
|
}
|
|
3162
|
-
if(!result.message
|
|
3139
|
+
if(!result.message||!is.string(result.message.content)){
|
|
3163
3140
|
throw new TypeError('The chat session result must contain assistant message content.');
|
|
3164
3141
|
}
|
|
3165
|
-
const committedTurn=
|
|
3142
|
+
const committedTurn=is.function(session.transcript)
|
|
3166
3143
|
?latestCommittedTranscriptTurn(
|
|
3167
3144
|
await session.transcript(),
|
|
3168
3145
|
sessionRequestMessages
|
|
@@ -3353,7 +3330,7 @@
|
|
|
3353
3330
|
error.code='AI_CHAT_TOOL_RESULT_NOT_PENDING';
|
|
3354
3331
|
throw error;
|
|
3355
3332
|
}
|
|
3356
|
-
if(!
|
|
3333
|
+
if(!is.array(options.results)||options.results.length===0){
|
|
3357
3334
|
throw new TypeError('Tool results must be a nonempty array.');
|
|
3358
3335
|
}
|
|
3359
3336
|
const statuses=new Map([
|
|
@@ -3395,7 +3372,7 @@
|
|
|
3395
3372
|
}
|
|
3396
3373
|
const toolCallId=result.toolCallId;
|
|
3397
3374
|
if(
|
|
3398
|
-
|
|
3375
|
+
!is.string(toolCallId)
|
|
3399
3376
|
||!pendingById.has(toolCallId)
|
|
3400
3377
|
||resultsById.has(toolCallId)
|
|
3401
3378
|
){
|
|
@@ -3418,11 +3395,11 @@
|
|
|
3418
3395
|
'Tool-result status must be executed, declined, cancelled, or not-executed.'
|
|
3419
3396
|
);
|
|
3420
3397
|
}
|
|
3421
|
-
if(
|
|
3398
|
+
if(!is.string(result.message)||!result.message.trim()){
|
|
3422
3399
|
throw new TypeError('Tool-result message must contain user-facing text.');
|
|
3423
3400
|
}
|
|
3424
3401
|
const persist=result.persist??true;
|
|
3425
|
-
if(
|
|
3402
|
+
if(!is.boolean(persist)){
|
|
3426
3403
|
throw new TypeError('Tool-result persist must be boolean.');
|
|
3427
3404
|
}
|
|
3428
3405
|
resultsById.set(toolCallId,{
|
|
@@ -3452,7 +3429,7 @@
|
|
|
3452
3429
|
error.code='AI_CHAT_INCOHERENT_PERSISTENCE';
|
|
3453
3430
|
throw error;
|
|
3454
3431
|
}
|
|
3455
|
-
const operationId=
|
|
3432
|
+
const operationId=is.string(context.operationId)&&context.operationId
|
|
3456
3433
|
?context.operationId
|
|
3457
3434
|
:nextChatOperationId('tool-results');
|
|
3458
3435
|
const ownership=createChatSubmissionOwnership(context.signal??null);
|
|
@@ -3582,10 +3559,10 @@
|
|
|
3582
3559
|
if(destroyed){
|
|
3583
3560
|
return false;
|
|
3584
3561
|
}
|
|
3585
|
-
if(
|
|
3562
|
+
if(!is.string(textOverride)){
|
|
3586
3563
|
throw new TypeError('Programmatic chat messages must be strings.');
|
|
3587
3564
|
}
|
|
3588
|
-
if(!context
|
|
3565
|
+
if(!context||!is.object(context)||is.array(context)){
|
|
3589
3566
|
throw new TypeError('Chat submission context must be an object.');
|
|
3590
3567
|
}
|
|
3591
3568
|
if(host.conversationComplete){
|
|
@@ -3612,7 +3589,7 @@
|
|
|
3612
3589
|
if(!text.trim()){
|
|
3613
3590
|
return false;
|
|
3614
3591
|
}
|
|
3615
|
-
const operationId=
|
|
3592
|
+
const operationId=is.string(submissionContext.operationId)
|
|
3616
3593
|
&&submissionContext.operationId
|
|
3617
3594
|
?submissionContext.operationId
|
|
3618
3595
|
:nextChatOperationId('message');
|
|
@@ -3682,7 +3659,7 @@
|
|
|
3682
3659
|
if(host.aiAvailability.tts&&speech.muted===false){
|
|
3683
3660
|
const aiRuntime=boundChatAI??globalThis.ai;
|
|
3684
3661
|
aiRuntime?.stopAudio?.();
|
|
3685
|
-
if(
|
|
3662
|
+
if(is.function(aiRuntime?.resumeAudio)){
|
|
3686
3663
|
void Promise.resolve(aiRuntime.resumeAudio()).catch(
|
|
3687
3664
|
function reportPlaybackResumeFailure(error){
|
|
3688
3665
|
reportTTSError(error,'playback-resume');
|
|
@@ -3719,7 +3696,7 @@
|
|
|
3719
3696
|
if(destroyed){
|
|
3720
3697
|
return false;
|
|
3721
3698
|
}
|
|
3722
|
-
if(
|
|
3699
|
+
if(is.function(speech.reportTTSError)){
|
|
3723
3700
|
try{
|
|
3724
3701
|
speech.reportTTSError(error,boundary);
|
|
3725
3702
|
return true;
|