refactor(heartbeat): config-driven checks, channel delivery, remove hardcoded values
Heartbeat system overhaul: - Fix email/calendar checks to parse JSON output correctly - Add per-check cooldowns and quiet hours config - Send findings to Discord channel instead of just logging - Auto-reindex KB when stale files detected - Claude CLI called only if HEARTBEAT.md has extra instructions - All settings configurable via config.json heartbeat section Move hardcoded values to config.json: - allowed_tools list (claude_session.py) - Ollama URL/model (memory_search.py now reads ollama.url from config) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,62 +47,50 @@ PERSONALITY_FILES = [
|
||||
]
|
||||
|
||||
# Tools allowed in non-interactive (-p) mode.
|
||||
# NOTE: curl/wget intentionally excluded (data exfiltration risk).
|
||||
# Use WebFetch/WebSearch for safe, read-only web access.
|
||||
# SSH/SCP/rsync restricted to local network (10.0.20.*).
|
||||
ALLOWED_TOOLS = [
|
||||
# Loaded from config.json "allowed_tools" at init, with hardcoded defaults.
|
||||
_DEFAULT_ALLOWED_TOOLS = [
|
||||
"Read", "Edit", "Write", "Glob", "Grep",
|
||||
# Read-only web (safe — cannot POST data)
|
||||
"WebFetch",
|
||||
"WebSearch",
|
||||
# Python scripts
|
||||
"Bash(python3 *)",
|
||||
"Bash(.venv/bin/python3 *)",
|
||||
"Bash(pip *)",
|
||||
"Bash(pytest *)",
|
||||
# Git — both bare commands and commands with arguments
|
||||
"Bash(git add *)",
|
||||
"Bash(git commit *)",
|
||||
"Bash(git push)",
|
||||
"Bash(git push *)",
|
||||
"Bash(git pull)",
|
||||
"Bash(git pull *)",
|
||||
"Bash(git status)",
|
||||
"Bash(git status *)",
|
||||
"Bash(git diff)",
|
||||
"Bash(git diff *)",
|
||||
"Bash(git log)",
|
||||
"Bash(git log *)",
|
||||
"WebFetch", "WebSearch",
|
||||
"Bash(python3 *)", "Bash(.venv/bin/python3 *)",
|
||||
"Bash(pip *)", "Bash(pytest *)",
|
||||
"Bash(git add *)", "Bash(git commit *)",
|
||||
"Bash(git push)", "Bash(git push *)",
|
||||
"Bash(git pull)", "Bash(git pull *)",
|
||||
"Bash(git status)", "Bash(git status *)",
|
||||
"Bash(git diff)", "Bash(git diff *)",
|
||||
"Bash(git log)", "Bash(git log *)",
|
||||
"Bash(git checkout *)",
|
||||
"Bash(git branch)",
|
||||
"Bash(git branch *)",
|
||||
"Bash(git stash)",
|
||||
"Bash(git stash *)",
|
||||
# Node/npm
|
||||
"Bash(npm *)",
|
||||
"Bash(node *)",
|
||||
"Bash(npx *)",
|
||||
# System
|
||||
"Bash(git branch)", "Bash(git branch *)",
|
||||
"Bash(git stash)", "Bash(git stash *)",
|
||||
"Bash(npm *)", "Bash(node *)", "Bash(npx *)",
|
||||
"Bash(systemctl --user *)",
|
||||
"Bash(trash *)",
|
||||
"Bash(mkdir *)",
|
||||
"Bash(cp *)",
|
||||
"Bash(mv *)",
|
||||
"Bash(ls *)",
|
||||
"Bash(cat *)",
|
||||
"Bash(chmod *)",
|
||||
# Docker (local daemon only)
|
||||
"Bash(docker *)",
|
||||
"Bash(docker-compose *)",
|
||||
"Bash(docker compose *)",
|
||||
# SSH — local network only (no external hosts)
|
||||
"Bash(ssh *@10.0.20.*)",
|
||||
"Bash(ssh root@10.0.20.*)",
|
||||
"Bash(trash *)", "Bash(mkdir *)", "Bash(cp *)",
|
||||
"Bash(mv *)", "Bash(ls *)", "Bash(cat *)", "Bash(chmod *)",
|
||||
"Bash(docker *)", "Bash(docker-compose *)", "Bash(docker compose *)",
|
||||
"Bash(ssh *@10.0.20.*)", "Bash(ssh root@10.0.20.*)",
|
||||
"Bash(ssh echo@10.0.20.*)",
|
||||
"Bash(scp *10.0.20.*)",
|
||||
"Bash(rsync *10.0.20.*)",
|
||||
"Bash(scp *10.0.20.*)", "Bash(rsync *10.0.20.*)",
|
||||
]
|
||||
|
||||
|
||||
def _load_allowed_tools() -> list[str]:
|
||||
"""Load allowed_tools from config.json, falling back to defaults."""
|
||||
config_file = PROJECT_ROOT / "config.json"
|
||||
if config_file.exists():
|
||||
try:
|
||||
import json as _json
|
||||
with open(config_file, encoding="utf-8") as f:
|
||||
data = _json.load(f)
|
||||
tools = data.get("allowed_tools")
|
||||
if isinstance(tools, list) and tools:
|
||||
return tools
|
||||
except (ValueError, OSError):
|
||||
pass
|
||||
return list(_DEFAULT_ALLOWED_TOOLS)
|
||||
|
||||
|
||||
ALLOWED_TOOLS = _load_allowed_tools()
|
||||
|
||||
# Environment variables to REMOVE from Claude subprocess
|
||||
# (secrets, tokens, and vars that cause nested-session errors)
|
||||
_ENV_STRIP = {
|
||||
|
||||
Reference in New Issue
Block a user