synapse-memory-engine 1.3.0__tar.gz → 1.4.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.
- synapse_memory_engine-1.4.0/PKG-INFO +165 -0
- synapse_memory_engine-1.4.0/README.md +116 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/pyproject.toml +1 -1
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/setup.py +4 -3
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/__init__.py +29 -1
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/api/fastapi_server.py +221 -16
- synapse_memory_engine-1.4.0/synapse_memory/client.py +250 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/auth.py +3 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/embedder.py +14 -6
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/embedding_provider.py +10 -2
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/knapsack_packer.py +13 -3
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/migrations.py +130 -1
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/pgvector_db.py +249 -29
- synapse_memory_engine-1.4.0/synapse_memory/core/run_trace_store.py +547 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/sqlite_db.py +1 -0
- synapse_memory_engine-1.4.0/synapse_memory/runtime.py +540 -0
- synapse_memory_engine-1.4.0/synapse_memory_engine.egg-info/PKG-INFO +165 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory_engine.egg-info/SOURCES.txt +12 -0
- synapse_memory_engine-1.4.0/tests/test_agent_run_api.py +160 -0
- synapse_memory_engine-1.4.0/tests/test_client_retry_policy.py +116 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_db_role_provisioning.py +100 -2
- synapse_memory_engine-1.4.0/tests/test_developer_relevance_scoring.py +108 -0
- synapse_memory_engine-1.4.0/tests/test_developer_review_packet.py +57 -0
- synapse_memory_engine-1.4.0/tests/test_f17_provider_dimension.py +106 -0
- synapse_memory_engine-1.4.0/tests/test_f18_pgvector_3072.py +114 -0
- synapse_memory_engine-1.4.0/tests/test_first_run_http_e2e.py +154 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_helm_chart.py +19 -7
- synapse_memory_engine-1.4.0/tests/test_knapsack_score_precision.py +55 -0
- synapse_memory_engine-1.4.0/tests/test_longmemeval_benchmark.py +142 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_migrations.py +19 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_p1_contract_regressions.py +12 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_pgvector_integration.py +77 -0
- synapse_memory_engine-1.4.0/tests/test_retrieval_baseline_benchmark.py +247 -0
- synapse_memory_engine-1.4.0/tests/test_run_trace_store.py +202 -0
- synapse_memory_engine-1.4.0/tests/test_runtime.py +280 -0
- synapse_memory_engine-1.3.0/PKG-INFO +0 -75
- synapse_memory_engine-1.3.0/README.md +0 -26
- synapse_memory_engine-1.3.0/synapse_memory/client.py +0 -127
- synapse_memory_engine-1.3.0/synapse_memory_engine.egg-info/PKG-INFO +0 -75
- synapse_memory_engine-1.3.0/tests/test_f17_provider_dimension.py +0 -43
- synapse_memory_engine-1.3.0/tests/test_f18_pgvector_3072.py +0 -69
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/setup.cfg +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/cli/synapse_cli.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/__init__.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/decay_engine.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/deduplicator.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/encryption.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/hybrid_search.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/memory_manager.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/observability.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/pruner.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/core/rate_limiter.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/examples/langchain_integration.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/examples/llamaindex_integration.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/integrations/__init__.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/integrations/langchain.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/integrations/llamaindex.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/main.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory/py.typed +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory_engine.egg-info/dependency_links.txt +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory_engine.egg-info/entry_points.txt +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory_engine.egg-info/requires.txt +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/synapse_memory_engine.egg-info/top_level.txt +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_auth_multitenancy.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_backup_restore_drill.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_decay.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_deduplicator.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_deterministic_embedding.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_encryption.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_f01_auth_escalation.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_f02_f07_probes.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_f05_f06_data_at_rest.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_f10_f15_hardening.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_integration.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_knapsack.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_langchain.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_llamaindex.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_load_resilience.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_max_record_limit.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_p0_safety_regressions.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_pgvector.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_phase_cd.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_pruner.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_rate_limit.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_required_auth_gateway.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_retrieval_eval.py +0 -0
- {synapse_memory_engine-1.3.0 → synapse_memory_engine-1.4.0}/tests/test_synapse.py +0 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: synapse-memory-engine
|
|
3
|
+
Version: 1.4.0
|
|
4
|
+
Summary: Production-grade active RAG & cognitive memory engine with multi-tenancy, pgvector HNSW indexing, semantic deduplication, decay-based pruning, and token-aware context packing.
|
|
5
|
+
Home-page: https://github.com/721189/Synapse-Memory
|
|
6
|
+
Author: Synapse Cognitive Systems
|
|
7
|
+
Author-email: Synapse Cognitive Systems <singhshivam20009@gmail.com>
|
|
8
|
+
Project-URL: Homepage, https://github.com/721189/Synapse-Memory
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/721189/Synapse-Memory/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/721189/Synapse-Memory#readme
|
|
11
|
+
Project-URL: Repository, https://github.com/721189/Synapse-Memory.git
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: fastapi>=0.115.0
|
|
15
|
+
Requires-Dist: pydantic>=2.10.0
|
|
16
|
+
Requires-Dist: uvicorn>=0.34.0
|
|
17
|
+
Requires-Dist: cryptography>=42.0.0
|
|
18
|
+
Requires-Dist: requests>=2.31.0
|
|
19
|
+
Requires-Dist: numpy>=1.26.0
|
|
20
|
+
Requires-Dist: urllib3>=2.8.0
|
|
21
|
+
Provides-Extra: local-models
|
|
22
|
+
Requires-Dist: sentence-transformers>=5.0.0; extra == "local-models"
|
|
23
|
+
Provides-Extra: pgvector
|
|
24
|
+
Requires-Dist: psycopg2-binary>=2.9.9.1; extra == "pgvector"
|
|
25
|
+
Requires-Dist: pgvector>=0.4.0; extra == "pgvector"
|
|
26
|
+
Provides-Extra: redis
|
|
27
|
+
Requires-Dist: redis>=5.0.0; extra == "redis"
|
|
28
|
+
Provides-Extra: langchain
|
|
29
|
+
Requires-Dist: langchain-core>=0.3.0; extra == "langchain"
|
|
30
|
+
Provides-Extra: llamaindex
|
|
31
|
+
Requires-Dist: llama-index-core>=0.13.0; extra == "llamaindex"
|
|
32
|
+
Provides-Extra: all
|
|
33
|
+
Requires-Dist: sentence-transformers>=5.0.0; extra == "all"
|
|
34
|
+
Requires-Dist: psycopg2-binary>=2.9.9.1; extra == "all"
|
|
35
|
+
Requires-Dist: pgvector>=0.4.0; extra == "all"
|
|
36
|
+
Requires-Dist: langchain-core>=0.3.0; extra == "all"
|
|
37
|
+
Requires-Dist: llama-index-core>=0.13.0; extra == "all"
|
|
38
|
+
Requires-Dist: redis>=5.0.0; extra == "all"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: flake8>=7.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: mypy>=1.13.0; extra == "dev"
|
|
42
|
+
Requires-Dist: bandit>=1.8.0; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
44
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
45
|
+
Requires-Dist: types-requests>=2.32.0; extra == "dev"
|
|
46
|
+
Dynamic: author
|
|
47
|
+
Dynamic: home-page
|
|
48
|
+
Dynamic: requires-python
|
|
49
|
+
|
|
50
|
+
# Synapse Memory Python SDK
|
|
51
|
+
|
|
52
|
+
Python distribution for the Synapse Memory engine. The distribution name is `synapse-memory-engine`; the import package is `synapse_memory`.
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- **Encrypted SQLite Storage**: Fernet AES-128-CBC with HMAC-SHA256 authenticated encryption at rest.
|
|
57
|
+
- **Dynamic Programming Knapsack Packing**: Exact 0/1 Knapsack optimizer for packing high-relevance memories into strict token envelopes.
|
|
58
|
+
- **Ebbinghaus Decay Engine**: Continuous temporal decay with positive/negative reinforcement factors.
|
|
59
|
+
- **Semantic Deduplication**: Dual lexical Jaccard and dense cosine similarity detection to prevent node fragmentation.
|
|
60
|
+
- **Hybrid Retrieval**: BM25 sparse lexical ranking fused with dense vector embeddings via Reciprocal Rank Fusion (RRF).
|
|
61
|
+
- **Framework Integrations**: True drop-in adapters for LangChain (`BaseMemory`) and LlamaIndex (`BaseMemory`).
|
|
62
|
+
- **Agent reliability runtime**: Opt-in run budgets, repeated failed-call blocking, versioned event serialization, and persistent tenant-scoped run traces.
|
|
63
|
+
- **Opt-in agent run guard**: Bounded steps/tool calls, cooperative deadlines, repeated-failure blocking, and privacy-minimized in-memory events.
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install synapse-memory-engine # from PyPI
|
|
69
|
+
# or, from a checkout of this repository:
|
|
70
|
+
pip install -e .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## REST client quick start
|
|
74
|
+
|
|
75
|
+
Use `SynapseClient` when connecting an application to a running Synapse API:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from synapse_memory import SynapseClient, SynapseError
|
|
79
|
+
|
|
80
|
+
with SynapseClient(
|
|
81
|
+
"http://127.0.0.1:8008",
|
|
82
|
+
api_key="syn_live_your_key",
|
|
83
|
+
tenant_id="your-tenant",
|
|
84
|
+
) as client:
|
|
85
|
+
created = client.create_memory("Customer selected the annual plan.", category="fact")
|
|
86
|
+
result = client.retrieve("Which plan did the customer select?")
|
|
87
|
+
print(created.id, result.fused_context)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The client automatically retries idempotent `GET`/`HEAD`/`OPTIONS` requests and honours `Retry-After`. It does not automatically replay `POST` requests (including `/query`, which updates access metadata) after an ambiguous failure; callers should reconcile the operation before manually retrying, or provide their own idempotency mechanism.
|
|
91
|
+
|
|
92
|
+
## Opt-in Python run guard
|
|
93
|
+
|
|
94
|
+
The runtime only guards tool calls explicitly routed through `SynapseRun`; it does not intercept arbitrary framework calls. Events stay in memory until the application exports or persists them. Event records contain tool names and keyed argument fingerprints, not raw arguments, prompts, tool results, or exception messages.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from synapse_memory import RunPolicy, SynapseRun
|
|
98
|
+
|
|
99
|
+
policy = RunPolicy(
|
|
100
|
+
max_steps=12,
|
|
101
|
+
max_tool_calls=8,
|
|
102
|
+
timeout_seconds=30,
|
|
103
|
+
max_repeated_failures=2,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
with SynapseRun(policy=policy) as run:
|
|
107
|
+
customer = run.call_tool(
|
|
108
|
+
"lookup_customer",
|
|
109
|
+
{"customer_id": "cust_123"},
|
|
110
|
+
lookup_customer, # callable accepts arguments as keyword arguments
|
|
111
|
+
)
|
|
112
|
+
run.record_step() # account for non-tool work
|
|
113
|
+
print(customer)
|
|
114
|
+
|
|
115
|
+
# Inspect metadata-only events after the context exits.
|
|
116
|
+
for event in run.events:
|
|
117
|
+
print(event.event_type.value, event.reason, event.tool_fingerprint)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Limits are checked before admitting each step/tool call. The deadline is cooperative: a synchronous tool already in progress cannot be forcibly interrupted. A run guard is not a sandbox, does not authorize tools, does not intercept unwrapped calls, or enforce provider token/cost budgets. Repeated-call blocking applies after the configured number of consecutive failures for the same tool and equivalent JSON arguments; a successful call resets that failure count. No automatic retries are performed.
|
|
121
|
+
|
|
122
|
+
## Persistent run traces and retrieval provenance
|
|
123
|
+
|
|
124
|
+
Trace persistence is an explicit opt-in operation. The event contract is versioned (schema_version=1) and records only run lifecycle metadata, tool name/status, a per-run keyed argument fingerprint, typed failure reasons, and retrieval evidence. It does not record prompts, raw tool arguments, tool results, memory content, or the retrieval query. Retrieval evidence must be supplied by the application from its own retrieval/packing pipeline; Synapse does not silently instrument arbitrary framework calls or automatically attach every /query response to a run.
|
|
125
|
+
|
|
126
|
+
To persist a completed SynapseRun, use a key with agent-runs:read and agent-runs:write scopes, plus agent-runs:delete only when deletion is needed:
|
|
127
|
+
|
|
128
|
+
~~~python
|
|
129
|
+
from synapse_memory import RunPolicy, SynapseClient, SynapseRun
|
|
130
|
+
|
|
131
|
+
with SynapseRun(policy=RunPolicy(max_steps=12, max_tool_calls=8)) as run:
|
|
132
|
+
# The app can query Synapse or another retriever here.
|
|
133
|
+
candidates = [
|
|
134
|
+
{"id": "memory_01", "relevance_score": 0.91, "token_cost": 18},
|
|
135
|
+
{"id": "memory_02", "relevance_score": 0.43, "token_cost": 16},
|
|
136
|
+
]
|
|
137
|
+
packed_ids = ["memory_01"]
|
|
138
|
+
run.record_memory_retrieval(candidates, packed_memory_ids=packed_ids)
|
|
139
|
+
answer = run.call_tool("lookup_customer", {"customer_id": "cust_123"}, lookup_customer)
|
|
140
|
+
|
|
141
|
+
with SynapseClient(
|
|
142
|
+
"https://your-synapse-api",
|
|
143
|
+
api_key="syn_live_your_key",
|
|
144
|
+
tenant_id="your-tenant",
|
|
145
|
+
) as client:
|
|
146
|
+
receipt = client.upload_agent_run(run)
|
|
147
|
+
print(receipt["events_inserted"], receipt["events_deduplicated"])
|
|
148
|
+
~~~
|
|
149
|
+
|
|
150
|
+
The client uploads the run's ordered events after the run ends. Stable event IDs make retrying a partially completed upload idempotent. Event records are tenant-bound by the authenticated API key; a caller-supplied tenant field in an event is rejected. Available endpoints are documented in the API contract (../../docs/api-reference.md). Each tenant can list and delete only its own trace records; event pages are bounded and ordered by sequence number.
|
|
151
|
+
|
|
152
|
+
This first persistence layer is not yet a live streaming sink, a full observability dashboard, an outcome verifier, or a retention scheduler. Deployments must apply schema migration v6 before starting a PostgreSQL least-privilege runtime role. Use the API's deletion endpoint or a separately configured retention job to remove stored runs.
|
|
153
|
+
|
|
154
|
+
## Testing
|
|
155
|
+
|
|
156
|
+
From the repository root:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pip install -e "sdk/python[pgvector,langchain,llamaindex,dev]"
|
|
160
|
+
PYTHONPATH=sdk/python pytest sdk/python/tests -v
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Database-gated tests require a disposable PostgreSQL/pgvector database and explicitly documented environment flags. Passing the offline suite alone is not production verification.
|
|
164
|
+
|
|
165
|
+
**Licence:** proprietary. Installation does not grant unrestricted usage or deployment rights; obtain written permission under [`../../LICENSE`](../../LICENSE) before using this package outside the permissions granted by the copyright holder.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Synapse Memory Python SDK
|
|
2
|
+
|
|
3
|
+
Python distribution for the Synapse Memory engine. The distribution name is `synapse-memory-engine`; the import package is `synapse_memory`.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Encrypted SQLite Storage**: Fernet AES-128-CBC with HMAC-SHA256 authenticated encryption at rest.
|
|
8
|
+
- **Dynamic Programming Knapsack Packing**: Exact 0/1 Knapsack optimizer for packing high-relevance memories into strict token envelopes.
|
|
9
|
+
- **Ebbinghaus Decay Engine**: Continuous temporal decay with positive/negative reinforcement factors.
|
|
10
|
+
- **Semantic Deduplication**: Dual lexical Jaccard and dense cosine similarity detection to prevent node fragmentation.
|
|
11
|
+
- **Hybrid Retrieval**: BM25 sparse lexical ranking fused with dense vector embeddings via Reciprocal Rank Fusion (RRF).
|
|
12
|
+
- **Framework Integrations**: True drop-in adapters for LangChain (`BaseMemory`) and LlamaIndex (`BaseMemory`).
|
|
13
|
+
- **Agent reliability runtime**: Opt-in run budgets, repeated failed-call blocking, versioned event serialization, and persistent tenant-scoped run traces.
|
|
14
|
+
- **Opt-in agent run guard**: Bounded steps/tool calls, cooperative deadlines, repeated-failure blocking, and privacy-minimized in-memory events.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install synapse-memory-engine # from PyPI
|
|
20
|
+
# or, from a checkout of this repository:
|
|
21
|
+
pip install -e .
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## REST client quick start
|
|
25
|
+
|
|
26
|
+
Use `SynapseClient` when connecting an application to a running Synapse API:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from synapse_memory import SynapseClient, SynapseError
|
|
30
|
+
|
|
31
|
+
with SynapseClient(
|
|
32
|
+
"http://127.0.0.1:8008",
|
|
33
|
+
api_key="syn_live_your_key",
|
|
34
|
+
tenant_id="your-tenant",
|
|
35
|
+
) as client:
|
|
36
|
+
created = client.create_memory("Customer selected the annual plan.", category="fact")
|
|
37
|
+
result = client.retrieve("Which plan did the customer select?")
|
|
38
|
+
print(created.id, result.fused_context)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The client automatically retries idempotent `GET`/`HEAD`/`OPTIONS` requests and honours `Retry-After`. It does not automatically replay `POST` requests (including `/query`, which updates access metadata) after an ambiguous failure; callers should reconcile the operation before manually retrying, or provide their own idempotency mechanism.
|
|
42
|
+
|
|
43
|
+
## Opt-in Python run guard
|
|
44
|
+
|
|
45
|
+
The runtime only guards tool calls explicitly routed through `SynapseRun`; it does not intercept arbitrary framework calls. Events stay in memory until the application exports or persists them. Event records contain tool names and keyed argument fingerprints, not raw arguments, prompts, tool results, or exception messages.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from synapse_memory import RunPolicy, SynapseRun
|
|
49
|
+
|
|
50
|
+
policy = RunPolicy(
|
|
51
|
+
max_steps=12,
|
|
52
|
+
max_tool_calls=8,
|
|
53
|
+
timeout_seconds=30,
|
|
54
|
+
max_repeated_failures=2,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
with SynapseRun(policy=policy) as run:
|
|
58
|
+
customer = run.call_tool(
|
|
59
|
+
"lookup_customer",
|
|
60
|
+
{"customer_id": "cust_123"},
|
|
61
|
+
lookup_customer, # callable accepts arguments as keyword arguments
|
|
62
|
+
)
|
|
63
|
+
run.record_step() # account for non-tool work
|
|
64
|
+
print(customer)
|
|
65
|
+
|
|
66
|
+
# Inspect metadata-only events after the context exits.
|
|
67
|
+
for event in run.events:
|
|
68
|
+
print(event.event_type.value, event.reason, event.tool_fingerprint)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Limits are checked before admitting each step/tool call. The deadline is cooperative: a synchronous tool already in progress cannot be forcibly interrupted. A run guard is not a sandbox, does not authorize tools, does not intercept unwrapped calls, or enforce provider token/cost budgets. Repeated-call blocking applies after the configured number of consecutive failures for the same tool and equivalent JSON arguments; a successful call resets that failure count. No automatic retries are performed.
|
|
72
|
+
|
|
73
|
+
## Persistent run traces and retrieval provenance
|
|
74
|
+
|
|
75
|
+
Trace persistence is an explicit opt-in operation. The event contract is versioned (schema_version=1) and records only run lifecycle metadata, tool name/status, a per-run keyed argument fingerprint, typed failure reasons, and retrieval evidence. It does not record prompts, raw tool arguments, tool results, memory content, or the retrieval query. Retrieval evidence must be supplied by the application from its own retrieval/packing pipeline; Synapse does not silently instrument arbitrary framework calls or automatically attach every /query response to a run.
|
|
76
|
+
|
|
77
|
+
To persist a completed SynapseRun, use a key with agent-runs:read and agent-runs:write scopes, plus agent-runs:delete only when deletion is needed:
|
|
78
|
+
|
|
79
|
+
~~~python
|
|
80
|
+
from synapse_memory import RunPolicy, SynapseClient, SynapseRun
|
|
81
|
+
|
|
82
|
+
with SynapseRun(policy=RunPolicy(max_steps=12, max_tool_calls=8)) as run:
|
|
83
|
+
# The app can query Synapse or another retriever here.
|
|
84
|
+
candidates = [
|
|
85
|
+
{"id": "memory_01", "relevance_score": 0.91, "token_cost": 18},
|
|
86
|
+
{"id": "memory_02", "relevance_score": 0.43, "token_cost": 16},
|
|
87
|
+
]
|
|
88
|
+
packed_ids = ["memory_01"]
|
|
89
|
+
run.record_memory_retrieval(candidates, packed_memory_ids=packed_ids)
|
|
90
|
+
answer = run.call_tool("lookup_customer", {"customer_id": "cust_123"}, lookup_customer)
|
|
91
|
+
|
|
92
|
+
with SynapseClient(
|
|
93
|
+
"https://your-synapse-api",
|
|
94
|
+
api_key="syn_live_your_key",
|
|
95
|
+
tenant_id="your-tenant",
|
|
96
|
+
) as client:
|
|
97
|
+
receipt = client.upload_agent_run(run)
|
|
98
|
+
print(receipt["events_inserted"], receipt["events_deduplicated"])
|
|
99
|
+
~~~
|
|
100
|
+
|
|
101
|
+
The client uploads the run's ordered events after the run ends. Stable event IDs make retrying a partially completed upload idempotent. Event records are tenant-bound by the authenticated API key; a caller-supplied tenant field in an event is rejected. Available endpoints are documented in the API contract (../../docs/api-reference.md). Each tenant can list and delete only its own trace records; event pages are bounded and ordered by sequence number.
|
|
102
|
+
|
|
103
|
+
This first persistence layer is not yet a live streaming sink, a full observability dashboard, an outcome verifier, or a retention scheduler. Deployments must apply schema migration v6 before starting a PostgreSQL least-privilege runtime role. Use the API's deletion endpoint or a separately configured retention job to remove stored runs.
|
|
104
|
+
|
|
105
|
+
## Testing
|
|
106
|
+
|
|
107
|
+
From the repository root:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install -e "sdk/python[pgvector,langchain,llamaindex,dev]"
|
|
111
|
+
PYTHONPATH=sdk/python pytest sdk/python/tests -v
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Database-gated tests require a disposable PostgreSQL/pgvector database and explicitly documented environment flags. Passing the offline suite alone is not production verification.
|
|
115
|
+
|
|
116
|
+
**Licence:** proprietary. Installation does not grant unrestricted usage or deployment rights; obtain written permission under [`../../LICENSE`](../../LICENSE) before using this package outside the permissions granted by the copyright holder.
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
# owned by an unrelated third-party project. Import package stays `synapse_memory`.
|
|
8
8
|
# See docs/publishing.md.
|
|
9
9
|
name = "synapse-memory-engine"
|
|
10
|
-
version = "1.
|
|
10
|
+
version = "1.4.0"
|
|
11
11
|
authors = [{name = "Synapse Cognitive Systems", email = "singhshivam20009@gmail.com"}]
|
|
12
12
|
description = "Production-grade active RAG & cognitive memory engine with multi-tenancy, pgvector HNSW indexing, semantic deduplication, decay-based pruning, and token-aware context packing."
|
|
13
13
|
readme = "README.md"
|
|
@@ -2,10 +2,10 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="synapse-memory-engine",
|
|
5
|
-
version="1.
|
|
5
|
+
version="1.4.0",
|
|
6
6
|
description="Sovereign, active RAG & cognitive long-term memory engine for AI agents",
|
|
7
7
|
author="Synapse Cognitive Systems",
|
|
8
|
-
author_email="
|
|
8
|
+
author_email="singhshivam20009@gmail.com",
|
|
9
9
|
url="https://github.com/721189/Synapse-Memory",
|
|
10
10
|
license="All Rights Reserved",
|
|
11
11
|
packages=find_packages(include=["synapse_memory*"]),
|
|
@@ -16,6 +16,7 @@ setup(
|
|
|
16
16
|
"uvicorn>=0.34.0",
|
|
17
17
|
"cryptography>=42.0.0",
|
|
18
18
|
"requests>=2.31.0",
|
|
19
|
+
"urllib3>=2.8.0",
|
|
19
20
|
"numpy>=1.26.0",
|
|
20
21
|
],
|
|
21
22
|
extras_require={
|
|
@@ -29,13 +30,13 @@ setup(
|
|
|
29
30
|
"pgvector>=0.4.0",
|
|
30
31
|
"langchain-core>=0.3.0",
|
|
31
32
|
"llama-index-core>=0.13.0",
|
|
33
|
+
"redis>=5.0.0",
|
|
32
34
|
],
|
|
33
35
|
"dev": [
|
|
34
36
|
"flake8>=7.0.0",
|
|
35
37
|
"mypy>=1.13.0",
|
|
36
38
|
"bandit>=1.8.0",
|
|
37
39
|
"pytest>=8.0.0",
|
|
38
|
-
"types-cryptography>=42.0.0",
|
|
39
40
|
"types-requests>=2.32.0",
|
|
40
41
|
],
|
|
41
42
|
},
|
|
@@ -9,8 +9,23 @@ from synapse_memory.core.decay_engine import DecayEngine
|
|
|
9
9
|
from synapse_memory.integrations.langchain import SynapseLangChainMemory
|
|
10
10
|
from synapse_memory.integrations.llamaindex import SynapseLlamaIndexMemory
|
|
11
11
|
from synapse_memory.client import SynapseClient, SynapseError, CreateResult, QueryResult
|
|
12
|
+
from synapse_memory.runtime import (
|
|
13
|
+
RunPolicy,
|
|
14
|
+
RunStatus,
|
|
15
|
+
RunEventType,
|
|
16
|
+
RunEvent,
|
|
17
|
+
MemoryEvidence,
|
|
18
|
+
SynapseRun,
|
|
19
|
+
RunGuardError,
|
|
20
|
+
RunStateError,
|
|
21
|
+
RunLimitExceeded,
|
|
22
|
+
RunStepLimitExceeded,
|
|
23
|
+
RunToolCallLimitExceeded,
|
|
24
|
+
RunDeadlineExceeded,
|
|
25
|
+
RepeatedToolCallError,
|
|
26
|
+
)
|
|
12
27
|
|
|
13
|
-
__version__ = "1.
|
|
28
|
+
__version__ = "1.4.0"
|
|
14
29
|
__api_compat_version__ = "v1"
|
|
15
30
|
|
|
16
31
|
__all__ = [
|
|
@@ -28,4 +43,17 @@ __all__ = [
|
|
|
28
43
|
"SynapseError",
|
|
29
44
|
"CreateResult",
|
|
30
45
|
"QueryResult",
|
|
46
|
+
"RunPolicy",
|
|
47
|
+
"RunStatus",
|
|
48
|
+
"RunEventType",
|
|
49
|
+
"RunEvent",
|
|
50
|
+
"MemoryEvidence",
|
|
51
|
+
"SynapseRun",
|
|
52
|
+
"RunGuardError",
|
|
53
|
+
"RunStateError",
|
|
54
|
+
"RunLimitExceeded",
|
|
55
|
+
"RunStepLimitExceeded",
|
|
56
|
+
"RunToolCallLimitExceeded",
|
|
57
|
+
"RunDeadlineExceeded",
|
|
58
|
+
"RepeatedToolCallError",
|
|
31
59
|
]
|