agentcache-core 0.9.9__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.
- agentcache/__init__.py +29 -0
- agentcache/app.py +312 -0
- agentcache/cli.py +346 -0
- agentcache/connect.py +724 -0
- agentcache/core/__init__.py +19 -0
- agentcache/core/audit_log.py +104 -0
- agentcache/core/config.py +51 -0
- agentcache/core/context_builder.py +209 -0
- agentcache/core/graph.py +120 -0
- agentcache/core/image_store.py +111 -0
- agentcache/core/infer.py +142 -0
- agentcache/core/kv_scopes.py +86 -0
- agentcache/core/lessons.py +242 -0
- agentcache/core/llm.py +596 -0
- agentcache/core/memory_store.py +207 -0
- agentcache/core/observation_store.py +576 -0
- agentcache/core/privacy.py +34 -0
- agentcache/core/project_profile.py +625 -0
- agentcache/core/search_service.py +444 -0
- agentcache/core/session_store.py +382 -0
- agentcache/core/slots.py +504 -0
- agentcache/db.py +359 -0
- agentcache/import_data.py +86 -0
- agentcache/legacy.py +94 -0
- agentcache/mcp_stdio.py +141 -0
- agentcache/py.typed +0 -0
- agentcache/replay_import.py +680 -0
- agentcache/routes/__init__.py +29 -0
- agentcache/routes/_deps.py +46 -0
- agentcache/routes/auth.py +68 -0
- agentcache/routes/graph.py +81 -0
- agentcache/routes/health.py +149 -0
- agentcache/routes/mcp.py +614 -0
- agentcache/routes/memories.py +116 -0
- agentcache/routes/migration.py +32 -0
- agentcache/routes/observations.py +253 -0
- agentcache/routes/search.py +80 -0
- agentcache/search.py +935 -0
- agentcache/storage/__init__.py +29 -0
- agentcache/storage/images.py +102 -0
- agentcache/storage/paths.py +116 -0
- agentcache/storage/scopes.py +9 -0
- agentcache/viewer/favicon.svg +1 -0
- agentcache/viewer/index.html +4235 -0
- agentcache/viewer_helpers.py +61 -0
- agentcache/workers.py +192 -0
- agentcache_core-0.9.9.dist-info/METADATA +194 -0
- agentcache_core-0.9.9.dist-info/RECORD +52 -0
- agentcache_core-0.9.9.dist-info/WHEEL +5 -0
- agentcache_core-0.9.9.dist-info/entry_points.txt +2 -0
- agentcache_core-0.9.9.dist-info/licenses/LICENSE +190 -0
- agentcache_core-0.9.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Viewer HTML rendering helpers.
|
|
3
|
+
|
|
4
|
+
Separated from app.py so the factory stays under 150 lines.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import base64
|
|
8
|
+
import os
|
|
9
|
+
import secrets
|
|
10
|
+
|
|
11
|
+
from flask import make_response
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def make_viewer_response(base_dir: str):
|
|
15
|
+
"""
|
|
16
|
+
Read src/viewer/index.html, inject nonce + version + token, set CSP headers.
|
|
17
|
+
|
|
18
|
+
Returns a Flask Response object ready to send to the client.
|
|
19
|
+
Raises an exception if the template file is missing.
|
|
20
|
+
"""
|
|
21
|
+
template_path = os.path.join(base_dir, "viewer", "index.html")
|
|
22
|
+
with open(template_path, "r", encoding="utf-8") as f:
|
|
23
|
+
template = f.read()
|
|
24
|
+
|
|
25
|
+
nonce = (
|
|
26
|
+
base64.urlsafe_b64encode(secrets.token_bytes(16)).decode("utf-8").rstrip("=")
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# D2.2: Never embed the raw AGENTCACHE_SECRET in page source.
|
|
30
|
+
# Replace the placeholder with an empty string — the viewer authenticates
|
|
31
|
+
# via the Authorization header set programmatically after load.
|
|
32
|
+
html = (
|
|
33
|
+
template.replace("__AGENTCACHE_VIEWER_NONCE__", nonce)
|
|
34
|
+
.replace("__AGENTCACHE_VERSION__", "0.9.9")
|
|
35
|
+
.replace("__AGENTCACHE_AUTO_TOKEN__", "")
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
csp = "; ".join(
|
|
39
|
+
[
|
|
40
|
+
"default-src 'none'",
|
|
41
|
+
"base-uri 'none'",
|
|
42
|
+
"frame-ancestors 'self' https://huggingface.co https://*.hf.space",
|
|
43
|
+
"object-src 'none'",
|
|
44
|
+
"form-action 'none'",
|
|
45
|
+
f"script-src 'nonce-{nonce}'",
|
|
46
|
+
"script-src-attr 'none'",
|
|
47
|
+
"style-src 'unsafe-inline'",
|
|
48
|
+
(
|
|
49
|
+
"connect-src 'self' https: http://localhost:* http://127.0.0.1:* "
|
|
50
|
+
"wss: ws://localhost:* ws://127.0.0.1:* wss://localhost:* wss://127.0.0.1:*"
|
|
51
|
+
),
|
|
52
|
+
"img-src 'self' data:",
|
|
53
|
+
"font-src 'self'",
|
|
54
|
+
]
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
res = make_response(html)
|
|
58
|
+
res.headers["Content-Type"] = "text/html; charset=utf-8"
|
|
59
|
+
res.headers["Content-Security-Policy"] = csp
|
|
60
|
+
res.headers["Cache-Control"] = "no-cache"
|
|
61
|
+
return res
|
agentcache/workers.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Background worker threads for agentcache-python.
|
|
3
|
+
|
|
4
|
+
Start all workers via start_background_workers(kv).
|
|
5
|
+
Each worker runs as a daemon thread so it exits automatically when the process dies.
|
|
6
|
+
|
|
7
|
+
C5.1: SIGTERM and SIGINT handlers are registered here to flush the index
|
|
8
|
+
persistence debounce queue and run a WAL checkpoint before exit.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import signal
|
|
13
|
+
import sys
|
|
14
|
+
import threading
|
|
15
|
+
import time
|
|
16
|
+
|
|
17
|
+
from . import legacy
|
|
18
|
+
|
|
19
|
+
# Module-level shutdown flag — set by signal handlers
|
|
20
|
+
_shutting_down = threading.Event()
|
|
21
|
+
|
|
22
|
+
_persistence_ref = None
|
|
23
|
+
_search_svc_ref = None
|
|
24
|
+
_obs_store_ref = None
|
|
25
|
+
_kv_ref = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _shutdown_handler(signum, frame) -> None: # noqa: ARG001
|
|
29
|
+
"""Handle SIGTERM/SIGINT gracefully (C5.1).
|
|
30
|
+
|
|
31
|
+
Steps:
|
|
32
|
+
1. Set the global _shutting_down flag to stop background loops.
|
|
33
|
+
2. Flush the debounce timer and save the index synchronously via SearchService.flush_persist().
|
|
34
|
+
3. Run a WAL checkpoint via StateKV.teardown().
|
|
35
|
+
4. Exit cleanly with code 0.
|
|
36
|
+
"""
|
|
37
|
+
sig_name = signal.Signals(signum).name
|
|
38
|
+
print(f"\n[workers] Received {sig_name} — initiating graceful shutdown...")
|
|
39
|
+
|
|
40
|
+
_shutting_down.set()
|
|
41
|
+
|
|
42
|
+
global _search_svc_ref, _persistence_ref
|
|
43
|
+
if _search_svc_ref is not None:
|
|
44
|
+
try:
|
|
45
|
+
print("[workers] Flushing SearchService persistence...")
|
|
46
|
+
_search_svc_ref.flush_persist()
|
|
47
|
+
print("[workers] SearchService persistence flushed.")
|
|
48
|
+
except Exception as e:
|
|
49
|
+
print(f"[workers] Error flushing SearchService: {e}")
|
|
50
|
+
elif _persistence_ref is not None:
|
|
51
|
+
try:
|
|
52
|
+
print("[workers] Flushing index persistence...")
|
|
53
|
+
_persistence_ref.flush()
|
|
54
|
+
print("[workers] Index persistence flushed.")
|
|
55
|
+
except Exception as e:
|
|
56
|
+
print(f"[workers] Error flushing persistence: {e}")
|
|
57
|
+
|
|
58
|
+
# WAL checkpoint — flush WAL to the main DB file
|
|
59
|
+
global _kv_ref
|
|
60
|
+
if _kv_ref is not None:
|
|
61
|
+
try:
|
|
62
|
+
print("[workers] Running WAL checkpoint...")
|
|
63
|
+
_kv_ref.teardown()
|
|
64
|
+
print("[workers] WAL checkpoint complete.")
|
|
65
|
+
except Exception as e:
|
|
66
|
+
print(f"[workers] Error during WAL checkpoint: {e}")
|
|
67
|
+
|
|
68
|
+
print("[workers] Shutdown complete.")
|
|
69
|
+
sys.exit(0)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _register_signal_handlers() -> None:
|
|
73
|
+
"""Register SIGTERM and SIGINT handlers (C5.1).
|
|
74
|
+
|
|
75
|
+
Skipped if the calling thread is not the main thread, because Python
|
|
76
|
+
only allows signal handlers to be registered from the main thread.
|
|
77
|
+
"""
|
|
78
|
+
if threading.current_thread() is not threading.main_thread():
|
|
79
|
+
return
|
|
80
|
+
try:
|
|
81
|
+
signal.signal(signal.SIGTERM, _shutdown_handler)
|
|
82
|
+
signal.signal(signal.SIGINT, _shutdown_handler)
|
|
83
|
+
print("[workers] Signal handlers registered (SIGTERM, SIGINT).")
|
|
84
|
+
except (OSError, ValueError) as e:
|
|
85
|
+
# Some environments (e.g. Windows without signal support) may raise here
|
|
86
|
+
print(f"[workers] Could not register signal handlers: {e}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _auto_forget_loop(kv) -> None:
|
|
90
|
+
"""Periodically sweep and evict stale observations (configurable via AUTO_FORGET_ENABLED)."""
|
|
91
|
+
time.sleep(10)
|
|
92
|
+
while not _shutting_down.is_set():
|
|
93
|
+
try:
|
|
94
|
+
if os.getenv("AUTO_FORGET_ENABLED") != "false":
|
|
95
|
+
if kv.acquire_lock("auto_forget", lease_seconds=300):
|
|
96
|
+
try:
|
|
97
|
+
print("[scheduler] Running auto_forget sweep...")
|
|
98
|
+
res = legacy.auto_forget(kv, dry_run=False)
|
|
99
|
+
print(f"[scheduler] auto_forget sweep completed: {res}")
|
|
100
|
+
finally:
|
|
101
|
+
kv.release_lock("auto_forget")
|
|
102
|
+
except Exception as e:
|
|
103
|
+
print(f"[scheduler] auto_forget loop error: {e}")
|
|
104
|
+
# Sleep in 10-second chunks so we notice _shutting_down quickly
|
|
105
|
+
for _ in range(360): # 360 × 10s = 1 hour
|
|
106
|
+
if _shutting_down.is_set():
|
|
107
|
+
break
|
|
108
|
+
time.sleep(10)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _rebuild_index(kv) -> None:
|
|
112
|
+
"""Rebuild the BM25/vector index from scratch in a background thread."""
|
|
113
|
+
try:
|
|
114
|
+
if kv.acquire_lock("index_rebuild", lease_seconds=600):
|
|
115
|
+
try:
|
|
116
|
+
from . import app as app_module
|
|
117
|
+
|
|
118
|
+
obs_store = getattr(app_module, "observation_store", None)
|
|
119
|
+
if obs_store is not None:
|
|
120
|
+
count = obs_store.rebuild_index()
|
|
121
|
+
else:
|
|
122
|
+
count = 0
|
|
123
|
+
print(f"[persistence] Rebuild completed: indexed {count} items.")
|
|
124
|
+
finally:
|
|
125
|
+
kv.release_lock("index_rebuild")
|
|
126
|
+
else:
|
|
127
|
+
print("[persistence] Another process is rebuilding the index. Skipping...")
|
|
128
|
+
except Exception as ex:
|
|
129
|
+
print(f"[persistence] Rebuild failed: {ex}")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def start_background_workers(kv, tasks=None) -> None:
|
|
133
|
+
"""Start all background daemon threads and register signal handlers.
|
|
134
|
+
|
|
135
|
+
Called once by create_app() after the DB and indexes are initialised.
|
|
136
|
+
Workers are daemon threads — they die automatically when the main process exits.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
kv: Initialised StateKV instance.
|
|
140
|
+
tasks: Optional list of tasks to run ("index", "forget"). Defaults to running both.
|
|
141
|
+
"""
|
|
142
|
+
global _kv_ref, _persistence_ref, _search_svc_ref, _obs_store_ref
|
|
143
|
+
_kv_ref = kv
|
|
144
|
+
|
|
145
|
+
from . import app as app_module
|
|
146
|
+
|
|
147
|
+
search_svc = getattr(app_module, "search_service", None)
|
|
148
|
+
obs_store = getattr(app_module, "observation_store", None)
|
|
149
|
+
|
|
150
|
+
_search_svc_ref = search_svc
|
|
151
|
+
_obs_store_ref = obs_store
|
|
152
|
+
|
|
153
|
+
if search_svc is not None:
|
|
154
|
+
_persistence_ref = search_svc._persistence
|
|
155
|
+
else:
|
|
156
|
+
_persistence_ref = None
|
|
157
|
+
|
|
158
|
+
# Register graceful shutdown signal handlers (C5.1)
|
|
159
|
+
_register_signal_handlers()
|
|
160
|
+
|
|
161
|
+
if tasks is None or "index" in tasks:
|
|
162
|
+
# Rebuild search index if empty or out of sync (Step 5)
|
|
163
|
+
bm25_size = search_svc.bm25_size if search_svc is not None else 0
|
|
164
|
+
index_empty = bm25_size == 0
|
|
165
|
+
index_in_sync = True
|
|
166
|
+
if not index_empty:
|
|
167
|
+
index_in_sync = legacy.verify_index_sync_on_boot(
|
|
168
|
+
kv, search_service=search_svc
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
if index_empty or not index_in_sync:
|
|
172
|
+
reason = "empty" if index_empty else "out of sync"
|
|
173
|
+
print(
|
|
174
|
+
f"[persistence] Search index is {reason}. Rebuilding in background thread..."
|
|
175
|
+
)
|
|
176
|
+
t_rebuild = threading.Thread(
|
|
177
|
+
target=_rebuild_index,
|
|
178
|
+
args=(kv,),
|
|
179
|
+
daemon=True,
|
|
180
|
+
name="index-rebuild",
|
|
181
|
+
)
|
|
182
|
+
t_rebuild.start()
|
|
183
|
+
|
|
184
|
+
if tasks is None or "forget" in tasks:
|
|
185
|
+
# Auto-forget sweep
|
|
186
|
+
t_forget = threading.Thread(
|
|
187
|
+
target=_auto_forget_loop,
|
|
188
|
+
args=(kv,),
|
|
189
|
+
daemon=True,
|
|
190
|
+
name="auto-forget",
|
|
191
|
+
)
|
|
192
|
+
t_forget.start()
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentcache-core
|
|
3
|
+
Version: 0.9.9
|
|
4
|
+
Summary: A Python REST + WebSocket + MCP cache server for AI agents, backed by SQLite
|
|
5
|
+
Author-email: Yashwant K <yashwantk0303@gmail.com>
|
|
6
|
+
Maintainer-email: Yashwant K <yashwantk0303@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/Yashwant00CR7/agentcache
|
|
9
|
+
Project-URL: Repository, https://github.com/Yashwant00CR7/agentcache.git
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/Yashwant00CR7/agentcache/issues
|
|
11
|
+
Project-URL: Documentation, https://github.com/Yashwant00CR7/agentcache#readme
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: flask>=3.0.0
|
|
26
|
+
Requires-Dist: flask-sock>=0.7.0
|
|
27
|
+
Requires-Dist: requests>=2.31.0
|
|
28
|
+
Requires-Dist: python-dateutil>=2.8.2
|
|
29
|
+
Requires-Dist: huggingface_hub>=0.20.0
|
|
30
|
+
Requires-Dist: websockets>=12.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: hypothesis>=6.100.0; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.3.0; extra == "dev"
|
|
35
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
36
|
+
Provides-Extra: local-embeddings
|
|
37
|
+
Requires-Dist: sentence-transformers>=2.7.0; extra == "local-embeddings"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# agentcache
|
|
41
|
+
|
|
42
|
+
A Python REST + WebSocket + MCP cache server for AI agents, backed by SQLite.
|
|
43
|
+
|
|
44
|
+
`agentcache` gives coding agents (Claude Code, Cursor, Cline, Kiro, Antigravity, …) a persistent, searchable memory of what happened in a project — observations, sessions, long-term memories, and a folder-scoped knowledge graph — with hybrid BM25 + vector search, WebSocket live updates, and a Model Context Protocol (MCP) stdio bridge.
|
|
45
|
+
|
|
46
|
+
- **Server:** Flask + `flask-sock` (REST + WebSocket) on a single port
|
|
47
|
+
- **Storage:** SQLite in WAL mode (zero external services)
|
|
48
|
+
- **Search:** BM25 + optional local embeddings (`sentence-transformers`) or Hugging Face inference
|
|
49
|
+
- **MCP:** stdio bridge so any MCP-compatible client can `observe` / `remember` / `search` natively
|
|
50
|
+
- **CLI:** `agentcache serve|worker|migrate|export|context|connect`
|
|
51
|
+
|
|
52
|
+
Status: **Beta** (`Development Status :: 4 - Beta`). API is stable enough for daily use; internals may still shift before 1.0.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Install
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install agentcache-core
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The package installs as `agentcache-core` on PyPI but imports and runs as `agentcache` (`import agentcache`, `agentcache serve`). The plain `agentcache` name on PyPI belongs to an unrelated project.
|
|
63
|
+
|
|
64
|
+
With optional local embeddings (adds `sentence-transformers`, ~1 GB of model weights on first use):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install "agentcache-core[local-embeddings]"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Requires Python 3.10+.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Quickstart
|
|
75
|
+
|
|
76
|
+
Start the server:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
agentcache serve --port 3111
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Record an observation (any HTTP client works):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
curl -X POST http://localhost:3111/agentcache/observe \
|
|
86
|
+
-H "Content-Type: application/json" \
|
|
87
|
+
-d '{
|
|
88
|
+
"folderPath": "/abs/path/to/project",
|
|
89
|
+
"agentId": "coder-1",
|
|
90
|
+
"text": "Refactored auth into a decorator; see routes/auth.py",
|
|
91
|
+
"type": "refactor"
|
|
92
|
+
}'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Search across a folder:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
curl "http://localhost:3111/agentcache/folder/observations?folderPath=/abs/path/to/project&q=auth"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Health check:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
curl http://localhost:3111/agentcache/health
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Generate a live context file for your IDE:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
cd /abs/path/to/project
|
|
111
|
+
agentcache context --watch # writes .agentcache_context.md and re-writes on change
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Programmatic use
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from agentcache import create_app, StateKV, remember
|
|
120
|
+
|
|
121
|
+
app = create_app() # Flask app, ready for WSGI or app.run()
|
|
122
|
+
kv = StateKV() # direct KV access to the SQLite store
|
|
123
|
+
remember(kv, {"title": "auth decorator", "content": "…", "agentId": "coder-1"})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Top-level exports: `create_app`, `StateKV`, `KV`, `ObservationStore`, `ObservationEvents`, `SearchService`, `remember`, `folder_graph_build`, `health_check`, `run_connect`.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Wire it into your agent
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
agentcache connect claude-code # or: cursor, cline, kiro, antigravity, codex
|
|
134
|
+
agentcache connect --all # detect and wire every supported client
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
This registers the MCP stdio bridge (`agentcache.mcp_stdio`) and, with `--with-hooks`, installs workspace hook blocks that call `/agentcache/observe` on file events.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Auth
|
|
142
|
+
|
|
143
|
+
Set `AGENTCACHE_SECRET` to require a shared secret on write routes:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
export AGENTCACHE_SECRET=your-long-random-string
|
|
147
|
+
agentcache serve
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Clients send it via `Authorization: Bearer <secret>` or `?secret=<secret>`. Unset = open (fine for `localhost`; **do not** expose an unauthenticated instance).
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Deployment
|
|
155
|
+
|
|
156
|
+
`Dockerfile` and `docker-compose.yml` are included. For multi-worker WSGI (Gunicorn + workers), run the server without background threads and use a dedicated worker process:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
agentcache serve --no-workers # web tier
|
|
160
|
+
agentcache worker --tasks=index,forget # sidecar
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Details and the ongoing hardening plan live in [`docs/publishing_roadmap.md`](docs/publishing_roadmap.md).
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Compatibility notes
|
|
168
|
+
|
|
169
|
+
- Routes are dual-mounted at both `/agentcache/*` and `/agentmemory/*` for backward compatibility with the previous package name.
|
|
170
|
+
- `agentcache.legacy` is a thin re-export shim retained for callers that imported from the pre-split module layout. It will be removed in **1.0** — migrate imports to `agentcache.core.*` when convenient. See [`docs/adr/`](docs/adr/) for the split rationale.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Development
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
git clone https://github.com/Yashwant00CR7/agentcache
|
|
178
|
+
cd agentcache
|
|
179
|
+
pip install -e ".[dev,local-embeddings]"
|
|
180
|
+
|
|
181
|
+
pytest # test suite
|
|
182
|
+
ruff check . # lint
|
|
183
|
+
ruff format . # format
|
|
184
|
+
python -m build # build sdist + wheel into dist/
|
|
185
|
+
twine check dist/* # validate metadata before upload
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Links
|
|
191
|
+
|
|
192
|
+
- **Source:** https://github.com/Yashwant00CR7/agentcache
|
|
193
|
+
- **Issues:** https://github.com/Yashwant00CR7/agentcache/issues
|
|
194
|
+
- **License:** MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
agentcache/__init__.py,sha256=3eP0w4CraxlOxO4CXsv9uRl7y7Kg3_vE8ddTyOlpajc,591
|
|
2
|
+
agentcache/app.py,sha256=7nXvkLXgVdyA0nViZYTV9ZR_DABbmiC60ASdz_c9oNc,11229
|
|
3
|
+
agentcache/cli.py,sha256=RfSNZc7EsaTscuMwe7CAYO08Yz0K02uwpU4evevRF2Y,11179
|
|
4
|
+
agentcache/connect.py,sha256=u7_Lta-HBBzJzNYTd7xOx1bSbhiWNp64bJSG9NKMi18,26199
|
|
5
|
+
agentcache/db.py,sha256=udrasWFSrYFUdmIj0mVwvaBiWsIpk1Bvrwy54ifJ_O8,13476
|
|
6
|
+
agentcache/import_data.py,sha256=5d3oPOHqDOeK8rISCb92UiynbujvRY8JbH2i85wUY-w,2886
|
|
7
|
+
agentcache/legacy.py,sha256=fEqJ-nIg8ifu-hKTrMJsygaptAuE63NnompnMAtCJSw,3526
|
|
8
|
+
agentcache/mcp_stdio.py,sha256=xPLSFFPFCJSvSgjpauXJNsKrWXTAbbnHmaR0T_ccqaw,3921
|
|
9
|
+
agentcache/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
agentcache/replay_import.py,sha256=bzFPgY8tadFJB7mOxANV80bTVCliZoMWb8nJGhBIgcw,22354
|
|
11
|
+
agentcache/search.py,sha256=Q1WGbv2-UKTO1rFcS-MHkl0E7ugpxa2TB1MyGLsseHc,29957
|
|
12
|
+
agentcache/viewer_helpers.py,sha256=IA6v_AJDzTCZfGIFXA8pkivzQZ2zvNGwY00DuT65Q04,1951
|
|
13
|
+
agentcache/workers.py,sha256=gGS-yBNQTKa6LeY_AiYIZvyOu7-1IJxA0erWy29B-RY,6805
|
|
14
|
+
agentcache/core/__init__.py,sha256=iC76O4gI-a-tlTMXPgbXFopJrbcxKyPvm_iLC1Elqqw,513
|
|
15
|
+
agentcache/core/audit_log.py,sha256=nqz6jjRxUi-h2aKjbmPS_6LrxRxRaUmQSZ6tmkkP8OM,3065
|
|
16
|
+
agentcache/core/config.py,sha256=QBQ66YuY1zqBFptYSAsBY7kzBJbUVpt574w_zljKI7w,1336
|
|
17
|
+
agentcache/core/context_builder.py,sha256=1sY7DspY_ikyv6c2AWRVgbGirHwYw3iuSy7RB_knOe4,7000
|
|
18
|
+
agentcache/core/graph.py,sha256=UJf_vRCxSZ18uYAXL0TL4ZvGWiKh70Dte2_OAKFzBgs,3946
|
|
19
|
+
agentcache/core/image_store.py,sha256=IxzwMvG1Y1LedPqyv2Cjsokm3UP5NDp1O96hQVcDoRU,3060
|
|
20
|
+
agentcache/core/infer.py,sha256=ddxmn8VZz3KWcDuUpuZDQnWaugt7G6CGdd2x_sZCav0,4288
|
|
21
|
+
agentcache/core/kv_scopes.py,sha256=uMy6_uCPVvpoCXy0lkyjYCLCWMggCJ_BpxtpBqkyB2c,2762
|
|
22
|
+
agentcache/core/lessons.py,sha256=Za0bq_0HrxNurGPIbq5ZzNfZ_L-PnjFWlJ0uv9X4f-8,8083
|
|
23
|
+
agentcache/core/llm.py,sha256=Ls3TBauatnVwvqUlTKJYe4_hXcpPwln4JIvAT79Z9gs,23151
|
|
24
|
+
agentcache/core/memory_store.py,sha256=N5wMd3ihZmJunkVFE1mpOC9x5KxnKMEs2-_STVr8Q3g,6637
|
|
25
|
+
agentcache/core/observation_store.py,sha256=zezGLxPHfEx_KBQdhScOkJAaOlz2nS7hd1KkPDjhSYI,21812
|
|
26
|
+
agentcache/core/privacy.py,sha256=rJ6lt2hh3HLgCcD4QpSyxxEbOJGjSpEby8J7NxSnIWw,1432
|
|
27
|
+
agentcache/core/project_profile.py,sha256=bPDETYup4hHO9q3jUCXhH_04nCKyI4-nOmgGsyKlih0,22046
|
|
28
|
+
agentcache/core/search_service.py,sha256=pZihTPkdkCnvDuvJZ6I7ILRWAQj4mPCHcoX0_Y7BXI4,17775
|
|
29
|
+
agentcache/core/session_store.py,sha256=ClGNvfWwk-FyFCM4PBVYCTWZQKS3sSVp0ObMqa6sTnQ,12300
|
|
30
|
+
agentcache/core/slots.py,sha256=gxew0cUF8Cg7IT_v3K1G93rkr86LRqzX3eoaaIK93xQ,16259
|
|
31
|
+
agentcache/routes/__init__.py,sha256=UkJDqzbrw3bNiPgYwjBinhAsNKiCwLKt1r8x5XV9TEo,907
|
|
32
|
+
agentcache/routes/_deps.py,sha256=K6eQ4tfvjyFvXbIMIk2GIkPpvtxJaKVdcv-CSOqUk70,1328
|
|
33
|
+
agentcache/routes/auth.py,sha256=V55bRbPVdvGWmGyDRUWa1KvqSjPLPqKUBCSPOmA6y1U,2084
|
|
34
|
+
agentcache/routes/graph.py,sha256=3coYit-h5EV_DSpSe63wunFzy1z1DmNADErX6bAOSZ0,2718
|
|
35
|
+
agentcache/routes/health.py,sha256=uyRTY1ErO8QiMGbtrPFvsQSoxt6pz4nPSgBRvUCBvmg,5697
|
|
36
|
+
agentcache/routes/mcp.py,sha256=6N0367oOSYVpCDizyzbgLsbKCcomtWeh2Dx4CxylPSM,24386
|
|
37
|
+
agentcache/routes/memories.py,sha256=OWj0Idk-pmsYRWVQFqvWbi0F5fYMqS29r3y1QLcwDlE,4045
|
|
38
|
+
agentcache/routes/migration.py,sha256=UujsgPUbiARfhTTdN5xf29rkoZQdL4Q6PavxJZhk-P0,899
|
|
39
|
+
agentcache/routes/observations.py,sha256=AVd1G-BAnTJjOCmgjqig2nNXY2ENxmDQ16Ul4CsQ1Ds,8377
|
|
40
|
+
agentcache/routes/search.py,sha256=jFyQqgOkXnMxVT2gwrk5Ri-lbQvVBD918_mv9IswE08,2453
|
|
41
|
+
agentcache/storage/__init__.py,sha256=m2WcbQ0L0lbpY3EL9pW5D8Kptq2KR7Q28F_pMCt9XvQ,937
|
|
42
|
+
agentcache/storage/images.py,sha256=1eclOAEyDfIHclpG293c9TfX_SCsT3c5LonmoHsTb0U,3051
|
|
43
|
+
agentcache/storage/paths.py,sha256=cYLTLgmvrpD0uaJZ_xAjDOBXn1342YRsenUlNpWcpDs,3745
|
|
44
|
+
agentcache/storage/scopes.py,sha256=Zv1W7XdoScjMvfD0WBVtwTMmL2fioga6Z7fdYilGMqQ,174
|
|
45
|
+
agentcache/viewer/favicon.svg,sha256=kAnAwcC26JWar46tMtTYMifvAz2B8dW4eJfwGaZhpmg,249
|
|
46
|
+
agentcache/viewer/index.html,sha256=LcgxQan8roOoiTCxqnj9UzGxTdIBdWxxfe-A4abV32w,182896
|
|
47
|
+
agentcache_core-0.9.9.dist-info/licenses/LICENSE,sha256=dsjUmrQiFqJTP2A_uvogob9xtW3hNqQBvlLaA03MASw,10764
|
|
48
|
+
agentcache_core-0.9.9.dist-info/METADATA,sha256=1Yoc4mTjltjTKM-C07yuCshgQF0GAaSScWr1GUQlGsM,6531
|
|
49
|
+
agentcache_core-0.9.9.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
50
|
+
agentcache_core-0.9.9.dist-info/entry_points.txt,sha256=e_uwu1g4TggwGvTundDtHH5d_SYm_EQ5liaPpwd6N9w,51
|
|
51
|
+
agentcache_core-0.9.9.dist-info/top_level.txt,sha256=l1iTOQb85Sum3076_Ej_JkDWmiB2ZnF07bgHfu4uE3E,11
|
|
52
|
+
agentcache_core-0.9.9.dist-info/RECORD,,
|