activity-frames 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: activity-frames
3
+ Version: 0.1.0
4
+ Summary: Episodic memory for AI agents: compile raw screen capture into structured, deterministic activity frames.
5
+ Project-URL: Homepage, https://github.com/nossa-y/activity-frames
6
+ Project-URL: Repository, https://github.com/nossa-y/activity-frames
7
+ Project-URL: Issues, https://github.com/nossa-y/activity-frames/issues
8
+ Author: Nossa Iyamu
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent-memory,ai-agents,context,episodic-memory,llm,mcp,screen-activity,screenpipe
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Requires-Python: >=3.9
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7; extra == 'dev'
27
+ Requires-Dist: pyyaml>=6.0; extra == 'dev'
28
+ Provides-Extra: yaml
29
+ Requires-Dist: pyyaml>=6.0; extra == 'yaml'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # activity-frames
33
+
34
+ [![tests](https://github.com/nossa-y/activity-frames/actions/workflows/test.yml/badge.svg)](https://github.com/nossa-y/activity-frames/actions/workflows/test.yml)
35
+ [![PyPI](https://img.shields.io/pypi/v/activity-frames)](https://pypi.org/project/activity-frames/)
36
+ [![Python](https://img.shields.io/pypi/pyversions/activity-frames)](https://pypi.org/project/activity-frames/)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
38
+ [![MCP](https://img.shields.io/badge/MCP-server-6E56CF)](https://modelcontextprotocol.io)
39
+
40
+ **Episodic memory for AI agents.**
41
+
42
+ Your agent can read your code, search the web, and call APIs - but it has no idea what you have been doing for the last 8 hours. It starts every conversation blind.
43
+
44
+ activity-frames gives your agent eyes. It records your screen locally, compiles what it sees into structured **activity frames** (bounded episodes of what you actually did), and serves them to any agent over MCP. No cloud, no LLM in the pipeline, no guessing.
45
+
46
+ ```bash
47
+ pip install activity-frames
48
+ aframes record # start capturing (local, audio off by default)
49
+ aframes context # your last 2 hours, agent-ready
50
+ ```
51
+
52
+ ## What your agent sees
53
+
54
+ Capture stores instants: thousands of snapshot rows a day, each one saying "at 22:53:05, Chrome showed linkedin.com/in/...". Useless to reason over.
55
+
56
+ activity-frames compiles those instants into episodes:
57
+
58
+ ```yaml
59
+ - id: f-0007
60
+ app: Google Chrome
61
+ site: linkedin.com
62
+ start: "20:24:04"
63
+ end: "20:42:11"
64
+ duration_min: 18.0
65
+ pages:
66
+ - {kind: people_search, entity: "cto paris", count: 2}
67
+ - {kind: profile, entity: najmuzzaman}
68
+ - {kind: company, entity: nexdotai}
69
+ input: {keys: 214, clicks: 31}
70
+ evidence: {frame_ids: "99871..100147"}
71
+ ```
72
+
73
+ And into a compact context block for any system prompt:
74
+
75
+ ```
76
+ USER ACTIVITY (2026-07-04, local time; measured from screen capture, no interpretation):
77
+ coverage: 09:12-18:47, 342 active min, 11 apps
78
+ away: 12:30-13:15 (45m)
79
+ - 09:12-09:58 Cursor (46.2m): main.py - api
80
+ - 10:01-10:44 Google Chrome/github.com (41.3m): pull_request:acme/api#412; code:acme/api
81
+ - 20:24-20:42 Google Chrome/linkedin.com (18.0m): people_search:cto paris x2; profile:najmuzzaman; company:nexdotai
82
+ ```
83
+
84
+ Drop that into a prompt and your agent knows your day. A full day compiles in under a second and costs zero tokens.
85
+
86
+ ## Episodic memory, done honestly
87
+
88
+ Agent memory today means conversation memory: what you told the model. Episodic memory is what you actually *did* - and the hard part is representing it without lying.
89
+
90
+ activity-frames enforces a two-tier contract ([SPEC.md](SPEC.md)):
91
+
92
+ - **Tier 1, measured (this package):** everything is derivable by deterministic code from capture data. Sessions, durations, typed page entities, input volume, coverage gaps. Same input, same output, every time. There are no intent labels - code cannot know that 2 profile views + a people search was "prospecting". That is your agent's job; it is an LLM.
93
+ - **Tier 2, inferred (optional extension):** tools that add interpretation must namespace it, tag confidence (`high | medium | speculative`), and link evidence. Facts and guesses can never silently mix.
94
+
95
+ Every frame carries evidence pointers back to raw capture rows. Every document declares its blind spots. What the system did not see, it says it did not see.
96
+
97
+ ## Use it from an agent (MCP)
98
+
99
+ ```bash
100
+ # Claude Code
101
+ claude mcp add activity-frames -- aframes mcp
102
+ ```
103
+
104
+ Any MCP client works: command `aframes`, args `["mcp"]`. Four tools: `get_context`, `get_activity`, `get_day_summary`, `get_patterns` (repetitive-workflow detection: repeated clicks, URL loops, daily habits).
105
+
106
+ ## Use it from Python
107
+
108
+ ```python
109
+ from activity_frames import ActivityLog
110
+
111
+ log = ActivityLog()
112
+ doc = log.day() # today, structured
113
+ doc = log.recent(hours=2) # last 2 hours
114
+ print(log.context(hours=2)) # paste-ready context block
115
+ ```
116
+
117
+ ## Privacy model
118
+
119
+ - **Local only.** Capture, storage, and compilation all happen on your machine. Nothing is uploaded anywhere, ever.
120
+ - **Read-only compilation.** The compiler opens the capture database read-only.
121
+ - **Content opt-in at the output.** Compiled documents carry input *counts* by default; typed-text content appears only if you explicitly pass `--include-text` (this also gates the repeated-text pattern detector). Be clear about the boundary: the capture database itself does store what the recorder sees, locally, so protect it like any sensitive file (FileVault, permissions).
122
+ - **Audio off by default.** `aframes record --audio` to opt in.
123
+ - **No LLM in the compile path.** Compilation is plain code, so no language model, local or remote, is involved in producing memory. The capture engine does run on-device OCR to read what is on screen; that stays on your machine.
124
+ - **You choose what leaves**, when you paste a context block into an agent. Note that window titles and page entities originate from your screen and can contain third-party text; agents should treat them as data, not instructions.
125
+
126
+ ## Architecture
127
+
128
+ ```
129
+ capture engine compiler (this package) your agent
130
+ ------------------ --------------------------- -----------------
131
+ screen snapshots --> sessionize (dwell, gaps, --> MCP tools /
132
+ accessibility tree flicker merge) context blocks /
133
+ input events entity typing (20+ sites) JSON, YAML, md
134
+ (local SQLite) enrichment, patterns
135
+ ```
136
+
137
+ The default capture engine is [screenpipe](https://github.com/mediar-ai/screenpipe): `aframes record` provisions a pinned, MIT-licensed build (v0.3.324), verifies its published sha512 before first run, and manages it for you (see [ACKNOWLEDGMENTS.md](ACKNOWLEDGMENTS.md)). Already running your own recorder? Point `$AFRAMES_DB` at any capture database with compatible `frames` / `ui_events` / `elements` tables and skip `aframes record` entirely.
138
+
139
+ ## CLI
140
+
141
+ ```bash
142
+ aframes record # start capture (--stop / --status / --audio)
143
+ aframes today # today's frames (YAML*)
144
+ aframes day 2026-07-03 -f json # any day, JSON
145
+ aframes context --hours 3 # agent context block
146
+ aframes apps # per-app time ledger
147
+ aframes patterns --days 7 # repetitive workflow detection
148
+ aframes mcp # MCP stdio server
149
+ ```
150
+
151
+ *YAML output uses PyYAML (`pip install "activity-frames[yaml]"`); without it the CLI falls back to JSON.
152
+
153
+ ## Status
154
+
155
+ v0.1. Developed and tested on macOS (Apple Silicon); Intel macOS and Linux x64 engine builds exist but are less exercised - reports welcome. Entity parsers cover LinkedIn, GitHub, Google (Search/Docs/Gmail/Maps/Meet/Calendar), YouTube, X, Instagram, Reddit, Luma, Partiful, Product Hunt, Vercel, Supabase, Stripe, Discord, Notion, Figma, Stack Overflow, Calendly, ChatGPT/Claude, localhost; unknown sites fall back to a generic page reference - always total, never lossy. Issues and parser PRs welcome.
156
+
157
+ Built by [Nossa Iyamu](https://github.com/nossa-y), maker of [Nocta](https://usenocta.com). MIT.
@@ -0,0 +1,17 @@
1
+ activity_frames/__init__.py,sha256=Bbk3bXKB2eevMLpVQFnJcHPsfPmRd-CAIT49PLsaOVU,4206
2
+ activity_frames/_time.py,sha256=3xv7tuAu1Tx5oHPKrl3rbmyEI1yIB0BYXoRDqjIgi5k,2782
3
+ activity_frames/capture.py,sha256=SYdFKyZJ0E_Vljs8Jrfu1uhKU2Uzx0XH97PTXD8yu-w,8530
4
+ activity_frames/cli.py,sha256=OVl_go2FwuqWQ46EIVPQIGfbxuL_J0-naZjIgqVbKcU,6015
5
+ activity_frames/db.py,sha256=XYETa60ul6pP5dWspJsrUalqSAtnN-ksZQZSZD7CXLo,2772
6
+ activity_frames/emit.py,sha256=85k3v_MiBoZEfhd3XzwYWlnz1VjEKFWnmusDA9v5kaU,4456
7
+ activity_frames/enrich.py,sha256=Es0EG4l0bpyQpQjDkNHbagQdxM13XGJ8gEGiqvnQRVQ,12073
8
+ activity_frames/entities.py,sha256=Q6YgYQmNRmC84XileGGd4RyUWPgY7bZrd353XhFl0IA,15264
9
+ activity_frames/frames.py,sha256=wPsyn7t4AjyqAP5htL3Hgexitj2qhKgXBzmpXNlKb48,12204
10
+ activity_frames/mcp_server.py,sha256=uMVX7cEtFM1qGVOJ3xwTwIEXek57Q0rI9p8Mk1mDHJY,9554
11
+ activity_frames/patterns.py,sha256=Fu5P-Oy_jcAUJ-tpceE4ClFkkmRCw-CNFm9xt4_B2v0,8501
12
+ activity_frames/sessionize.py,sha256=VeVvjA56dIVuX951D1hUxk-q6weFv7u2MJ08NAcfa50,11428
13
+ activity_frames-0.1.0.dist-info/METADATA,sha256=6TefRRKfgkq3cfN8KuLwpL43TPnKJRcl4YAg52JUoms,8458
14
+ activity_frames-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
15
+ activity_frames-0.1.0.dist-info/entry_points.txt,sha256=fEKkNTgoEHqxrztFm9ndhtjZl7a6mZf_yAg5GU-rHhg,53
16
+ activity_frames-0.1.0.dist-info/licenses/LICENSE,sha256=jl2_onknQZ2IYcvTN_szF-T6A5ur8ZMM4tXawBVO20g,1068
17
+ activity_frames-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ aframes = activity_frames.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nossa Iyamu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.