- stopListening() called in both toggleKiosk exit and _onFsChange so mic
stops when leaving kiosk (was staying live indefinitely)
- exitVoiceMode() now returns early if kiosk-mode active so the 30-min
idle timer and face-detection loop cannot kill the always-on mic
- Adds body.kiosk-mode class on fullscreen entry/exit
- Hides: #server-panel, #tab-agents, #tab-guardian, tab buttons
- Hides bottom bar: Home Assistant, Agents, Memory, Proxmox
- Falls back to INTEL tab if agents/guardian was active on kiosk entry
- All elements remain visible in normal/tablet mode
- /api/do now includes do_server key with jarvis-do agent metrics
(CPU, RAM, disk, uptime from Tailscale-connected DO server agent)
- Front page JARVIS SERVER panel has WEB HOST section with live
CPU/RAM/DISK bars from DO server agent data
- Panel title updated to show 10.48.200.211 (JARVIS VM IP)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A single SyntaxError in the 1668-line monolith kills every panel
(proven by the apostrophe bug on 2026-06-17). Split into:
panels/jarvis-arc.js (608 lines) — Arc Reactor, Intel, Comms, Guardian
panels/jarvis-agents.js (715 lines) — Missions, Directives, Memory,
Clearance, Agents tab, Sites, Vision
panels/jarvis-assistant.js (345 lines) — Chat History, Suggestions,
Mobile, Command Palette, Topo map
A parse error in any one file now fails only that group of panels.
escHtml() stays in jarvis-arc.js (loads first) and remains global.
All other dependencies (api, speak, addMessage) come from jarvis-app.js.
Version param bumped to ?v=20260617b to force Cloudflare cache miss.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
One untagged script tag is enough for Cloudflare Rocket Loader to
activate its bootstrap and inject mainScript.js, which declares
mainScriptFlag. When mainScript.js loads twice (script + eval), it
throws SyntaxError: Identifier 'mainScriptFlag' has already been
declared. All script tags now have data-cfasync=false.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jarvis-protocols.js had a syntax error (apostrophe in single-quoted string)
that Cloudflare was caching (4h TTL). Adding ?v=20260617 to all JS script
tags forces a cache miss so the browser gets the fixed file immediately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#1 Voice waveform: Web Audio API drives wave-bar heights in real time
#2 Ambient dim mode: panels fade to 12% after 90s idle
#6 Streaming AI replies: Groq tokens via SSE; frontend ReadableStream
#7 Quick-note capture: N key / "note: text" saves to kb_facts instantly
#8 Cancel in-flight request: AbortController + CANCEL button
#9 Accent color themes: Stark Blue / Widow Red / Hulk Green, localStorage
#10 Browser push notifications: critical alerts when tab is backgrounded
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#3 Live Voice Transcript: Real-time subtitle bar at bottom of screen shows
what JARVIS hears as you speak. Interim results appear word-by-word via
SpeechRecognition.onresult interim events; bar fades 3.2s after final result.
#4 Keyboard Shortcuts: Global keydown handler (skips input fields):
F5=refresh all, Esc=close modals/overlays, M=mute mic toggle,
Space=focus chat input, 1/2/3/4=switch HOME/ALERTS/NEWS/AGENTS tabs.
Shortcut hints added to Ctrl+K palette footer.
#5 Agent Topology Map: TOPOLOGY button in AGENTS tab switches from card
view to animated ring-based canvas showing all agents by type (Proxmox=green
inner ring, HA=yellow mid ring, Linux/Windows=blue outer ring). Live particles
flow hub→agents; offline nodes shown in red. Reads from rendered agent cards.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HA toggle broken after modularization: separate <script src> files are
deferred by Cloudflare Rocket Loader, so inline onchange handlers fire
before toggleHA() is defined. Fix: add data-cfasync="false" to all
four JARVIS script tags to prevent Rocket Loader interference.
Network map cleanup:
- Deduplicate agent devices by hostname — two homeassistant agents
(10.48.200.97 and 172.30.32.1) now show as one node; prefer online
over offline, then most-recently-seen
- Offline agents excluded from inner rings — jellyfin (offline June 3)
and mini_it12 (offline June 12) no longer appear on the map
- DB-pinned devices (Yealink phones) unaffected; still show in devices ring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#11 Smart Morning Briefing: auto-speaks once per day before noon — fetches
tasks, appointments, active alerts, and weather, composes a ~2-sentence TTS
summary. Stored in localStorage (jarvis_brief_YYYY-MM-DD) to fire only once.
#12 Quick Command Palette (Ctrl+K): frosted-glass overlay with 20 pre-loaded
commands across 6 groups (Network/Agents/Planner/Media/Smart Home/System).
Fuzzy filter as you type, arrow-key navigation, Enter to fire. Matches are
highlighted. Backdrop click or Escape to close.
#13 Live Boot Animation: stat bars and numbers now count from 0 on first render
via tickTo() change. Arc Reactor rings spin in with staggered delays (0.08s
per ring) on login using boot-spin CSS class + @keyframes arcBootSpin.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Mobile UI: 3-button bottom nav with panel switcher
- Chat history search: search modal with keyword query
- News filtering: category filter with localStorage persistence
- Proactive reminders: planner/appointment alerts at login and every 5 min
- Proactive alerts: polls every 60s, speaks new critical/warning alerts
- Agent sparklines: 2h CPU+MEM sparkline on each online agent card
- Tier source badge: KB/GROQ/CLAUDE/OLLAMA pill shown after each reply
- VM suggestions: 24h resource analysis via voice command
- HA scene control: fuzzy-match scene activation via voice
- Jellyfin control: pause/stop/next/previous via voice and KB
- Pattern suggestions: usage_patterns table + proactive chips every 30 min
- Multi-step commands: compound "X and Y" command parsing (Tier 0.5)
- Arc Reactor health: warning=amber/1.2s, critical=red/0.6s pulse encoding
- Cross-session history: last 6 turns loaded from prior session
- Restart agent: voice command to restart any JARVIS agent
- New endpoints: history.php, metrics.php, suggestions.php, jellyfin.php
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Proactive alerts (#1): polls every 60s; baselines on load so old alerts are silent; speaks new critical/warning alerts aloud if voice active; adds chat bubble for all new alerts
- Jellyfin control (#2): pause/stop/next/previous via voice — auto-detects active session; 12 KB intents; jellyfin.php control action uses Jellyfin General Commands API
- Agent sparklines (#6): metrics.php returns 2h CPU+MEM history per agent; SVG polyline sparklines rendered in each agent card (cyan=CPU, green=MEM); non-blocking fetch so existing view shows instantly
- Agent health CCR (#7): updated hourly cloud routine to current 13-agent roster, removed ollama-ai and alien-pc, added all active agents with correct IPs/IDs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Voice commands (#3): say "restart the homebridge agent" or "restart mediastack agent" → queues restart_service to that agent; lists options if no hostname matched; 6 KB intents added
- Persistent context (#4): chat.php now loads last 6 turns from most recent prior session before current session history, giving JARVIS memory across page reloads
- Proactive reminders (#5): 3s after login, auto-announces overdue tasks / tasks due today / upcoming appointments; 5-min interval checks for appointments starting within 15 min and speaks alert once
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two issues:
1. NM_OPEN_RE regex was too narrow — phrases like "show me the network",
"open the network", "show network status" did not match, so they fell
through to the API which returned text but never opened the map.
Broadened regex to catch natural network-related phrases.
2. When the network_scan intent IS triggered via API, the map never opened
because the API response handler only processed reply/arc_job.
chat.php now returns open_network_map:true for network_scan intent,
and the client calls openNetMap() when that flag is present.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Swap: replace grid-column reassignment with named grid-template-areas
(grid-column approach caused leftPanel to disappear and mis-position).
"left center right" <-> "right center left" cleanly swaps both columns.
Collapsible: clicking any panel-title collapses/expands that panel.
Chevron rotates -90deg when collapsed. State persists in localStorage.
All interactive elements in title bars (+ buttons etc) still work.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Broke entire JS block — side panels, data loading, everything.
synthesis.length>1500 ternary had bare newlines inside single quotes.
Replaced with \n escape sequences.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DB: missions, mission_steps, mission_runs tables
- reactor.py v7.0.0: handle_run_mission, _execute_mission, mission_trigger_loop (schedule/guardian_event/email_keyword triggers), {{template}} substitution across steps, full CRUD REST endpoints
- arc.php: missions/mission_get/mission_runs/mission_create/mission_update/mission_delete/mission_run/mission_toggle actions
- admin/index.php: Mission Ops tab with visual workflow builder (trigger config, step cards with ↑↓, JSON payload editor, continue-on-failure flag), run history with step-level detail, enable/disable toggle
- index.html: MISSIONS tab with collapsible mission cards, RUN NOW button per mission, live run result feedback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- chat.php: Add Tier 0.9a (gmail_triage), Tier 0.9b (remote_exec) detection;
refactor arc submit into arcSubmitJob() helper; natural-language triggers for
email triage (check my email, triage inbox) and remote exec (restart X on Y,
run X on Y, get logs from X on Y)
- arc.php: Add triage and triage_action endpoints (read/update email_triage table)
- index.html: Add COMMS tab with triage card UI (filter bar, category badges,
draft reply viewer, copy/dismiss actions); loadComms() with 8s polling;
onArcJobStarted() routes gmail_triage jobs to COMMS tab
- admin/index.php: Add GMAIL TRIAGE section under COMMUNICATIONS nav; triage_list/
triage_action/triage_run PHP actions; loadTriage() JS with full table + draft
modal; triageRunNow() submits gmail_triage job to Arc Reactor
Arc Reactor v2.0:
- research handler: DDG search → async page fetch → trafilatura extraction → Claude synthesis
- tool_loop handler: multi-step agent loop (up to 200 iter) with web_search, fetch_url, jarvis_agents, jarvis_alerts, current_time tools
- llm handler: multi-provider router (Claude/Groq/Ollama)
- /jobs/recent endpoint for HUD polling
- Phase 1 handlers preserved (ping/echo/shell)
chat.php — Tier 0.9 Intel Protocol (before KB intent engine):
- Detects: research/investigate/deep-dive/look up/find out about → research job
- Detects: step-by-step/figure out/analyze and report → tool_loop job
- Returns arc_job ID in response for UI polling
- Depth modifiers: quick/standard/deep
index.html:
- INTEL tab in right panel tab bar
- Research result cards with expand/collapse, synthesis, sources, status
- Live polling (4s) when INTEL tab is active + active jobs present
- Auto-switches to INTEL tab when research is triggered from chat
- intelPrompt() pre-fills chat input for new research
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Python asyncio daemon (/opt/jarvis-arc/reactor.py) running on 127.0.0.1:7474
- systemd service (jarvis-arc) auto-starts with MySQL dependency
- arc_jobs + arc_status MySQL tables for async job queue
- api/endpoints/arc.php: PHP bridge to daemon (status, job_create, job_get, jobs, purge)
- api.php: added arc route
- index.html: ARC REACTOR status indicator in bottom bar with live polling
- admin/index.php: ARC REACTOR nav section + full job management panel
- Built-in job handlers: ping, echo, shell (whitelist-gated)
- Foundation for Phase 2 (Intel Protocol) and beyond
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace tiny dot nodes with frosted-glass bubbles with ambient glow and float animation
- Add 6th ring for netscan-discovered network devices (cap 28)
- Split named/DB devices and discovered devices into separate rings
- Push rFrac to 0.82 to fill the overlay window
- Increase all ring caps and node radii
- Add FortiGate NAT IP to providers ACL
- Fix TCP SIP drop issue via transport=udp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause 1: Notification.requestPermission() on startup (3s delay) opened
a browser permission dialog while JARVIS was still speaking the welcome greeting.
This aborted the SpeechRecognition session. Because isSpeaking=true at that
moment, onend did not reschedule a restart — mic went permanently silent.
Fix: removed the startup requestPermission() call entirely.
Root cause 2: Same requestPermission() inside _focusWindow() called on every
enterVoiceMode() — could abort the recognition session on each wake.
Fix: only create notification when permission already granted, never request.
Root cause 3: SLEEP_CMDS matched bare words like offline and sleep that appear
in normal commands (check if server is offline, put device to sleep, etc.)
Fix: tightened to require explicit phrasing — go offline, sleep mode,
shut down jarvis, good night jarvis, etc.
Sleep mode:
- Commands: good night / go to sleep / shut down / standby / offline / signing off
- Works via voice or text
- UI dims to 8% brightness, slow-spinning standby reactor overlay appears
- Refresh loop pauses (light 2min heartbeat keeps session alive)
- Mic stays fully active — only responds to master wake phrases
- Idle-reload disabled while sleeping (prevents unwanted reloads overnight)
Wake from sleep (master wake phrase):
- Detects wake phrase while isAsleep=true, routes to wakeFromSleep()
- Full HUD boot sequence animation (panels slide in)
- refreshAll() fires immediately to reload all data
- JARVIS greets: All systems back online
Window focus on any wake:
- window.focus() called on every enterVoiceMode
- document.title flashes 8x between JARVIS ONLINE and default
- Web Notifications API: system popup fires when window is minimized/backgrounded
- Notification permission requested 3s after login
- Works regardless of sleep/voice mode
Reverted to c8e0020 (all 10 effects working) then added net map cleanly:
- Used var/for instead of const/let/arrow-functions to avoid any closure/scope issues
- Orbital ring layout: JARVIS hub center, 4 concentric rings (proxmox/services/agents/devices)
- Rings rotate at different speeds/directions independently
- Spoke lines hub-to-each-node with cyan inbound and orange outbound particles
- Node labels point outward from center, never overlap
- Tiny green/red status dot on every non-hub node
- Hover shows node info card (name/IP/status/ring)
- Open: say/type show network map / network topology / show connections
- Close: say/type close map / close network / dismiss map
- All other features (mic, voice, text, panels) unaffected