capsule-trace 0.1.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.
- capsule_trace-0.1.0/PKG-INFO +124 -0
- capsule_trace-0.1.0/README.md +71 -0
- capsule_trace-0.1.0/pyproject.toml +98 -0
- capsule_trace-0.1.0/setup.cfg +4 -0
- capsule_trace-0.1.0/src/capsule_trace/__init__.py +22 -0
- capsule_trace-0.1.0/src/capsule_trace/cli/__init__.py +3 -0
- capsule_trace-0.1.0/src/capsule_trace/cli/__main__.py +5 -0
- capsule_trace-0.1.0/src/capsule_trace/cli/main.py +429 -0
- capsule_trace-0.1.0/src/capsule_trace/cloud/__init__.py +1 -0
- capsule_trace-0.1.0/src/capsule_trace/cloud/uploader.py +108 -0
- capsule_trace-0.1.0/src/capsule_trace/core/__init__.py +4 -0
- capsule_trace-0.1.0/src/capsule_trace/core/context.py +21 -0
- capsule_trace-0.1.0/src/capsule_trace/core/decorator.py +88 -0
- capsule_trace-0.1.0/src/capsule_trace/core/exporter.py +115 -0
- capsule_trace-0.1.0/src/capsule_trace/core/importer.py +81 -0
- capsule_trace-0.1.0/src/capsule_trace/core/models.py +238 -0
- capsule_trace-0.1.0/src/capsule_trace/core/session.py +168 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/__init__.py +1 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/anthropic.py +163 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/autopatch.py +33 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/google.py +95 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/langchain.py +203 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/langgraph.py +121 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/openai.py +204 -0
- capsule_trace-0.1.0/src/capsule_trace/integrations/tools.py +161 -0
- capsule_trace-0.1.0/src/capsule_trace/replay/__init__.py +3 -0
- capsule_trace-0.1.0/src/capsule_trace/replay/cassette.py +44 -0
- capsule_trace-0.1.0/src/capsule_trace/replay/engine.py +357 -0
- capsule_trace-0.1.0/src/capsule_trace/replay/mode.py +29 -0
- capsule_trace-0.1.0/src/capsule_trace/storage/__init__.py +4 -0
- capsule_trace-0.1.0/src/capsule_trace/storage/base.py +30 -0
- capsule_trace-0.1.0/src/capsule_trace/storage/sqlite.py +279 -0
- capsule_trace-0.1.0/src/capsule_trace.egg-info/PKG-INFO +124 -0
- capsule_trace-0.1.0/src/capsule_trace.egg-info/SOURCES.txt +36 -0
- capsule_trace-0.1.0/src/capsule_trace.egg-info/dependency_links.txt +1 -0
- capsule_trace-0.1.0/src/capsule_trace.egg-info/entry_points.txt +2 -0
- capsule_trace-0.1.0/src/capsule_trace.egg-info/requires.txt +39 -0
- capsule_trace-0.1.0/src/capsule_trace.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: capsule-trace
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deterministic replay & time-travel debugger for AI agents
|
|
5
|
+
Author-email: Capsule <sdk@capsule.dev>
|
|
6
|
+
Project-URL: Homepage, https://capsule.dev
|
|
7
|
+
Project-URL: Documentation, https://docs.capsule.dev
|
|
8
|
+
Project-URL: Repository, https://github.com/capsule-dev/capsule
|
|
9
|
+
Project-URL: Issues, https://github.com/capsule-dev/capsule/issues
|
|
10
|
+
Keywords: ai,agents,debugging,replay,llm,observability
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: sqlalchemy<3.0.0,>=2.0.0
|
|
22
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
23
|
+
Requires-Dist: click<9.0.0,>=8.1.0
|
|
24
|
+
Requires-Dist: httpx<1.0.0,>=0.27.0
|
|
25
|
+
Requires-Dist: zstandard>=0.22.0
|
|
26
|
+
Requires-Dist: rich>=13.0.0
|
|
27
|
+
Requires-Dist: ulid-py>=1.1.0
|
|
28
|
+
Provides-Extra: openai
|
|
29
|
+
Requires-Dist: openai>=1.30.0; extra == "openai"
|
|
30
|
+
Provides-Extra: anthropic
|
|
31
|
+
Requires-Dist: anthropic>=0.28.0; extra == "anthropic"
|
|
32
|
+
Provides-Extra: google
|
|
33
|
+
Requires-Dist: google-generativeai>=0.7.0; extra == "google"
|
|
34
|
+
Provides-Extra: langchain
|
|
35
|
+
Requires-Dist: langchain>=0.2.0; extra == "langchain"
|
|
36
|
+
Requires-Dist: langchain-core>=0.2.0; extra == "langchain"
|
|
37
|
+
Provides-Extra: langgraph
|
|
38
|
+
Requires-Dist: langgraph>=0.1.0; extra == "langgraph"
|
|
39
|
+
Provides-Extra: all
|
|
40
|
+
Requires-Dist: openai>=1.30.0; extra == "all"
|
|
41
|
+
Requires-Dist: anthropic>=0.28.0; extra == "all"
|
|
42
|
+
Requires-Dist: google-generativeai>=0.7.0; extra == "all"
|
|
43
|
+
Requires-Dist: langchain>=0.2.0; extra == "all"
|
|
44
|
+
Requires-Dist: langchain-core>=0.2.0; extra == "all"
|
|
45
|
+
Requires-Dist: langgraph>=0.1.0; extra == "all"
|
|
46
|
+
Provides-Extra: dev
|
|
47
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
49
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
|
|
50
|
+
Requires-Dist: hypothesis>=6.100.0; extra == "dev"
|
|
51
|
+
Requires-Dist: mypy>=1.10.0; extra == "dev"
|
|
52
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
53
|
+
|
|
54
|
+
# capsule-trace
|
|
55
|
+
|
|
56
|
+
**Deterministic replay & time-travel debugger for AI agents.**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install capsule-trace
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import capsule_trace
|
|
68
|
+
|
|
69
|
+
@capsule.trace(agent_name="my-agent")
|
|
70
|
+
def run_agent(query: str) -> str:
|
|
71
|
+
from openai import OpenAI
|
|
72
|
+
client = OpenAI()
|
|
73
|
+
response = client.chat.completions.create(
|
|
74
|
+
model="gpt-4o",
|
|
75
|
+
messages=[{"role": "user", "content": query}],
|
|
76
|
+
)
|
|
77
|
+
return response.choices[0].message.content
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
That's it. Every LLM call is now captured automatically.
|
|
81
|
+
|
|
82
|
+
## CLI
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# List captured sessions
|
|
86
|
+
capsule-trace list
|
|
87
|
+
|
|
88
|
+
# Inspect a session step by step
|
|
89
|
+
capsule-trace show ses_01HXYZ123
|
|
90
|
+
|
|
91
|
+
# Export to shareable file
|
|
92
|
+
capsule-trace export ses_01HXYZ123 --output bug.capsule
|
|
93
|
+
|
|
94
|
+
# Replay deterministically
|
|
95
|
+
capsule-trace replay ses_01HXYZ123
|
|
96
|
+
|
|
97
|
+
# Branch from step 7 with different temperature
|
|
98
|
+
capsule-trace branch ses_01HXYZ123 --from-step 7 --modify temperature=0.0
|
|
99
|
+
|
|
100
|
+
# Diff two sessions
|
|
101
|
+
capsule-trace diff ses_01HXYZ ses_01HABC
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Supported Providers
|
|
105
|
+
|
|
106
|
+
| Provider | Status |
|
|
107
|
+
|----------|--------|
|
|
108
|
+
| OpenAI (sync + async) | ✅ Sprint 2 |
|
|
109
|
+
| Anthropic (sync + async) | ✅ Sprint 2 |
|
|
110
|
+
| Google Generative AI | ✅ Sprint 2 |
|
|
111
|
+
| LangChain | Sprint 4 |
|
|
112
|
+
| LangGraph | Sprint 4 |
|
|
113
|
+
|
|
114
|
+
## Disable at Runtime
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
CAPSULE_DISABLE=1 python my_agent.py
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Zero overhead when disabled — checked once at function entry.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
Apache 2.0 — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# capsule-trace
|
|
2
|
+
|
|
3
|
+
**Deterministic replay & time-travel debugger for AI agents.**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install capsule-trace
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import capsule_trace
|
|
15
|
+
|
|
16
|
+
@capsule.trace(agent_name="my-agent")
|
|
17
|
+
def run_agent(query: str) -> str:
|
|
18
|
+
from openai import OpenAI
|
|
19
|
+
client = OpenAI()
|
|
20
|
+
response = client.chat.completions.create(
|
|
21
|
+
model="gpt-4o",
|
|
22
|
+
messages=[{"role": "user", "content": query}],
|
|
23
|
+
)
|
|
24
|
+
return response.choices[0].message.content
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
That's it. Every LLM call is now captured automatically.
|
|
28
|
+
|
|
29
|
+
## CLI
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# List captured sessions
|
|
33
|
+
capsule-trace list
|
|
34
|
+
|
|
35
|
+
# Inspect a session step by step
|
|
36
|
+
capsule-trace show ses_01HXYZ123
|
|
37
|
+
|
|
38
|
+
# Export to shareable file
|
|
39
|
+
capsule-trace export ses_01HXYZ123 --output bug.capsule
|
|
40
|
+
|
|
41
|
+
# Replay deterministically
|
|
42
|
+
capsule-trace replay ses_01HXYZ123
|
|
43
|
+
|
|
44
|
+
# Branch from step 7 with different temperature
|
|
45
|
+
capsule-trace branch ses_01HXYZ123 --from-step 7 --modify temperature=0.0
|
|
46
|
+
|
|
47
|
+
# Diff two sessions
|
|
48
|
+
capsule-trace diff ses_01HXYZ ses_01HABC
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Supported Providers
|
|
52
|
+
|
|
53
|
+
| Provider | Status |
|
|
54
|
+
|----------|--------|
|
|
55
|
+
| OpenAI (sync + async) | ✅ Sprint 2 |
|
|
56
|
+
| Anthropic (sync + async) | ✅ Sprint 2 |
|
|
57
|
+
| Google Generative AI | ✅ Sprint 2 |
|
|
58
|
+
| LangChain | Sprint 4 |
|
|
59
|
+
| LangGraph | Sprint 4 |
|
|
60
|
+
|
|
61
|
+
## Disable at Runtime
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
CAPSULE_DISABLE=1 python my_agent.py
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Zero overhead when disabled — checked once at function entry.
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
Apache 2.0 — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "capsule-trace"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Deterministic replay & time-travel debugger for AI agents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
authors = [{ name = "Capsule", email = "sdk@capsule.dev" }]
|
|
12
|
+
keywords = ["ai", "agents", "debugging", "replay", "llm", "observability"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: Apache Software License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Software Development :: Debuggers",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
22
|
+
]
|
|
23
|
+
requires-python = ">=3.11"
|
|
24
|
+
dependencies = [
|
|
25
|
+
"sqlalchemy>=2.0.0,<3.0.0",
|
|
26
|
+
"pydantic>=2.0.0,<3.0.0",
|
|
27
|
+
"click>=8.1.0,<9.0.0",
|
|
28
|
+
"httpx>=0.27.0,<1.0.0",
|
|
29
|
+
"zstandard>=0.22.0",
|
|
30
|
+
"rich>=13.0.0",
|
|
31
|
+
"ulid-py>=1.1.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
openai = ["openai>=1.30.0"]
|
|
36
|
+
anthropic = ["anthropic>=0.28.0"]
|
|
37
|
+
google = ["google-generativeai>=0.7.0"]
|
|
38
|
+
langchain = ["langchain>=0.2.0", "langchain-core>=0.2.0"]
|
|
39
|
+
langgraph = ["langgraph>=0.1.0"]
|
|
40
|
+
all = [
|
|
41
|
+
"openai>=1.30.0",
|
|
42
|
+
"anthropic>=0.28.0",
|
|
43
|
+
"google-generativeai>=0.7.0",
|
|
44
|
+
"langchain>=0.2.0",
|
|
45
|
+
"langchain-core>=0.2.0",
|
|
46
|
+
"langgraph>=0.1.0",
|
|
47
|
+
]
|
|
48
|
+
dev = [
|
|
49
|
+
"pytest>=8.0.0",
|
|
50
|
+
"pytest-asyncio>=0.23.0",
|
|
51
|
+
"pytest-cov>=5.0.0",
|
|
52
|
+
"hypothesis>=6.100.0",
|
|
53
|
+
"mypy>=1.10.0",
|
|
54
|
+
"ruff>=0.4.0",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[project.scripts]
|
|
58
|
+
capsule-trace = "capsule_trace.cli:main"
|
|
59
|
+
|
|
60
|
+
[project.urls]
|
|
61
|
+
Homepage = "https://capsule.dev"
|
|
62
|
+
Documentation = "https://docs.capsule.dev"
|
|
63
|
+
Repository = "https://github.com/capsule-dev/capsule"
|
|
64
|
+
Issues = "https://github.com/capsule-dev/capsule/issues"
|
|
65
|
+
|
|
66
|
+
[tool.setuptools.packages.find]
|
|
67
|
+
where = ["src"]
|
|
68
|
+
include = ["capsule_trace*"]
|
|
69
|
+
|
|
70
|
+
[tool.ruff]
|
|
71
|
+
line-length = 100
|
|
72
|
+
target-version = "py311"
|
|
73
|
+
|
|
74
|
+
[tool.ruff.lint]
|
|
75
|
+
select = ["E", "F", "W", "I", "N", "UP", "B", "C4", "SIM", "TCH", "RET"]
|
|
76
|
+
ignore = ["E501"]
|
|
77
|
+
|
|
78
|
+
[tool.mypy]
|
|
79
|
+
python_version = "3.11"
|
|
80
|
+
strict = true
|
|
81
|
+
ignore_missing_imports = true
|
|
82
|
+
|
|
83
|
+
[tool.pytest.ini_options]
|
|
84
|
+
asyncio_mode = "auto"
|
|
85
|
+
testpaths = ["tests"]
|
|
86
|
+
addopts = "-v --tb=short"
|
|
87
|
+
|
|
88
|
+
[tool.coverage.run]
|
|
89
|
+
source = ["capsule_trace"]
|
|
90
|
+
branch = true
|
|
91
|
+
|
|
92
|
+
[tool.coverage.report]
|
|
93
|
+
exclude_lines = [
|
|
94
|
+
"pragma: no cover",
|
|
95
|
+
"if TYPE_CHECKING:",
|
|
96
|
+
"raise NotImplementedError",
|
|
97
|
+
"@overload",
|
|
98
|
+
]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Capsule — Deterministic replay & time-travel debugger for AI agents."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from capsule_trace.core.decorator import trace
|
|
8
|
+
from capsule_trace.core.session import Session, get_current_session
|
|
9
|
+
|
|
10
|
+
__version__ = "0.1.0"
|
|
11
|
+
__all__ = ["trace", "Session", "get_current_session", "last_session_path"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def last_session_path() -> Path | None:
|
|
15
|
+
"""Return the path of the most recently saved .capsule file, or None."""
|
|
16
|
+
candidates: list[Path] = []
|
|
17
|
+
for search_dir in (Path.home() / ".capsule", Path.cwd()):
|
|
18
|
+
if search_dir.is_dir():
|
|
19
|
+
candidates.extend(search_dir.glob("*.capsule"))
|
|
20
|
+
if not candidates:
|
|
21
|
+
return None
|
|
22
|
+
return max(candidates, key=lambda p: p.stat().st_mtime)
|