arcane-os 0.3.4 → 0.3.6

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +7 -7
  3. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +315 -119
  4. package/browser-runtime/ai/model-controller.mjs +439 -95
  5. package/package.json +1 -1
  6. package/runtime/arcane/components/assistant-panel.html +2 -1
  7. package/runtime/arcane/components/chat.html +469 -220
  8. package/runtime/arcane/components/speech.html +33 -13
  9. package/runtime/arcane/components/voice-transcription.html +27 -3
  10. package/runtime/arcane/entities/Chat.js +165 -97
  11. package/runtime/arcane/entities/IntentEnvelope.js +52 -118
  12. package/runtime/arcane/entities/TWiNPolicyDecision.js +33 -130
  13. package/runtime/arcane/entities/User.js +38 -44
  14. package/runtime/arcane/modules/AI.js +569 -302
  15. package/runtime/arcane/modules/AIProviderRuntime.js +776 -151
  16. package/runtime/arcane/modules/AIRuntimeState.js +22 -24
  17. package/runtime/arcane/modules/ApiModelDatabase.js +54 -48
  18. package/runtime/arcane/modules/CaseEvidenceIndexer.js +6 -10
  19. package/runtime/arcane/modules/CommunicationHub.js +90 -94
  20. package/runtime/arcane/modules/ComponentContracts.js +23 -9
  21. package/runtime/arcane/modules/ConfiguredAIChatSession.js +77 -77
  22. package/runtime/arcane/modules/ConversationTimebox.js +76 -104
  23. package/runtime/arcane/modules/DBLS.js +14 -12
  24. package/runtime/arcane/modules/DBOPFS.js +20 -15
  25. package/runtime/arcane/modules/Errors.js +196 -436
  26. package/runtime/arcane/modules/HTMLImport.js +49 -32
  27. package/runtime/arcane/modules/Ollama.js +16 -14
  28. package/runtime/arcane/modules/PersistentAIChatSession.js +174 -93
  29. package/runtime/arcane/modules/RecordReviewStore.js +40 -35
  30. package/runtime/arcane/modules/TerminalClient.js +12 -14
  31. package/runtime/arcane/modules/ThemeBootstrap.js +7 -7
  32. package/runtime/arcane/modules/ThemeManager.js +5 -5
  33. package/runtime/arcane/modules/TimeGuard.js +5 -65
  34. package/runtime/arcane/modules/WaitForComponent.js +43 -40
  35. package/src/installed-sdk-runtime.mjs +11 -1
@@ -3,24 +3,24 @@ import CommunicationMessage from '../entities/CommunicationMessage.js';
3
3
  import CommunicationThread from '../entities/CommunicationThread.js';
4
4
  import CommunicationProviderRegistry from './CommunicationProviderRegistry.js?v=2';
5
5
 
6
- export const COMMUNICATION_HUB_EVENTS=Object.freeze({
6
+ const communicationHubEvents={
7
7
  refreshCancelled:'communications-refresh-cancelled',
8
8
  refreshCompleted:'communications-refresh-completed',
9
9
  refreshFailed:'communications-refresh-failed',
10
10
  refreshLegacy:'communications-refresh',
11
11
  refreshPartiallyCompleted:'communications-refresh-partially-completed',
12
12
  refreshStarted:'communications-refresh-started'
13
- });
13
+ };
14
14
 
15
- export const COMMUNICATION_HUB_REFRESH_STATES=Object.freeze({
15
+ const communicationHubRefreshStates={
16
16
  cancelled:'refresh-cancelled',
17
17
  completed:'refresh-completed',
18
18
  failed:'refresh-failed',
19
19
  partiallyCompleted:'refresh-partially-completed',
20
20
  started:'refresh-started'
21
- });
21
+ };
22
22
 
