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,13 @@
1
+ <link rel="stylesheet" href="./arcane/css/primitives.css?v=1">
2
+ <style>
3
+ :host{display:block;min-width:0;height:100%}.shell{display:grid;grid-template-rows:auto 1fr auto;height:100%;min-height:32rem}.heading{align-items:center;display:flex;gap:.75rem;justify-content:space-between;padding:1rem;border-bottom:1px solid var(--border-color,#ccd4df)}.heading h2,.heading p{margin:0}.heading p{color:var(--muted-text-color,#607080)}.badge{border:1px solid var(--border-color,#ccd4df);border-radius:999px;padding:.25rem .55rem;font-size:.72rem;text-transform:uppercase}.messages{display:flex;flex-direction:column;gap:.8rem;overflow:auto;padding:1rem}.message{align-self:flex-start;max-width:min(78%,42rem);padding:.75rem .9rem;border:1px solid var(--border-color,#ccd4df);border-radius:.9rem;background:var(--modal-background,#fff)}.message.outbound{align-self:flex-end;color:var(--button-text-color,#fff);background:var(--primary-color,#172238)}.message p{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}.message footer{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.4rem;font-size:.7rem;opacity:.72}.advisory{display:grid;gap:.45rem;margin-top:.7rem;padding:.7rem;border:2px solid var(--border-color,#ccd4df);border-radius:.65rem;background:var(--background-color,#f5f7fa);color:var(--text-color,#172238)}.advisory[data-level="critical"],.advisory[data-level="high"]{border-color:rgb(174,48,52)}.advisory[data-level="caution"]{border-color:rgb(190,120,34)}.advisory strong,.advisory p{margin:0}.advisory ul{margin:.1rem 0;padding-left:1.2rem}.advisory button{justify-self:start}.composer{display:grid;gap:.6rem;padding:1rem;border-top:1px solid var(--border-color,#ccd4df)}textarea{min-height:5rem;resize:vertical}.composer-row{align-items:center;display:flex;gap:.75rem;justify-content:space-between}.status{color:var(--muted-text-color,#607080);margin:0}.blank{display:grid;place-items:center;height:100%;padding:2rem;text-align:center}.blank p{color:var(--muted-text-color,#607080)}
4
+ </style>
5
+ <section class="shell"><header id="heading" class="heading" hidden><div><h2 id="title"></h2><p id="participants"></p></div><span id="badge" class="badge"></span></header><div id="messages" class="messages"><div class="blank"><div><strong>Select a conversation</strong><p>Choose a thread from the inbox, or connect a service in settings.</p></div></div></div><form id="composer" class="composer" hidden><label class="arcane-field"><span class="sr-only">Reply</span><textarea id="body" required placeholder="Write a reply"></textarea></label><div class="composer-row"><p id="status" class="status" role="status" aria-live="polite"></p><button class="arcane-button" type="submit">Send</button></div></form></section>
6
+ <script type="module">
7
+ const host=this,root=host.shadowRoot,heading=root.querySelector('#heading'),messages=root.querySelector('#messages'),composer=root.querySelector('#composer'),body=root.querySelector('#body'),status=root.querySelector('#status');let thread=null,advisories={};
8
+ host.setConversation=(next,items=[],options={})=>{thread=next||null;advisories=options?.advisories instanceof Map?options.advisories:new Map();heading.hidden=!thread;composer.hidden=!thread;if(!thread){messages.innerHTML='<div class="blank"><div><strong>Select a conversation</strong><p>Choose a thread from the inbox, or connect a service in settings.</p></div></div>';return}root.querySelector('#title').textContent=thread.title;root.querySelector('#participants').textContent=(thread.participants||[]).join(', ');root.querySelector('#badge').textContent=`${thread.channel} · ${thread.providerId}`;render(items)};
9
+ host.setBusy=value=>{for(const control of composer.elements) control.disabled=Boolean(value)};host.setStatus=value=>status.textContent=String(value||'');
10
+ composer.addEventListener('submit',event=>{event.preventDefault();const value=body.value.trim();if(!value)return;host.dispatchEvent(new CustomEvent('communication-send',{bubbles:true,composed:true,detail:{thread,body:value}}))});
11
+ function render(items){messages.replaceChildren(...Array.from(items||[]).map(item=>{const article=document.createElement('article'),text=document.createElement('p'),footer=document.createElement('footer'),time=document.createElement('time'),state=document.createElement('span');article.className=`message ${item.direction}`;text.textContent=item.body||item.subject||'';time.dateTime=item.timestamp;time.textContent=new Intl.DateTimeFormat(undefined,{dateStyle:'short',timeStyle:'short'}).format(new Date(item.timestamp));state.textContent=item.status;footer.append(time,state);article.append(text,footer);const advisory=advisories.get(item);if(advisory){const note=document.createElement('aside'),title=document.createElement('strong'),summary=document.createElement('p');note.className='advisory';note.dataset.level=String(advisory.level||'caution');note.setAttribute('role','note');title.textContent=String(advisory.title||'Content advisory');summary.textContent=String(advisory.summary||'Review this message carefully.');note.append(title,summary);const signals=Array.from(advisory.signals||[]).map(String).filter(Boolean).slice(0,8);if(signals.length){const list=document.createElement('ul');for(const signal of signals){const entry=document.createElement('li');entry.textContent=signal;list.append(entry)}note.append(list)}if(advisory.actionLabel){const action=document.createElement('button');action.type='button';action.className='arcane-button arcane-button--tertiary';action.textContent=String(advisory.actionLabel);action.addEventListener('click',()=>host.dispatchEvent(new CustomEvent('communication-advisory-action',{bubbles:true,composed:true,detail:{thread,message:item,advisory}})));note.append(action)}article.append(note)}return article}));messages.scrollTop=messages.scrollHeight;}
12
+ host.clearComposer=()=>{body.value='';body.focus()};host.ready=true;host.dispatchEvent(new CustomEvent('conversation-view-ready',{bubbles:true,composed:true}));
13
+ </script>
@@ -0,0 +1,341 @@
1
+ <link rel="stylesheet" href="./arcane/css/layout.css?v=3">
2
+ <link rel="stylesheet" href="./arcane/css/dashboard-config.css?v=2">
3
+ <style>
4
+ :host{
5
+ display:block;
6
+ }
7
+ </style>
8
+
9
+ <button id="openConfig" type="button" aria-haspopup="dialog" disabled></button>
10
+ <html-import id="configModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
11
+
12
+ <script type="module">
13
+ const host=this;
14
+ const componentURL=new URL(
15
+ host.getAttribute('href')||'./arcane/components/dashboard-config.html',
16
+ document.baseURI
17
+ );
18
+ const moduleURL=name=>new URL(`../modules/${name}`,componentURL).href;
19
+ const {default:waitForComponent}=await import(moduleURL('WaitForComponent.js'));
20
+ const {
21
+ effectiveDashboardVisibility,
22
+ normalizeDashboardDefinitions,
23
+ normalizeDashboardOptions,
24
+ normalizeDashboardVisibility
25
+ }=await import(moduleURL('ComponentContracts.js'));
26
+ const openButton=host.shadowRoot.querySelector('#openConfig');
27
+ const configModal=host.shadowRoot.querySelector('#configModal');
28
+
29
+ let definitions=[];
30
+ let visibility={};
31
+ let content=null;
32
+ let labels=normalizeDashboardOptions(optionsFromDataset()).labels;
33
+
34
+ host.close=closeConfig;
35
+ host.configure=configure;
36
+ host.getChartOptions=getChartOptions;
37
+ host.getEffectiveVisibility=getEffectiveVisibility;
38
+ host.open=openConfig;
39
+ host.setDefinitions=setDefinitions;
40
+ host.setVisibility=setVisibility;
41
+
42
+ Object.defineProperties(
43
+ host,
44
+ {
45
+ definitions:{get:getDefinitions,set:setDefinitions},
46
+ effectiveVisibility:{get:getEffectiveVisibility},
47
+ options:{get:getOptions,set:configure},
48
+ visibility:{get:getVisibility,set:setVisibility}
49
+ }
50
+ );
51
+
52
+ openButton.addEventListener(
53
+ 'click',
54
+ ()=>openConfig().catch(
55
+ error=>console.error('Unable to configure dashboard:',error)
56
+ )
57
+ );
58
+ configModal.addEventListener(
59
+ 'modal-closed',
60
+ ()=>host.dispatchEvent(
61
+ new CustomEvent(
62
+ 'dashboard-config-closed',
63
+ {
64
+ bubbles:true,
65
+ composed:true,
66
+ detail:{
67
+ effectiveVisibility:getEffectiveVisibility(),
68
+ visibility:getVisibility()
69
+ }
70
+ }
71
+ )
72
+ )
73
+ );
74
+
75
+ function optionsFromDataset(){
76
+ const dataset=host.dataset||{};
77
+ const options={};
78
+ for(const field of ['description','emptyLabel','heading','triggerLabel']){
79
+ if(dataset[field]!==undefined){
80
+ options[field]=dataset[field];
81
+ }
82
+ }
83
+ return options;
84
+ }
85
+
86
+ function configure(input={}){
87
+ const normalized=normalizeDashboardOptions(
88
+ input,
89
+ {definitions,labels,visibility}
90
+ );
91
+ definitions=normalized.definitions;
92
+ visibility=normalized.visibility;
93
+ labels=normalized.labels;
94
+ renderTrigger();
95
+ refreshContent();
96
+ return getOptions();
97
+ }
98
+
99
+ function setDefinitions(values=[]){
100
+ definitions=normalizeDashboardDefinitions(values);
101
+ renderTrigger();
102
+ refreshContent();
103
+ return getDefinitions();
104
+ }
105
+
106
+ function setVisibility(values={}){
107
+ visibility=normalizeDashboardVisibility(values);
108
+ syncOptions();
109
+ return getVisibility();
110
+ }
111
+
112
+ function getDefinitions(){
113
+ return definitions.map(cloneDefinition);
114
+ }
115
+
116
+ function getVisibility(){
117
+ return {...visibility};
118
+ }
119
+
120
+ function getEffectiveVisibility(){
121
+ return effectiveDashboardVisibility(definitions,visibility);
122
+ }
123
+
124
+ function getChartOptions(key=''){
125
+ const definition=definitions.find(candidate=>candidate.key===key);
126
+ if(!definition){
127
+ return null;
128
+ }
129
+ return {
130
+ ...definition.chartOptions,
131
+ labels:{...definition.chartOptions.labels},
132
+ chartOptions:typeof definition.chartOptions.chartOptions==='object'
133
+ &&definition.chartOptions.chartOptions!==null
134
+ ?{...definition.chartOptions.chartOptions}
135
+ :definition.chartOptions.chartOptions
136
+ };
137
+ }
138
+
139
+ function isVisible(definition={}){
140
+ return typeof visibility[definition.key]==='boolean'
141
+ ?visibility[definition.key]
142
+ :definition.defaultVisible;
143
+ }
144
+
145
+ async function openConfig(){
146
+ if(!definitions.length){
147
+ return false;
148
+ }
149
+ const modal=await waitForComponent(
150
+ configModal,
151
+ {
152
+ methods:['populate','open'],
153
+ property:'ready',
154
+ event:'modal-ready'
155
+ }
156
+ );
157
+ if(!content){
158
+ content=createContent();
159
+ await modal.populate(content,false);
160
+ }
161
+ refreshContent();
162
+ modal.open();
163
+ host.dispatchEvent(
164
+ new CustomEvent(
165
+ 'dashboard-config-opened',
166
+ {
167
+ bubbles:true,
168
+ composed:true,
169
+ detail:{
170
+ effectiveVisibility:getEffectiveVisibility(),
171
+ visibility:getVisibility()
172
+ }
173
+ }
174
+ )
175
+ );
176
+ return true;
177
+ }
178
+
179
+ async function closeConfig(){
180
+ const modal=await waitForComponent(
181
+ configModal,
182
+ {
183
+ methods:['close'],
184
+ property:'ready',
185
+ event:'modal-ready'
186
+ }
187
+ );
188
+ modal.close();
189
+ return true;
190
+ }
191
+
192
+ function createContent(){
193
+ const section=document.createElement('section');
194
+ const styles=document.createElement('link');
195
+ const heading=document.createElement('h1');
196
+ const message=document.createElement('p');
197
+ const empty=document.createElement('p');
198
+ const items=document.createElement('section');
199
+
200
+ styles.rel='stylesheet';
201
+ styles.href='./arcane/css/dashboard-config.css?v=2';
202
+ heading.dataset.dashboardConfigHeading='';
203
+ message.dataset.dashboardConfigDescription='';
204
+ empty.className='dashboard-config-empty';
205
+ empty.dataset.dashboardConfigEmpty='';
206
+ items.className='chart-options';
207
+ items.dataset.dashboardConfigOptions='';
208
+ items.addEventListener('change',changeVisibility);
209
+ section.append(styles,heading,message,empty,items);
210
+ return section;
211
+ }
212
+
213
+ function refreshContent(){
214
+ if(!content){
215
+ return;
216
+ }
217
+ const heading=content.querySelector('[data-dashboard-config-heading]');
218
+ const message=content.querySelector('[data-dashboard-config-description]');
219
+ const empty=content.querySelector('[data-dashboard-config-empty]');
220
+ const items=content.querySelector('[data-dashboard-config-options]');
221
+ const fragment=document.createDocumentFragment();
222
+ let group=null;
223
+
224
+ heading.innerText=labels.heading;
225
+ message.innerText=labels.description;
226
+ empty.innerText=labels.empty;
227
+ empty.hidden=definitions.length>0;
228
+
229
+ for(const definition of definitions){
230
+ if(definition.group&&definition.group!==group){
231
+ group=definition.group;
232
+ const groupHeading=document.createElement('h2');
233
+ groupHeading.className='chart-option-group';
234
+ groupHeading.innerText=group;
235
+ fragment.append(groupHeading);
236
+ }
237
+ const label=document.createElement('label');
238
+ const checkbox=document.createElement('input');
239
+ const title=document.createElement('h3');
240
+ const description=document.createElement('p');
241
+
242
+ label.className='chart-option';
243
+ label.classList.toggle('disabled',definition.disabled);
244
+ checkbox.type='checkbox';
245
+ checkbox.dataset.chartKey=definition.key;
246
+ checkbox.checked=isVisible(definition);
247
+ checkbox.disabled=definition.disabled;
248
+ title.innerText=definition.title;
249
+ description.innerText=definition.description;
250
+ description.hidden=!definition.description;
251
+ label.append(checkbox,title,description);
252
+ fragment.append(label);
253
+ }
254
+ items.replaceChildren(fragment);
255
+ }
256
+
257
+ function syncOptions(){
258
+ if(!content){
259
+ return;
260
+ }
261
+ const byKey=new Map(definitions.map(definition=>[definition.key,definition]));
262
+ content.querySelectorAll('[data-chart-key]').forEach(
263
+ checkbox=>{
264
+ const definition=byKey.get(checkbox.dataset.chartKey);
265
+ checkbox.checked=definition?isVisible(definition):false;
266
+ checkbox.disabled=!definition||definition.disabled;
267
+ }
268
+ );
269
+ }
270
+
271
+ function changeVisibility(event){
272
+ const checkbox=event.target.closest?.('[data-chart-key]');
273
+ const definition=definitions.find(
274
+ candidate=>candidate.key===checkbox?.dataset.chartKey
275
+ );
276
+ if(!checkbox||!definition||definition.disabled){
277
+ return;
278
+ }
279
+
280
+ const previous=isVisible(definition);
281
+ const next={...visibility,[definition.key]:checkbox.checked};
282
+ const effective=effectiveDashboardVisibility(definitions,next);
283
+ const changeEvent=new CustomEvent(
284
+ 'dashboard-config-change',
285
+ {
286
+ bubbles:true,
287
+ cancelable:true,
288
+ composed:true,
289
+ detail:{
290
+ definition:cloneDefinition(definition),
291
+ effectiveVisibility:effective,
292
+ key:definition.key,
293
+ visibility:{...next},
294
+ visible:checkbox.checked
295
+ }
296
+ }
297
+ );
298
+ if(!host.dispatchEvent(changeEvent)){
299
+ checkbox.checked=previous;
300
+ return;
301
+ }
302
+ visibility=next;
303
+ syncOptions();
304
+ }
305
+
306
+ function renderTrigger(){
307
+ openButton.innerText=labels.trigger;
308
+ openButton.disabled=definitions.length===0;
309
+ }
310
+
311
+ function cloneDefinition(definition){
312
+ return {
313
+ ...definition,
314
+ chartOptions:{
315
+ ...definition.chartOptions,
316
+ labels:{...definition.chartOptions.labels},
317
+ chartOptions:typeof definition.chartOptions.chartOptions==='object'
318
+ &&definition.chartOptions.chartOptions!==null
319
+ ?{...definition.chartOptions.chartOptions}
320
+ :definition.chartOptions.chartOptions
321
+ }
322
+ };
323
+ }
324
+
325
+ function getOptions(){
326
+ return {
327
+ definitions:getDefinitions(),
328
+ labels:{...labels},
329
+ visibility:getVisibility()
330
+ };
331
+ }
332
+
333
+ renderTrigger();
334
+ host.ready=true;
335
+ host.dispatchEvent(
336
+ new CustomEvent(
337
+ 'dashboard-config-ready',
338
+ {bubbles:true,composed:true}
339
+ )
340
+ );
341
+ </script>
@@ -0,0 +1,112 @@
1
+ <link rel="stylesheet" href="./arcane/css/layout.css?v=3">
2
+ <style>
3
+ :host{
4
+ display:block;
5
+ }
6
+
7
+ button{
8
+ margin:0;
9
+ }
10
+ </style>
11
+
12
+ <button id="openMaintenance" type="button" aria-haspopup="dialog">Maintenance</button>
13
+ <html-import id="maintenanceModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
14
+
15
+ <script type="module">
16
+ const host=this;
17
+ const openButton=host.shadowRoot.querySelector('#openMaintenance');
18
+ const maintenanceModal=host.shadowRoot.querySelector('#maintenanceModal');
19
+ const {default:waitForComponent}=await import('../modules/WaitForComponent.js');
20
+ const {clearEmptyChatsAndMemories}=await import('../modules/DataMaintenance.js?v=3');
21
+
22
+ let content=null;
23
+
24
+ host.open=openMaintenance;
25
+
26
+ openButton.addEventListener(
27
+ 'click',
28
+ ()=>openMaintenance().catch(
29
+ error=>console.error('Unable to open maintenance:',error)
30
+ )
31
+ );
32
+
33
+ async function openMaintenance(){
34
+ const modal=await waitForComponent(
35
+ maintenanceModal,
36
+ {
37
+ methods:['populate','open'],
38
+ property:'ready',
39
+ event:'modal-ready'
40
+ }
41
+ );
42
+
43
+ if(!content){
44
+ content=createContent();
45
+ await modal.populate(content,false);
46
+ }
47
+
48
+ modal.open();
49
+ }
50
+
51
+ function createContent(){
52
+ const section=document.createElement('section');
53
+ const heading=document.createElement('h1');
54
+ const message=document.createElement('p');
55
+ const clearButton=document.createElement('button');
56
+ const status=document.createElement('p');
57
+
58
+ heading.innerText='Data Maintenance';
59
+ message.innerText='Remove chat logs with no user entries, their associated memories, and memory records with no content.';
60
+ clearButton.type='button';
61
+ clearButton.innerText='Clear Empty Chats & Memories';
62
+ status.setAttribute('aria-live','polite');
63
+
64
+ clearButton.addEventListener(
65
+ 'click',
66
+ async function clearChats(){
67
+ clearButton.disabled=true;
68
+ status.innerText='Checking chat logs...';
69
+
70
+ try{
71
+ const result=await clearEmptyChatsAndMemories();
72
+
73
+ if(result.deletedChats||result.deletedMemories){
74
+ status.innerText=`Deleted ${result.deletedChats} empty ${result.deletedChats===1?'chat':'chats'} and ${result.deletedMemories} empty or associated ${result.deletedMemories===1?'memory':'memories'}.`;
75
+ }else{
76
+ status.innerText='No empty chats or memories were found.';
77
+ }
78
+
79
+ if(result.failed){
80
+ status.innerText+=` ${result.failed} could not be deleted.`;
81
+ }
82
+
83
+ host.dispatchEvent(
84
+ new CustomEvent(
85
+ 'data-maintenance-complete',
86
+ {detail:result}
87
+ )
88
+ );
89
+ }catch(error){
90
+ status.innerText='Unable to complete data maintenance.';
91
+ console.error('Unable to clear empty chats and memories:',error);
92
+ }finally{
93
+ clearButton.disabled=false;
94
+ }
95
+ }
96
+ );
97
+
98
+ section.append(
99
+ heading,
100
+ message,
101
+ clearButton,
102
+ status
103
+ );
104
+
105
+ return section;
106
+ }
107
+
108
+ host.ready=true;
109
+ host.dispatchEvent(
110
+ new CustomEvent('data-maintenance-ready')
111
+ );
112
+ </script>
@@ -0,0 +1,92 @@
1
+ <link rel="stylesheet" href="./arcane/css/layout.css?v=3">
2
+ <style>
3
+ :host{
4
+ display:flex;
5
+ justify-content:flex-end;
6
+ }
7
+
8
+ button{
9
+ margin:0;
10
+ }
11
+ </style>
12
+
13
+ <button id="openData" type="button" aria-haspopup="dialog"></button>
14
+ <html-import id="dataModal" class="modal" href="./arcane/components/modal.html?v=13"></html-import>
15
+
16
+ <script type="module">
17
+ const host=this;
18
+ const openButton=host.shadowRoot.querySelector('#openData');
19
+ const dataModal=host.shadowRoot.querySelector('#dataModal');
20
+ const {default:waitForComponent}=await import('../modules/WaitForComponent.js');
21
+
22
+ let content=null;
23
+ let fileManager=null;
24
+
25
+ host.beforeOpen=typeof host.beforeOpen==='function'
26
+ ?host.beforeOpen
27
+ :async function beforeOpen(){};
28
+ host.open=openData;
29
+
30
+ openButton.innerText=host.dataset.button||'View Data';
31
+ openButton.addEventListener(
32
+ 'click',
33
+ ()=>openData().catch(
34
+ error=>console.error('Unable to open data view:',error)
35
+ )
36
+ );
37
+
38
+ async function openData(){
39
+ await host.beforeOpen();
40
+
41
+ const reload=Boolean(content);
42
+
43
+ const modal=await waitForComponent(
44
+ dataModal,
45
+ {
46
+ methods:['populate','open'],
47
+ property:'ready',
48
+ event:'modal-ready'
49
+ }
50
+ );
51
+
52
+ if(!content){
53
+ content=document.createElement('section');
54
+ fileManager=document.createElement('html-import');
55
+
56
+ const heading=document.createElement('h1');
57
+
58
+ heading.innerText=host.dataset.title||'Data';
59
+ fileManager.className='file-manager';
60
+ fileManager.previewTransform=host.previewTransform;
61
+ fileManager.dataset.dirs=host.dataset.dirs||'';
62
+ fileManager.dataset.layout=host.dataset.layout||'files';
63
+ fileManager.setAttribute(
64
+ 'href',
65
+ './arcane/components/file-manager.html?v=18'
66
+ );
67
+
68
+ content.append(heading,fileManager);
69
+ await modal.populate(content,false);
70
+ }
71
+
72
+ const manager=await waitForComponent(
73
+ fileManager,
74
+ {
75
+ methods:['loadAll'],
76
+ property:'ready',
77
+ event:'file-manager-ready'
78
+ }
79
+ );
80
+
81
+ if(reload){
82
+ await manager.loadAll();
83
+ }
84
+
85
+ modal.open();
86
+ }
87
+
88
+ host.ready=true;
89
+ host.dispatchEvent(
90
+ new CustomEvent('data-view-ready')
91
+ );
92
+ </script>