- 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>
public_html/agent/ is what agents download for self-update.
It was 5 days out of date — missing the version-in-heartbeat fix
and all other v3.1 changes. Now mirrors agent/jarvis-agent.py exactly.
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>
'What's playing on Jellyfin' — the apostrophe inside the single-quoted
string caused a SyntaxError that prevented the entire file from loading,
making checkArcStatus and all other panel functions undefined.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
agent/list and agent/status are browser-facing and need $_SESSION loaded
to verify auth. Only skip session_start() for machine-agent sub-actions
(heartbeat, metrics, ha_state, command_result, register) that fire every
10-30s. Previous fix skipped session for all agent/* causing the agents
panel to return 401 to the browser.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Agent heartbeats (every 10s from 13 agents) were creating empty session files
because session_start() ran unconditionally. Over months this produced millions
of 0-byte files in the session directory, causing PHP session GC to hang and
making all browser API calls intermittently timeout (panels show offline/empty).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sendMessage() was fetching /api.php?action=chat which bypasses the
/api/* rewrite rule; api.php parsed endpoint as "api.php" → 404.
Fixed to /api/chat so the rewrite routes it correctly to chat.php.
- agent.php HA entity map INSERT used non-existent fact_type column,
causing PDOException on every agent heartbeat. Fixed to use the
correct (category, fact_key, fact_value) columns.
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>
After writing the updated script, _stop_event.set() caused a clean exit
(code 0). SCM failure recovery only fires on non-zero exit, so the service
stayed down permanently after every auto-update.
Fix: set _update_restart=True before signalling stop; SvcDoRun() checks
the flag after main() returns and calls sys.exit(1), which triggers the
sc.exe failure recovery chain (restart/5s/10s/30s configured at install).
The LocalSystem service account cannot access per-user Python installs
(AppData\Local\Programs\Python\...). When a per-user install is detected,
automatically install Python system-wide before proceeding.
- Detect per-user Python (AppData in path) and trigger system-wide install
- Extract system Python install logic into Install-PythonSystemWide function
- Check winget exit code before marking install successful
- Split pip install and postinstall into separate steps; pip failure is fatal,
postinstall failure is a warning (service DLLs may already be registered)
- Use $LASTEXITCODE check on pip rather than try/catch (external process)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the scheduled-task approach (required user to stay logged in) with a
proper Windows Service using pywin32. The service runs as LocalSystem, starts
at boot, and auto-restarts on failure — no PowerShell window needed.
Agent changes (jarvis-agent-windows.py):
- Add Windows Service class via pywin32 (JarvisAgentService)
- Cleanly handles SvcStop by setting a threading.Event
- main() loop uses _stop_event.wait() instead of time.sleep() so stop is immediate
- self_update() signals the stop event when running as a service (SCM restarts it)
- __main__ block dispatches to SCM entry point or HandleCommandLine (install/stop/remove)
- Falls back to direct run if pywin32 not installed (for debugging)
Installer changes (install-windows.ps1):
- pip install pywin32 + postinstall (registers service runner DLLs)
- Python search prefers system-wide install (accessible by LocalSystem)
- Downloads Python 3.11 directly from python.org for Win 8.1 machines without winget
- Removes legacy JARVIS-Agent scheduled task if present
- Registers JARVISAgent service with --startup auto
- Configures sc.exe failure recovery (restart at 5s/10s/30s)
- Updated management commands in summary (Start-Service, Stop-Service, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add version column to registered_agents table
- Agents send version on registration (Linux 3.1, Windows 3.0, macOS 3.0)
- workers_list API returns latest_versions per platform
- Workers tab: VERSION column with green check (up-to-date) or red (outdated)
- Outdated agents highlight row and show blue UPDATE button
- Up-to-date agents show dimmed UPDATE button
- Update button dispatches update command immediately
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Old installer wrote to /opt/jarvis-agent/config.json with server_url/api_key/
heartbeat_interval keys and pre-registered with JARVIS. Agent v3.0 expects:
- Config at /etc/jarvis-agent/config.json with jarvis_url/registration_key/
hostname/poll_interval/heartbeat_every keys
- api_key stored by agent itself in /var/lib/jarvis-agent/state.json
- Agent self-registers at startup using registration_key
Also adds: imagemagick install (headless screenshot support), apk support
for Alpine/WireGuard, copies to /usr/local/bin/jarvis-agent.py.
Previously agents only registered when api_key was missing (first run).
After updating to v3.0 with screenshot capability, restarted agents never
refreshed their capabilities in the DB. Now register() is called every
startup — server does UPDATE on existing agent_id so api_key is preserved.
self_update(cfg) and shell allow_shell_commands check both referenced cfg
from run() scope, but execute_command() is a standalone function. Fixed by
calling load_config() locally in each branch that needs it.
A ParseError or fatal in any endpoint file now returns JSON 500 for that
endpoint only. switch replaced with data-driven map. All other endpoints
continue working normally when one is broken.