Add heartbeat: reminders and delivered files reach Bolt Assistant
The client never called /desk/report_status, so Bolt's reminders and any files he delivered to this session sat in the server's outbox forever - the same dead-air failure the pet client showed when its heartbeat stopped. Now a heartbeat thread (HEARTBEAT_SECONDS, default 60; 0 disables) reports in, speaks announcements through the assistant's queue when the mic is idle, and downloads the outbox to BOLT_DOWNLOAD_DIR (default ~/Downloads/Bolt) via .part-then-rename, never overwriting. A startup health probe warns loudly when the server refuses the DESK_API_KEY. Also: add the .env.example the README's setup step references (it was missing, so `cp .env.example .env` failed for everyone), and gitignore .claude/ so Claude Code's worktree directory stays out of the repo. Tests: tests/test_heartbeat.py (12) plus announcement tests in tests/test_assistant.py (6); full suite 135 passed. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
a8c7db9520
commit
751d1c8b69
@@ -99,6 +99,25 @@ def main(argv=None) -> int:
|
||||
return 0
|
||||
|
||||
stop = threading.Event()
|
||||
from . import heartbeat
|
||||
|
||||
heartbeat.fetch_server_health()
|
||||
|
||||
def _on_heartbeat(result: dict) -> None:
|
||||
# What the server hands out is popped the moment it is handed over, so
|
||||
# everything goes into the spoken queue — announced when the mic is idle.
|
||||
if result.get("announcement"):
|
||||
assistant.announce(result["announcement"])
|
||||
saved = result.get("saved") or []
|
||||
if saved:
|
||||
names = ", ".join(path.name for path in saved)
|
||||
folder = str(saved[0].parent)
|
||||
assistant.announce(
|
||||
f"Saved {names} to {folder}."
|
||||
if len(saved) <= 3 else f"Saved {len(saved)} files to {folder}.")
|
||||
|
||||
threading.Thread(target=heartbeat.heartbeat_loop, args=(stop, _on_heartbeat),
|
||||
name="bolt-heartbeat", daemon=True).start()
|
||||
try:
|
||||
mic = audio.open_mic(assistant.on_mic_frame)
|
||||
except Exception as exc:
|
||||
|
||||
Reference in New Issue
Block a user