Add Android forensics, IOC threat-intel DB, Compose companion; scrub secrets from configs
This commit is contained in:
@@ -2161,6 +2161,8 @@ function halToggle() {
|
||||
if (!p) return;
|
||||
var visible = p.style.display !== 'none';
|
||||
p.style.display = visible ? 'none' : 'flex';
|
||||
// Remember open/closed state across page navigation
|
||||
sessionStorage.setItem('hal_panel_open', visible ? 'false' : 'true');
|
||||
if (!visible) {
|
||||
var inp = document.getElementById('hal-input');
|
||||
if (inp) inp.focus();
|
||||
@@ -2279,6 +2281,7 @@ function halAppendStyled(type, text) {
|
||||
}
|
||||
msgs.appendChild(div);
|
||||
halScroll();
|
||||
_halSaveMessages();
|
||||
}
|
||||
|
||||
function halAppend(role, text) {
|
||||
@@ -2289,6 +2292,8 @@ function halAppend(role, text) {
|
||||
div.textContent = text;
|
||||
msgs.appendChild(div);
|
||||
halScroll();
|
||||
// Persist to sessionStorage so messages survive page navigation
|
||||
_halSaveMessages();
|
||||
return div;
|
||||
}
|
||||
|
||||
@@ -2300,9 +2305,60 @@ function halScroll() {
|
||||
function halClear() {
|
||||
var m = document.getElementById('hal-messages');
|
||||
if (m) m.innerHTML = '';
|
||||
sessionStorage.removeItem('hal_messages');
|
||||
sessionStorage.removeItem('hal_panel_open');
|
||||
fetch('/api/chat/reset', {method: 'POST'}).catch(function() {});
|
||||
}
|
||||
|
||||
// Persist chat messages across page navigation
|
||||
function _halSaveMessages() {
|
||||
var msgs = document.getElementById('hal-messages');
|
||||
if (!msgs) return;
|
||||
var items = [];
|
||||
msgs.querySelectorAll('.hal-msg').forEach(function(el) {
|
||||
var role = 'hal';
|
||||
if (el.classList.contains('hal-msg-user')) role = 'user';
|
||||
else if (el.classList.contains('hal-msg-status')) role = 'status';
|
||||
else if (el.classList.contains('hal-msg-action')) role = 'action';
|
||||
else if (el.classList.contains('hal-msg-error')) role = 'error';
|
||||
items.push({role: role, text: el.textContent});
|
||||
});
|
||||
// Keep last 100 messages to avoid storage bloat
|
||||
if (items.length > 100) items = items.slice(-100);
|
||||
try { sessionStorage.setItem('hal_messages', JSON.stringify(items)); } catch(e) {}
|
||||
}
|
||||
|
||||
function _halRestoreMessages() {
|
||||
var msgs = document.getElementById('hal-messages');
|
||||
if (!msgs) return;
|
||||
try {
|
||||
var saved = sessionStorage.getItem('hal_messages');
|
||||
if (!saved) return;
|
||||
var items = JSON.parse(saved);
|
||||
items.forEach(function(item) {
|
||||
var div = document.createElement('div');
|
||||
if (item.role === 'user' || item.role === 'hal') {
|
||||
div.className = 'hal-msg hal-msg-' + item.role;
|
||||
div.textContent = item.text;
|
||||
} else {
|
||||
div.className = 'hal-msg hal-msg-' + item.role;
|
||||
div.textContent = item.text;
|
||||
}
|
||||
msgs.appendChild(div);
|
||||
});
|
||||
halScroll();
|
||||
} catch(e) {}
|
||||
|
||||
// Restore panel visibility
|
||||
if (sessionStorage.getItem('hal_panel_open') === 'true') {
|
||||
var p = document.getElementById('hal-panel');
|
||||
if (p) p.style.display = 'flex';
|
||||
}
|
||||
}
|
||||
|
||||
// Restore on page load
|
||||
document.addEventListener('DOMContentLoaded', _halRestoreMessages);
|
||||
|
||||
// ── HAL Auto-Analyst ──────────────────────────────────────────────────────────
|
||||
// Call halAnalyze() after any tool displays results. HAL will analyze the output
|
||||
// via the loaded LLM and open the chat panel with findings.
|
||||
|
||||
120
web/static/js/autarchos.js
Normal file
120
web/static/js/autarchos.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/* AutarchOS — desktop chrome client-side wiring.
|
||||
*
|
||||
* Owns: live clock, dock state highlight for current blueprint, apps launcher
|
||||
* modal (filterable list of every blueprint), keyboard shortcuts.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// ── Clock ────────────────────────────────────────────────────────
|
||||
function tickClock() {
|
||||
var el = document.getElementById('aos-clock');
|
||||
if (!el) return;
|
||||
el.textContent = new Date().toTimeString().slice(0, 8);
|
||||
}
|
||||
setInterval(tickClock, 1000);
|
||||
tickClock();
|
||||
|
||||
// ── Mark dock app for current blueprint ─────────────────────────
|
||||
function markActiveDockApp() {
|
||||
var bp = document.body.getAttribute('data-blueprint') || '';
|
||||
document.querySelectorAll('.aos-dock .app').forEach(function (a) {
|
||||
var slug = a.getAttribute('data-app') || '';
|
||||
a.classList.toggle('active', slug && slug === bp);
|
||||
});
|
||||
}
|
||||
markActiveDockApp();
|
||||
|
||||
// ── Apps launcher modal ─────────────────────────────────────────
|
||||
var backdrop = document.getElementById('aos-launcher');
|
||||
var searchInput = document.getElementById('aos-launcher-search');
|
||||
|
||||
function openLauncher() {
|
||||
if (!backdrop) return;
|
||||
backdrop.classList.add('open');
|
||||
if (searchInput) {
|
||||
searchInput.value = '';
|
||||
searchInput.focus();
|
||||
filterApps('');
|
||||
}
|
||||
}
|
||||
|
||||
function closeLauncher() {
|
||||
if (!backdrop) return;
|
||||
backdrop.classList.remove('open');
|
||||
}
|
||||
|
||||
function filterApps(query) {
|
||||
var q = (query || '').trim().toLowerCase();
|
||||
document.querySelectorAll('.aos-launcher .app-card').forEach(function (card) {
|
||||
var hay = (card.textContent || '').toLowerCase();
|
||||
card.style.display = (!q || hay.indexOf(q) !== -1) ? '' : 'none';
|
||||
});
|
||||
document.querySelectorAll('.aos-launcher .group').forEach(function (g) {
|
||||
var visible = g.querySelectorAll('.app-card:not([style*="display: none"])').length;
|
||||
g.style.display = visible ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('[data-aos-action="open-launcher"]').forEach(function (el) {
|
||||
el.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
openLauncher();
|
||||
});
|
||||
});
|
||||
|
||||
if (backdrop) {
|
||||
backdrop.addEventListener('click', function (e) {
|
||||
if (e.target === backdrop) closeLauncher();
|
||||
});
|
||||
}
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', function () { filterApps(this.value); });
|
||||
searchInput.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape') closeLauncher();
|
||||
if (e.key === 'Enter') {
|
||||
var first = document.querySelector(
|
||||
'.aos-launcher .app-card:not([style*="display: none"])'
|
||||
);
|
||||
if (first && first.href) window.location.href = first.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Global shortcuts
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && backdrop && backdrop.classList.contains('open')) {
|
||||
closeLauncher();
|
||||
}
|
||||
// Super/Ctrl+Space → open launcher
|
||||
if ((e.ctrlKey || e.metaKey) && e.code === 'Space') {
|
||||
e.preventDefault();
|
||||
if (backdrop && backdrop.classList.contains('open')) {
|
||||
closeLauncher();
|
||||
} else {
|
||||
openLauncher();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ── Sparkline helper (used by dashboard widgets) ────────────────
|
||||
window.aosRenderSpark = function (el, count, hotIndices) {
|
||||
if (!el) return;
|
||||
el.innerHTML = '';
|
||||
var hot = new Set(hotIndices || []);
|
||||
for (var i = 0; i < count; i++) {
|
||||
var b = document.createElement('i');
|
||||
b.style.height = (16 + Math.abs(Math.sin(i * 0.55)) * 60 + Math.random() * 18) + '%';
|
||||
if (hot.has(i)) {
|
||||
b.classList.add('hot');
|
||||
b.style.height = '92%';
|
||||
}
|
||||
el.appendChild(b);
|
||||
}
|
||||
};
|
||||
|
||||
// ── Expandable incidents (dashboard / triage views) ─────────────
|
||||
document.querySelectorAll('.inc').forEach(function (i) {
|
||||
i.addEventListener('click', function () { i.classList.toggle('open'); });
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user