The installer wrote the same service list (ollama, homeassistant, mysql,
mariadb, nginx, apache2, docker) onto every host regardless of what it
actually runs, causing false "Service Down" alerts on hosts that never
installed those services. Default is now empty; watch_services should be
set per-host to match what's actually running there.
- Fix 1 (ORDER BY): use table alias t.id to force integer PK ordering;
topic_id alias was causing alphabetical sort, breaking rotation offsets
- Fix 2 (PDOException): wrap INSERT/UPDATE in try/catch in kb_topic_save;
duplicate topic_id now returns clean JSON error instead of HTTP 500
- Fix 3 (XSS/onclick): DEL button passes only t.id; tmDelete looks up
name from _topicsData, removing JSON.stringify from onclick attribute
- Fix 4 (validation): topic_id must contain at least one [a-z0-9] after
sanitization; "@@@" to "___" no longer passes required-field check
- Fix 5 (stale logs): guard comment and log messages updated from 20h to
4h to match the actual 14400s threshold
- Fix 6 (dedup): tmEsc() replaced with existing esc() throughout; removed
duplicate function definition
- Fix 7 (toggle rollback): tmToggle uses inline fetch to revert el.checked
on API failure instead of leaving the UI in wrong state
- Fix 8 (confirm): tmDelete uses openModal confirmation instead of
confirm() dialog, consistent with project live-popup convention
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p87VFec84hNaf2WpvmLrW
- Create kb_generator_topics table (140 topics migrated from hardcoded array)
- kb_intent_generator.php now loads active topics from DB instead of $BATCHES array
- Admin panel: MANAGE TOPICS button opens full topic manager modal
- Browse all 140 topics with search, category, and active/disabled filters
- Inline active toggle per topic (checkbox)
- Add new topic form (topic_id, category, name, description)
- Edit existing topics (all fields)
- Delete topics with confirmation
- Run count display
- Backend API cases: kb_topics, kb_topic_save, kb_topic_delete, kb_topic_toggle
- Topics can now be added/managed without any code changes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p87VFec84hNaf2WpvmLrW
Rich topic library across mathematics (12), sciences (13), history (10),
government/economics, literature, life skills (13), technology (5),
Texas/local (4), national US (3), world affairs (5), human sexuality (2),
astronomy (3), space (2), culture/arts (8), sports (8), food/drink (4),
home/DIY (3), wellness (4), tech continued (3), national continued (2),
world continued (2), medicine (3), math continued (2), communication (2).
Each topic has detailed multi-subtopic descriptions (~200 chars each)
vs prior 8-word descriptions — significantly richer Groq prompts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p87VFec84hNaf2WpvmLrW
- Expanded $BATCHES from 25 to 122 topics across: life skills, personal
finance, Texas/local, US national, world geopolitics, human sexuality
(educational), deep astronomy (15 topics), and space exploration (15 topics)
- Rotation engine: 25 topics per run cycling through all 122 in order;
wraps to topic 1 on cycle complete (~30h full cycle at 6h interval)
- batch_offset tracked in kb_facts for cross-run persistence
- Cron changed from 0 3 * * * to 0 */6 * * * (every 6 hours)
- 20h skip guard reduced to 4h so 6h cron isn't blocked
- max_tokens bumped 3500 → 5000 to prevent JSON truncation errors
- JSON extraction: partial recovery + raw snippet logged on failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p87VFec84hNaf2WpvmLrW
Token budget was too low for 40 intents — responses were truncated mid-JSON,
causing "No JSON array found" on ~88% of batches. Fixes 880 errors/run.
Also adds partial-JSON truncation recovery and raw response debug logging.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p87VFec84hNaf2WpvmLrW
- Always runs when triggered from admin (JARVIS_FORCE_RUN=1 bypasses 20h guard)
- Closing popup stops UI polling but server job continues; toast confirms background run
- History panel at top of popup shows last success time/count + failures from last 7 days
- New intent_gen_history backend case parses cron.log for status summary
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p87VFec84hNaf2WpvmLrW
- 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