-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhook_base.py
More file actions
74 lines (61 loc) · 2.27 KB
/
hook_base.py
File metadata and controls
74 lines (61 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Base class for PostToolUse hooks. Reads JSON from stdin, routes to handler."""
import json
import os
import sys
import subprocess
from datetime import datetime
from pathlib import Path
DEBUG_LOG = Path("/tmp/claude_hooks_debug.log")
DEBUG = os.environ.get("CLAUDE_HOOKS_DEBUG", "0") == "1"
def _log(hook_name, msg):
"""Append to debug log if DEBUG enabled."""
if not DEBUG:
return
ts = datetime.now().strftime("%H:%M:%S")
with open(DEBUG_LOG, "a") as f:
f.write(f"[{ts}] {hook_name}: {msg}\n")
def run_hook(check_fn, action_fn, hook_name="unknown"):
"""Standard hook runner pattern.
check_fn(tool_name, tool_input, input_data) -> bool
action_fn(tool_name, tool_input, input_data) -> str (message) or None
"""
try:
input_data = json.load(sys.stdin)
except (json.JSONDecodeError, EOFError):
_log(hook_name, "bad stdin")
print("{}")
return
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
_log(hook_name, f"tool={tool_name} input_keys={list(tool_input.keys())}")
if not check_fn(tool_name, tool_input, input_data):
_log(hook_name, "no match")
print("{}")
return
_log(hook_name, "MATCHED — running action")
message = action_fn(tool_name, tool_input, input_data)
if message:
_log(hook_name, f"result: {message[:100]}")
print(json.dumps({"systemMessage": message}))
else:
_log(hook_name, "action returned None")
print("{}")
def ssh_cmd(cmd, timeout=10):
"""Run command on VPS via SSH. Returns (success, output)."""
sys.path.insert(0, str(Path(__file__).parent))
from vps_config import VPS_SSH
_log("ssh", f"running: ssh {VPS_SSH} {cmd[:80]}")
try:
result = subprocess.run(
["ssh", "-o", "ConnectTimeout=5", VPS_SSH, cmd],
capture_output=True, text=True, timeout=timeout
)
ok = result.returncode == 0
_log("ssh", f"{'ok' if ok else 'FAIL'}: {result.stdout[:80] or result.stderr[:80]}")
return ok, result.stdout.strip()
except subprocess.TimeoutExpired:
_log("ssh", "TIMEOUT")
return False, "SSH timeout"
except Exception as e:
_log("ssh", f"ERROR: {e}")
return False, str(e)