feat: RSO observation system, child safety, Discord adapter, Telegram watchdog, email attachments
Core agent improvements: - RSO (Relevance Scoring & Observation) system: interaction_logger, memory_scorer, signal_detector - Memory access logging (memory_access_log table) for relevance scoring; high-signal turn detection - Rich conversation storage for notable turns; compact_conversation truncates long user messages - Task-type classifier (query/action/analysis/creative) for observation tagging - Nested sub-agent visibility: deep delegations now register against the main agent's manager Child safety (Gabriel profile): - child_safety.py: filtering, audit logging, prompt constants for restricted sessions - .kiro/specs/child-safety-profile: requirements, design, tasks specs - GABRIEL_BOT_PROPOSAL.md: initial proposal doc - Reduced context window (10 msgs) and tutor-mode identity for restricted users Telegram adapter: - Polling watchdog: auto-restarts updater if polling drops unexpectedly - get_me() with exponential-backoff retry on NetworkError at startup - Correct stop() ordering: signal watchdog before cancelling tasks Email / Gmail: - send_email: supports file attachments (attachments list param) - get_email: surfaces attachment metadata in response Scheduled tasks / weather: - Remove OpenWeatherMap API calls from morning-weather task; use wttr.in exclusively - New scheduled tasks and scheduler state persistence Discord: - adapters/discord/__init__.py scaffold - discord-plugin: MCP plugin for Claude Code Discord integration (server.ts, skills, config) Infrastructure: - n8n workflow exports (garvis_webhook, content_pipeline variants) - memory_workspace: context, homelab-repo-updates, weekly observation summaries, error logs - UCS C240 migration plan doc - requirements.txt: new deps - .claude/settings.json, fix_hooks.py: hook/permission tuning
This commit is contained in:
@@ -7,9 +7,11 @@ No auto-fixing in this phase - observation only.
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import threading
|
||||
import traceback
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
@@ -127,6 +129,47 @@ class SelfHealingSystem:
|
||||
f"---"
|
||||
)
|
||||
|
||||
# RSO Phase 1: also export to JSONL for structured analysis
|
||||
try:
|
||||
_workspace = Path(getattr(self.memory, 'workspace_dir', './memory_workspace'))
|
||||
_errors_dir = _workspace / "observation" / "errors"
|
||||
_errors_dir.mkdir(parents=True, exist_ok=True)
|
||||
_error_date = error_ctx.timestamp[:10] # YYYY-MM-DD
|
||||
_error_log_path = _errors_dir / f"{_error_date}.jsonl"
|
||||
|
||||
try:
|
||||
_ctx_serializable = json.loads(json.dumps(error_ctx.context, default=str))
|
||||
except Exception:
|
||||
_ctx_serializable = str(error_ctx.context)
|
||||
|
||||
_jsonl_record = {
|
||||
"record_type": "error",
|
||||
"timestamp": error_ctx.timestamp,
|
||||
"error_type": error_ctx.error_type,
|
||||
"message": error_ctx.message[:500],
|
||||
"component": error_ctx.component,
|
||||
"intent": error_ctx.intent,
|
||||
"attempt": attempt,
|
||||
"context": _ctx_serializable,
|
||||
"self_healed": False, # Phase 1: observation only
|
||||
}
|
||||
|
||||
def _write_jsonl(path: Path, record: dict) -> None:
|
||||
try:
|
||||
line = json.dumps(record, default=str, ensure_ascii=False)
|
||||
with open(path, "a", encoding="utf-8") as fh:
|
||||
fh.write(line + "\n")
|
||||
except Exception as exc:
|
||||
print(f"[SelfHealing] JSONL write failed: {exc}")
|
||||
|
||||
threading.Thread(
|
||||
target=_write_jsonl,
|
||||
args=(_error_log_path, _jsonl_record),
|
||||
daemon=True,
|
||||
).start()
|
||||
except Exception as _jsonl_err:
|
||||
print(f"[SelfHealing] JSONL export setup failed: {_jsonl_err}")
|
||||
|
||||
try:
|
||||
self.memory.write_memory(log_entry, daily=True)
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user