vek 0.2.0__tar.gz

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,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ matrix:
14
+ os: [ubuntu-latest, windows-latest]
15
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Install package
26
+ run: pip install -e ".[dev]"
27
+
28
+ - name: Run tests
29
+ run: python -m pytest tests/ -v --tb=short
vek-0.2.0/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+ .eggs/
9
+ *.so
10
+ .vek/
11
+ *.db
12
+ .venv/
13
+ venv/
14
+ .mypy_cache/
15
+ .pytest_cache/
16
+ .ruff_cache/
vek-0.2.0/LICENSE ADDED
Binary file
vek-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,167 @@
1
+ Metadata-Version: 2.4
2
+ Name: vek
3
+ Version: 0.2.0
4
+ Summary: Content-addressed execution store for AI agents — git semantics for agent tool calls.
5
+ Project-URL: Repository, https://github.com/AVIDS2/vek
6
+ Author: AVIDS2
7
+ License-Expression: AGPL-3.0-only
8
+ License-File: LICENSE
9
+ Keywords: DAG,agent,content-addressed,execution-history,git,tool-call
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Version Control
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.10
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7; extra == 'dev'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # vek
25
+
26
+ > Content-addressed execution store for AI agents — git semantics for agent tool calls.
27
+
28
+ [![CI](https://github.com/AVIDS2/vek/actions/workflows/ci.yml/badge.svg)](https://github.com/AVIDS2/vek/actions/workflows/ci.yml)
29
+
30
+ Vek is a minimal execution history layer for AI agents. Every tool call's input and output is stored as an immutable, content-addressed blob, forming a traceable, forkable, replayable execution DAG. Framework-agnostic — plug in with a single function call.
31
+
32
+ ## Philosophy
33
+
34
+ **Manage agent execution history like git manages code.**
35
+ Git doesn't care what language you write in. Vek doesn't care what framework your agent runs on.
36
+
37
+ ## Install
38
+
39
+ ```
40
+ pip install vek
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ```python
46
+ import vek
47
+
48
+ vek.init()
49
+
50
+ # record a single tool call
51
+ h = vek.store(tool="search", input={"q": "climate change"}, output={"results": [...]})
52
+
53
+ # session — auto-chained, atomic recording
54
+ with vek.session() as s:
55
+ s.store(tool="search", input=query, output=results)
56
+ s.store(tool="summarise", input=text, output=summary)
57
+
58
+ # auto-record with decorator
59
+ @vek.wrap
60
+ def search(query: str) -> dict:
61
+ return {"results": [...]}
62
+
63
+ # inspect
64
+ node = vek.show(h)
65
+ blob = vek.cat_file(node["input_hash"])
66
+ ```
67
+
68
+ ## CLI
69
+
70
+ ```
71
+ vek init # create .vek/ repository
72
+ vek status # current branch, tip, stats
73
+ vek log [-n 20] [--graph] # execution history / ASCII DAG
74
+ vek show <hash> # inspect a node (short hash OK)
75
+ vek cat-file <hash> # dump raw object content
76
+ vek branch [name] # list or create/switch branches
77
+ vek fork <hash> # fork at a node
78
+ vek merge <branch> # merge branch into current
79
+ vek diff <hash1> <hash2> # structural JSON diff
80
+ vek replay <hash> # replay execution chain
81
+ vek tag [name] [hash] # list or create tags
82
+ vek fsck # verify repository integrity
83
+ vek gc [--dry-run] # remove unreachable objects
84
+ vek export [--format json|jsonl] [--branch name]
85
+ vek import <file> [--format auto|json|jsonl]
86
+ vek --version
87
+ ```
88
+
89
+ ## Python API
90
+
91
+ | Function | Description |
92
+ |----------|-------------|
93
+ | `vek.init()` | Initialise `.vek/` repository |
94
+ | `vek.store(tool, input, output)` | Record one tool call |
95
+ | `vek.session()` | Context manager for atomic batch recording |
96
+ | `vek.async_session()` | Async context manager |
97
+ | `vek.wrap(fn)` | Decorator for auto-recording |
98
+ | `vek.hook(dispatch_fn)` | Wrap a dispatch function |
99
+ | `vek.log(n=20)` | Recent execution history |
100
+ | `vek.log_graph()` | ASCII DAG visualisation |
101
+ | `vek.show(hash)` | Node details with materialised content |
102
+ | `vek.cat_file(hash)` | Raw object bytes |
103
+ | `vek.status()` | Repository summary |
104
+ | `vek.branch(name)` | Create/switch branch |
105
+ | `vek.fork(hash, name)` | Fork at a node |
106
+ | `vek.merge(branch)` | Merge branch (creates multi-parent node) |
107
+ | `vek.diff(h1, h2)` | Structural JSON diff |
108
+ | `vek.replay(hash)` | Full chain from root to hash |
109
+ | `vek.tag(name, hash)` | Lightweight tags |
110
+ | `vek.fsck()` | Integrity verification |
111
+ | `vek.gc()` | Garbage collection |
112
+ | `vek.export()` | Export chains (JSON/JSONL) |
113
+ | `vek.import_data(data)` | Import chains |
114
+
115
+ All hash arguments accept short prefixes (e.g. `h[:8]`).
116
+
117
+ ## Storage Layout
118
+
119
+ ```
120
+ .vek/
121
+ ├── objects/ # (reserved) content-addressed hash objects
122
+ ├── refs/ # (reserved) branch pointer files
123
+ ├── HEAD # current branch
124
+ ├── config # repository configuration
125
+ └── vek.db # SQLite — objects + nodes + refs
126
+ ```
127
+
128
+ ## Data Model
129
+
130
+ ```
131
+ objects: hash | content
132
+ nodes: hash | tool | input_hash | output_hash | parent_hash | timestamp | merge_parent
133
+ refs: name | hash (branches, tags with "tag/" prefix)
134
+ ```
135
+
136
+ ### Object Hashing (git-style)
137
+
138
+ ```
139
+ SHA-256( "blob" + " " + size + "\0" + content ) # input/output blobs
140
+ SHA-256( "node" + " " + size + "\0" + content ) # execution nodes
141
+ ```
142
+
143
+ Same content stored exactly once. Different types with identical content produce different hashes.
144
+
145
+ ### Merge Nodes
146
+
147
+ Merge creates a node with two parents: `parent_hash` (current branch) and `merge_parent` (target branch). Tool is `__merge__`.
148
+
149
+ ## Concurrency
150
+
151
+ - SQLite WAL mode with 5s busy timeout
152
+ - Advisory file lock (`HEAD.lock`) prevents concurrent branch pointer writes
153
+ - Sessions batch all writes in a single transaction (atomic commit/rollback)
154
+
155
+ ## Design Principles
156
+
157
+ - **Content-addressed** — identical content stored once, forever
158
+ - **Immutable** — history cannot be tampered with
159
+ - **Framework-agnostic** — no adapters, no shims
160
+ - **Local-first** — `.vek/` directory, zero external dependencies
161
+ - **Minimal API** — one function call to integrate
162
+ - **Atomic sessions** — all-or-nothing batch writes
163
+ - **Portable** — export/import execution chains as JSON/JSONL
164
+
165
+ ## License
166
+
167
+ [AGPL-3.0](LICENSE)
vek-0.2.0/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # vek
2
+
3
+ > Content-addressed execution store for AI agents — git semantics for agent tool calls.
4
+
5
+ [![CI](https://github.com/AVIDS2/vek/actions/workflows/ci.yml/badge.svg)](https://github.com/AVIDS2/vek/actions/workflows/ci.yml)
6
+
7
+ Vek is a minimal execution history layer for AI agents. Every tool call's input and output is stored as an immutable, content-addressed blob, forming a traceable, forkable, replayable execution DAG. Framework-agnostic — plug in with a single function call.
8
+
9
+ ## Philosophy
10
+
11
+ **Manage agent execution history like git manages code.**
12
+ Git doesn't care what language you write in. Vek doesn't care what framework your agent runs on.
13
+
14
+ ## Install
15
+
16
+ ```
17
+ pip install vek
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```python
23
+ import vek
24
+
25
+ vek.init()
26
+
27
+ # record a single tool call
28
+ h = vek.store(tool="search", input={"q": "climate change"}, output={"results": [...]})
29
+
30
+ # session — auto-chained, atomic recording
31
+ with vek.session() as s:
32
+ s.store(tool="search", input=query, output=results)
33
+ s.store(tool="summarise", input=text, output=summary)
34
+
35
+ # auto-record with decorator
36
+ @vek.wrap
37
+ def search(query: str) -> dict:
38
+ return {"results": [...]}
39
+
40
+ # inspect
41
+ node = vek.show(h)
42
+ blob = vek.cat_file(node["input_hash"])
43
+ ```
44
+
45
+ ## CLI
46
+
47
+ ```
48
+ vek init # create .vek/ repository
49
+ vek status # current branch, tip, stats
50
+ vek log [-n 20] [--graph] # execution history / ASCII DAG
51
+ vek show <hash> # inspect a node (short hash OK)
52
+ vek cat-file <hash> # dump raw object content
53
+ vek branch [name] # list or create/switch branches
54
+ vek fork <hash> # fork at a node
55
+ vek merge <branch> # merge branch into current
56
+ vek diff <hash1> <hash2> # structural JSON diff
57
+ vek replay <hash> # replay execution chain
58
+ vek tag [name] [hash] # list or create tags
59
+ vek fsck # verify repository integrity
60
+ vek gc [--dry-run] # remove unreachable objects
61
+ vek export [--format json|jsonl] [--branch name]
62
+ vek import <file> [--format auto|json|jsonl]
63
+ vek --version
64
+ ```
65
+
66
+ ## Python API
67
+
68
+ | Function | Description |
69
+ |----------|-------------|
70
+ | `vek.init()` | Initialise `.vek/` repository |
71
+ | `vek.store(tool, input, output)` | Record one tool call |
72
+ | `vek.session()` | Context manager for atomic batch recording |
73
+ | `vek.async_session()` | Async context manager |
74
+ | `vek.wrap(fn)` | Decorator for auto-recording |
75
+ | `vek.hook(dispatch_fn)` | Wrap a dispatch function |
76
+ | `vek.log(n=20)` | Recent execution history |
77
+ | `vek.log_graph()` | ASCII DAG visualisation |
78
+ | `vek.show(hash)` | Node details with materialised content |
79
+ | `vek.cat_file(hash)` | Raw object bytes |
80
+ | `vek.status()` | Repository summary |
81
+ | `vek.branch(name)` | Create/switch branch |
82
+ | `vek.fork(hash, name)` | Fork at a node |
83
+ | `vek.merge(branch)` | Merge branch (creates multi-parent node) |
84
+ | `vek.diff(h1, h2)` | Structural JSON diff |
85
+ | `vek.replay(hash)` | Full chain from root to hash |
86
+ | `vek.tag(name, hash)` | Lightweight tags |
87
+ | `vek.fsck()` | Integrity verification |
88
+ | `vek.gc()` | Garbage collection |
89
+ | `vek.export()` | Export chains (JSON/JSONL) |
90
+ | `vek.import_data(data)` | Import chains |
91
+
92
+ All hash arguments accept short prefixes (e.g. `h[:8]`).
93
+
94
+ ## Storage Layout
95
+
96
+ ```
97
+ .vek/
98
+ ├── objects/ # (reserved) content-addressed hash objects
99
+ ├── refs/ # (reserved) branch pointer files
100
+ ├── HEAD # current branch
101
+ ├── config # repository configuration
102
+ └── vek.db # SQLite — objects + nodes + refs
103
+ ```
104
+
105
+ ## Data Model
106
+
107
+ ```
108
+ objects: hash | content
109
+ nodes: hash | tool | input_hash | output_hash | parent_hash | timestamp | merge_parent
110
+ refs: name | hash (branches, tags with "tag/" prefix)
111
+ ```
112
+
113
+ ### Object Hashing (git-style)
114
+
115
+ ```
116
+ SHA-256( "blob" + " " + size + "\0" + content ) # input/output blobs
117
+ SHA-256( "node" + " " + size + "\0" + content ) # execution nodes
118
+ ```
119
+
120
+ Same content stored exactly once. Different types with identical content produce different hashes.
121
+
122
+ ### Merge Nodes
123
+
124
+ Merge creates a node with two parents: `parent_hash` (current branch) and `merge_parent` (target branch). Tool is `__merge__`.
125
+
126
+ ## Concurrency
127
+
128
+ - SQLite WAL mode with 5s busy timeout
129
+ - Advisory file lock (`HEAD.lock`) prevents concurrent branch pointer writes
130
+ - Sessions batch all writes in a single transaction (atomic commit/rollback)
131
+
132
+ ## Design Principles
133
+
134
+ - **Content-addressed** — identical content stored once, forever
135
+ - **Immutable** — history cannot be tampered with
136
+ - **Framework-agnostic** — no adapters, no shims
137
+ - **Local-first** — `.vek/` directory, zero external dependencies
138
+ - **Minimal API** — one function call to integrate
139
+ - **Atomic sessions** — all-or-nothing batch writes
140
+ - **Portable** — export/import execution chains as JSON/JSONL
141
+
142
+ ## License
143
+
144
+ [AGPL-3.0](LICENSE)
@@ -0,0 +1,65 @@
1
+ """vek — 30-second demo.
2
+
3
+ Run:
4
+ pip install -e .
5
+ python examples/demo.py
6
+ """
7
+
8
+ import tempfile, os, vek
9
+
10
+ # --- setup (use a temp dir so it's self-contained) ---
11
+ os.chdir(tempfile.mkdtemp())
12
+ vek.init()
13
+
14
+
15
+ # --- 1. @vek.wrap: one decorator, every call recorded ---
16
+
17
+ @vek.wrap
18
+ def search(query: str) -> dict:
19
+ """Simulate a web search tool."""
20
+ return {"results": [f"Result for '{query}'"]}
21
+
22
+ @vek.wrap
23
+ def summarise(text: str) -> str:
24
+ """Simulate an LLM summariser."""
25
+ return f"Summary: {text[:50]}..."
26
+
27
+ @vek.wrap
28
+ def decide(options: list) -> str:
29
+ """Simulate an agent decision."""
30
+ return options[0] # always pick first
31
+
32
+
33
+ # --- 2. Run an "agent" ---
34
+
35
+ results = search("climate change effects")
36
+ summary = summarise(str(results))
37
+ action = decide(["publish report", "gather more data"])
38
+
39
+
40
+ # --- 3. Inspect what happened ---
41
+
42
+ print("=== Execution Log ===")
43
+ for node in vek.log():
44
+ print(f" {node['hash'][:10]} {node['tool']}")
45
+
46
+ print()
47
+ print("=== Status ===")
48
+ s = vek.status()
49
+ print(f" Branch: {s['branch']}, Nodes: {s['nodes']}, Objects: {s['objects']}")
50
+
51
+ print()
52
+ print("=== Replay (full chain) ===")
53
+ tip = vek.log()[0]["hash"]
54
+ for i, step in enumerate(vek.replay(tip)):
55
+ print(f" [{i}] {step['tool']}")
56
+ print(f" in: {step['input']}")
57
+ print(f" out: {step['output']}")
58
+
59
+ print(f"\n=== Integrity Check ===")
60
+ errors = vek.fsck()
61
+ print(f" {'OK - clean' if not errors else f'{len(errors)} error(s)'}")
62
+
63
+ print(f"\n=== Export (portable JSON) ===")
64
+ data = vek.export()
65
+ print(f" {len(data['nodes'])} nodes, {len(data['objects'])} objects — ready to share")
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "vek"
7
+ version = "0.2.0"
8
+ description = "Content-addressed execution store for AI agents — git semantics for agent tool calls."
9
+ readme = "README.md"
10
+ license = "AGPL-3.0-only"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "AVIDS2" },
14
+ ]
15
+ keywords = ["agent", "git", "content-addressed", "execution-history", "DAG", "tool-call"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "License :: OSI Approved :: GNU Affero General Public License v3",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Software Development :: Version Control",
25
+ "Typing :: Typed",
26
+ ]
27
+
28
+ [project.optional-dependencies]
29
+ dev = ["pytest>=7"]
30
+
31
+ [project.scripts]
32
+ vek = "vek.cli:main"
33
+
34
+ [project.urls]
35
+ Repository = "https://github.com/AVIDS2/vek"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/vek"]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
@@ -0,0 +1,28 @@
1
+ """vek - Content-addressed execution store for AI agents."""
2
+
3
+ from vek.api import (
4
+ init, store, log, branch, fork, diff, replay,
5
+ show, cat_file, status, tag, fsck, gc,
6
+ merge, log_graph, export, import_data,
7
+ )
8
+ from vek.hooks import AsyncSession as _AsyncSession
9
+ from vek.hooks import hook, wrap
10
+ from vek.session import Session as _Session
11
+
12
+ __version__ = "0.2.0"
13
+ __all__ = [
14
+ "init", "store", "log", "branch", "fork", "diff", "replay",
15
+ "show", "cat_file", "status", "tag", "fsck", "gc",
16
+ "merge", "log_graph", "export", "import_data",
17
+ "session", "async_session", "wrap", "hook",
18
+ ]
19
+
20
+
21
+ def session(**kwargs):
22
+ """Open an auto-recording execution session."""
23
+ return _Session(**kwargs)
24
+
25
+
26
+ def async_session(**kwargs):
27
+ """Open an async auto-recording execution session."""
28
+ return _AsyncSession(**kwargs)