arcane-os 0.5.12 → 0.5.14
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/browser-runtime/ai/browser-wasm-llm-provider.mjs +11 -10
- package/browser-runtime/ai/browser-wllama-runtime.mjs +2 -1
- package/browser-runtime/ai/model-controller.mjs +6 -5
- package/browser-runtime/ai/speech-worker-client.mjs +45 -3
- package/browser-runtime/event-manager.mjs +2 -1
- package/browser-runtime/logging.mjs +58 -0
- package/docs/reference/README.md +8 -7
- package/docs/reference/ai/browser-speech.md +46 -1
- package/docs/reference/asset-versioning.md +69 -0
- package/docs/reference/inventory/package-api.json +30 -2
- package/docs/reference/runtime-modules.md +18 -0
- package/docs/reference/sdk-api.md +94 -8
- package/package.json +3 -2
- package/runtime/arcane/components/app-bar.html +3 -1
- package/runtime/arcane/components/calculator.html +1 -1
- package/runtime/arcane/components/chart.html +2 -7
- package/runtime/arcane/components/chat.html +22 -20
- package/runtime/arcane/components/dashboard-config.html +6 -9
- package/runtime/arcane/components/data-maintenance.html +4 -2
- package/runtime/arcane/components/data-view.html +3 -1
- package/runtime/arcane/components/directory-picker.html +3 -1
- package/runtime/arcane/components/file-manager.html +17 -15
- package/runtime/arcane/components/header.html +5 -3
- package/runtime/arcane/components/markdown-document.html +4 -7
- package/runtime/arcane/components/markdown-editor.html +6 -9
- package/runtime/arcane/components/media-embed.html +1 -1
- package/runtime/arcane/components/modal.html +3 -1
- package/runtime/arcane/components/screen-capture.html +4 -2
- package/runtime/arcane/components/speech.html +10 -8
- package/runtime/arcane/components/table.html +3 -1
- package/runtime/arcane/components/voice-transcription.html +12 -15
- package/runtime/arcane/entities/Chat.js +5 -4
- package/runtime/arcane/entities/User.js +2 -1
- package/runtime/arcane/modules/AI.js +442 -292
- package/runtime/arcane/modules/AIProviderRuntime.js +359 -82
- package/runtime/arcane/modules/CommunicationAppController.js +2 -1
- package/runtime/arcane/modules/ComponentContracts.js +3 -2
- package/runtime/arcane/modules/ConversationTimebox.js +2 -1
- package/runtime/arcane/modules/DBOPFS.js +5 -4
- package/runtime/arcane/modules/Errors.js +3 -14
- package/runtime/arcane/modules/HTMLImport.js +188 -16
- package/runtime/arcane/modules/LocalAIReadinessController.js +2 -1
- package/runtime/arcane/modules/MD.js +3 -2
- package/runtime/arcane/modules/MailOutbox.mjs +2 -1
- package/runtime/arcane/modules/PersistentAIChatSession.js +2 -1
- package/runtime/arcane/modules/ScreenCapture.js +2 -1
- package/runtime/arcane/modules/ThemeBootstrap.js +3 -2
- package/runtime/arcane/modules/ToolCallRouter.js +2 -1
- package/src/dev-server.mjs +72 -5
- package/src/import-map.mjs +603 -16
- package/src/installed-sdk-runtime.mjs +1 -0
- package/src/packager/core.mjs +60 -1
- package/src/workspace-runtime.mjs +19 -7
|
@@ -343,6 +343,8 @@
|
|
|
343
343
|
<html-import id="deleteModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
|
|
344
344
|
|
|
345
345
|
<script type="module">
|
|
346
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
347
|
+
|
|
346
348
|
import('../modules/DBOPFS.js');
|
|
347
349
|
//importing Document at the end of the file to avoid blocking;
|
|
348
350
|
|
|
@@ -461,7 +463,7 @@
|
|
|
461
463
|
()=>uploadFiles().catch(
|
|
462
464
|
error=>{
|
|
463
465
|
if(!destroyed){
|
|
464
|
-
|
|
466
|
+
arcaneLogging.error('Unable to upload files:',error);
|
|
465
467
|
}
|
|
466
468
|
}
|
|
467
469
|
),
|
|
@@ -481,7 +483,7 @@
|
|
|
481
483
|
openDirectory(directoryElement.dataset.directory).catch(
|
|
482
484
|
error=>{
|
|
483
485
|
if(!destroyed){
|
|
484
|
-
|
|
486
|
+
arcaneLogging.error('Unable to open directory:',error);
|
|
485
487
|
}
|
|
486
488
|
}
|
|
487
489
|
);
|
|
@@ -825,8 +827,8 @@
|
|
|
825
827
|
icon.className='tree-entry-icon';
|
|
826
828
|
icon.alt='';
|
|
827
829
|
icon.src=entry.kind==='directory'
|
|
828
|
-
?'./arcane/img/folder.svg'
|
|
829
|
-
:'./arcane/img/doc.svg';
|
|
830
|
+
?new URL('./arcane/img/folder.svg',document.baseURI).href
|
|
831
|
+
:new URL('./arcane/img/doc.svg',document.baseURI).href;
|
|
830
832
|
name.className='tree-entry-name';
|
|
831
833
|
name.innerText=entry.name;
|
|
832
834
|
count.className='tree-file-count';
|
|
@@ -1205,7 +1207,7 @@
|
|
|
1205
1207
|
false,
|
|
1206
1208
|
nextOperationId('open-error')
|
|
1207
1209
|
);
|
|
1208
|
-
|
|
1210
|
+
arcaneLogging.error('Unable to open file:',error);
|
|
1209
1211
|
}
|
|
1210
1212
|
return false;
|
|
1211
1213
|
}
|
|
@@ -1404,14 +1406,14 @@
|
|
|
1404
1406
|
deleteButton.innerText='Delete File';
|
|
1405
1407
|
deleteIcon.alt='';
|
|
1406
1408
|
deleteIcon.className='action-icon';
|
|
1407
|
-
deleteIcon.src='./arcane/img/trash.svg';
|
|
1409
|
+
deleteIcon.src=new URL('./arcane/img/trash.svg',document.baseURI).href;
|
|
1408
1410
|
deleteButton.prepend(deleteIcon);
|
|
1409
1411
|
deleteButton.addEventListener(
|
|
1410
1412
|
'click',
|
|
1411
1413
|
()=>confirmDelete(directory,fileName,true).catch(
|
|
1412
1414
|
error=>{
|
|
1413
1415
|
if(!destroyed){
|
|
1414
|
-
|
|
1416
|
+
arcaneLogging.error('Unable to delete file:',error);
|
|
1415
1417
|
}
|
|
1416
1418
|
}
|
|
1417
1419
|
),
|
|
@@ -1455,7 +1457,7 @@
|
|
|
1455
1457
|
}catch(error){
|
|
1456
1458
|
if(!destroyed&&generation===fileOpenGeneration){
|
|
1457
1459
|
status.innerText='Unable to open this file.';
|
|
1458
|
-
|
|
1460
|
+
arcaneLogging.error('Unable to open file:',error);
|
|
1459
1461
|
}
|
|
1460
1462
|
return false;
|
|
1461
1463
|
}
|
|
@@ -1610,7 +1612,7 @@
|
|
|
1610
1612
|
|
|
1611
1613
|
fileIcon.alt='';
|
|
1612
1614
|
fileIcon.className='icon file-icon';
|
|
1613
|
-
fileIcon.src='./arcane/img/doc.svg';
|
|
1615
|
+
fileIcon.src=new URL('./arcane/img/doc.svg',document.baseURI).href;
|
|
1614
1616
|
fileDetails.className='file-details';
|
|
1615
1617
|
fileLabel.className='file-name';
|
|
1616
1618
|
fileLabel.innerText=fileName;
|
|
@@ -1633,7 +1635,7 @@
|
|
|
1633
1635
|
|
|
1634
1636
|
deleteIcon.alt='';
|
|
1635
1637
|
deleteIcon.className='action-icon';
|
|
1636
|
-
deleteIcon.src='./arcane/img/trash.svg';
|
|
1638
|
+
deleteIcon.src=new URL('./arcane/img/trash.svg',document.baseURI).href;
|
|
1637
1639
|
|
|
1638
1640
|
openButton.addEventListener(
|
|
1639
1641
|
'click',
|
|
@@ -1649,7 +1651,7 @@
|
|
|
1649
1651
|
}
|
|
1650
1652
|
|
|
1651
1653
|
openFile(directory,fileName).catch(
|
|
1652
|
-
error=>
|
|
1654
|
+
error=>arcaneLogging.error('Unable to open file:',error)
|
|
1653
1655
|
);
|
|
1654
1656
|
},
|
|
1655
1657
|
{signal:lifecycleController.signal}
|
|
@@ -1662,7 +1664,7 @@
|
|
|
1662
1664
|
}
|
|
1663
1665
|
|
|
1664
1666
|
confirmDelete(directory,fileName).catch(
|
|
1665
|
-
error=>
|
|
1667
|
+
error=>arcaneLogging.error('Unable to delete file:',error)
|
|
1666
1668
|
);
|
|
1667
1669
|
},
|
|
1668
1670
|
{signal:lifecycleController.signal}
|
|
@@ -1747,7 +1749,7 @@
|
|
|
1747
1749
|
message.innerText=`Unable to delete ${fileName}.`;
|
|
1748
1750
|
cancelButton.disabled=false;
|
|
1749
1751
|
deleteButton.disabled=false;
|
|
1750
|
-
|
|
1752
|
+
arcaneLogging.error('Unable to delete file:',error);
|
|
1751
1753
|
}
|
|
1752
1754
|
}
|
|
1753
1755
|
},
|
|
@@ -1850,7 +1852,7 @@
|
|
|
1850
1852
|
}catch(error){
|
|
1851
1853
|
if(!destroyed){
|
|
1852
1854
|
initialized=false;
|
|
1853
|
-
|
|
1855
|
+
arcaneLogging.error('Unable to initialize file manager:',error);
|
|
1854
1856
|
}
|
|
1855
1857
|
}
|
|
1856
1858
|
}
|
|
@@ -1933,7 +1935,7 @@
|
|
|
1933
1935
|
directory.dataset.directory=tableName;
|
|
1934
1936
|
folder.className='file folder';
|
|
1935
1937
|
folderIcon.className='icon';
|
|
1936
|
-
folderIcon.src='./arcane/img/folder.svg';
|
|
1938
|
+
folderIcon.src=new URL('./arcane/img/folder.svg',document.baseURI).href;
|
|
1937
1939
|
folderName.innerText=tableName;
|
|
1938
1940
|
fileCount.className='file-count';
|
|
1939
1941
|
fileCount.innerText=`${files.length} ${files.length===1?'file':'files'}`;
|
|
@@ -78,6 +78,8 @@
|
|
|
78
78
|
</header>
|
|
79
79
|
|
|
80
80
|
<script type="module">
|
|
81
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
82
|
+
|
|
81
83
|
import('../entities/User.js');
|
|
82
84
|
|
|
83
85
|
const host=this;
|
|
@@ -123,17 +125,17 @@
|
|
|
123
125
|
if (skin) {
|
|
124
126
|
document.body.className = skin;
|
|
125
127
|
} else {
|
|
126
|
-
|
|
128
|
+
arcaneLogging.log('No saved skin found. Using default.');
|
|
127
129
|
}
|
|
128
130
|
} catch (err) {
|
|
129
|
-
|
|
131
|
+
arcaneLogging.error('Failed to set global saved skin', err);
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
// Check if user can connect to the internet (make sure the cloud can be reached)
|
|
134
136
|
async function checkInternet() {
|
|
135
137
|
const online = navigator.onLine;
|
|
136
|
-
|
|
138
|
+
arcaneLogging.log(`Internet status: ${online ? 'Online' : 'Offline'}`);
|
|
137
139
|
host.shadowRoot.querySelector('.internet-status')
|
|
138
140
|
.classList
|
|
139
141
|
.toggle('online', online);
|
|
@@ -211,15 +211,12 @@
|
|
|
211
211
|
</section>
|
|
212
212
|
|
|
213
213
|
<script type="module">
|
|
214
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
215
|
+
|
|
214
216
|
const host=this;
|
|
215
217
|
host.ready=false;
|
|
216
218
|
|
|
217
|
-
const
|
|
218
|
-
host.getAttribute('href')||'./arcane/components/markdown-document.html',
|
|
219
|
-
document.baseURI
|
|
220
|
-
);
|
|
221
|
-
const moduleURL=name=>new URL(`../modules/${name}`,componentURL).href;
|
|
222
|
-
const {default:MD}=await import(moduleURL('MD.js?v=2'));
|
|
219
|
+
const {default:MD}=await import('../modules/MD.js?v=2');
|
|
223
220
|
const {createArcaneEventSource,projectArcaneDOMEvent}=await import('arcane-os/event-manager');
|
|
224
221
|
const events=createArcaneEventSource(host,{source:'arcane.component.markdown-document',eventTypes:['markdown-document-state','markdown-document-empty','markdown-document-error','markdown-document-loading','markdown-document-rendered','markdown-document-navigate','markdown-document-ready']});
|
|
225
222
|
const lifecycleController=new AbortController();
|
|
@@ -888,7 +885,7 @@
|
|
|
888
885
|
Promise.resolve(options.onNavigate(detail,{signal:lifecycleController.signal,operationId})).catch(
|
|
889
886
|
error=>{
|
|
890
887
|
if(!destroyed){
|
|
891
|
-
|
|
888
|
+
arcaneLogging.error('Markdown document navigation callback failed.',error);
|
|
892
889
|
}
|
|
893
890
|
}
|
|
894
891
|
);
|
|
@@ -74,17 +74,14 @@
|
|
|
74
74
|
</section>
|
|
75
75
|
|
|
76
76
|
<script type="module">
|
|
77
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
78
|
+
|
|
77
79
|
const host=this;
|
|
78
|
-
const
|
|
79
|
-
host.getAttribute('href')||'./arcane/components/markdown-editor.html',
|
|
80
|
-
document.baseURI
|
|
81
|
-
);
|
|
82
|
-
const moduleURL=name=>new URL(`../modules/${name}`,componentURL).href;
|
|
83
|
-
const {default:MD}=await import(moduleURL('MD.js?v=2'));
|
|
80
|
+
const {default:MD}=await import('../modules/MD.js?v=2');
|
|
84
81
|
const {
|
|
85
82
|
applyMarkdownFormat,
|
|
86
83
|
normalizeMarkdownOptions
|
|
87
|
-
}=await import(
|
|
84
|
+
}=await import('../modules/ComponentContracts.js');
|
|
88
85
|
const {createArcaneEventSource,projectArcaneDOMEvent}=await import('arcane-os/event-manager');
|
|
89
86
|
const events=createArcaneEventSource(host,{source:'arcane.component.markdown-editor',eventTypes:['markdown-editor-change','markdown-editor-saved','markdown-editor-ready']});
|
|
90
87
|
const lifecycleController=new AbortController();
|
|
@@ -234,7 +231,7 @@
|
|
|
234
231
|
emit('markdown-editor-change',detail,detail);
|
|
235
232
|
if(options.onChange){
|
|
236
233
|
Promise.resolve(options.onChange(detail)).catch(
|
|
237
|
-
error=>
|
|
234
|
+
error=>arcaneLogging.error('Markdown change callback failed:',error)
|
|
238
235
|
);
|
|
239
236
|
}
|
|
240
237
|
}
|
|
@@ -334,7 +331,7 @@
|
|
|
334
331
|
return false;
|
|
335
332
|
}
|
|
336
333
|
status.innerText=options.labels.saveError;
|
|
337
|
-
|
|
334
|
+
arcaneLogging.error('Unable to save Markdown content:',error);
|
|
338
335
|
return false;
|
|
339
336
|
}finally{
|
|
340
337
|
if(saveController===controller){
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<link rel="stylesheet" href="./arcane/css/theme.css?v=1"><link rel="stylesheet" href="./arcane/css/primitives.css?v=1">
|
|
2
2
|
<style>:host{display:block}.player-shell{display:grid;gap:var(--arcane-space-4)}.loader{display:flex;gap:var(--arcane-space-2)}.loader input{min-width:0;width:100%}.player{aspect-ratio:16/9;display:grid;place-items:center;background:var(--arcane-surface-muted);border:1px solid var(--arcane-border);border-radius:var(--arcane-radius-large)}iframe{width:100%;height:100%;border:0}.empty{text-align:center;color:var(--arcane-muted);padding:var(--arcane-space-5)}.footer{align-items:center;display:flex;gap:var(--arcane-space-3);justify-content:space-between}.status{margin:0;color:var(--arcane-muted)}@media(max-width:36rem){.loader,.footer{align-items:stretch;flex-direction:column}}</style>
|
|
3
3
|
<section class="player-shell"><form id="loader" class="loader"><label class="visually-hidden" for="mediaUrl">Video or playlist address</label><input id="mediaUrl" type="text" inputmode="url" autocomplete="off" spellcheck="false" placeholder="Paste a YouTube video or playlist URL"><button class="arcane-button" type="submit">Play</button></form><div class="player"><div id="empty" class="empty"><strong>Choose something to play</strong><p>Paste a YouTube or YouTube Music video or playlist address.</p></div><iframe id="frame" title="Embedded media player" hidden allow="autoplay; encrypted-media; picture-in-picture; fullscreen" allowfullscreen></iframe></div><div class="footer"><p id="status" class="status" role="status" aria-live="polite">Nothing loaded.</p><button id="platform" class="arcane-button arcane-button--secondary" type="button">Open platform</button></div></section>
|
|
4
|
-
<script type="module">const host=this,root=host.shadowRoot,form=root.querySelector('#loader'),input=root.querySelector('#mediaUrl'),frame=root.querySelector('#frame'),empty=root.querySelector('#empty'),status=root.querySelector('#status');const
|
|
4
|
+
<script type="module">const host=this,root=host.shadowRoot,form=root.querySelector('#loader'),input=root.querySelector('#mediaUrl'),frame=root.querySelector('#frame'),empty=root.querySelector('#empty'),status=root.querySelector('#status');const {parseYouTubeMedia,youtubeEmbedUrl}=await import('../modules/YouTubeMedia.js');const {createArcaneEventSource,projectArcaneDOMEvent}=await import('arcane-os/event-manager');const events=createArcaneEventSource(host,{source:'arcane.component.media-embed',eventTypes:['media-open-platform','media-load','media-error','media-embed-ready']}),lifecycleController=new AbortController();let platformUrl='https://www.youtube.com/',privacyEnhanced=false,destroyed=false,operationSequence=0;
|
|
5
5
|
function nextOperationId(kind){operationSequence+=1;return `${events.descriptor.instanceId}:${kind}:${operationSequence}`}
|
|
6
6
|
function emit(type,detail={},publicDetail={},operationId=null){if(destroyed)return false;const publication=events.dispatch(type,detail,{publicDetail,operationId});return projectArcaneDOMEvent(host,publication.occurrence,{bubbles:true,composed:true})}
|
|
7
7
|
host.configure=options=>{if(destroyed)return false;platformUrl=String(options?.platformUrl||platformUrl);if(Object.hasOwn(options||{},'privacyEnhanced'))privacyEnhanced=options.privacyEnhanced===true;if(options?.placeholder)input.placeholder=String(options.placeholder);if(options?.openLabel)root.querySelector('#platform').textContent=String(options.openLabel);if(options?.initialValue){input.value=String(options.initialValue);load(input.value)}return host};host.load=load;host.destroy=destroy;
|
|
@@ -156,6 +156,8 @@
|
|
|
156
156
|
</dialog>
|
|
157
157
|
|
|
158
158
|
<script type="module">
|
|
159
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
160
|
+
|
|
159
161
|
const host=this;
|
|
160
162
|
const shadowRoot=host.shadowRoot;
|
|
161
163
|
const {createArcaneEventSource,projectArcaneDOMEvent}=await import('arcane-os/event-manager');
|
|
@@ -384,7 +386,7 @@
|
|
|
384
386
|
}catch(error){
|
|
385
387
|
rows[index].row.dataset.status='failed';
|
|
386
388
|
rows[index].status.innerText='Unable to complete';
|
|
387
|
-
|
|
389
|
+
arcaneLogging.error(`Unable to complete ${job.name}:`,error);
|
|
388
390
|
throw error;
|
|
389
391
|
}
|
|
390
392
|
}));
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<link rel="stylesheet" href="./arcane/css/theme.css?v=1"><link rel="stylesheet" href="./arcane/css/primitives.css?v=1">
|
|
2
2
|
<style>:host{display:block}.capture{display:grid;gap:var(--arcane-space-4)}.actions{display:grid;gap:var(--arcane-space-3);grid-template-columns:repeat(3,minmax(0,1fr))}.action{display:grid;gap:var(--arcane-space-2);padding:var(--arcane-space-4);text-align:left}.action strong{font-size:1.05rem}.action span{color:var(--arcane-muted);font-size:.85rem}.recording{align-items:center;display:flex;gap:var(--arcane-space-3);justify-content:space-between;padding:var(--arcane-space-3);border:1px solid var(--arcane-border);border-radius:var(--arcane-radius-medium)}.preview{display:grid;place-items:center;min-height:16rem;overflow:auto;background:var(--arcane-surface-muted);border:1px solid var(--arcane-border);border-radius:var(--arcane-radius-large)}.preview :where(img,video){display:block}.empty{color:var(--arcane-muted);text-align:center}.status{margin:0;color:var(--arcane-muted)}@media(max-width:44rem){.actions{grid-template-columns:1fr}}</style>
|
|
3
3
|
<section class="capture"><div class="actions"><button class="action arcane-card" type="button" data-capture="image"><strong>Screenshot</strong><span>Capture the selected display as PNG.</span></button><button class="action arcane-card" type="button" data-capture="video"><strong>Record video</strong><span>Record the selected display in a browser-supported video format.</span></button><button class="action arcane-card" type="button" data-capture="gif"><strong>Record GIF</strong><span>Record the selected display as an animated GIF.</span></button></div><div id="recording" class="recording" hidden><span id="recordingLabel">Recording…</span><button id="stop" class="arcane-button" type="button">Stop recording</button></div><div id="preview" class="preview"><div class="empty"><strong>No capture yet</strong><p>Your capture remains on this device unless you choose to save it.</p></div></div><p id="status" class="status" role="status" aria-live="polite">Choose a capture type. Your browser will ask which display to share.</p></section>
|
|
4
|
-
<script type="module">
|
|
4
|
+
<script type="module">
|
|
5
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
6
|
+
const host=this,root=host.shadowRoot,preview=root.querySelector('#preview'),recording=root.querySelector('#recording'),status=root.querySelector('#status');const {default:ScreenCapture}=await import('../modules/ScreenCapture.js');const {createArcaneEventSource,projectArcaneDOMEvent}=await import('arcane-os/event-manager');const events=createArcaneEventSource(host,{source:'arcane.component.screen-capture',eventTypes:['screen-capture-result','screen-capture-ready']});const capture=new ScreenCapture(),listeners=new AbortController();let destroyed=false,operationGeneration=0,previewUrl='';
|
|
5
7
|
function emit(type,detail={},publicDetail={},operationId=null){if(destroyed)return false;const publication=events.dispatch(type,detail,{operationId,publicDetail});return projectArcaneDOMEvent(host,publication.occurrence,{bubbles:true,composed:true})}
|
|
6
8
|
function current(generation){return !destroyed&&generation===operationGeneration}
|
|
7
|
-
function cleanupCaptureStart(originalError=null){const cleanupErrors=[];if(capture.recorder&&capture.recorder.state!=='inactive'){try{capture.recorder.stop()}catch(error){cleanupErrors.push(error)}}try{capture.stopTracks(capture.stream)}catch(error){cleanupErrors.push(error)}try{capture.reset()}catch(error){cleanupErrors.push(error)}for(const error of cleanupErrors)
|
|
9
|
+
function cleanupCaptureStart(originalError=null){const cleanupErrors=[];if(capture.recorder&&capture.recorder.state!=='inactive'){try{capture.recorder.stop()}catch(error){cleanupErrors.push(error)}}try{capture.stopTracks(capture.stream)}catch(error){cleanupErrors.push(error)}try{capture.reset()}catch(error){cleanupErrors.push(error)}for(const error of cleanupErrors)arcaneLogging.error('Error cleaning up rejected screen capture start:',error);return originalError}
|
|
8
10
|
async function onCapture(event){const mode=event.target.closest('[data-capture]')?.dataset.capture;if(!mode||destroyed)return;const generation=++operationGeneration;setButtons(true);try{if(mode==='image'){status.textContent='Choose a display to capture…';const result=await capture.captureImage();if(!current(generation))return;showResult(result,generation)}else{status.textContent='Choose a display to record…';if(mode==='video')await capture.startVideo();else await capture.startGif();if(!current(generation)){cleanupCaptureStart();return}recording.hidden=false;root.querySelector('#recordingLabel').textContent=mode==='gif'?'Recording GIF frames…':'Recording video…';status.textContent='Recording. Return here and press Stop when finished.'}}catch(error){const originalError=mode==='image'?error:cleanupCaptureStart(error);if(!current(generation))return;status.textContent=originalError.message;setButtons(false)}}
|
|
9
11
|
async function onStop(){if(destroyed)return;const generation=operationGeneration;root.querySelector('#stop').disabled=true;status.textContent='Finishing capture…';try{const result=await capture.stop();if(current(generation)&&result)showResult(result,generation)}catch(error){if(current(generation))status.textContent=error.message}finally{if(current(generation)){recording.hidden=true;root.querySelector('#stop').disabled=false;setButtons(false)}}}
|
|
10
12
|
root.querySelector('.actions').addEventListener('click',onCapture,{signal:listeners.signal});root.querySelector('#stop').addEventListener('click',onStop,{signal:listeners.signal});
|
|
@@ -132,6 +132,8 @@
|
|
|
132
132
|
<button id="muteButton" type="button" class="mute" aria-pressed="true" aria-label="Voice unavailable" disabled>Voice unavailable</button>
|
|
133
133
|
|
|
134
134
|
<script type="module">
|
|
135
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
136
|
+
|
|
135
137
|
const completeValue = (value) => value;
|
|
136
138
|
const {
|
|
137
139
|
createArcaneEventSource,
|
|
@@ -140,7 +142,7 @@
|
|
|
140
142
|
|
|
141
143
|
void import('../modules/DBLS.js').catch(
|
|
142
144
|
function reportDBLSImportFailure(error) {
|
|
143
|
-
|
|
145
|
+
arcaneLogging.error('The shared database runtime could not load.');
|
|
144
146
|
}
|
|
145
147
|
);
|
|
146
148
|
const aiModuleImport = import('../modules/AI.js');
|
|
@@ -365,7 +367,7 @@
|
|
|
365
367
|
if (destroyed) {
|
|
366
368
|
return;
|
|
367
369
|
}
|
|
368
|
-
|
|
370
|
+
arcaneLogging.error('The shared AI runtime could not load.');
|
|
369
371
|
}
|
|
370
372
|
);
|
|
371
373
|
|
|
@@ -476,10 +478,10 @@
|
|
|
476
478
|
sttRole = snapshot.roles.stt;
|
|
477
479
|
ttsRole = snapshot.roles.tts;
|
|
478
480
|
if (sttRole.state === 'error' && previousSTTRole.state !== 'error') {
|
|
479
|
-
|
|
481
|
+
arcaneLogging.error('Arcane transcription runtime failed.', sttRole.error);
|
|
480
482
|
}
|
|
481
483
|
if (ttsRole.state === 'error' && previousTTSRole.state !== 'error') {
|
|
482
|
-
|
|
484
|
+
arcaneLogging.error('Arcane voice runtime failed.', ttsRole.error);
|
|
483
485
|
}
|
|
484
486
|
clearSettledTTSIntent();
|
|
485
487
|
applyRoleTransitions(previousSTTRole, previousTTSRole);
|
|
@@ -1048,7 +1050,7 @@
|
|
|
1048
1050
|
`ARCANE_SPEECH_TTS_${action.toUpperCase()}_REJECTED`
|
|
1049
1051
|
);
|
|
1050
1052
|
const reason = `tts-${action}-rejected`;
|
|
1051
|
-
|
|
1053
|
+
arcaneLogging.error(`Arcane voice ${action} request failed.`, error);
|
|
1052
1054
|
dispatchSpeechEvent(
|
|
1053
1055
|
'speech-tts-lifecycle-error',
|
|
1054
1056
|
{
|
|
@@ -1113,7 +1115,7 @@
|
|
|
1113
1115
|
tone: 'error'
|
|
1114
1116
|
};
|
|
1115
1117
|
const errorFields = publicSpeechErrorFields(error, failure.code);
|
|
1116
|
-
|
|
1118
|
+
arcaneLogging.error(`Arcane ${normalizedBoundary} speech operation failed.`, error);
|
|
1117
1119
|
dispatchSpeechEvent(
|
|
1118
1120
|
'speech-synthesis-error',
|
|
1119
1121
|
{
|
|
@@ -1535,7 +1537,7 @@
|
|
|
1535
1537
|
'ARCANE_SPEECH_STT_TRANSCRIPTION_REQUEST_REJECTED'
|
|
1536
1538
|
);
|
|
1537
1539
|
const reason = 'stt-transcription-rejected';
|
|
1538
|
-
|
|
1540
|
+
arcaneLogging.error('Arcane speech transcription failed.', error);
|
|
1539
1541
|
dispatchSpeechEvent(
|
|
1540
1542
|
'speech-transcription-error',
|
|
1541
1543
|
{
|
|
@@ -1642,7 +1644,7 @@
|
|
|
1642
1644
|
if (session.audioContext.state !== 'closed') {
|
|
1643
1645
|
void session.audioContext.close().catch(
|
|
1644
1646
|
function reportAudioContextCloseFailure(error) {
|
|
1645
|
-
|
|
1647
|
+
arcaneLogging.warn('The microphone audio context could not close.');
|
|
1646
1648
|
}
|
|
1647
1649
|
);
|
|
1648
1650
|
}
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
</table>
|
|
18
18
|
|
|
19
19
|
<script type="module">
|
|
20
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
21
|
+
|
|
20
22
|
const host = this;
|
|
21
23
|
const shadowRoot=this.shadowRoot;
|
|
22
24
|
const {createArcaneEventSource,projectArcaneDOMEvent}=
|
|
@@ -68,7 +70,7 @@
|
|
|
68
70
|
tableBody.innerHTML = '';
|
|
69
71
|
|
|
70
72
|
tableArray.forEach(
|
|
71
|
-
(row)=>{
|
|
73
|
+
(row)=>{ arcaneLogging.log('row',row);
|
|
72
74
|
const tr = tableBody.insertRow();
|
|
73
75
|
row.forEach(
|
|
74
76
|
(cellValue)=>{
|
|
@@ -60,6 +60,8 @@
|
|
|
60
60
|
</section>
|
|
61
61
|
|
|
62
62
|
<script type="module">
|
|
63
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
64
|
+
|
|
63
65
|
const completeValue=(value)=>value;
|
|
64
66
|
const {
|
|
65
67
|
createArcaneEventSource,
|
|
@@ -84,21 +86,16 @@
|
|
|
84
86
|
]
|
|
85
87
|
}
|
|
86
88
|
);
|
|
87
|
-
const
|
|
88
|
-
host.getAttribute('href')||'./arcane/components/voice-transcription.html',
|
|
89
|
-
document.baseURI
|
|
90
|
-
);
|
|
91
|
-
const moduleURL=name=>new URL(`../modules/${name}`,componentURL).href;
|
|
92
|
-
const {default:MD}=await import(moduleURL('MD.js?v=2'));
|
|
89
|
+
const {default:MD}=await import('../modules/MD.js?v=2');
|
|
93
90
|
const {
|
|
94
91
|
appendTranscription,
|
|
95
92
|
createSTTActivationController,
|
|
96
93
|
normalizeVoiceOptions
|
|
97
|
-
}=await import(
|
|
94
|
+
}=await import('../modules/ComponentContracts.js');
|
|
98
95
|
const {
|
|
99
96
|
requestAIRuntimeIntent,
|
|
100
97
|
subscribeAIRuntimeState
|
|
101
|
-
}=await import(
|
|
98
|
+
}=await import('../modules/AIRuntimeState.js');
|
|
102
99
|
const description=host.shadowRoot.querySelector('#description');
|
|
103
100
|
const transcriptElement=host.shadowRoot.querySelector('#transcript');
|
|
104
101
|
const status=host.shadowRoot.querySelector('#status');
|
|
@@ -352,7 +349,7 @@
|
|
|
352
349
|
return false;
|
|
353
350
|
}
|
|
354
351
|
releaseMicrophone();
|
|
355
|
-
|
|
352
|
+
arcaneLogging.error('Unable to start recording:',error);
|
|
356
353
|
setState('error',options.messages.startError);
|
|
357
354
|
return false;
|
|
358
355
|
}
|
|
@@ -502,7 +499,7 @@
|
|
|
502
499
|
if(!isCurrentVoiceOperation(generation,'saving')){
|
|
503
500
|
return false;
|
|
504
501
|
}
|
|
505
|
-
|
|
502
|
+
arcaneLogging.error('Unable to save transcription:',error);
|
|
506
503
|
setState('error',options.messages.saveError);
|
|
507
504
|
return false;
|
|
508
505
|
}
|
|
@@ -531,7 +528,7 @@
|
|
|
531
528
|
);
|
|
532
529
|
return false;
|
|
533
530
|
}
|
|
534
|
-
|
|
531
|
+
arcaneLogging.error('Unable to transcribe recording:',error);
|
|
535
532
|
setState('error',options.messages.transcribeError);
|
|
536
533
|
return false;
|
|
537
534
|
}finally{
|
|
@@ -598,7 +595,7 @@
|
|
|
598
595
|
return options.transcribe(file,context);
|
|
599
596
|
}
|
|
600
597
|
if(typeof globalThis.ai?.fetchSTT!=='function'){
|
|
601
|
-
await import(
|
|
598
|
+
await import('../modules/AI.js');
|
|
602
599
|
}
|
|
603
600
|
if(typeof globalThis.ai?.fetchSTT!=='function'){
|
|
604
601
|
const error=new Error('Speech transcription is not configured.');
|
|
@@ -639,7 +636,7 @@
|
|
|
639
636
|
function recordingError(event){
|
|
640
637
|
setState('error',options.messages.interrupted);
|
|
641
638
|
releaseMicrophone();
|
|
642
|
-
|
|
639
|
+
arcaneLogging.error('Audio recorder error:',event.error||event);
|
|
643
640
|
}
|
|
644
641
|
|
|
645
642
|
async function completeStream(){
|
|
@@ -684,7 +681,7 @@
|
|
|
684
681
|
if(!isCurrentVoiceOperation(generation,'completing')){
|
|
685
682
|
return false;
|
|
686
683
|
}
|
|
687
|
-
|
|
684
|
+
arcaneLogging.error('Unable to complete transcription:',error);
|
|
688
685
|
setState('error',options.messages.completeError);
|
|
689
686
|
return false;
|
|
690
687
|
}
|
|
@@ -827,7 +824,7 @@
|
|
|
827
824
|
const previousRole=sttRole;
|
|
828
825
|
sttRole=snapshot.roles.stt;
|
|
829
826
|
if(sttRole.state==='error'&&previousRole.state!=='error'){
|
|
830
|
-
|
|
827
|
+
arcaneLogging.error('Arcane transcription runtime failed.',sttRole.error);
|
|
831
828
|
}
|
|
832
829
|
sttActivationController.synchronize(sttRole);
|
|
833
830
|
if(previousRole.state==='ready'&&sttRole.state!=='ready'){
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { arcaneLogging } from 'arcane-os/logging';
|
|
1
2
|
import Is from '../../node_modules/strong-type/index.js';
|
|
2
3
|
import '../modules/DBOPFS.js';
|
|
3
4
|
import '../modules/AI.js';
|
|
@@ -114,7 +115,7 @@ function structuralToolMessage(call){
|
|
|
114
115
|
function storedStructuralToolCalls(value){
|
|
115
116
|
if(value===undefined) return [];
|
|
116
117
|
if(!Array.isArray(value)){
|
|
117
|
-
|
|
118
|
+
arcaneLogging.error('Arcane stored assistant tool calls were not an array and were not retained.');
|
|
118
119
|
return [];
|
|
119
120
|
}
|
|
120
121
|
const result=[];
|
|
@@ -122,7 +123,7 @@ function storedStructuralToolCalls(value){
|
|
|
122
123
|
try{
|
|
123
124
|
result.push(copyToolCalls([call])[0]);
|
|
124
125
|
}catch(error){
|
|
125
|
-
|
|
126
|
+
arcaneLogging.error(
|
|
126
127
|
`Arcane stored assistant tool call ${index+1} had no usable user-facing message and was not retained.`,
|
|
127
128
|
error
|
|
128
129
|
);
|
|
@@ -840,7 +841,7 @@ class ChatEntity{
|
|
|
840
841
|
try{
|
|
841
842
|
return JSON.parse(row);
|
|
842
843
|
}catch(error){
|
|
843
|
-
|
|
844
|
+
arcaneLogging.error(
|
|
844
845
|
`Arcane saved chat row ${index+1} could not be parsed.`,
|
|
845
846
|
error,
|
|
846
847
|
row
|
|
@@ -951,7 +952,7 @@ ${JSON.stringify(transcript)}`
|
|
|
951
952
|
.map(message=>copyCompleteValue(message));
|
|
952
953
|
const queued=this.#memoryQueue.then(()=>this.#writeMemory(snapshot,request));
|
|
953
954
|
this.#memoryQueue=queued.catch(()=>{
|
|
954
|
-
|
|
955
|
+
arcaneLogging.warn('Unable to update chat memory.');
|
|
955
956
|
return false;
|
|
956
957
|
});
|
|
957
958
|
return this.#memoryQueue;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { arcaneLogging } from 'arcane-os/logging';
|
|
1
2
|
import Is from '../../node_modules/strong-type/index.js';
|
|
2
3
|
import DBLS from '../modules/DBLS.js';
|
|
3
4
|
import {
|
|
@@ -818,7 +819,7 @@ class UserEntity {
|
|
|
818
819
|
try {
|
|
819
820
|
this[key] = src[key];
|
|
820
821
|
} catch(e){
|
|
821
|
-
|
|
822
|
+
arcaneLogging.warn(`UserEntity.explicit setter skipping invalid field ${key}: ${e.message}`);
|
|
822
823
|
}
|
|
823
824
|
}
|
|
824
825
|
|