- Centralises all vision logic in one place instead of duplicated inline blocks
- Claude remains primary; set OLLAMA_VISION_MODEL env var to enable a local
vision model (e.g. llava, moondream) as automatic fallback
- Graceful degradation message when no vision provider is available
- Both handle_screenshot and handle_vision now use _vision_call()
Backup script was never migrated when JARVIS moved from DO to VM 211.
Runs daily at 3am, stores compressed dumps in /var/backups/jarvis/,
logs to /var/log/jarvis/backup.log.
- deploy/requirements.txt: explicit pip deps (fastapi, uvicorn, aiomysql, aiohttp, anthropic, trafilatura)
- jarvis-deploy.sh: self-installs to /usr/local/bin/ on every run so updates propagate;
auto-creates venv and installs packages if missing before restart attempt
- admin/index.php: add SETUP button next to RESTART — runs full setup+start in one click
(creates venv, installs deps, copies reactor.py, starts it)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8tDRrQqgLjqXebMCBNcP3
- Add _ollama_vision_call() using Ollama /api/generate with images array
- handle_screenshot: try llava first (free, on-LAN), fall back to Claude on error;
text-only snapshots now use ollama instead of groq
- handle_vision: same llava-first/Claude-fallback pattern; caller can force
provider='ollama' or 'claude' explicitly; stored provider_used reflects actual
provider that ran
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8tDRrQqgLjqXebMCBNcP3
- reactor.py: fix OLLAMA_HOST .95 → .210 (actual Ollama VM IP)
- reactor.py: upgrade OLLAMA_MODEL 1b → 8b (llama3.1:8b has tool-calling, 131K ctx)
- reactor.py: guardian alerts and sitrep now use ollama instead of groq (free, on-LAN, no quota)
- config.example.php: same IP/model fixes + fix GROQ_MODEL_SEARCH to compound-beta-mini (groq/ prefix causes 404)
- deploy script: patch live config.php on every deploy to correct Ollama IP/model and Groq model name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8tDRrQqgLjqXebMCBNcP3
The admin panel restart command used shell_exec which runs /bin/sh (dash on
Ubuntu) — dash doesn't support 'source', so the venv never activated and the
reactor silently never started.
- admin/index.php: wrap restart in bash -c so 'source' works; try systemctl
first then fall back to nohup
- deploy/jarvis-arc.service: add proper systemd unit so reactor auto-starts
on boot and auto-restarts on crash
- deploy/jarvis-deploy.sh: install+enable service file when it changes; mkdir
log dir before restart; fall back to nohup if systemctl not set up yet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8tDRrQqgLjqXebMCBNcP3
- Add CREATE TABLE IF NOT EXISTS for guardian_config and guardian_events in
reactor lifespan so tables are created automatically on next restart
- Fix conversations column bug: reactor used 'message' but schema has 'content';
fix INSERT and SELECT queries to use content (SELECT aliases it as 'message'
so the JSON response key stays the same)
- Add guardian tables to schema.sql for documentation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8tDRrQqgLjqXebMCBNcP3
- db/seed_kb.sql: 25 intent patterns + user prefs (Myron / Mr. Blair)
- usage_patterns: renamed last_used→last_seen to match chat.php
- facts_collector: JARVIS self-check URL was port 1972 (DO), now correct URL
- db/schema.sql: reflects current live DB schema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- install-windows.ps1: one-liner PowerShell installs Python, pywin32,
downloads agent, creates config, installs Windows Service (auto-start)
- install.sh: fix JARVIS_URL from hardcoded LAN IP to https://jarvis.orbishosting.com
- install.sh: fix ssl_verify default to true for external agents
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ha.php skipDomains: added media_player, scene
- ha.php skipKeywords: konnected, energy/power/voltage/current, full camera list
- stats_cache.php: same filter updates, removed scene/media_player from sync
- Removed JS setInterval polling; entity state kept fresh by HA agent push
- Added nightly 3am cron for full HA entity resync
- Added to skipDomains: media_player
- Added to skipKeywords: konnected, energy/power/voltage/current,
camera controls (infrared, email, FTP, push, siren, hub ringtone, manual record),
system noise (CEC scanner, ESPHome builder, Echo DND)
- Auto-refresh every 30s when HA tab is active
- 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>
- Site checks use external URLs instead of 127.0.0.1 loopback (JARVIS
no longer shares a server with the websites)
- JARVIS site URL updated to port 1972
- Fixed syntax error in DO server ping exec call
- Removed Host header injection (not needed for external checks)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three issues caused periodic worker saturation:
1. Network section pinged 5 private LAN IPs (10.48.200.x) unreachable
from DO — each failed after 1s timeout = 5s wasted per run.
Replaced with a fast DB query on registered_agents.
2. pve_api_get() had no CURLOPT_CONNECTTIMEOUT — added 3s limit so
unreachable Proxmox fails fast instead of blocking the full 8s.
3. Ollama curl timeout reduced from 5s→3s total, added 2s connect limit.
Cron interpreter also changed from lsphp85 to php8.3 in crontab
(done directly on server) — lsphp85 adds ~8s LSAPI startup overhead
and consumes a PHP worker slot; php8.3 runs standalone.
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>
Heartbeat was sending {} — version only appeared in registration.
Agents that never re-register (most of them) stayed NULL in the DB.
Now every heartbeat carries {"version": AGENT_VERSION} so agent.php
can update the column on every check-in.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
update_agent_seen() now updates version column when agents include it
in their heartbeat payload. Previously version was only stored on
registration, leaving the Workers tab showing NULL for agents that
hadn't re-registered since v3.1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Guardian anomaly alerts and SITREP are pure text reasoning — Groq's
llama-3.3-70b-versatile handles them at near-zero cost with lower
latency. Vision Protocol image analysis stays on Claude (claude-opus-
4-8) because Groq has no vision models. Text-only sysinfo snapshots
(no image captured) also move to Groq.
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>