23
- export const COMMUNICATION_HUB_REFRESH_REASONS=Object.freeze({
23
+ const communicationHubRefreshReasons={
24
24
  allProviderThreadListsRejected:'all-provider-thread-lists-rejected',
25
25
  boundaryThrew:'refresh-boundary-threw',
26
26
  hubDisposed:'hub-disposed',
@@ -28,9 +28,9 @@ export const COMMUNICATION_HUB_REFRESH_REASONS=Object.freeze({
28
28
  signalAborted:'refresh-signal-aborted',
29
29
  startCancelled:'refresh-start-cancelled',
30
30
  superseded:'refresh-superseded'
31
- });
31
+ };
32
32
 
33
- export const COMMUNICATION_HUB_ERROR_CODES=Object.freeze({
33
+ const communicationHubErrorCodes={
34
34
  allProviderThreadListsRejected:'ARCANE_COMMUNICATION_PROVIDER_THREAD_LISTS_REJECTED',
35
35
  disposed:'ARCANE_COMMUNICATION_HUB_DISPOSED',
36
36
  providerThreadListRejected:'ARCANE_COMMUNICATION_PROVIDER_THREAD_LIST_REJECTED',
@@ -38,7 +38,12 @@ export const COMMUNICATION_HUB_ERROR_CODES=Object.freeze({
38
38
  refreshFailed:'ARCANE_COMMUNICATION_HUB_REFRESH_FAILED',
39
39
  refreshOptionsInvalid:'ARCANE_COMMUNICATION_HUB_REFRESH_OPTIONS_INVALID',
40
40
  refreshSuperseded:'ARCANE_COMMUNICATION_HUB_REFRESH_SUPERSEDED'
41
- });
41
+ };
42
+
43
+ export const COMMUNICATION_HUB_EVENTS={...communicationHubEvents};
44
+ export const COMMUNICATION_HUB_REFRESH_STATES={...communicationHubRefreshStates};
45
+ export const COMMUNICATION_HUB_REFRESH_REASONS={...communicationHubRefreshReasons};
46
+ export const COMMUNICATION_HUB_ERROR_CODES={...communicationHubErrorCodes};
42
47
 
43
48
  function codedError(message,code,{cause,name='Error',ErrorType=Error}={}){
44
49
  const error=new ErrorType(message);
@@ -53,16 +58,16 @@ function codedError(message,code,{cause,name='Error',ErrorType=Error}={}){
53
58
  function disposedError(){
54
59
  return codedError(
55
60
  'The communication hub has been disposed.',
56
- COMMUNICATION_HUB_ERROR_CODES.disposed
61
+ communicationHubErrorCodes.disposed
57
62
  );
58
63
  }
59
64
 
60
- function refreshAbortError(reason,code=COMMUNICATION_HUB_ERROR_CODES.refreshAborted){
65
+ function refreshAbortError(reason,code=communicationHubErrorCodes.refreshAborted){
61
66
  if(reason instanceof Error&&reason.name==='AbortError'&&reason.code===code){
62
67
  return reason;
63
68
  }
64
69
  return codedError(
65
- code===COMMUNICATION_HUB_ERROR_CODES.refreshSuperseded
70
+ code===communicationHubErrorCodes.refreshSuperseded
66
71
  ?'The communication refresh was superseded by a newer refresh.'
67
72
  :'The communication refresh was aborted.',
68
73
  code,
@@ -74,12 +79,12 @@ function refreshAbortError(reason,code=COMMUNICATION_HUB_ERROR_CODES.refreshAbor
74
79
  }
75
80
 
76
81
  function refreshFailureError(error){
77
- if(error instanceof Error&&error.code===COMMUNICATION_HUB_ERROR_CODES.refreshFailed){
82
+ if(error instanceof Error&&error.code===communicationHubErrorCodes.refreshFailed){
78
83
  return error;
79
84
  }
80
85
  return codedError(
81
86
  'The communication refresh boundary failed.',
82
- COMMUNICATION_HUB_ERROR_CODES.refreshFailed,
87
+ communicationHubErrorCodes.refreshFailed,
83
88
  {cause:error}
84
89
  );
85
90
  }
@@ -94,41 +99,24 @@ function isAbortSignal(value){
94
99
 
95
100
  function normalizeRefreshOptions(value){
96
101
  if(value===undefined){
97
- return Object.freeze({signal:null});
102
+ return {signal:null};
98
103
  }
99
104
  if(!value||typeof value!=='object'||Array.isArray(value)){
100
105
  throw codedError(
101
106
  'Communication refresh options must be a plain record.',
102
- COMMUNICATION_HUB_ERROR_CODES.refreshOptionsInvalid,
103
- {ErrorType:TypeError}
104
- );
105
- }
106
- const descriptors=Object.getOwnPropertyDescriptors(value);
107
- const unknown=Reflect.ownKeys(descriptors).find(
108
- function findUnknownRefreshOption(key){
109
- return key!=='signal';
110
- }
111
- );
112
- if(unknown!==undefined||Object.values(descriptors).some(
113
- function findRefreshOptionAccessor(descriptor){
114
- return !Object.hasOwn(descriptor,'value');
115
- }
116
- )){
117
- throw codedError(
118
- 'Communication refresh options may contain only a data signal property.',
119
- COMMUNICATION_HUB_ERROR_CODES.refreshOptionsInvalid,
107
+ communicationHubErrorCodes.refreshOptionsInvalid,
120
108
  {ErrorType:TypeError}
121
109
  );
122
110
  }
123
- const signal=descriptors.signal?.value??null;
111
+ const signal=value.signal??null;
124
112
  if(signal!==null&&!isAbortSignal(signal)){
125
113
  throw codedError(
126
114
  'Communication refresh signal must be an AbortSignal.',
127
- COMMUNICATION_HUB_ERROR_CODES.refreshOptionsInvalid,
115
+ communicationHubErrorCodes.refreshOptionsInvalid,
128
116
  {ErrorType:TypeError}
129
117
  );
130
118
  }
131
- return Object.freeze({signal});
119
+ return {signal};
132
120
  }
133
121
 
134
122
  function normalizeProviderThreads(provider,values){
@@ -152,11 +140,15 @@ function compareThreadsByUpdatedAt(left,right){
152
140
  }
153
141
 
154
142
  function providerFailure(provider){
155
- return Object.freeze({
156
- code:COMMUNICATION_HUB_ERROR_CODES.providerThreadListRejected,
143
+ return {
144
+ code:communicationHubErrorCodes.providerThreadListRejected,
157
145
  providerId:provider.id,
158
- reason:COMMUNICATION_HUB_REFRESH_REASONS.providerThreadListRejected
159
- });
146
+ reason:communicationHubRefreshReasons.providerThreadListRejected
147
+ };
148
+ }
149
+
150
+ function copyProviderFailure(failure){
151
+ return {...failure};
160
152
  }
161
153
 
162
154
  function settleWithAbort(operation,promise){
@@ -215,7 +207,7 @@ export default class CommunicationHub extends EventTarget{
215
207
  this,
216
208
  {
217
209
  source:'communication-hub',
218
- eventTypes:Object.freeze(Object.values(COMMUNICATION_HUB_EVENTS))
210
+ eventTypes:Object.values(communicationHubEvents)
219
211
  }
220
212
  );
221
213
  }
@@ -264,15 +256,15 @@ export default class CommunicationHub extends EventTarget{
264
256
  operation.controller.abort(error);
265
257
  if(!this.#events.disposed){
266
258
  this.#events.dispatch(
267
- COMMUNICATION_HUB_EVENTS.refreshCancelled,
268
- Object.freeze({error,reason}),
259
+ communicationHubEvents.refreshCancelled,
260
+ {error,reason},
269
261
  {
270
262
  operationId:operation.operationId,
271
- publicDetail:Object.freeze({
263
+ publicDetail:{
272
264
  code:error.code,
273
265
  reason,
274
- state:COMMUNICATION_HUB_REFRESH_STATES.cancelled
275
- })
266
+ state:communicationHubRefreshStates.cancelled
267
+ }
276
268
  }
277
269
  );
278
270
  }
@@ -312,9 +304,9 @@ export default class CommunicationHub extends EventTarget{
312
304
  this.#cancelActiveRefresh(
313
305
  refreshAbortError(
314
306
  undefined,
315
- COMMUNICATION_HUB_ERROR_CODES.refreshSuperseded
307
+ communicationHubErrorCodes.refreshSuperseded
316
308
  ),
317
- COMMUNICATION_HUB_REFRESH_REASONS.superseded
309
+ communicationHubRefreshReasons.superseded
318
310
  );
319
311
 
320
312
  const providers=this.enabledProviders();
@@ -331,7 +323,7 @@ export default class CommunicationHub extends EventTarget{
331
323
  this.#publishCancellation(
332
324
  operation,
333
325
  refreshAbortError(settings.signal.reason),
334
- COMMUNICATION_HUB_REFRESH_REASONS.signalAborted
326
+ communicationHubRefreshReasons.signalAborted
335
327
  );
336
328
  }.bind(this);
337
329
  settings.signal?.addEventListener(
@@ -341,22 +333,22 @@ export default class CommunicationHub extends EventTarget{
341
333
  );
342
334
  this.#refreshOperation=operation;
343
335
 
344
- const providerIds=Object.freeze(providers.map(
336
+ const providerIds=providers.map(
345
337
  function communicationProviderId(provider){
346
338
  return provider.id;
347
339
  }
348
- ));
340
+ );
349
341
  const startPublication=this.#events.dispatch(
350
- COMMUNICATION_HUB_EVENTS.refreshStarted,
351
- Object.freeze({providerIds}),
342
+ communicationHubEvents.refreshStarted,
343
+ {providerIds:[...providerIds]},
352
344
  {
353
345
  cancelable:true,
354
346
  operationId:operation.operationId,
355
- publicDetail:Object.freeze({
347
+ publicDetail:{
356
348
  providerCount:providerIds.length,
357
- providerIds,
358
- state:COMMUNICATION_HUB_REFRESH_STATES.started
359
- })
349
+ providerIds:[...providerIds],
350
+ state:communicationHubRefreshStates.started
351
+ }
360
352
  }
361
353
  );
362
354
  if(operation.terminal){
@@ -367,7 +359,7 @@ export default class CommunicationHub extends EventTarget{
367
359
  this.#publishCancellation(
368
360
  operation,
369
361
  error,
370
- COMMUNICATION_HUB_REFRESH_REASONS.startCancelled
362
+ communicationHubRefreshReasons.startCancelled
371
363
  );
372
364
  throw error;
373
365
  }
@@ -375,7 +367,7 @@ export default class CommunicationHub extends EventTarget{
375
367
  if(this.#refreshOperation!==operation){
376
368
  throw operation.error??refreshAbortError(
377
369
  undefined,
378
- COMMUNICATION_HUB_ERROR_CODES.refreshSuperseded
370
+ communicationHubErrorCodes.refreshSuperseded
379
371
  );
380
372
  }
381
373
 
@@ -411,7 +403,7 @@ export default class CommunicationHub extends EventTarget{
411
403
  if(this.#refreshOperation!==operation){
412
404
  throw operation.error??refreshAbortError(
413
405
  undefined,
414
- COMMUNICATION_HUB_ERROR_CODES.refreshSuperseded
406
+ communicationHubErrorCodes.refreshSuperseded
415
407
  );
416
408
  }
417
409
 
@@ -435,45 +427,52 @@ export default class CommunicationHub extends EventTarget{
435
427
  if(this.#refreshOperation!==operation){
436
428
  throw operation.error??refreshAbortError(
437
429
  undefined,
438
- COMMUNICATION_HUB_ERROR_CODES.refreshSuperseded
430
+ communicationHubErrorCodes.refreshSuperseded
439
431
  );
440
432
  }
441
433
 
442
434
  this.threads=threads;
443
435
  const returnedThreads=[...this.threads];
444
436
  const returnedErrors=[...errors];
445
- const frozenFailures=Object.freeze([...failures]);
446
437
  const allProvidersRejected=providers.length>0
447
438
  &&failures.length===providers.length;
448
439
  const state=allProvidersRejected
449
- ?COMMUNICATION_HUB_REFRESH_STATES.failed
440
+ ?communicationHubRefreshStates.failed
450
441
  :failures.length
451
- ?COMMUNICATION_HUB_REFRESH_STATES.partiallyCompleted
452
- :COMMUNICATION_HUB_REFRESH_STATES.completed;
442
+ ?communicationHubRefreshStates.partiallyCompleted
443
+ :communicationHubRefreshStates.completed;
453
444
  const terminalType=allProvidersRejected
454
- ?COMMUNICATION_HUB_EVENTS.refreshFailed
445
+ ?communicationHubEvents.refreshFailed
455
446
  :failures.length
456
- ?COMMUNICATION_HUB_EVENTS.refreshPartiallyCompleted
457
- :COMMUNICATION_HUB_EVENTS.refreshCompleted;
458
- const compatibilityDetail=Object.freeze({
459
- errors:Object.freeze([...returnedErrors]),
460
- failures:frozenFailures,
447
+ ?communicationHubEvents.refreshPartiallyCompleted
448
+ :communicationHubEvents.refreshCompleted;
449
+ const compatibilityDetail={
450
+ errors:[...returnedErrors],
451
+ failures:failures.map(copyProviderFailure),
461
452
  state,
462
- threads:Object.freeze([...returnedThreads])
463
- });
464
- const publicDetail=Object.freeze({
453
+ threads:[...returnedThreads]
454
+ };
455
+ const publicDetail={
465
456
  ...(allProvidersRejected
466
457
  ?{
467
- code:COMMUNICATION_HUB_ERROR_CODES.allProviderThreadListsRejected,
468
- reason:COMMUNICATION_HUB_REFRESH_REASONS.allProviderThreadListsRejected
458
+ code:communicationHubErrorCodes.allProviderThreadListsRejected,
459
+ reason:communicationHubRefreshReasons.allProviderThreadListsRejected
469
460
  }
470
461
  :{}),
471
462
  failureCount:failures.length,
472
- failures:frozenFailures,
463
+ failures:failures.map(copyProviderFailure),
473
464
  providerCount:providers.length,
474
465
  state,
475
466
  threadCount:threads.length
476
- });
467
+ };
468
+ const legacyDetail={
469
+ errors:[...returnedErrors],
470
+ threads:[...returnedThreads]
471
+ };
472
+ const legacyPublicDetail={
473
+ ...publicDetail,
474
+ failures:publicDetail.failures.map(copyProviderFailure)
475
+ };
477
476
  operation.terminal=true;
478
477
  this.#clearRefreshOperation(operation);
479
478
  this.#events.dispatch(
@@ -486,14 +485,11 @@ export default class CommunicationHub extends EventTarget{
486
485
  );
487
486
  if(!this.#events.disposed){
488
487
  this.#events.dispatch(
489
- COMMUNICATION_HUB_EVENTS.refreshLegacy,
490
- Object.freeze({
491
- errors:compatibilityDetail.errors,
492
- threads:compatibilityDetail.threads
493
- }),
488
+ communicationHubEvents.refreshLegacy,
489
+ legacyDetail,
494
490
  {
495
491
  operationId:operation.operationId,
496
- publicDetail
492
+ publicDetail:legacyPublicDetail
497
493
  }
498
494
  );
499
495
  }
@@ -506,9 +502,9 @@ export default class CommunicationHub extends EventTarget{
506
502
  this.#publishCancellation(
507
503
  operation,
508
504
  error,
509
- error.code===COMMUNICATION_HUB_ERROR_CODES.refreshSuperseded
510
- ?COMMUNICATION_HUB_REFRESH_REASONS.superseded
511
- :COMMUNICATION_HUB_REFRESH_REASONS.signalAborted
505
+ error.code===communicationHubErrorCodes.refreshSuperseded
506
+ ?communicationHubRefreshReasons.superseded
507
+ :communicationHubRefreshReasons.signalAborted
512
508
  );
513
509
  throw error;
514
510
  }
@@ -518,15 +514,15 @@ export default class CommunicationHub extends EventTarget{
518
514
  this.#clearRefreshOperation(operation);
519
515
  if(!this.#events.disposed){
520
516
  this.#events.dispatch(
521
- COMMUNICATION_HUB_EVENTS.refreshFailed,
522
- Object.freeze({error:failure}),
517
+ communicationHubEvents.refreshFailed,
518
+ {error:failure},
523
519
  {
524
520
  operationId:operation.operationId,
525
- publicDetail:Object.freeze({
521
+ publicDetail:{
526
522
  code:failure.code,
527
- reason:COMMUNICATION_HUB_REFRESH_REASONS.boundaryThrew,
528
- state:COMMUNICATION_HUB_REFRESH_STATES.failed
529
- })
523
+ reason:communicationHubRefreshReasons.boundaryThrew,
524
+ state:communicationHubRefreshStates.failed
525
+ }
530
526
  }
531
527
  );
532
528
  }
@@ -583,9 +579,9 @@ export default class CommunicationHub extends EventTarget{
583
579
  this.#cancelActiveRefresh(
584
580
  refreshAbortError(
585
581
  disposedError(),
586
- COMMUNICATION_HUB_ERROR_CODES.disposed
582
+ communicationHubErrorCodes.disposed
587
583
  ),
588
- COMMUNICATION_HUB_REFRESH_REASONS.hubDisposed
584
+ communicationHubRefreshReasons.hubDisposed
589
585
  );
590
586
  return this.#events.dispose();
591
587
  }
@@ -403,6 +403,26 @@ function effectiveDashboardVisibility(definitions=[],visibility={}){
403
403
  );
404
404
  }
405
405
 
406
+ function formatAIRuntimeProgress(progress,fallback){
407
+ const phase=typeof progress?.phase==='string'&&progress.phase
408
+ ?progress.phase
409
+ :fallback;
410
+ const completed=progress?.completed;
411
+ const total=progress?.total;
412
+ const unit=typeof progress?.unit==='string'
413
+ ?progress.unit
414
+ :'';
415
+ if(!Number.isSafeInteger(completed)
416
+ ||completed<0
417
+ ||!Number.isSafeInteger(total)
418
+ ||total<=0
419
+ ||completed>total
420
+ ||!unit){
421
+ return phase;
422
+ }
423
+ return `${phase} · ${completed} of ${total} ${unit}`;
424
+ }
425
+
406
426
  function createSTTActivationController({
407
427
  host,
408
428
  button,
@@ -539,13 +559,6 @@ function createSTTActivationController({
539
559
  return 'Start the selected transcription service.';
540
560
  }
541
561
 
542
- function formatProgress(progress,fallback){
543
- if(!progress){
544
- return fallback;
545
- }
546
- return progress.phase;
547
- }
548
-
549
562
  function status(){
550
563
  if(requestError){
551
564
  return `Transcription activation error: ${requestError}.`;
@@ -557,10 +570,10 @@ function createSTTActivationController({
557
570
  return role.busy?'Transcription busy.':'Transcription ready.';
558
571
  }
559
572
  if(role?.state==='loading'){
560
- return `Transcription ${formatProgress(role.progress,'loading')}; Cancel is available.`;
573
+ return `Transcription ${formatAIRuntimeProgress(role.progress,'loading')}; Cancel is available.`;
561
574
  }
562
575
  if(role?.state==='unloading'){
563
- return `Transcription ${formatProgress(role.progress,'releasing')}.`;
576
+ return `Transcription ${formatAIRuntimeProgress(role.progress,'releasing')}.`;
564
577
  }
565
578
  if(role?.state==='error'){
566
579
  return `Transcription error: ${visibleError(role.error,'Unknown error')}.`;
@@ -1043,6 +1056,7 @@ export {
1043
1056
  applyMarkdownFormat,
1044
1057
  createSTTActivationController,
1045
1058
  effectiveDashboardVisibility,
1059
+ formatAIRuntimeProgress,
1046
1060
  normalizeChartOptions,
1047
1061
  normalizeChartRows,
1048
1062
  normalizeDashboardDefinitions,