arcane-os 0.1.0-dev.5

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 (248) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/COMMERCIAL-LICENSE.md +13 -0
  3. package/LICENSE +661 -0
  4. package/NOTICE +70 -0
  5. package/README.md +448 -0
  6. package/bin/arcane-test.mjs +741 -0
  7. package/bin/arcane.mjs +5 -0
  8. package/docs/architecture.md +234 -0
  9. package/docs/compatibility.md +36 -0
  10. package/docs/event-manager.md +166 -0
  11. package/docs/platform-targets.md +108 -0
  12. package/docs/publishing.md +203 -0
  13. package/docs/reference/README.md +117 -0
  14. package/docs/reference/arcane-ollama.md +288 -0
  15. package/docs/reference/availability-and-normalization.md +123 -0
  16. package/docs/reference/behavioral-testing.md +86 -0
  17. package/docs/reference/cli.md +569 -0
  18. package/docs/reference/core/README.md +62 -0
  19. package/docs/reference/core/arcane-ai-contracts.md +873 -0
  20. package/docs/reference/core/arcane-api.md +601 -0
  21. package/docs/reference/core/arcane-entities.md +65 -0
  22. package/docs/reference/core/arcane-events.md +134 -0
  23. package/docs/reference/core/ollama-module.md +181 -0
  24. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  25. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  26. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  27. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  28. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  29. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  30. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  31. package/docs/reference/event-manager.md +957 -0
  32. package/docs/reference/inventory/package-api.json +2632 -0
  33. package/docs/reference/inventory/runtime-components.json +934 -0
  34. package/docs/reference/inventory/runtime-entities.json +26 -0
  35. package/docs/reference/inventory/runtime-modules.json +1249 -0
  36. package/docs/reference/protocols.md +242 -0
  37. package/docs/reference/runtime-components.md +1098 -0
  38. package/docs/reference/runtime-entities.md +303 -0
  39. package/docs/reference/runtime-modules.md +2010 -0
  40. package/docs/reference/sdk-api.md +4901 -0
  41. package/docs/roadmap.md +79 -0
  42. package/docs/work-amplification.md +124 -0
  43. package/node_modules/event-pubsub/CHANGELOG.md +55 -0
  44. package/node_modules/event-pubsub/MIGRATION.md +70 -0
  45. package/node_modules/event-pubsub/README.md +363 -0
  46. package/node_modules/event-pubsub/SECURITY.md +37 -0
  47. package/node_modules/event-pubsub/index.js +141 -0
  48. package/node_modules/event-pubsub/licence +21 -0
  49. package/node_modules/event-pubsub/package.json +59 -0
  50. package/node_modules/strong-type/README.md +408 -0
  51. package/node_modules/strong-type/assets/strong-type-header.png +0 -0
  52. package/node_modules/strong-type/index.js +1151 -0
  53. package/node_modules/strong-type/licence +21 -0
  54. package/node_modules/strong-type/node.js +125 -0
  55. package/node_modules/strong-type/package.json +61 -0
  56. package/package.json +95 -0
  57. package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
  58. package/runtime/arcane/components/app-bar.html +468 -0
  59. package/runtime/arcane/components/assistant-panel.html +715 -0
  60. package/runtime/arcane/components/calculator.html +8 -0
  61. package/runtime/arcane/components/chart.html +655 -0
  62. package/runtime/arcane/components/chat.html +1225 -0
  63. package/runtime/arcane/components/conversation-view.html +13 -0
  64. package/runtime/arcane/components/dashboard-config.html +341 -0
  65. package/runtime/arcane/components/data-maintenance.html +112 -0
  66. package/runtime/arcane/components/data-view.html +92 -0
  67. package/runtime/arcane/components/directory-picker.html +197 -0
  68. package/runtime/arcane/components/document-inspector.html +252 -0
  69. package/runtime/arcane/components/file-drop.html +264 -0
  70. package/runtime/arcane/components/file-inspector.html +293 -0
  71. package/runtime/arcane/components/file-manager.html +1715 -0
  72. package/runtime/arcane/components/header.html +142 -0
  73. package/runtime/arcane/components/integration-settings.html +14 -0
  74. package/runtime/arcane/components/local-ai-status.html +360 -0
  75. package/runtime/arcane/components/markdown-document.html +1048 -0
  76. package/runtime/arcane/components/markdown-editor.html +360 -0
  77. package/runtime/arcane/components/media-embed.html +8 -0
  78. package/runtime/arcane/components/modal.html +402 -0
  79. package/runtime/arcane/components/output-panel.html +259 -0
  80. package/runtime/arcane/components/preferences-form.html +135 -0
  81. package/runtime/arcane/components/record-timeline.html +105 -0
  82. package/runtime/arcane/components/relationship-board.html +116 -0
  83. package/runtime/arcane/components/screen-capture.html +8 -0
  84. package/runtime/arcane/components/source-code-viewer.html +441 -0
  85. package/runtime/arcane/components/source-explanation.html +124 -0
  86. package/runtime/arcane/components/speech.html +365 -0
  87. package/runtime/arcane/components/summary-strip.html +177 -0
  88. package/runtime/arcane/components/table.html +77 -0
  89. package/runtime/arcane/components/task-progress.html +282 -0
  90. package/runtime/arcane/components/terminal-workspace.html +65 -0
  91. package/runtime/arcane/components/theme-editor.html +41 -0
  92. package/runtime/arcane/components/theme-switcher.html +46 -0
  93. package/runtime/arcane/components/unified-inbox.html +20 -0
  94. package/runtime/arcane/components/voice-transcription.html +476 -0
  95. package/runtime/arcane/components/weather-widget.html +8 -0
  96. package/runtime/arcane/components/web-navigator.html +239 -0
  97. package/runtime/arcane/css/communications.css +1 -0
  98. package/runtime/arcane/css/dashboard-config.css +45 -0
  99. package/runtime/arcane/css/document-site.css +981 -0
  100. package/runtime/arcane/css/layout.css +438 -0
  101. package/runtime/arcane/css/primitives.css +321 -0
  102. package/runtime/arcane/css/theme.css +112 -0
  103. package/runtime/arcane/css/utility-workspace.css +1 -0
  104. package/runtime/arcane/entities/ApiModelRecord.js +20 -0
  105. package/runtime/arcane/entities/Calculation.js +13 -0
  106. package/runtime/arcane/entities/Chat.js +581 -0
  107. package/runtime/arcane/entities/CommunicationMessage.js +29 -0
  108. package/runtime/arcane/entities/CommunicationThread.js +21 -0
  109. package/runtime/arcane/entities/Document.js +10 -0
  110. package/runtime/arcane/entities/File.js +143 -0
  111. package/runtime/arcane/entities/Image.js +135 -0
  112. package/runtime/arcane/entities/IntentEnvelope.js +834 -0
  113. package/runtime/arcane/entities/Preference.js +83 -0
  114. package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
  115. package/runtime/arcane/entities/TerminalSession.js +46 -0
  116. package/runtime/arcane/entities/Theme.js +107 -0
  117. package/runtime/arcane/entities/User.js +1046 -0
  118. package/runtime/arcane/entities/Weather.js +23 -0
  119. package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
  120. package/runtime/arcane/img/arrow-left.png +0 -0
  121. package/runtime/arcane/img/arrow-right.png +0 -0
  122. package/runtime/arcane/img/doc.svg +5 -0
  123. package/runtime/arcane/img/folder.svg +4 -0
  124. package/runtime/arcane/img/image.svg +5 -0
  125. package/runtime/arcane/img/refresh.png +0 -0
  126. package/runtime/arcane/img/send.svg +9 -0
  127. package/runtime/arcane/img/trash.svg +5 -0
  128. package/runtime/arcane/img/upload.svg +5 -0
  129. package/runtime/arcane/modules/AI.js +2048 -0
  130. package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
  131. package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
  132. package/runtime/arcane/modules/AIResponseLength.js +42 -0
  133. package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
  134. package/runtime/arcane/modules/AnsiText.js +53 -0
  135. package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
  136. package/runtime/arcane/modules/AppDataScope.js +245 -0
  137. package/runtime/arcane/modules/AppearancePreferences.js +28 -0
  138. package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
  139. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
  140. package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
  141. package/runtime/arcane/modules/AsyncBoundary.js +161 -0
  142. package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
  143. package/runtime/arcane/modules/CalculatorEngine.js +20 -0
  144. package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
  145. package/runtime/arcane/modules/ChartLibrary.js +35 -0
  146. package/runtime/arcane/modules/ChatRecords.js +13 -0
  147. package/runtime/arcane/modules/CommunicationAppController.js +43 -0
  148. package/runtime/arcane/modules/CommunicationHub.js +16 -0
  149. package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
  150. package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
  151. package/runtime/arcane/modules/ComponentContracts.js +586 -0
  152. package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
  153. package/runtime/arcane/modules/ConversationActionItems.js +488 -0
  154. package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
  155. package/runtime/arcane/modules/ConversationTimebox.js +527 -0
  156. package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
  157. package/runtime/arcane/modules/DBLS.js +171 -0
  158. package/runtime/arcane/modules/DBOPFS.js +1154 -0
  159. package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
  160. package/runtime/arcane/modules/DataMaintenance.js +91 -0
  161. package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
  162. package/runtime/arcane/modules/DirectoryPicker.js +109 -0
  163. package/runtime/arcane/modules/DocumentNavigation.js +223 -0
  164. package/runtime/arcane/modules/Errors.js +1025 -0
  165. package/runtime/arcane/modules/GifEncoder.js +29 -0
  166. package/runtime/arcane/modules/HTMLImport.js +114 -0
  167. package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
  168. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
  169. package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
  170. package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
  171. package/runtime/arcane/modules/MD.js +111 -0
  172. package/runtime/arcane/modules/Mail.js +352 -0
  173. package/runtime/arcane/modules/MailTransport.mjs +180 -0
  174. package/runtime/arcane/modules/Marked.min.js +71 -0
  175. package/runtime/arcane/modules/MemoryRecords.js +44 -0
  176. package/runtime/arcane/modules/MessageAdvisory.js +38 -0
  177. package/runtime/arcane/modules/ModelDefinition.js +189 -0
  178. package/runtime/arcane/modules/Ollama.js +74 -0
  179. package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
  180. package/runtime/arcane/modules/OllamaSettings.js +24 -0
  181. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
  182. package/runtime/arcane/modules/PreferenceStore.js +109 -0
  183. package/runtime/arcane/modules/QRCode.min.js +1 -0
  184. package/runtime/arcane/modules/Questionnaire.js +61 -0
  185. package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
  186. package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
  187. package/runtime/arcane/modules/RecordReviewStore.js +94 -0
  188. package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
  189. package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
  190. package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
  191. package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
  192. package/runtime/arcane/modules/ScreenCapture.js +20 -0
  193. package/runtime/arcane/modules/SpeechPlayback.js +581 -0
  194. package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
  195. package/runtime/arcane/modules/SystemAppearance.js +20 -0
  196. package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
  197. package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
  198. package/runtime/arcane/modules/TerminalClient.js +52 -0
  199. package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
  200. package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
  201. package/runtime/arcane/modules/ThemeManager.js +131 -0
  202. package/runtime/arcane/modules/TimeGuard.js +149 -0
  203. package/runtime/arcane/modules/ToolCallRouter.js +83 -0
  204. package/runtime/arcane/modules/WaitForComponent.js +102 -0
  205. package/runtime/arcane/modules/YouTubeMedia.js +16 -0
  206. package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
  207. package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
  208. package/runtime/arcane/modules/uPlot.min.css +1 -0
  209. package/runtime/arcane/security/arcane-network-policy.json +6 -0
  210. package/runtime/strong-type/index.js +352 -0
  211. package/runtime/strong-type/licence +21 -0
  212. package/runtime/strong-type/package.json +45 -0
  213. package/schemas/arcane-app-bundle.schema.json +125 -0
  214. package/schemas/arcane-app.schema.json +329 -0
  215. package/schemas/arcane-lock.schema.json +86 -0
  216. package/schemas/arcane-package.schema.json +224 -0
  217. package/schemas/cli-event.schema.json +122 -0
  218. package/schemas/event-stack.schema.json +152 -0
  219. package/schemas/native-build-plan.schema.json +176 -0
  220. package/schemas/target-adapter.schema.json +117 -0
  221. package/src/app-descriptor.mjs +500 -0
  222. package/src/cli/main.mjs +561 -0
  223. package/src/constants.mjs +31 -0
  224. package/src/dev-server.mjs +718 -0
  225. package/src/doctor.mjs +315 -0
  226. package/src/dom-event-instrumentation.mjs +594 -0
  227. package/src/errors.mjs +75 -0
  228. package/src/event-manager.mjs +1342 -0
  229. package/src/event-queue.mjs +138 -0
  230. package/src/events.mjs +219 -0
  231. package/src/index.mjs +177 -0
  232. package/src/integrated-provider-loader.mjs +432 -0
  233. package/src/native-plan.mjs +698 -0
  234. package/src/native-provider-loader.mjs +1126 -0
  235. package/src/packager/core.mjs +2691 -0
  236. package/src/process.mjs +353 -0
  237. package/src/release-bundle.mjs +2523 -0
  238. package/src/repository.mjs +90 -0
  239. package/src/runtime.mjs +452 -0
  240. package/src/scaffold.mjs +380 -0
  241. package/src/targets/index.mjs +436 -0
  242. package/src/templates/assets/app-icon.png +0 -0
  243. package/src/templates/workspace-template.mjs +388 -0
  244. package/src/testing-loader.mjs +9 -0
  245. package/src/testing.mjs +427 -0
  246. package/src/toolchain.mjs +1335 -0
  247. package/src/update-check.mjs +307 -0
  248. package/src/workspace.mjs +449 -0
