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
@@ -1,10 +1,4 @@
1
- const AGGREGATE_MAXIMUM_BYTES = 32 * 1024;
2
1
  const IDENTIFIER_MAXIMUM_CHARACTERS = 128;
3
- const REASON_CODE_MAXIMUM_BYTES = 128;
4
- const REASON_CODE_MAXIMUM = 16;
5
- const REQUIREMENT_MAXIMUM = 32;
6
- const REQUIREMENT_TARGET_MAXIMUM_BYTES = 256;
7
- const SCALAR_STRING_MAXIMUM_BYTES = 2048;
8
2
 
9
3
  const SCHEMA = 'arcane.twin-policy-decision';
10
4
  const VERSION = 1;
@@ -45,40 +39,14 @@ const RESERVED_KEYS = new Set(RESERVED_KEYS_VALUES);
45
39
  const LAYERS = new Set(LAYER_VALUES);
46
40
  const OUTCOMES = new Set(OUTCOME_VALUES);
47
41
  const REQUIREMENT_OUTCOMES = new Set(REQUIREMENT_OUTCOME_VALUES);
48
- const ROOT_KEYS = Object.freeze(ROOT_KEY_VALUES);
49
- const PAYLOAD_KEYS = Object.freeze(PAYLOAD_KEY_VALUES);
50
- const TRUSTED_CONTEXT_KEYS = Object.freeze(TRUSTED_CONTEXT_KEY_VALUES);
51
- const POLICY_KEYS = Object.freeze(POLICY_KEY_VALUES);
52
- const REQUIREMENT_KEYS = Object.freeze(REQUIREMENT_KEY_VALUES);
53
- const CORE_REASON_CODES = Object.freeze(CORE_REASON_CODE_VALUES);
42
+ const ROOT_KEYS = ROOT_KEY_VALUES;
43
+ const PAYLOAD_KEYS = PAYLOAD_KEY_VALUES;
44
+ const TRUSTED_CONTEXT_KEYS = TRUSTED_CONTEXT_KEY_VALUES;
45
+ const POLICY_KEYS = POLICY_KEY_VALUES;
46
+ const REQUIREMENT_KEYS = REQUIREMENT_KEY_VALUES;
47
+ const CORE_REASON_CODES = CORE_REASON_CODE_VALUES;
54
48
  const CORE_REASON_CODE_SET = new Set(Object.values(CORE_REASON_CODES));
55
49
 
56
- function safeJSONIdentity() {
57
- return this;
58
- }
59
- Object.freeze(safeJSONIdentity);
60
-
61
- const SAFE_RECORD_PROTOTYPE = Object.create(Object.prototype);
62
- Object.defineProperty(
63
- SAFE_RECORD_PROTOTYPE,
64
- 'toJSON',
65
- {
66
- value: safeJSONIdentity
67
- }
68
- );
69
- Object.freeze(SAFE_RECORD_PROTOTYPE);
70
-
71
- const SAFE_ARRAY_PROTOTYPE = Object.create(Array.prototype);
72
- Object.defineProperty(
73
- SAFE_ARRAY_PROTOTYPE,
74
- 'toJSON',
75
- {
76
- value: safeJSONIdentity
77
- }
78
- );
79
- Object.freeze(SAFE_ARRAY_PROTOTYPE);
80
-
81
- const encoder = new TextEncoder();
82
50
  const constructionToken = Symbol('TWiNPolicyDecision construction');
83
51
  const decisionInstances = new WeakSet();
84
52
  const validationFailureTokens = new WeakMap();
@@ -97,7 +65,6 @@ function fail(code, path, message) {
97
65
  const error = new TWiNPolicyDecisionValidationError(code, path, message);
98
66
 
99
67
  validationFailureTokens.set(error, activeValidationToken);
100
- Object.freeze(error);
101
68
  throw error;
102
69
  }
103
70
 
@@ -123,7 +90,7 @@ function validationBoundary(operation) {
123
90
  }
124
91
 
125
92
  function safeRecord() {
126
- return Object.create(SAFE_RECORD_PROTOTYPE);
93
+ return {};
127
94
  }
128
95
 
