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.
- package/CHANGELOG.md +154 -0
- package/COMMERCIAL-LICENSE.md +13 -0
- package/LICENSE +661 -0
- package/NOTICE +70 -0
- package/README.md +448 -0
- package/bin/arcane-test.mjs +741 -0
- package/bin/arcane.mjs +5 -0
- package/docs/architecture.md +234 -0
- package/docs/compatibility.md +36 -0
- package/docs/event-manager.md +166 -0
- package/docs/platform-targets.md +108 -0
- package/docs/publishing.md +203 -0
- package/docs/reference/README.md +117 -0
- package/docs/reference/arcane-ollama.md +288 -0
- package/docs/reference/availability-and-normalization.md +123 -0
- package/docs/reference/behavioral-testing.md +86 -0
- package/docs/reference/cli.md +569 -0
- package/docs/reference/core/README.md +62 -0
- package/docs/reference/core/arcane-ai-contracts.md +873 -0
- package/docs/reference/core/arcane-api.md +601 -0
- package/docs/reference/core/arcane-entities.md +65 -0
- package/docs/reference/core/arcane-events.md +134 -0
- package/docs/reference/core/ollama-module.md +181 -0
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
- package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
- package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
- package/docs/reference/event-manager.md +957 -0
- package/docs/reference/inventory/package-api.json +2632 -0
- package/docs/reference/inventory/runtime-components.json +934 -0
- package/docs/reference/inventory/runtime-entities.json +26 -0
- package/docs/reference/inventory/runtime-modules.json +1249 -0
- package/docs/reference/protocols.md +242 -0
- package/docs/reference/runtime-components.md +1098 -0
- package/docs/reference/runtime-entities.md +303 -0
- package/docs/reference/runtime-modules.md +2010 -0
- package/docs/reference/sdk-api.md +4901 -0
- package/docs/roadmap.md +79 -0
- package/docs/work-amplification.md +124 -0
- package/node_modules/event-pubsub/CHANGELOG.md +55 -0
- package/node_modules/event-pubsub/MIGRATION.md +70 -0
- package/node_modules/event-pubsub/README.md +363 -0
- package/node_modules/event-pubsub/SECURITY.md +37 -0
- package/node_modules/event-pubsub/index.js +141 -0
- package/node_modules/event-pubsub/licence +21 -0
- package/node_modules/event-pubsub/package.json +59 -0
- package/node_modules/strong-type/README.md +408 -0
- package/node_modules/strong-type/assets/strong-type-header.png +0 -0
- package/node_modules/strong-type/index.js +1151 -0
- package/node_modules/strong-type/licence +21 -0
- package/node_modules/strong-type/node.js +125 -0
- package/node_modules/strong-type/package.json +61 -0
- package/package.json +95 -0
- package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
- package/runtime/arcane/components/app-bar.html +468 -0
- package/runtime/arcane/components/assistant-panel.html +715 -0
- package/runtime/arcane/components/calculator.html +8 -0
- package/runtime/arcane/components/chart.html +655 -0
- package/runtime/arcane/components/chat.html +1225 -0
- package/runtime/arcane/components/conversation-view.html +13 -0
- package/runtime/arcane/components/dashboard-config.html +341 -0
- package/runtime/arcane/components/data-maintenance.html +112 -0
- package/runtime/arcane/components/data-view.html +92 -0
- package/runtime/arcane/components/directory-picker.html +197 -0
- package/runtime/arcane/components/document-inspector.html +252 -0
- package/runtime/arcane/components/file-drop.html +264 -0
- package/runtime/arcane/components/file-inspector.html +293 -0
- package/runtime/arcane/components/file-manager.html +1715 -0
- package/runtime/arcane/components/header.html +142 -0
- package/runtime/arcane/components/integration-settings.html +14 -0
- package/runtime/arcane/components/local-ai-status.html +360 -0
- package/runtime/arcane/components/markdown-document.html +1048 -0
- package/runtime/arcane/components/markdown-editor.html +360 -0
- package/runtime/arcane/components/media-embed.html +8 -0
- package/runtime/arcane/components/modal.html +402 -0
- package/runtime/arcane/components/output-panel.html +259 -0
- package/runtime/arcane/components/preferences-form.html +135 -0
- package/runtime/arcane/components/record-timeline.html +105 -0
- package/runtime/arcane/components/relationship-board.html +116 -0
- package/runtime/arcane/components/screen-capture.html +8 -0
- package/runtime/arcane/components/source-code-viewer.html +441 -0
- package/runtime/arcane/components/source-explanation.html +124 -0
- package/runtime/arcane/components/speech.html +365 -0
- package/runtime/arcane/components/summary-strip.html +177 -0
- package/runtime/arcane/components/table.html +77 -0
- package/runtime/arcane/components/task-progress.html +282 -0
- package/runtime/arcane/components/terminal-workspace.html +65 -0
- package/runtime/arcane/components/theme-editor.html +41 -0
- package/runtime/arcane/components/theme-switcher.html +46 -0
- package/runtime/arcane/components/unified-inbox.html +20 -0
- package/runtime/arcane/components/voice-transcription.html +476 -0
- package/runtime/arcane/components/weather-widget.html +8 -0
- package/runtime/arcane/components/web-navigator.html +239 -0
- package/runtime/arcane/css/communications.css +1 -0
- package/runtime/arcane/css/dashboard-config.css +45 -0
- package/runtime/arcane/css/document-site.css +981 -0
- package/runtime/arcane/css/layout.css +438 -0
- package/runtime/arcane/css/primitives.css +321 -0
- package/runtime/arcane/css/theme.css +112 -0
- package/runtime/arcane/css/utility-workspace.css +1 -0
- package/runtime/arcane/entities/ApiModelRecord.js +20 -0
- package/runtime/arcane/entities/Calculation.js +13 -0
- package/runtime/arcane/entities/Chat.js +581 -0
- package/runtime/arcane/entities/CommunicationMessage.js +29 -0
- package/runtime/arcane/entities/CommunicationThread.js +21 -0
- package/runtime/arcane/entities/Document.js +10 -0
- package/runtime/arcane/entities/File.js +143 -0
- package/runtime/arcane/entities/Image.js +135 -0
- package/runtime/arcane/entities/IntentEnvelope.js +834 -0
- package/runtime/arcane/entities/Preference.js +83 -0
- package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
- package/runtime/arcane/entities/TerminalSession.js +46 -0
- package/runtime/arcane/entities/Theme.js +107 -0
- package/runtime/arcane/entities/User.js +1046 -0
- package/runtime/arcane/entities/Weather.js +23 -0
- package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
- package/runtime/arcane/img/arrow-left.png +0 -0
- package/runtime/arcane/img/arrow-right.png +0 -0
- package/runtime/arcane/img/doc.svg +5 -0
- package/runtime/arcane/img/folder.svg +4 -0
- package/runtime/arcane/img/image.svg +5 -0
- package/runtime/arcane/img/refresh.png +0 -0
- package/runtime/arcane/img/send.svg +9 -0
- package/runtime/arcane/img/trash.svg +5 -0
- package/runtime/arcane/img/upload.svg +5 -0
- package/runtime/arcane/modules/AI.js +2048 -0
- package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
- package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
- package/runtime/arcane/modules/AIResponseLength.js +42 -0
- package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
- package/runtime/arcane/modules/AnsiText.js +53 -0
- package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
- package/runtime/arcane/modules/AppDataScope.js +245 -0
- package/runtime/arcane/modules/AppearancePreferences.js +28 -0
- package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
- package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
- package/runtime/arcane/modules/AsyncBoundary.js +161 -0
- package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
- package/runtime/arcane/modules/CalculatorEngine.js +20 -0
- package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
- package/runtime/arcane/modules/ChartLibrary.js +35 -0
- package/runtime/arcane/modules/ChatRecords.js +13 -0
- package/runtime/arcane/modules/CommunicationAppController.js +43 -0
- package/runtime/arcane/modules/CommunicationHub.js +16 -0
- package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
- package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
- package/runtime/arcane/modules/ComponentContracts.js +586 -0
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
- package/runtime/arcane/modules/ConversationActionItems.js +488 -0
- package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
- package/runtime/arcane/modules/ConversationTimebox.js +527 -0
- package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
- package/runtime/arcane/modules/DBLS.js +171 -0
- package/runtime/arcane/modules/DBOPFS.js +1154 -0
- package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
- package/runtime/arcane/modules/DataMaintenance.js +91 -0
- package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
- package/runtime/arcane/modules/DirectoryPicker.js +109 -0
- package/runtime/arcane/modules/DocumentNavigation.js +223 -0
- package/runtime/arcane/modules/Errors.js +1025 -0
- package/runtime/arcane/modules/GifEncoder.js +29 -0
- package/runtime/arcane/modules/HTMLImport.js +114 -0
- package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
- package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
- package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
- package/runtime/arcane/modules/MD.js +111 -0
- package/runtime/arcane/modules/Mail.js +352 -0
- package/runtime/arcane/modules/MailTransport.mjs +180 -0
- package/runtime/arcane/modules/Marked.min.js +71 -0
- package/runtime/arcane/modules/MemoryRecords.js +44 -0
- package/runtime/arcane/modules/MessageAdvisory.js +38 -0
- package/runtime/arcane/modules/ModelDefinition.js +189 -0
- package/runtime/arcane/modules/Ollama.js +74 -0
- package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
- package/runtime/arcane/modules/OllamaSettings.js +24 -0
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
- package/runtime/arcane/modules/PreferenceStore.js +109 -0
- package/runtime/arcane/modules/QRCode.min.js +1 -0
- package/runtime/arcane/modules/Questionnaire.js +61 -0
- package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
- package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
- package/runtime/arcane/modules/RecordReviewStore.js +94 -0
- package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
- package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
- package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
- package/runtime/arcane/modules/ScreenCapture.js +20 -0
- package/runtime/arcane/modules/SpeechPlayback.js +581 -0
- package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
- package/runtime/arcane/modules/SystemAppearance.js +20 -0
- package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
- package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
- package/runtime/arcane/modules/TerminalClient.js +52 -0
- package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
- package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
- package/runtime/arcane/modules/ThemeManager.js +131 -0
- package/runtime/arcane/modules/TimeGuard.js +149 -0
- package/runtime/arcane/modules/ToolCallRouter.js +83 -0
- package/runtime/arcane/modules/WaitForComponent.js +102 -0
- package/runtime/arcane/modules/YouTubeMedia.js +16 -0
- package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
- package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
- package/runtime/arcane/modules/uPlot.min.css +1 -0
- package/runtime/arcane/security/arcane-network-policy.json +6 -0
- package/runtime/strong-type/index.js +352 -0
- package/runtime/strong-type/licence +21 -0
- package/runtime/strong-type/package.json +45 -0
- package/schemas/arcane-app-bundle.schema.json +125 -0
- package/schemas/arcane-app.schema.json +329 -0
- package/schemas/arcane-lock.schema.json +86 -0
- package/schemas/arcane-package.schema.json +224 -0
- package/schemas/cli-event.schema.json +122 -0
- package/schemas/event-stack.schema.json +152 -0
- package/schemas/native-build-plan.schema.json +176 -0
- package/schemas/target-adapter.schema.json +117 -0
- package/src/app-descriptor.mjs +500 -0
- package/src/cli/main.mjs +561 -0
- package/src/constants.mjs +31 -0
- package/src/dev-server.mjs +718 -0
- package/src/doctor.mjs +315 -0
- package/src/dom-event-instrumentation.mjs +594 -0
- package/src/errors.mjs +75 -0
- package/src/event-manager.mjs +1342 -0
- package/src/event-queue.mjs +138 -0
- package/src/events.mjs +219 -0
- package/src/index.mjs +177 -0
- package/src/integrated-provider-loader.mjs +432 -0
- package/src/native-plan.mjs +698 -0
- package/src/native-provider-loader.mjs +1126 -0
- package/src/packager/core.mjs +2691 -0
- package/src/process.mjs +353 -0
- package/src/release-bundle.mjs +2523 -0
- package/src/repository.mjs +90 -0
- package/src/runtime.mjs +452 -0
- package/src/scaffold.mjs +380 -0
- package/src/targets/index.mjs +436 -0
- package/src/templates/assets/app-icon.png +0 -0
- package/src/templates/workspace-template.mjs +388 -0
- package/src/testing-loader.mjs +9 -0
- package/src/testing.mjs +427 -0
- package/src/toolchain.mjs +1335 -0
- package/src/update-check.mjs +307 -0
- 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>
|