-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathhud_state.py
More file actions
123 lines (105 loc) · 3.41 KB
/
Copy pathhud_state.py
File metadata and controls
123 lines (105 loc) · 3.41 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""HUD state management for CodingBuddy statusLine (#1087, #1326).
Manages ~/.codingbuddy/hud-state.json shared between hooks.
Uses fcntl.flock() for file-level locking on every IO operation.
"""
import json
import os
from datetime import datetime, timezone
from typing import Any, Dict
# Default values for extended schema fields (#1326).
_EXTENDED_DEFAULTS: Dict[str, Any] = {
"phase": "ready",
"focus": None,
"executionStrategy": None,
"councilStatus": None,
"blockerCount": 0,
"lastHandoff": None,
}
try:
import fcntl
HAS_FCNTL = True
except ImportError:
HAS_FCNTL = False
DEFAULT_STATE_FILE = os.path.join(
os.environ.get(
"CLAUDE_PLUGIN_DATA",
os.path.join(os.path.expanduser("~"), ".codingbuddy"),
),
"hud-state.json",
)
def read_hud_state(
state_file: str = DEFAULT_STATE_FILE,
*,
fill_defaults: bool = False,
) -> Dict[str, Any]:
"""Read HUD state from JSON file with shared lock.
Args:
state_file: Path to the state JSON file.
fill_defaults: When True, back-fill missing extended-schema keys
with their defaults so callers always see the full schema.
Returns empty dict on any error (missing file, parse error).
"""
try:
with open(state_file, "r", encoding="utf-8") as f:
if HAS_FCNTL:
fcntl.flock(f.fileno(), fcntl.LOCK_SH)
data: Dict[str, Any] = json.load(f)
except (json.JSONDecodeError, OSError):
return {}
if fill_defaults:
for key, default in _EXTENDED_DEFAULTS.items():
data.setdefault(key, default)
return data
def init_hud_state(
session_id: str,
version: str,
state_file: str = DEFAULT_STATE_FILE,
) -> None:
"""Initialize HUD state for a new session.
Creates parent directory if needed. Overwrites existing state.
"""
now = datetime.now(timezone.utc).isoformat()
data: Dict[str, Any] = {
"sessionStartTimestamp": now,
"sessionId": session_id,
"version": version,
"currentMode": None,
"activeAgent": None,
# Extended schema (#1326)
"phase": "ready",
"focus": None,
"executionStrategy": None,
"councilStatus": None,
"blockerCount": 0,
"lastHandoff": None,
"updatedAt": now,
}
_locked_write(state_file, data)
def update_hud_state(
state_file: str = DEFAULT_STATE_FILE,
**kwargs: Any,
) -> None:
"""Update HUD state by merging kwargs into existing state.
Atomic read-modify-write under a single exclusive lock.
Silently no-ops on error.
"""
try:
os.makedirs(os.path.dirname(state_file), mode=0o700, exist_ok=True)
with open(state_file, "r+", encoding="utf-8") as f:
if HAS_FCNTL:
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
data = json.load(f)
data.update(kwargs)
data["updatedAt"] = datetime.now(timezone.utc).isoformat()
f.seek(0)
f.truncate()
json.dump(data, f)
except (OSError, json.JSONDecodeError):
pass
def _locked_write(state_file: str, data: Dict[str, Any]) -> None:
"""Write state file with exclusive lock."""
os.makedirs(os.path.dirname(state_file), mode=0o700, exist_ok=True)
with open(state_file, "w", encoding="utf-8") as f:
if HAS_FCNTL:
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
json.dump(data, f)