maryjscout commited on
Commit
c362ff7
·
verified ·
1 Parent(s): ea56056

Upload jarvis_core/events.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. jarvis_core/events.py +92 -0
jarvis_core/events.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """jarvis_core.events — proactive event engine.
2
+
3
+ Event: {event_id, type, timestamp, source, payload, priority}
4
+ Decision: IGNORE LOG NOTIFY CREATE_TASK EXECUTE_ACTION ASK_USER
5
+ Proactive actions NEVER bypass approvals (see approvals.py).
6
+ """
7
+ import time
8
+ import uuid
9
+
10
+ from .store import get_store, redact
11
+
12
+ COL = "jarvis_events"
13
+ DECISIONS = {"IGNORE", "LOG", "NOTIFY", "CREATE_TASK", "EXECUTE_ACTION", "ASK_USER"}
14
+
15
+ # type -> (decision, min_priority)
16
+ _RULES = {
17
+ "pc.online": ("NOTIFY", 0),
18
+ "pc.offline": ("LOG", 0),
19
+ "telegram.message": ("LOG", 0),
20
+ "n8n.completed": ("LOG", 0),
21
+ "n8n.failed": ("NOTIFY", 0),
22
+ "mission.blocked": ("NOTIFY", 0),
23
+ "task.due": ("EXECUTE_ACTION", 0),
24
+ "job.finished": ("LOG", 0),
25
+ "job.failed": ("NOTIFY", 0),
26
+ "mcp.failed": ("CREATE_TASK", 0),
27
+ "brain failing": ("NOTIFY", 0),
28
+ "service.down": ("NOTIFY", 0),
29
+ "routine.due": ("EXECUTE_ACTION", 0),
30
+ }
31
+
32
+ _notifiers = [] # fn(text) — e.g. Telegram sender
33
+
34
+
35
+ def on_notify(fn):
36
+ _notifiers.append(fn)
37
+
38
+
39
+ def emit(etype, source="system", payload=None, priority=0):
40
+ store = get_store()
41
+ eid = store.add(COL, {
42
+ "event_id": f"ev-{uuid.uuid4().hex[:8]}",
43
+ "type": etype, "timestamp": time.time(), "source": source,
44
+ "payload": {k: redact(v)[:300] for k, v in (payload or {}).items()},
45
+ "priority": priority,
46
+ })
47
+ ev = store.get(COL, eid)
48
+ decision = classify(ev)
49
+ ev["decision"] = decision
50
+ store.set(COL, eid, ev)
51
+ dispatch(ev, decision)
52
+ return ev
53
+
54
+
55
+ def classify(ev):
56
+ rule = _RULES.get(ev.get("type"))
57
+ if not rule:
58
+ return "LOG"
59
+ decision, min_pri = rule
60
+ if ev.get("priority", 0) < min_pri:
61
+ return "LOG"
62
+ return decision
63
+
64
+
65
+ def dispatch(ev, decision):
66
+ text = f"{ev.get('type')} from {ev.get('source')}: " \
67
+ f"{redact(str(ev.get('payload')) )[:200]}"
68
+ if decision == "NOTIFY":
69
+ for fn in _notifiers:
70
+ try:
71
+ fn(f"JARVIS event, sir — {text}")
72
+ except Exception:
73
+ pass
74
+ elif decision == "CREATE_TASK":
75
+ try:
76
+ from . import jobs
77
+ jobs.enqueue("note", {"text": f"auto-task from event: {text}"},
78
+ idempotency_key=ev.get("event_id", ""))
79
+ except Exception:
80
+ pass
81
+ if decision in ("LOG", "NOTIFY", "CREATE_TASK", "EXECUTE_ACTION", "ASK_USER"):
82
+ try:
83
+ from . import audit
84
+ audit.record("system", ev.get("source", "?"), f"event:{ev.get('type')}",
85
+ tool="events", status="SUCCESS", result=text[:200])
86
+ except Exception:
87
+ pass
88
+
89
+
90
+ def recent(limit=10):
91
+ items = get_store().all(COL)
92
+ return sorted(items, key=lambda e: e.get("timestamp", 0), reverse=True)[:limit]