129
96
  function defineDataProperty(target, key, value) {
@@ -153,8 +120,6 @@ function safeArray(values) {
153
120
  for (let index = 0; index < values.length; index += 1) {
154
121
  appendOwn(array, values[index]);
155
122
  }
156
- Object.setPrototypeOf(array, SAFE_ARRAY_PROTOTYPE);
157
-
158
123
  return array;
159
124
  }
160
125
 
@@ -178,10 +143,6 @@ function sortedCopy(values, compare) {
178
143
  return sorted;
179
144
  }
180
145
 
181
- function byteLength(value) {
182
- return encoder.encode(value).byteLength;
183
- }
184
-
185
146
  function validateUnicode(value, path) {
186
147
  for (let index = 0; index < value.length; index += 1) {
187
148
  const unit = value.charCodeAt(index);
@@ -209,7 +170,7 @@ function validateUnicode(value, path) {
209
170
  return value;
210
171
  }
211
172
 
212
- function boundedString(value, path, maximum, options = {}) {
173
+ function normalizedString(value, path, options = {}) {
213
174
  const nullable = options.nullable === true;
214
175
  const nonempty = options.nonempty !== false;
215
176
 
@@ -223,13 +184,6 @@ function boundedString(value, path, maximum, options = {}) {
223
184
  'TWiN policy decision field has an invalid type.'
224
185
  );
225
186
  }
226
- if (value.length > maximum) {
227
- fail(
228
- 'TWIN_POLICY_DECISION_LIMIT_EXCEEDED',
229
- path,
230
- 'TWiN policy decision field exceeds its size limit.'
231
- );
232
- }
233
187
  validateUnicode(value, path);
234
188
  if (nonempty && !value.trim()) {
235
189
  fail(
@@ -238,14 +192,6 @@ function boundedString(value, path, maximum, options = {}) {
238
192
  'TWiN policy decision field must contain text.'
239
193
  );
240
194
  }
241
- if (byteLength(value) > maximum) {
242
- fail(
243
- 'TWIN_POLICY_DECISION_LIMIT_EXCEEDED',
244
- path,
245
- 'TWiN policy decision field exceeds its size limit.'
246
- );
247
- }
248
-
249
195
  return value;
250
196
  }
251
197
 
@@ -298,7 +244,7 @@ function plainRecord(value, path, allowedKeys, active) {
298
244
  if (
299
245
  prototype !== Object.prototype
300
246
  && prototype !== null
301
- && prototype !== SAFE_RECORD_PROTOTYPE
247
+ && !decisionInstances.has(value)
302
248
  ) {
303
249
  fail(
304
250
  'TWIN_POLICY_DECISION_INVALID',
@@ -363,7 +309,7 @@ function ownValue(record, key, path, options = {}) {
363
309
  return descriptor.value;
364
310
  }
365
311
 
366
- function denseArray(value, path, maximum, active) {
312
+ function denseArray(value, path, active) {
367
313
  if (!Array.isArray(value)) {
368
314
  fail(
369
315
  'TWIN_POLICY_DECISION_INVALID',
@@ -373,7 +319,7 @@ function denseArray(value, path, maximum, active) {
373
319
  }
374
320
  const prototype = Object.getPrototypeOf(value);
375
321
 
376
- if (prototype !== Array.prototype && prototype !== SAFE_ARRAY_PROTOTYPE) {
322
+ if (prototype !== Array.prototype) {
377
323
  fail(
378
324
  'TWIN_POLICY_DECISION_INVALID',
379
325
  path,
@@ -387,13 +333,6 @@ function denseArray(value, path, maximum, active) {
387
333
  'TWiN policy decision data must not contain cycles.'
388
334
  );
389
335
  }
390
- if (value.length > maximum) {
391
- fail(
392
- 'TWIN_POLICY_DECISION_LIMIT_EXCEEDED',
393
- path,
394
- 'TWiN policy decision array exceeds its item limit.'
395
- );
396
- }
397
336
  active.add(value);
398
337
 
399
338
  for (const key of Reflect.ownKeys(value)) {
@@ -558,7 +497,7 @@ function normalizeTrustedTimestamp(value, path) {
558
497
  }
559
498
 
560
499
  function normalizeReasonCode(value, path) {
561
- const code = boundedString(value, path, REASON_CODE_MAXIMUM_BYTES);
500
+ const code = normalizedString(value, path);
562
501
 
563
502
  if (!REASON_CODE_PATTERN.test(code)) {
564
503
  fail(
@@ -580,7 +519,7 @@ function compareStrings(left, right) {
580
519
  }
581
520
 
582
521
  function normalizeReasonCodes(value, outcome, path, active) {
583
- const list = denseArray(value, path, REASON_CODE_MAXIMUM, active);
522
+ const list = denseArray(value, path, active);
584
523
 
585
524
  if (list.length === 0) {
586
525
  finishArray(list, active);
@@ -638,14 +577,13 @@ function normalizeReasonCodes(value, outcome, path, active) {
638
577
  appendOwn(canonicalReasons, sortedAdditional[index]);
639
578
  }
640
579
 
641
- return Object.freeze(safeArray(canonicalReasons));
580
+ return safeArray(canonicalReasons);
642
581
  }
643
582
 
644
583
  function normalizeRequirementTarget(value, path) {
645
- const target = boundedString(
584
+ const target = normalizedString(
646
585
  value,
647
586
  path,
648
- REQUIREMENT_TARGET_MAXIMUM_BYTES,
649
587
  {
650
588
  nullable: true
651
589
  }
@@ -667,10 +605,9 @@ function normalizeScalar(value, path) {
667
605
  return value;
668
606
  }
669
607
  if (typeof value === 'string') {
670
- return boundedString(
608
+ return normalizedString(
671
609
  value,
672
610
  path,
673
- SCALAR_STRING_MAXIMUM_BYTES,
674
611
  {
675
612
  nonempty: false
676
613
  }
@@ -714,7 +651,7 @@ function normalizeRequirement(value, path, reasonCodes, active) {
714
651
  );
715
652
  }
716
653
 
717
- return Object.freeze(requirement);
654
+ return requirement;
718
655
  }
719
656
 
720
657
  function compareRequirements(left, right) {
@@ -722,7 +659,7 @@ function compareRequirements(left, right) {
722
659
  }
723
660
 
724
661
  function normalizeRequirements(value, outcome, reasonCodes, path, active) {
725
- const list = denseArray(value, path, REQUIREMENT_MAXIMUM, active);
662
+ const list = denseArray(value, path, active);
726
663
  const normalized = [];
727
664
  const ids = new Set();
728
665
 
@@ -762,7 +699,7 @@ function normalizeRequirements(value, outcome, reasonCodes, path, active) {
762
699
  );
763
700
  }
764
701
 
765
- return Object.freeze(safeArray(sortedCopy(normalized, compareRequirements)));
702
+ return safeArray(sortedCopy(normalized, compareRequirements));
766
703
  }
767
704
 
768
705
  function normalizePolicy(value, path, active) {
@@ -773,7 +710,7 @@ function normalizePolicy(value, path, active) {
773
710
  };
774
711
  finishRecord(record, active);
775
712
 
776
- return Object.freeze(policy);
713
+ return policy;
777
714
  }
778
715
 
779
716
  function clonePolicy(value) {
@@ -817,18 +754,6 @@ function canonicalRecord(values) {
817
754
  return canonical;
818
755
  }
819
756
 
820
- function validateAggregate(values) {
821
- const serialized = JSON.stringify(canonicalRecord(values));
822
-
823
- if (byteLength(serialized) > AGGREGATE_MAXIMUM_BYTES) {
824
- fail(
825
- 'TWIN_POLICY_DECISION_LIMIT_EXCEEDED',
826
- '$',
827
- 'TWiN policy decision exceeds its aggregate size limit.'
828
- );
829
- }
830
- }
831
-
832
757
  function normalizeValues(input) {
833
758
  const active = new WeakSet();
834
759
  const record = plainRecord(input, '$', ROOT_KEYS, active);
@@ -890,7 +815,6 @@ function normalizeValues(input) {
890
815
  )
891
816
  };
892
817
  finishRecord(record, active);
893
- validateAggregate(values);
894
818
 
895
819
  return values;
896
820
  }
@@ -969,14 +893,12 @@ class TWiNPolicyDecision {
969
893
  defineDataProperty(this, 'reasonCodes', values.reasonCodes);
970
894
  defineDataProperty(this, 'requirements', values.requirements);
971
895
  decisionInstances.add(this);
972
- Object.freeze(this);
973
896
  }
974
897
 
975
898
  toJSON() {
976
- return canonicalRecord(this);
899
+ return canonicalRecord(normalizeValues(this));
977
900
  }
978
901
  }
979
- Object.freeze(TWiNPolicyDecision.prototype);
980
902
 
981
903
  function buildDecision(canonical) {
982
904
  const values = normalizeValues(canonical);
@@ -993,25 +915,12 @@ export function createTWiNPolicyDecision(payload, trustedContext) {
993
915
  }
994
916
 
995
917
  export function rehydrateTWiNPolicyDecision(canonical) {
996
- if (decisionInstances.has(canonical)) {
997
- return canonical;
998
- }
999
918
  return validationBoundary(
1000
919
  function validateCanonicalInput() {
1001
920
  let source = canonical;
1002
921
  let canonicalText = null;
1003
922
 
1004
923
  if (typeof source === 'string') {
1005
- if (
1006
- source.length > AGGREGATE_MAXIMUM_BYTES
1007
- || byteLength(source) > AGGREGATE_MAXIMUM_BYTES
1008
- ) {
1009
- fail(
1010
- 'TWIN_POLICY_DECISION_LIMIT_EXCEEDED',
1011
- '$',
1012
- 'TWiN policy decision JSON exceeds its input size limit.'
1013
- );
1014
- }
1015
924
  canonicalText = source;
1016
925
  source = JSON.parse(source);
1017
926
  }
@@ -1044,7 +953,7 @@ export function twinPolicyDecisionAuditProjection(decision) {
1044
953
  for (let index = 0; index < value.requirements.length; index += 1) {
1045
954
  appendOwn(
1046
955
  requirements,
1047
- Object.freeze(auditRequirement(value.requirements[index]))
956
+ auditRequirement(value.requirements[index])
1048
957
  );
1049
958
  }
1050
959
  const projection = safeRecord();
@@ -1054,39 +963,33 @@ export function twinPolicyDecisionAuditProjection(decision) {
1054
963
  defineDataProperty(projection, 'id', value.id);
1055
964
  defineDataProperty(projection, 'evaluatedAt', value.evaluatedAt);
1056
965
  defineDataProperty(projection, 'layer', value.layer);
1057
- defineDataProperty(projection, 'policy', Object.freeze(clonePolicy(value.policy)));
966
+ defineDataProperty(projection, 'policy', clonePolicy(value.policy));
1058
967
  defineDataProperty(projection, 'outcome', value.outcome);
1059
968
  defineDataProperty(
1060
969
  projection,
1061
970
  'reasonCodes',
1062
- Object.freeze(safeArray(value.reasonCodes))
971
+ safeArray(value.reasonCodes)
1063
972
  );
1064
973
  defineDataProperty(
1065
974
  projection,
1066
975
  'requirements',
1067
- Object.freeze(safeArray(requirements))
976
+ safeArray(requirements)
1068
977
  );
1069
978
 
1070
- return Object.freeze(projection);
979
+ return projection;
1071
980
  }
1072
981
 
1073
- const limits = Object.freeze({
1074
- aggregateBytes: AGGREGATE_MAXIMUM_BYTES,
1075
- identifierCharacters: IDENTIFIER_MAXIMUM_CHARACTERS,
1076
- reasonCodeBytes: REASON_CODE_MAXIMUM_BYTES,
1077
- reasonCodeCount: REASON_CODE_MAXIMUM,
1078
- requirementCount: REQUIREMENT_MAXIMUM,
1079
- requirementTargetBytes: REQUIREMENT_TARGET_MAXIMUM_BYTES,
1080
- scalarStringBytes: SCALAR_STRING_MAXIMUM_BYTES
1081
- });
982
+ const limits = {
983
+ identifierCharacters: IDENTIFIER_MAXIMUM_CHARACTERS
984
+ };
1082
985
  const contractValue = {
1083
986
  schema: SCHEMA,
1084
987
  version: VERSION,
1085
- layers: Object.freeze([...LAYERS]),
1086
- outcomes: Object.freeze([...OUTCOMES]),
1087
- requirementOutcomes: Object.freeze([...REQUIREMENT_OUTCOMES]),
988
+ layers: [...LAYERS],
989
+ outcomes: [...OUTCOMES],
990
+ requirementOutcomes: [...REQUIREMENT_OUTCOMES],
1088
991
  coreReasonCodes: CORE_REASON_CODES,
1089
992
  limits
1090
993
  };
1091
994
 
1092
- export const twinPolicyDecisionContract = Object.freeze(contractValue);
995
+ export const twinPolicyDecisionContract = contractValue;
@@ -130,41 +130,39 @@ class UserEntity {
130
130
 
131
131
  #explicitUpdateQueue = Promise.resolve();
132
132
 
133
- #schema = Object.freeze(
134
- [
135
- 'username',
136
- 'email',
137
- 'phone',
138
- 'language',
139
- 'license_key',
140
- 'subscription_key',
141
- 'current_time',
142
- 'last_successful_time',
143
-
144
- 'contact_1',
145
- 'contact_2',
146
- 'contact_3',
147
- 'contact_4',
148
- 'contact_5',
149
- 'contact_6',
150
-
151
- 'AI_personality',
152
- 'religion',
153
- 'AI_voice',
154
- 'AI_speed',
155
- 'ai_verbosity',
156
- 'initialSpeechMuted',
157
- 'conversationClosingReportEnabled',
158
- 'conversationActionItemsEnabled',
159
- 'firstBootUp',
160
- 'questionnaireShown',
161
- 'skin',
162
- 'developer',
163
- 'prefersLocal',
164
- 'preferredModels',
165
- 'dashboard'
166
- ]
167
- );
133
+ #schema = [
134
+ 'username',
135
+ 'email',
136
+ 'phone',
137
+ 'language',
138
+ 'license_key',
139
+ 'subscription_key',
140
+ 'current_time',
141
+ 'last_successful_time',
142
+
143
+ 'contact_1',
144
+ 'contact_2',
145
+ 'contact_3',
146
+ 'contact_4',
147
+ 'contact_5',
148
+ 'contact_6',
149
+
150
+ 'AI_personality',
151
+ 'religion',
152
+ 'AI_voice',
153
+ 'AI_speed',
154
+ 'ai_verbosity',
155
+ 'initialSpeechMuted',
156
+ 'conversationClosingReportEnabled',
157
+ 'conversationActionItemsEnabled',
158
+ 'firstBootUp',
159
+ 'questionnaireShown',
160
+ 'skin',
161
+ 'developer',
162
+ 'prefersLocal',
163
+ 'preferredModels',
164
+ 'dashboard'
165
+ ];
168
166
 
169
167
 
170
168
 
@@ -220,7 +218,7 @@ class UserEntity {
220
218
  this.fileName = fileName;
221
219
  this.#events=createArcaneEventSource(this,{
222
220
  source:'user-entity',
223
- eventTypes:Object.freeze([USER_ENTITY_LOADED_EVENT])
221
+ eventTypes:[USER_ENTITY_LOADED_EVENT]
224
222
  });
225
223
 
226
224
  if(window.dbopfs?.ready){
@@ -499,10 +497,6 @@ class UserEntity {
499
497
  throw new Error('AI_personality must be string');
500
498
  }
501
499
 
502
- if(v.length > 1000){
503
- throw new Error('AI_personality must be less than 1000 characters');
504
- }
505
-
506
500
  this.#AI_personality = v;
507
501
 
508
502
  this.#persist();
@@ -1038,16 +1032,16 @@ class UserEntity {
1038
1032
 
1039
1033
  const {occurrence}=this.#events.dispatch(
1040
1034
  USER_ENTITY_LOADED_EVENT,
1041
- Object.freeze({
1035
+ {
1042
1036
  reason:USER_ENTITY_LOADED_REASON,
1043
1037
  user:this
1044
- }),
1038
+ },
1045
1039
  {
1046
1040
  operationId,
1047
- publicDetail:Object.freeze({
1041
+ publicDetail:{
1048
1042
  ready:true,
1049
1043
  reason:USER_ENTITY_LOADED_REASON
1050
- })
1044
+ }
1051
1045
  }
1052
1046
  );
1053
1047
  projectArcaneDOMEvent(window,occurrence);