arcane-os 0.5.13 → 0.5.15
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 +32 -0
- package/README.md +33 -8
- 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/architecture.md +1 -1
- package/docs/reference/README.md +9 -7
- package/docs/reference/ai/browser-speech.md +90 -1
- package/docs/reference/ai/twin-cloud.md +1 -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 +34 -6
- package/docs/reference/inventory/runtime-components.json +1 -1
- package/docs/reference/inventory/runtime-modules.json +4 -4
- package/docs/reference/protocols.md +5 -5
- package/docs/reference/runtime-modules.md +70 -15
- package/docs/reference/sdk-api.md +120 -11
- package/package.json +4 -3
- package/runtime/arcane/components/app-bar.html +3 -1
- package/runtime/arcane/components/chat.html +22 -20
- package/runtime/arcane/components/dashboard-config.html +3 -1
- 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 +11 -9
- package/runtime/arcane/components/header.html +5 -3
- package/runtime/arcane/components/markdown-document.html +3 -1
- package/runtime/arcane/components/markdown-editor.html +4 -2
- 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 +8 -6
- 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 +4 -3
- 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/SpeechPlayback.js +206 -40
- package/runtime/arcane/modules/ThemeBootstrap.js +3 -2
- package/runtime/arcane/modules/ToolCallRouter.js +2 -1
- package/src/import-map.mjs +65 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcane-os",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.15",
|
|
4
4
|
"description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.mjs",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"./toolchain": "./src/toolchain.mjs",
|
|
14
14
|
"./events": "./src/events.mjs",
|
|
15
15
|
"./event-manager": "./src/event-manager.mjs",
|
|
16
|
+
"./logging": "./browser-runtime/logging.mjs",
|
|
16
17
|
"./preference-store": "./runtime/arcane/modules/PreferenceStore.js",
|
|
17
18
|
"./speech-playback": "./runtime/arcane/modules/SpeechPlayback.js",
|
|
18
19
|
"./ai/browser-wasm": "./browser-runtime/ai/browser-wasm.mjs",
|
|
@@ -63,9 +64,9 @@
|
|
|
63
64
|
"test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
|
|
64
65
|
"test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
|
|
65
66
|
"test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/contracts.test.mjs test/doctor.test.mjs test/mail-credentials.test.mjs test/mail-outbox.test.mjs test/mail-public-api.test.mjs test/mail-send.test.mjs test/mail-transport.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
|
|
66
|
-
"test:functional": "node ./bin/arcane-test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/cli.test.mjs test/dbopfs-document-library.test.mjs test/dev-server.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/packaging.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/site.test.mjs test/update-check.test.mjs",
|
|
67
|
+
"test:functional": "node ./bin/arcane-test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/cli.test.mjs test/dbopfs-document-library.test.mjs test/dev-server.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/packaging.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/update-check.test.mjs",
|
|
67
68
|
"test:integration": "node ./bin/arcane-test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-plan.test.mjs test/native-provider-loader.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
68
|
-
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/native-provider-generation.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
69
|
+
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/logging-regression.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
69
70
|
"check": "node tools/check-source.mjs && npm test",
|
|
70
71
|
"check:release": "node tools/check-source.mjs --package-only && npm run test:release",
|
|
71
72
|
"pack:local": "npm pack --ignore-scripts",
|
|
@@ -220,6 +220,8 @@
|
|
|
220
220
|
</nav>
|
|
221
221
|
|
|
222
222
|
<script type="module">
|
|
223
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
224
|
+
|
|
223
225
|
const host=this;
|
|
224
226
|
const root=host.shadowRoot;
|
|
225
227
|
const {createArcaneEventSource,projectArcaneDOMEvent}=await import('arcane-os/event-manager');
|
|
@@ -349,7 +351,7 @@
|
|
|
349
351
|
try{
|
|
350
352
|
setNavigation(JSON.parse(source));
|
|
351
353
|
}catch(error){
|
|
352
|
-
|
|
354
|
+
arcaneLogging.warn('Unable to parse app-bar data-navigation.',error);
|
|
353
355
|
setNavigation([]);
|
|
354
356
|
}
|
|
355
357
|
}
|
|
@@ -832,7 +832,9 @@
|
|
|
832
832
|
</section>
|
|
833
833
|
</section>
|
|
834
834
|
|
|
835
|
-
<script type="module">
|
|
835
|
+
<script type="module">
|
|
836
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
837
|
+
|
|
836
838
|
const {
|
|
837
839
|
createArcaneEventSource,
|
|
838
840
|
projectArcaneDOMEvent
|
|
@@ -1059,7 +1061,7 @@
|
|
|
1059
1061
|
return value||fallback;
|
|
1060
1062
|
}
|
|
1061
1063
|
if(value&&typeof value==='object'){
|
|
1062
|
-
|
|
1064
|
+
arcaneLogging.error(`Arcane chat progress ${field} is not text.`,value);
|
|
1063
1065
|
return visibleErrorMessage(value,fallback);
|
|
1064
1066
|
}
|
|
1065
1067
|
if(value!==undefined&&value!==null&&value!==''){
|
|
@@ -1067,7 +1069,7 @@
|
|
|
1067
1069
|
`Arcane chat progress ${field} must be text.`,
|
|
1068
1070
|
{cause:value}
|
|
1069
1071
|
);
|
|
1070
|
-
|
|
1072
|
+
arcaneLogging.error(`Arcane chat progress ${field} is not text.`,error);
|
|
1071
1073
|
}
|
|
1072
1074
|
return fallback;
|
|
1073
1075
|
}
|
|
@@ -1394,7 +1396,7 @@
|
|
|
1394
1396
|
const serialized=JSON.stringify(value,null,2);
|
|
1395
1397
|
if(serialized!==undefined) return serialized;
|
|
1396
1398
|
}catch(error){
|
|
1397
|
-
|
|
1399
|
+
arcaneLogging.error('Arcane saved chat record could not be serialized as JSON.',error);
|
|
1398
1400
|
}
|
|
1399
1401
|
return String(value);
|
|
1400
1402
|
}
|
|
@@ -1506,7 +1508,7 @@
|
|
|
1506
1508
|
recoveryNeeded=true;
|
|
1507
1509
|
actionable=false;
|
|
1508
1510
|
restoredPendingToolCalls.clear();
|
|
1509
|
-
|
|
1511
|
+
arcaneLogging.error(`Arcane saved chat record ${index+1} is not actionable.`,error);
|
|
1510
1512
|
item=createSavedRecordFallback(message,index);
|
|
1511
1513
|
}
|
|
1512
1514
|
fragment.append(item);
|
|
@@ -1617,7 +1619,7 @@
|
|
|
1617
1619
|
}catch(error){
|
|
1618
1620
|
if(!destroyed&&generation===sessionBindingGeneration){
|
|
1619
1621
|
const internalProtocolFailure=internalStructuralToolFailure(error);
|
|
1620
|
-
|
|
1622
|
+
arcaneLogging.error('Arcane saved chat could not be opened.',error);
|
|
1621
1623
|
const message=internalProtocolFailure
|
|
1622
1624
|
?'This saved chat could not be opened.'
|
|
1623
1625
|
:visibleErrorMessage(error,'The chat session could not be opened.');
|
|
@@ -1738,11 +1740,11 @@
|
|
|
1738
1740
|
}
|
|
1739
1741
|
|
|
1740
1742
|
host.sendMessage=host.sendMessage||async function(text=''){
|
|
1741
|
-
|
|
1743
|
+
arcaneLogging.warn('html-import chat.html `host.sendMessage` method not implemented.\n\nThis can also be done by listening for the "chat-send-message" event.\n\nIt is still best practice to implement the `.sendMessage` method atleast with an empty function.\n\n')
|
|
1742
1744
|
}
|
|
1743
1745
|
|
|
1744
1746
|
host.languageChanged=host.languageChanged||async function(text=''){
|
|
1745
|
-
|
|
1747
|
+
arcaneLogging.warn('html-import chat.html `host.languageChanged` method not implemented.\n\nThis can also be done by listening for the "chat-language-changed" event.\n\nIt is still best practice to implement the `.languageChanged` method atleast with an empty function.\n\n')
|
|
1746
1748
|
}
|
|
1747
1749
|
|
|
1748
1750
|
host.requestAIActivation=host.requestAIActivation||function requestAIActivation(intent){
|
|
@@ -2381,7 +2383,7 @@
|
|
|
2381
2383
|
`The language model ${action} request failed.`
|
|
2382
2384
|
);
|
|
2383
2385
|
requestError=message;
|
|
2384
|
-
|
|
2386
|
+
arcaneLogging.error('Arcane language model activation request failed.',error);
|
|
2385
2387
|
publish(
|
|
2386
2388
|
'chat-ai-activation-error',
|
|
2387
2389
|
{request,error,message},
|
|
@@ -2420,7 +2422,7 @@
|
|
|
2420
2422
|
&&nextRole.error
|
|
2421
2423
|
&&nextRole.error!==role?.error
|
|
2422
2424
|
){
|
|
2423
|
-
|
|
2425
|
+
arcaneLogging.error('Arcane language model runtime failed.',nextRole.error);
|
|
2424
2426
|
}
|
|
2425
2427
|
if(role?.state!==nextRole.state
|
|
2426
2428
|
||role?.providerId!==nextRole.providerId
|
|
@@ -2501,7 +2503,7 @@
|
|
|
2501
2503
|
try{
|
|
2502
2504
|
controller.start();
|
|
2503
2505
|
}catch(error){
|
|
2504
|
-
|
|
2506
|
+
arcaneLogging.error('Arcane conversation timebox could not start.',error);
|
|
2505
2507
|
conversationTimeboxStatus.textContent='The elapsed timer could not start.';
|
|
2506
2508
|
conversationTimeboxPanel.dataset.error='true';
|
|
2507
2509
|
conversationTimeboxUnsubscribe?.();
|
|
@@ -2694,7 +2696,7 @@
|
|
|
2694
2696
|
}
|
|
2695
2697
|
}
|
|
2696
2698
|
);
|
|
2697
|
-
|
|
2699
|
+
arcaneLogging.error('The conversation timebox message could not be sent.',error);
|
|
2698
2700
|
return false;
|
|
2699
2701
|
}
|
|
2700
2702
|
);
|
|
@@ -2746,7 +2748,7 @@
|
|
|
2746
2748
|
async function streamMessage(text='', id='', isThinking){
|
|
2747
2749
|
if(typeof text!=='string'){
|
|
2748
2750
|
if(text instanceof Error){
|
|
2749
|
-
|
|
2751
|
+
arcaneLogging.error('Arcane chat stream delivered an Error as content.',text);
|
|
2750
2752
|
throw text;
|
|
2751
2753
|
}
|
|
2752
2754
|
const error=new TypeError(
|
|
@@ -2754,11 +2756,11 @@
|
|
|
2754
2756
|
{cause:text}
|
|
2755
2757
|
);
|
|
2756
2758
|
error.code='ARCANE_CHAT_STREAM_CONTENT_INVALID';
|
|
2757
|
-
|
|
2759
|
+
arcaneLogging.error('Arcane chat stream delivered invalid content.',error);
|
|
2758
2760
|
throw error;
|
|
2759
2761
|
}
|
|
2760
2762
|
if(!id){
|
|
2761
|
-
|
|
2763
|
+
arcaneLogging.warn('Streaming messages require ids, none specified.')
|
|
2762
2764
|
return false;
|
|
2763
2765
|
}
|
|
2764
2766
|
|
|
@@ -2949,7 +2951,7 @@
|
|
|
2949
2951
|
return;
|
|
2950
2952
|
}
|
|
2951
2953
|
host.language=language;
|
|
2952
|
-
|
|
2954
|
+
arcaneLogging.info("Language changed to:",host.language);
|
|
2953
2955
|
let result;
|
|
2954
2956
|
try{result=host.languageChanged(host.language);}
|
|
2955
2957
|
catch(error){result=Promise.reject(error);}
|
|
@@ -3266,13 +3268,13 @@
|
|
|
3266
3268
|
}else{
|
|
3267
3269
|
restoreRejectedStructuralDraft(messageId,context.operationId,text);
|
|
3268
3270
|
}
|
|
3269
|
-
|
|
3271
|
+
arcaneLogging.error('Arcane structural tool protocol failure.',error);
|
|
3270
3272
|
setSessionStatus(
|
|
3271
3273
|
pendingStructuralToolCalls.length?'tool':'ready',
|
|
3272
3274
|
pendingStructuralToolMessage||'Chat ready.'
|
|
3273
3275
|
);
|
|
3274
3276
|
}else if(!destroyed&&bindingGeneration===sessionBindingGeneration){
|
|
3275
|
-
|
|
3277
|
+
arcaneLogging.error('Arcane chat request failed.',error);
|
|
3276
3278
|
if(sessionRequestMessages.every(message=>message.role==='tool')){
|
|
3277
3279
|
const requestMessages=[...chatOutput.children].filter(
|
|
3278
3280
|
candidate=>candidate.dataset.operationId===context.operationId
|
|
@@ -3541,7 +3543,7 @@
|
|
|
3541
3543
|
if(destroyed||context.signal.aborted){
|
|
3542
3544
|
return false;
|
|
3543
3545
|
}
|
|
3544
|
-
|
|
3546
|
+
arcaneLogging.error(
|
|
3545
3547
|
internalStructuralToolFailure(error)
|
|
3546
3548
|
?'Arcane structural tool protocol failure.'
|
|
3547
3549
|
:'The chat message could not be submitted.',
|
|
@@ -3751,7 +3753,7 @@
|
|
|
3751
3753
|
}
|
|
3752
3754
|
}
|
|
3753
3755
|
);
|
|
3754
|
-
|
|
3756
|
+
arcaneLogging.error('Speech synthesis failed.',error);
|
|
3755
3757
|
return false;
|
|
3756
3758
|
}
|
|
3757
3759
|
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
<html-import id="configModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
|
|
11
11
|
|
|
12
12
|
<script type="module">
|
|
13
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
14
|
+
|
|
13
15
|
const host=this;
|
|
14
16
|
const {default:waitForComponent}=await import('../modules/WaitForComponent.js');
|
|
15
17
|
const {
|
|
@@ -65,7 +67,7 @@
|
|
|
65
67
|
()=>openConfig().catch(
|
|
66
68
|
error=>{
|
|
67
69
|
if(!destroyed){
|
|
68
|
-
|
|
70
|
+
arcaneLogging.error('Unable to configure dashboard:',error);
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
),
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
<html-import id="maintenanceModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
|
|
14
14
|
|
|
15
15
|
<script type="module">
|
|
16
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
17
|
+
|
|
16
18
|
const host=this;
|
|
17
19
|
const openButton=host.shadowRoot.querySelector('#openMaintenance');
|
|
18
20
|
const maintenanceModal=host.shadowRoot.querySelector('#maintenanceModal');
|
|
@@ -36,7 +38,7 @@
|
|
|
36
38
|
()=>openMaintenance().catch(
|
|
37
39
|
error=>{
|
|
38
40
|
if(!destroyed){
|
|
39
|
-
|
|
41
|
+
arcaneLogging.error('Unable to open maintenance:',error);
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
),
|
|
@@ -127,7 +129,7 @@
|
|
|
127
129
|
return;
|
|
128
130
|
}
|
|
129
131
|
status.innerText='Unable to complete data maintenance.';
|
|
130
|
-
|
|
132
|
+
arcaneLogging.error('Unable to clear empty chats and memories:',error);
|
|
131
133
|
}finally{
|
|
132
134
|
if(!destroyed&&generation===clearGeneration){
|
|
133
135
|
clearButton.disabled=false;
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
<html-import id="dataModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
|
|
15
15
|
|
|
16
16
|
<script type="module">
|
|
17
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
18
|
+
|
|
17
19
|
const host=this;
|
|
18
20
|
const openButton=host.shadowRoot.querySelector('#openData');
|
|
19
21
|
const dataModal=host.shadowRoot.querySelector('#dataModal');
|
|
@@ -39,7 +41,7 @@
|
|
|
39
41
|
()=>openData().catch(
|
|
40
42
|
error=>{
|
|
41
43
|
if(!destroyed){
|
|
42
|
-
|
|
44
|
+
arcaneLogging.error('Unable to open data view:',error);
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
),
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
32
|
<script type="module">
|
|
33
|
+
const {arcaneLogging}=await import('arcane-os/logging');
|
|
34
|
+
|
|
33
35
|
const host=this;
|
|
34
36
|
const root=host.shadowRoot;
|
|
35
37
|
const {default:DirectoryPicker}=await import('../modules/DirectoryPicker.js');
|
|
@@ -67,7 +69,7 @@
|
|
|
67
69
|
choose.addEventListener(
|
|
68
70
|
'click',
|
|
69
71
|
()=>select().catch(
|
|
70
|
-
error=>
|
|
72
|
+
error=>arcaneLogging.error('Unable to select a directory:',error)
|
|
71
73
|
),
|
|
72
74
|
{signal:lifecycleController.signal}
|
|
73
75
|
);
|
|
@@ -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
|
);
|
|
@@ -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
|
}
|
|
@@ -1411,7 +1413,7 @@
|
|
|
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
|
}
|
|
@@ -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
|
}
|
|
@@ -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,6 +211,8 @@
|
|
|
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
|
|
|
@@ -883,7 +885,7 @@
|
|
|
883
885
|
Promise.resolve(options.onNavigate(detail,{signal:lifecycleController.signal,operationId})).catch(
|
|
884
886
|
error=>{
|
|
885
887
|
if(!destroyed){
|
|
886
|
-
|
|
888
|
+
arcaneLogging.error('Markdown document navigation callback failed.',error);
|
|
887
889
|
}
|
|
888
890
|
}
|
|
889
891
|
);
|
|
@@ -74,6 +74,8 @@
|
|
|
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
80
|
const {default:MD}=await import('../modules/MD.js?v=2');
|
|
79
81
|
const {
|
|
@@ -229,7 +231,7 @@
|
|
|
229
231
|
emit('markdown-editor-change',detail,detail);
|
|
230
232
|
if(options.onChange){
|
|
231
233
|
Promise.resolve(options.onChange(detail)).catch(
|
|
232
|
-
error=>
|
|
234
|
+
error=>arcaneLogging.error('Markdown change callback failed:',error)
|
|
233
235
|
);
|
|
234
236
|
}
|
|
235
237
|
}
|
|
@@ -329,7 +331,7 @@
|
|
|
329
331
|
return false;
|
|
330
332
|
}
|
|
331
333
|
status.innerText=options.labels.saveError;
|
|
332
|
-
|
|
334
|
+
arcaneLogging.error('Unable to save Markdown content:',error);
|
|
333
335
|
return false;
|
|
334
336
|
}finally{
|
|
335
337
|
if(saveController===controller){
|
|
@@ -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)=>{
|