Spaces:
Running
Running
| """ | |
| modules/clipboard_intelligence.py - Phase 8 clipboard intelligence | |
| Detects useful content types from clipboard history/current clipboard: | |
| - URLs | |
| - code snippets | |
| - email addresses | |
| - phone numbers | |
| - postal-ish addresses (best-effort heuristic) | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import re | |
| from dataclasses import dataclass | |
| from pathlib import Path | |
| from modules.clipboard_control import _read_text, HIST_PATH | |
| URL_RE = re.compile(r"https?://[^\s]+", re.I) | |
| EMAIL_RE = re.compile(r"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b", re.I) | |
| PHONE_RE = re.compile(r"(?:(?:\+?\d{1,3}[- ]?)?(?:\(?\d{3}\)?[- ]?)?\d{3}[- ]?\d{4,})") | |
| CODE_HINTS = ("def ", "class ", "import ", "from ", "{", "}", "=>", "function ", "SELECT ", "CREATE ", "console.log") | |
| class ClipInsight: | |
| kind: str | |
| preview: str | |
| def _load_history(limit: int = 20) -> list[str]: | |
| if not HIST_PATH.exists(): | |
| return [] | |
| try: | |
| data = json.loads(HIST_PATH.read_text(encoding="utf-8")) | |
| if not isinstance(data, list): | |
| return [] | |
| return [str(item.get("text") or "") for item in data[-limit:]] | |
| except Exception: | |
| return [] | |
| def _detect_one(text: str) -> list[ClipInsight]: | |
| t = (text or "").strip() | |
| if not t: | |
| return [] | |
| out: list[ClipInsight] = [] | |
| urls = URL_RE.findall(t) | |
| if urls: | |
| out.extend(ClipInsight("url", u[:120]) for u in urls[:3]) | |
| mails = EMAIL_RE.findall(t) | |
| if mails: | |
| out.extend(ClipInsight("email", m[:120]) for m in mails[:3]) | |
| phones = PHONE_RE.findall(t) | |
| if phones: | |
| out.extend(ClipInsight("phone", p[:40]) for p in phones[:3]) | |
| if any(h in t for h in CODE_HINTS): | |
| out.append(ClipInsight("code", t[:120].replace("\n", " "))) | |
| # Rough address heuristic: number + street-ish word + comma/city-like structure | |
| if re.search(r"\b\d{1,5}\s+[A-Za-z0-9 .'-]{3,}\b(?:road|rd|street|st|avenue|ave|lane|ln|nagar|society|colony)\b", t, re.I): | |
| out.append(ClipInsight("address", t[:140].replace("\n", " "))) | |
| return out | |
| def inspect_current() -> list[ClipInsight]: | |
| return _detect_one(_read_text() or "") | |
| def inspect_history(limit: int = 20) -> list[ClipInsight]: | |
| seen = set() | |
| out: list[ClipInsight] = [] | |
| for text in reversed(_load_history(limit)): | |
| for insight in _detect_one(text): | |
| key = (insight.kind, insight.preview) | |
| if key in seen: | |
| continue | |
| seen.add(key) | |
| out.append(insight) | |
| return out | |
| def summary() -> str: | |
| items = inspect_current() or inspect_history(20) | |
| if not items: | |
| return "Clipboard intelligence: nothing structured detected." | |
| kinds = {} | |
| for item in items: | |
| kinds[item.kind] = kinds.get(item.kind, 0) + 1 | |
| parts = [f"{k} x{v}" for k, v in sorted(kinds.items())] | |
| preview = items[0].preview | |
| return f"Clipboard intelligence: {', '.join(parts)}. Latest match: {preview}" | |