Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion skills/.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"network_info.py": "bd776b619cf7c18d67fe03cb0f0456cf9c4f9bf71475740a233a9ca1e6672fcd",
"notes.py": "7d50d1544ea955f59917a1f0e7902d115e9dbccd3188b641057a55b6a5b2803a",
"notification_reader.py": "681208ae4253dfe549512cce4c722c76ca85f2bbbdb8737e37c026ec9444c972",
"observer_recall.py": "f7084d11c069603d815e648dd765628bfed6d31c1df4ac59f0dac35259aa6fe2",
"observer_recall.py": "5234ab88d151003d8acb00b0e72139d668cfbcd5f091cdda52f247682698a9ff",
"password_generator.py": "f11a917299e14cbd2560111da0bb748cd08792cf715cc4098c64eb62da8c54e3",
"philips_hue.py": "fa831712c39dc6327c84199d8f0aeb09a169a264ce3d936cc337a5c5d6632f7e",
"pilot.py": "f9967890f138bc7a48ae4abc8b4170dca13961b81659ef4e530dc619c1cf90d4",
Expand Down
53 changes: 47 additions & 6 deletions skills/observer_recall.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,30 @@ def _parse_ts(entry: dict) -> datetime | None:
return None


def _fmt_span(entries: list) -> str:
"""Natural opener for how long the snapshots span, e.g. "Over the last
25 minutes" / "In the last couple of minutes". "" if it can't be derived."""
if len(entries) < 2:
return ""
first, last = _parse_ts(entries[0]), _parse_ts(entries[-1])
if not first or not last:
return ""
mins = int((last - first).total_seconds() // 60)
if mins <= 1:
return "In the last minute or so"
if mins < 5:
return "Over the last couple of minutes"
return f"Over the last {mins} minutes"


def _summarise(entries: list) -> str:
"""A compact, human timeline of the entries (oldest→newest)."""
if not entries:
return "nothing recorded in that window."

lines: list[str] = []
last_app = None
last_title_seen = ""
apps_seen: list[str] = []
files_seen: set[str] = set()
ocr_bits: list[str] = []
Expand All @@ -122,6 +139,8 @@ def _summarise(entries: list) -> str:
win = e.get("active_window") or {}
app = win.get("app")
title = (win.get("title") or "").strip()
if title:
last_title_seen = title
if app and app != last_app:
label = app + (f" — {title[:60]}" if title else "")
lines.append(f" {stamp} {label}")
Expand All @@ -136,15 +155,35 @@ def _summarise(entries: list) -> str:
if ocr and len(ocr) > 20:
ocr_bits.append(ocr[:120])

# Conversational prose, not a machine dump. The old format printed
# "You were in: X. / Timeline: / 12:20 X / Files touched: y" — accurate but
# robotic. CODEC should answer like a person who was watching over your
# shoulder. Deterministic templating (no second LLM call) keeps it instant
# and, crucially, keeps it from inventing anything.
out = []
if apps_seen:
out.append("You were in: " + ", ".join(apps_seen[:6]) + ".")
if lines:
out.append("Timeline:\n" + "\n".join(lines[:12]))
span = _fmt_span(entries)
if len(apps_seen) == 1:
body = f"you were in {apps_seen[0]} the whole time"
elif len(apps_seen) == 2:
body = f"you went back and forth between {apps_seen[0]} and {apps_seen[1]}"
else:
shown = apps_seen[:4]
body = ("you moved around a fair bit — "
+ ", ".join(shown[:-1]) + f" and {shown[-1]}")
opener = f"{span}, {body}" if span else body[0].upper() + body[1:]
if last_title_seen:
opener += f". Last thing on screen was \"{last_title_seen[:70]}\""
out.append(opener + ".")
if files_seen:
out.append("Files touched: " + ", ".join(sorted(files_seen)[:8]) + ".")
fl = sorted(files_seen)
if len(fl) == 1:
out.append(f"You touched one file: {fl[0]}.")
else:
out.append(f"You touched {len(fl)} files: " + ", ".join(fl[:6])
+ ("…" if len(fl) > 6 else "") + ".")
if ocr_bits:
out.append('On screen (excerpt): "' + ocr_bits[-1] + '"')
out.append(f"Text on screen included: \"{ocr_bits[-1].strip()}\"")
if not out:
# Entries exist but carry no window/title/OCR/file content — the observer
# is polling but capturing nothing. This is almost always a macOS
Expand Down Expand Up @@ -204,4 +243,6 @@ def run(task: str, context: str = "") -> str:
return (f"Nothing in {span} — the observer keeps roughly the last 10 "
f"minutes, so I can't see that far back.{depth}")

return f"Here's {span} (from CODEC's observer):\n{_summarise(kept)}"
# _summarise already opens conversationally ("Over the last 25 minutes, you
# were in Claude…"), so no robotic "Here's X (from CODEC's observer):" header.
return _summarise(kept)