arcane-os 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +86 -117
- package/bin/arcane-test.mjs +170 -46
- package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
- package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
- package/browser-runtime/ai/browser-wasm.mjs +24 -35
- package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
- package/browser-runtime/ai/model-controller.mjs +584 -181
- package/browser-runtime/ai/speech-worker-client.mjs +8 -146
- package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
- package/browser-runtime/dom-event-instrumentation.mjs +55 -147
- package/browser-runtime/event-manager.mjs +239 -624
- package/package.json +5 -6
- package/runtime/arcane/components/app-bar.html +3 -15
- package/runtime/arcane/components/assistant-panel.html +10 -10
- package/runtime/arcane/components/calculator.html +1 -1
- package/runtime/arcane/components/chat.html +1359 -135
- package/runtime/arcane/components/conversation-view.html +2 -2
- package/runtime/arcane/components/document-inspector.html +11 -17
- package/runtime/arcane/components/file-manager.html +13 -56
- package/runtime/arcane/components/markdown-document.html +82 -281
- package/runtime/arcane/components/markdown-editor.html +7 -10
- package/runtime/arcane/components/media-embed.html +6 -6
- package/runtime/arcane/components/screen-capture.html +4 -4
- package/runtime/arcane/components/source-explanation.html +2 -2
- package/runtime/arcane/components/speech.html +112 -68
- package/runtime/arcane/components/terminal-workspace.html +4 -4
- package/runtime/arcane/components/theme-editor.html +1 -1
- package/runtime/arcane/components/unified-inbox.html +2 -2
- package/runtime/arcane/components/voice-transcription.html +31 -21
- package/runtime/arcane/entities/Calculation.js +2 -3
- package/runtime/arcane/entities/Chat.js +228 -43
- package/runtime/arcane/entities/Preference.js +3 -5
- package/runtime/arcane/entities/Weather.js +5 -5
- package/runtime/arcane/modules/AI.js +1050 -427
- package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
- package/runtime/arcane/modules/AIResponseLength.js +9 -19
- package/runtime/arcane/modules/AIRuntimeState.js +109 -72
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
- package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
- package/runtime/arcane/modules/CalculatorEngine.js +9 -9
- package/runtime/arcane/modules/CommunicationAppController.js +3 -7
- package/runtime/arcane/modules/ComponentContracts.js +30 -32
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
- package/runtime/arcane/modules/ConversationActionItems.js +26 -59
- package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
- package/runtime/arcane/modules/ConversationTimebox.js +27 -15
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
- package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
- package/runtime/arcane/modules/HTMLImport.js +54 -1
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
- package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
- package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
- package/runtime/arcane/modules/MD.js +1 -45
- package/runtime/arcane/modules/Mail.js +51 -103
- package/runtime/arcane/modules/MailOutbox.mjs +95 -193
- package/runtime/arcane/modules/MailTransport.mjs +36 -57
- package/runtime/arcane/modules/ModelDefinition.js +22 -106
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
- package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
- package/runtime/arcane/modules/PreferenceStore.js +102 -30
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
- package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
- package/runtime/arcane/modules/ScreenCapture.js +175 -128
- package/runtime/arcane/modules/SpeechPlayback.js +46 -149
- package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
- package/runtime/arcane/modules/ToolCallRouter.js +25 -12
- package/runtime/arcane/modules/YouTubeMedia.js +6 -5
- package/schemas/arcane-app-bundle.schema.json +13 -78
- package/schemas/arcane-app.schema.json +9 -25
- package/schemas/arcane-lock.schema.json +18 -151
- package/schemas/arcane-package.schema.json +2 -16
- package/schemas/native-build-plan.schema.json +119 -122
- package/src/app-descriptor.mjs +75 -132
- package/src/application-tests.mjs +200 -0
- package/src/cli/main.mjs +27 -46
- package/src/constants.mjs +3 -4
- package/src/dev-server.mjs +30 -324
- package/src/doctor.mjs +92 -154
- package/src/dom-event-instrumentation.mjs +55 -147
- package/src/errors.mjs +2 -3
- package/src/event-manager.mjs +239 -624
- package/src/event-queue.mjs +3 -3
- package/src/import-map.mjs +273 -1028
- package/src/index.mjs +14 -16
- package/src/installed-sdk-runtime.mjs +40 -62
- package/src/integrated-provider-loader.mjs +53 -382
- package/src/mail-api.mjs +0 -2
- package/src/mail-server.mjs +224 -580
- package/src/mail.mjs +4 -10
- package/src/native-plan.mjs +163 -598
- package/src/native-provider-loader.mjs +104 -1063
- package/src/packager/core.mjs +485 -3229
- package/src/process.mjs +5 -10
- package/src/release-bundle.mjs +292 -2405
- package/src/runtime.mjs +76 -396
- package/src/scaffold.mjs +30 -80
- package/src/sdk-browser-runtime.mjs +70 -626
- package/src/source-server.mjs +588 -0
- package/src/targets/index.mjs +78 -188
- package/src/templates/workspace-template.mjs +19 -135
- package/src/testing-loader.mjs +164 -0
- package/src/testing.mjs +1 -1
- package/src/toolchain.mjs +131 -544
- package/src/update-check.mjs +26 -64
- package/src/workspace-operation-lock.mjs +139 -430
- package/src/workspace-runtime.mjs +112 -779
- package/src/workspace.mjs +40 -302
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
- package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
- package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
- package/browser-runtime/ai/internal/sha256.mjs +0 -166
- package/docs/architecture.md +0 -344
- package/docs/compatibility.md +0 -36
- package/docs/event-manager.md +0 -294
- package/docs/platform-targets.md +0 -108
- package/docs/publishing.md +0 -201
- package/docs/reference/README.md +0 -187
- package/docs/reference/ai/browser-speech-package-authority.json +0 -835
- package/docs/reference/ai/browser-speech.md +0 -1252
- package/docs/reference/ai/browser-wasm.md +0 -530
- package/docs/reference/arcane-ollama.md +0 -288
- package/docs/reference/availability-and-normalization.md +0 -183
- package/docs/reference/behavioral-testing.md +0 -133
- package/docs/reference/cli.md +0 -779
- package/docs/reference/core/README.md +0 -62
- package/docs/reference/core/arcane-ai-contracts.md +0 -907
- package/docs/reference/core/arcane-api.md +0 -601
- package/docs/reference/core/arcane-entities.md +0 -65
- package/docs/reference/core/arcane-events.md +0 -134
- package/docs/reference/core/ollama-module.md +0 -181
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
- package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
- package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
- package/docs/reference/event-manager.md +0 -1511
- package/docs/reference/inventory/package-api.json +0 -3284
- package/docs/reference/inventory/runtime-components.json +0 -1011
- package/docs/reference/inventory/runtime-entities.json +0 -26
- package/docs/reference/inventory/runtime-modules.json +0 -1431
- package/docs/reference/mail.md +0 -316
- package/docs/reference/protocols.md +0 -677
- package/docs/reference/runtime-components.md +0 -1366
- package/docs/reference/runtime-entities.md +0 -303
- package/docs/reference/runtime-modules.md +0 -2960
- package/docs/reference/sdk-api.md +0 -6694
- package/docs/roadmap.md +0 -79
- package/docs/work-amplification.md +0 -129
- package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
|
@@ -6,13 +6,11 @@ import {
|
|
|
6
6
|
} from './CoreLocalModelCatalog.js';
|
|
7
7
|
import {normalizeOllamaModelIdentifier} from './OllamaModelIdentifier.js';
|
|
8
8
|
|
|
9
|
-
export const LOCAL_AI_BROWSER_ENDPOINTS=
|
|
9
|
+
export const LOCAL_AI_BROWSER_ENDPOINTS={
|
|
10
10
|
speech:'http://127.0.0.1:8011/health'
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
|
|
13
13
|
const DEFAULT_TIMEOUT_MS=3000;
|
|
14
|
-
const MAX_TIMEOUT_MS=10000;
|
|
15
|
-
const MAX_HEALTH_RESPONSE_CHARACTERS=64*1024;
|
|
16
14
|
const LOCAL_SPEECH_PROVIDERS=new Set([
|
|
17
15
|
'LOCAL',
|
|
18
16
|
'LOCAL_SPEACH',
|
|
@@ -31,21 +29,11 @@ function token(value,{uppercase=false}={}){
|
|
|
31
29
|
|
|
32
30
|
function errorCode(error,fallback){
|
|
33
31
|
const code=token(error?.code,{uppercase:true});
|
|
34
|
-
return code
|
|
35
|
-
?code
|
|
36
|
-
:fallback;
|
|
32
|
+
return code||fallback;
|
|
37
33
|
}
|
|
38
34
|
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
return value;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
for(const child of Object.values(value)){
|
|
45
|
-
freeze(child);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return Object.freeze(value);
|
|
35
|
+
function completeResult(value){
|
|
36
|
+
return value;
|
|
49
37
|
}
|
|
50
38
|
|
|
51
39
|
function positiveSafeInteger(value){
|
|
@@ -89,7 +77,7 @@ export function deriveLocalAIRequirements(preferences){
|
|
|
89
77
|
const ttsModel=preferenceSlot(preferences,4);
|
|
90
78
|
const sttModel=preferenceSlot(preferences,5);
|
|
91
79
|
|
|
92
|
-
return
|
|
80
|
+
return completeResult({
|
|
93
81
|
llm:{
|
|
94
82
|
slot:'llm',
|
|
95
83
|
provider:llmProvider,
|
|
@@ -137,7 +125,7 @@ function healthText(status,names){
|
|
|
137
125
|
const value=token(status[name]);
|
|
138
126
|
|
|
139
127
|
if(value){
|
|
140
|
-
return value
|
|
128
|
+
return value;
|
|
141
129
|
}
|
|
142
130
|
}
|
|
143
131
|
|
|
@@ -151,7 +139,7 @@ function healthText(status,names){
|
|
|
151
139
|
*/
|
|
152
140
|
export function evaluateLocalSpeechHealth(status){
|
|
153
141
|
if(!status||typeof status!=='object'||Array.isArray(status)){
|
|
154
|
-
return
|
|
142
|
+
return completeResult({
|
|
155
143
|
reachable:false,
|
|
156
144
|
ready:false,
|
|
157
145
|
status:'unavailable',
|
|
@@ -218,7 +206,7 @@ export function evaluateLocalSpeechHealth(status){
|
|
|
218
206
|
&&ttsEngine?.toLowerCase()==='kokoro-onnx'
|
|
219
207
|
&&(synthesisAvailable??(kokoro&&voices));
|
|
220
208
|
|
|
221
|
-
return
|
|
209
|
+
return completeResult({
|
|
222
210
|
reachable:true,
|
|
223
211
|
ready:sttReady&&ttsReady,
|
|
224
212
|
status:serviceStatus,
|
|
@@ -244,18 +232,14 @@ function normalizedTimeout(value){
|
|
|
244
232
|
return DEFAULT_TIMEOUT_MS;
|
|
245
233
|
}
|
|
246
234
|
|
|
247
|
-
if(!Number.isSafeInteger(value)||value<1
|
|
248
|
-
throw new RangeError(
|
|
249
|
-
'Local AI readiness timeout must be between 1 and '
|
|
250
|
-
+MAX_TIMEOUT_MS
|
|
251
|
-
+' milliseconds.'
|
|
252
|
-
);
|
|
235
|
+
if(!Number.isSafeInteger(value)||value<1){
|
|
236
|
+
throw new RangeError('Local AI readiness timeout must be a positive integer.');
|
|
253
237
|
}
|
|
254
238
|
|
|
255
239
|
return value;
|
|
256
240
|
}
|
|
257
241
|
|
|
258
|
-
async function
|
|
242
|
+
async function fetchJSON(fetchImpl,url,timeoutMs){
|
|
259
243
|
if(typeof fetchImpl!=='function'){
|
|
260
244
|
const error=new Error('Browser fetch is unavailable.');
|
|
261
245
|
error.code='BROWSER_FETCH_UNAVAILABLE';
|
|
@@ -299,12 +283,8 @@ async function boundedFetchJSON(fetchImpl,url,timeoutMs){
|
|
|
299
283
|
|
|
300
284
|
const text=await response.text();
|
|
301
285
|
|
|
302
|
-
if(
|
|
303
|
-
|
|
304
|
-
||!text
|
|
305
|
-
||text.length>MAX_HEALTH_RESPONSE_CHARACTERS
|
|
306
|
-
){
|
|
307
|
-
const error=new Error('The local readiness response was outside Arcane limits.');
|
|
286
|
+
if(typeof text!=='string'||!text){
|
|
287
|
+
const error=new Error('The local readiness endpoint returned an invalid response.');
|
|
308
288
|
error.code='LOCAL_AI_HEALTH_INVALID_RESPONSE';
|
|
309
289
|
throw error;
|
|
310
290
|
}
|
|
@@ -337,7 +317,7 @@ async function boundedFetchJSON(fetchImpl,url,timeoutMs){
|
|
|
337
317
|
|
|
338
318
|
async function probeNativeOllama(arcane,selectedModel){
|
|
339
319
|
if(typeof arcane?.localAI?.status!=='function'){
|
|
340
|
-
return
|
|
320
|
+
return completeResult({
|
|
341
321
|
ready:false,
|
|
342
322
|
model:null,
|
|
343
323
|
errorCode:'ARCANE_LOCAL_AI_STATUS_UNAVAILABLE'
|
|
@@ -347,7 +327,7 @@ async function probeNativeOllama(arcane,selectedModel){
|
|
|
347
327
|
const model=normalizeOllamaModelIdentifier(selectedModel);
|
|
348
328
|
|
|
349
329
|
if(!model){
|
|
350
|
-
return
|
|
330
|
+
return completeResult({
|
|
351
331
|
ready:false,
|
|
352
332
|
model:null,
|
|
353
333
|
errorCode:'OLLAMA_MODEL_INVALID'
|
|
@@ -361,7 +341,7 @@ async function probeNativeOllama(arcane,selectedModel){
|
|
|
361
341
|
);
|
|
362
342
|
|
|
363
343
|
if(status?.ollama?.available===false){
|
|
364
|
-
return
|
|
344
|
+
return completeResult({
|
|
365
345
|
ready:false,
|
|
366
346
|
model,
|
|
367
347
|
...(activeParallelRequests===null
|
|
@@ -379,7 +359,7 @@ async function probeNativeOllama(arcane,selectedModel){
|
|
|
379
359
|
return entry.modelId===model;
|
|
380
360
|
});
|
|
381
361
|
|
|
382
|
-
return
|
|
362
|
+
return completeResult({
|
|
383
363
|
ready:available,
|
|
384
364
|
model,
|
|
385
365
|
...(activeParallelRequests===null
|
|
@@ -388,7 +368,7 @@ async function probeNativeOllama(arcane,selectedModel){
|
|
|
388
368
|
errorCode:available?null:'OLLAMA_MODEL_UNAVAILABLE'
|
|
389
369
|
});
|
|
390
370
|
}catch(error){
|
|
391
|
-
return
|
|
371
|
+
return completeResult({
|
|
392
372
|
ready:false,
|
|
393
373
|
model,
|
|
394
374
|
errorCode:errorCode(error,'ARCANE_LOCAL_AI_STATUS_INVALID')
|
|
@@ -398,7 +378,7 @@ async function probeNativeOllama(arcane,selectedModel){
|
|
|
398
378
|
|
|
399
379
|
async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
400
380
|
if(typeof arcane?.localAI?.status!=='function'){
|
|
401
|
-
return
|
|
381
|
+
return completeResult({
|
|
402
382
|
ready:false,
|
|
403
383
|
model:null,
|
|
404
384
|
providerMode:USER_MANAGED_LOOPBACK_PROVIDER_MODE,
|
|
@@ -410,7 +390,7 @@ async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
|
410
390
|
const model=normalizeOllamaModelIdentifier(selectedModel);
|
|
411
391
|
|
|
412
392
|
if(!model){
|
|
413
|
-
return
|
|
393
|
+
return completeResult({
|
|
414
394
|
ready:false,
|
|
415
395
|
model:null,
|
|
416
396
|
providerMode:USER_MANAGED_LOOPBACK_PROVIDER_MODE,
|
|
@@ -423,7 +403,7 @@ async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
|
423
403
|
const status=await arcane.localAI.status();
|
|
424
404
|
|
|
425
405
|
if(!isUserManagedLoopbackLocalAIStatus(status)){
|
|
426
|
-
return
|
|
406
|
+
return completeResult({
|
|
427
407
|
ready:false,
|
|
428
408
|
model,
|
|
429
409
|
providerMode:USER_MANAGED_LOOPBACK_PROVIDER_MODE,
|
|
@@ -433,7 +413,7 @@ async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
|
433
413
|
}
|
|
434
414
|
|
|
435
415
|
if(status?.ollama?.available!==true){
|
|
436
|
-
return
|
|
416
|
+
return completeResult({
|
|
437
417
|
ready:false,
|
|
438
418
|
model,
|
|
439
419
|
providerMode:USER_MANAGED_LOOPBACK_PROVIDER_MODE,
|
|
@@ -450,7 +430,7 @@ async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
|
450
430
|
return entry.modelId===model;
|
|
451
431
|
});
|
|
452
432
|
|
|
453
|
-
return
|
|
433
|
+
return completeResult({
|
|
454
434
|
ready:available,
|
|
455
435
|
model,
|
|
456
436
|
providerMode:USER_MANAGED_LOOPBACK_PROVIDER_MODE,
|
|
@@ -458,7 +438,7 @@ async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
|
458
438
|
errorCode:available?null:'OLLAMA_MODEL_UNAVAILABLE'
|
|
459
439
|
});
|
|
460
440
|
}catch(error){
|
|
461
|
-
return
|
|
441
|
+
return completeResult({
|
|
462
442
|
ready:false,
|
|
463
443
|
model,
|
|
464
444
|
providerMode:USER_MANAGED_LOOPBACK_PROVIDER_MODE,
|
|
@@ -469,7 +449,7 @@ async function probeUserManagedLoopbackOllama(arcane,selectedModel){
|
|
|
469
449
|
}
|
|
470
450
|
|
|
471
451
|
function unavailableBrowserOllama(){
|
|
472
|
-
return
|
|
452
|
+
return completeResult({
|
|
473
453
|
ready:false,
|
|
474
454
|
model:null,
|
|
475
455
|
errorCode:'ARCANE_CORE_REQUIRED'
|
|
@@ -478,19 +458,19 @@ function unavailableBrowserOllama(){
|
|
|
478
458
|
|
|
479
459
|
async function probeNativeSpeech(arcane){
|
|
480
460
|
if(typeof arcane?.speech?.status!=='function'){
|
|
481
|
-
return
|
|
461
|
+
return completeResult({
|
|
482
462
|
...evaluateLocalSpeechHealth(null),
|
|
483
463
|
errorCode:'ARCANE_SPEECH_UNAVAILABLE'
|
|
484
464
|
});
|
|
485
465
|
}
|
|
486
466
|
|
|
487
467
|
try{
|
|
488
|
-
return
|
|
468
|
+
return completeResult({
|
|
489
469
|
...evaluateLocalSpeechHealth(await arcane.speech.status()),
|
|
490
470
|
errorCode:null
|
|
491
471
|
});
|
|
492
472
|
}catch(error){
|
|
493
|
-
return
|
|
473
|
+
return completeResult({
|
|
494
474
|
...evaluateLocalSpeechHealth(null),
|
|
495
475
|
errorCode:errorCode(error,'LOCAL_SPEECH_UNAVAILABLE')
|
|
496
476
|
});
|
|
@@ -499,9 +479,9 @@ async function probeNativeSpeech(arcane){
|
|
|
499
479
|
|
|
500
480
|
async function probeBrowserSpeech(fetchImpl,timeoutMs){
|
|
501
481
|
try{
|
|
502
|
-
return
|
|
482
|
+
return completeResult({
|
|
503
483
|
...evaluateLocalSpeechHealth(
|
|
504
|
-
await
|
|
484
|
+
await fetchJSON(
|
|
505
485
|
fetchImpl,
|
|
506
486
|
LOCAL_AI_BROWSER_ENDPOINTS.speech,
|
|
507
487
|
timeoutMs
|
|
@@ -510,7 +490,7 @@ async function probeBrowserSpeech(fetchImpl,timeoutMs){
|
|
|
510
490
|
errorCode:null
|
|
511
491
|
});
|
|
512
492
|
}catch(error){
|
|
513
|
-
return
|
|
493
|
+
return completeResult({
|
|
514
494
|
...evaluateLocalSpeechHealth(null),
|
|
515
495
|
errorCode:errorCode(error,'LOCAL_SPEECH_UNAVAILABLE')
|
|
516
496
|
});
|
|
@@ -583,7 +563,7 @@ async function probeRequiredServices({
|
|
|
583
563
|
:null
|
|
584
564
|
]);
|
|
585
565
|
|
|
586
|
-
return
|
|
566
|
+
return completeResult({ollama,speech});
|
|
587
567
|
}
|
|
588
568
|
|
|
589
569
|
function slotResults(requirements,services){
|
|
@@ -591,7 +571,7 @@ function slotResults(requirements,services){
|
|
|
591
571
|
services.ollama?.activeParallelRequests
|
|
592
572
|
);
|
|
593
573
|
|
|
594
|
-
return
|
|
574
|
+
return completeResult({
|
|
595
575
|
llm:{
|
|
596
576
|
...requirements.llm,
|
|
597
577
|
...(activeParallelRequests===null
|
|
@@ -690,17 +670,17 @@ function preserveRecoveryFailure(
|
|
|
690
670
|
?failedServices
|
|
691
671
|
:[];
|
|
692
672
|
|
|
693
|
-
return
|
|
673
|
+
return completeResult({
|
|
694
674
|
ollama:targets.includes('ollama')
|
|
695
675
|
&&services.ollama?.ready!==true
|
|
696
|
-
?
|
|
676
|
+
?completeResult({...services.ollama,errorCode:recoveryErrorCode})
|
|
697
677
|
:services.ollama,
|
|
698
678
|
speech:targets.includes('speech')
|
|
699
679
|
&&(
|
|
700
680
|
services.speech?.stt?.ready!==true
|
|
701
681
|
||services.speech?.tts?.ready!==true
|
|
702
682
|
)
|
|
703
|
-
?
|
|
683
|
+
?completeResult({...services.speech,errorCode:recoveryErrorCode})
|
|
704
684
|
:services.speech
|
|
705
685
|
});
|
|
706
686
|
}
|
|
@@ -746,7 +726,7 @@ function guidance(mode,slots){
|
|
|
746
726
|
+' Arcane does not install, start, repair, pull, or otherwise manage this service or its models. Alternatively, switch the affected Profile setting to OpenAI. Arcane will not switch providers automatically.'
|
|
747
727
|
:'Arcane could not recover the selected local AI service. Retry or review Local AI in Arcane Settings. Arcane will not switch providers automatically.';
|
|
748
728
|
|
|
749
|
-
return
|
|
729
|
+
return completeResult({
|
|
750
730
|
mode,
|
|
751
731
|
affectedSlots,
|
|
752
732
|
services,
|
|
@@ -779,7 +759,7 @@ function report({
|
|
|
779
759
|
const slots=slotResults(requirements,services);
|
|
780
760
|
const unavailable=unavailableSlots(slots);
|
|
781
761
|
|
|
782
|
-
return
|
|
762
|
+
return completeResult({
|
|
783
763
|
ready:unavailable.length===0,
|
|
784
764
|
mode,
|
|
785
765
|
requirements,
|
|
@@ -865,6 +845,6 @@ export async function checkLocalAIReadiness({
|
|
|
865
845
|
mode,
|
|
866
846
|
requirements,
|
|
867
847
|
services,
|
|
868
|
-
recovery:
|
|
848
|
+
recovery:completeResult(recovery)
|
|
869
849
|
});
|
|
870
850
|
}
|
|
@@ -7,17 +7,19 @@ import {
|
|
|
7
7
|
projectArcaneDOMEvent
|
|
8
8
|
} from 'arcane-os/event-manager';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
function completeResult(value){return value;}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const SLOT_NAMES=completeResult(['llm','stt','tts']);
|
|
13
|
+
|
|
14
|
+
export const LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES=completeResult({
|
|
13
15
|
changed:'local-ai-readiness-change'
|
|
14
16
|
});
|
|
15
|
-
export const LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES=
|
|
17
|
+
export const LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES=completeResult({
|
|
16
18
|
aborted:'ARCANE_LOCAL_AI_READINESS_CONTROLLER_ABORTED',
|
|
17
19
|
disposed:'ARCANE_LOCAL_AI_READINESS_CONTROLLER_DISPOSED',
|
|
18
20
|
statusReadyTimeout:'ARCANE_LOCAL_AI_STATUS_COMPONENT_READY_TIMEOUT'
|
|
19
21
|
});
|
|
20
|
-
export const LOCAL_AI_READINESS_CONTROLLER_REASONS=
|
|
22
|
+
export const LOCAL_AI_READINESS_CONTROLLER_REASONS=completeResult({
|
|
21
23
|
checked:'local-ai-readiness-checked',
|
|
22
24
|
aborted:'local-ai-readiness-controller-aborted',
|
|
23
25
|
disposed:'local-ai-readiness-controller-disposed',
|
|
@@ -26,7 +28,7 @@ export const LOCAL_AI_READINESS_CONTROLLER_REASONS=Object.freeze({
|
|
|
26
28
|
|
|
27
29
|
function availabilityFromReport(report={}){
|
|
28
30
|
const slots=report.slots||{};
|
|
29
|
-
return
|
|
31
|
+
return completeResult(Object.fromEntries(SLOT_NAMES.map(name=>{
|
|
30
32
|
const slot=slots[name]||{};
|
|
31
33
|
return [name,slot.required===true&&slot.ready===true];
|
|
32
34
|
})));
|
|
@@ -37,10 +39,10 @@ function selectedPreferences(source){
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
function pendingReport(requirements){
|
|
40
|
-
return
|
|
41
|
-
slots:
|
|
42
|
+
return completeResult({
|
|
43
|
+
slots:completeResult(Object.fromEntries(SLOT_NAMES.map(name=>[
|
|
42
44
|
name,
|
|
43
|
-
|
|
45
|
+
completeResult({
|
|
44
46
|
...requirements[name],
|
|
45
47
|
ready:requirements[name].required?false:null
|
|
46
48
|
})
|
|
@@ -148,12 +150,12 @@ export function createLocalAIReadinessController({
|
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
const lifecycleController=new AbortController();
|
|
151
|
-
const eventOwner=
|
|
153
|
+
const eventOwner=completeResult({kind:'local-ai-readiness-controller'});
|
|
152
154
|
const events=createArcaneEventSource(
|
|
153
155
|
eventOwner,
|
|
154
156
|
{
|
|
155
157
|
source:'local-ai-readiness-controller',
|
|
156
|
-
eventTypes:
|
|
158
|
+
eventTypes:completeResult(
|
|
157
159
|
Object.values(LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES)
|
|
158
160
|
)
|
|
159
161
|
}
|
|
@@ -251,10 +253,10 @@ export function createLocalAIReadinessController({
|
|
|
251
253
|
const reason=LOCAL_AI_READINESS_CONTROLLER_REASONS.checked;
|
|
252
254
|
const publication=events.dispatch(
|
|
253
255
|
LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES.changed,
|
|
254
|
-
|
|
256
|
+
completeResult({operationId,reason,report:latestReport}),
|
|
255
257
|
{
|
|
256
258
|
operationId,
|
|
257
|
-
publicDetail:
|
|
259
|
+
publicDetail:completeResult({availability,reason})
|
|
258
260
|
}
|
|
259
261
|
);
|
|
260
262
|
projectArcaneDOMEvent(
|
|
@@ -312,7 +314,7 @@ export function createLocalAIReadinessController({
|
|
|
312
314
|
return true;
|
|
313
315
|
}
|
|
314
316
|
|
|
315
|
-
return
|
|
317
|
+
return completeResult({
|
|
316
318
|
check,
|
|
317
319
|
ensure,
|
|
318
320
|
destroy,
|
|
@@ -32,7 +32,7 @@ class MD {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
get safeRendered(){
|
|
35
|
-
return
|
|
35
|
+
return this.#rendered;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
set rendered(value=''){
|
|
@@ -64,48 +64,4 @@ class MD {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function sanitize(html=''){
|
|
68
|
-
const template=document.createElement('template');
|
|
69
|
-
template.innerHTML=html;
|
|
70
|
-
|
|
71
|
-
template.content.querySelectorAll(
|
|
72
|
-
'script,style,iframe,object,embed,link,meta,base,form,input,button,textarea,select,option,svg,math'
|
|
73
|
-
).forEach(element=>element.remove());
|
|
74
|
-
|
|
75
|
-
template.content.querySelectorAll('*').forEach(
|
|
76
|
-
function sanitizeElement(element){
|
|
77
|
-
const attributes=Array.from(element.attributes);
|
|
78
|
-
|
|
79
|
-
for(let i=0;i<attributes.length;i++){
|
|
80
|
-
const attribute=attributes[i];
|
|
81
|
-
const name=attribute.name.toLowerCase();
|
|
82
|
-
|
|
83
|
-
if(name.startsWith('on')||name==='style'||name==='srcdoc'){
|
|
84
|
-
element.removeAttribute(attribute.name);
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if(!['href','src','xlink:href'].includes(name)){
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const value=attribute.value
|
|
93
|
-
.replace(/[\u0000-\u001F\u007F\s]+/g,'')
|
|
94
|
-
.toLowerCase();
|
|
95
|
-
const safeImage=name==='src'&&value.startsWith('data:image/');
|
|
96
|
-
|
|
97
|
-
if(
|
|
98
|
-
value.startsWith('javascript:')
|
|
99
|
-
|| value.startsWith('vbscript:')
|
|
100
|
-
|| value.startsWith('data:')&&!safeImage
|
|
101
|
-
){
|
|
102
|
-
element.removeAttribute(attribute.name);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
return template.innerHTML;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
67
|
export default MD;
|