@@ -0,0 +1,255 @@
1
+ import {normalizeOllamaModelIdentifier} from './OllamaModelIdentifier.js';
2
+
3
+ const MAX_CORE_LOCAL_SPEECH_MODELS=8;
4
+
5
+ const ADMISSION_REASON_BY_CODE=Object.freeze({
6
+ MODEL_ADMISSION_CONTEXT_EXCEEDS_MODEL_LIMIT:'context exceeds model limit',
7
+ MODEL_ADMISSION_CONTEXT_UNAVAILABLE:'context metadata unavailable',
8
+ MODEL_ADMISSION_DEFINITION_INVALID:'model definition unavailable',
9
+ MODEL_ADMISSION_DEFINITION_UNAVAILABLE:'model definition unavailable',
10
+ MODEL_ADMISSION_KV_EVIDENCE_UNAVAILABLE:'KV-cache metadata unavailable',
11
+ MODEL_ADMISSION_MEMORY_INSUFFICIENT:'insufficient memory at this context',
12
+ MODEL_ADMISSION_METADATA_UNAVAILABLE:'model metadata unavailable',
13
+ MODEL_ADMISSION_RUNNING_MODELS_UNAVAILABLE:'loaded-model state unavailable',
14
+ MODEL_ADMISSION_SIZE_UNAVAILABLE:'model size unavailable',
15
+ MODEL_ADMISSION_STORAGE_INSUFFICIENT:'insufficient model storage',
16
+ MODEL_ADMISSION_STORAGE_UNAVAILABLE:'model storage unavailable',
17
+ MODEL_ADMISSION_SYSTEM_MEMORY_UNAVAILABLE:'system memory unavailable',
18
+ MODEL_DEFINITION_VERIFICATION_FAILED:'model definition needs repair',
19
+ MODEL_PREFLIGHT_FAILED:'registry preflight unavailable'
20
+ });
21
+
22
+ export const USER_MANAGED_LOOPBACK_PROVIDER_MODE='user-managed-loopback';
23
+
24
+ /**
25
+ * Identifies the bounded Android host response that delegates inference to a
26
+ * user-owned loopback Ollama process. This is provider discovery only: it does
27
+ * not claim that Arcane manages the service or any model lifecycle operation.
28
+ */
29
+ export function isUserManagedLoopbackLocalAIStatus(status){
30
+ return status?.schemaVersion===2
31
+ &&status?.providerMode===USER_MANAGED_LOOPBACK_PROVIDER_MODE;
32
+ }
33
+
34
+ function modelDescriptor(model){
35
+ const id=normalizeOllamaModelIdentifier(model?.id);
36
+ const name=normalizeOllamaModelIdentifier(model?.name);
37
+
38
+ if(!id||!name){
39
+ throw new TypeError('Arcane Core returned an invalid local-model identifier.');
40
+ }
41
+
42
+ return Object.freeze({
43
+ providerValue:'OLLAMA',
44
+ preferenceValue:id,
45
+ modelId:id,
46
+ label:name
47
+ });
48
+ }
49
+
50
+ function boundedParallelRequests(value,{allowZero=false}={}){
51
+ return Number.isSafeInteger(value)
52
+ &&(allowZero?value>=0:value>=1)
53
+ ?value
54
+ :null;
55
+ }
56
+
57
+ function admissionCode(compatibility){
58
+ const code=compatibility?.code;
59
+
60
+ return typeof code==='string'&&/^[A-Z][A-Z0-9_]{0,95}$/.test(code)
61
+ ?code
62
+ :null;
63
+ }
64
+
65
+ function unavailableReason({
66
+ activeParallelRequests,
67
+ code,
68
+ maxAllowedParallelRequests
69
+ }){
70
+ if(
71
+ activeParallelRequests!==null
72
+ &&maxAllowedParallelRequests!==null
73
+ &&activeParallelRequests>maxAllowedParallelRequests
74
+ ){
75
+ if(maxAllowedParallelRequests===0){
76
+ return 'insufficient memory at this context';
77
+ }
78
+
79
+ const noun=maxAllowedParallelRequests===1?'request':'requests';
80
+ return `active ${activeParallelRequests}; max ${maxAllowedParallelRequests} parallel ${noun}`;
81
+ }
82
+
83
+ return ADMISSION_REASON_BY_CODE[code]||'not currently available';
84
+ }
85
+
86
+ function admissionAwareModelDescriptor(model,{rejected=false,activeFallback=null}={}){
87
+ const id=normalizeOllamaModelIdentifier(model?.id);
88
+ const name=normalizeOllamaModelIdentifier(model?.name??model?.id);
89
+
90
+ if(!id||!name){
91
+ throw new TypeError('Arcane Core returned an invalid local-model identifier.');
92
+ }
93
+
94
+ const compatibility=model?.compatibility&&typeof model.compatibility==='object'
95
+ &&!Array.isArray(model.compatibility)
96
+ ?model.compatibility
97
+ :null;
98
+ const activeParallelRequests=boundedParallelRequests(
99
+ compatibility?.activeParallelRequests
100
+ )??activeFallback;
101
+ const maxAllowedParallelRequests=boundedParallelRequests(
102
+ compatibility?.maxAllowedParallelRequests,
103
+ {allowZero:true}
104
+ );
105
+ const activeParallelRequestsAllowed=
106
+ typeof compatibility?.activeParallelRequestsAllowed==='boolean'
107
+ ?compatibility.activeParallelRequestsAllowed
108
+ :null;
109
+ const repairRequired=compatibility?.creationRequired===true
110
+ &&compatibility?.baseModelInstalled===true;
111
+ const downloadRequired=compatibility?.pullRequired===true
112
+ &&compatibility?.baseModelInstalled!==true;
113
+ const code=admissionCode(compatibility);
114
+ const disabled=rejected
115
+ ||model?.runnable===false
116
+ ||activeParallelRequestsAllowed===false;
117
+ const unavailable=disabled
118
+ ?unavailableReason({
119
+ activeParallelRequests,
120
+ code,
121
+ maxAllowedParallelRequests
122
+ })
123
+ :null;
124
+ const reason=[
125
+ repairRequired?'repair required':null,
126
+ downloadRequired?'download required':null,
127
+ unavailable
128
+ ].filter(Boolean).join('; ')||null;
129
+ const status=rejected
130
+ ?'rejected'
131
+ :disabled
132
+ ?'not-runnable'
133
+ :repairRequired
134
+ ?'repair-required'
135
+ :downloadRequired
136
+ ?'download-required'
137
+ :'available';
138
+
139
+ return Object.freeze({
140
+ providerValue:'OLLAMA',
141
+ preferenceValue:id,
142
+ modelId:id,
143
+ label:reason?`${name} (${reason})`:name,
144
+ disabled,
145
+ status,
146
+ reason,
147
+ repairRequired,
148
+ downloadRequired,
149
+ admissionCode:code,
150
+ activeParallelRequests,
151
+ maxAllowedParallelRequests,
152
+ activeParallelRequestsAllowed
153
+ });
154
+ }
155
+
156
+ /**
157
+ * Converts the authoritative Core catalog to UI-safe descriptors without
158
+ * filtering, sorting, or interpreting admission metadata in the renderer.
159
+ */
160
+ export function getCoreLocalModelCatalog(status){
161
+ const models=status?.models?.ollama;
162
+
163
+ if(!Array.isArray(models)){
164
+ return Object.freeze([]);
165
+ }
166
+ return Object.freeze(models.map(modelDescriptor));
167
+ }
168
+
169
+ /**
170
+ * Preserves Core admission failures for a bounded model-picker inventory.
171
+ * Failure text is projected from stable codes instead of rendering native
172
+ * diagnostic messages in the application UI.
173
+ */
174
+ export function getCoreLocalModelCatalogWithAdmissionFailures(status){
175
+ const admitted=Array.isArray(status?.models?.ollama)
176
+ ?status.models.ollama
177
+ :[];
178
+ const rejected=Array.isArray(status?.admission?.rejected)
179
+ ?status.admission.rejected
180
+ :[];
181
+
182
+ const activeFallback=boundedParallelRequests(
183
+ status?.ollama?.activeParallelRequests
184
+ );
185
+ const descriptors=[
186
+ ...admitted.map(model=>admissionAwareModelDescriptor(
187
+ model,
188
+ {activeFallback}
189
+ )),
190
+ ...rejected.map(model=>admissionAwareModelDescriptor(
191
+ model,
192
+ {rejected:true,activeFallback}
193
+ ))
194
+ ];
195
+ const identifiers=new Set();
196
+
197
+ for(const descriptor of descriptors){
198
+ const canonical=descriptor.modelId.toLowerCase();
199
+
200
+ if(identifiers.has(canonical)){
201
+ throw new TypeError('Arcane Core returned a duplicate local-model identifier.');
202
+ }
203
+ identifiers.add(canonical);
204
+ }
205
+
206
+ return Object.freeze(descriptors);
207
+ }
208
+
209
+ function hasAvailableSpeechRole(models,role){
210
+ if(!Array.isArray(models)){
211
+ return false;
212
+ }
213
+ if(models.length>MAX_CORE_LOCAL_SPEECH_MODELS){
214
+ throw new RangeError('Arcane Core returned too many local speech models.');
215
+ }
216
+
217
+ let available=false;
218
+ for(const model of models){
219
+ if(
220
+ !model
221
+ ||typeof model!=='object'
222
+ ||Array.isArray(model)
223
+ ||typeof model.id!=='string'
224
+ ||!model.id
225
+ ||model.id.length>128
226
+ ||typeof model.name!=='string'
227
+ ||!model.name
228
+ ||model.name.length>128
229
+ ||model.provider!=='speech'
230
+ ||!Array.isArray(model.roles)
231
+ ||model.roles.length<1
232
+ ||model.roles.length>2
233
+ ||!model.roles.every(candidate=>candidate==='stt'||candidate==='tts')
234
+ ){
235
+ throw new TypeError('Arcane Core returned an invalid local speech model.');
236
+ }
237
+ if(model.available===true&&model.roles.includes(role)){
238
+ available=true;
239
+ }
240
+ }
241
+ return available;
242
+ }
243
+
244
+ /**
245
+ * Projects Core's role-specific speech health and catalog into the two local
246
+ * profile choices without granting the renderer any service endpoint access.
247
+ */
248
+ export function getCoreLocalSpeechAvailability(status){
249
+ return Object.freeze({
250
+ stt:status?.speech?.transcriptionAvailable===true
251
+ &&hasAvailableSpeechRole(status?.models?.transcription,'stt'),
252
+ tts:status?.speech?.synthesisAvailable===true
253
+ &&hasAvailableSpeechRole(status?.models?.speech,'tts')
254
+ });
255
+ }
@@ -0,0 +1,171 @@
1
+ import {
2
+ APP_LOCAL_STORAGE_PREFIX,
3
+ resolveBrowserApplicationId
4
+ } from './AppDataScope.js';
5
+
6
+ class DBLS {
7
+ constructor({
8
+ applicationId=null,
9
+ documentObject=globalThis.document,
10
+ storage=globalThis.localStorage
11
+ }={}) {
12
+ if(window.dbls){
13
+ return window.dbls;
14
+ }
15
+
16
+ if(!storage
17
+ ||typeof storage.getItem!=='function'
18
+ ||typeof storage.setItem!=='function'){
19
+ const error=new Error('Local storage is unavailable in this browser.');
20
+ error.code='APP_DATA_STORAGE_UNAVAILABLE';
21
+ throw error;
22
+ }
23
+
24
+ this.applicationId=resolveBrowserApplicationId({
25
+ applicationId,
26
+ documentObject
27
+ });
28
+ this.storage=storage;
29
+ this.storagePrefix=`${APP_LOCAL_STORAGE_PREFIX}${this.applicationId}:`;
30
+ }
31
+
32
+ ready=false;
33
+
34
+ storageKey(key='') {
35
+ return `${this.storagePrefix}${String(key)}`;
36
+ }
37
+
38
+ logicalKeys() {
39
+ const keys=[];
40
+ for(let index=0;index<this.storage.length;index++){
41
+ const key=this.storage.key(index);
42
+ if(key?.startsWith(this.storagePrefix)){
43
+ keys.push(key.slice(this.storagePrefix.length));
44
+ }
45
+ }
46
+ return keys;
47
+ }
48
+
49
+ // Set an item
50
+ set(key='', value) {
51
+ if(typeof value !== 'string' && typeof value !== 'number'){
52
+ value=JSON.stringify(value);
53
+ }
54
+ this.storage.setItem(this.storageKey(key), value);
55
+ }
56
+
57
+ // Add new functionality: Set multiple items
58
+ setMany(items) {
59
+ const keys = Object.keys(items);
60
+ for (let i = 0; i < keys.length; i++) {
61
+ this.set(keys[i],items[keys[i]]);
62
+ }
63
+ }
64
+
65
+ // Get an item
66
+ get(key) {
67
+ const item = this.storage.getItem(this.storageKey(key));
68
+ try{
69
+ return JSON.parse(item);
70
+ }catch(err){
71
+ return item;
72
+ }
73
+ }
74
+
75
+ // Add new functionality: Get many items
76
+ getMany(keys=[]) {
77
+ const items={};
78
+ for (let i = 0; i < keys.length; i++) {
79
+ const item=this.storage.getItem(this.storageKey(keys[i]));
80
+ try{
81
+ items[keys[i]]=JSON.parse(item);
82
+ }catch(err){
83
+ items[keys[i]]=item;
84
+ }
85
+ }
86
+
87
+ return items;
88
+ }
89
+
90
+ // Add new functionality: Get many items whose keys include a subString
91
+ filterKeyIncludes(subString='') {
92
+ const items={};
93
+ const keys=this.logicalKeys();
94
+
95
+ for (let i = 0; i < keys.length; i++) {
96
+ //console.log(keys[i],subString);
97
+ if(!keys[i].includes(subString)){
98
+ continue;
99
+ }
100
+ const item=this.storage.getItem(this.storageKey(keys[i]));
101
+ try{
102
+ items[keys[i]]=JSON.parse(item);
103
+ }catch(err){
104
+ items[keys[i]]=item;
105
+ }
106
+ }
107
+
108
+ return items;
109
+ }
110
+
111
+ // Add new functionality: Get all items
112
+ getAll() {
113
+ const items = {};
114
+ const keys=this.logicalKeys();
115
+ for (let i = 0; i < keys.length; i++) {
116
+ const key=keys[i];
117
+ items[key] = this.storage.getItem(this.storageKey(key));
118
+ }
119
+ return items;
120
+ }
121
+
122
+ // Remove an item
123
+ delete(key) {
124
+ this.storage.removeItem(this.storageKey(key));
125
+ }
126
+
127
+ // Add new functionality: Remove multiple items
128
+ deleteMany(keys) {
129
+ for (let i = 0; i < keys.length; i++) {
130
+ this.storage.removeItem(this.storageKey(keys[i]));
131
+ }
132
+ }
133
+
134
+ // Clear all items
135
+ clear() {
136
+ const keys=this.logicalKeys();
137
+ for(let index=0;index<keys.length;index++){
138
+ this.storage.removeItem(this.storageKey(keys[index]));
139
+ }
140
+ }
141
+
142
+ // Get all keys
143
+ getAllKeys() {
144
+ return this.logicalKeys();
145
+ }
146
+
147
+ // Check if a key exists
148
+ hasKey(key) {
149
+ return this.storage.getItem(this.storageKey(key)) !== null;
150
+ }
151
+
152
+ // Add new functionality: Get item count
153
+ count() {
154
+ return this.logicalKeys().length;
155
+ }
156
+ }
157
+
158
+ if(typeof window.dbls?.get !== "function"){
159
+ window.dbls=new DBLS();
160
+ window.dbls.ready=true;
161
+
162
+ const dblsReady=new CustomEvent(
163
+ 'dbls-ready', {
164
+ detail: { dbls: window.dbls }
165
+ }
166
+ );
167
+
168
+ window.dispatchEvent(dblsReady);
169
+ }
170
+
171
+ export default DBLS;