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>
- guardian_loop + sitrep: SELECT metric_data (not metrics_json which does not exist)
- guardian_loop: metrics are flat (cpu_percent at top level), not nested under system key
- guardian_loop + sitrep: filter metric_type=system to avoid parsing proxmox blobs
- guardian_loop: disk.mount key (not mountpoint) + fallback for both key names
- sitrep: same metric_data + root-level key fixes
- _guardian_inject_chat (x2): INSERT into conversations.content (not message)
- /guardian/chat endpoint (x2): SELECT content (not message) from conversations
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>
- Proxmox: skip if data < 10 min old (was: every 3 min unconditionally)
- Ollama: skip if data < 15 min old (model list rarely changes)
- Site health: skip if data < 5 min old (was: 7 HTTP calls every 3 min)
- Home Assistant: removed entirely (HA agent pushes 212 entities every 30s)
Fast local reads (CPU/mem/network pings) still run every 3 min. External
HTTP calls now fire only when data is actually stale. Saves ~140 site-check
HTTP calls/hour and ~60 Proxmox API calls/hour in steady state.
When deploy/reactor.py changes in a push, the deploy runner now copies it
to the runtime location and restarts jarvis-arc.service automatically.
Eliminates the two-copy drift problem — repo is now canonical.
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.
Arc Reactor was running from /opt/jarvis-arc with no version tracking.
Added to deploy/ so all fixes (metrics_json→metric_data, flat JSON parsing,
disk mount key fix) are captured. WG configs are runtime-generated secrets
and must not be committed.
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>
const ts = ts() in loadVision caused TDZ ReferenceError crashing gallery.
visionRunScreenshot now fetches online agents from agents_list API when
no screenshots exist yet (previously showed No agents online falsely).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ARC REACTOR tab had HTML and PHP API handlers but no JS load function,
causing ReferenceError on every tab click. Adds all three missing functions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rename memory section CAT_COLORS to MEM_CAT_COLORS to avoid SyntaxError
that prevented doLogin from being defined, locking users out of admin.
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: open_basedir restriction prevented lsphp from reading config
files on other vhosts (/home/epictravelexpeditions.com/*, etc.)
TJJ worked via its own DB; TTG worked because file happened to be readable.
Epic, Parker Slingshot, Parker Slingshot Rentals all returned empty.
Fix: site_settings table in jarvis_db as primary storage for all sites.
- All reads/writes go through JarvisDB (always accessible, no open_basedir)
- TJJ still syncs bidirectionally with its own settings table (secondary)
- File push attempted best-effort on save (succeeds where writable, silent no-op otherwise)
- Seeded existing known values from file grep on table creation
- All 5 sites now return and save settings correctly
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
- Overlay shrunk to min(860px, 86vw) x min(570px, 76vh) — fits any screen
- Solar system layout: JARVIS hub at center, 4 concentric orbital rings
- Ring 1 (green, innermost): Proxmox nodes, rotates clockwise
- Ring 2 (gold): Services (HA, AI, PBX, Homebridge), counter-clockwise
- Ring 3 (cyan): Linux/Windows agents, slow clockwise
- Ring 4 (dim blue, outermost): Network scan devices, slow counter-clockwise
- Rings rotate at different speeds/directions (persistent offsets across frames)
- Each ring draws dashed track + tick marks every 30 deg + label + online/total count
- Nodes evenly spaced on their ring, rotate with it
- Spoke lines from each node to hub (straight, low opacity)
- Particle flow on spokes: cyan in (data), orange out (commands)
- Node positions computed per-frame from angle+ring radius+rotation
- Overlay canvas sized exactly to container minus header+legend height
- Quadrant layout: Proxmox (top-left), Services (top-right), Agents (bottom-left), Devices (bottom-right)
- Dashed divider lines + subtle per-zone color gradient fill separates sections visually
- Zone watermark labels (PROXMOX CLUSTER, SERVICES, AGENTS, NETWORK DEVICES) with online/total count
- Nodes arranged in tidy grid within each zone — no more single crowded ring
- Labels positioned OUTWARD from hub center (atan2 to calculate angle) so they never overlap nodes
- Bezier lines bow outward away from hub center (control point pushed along hub→midpoint vector)
so lines spread out and each is individually traceable
- IP shown only on hub and hovered nodes — reduces label clutter
- Overflow indicator: shows +N MORE when zone has too many nodes (max per zone: 6/6/8/10)
- Intra-zone cross-links for Proxmox cluster (green) and Services cluster (gold)
- RGB color system replaces old r/g/b object — cleaner rgba() template strings
- Voice: say show network map / network topology / show connections to open
- Voice: say close map / dismiss / close network to close
- Same commands work in chat text input
- Explode animation: overlay expands from top-left reactor position with clip-path wipe
- Collapse animation: folds back to reactor on close
- Visualization: live node graph with bezier curved edges, hub (JARVIS) at center
- Inner ring: all registered agents (agents color-coded by type: proxmox=green, HA=gold, etc)
- Outer ring: netscan-discovered devices
- Rotating orbit rings on hub and agent nodes
- Pulsing radial glow per node keyed to online status
- Hub cross-hair targeting lines
- Directional particle flow:
- CYAN particles: data/heartbeats flowing FROM agents TO JARVIS hub
- ORANGE particles: commands flowing FROM JARVIS hub TO agents
- All particles travel curved bezier paths, fade at endpoints, glow with shadows
- Mouse hover: node info card shows name/IP/status/type
- Stats bar: total nodes, online count, agent count
- Background: faint hex grid overlay for sci-fi depth