lore-sdk 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.
- lore_sdk-0.1.0/.github/workflows/ci.yml +49 -0
- lore_sdk-0.1.0/.gitignore +12 -0
- lore_sdk-0.1.0/LICENSE +21 -0
- lore_sdk-0.1.0/PKG-INFO +246 -0
- lore_sdk-0.1.0/README.md +219 -0
- lore_sdk-0.1.0/architecture.md +381 -0
- lore_sdk-0.1.0/examples/basic_usage.py +45 -0
- lore_sdk-0.1.0/examples/custom_embeddings.py +51 -0
- lore_sdk-0.1.0/examples/redaction_demo.py +43 -0
- lore_sdk-0.1.0/prd.md +177 -0
- lore_sdk-0.1.0/product-brief.md +182 -0
- lore_sdk-0.1.0/pyproject.toml +54 -0
- lore_sdk-0.1.0/sprint-plan.md +100 -0
- lore_sdk-0.1.0/src/lore/__init__.py +8 -0
- lore_sdk-0.1.0/src/lore/__main__.py +5 -0
- lore_sdk-0.1.0/src/lore/cli.py +138 -0
- lore_sdk-0.1.0/src/lore/embed/__init__.py +6 -0
- lore_sdk-0.1.0/src/lore/embed/base.py +18 -0
- lore_sdk-0.1.0/src/lore/embed/local.py +187 -0
- lore_sdk-0.1.0/src/lore/exceptions.py +9 -0
- lore_sdk-0.1.0/src/lore/lore.py +380 -0
- lore_sdk-0.1.0/src/lore/prompt.py +52 -0
- lore_sdk-0.1.0/src/lore/redact/__init__.py +5 -0
- lore_sdk-0.1.0/src/lore/redact/patterns.py +59 -0
- lore_sdk-0.1.0/src/lore/redact/pipeline.py +92 -0
- lore_sdk-0.1.0/src/lore/store/__init__.py +7 -0
- lore_sdk-0.1.0/src/lore/store/base.py +36 -0
- lore_sdk-0.1.0/src/lore/store/memory.py +45 -0
- lore_sdk-0.1.0/src/lore/store/sqlite.py +167 -0
- lore_sdk-0.1.0/src/lore/types.py +35 -0
- lore_sdk-0.1.0/stories/story-1.md +24 -0
- lore_sdk-0.1.0/stories/story-10.md +23 -0
- lore_sdk-0.1.0/stories/story-11.md +22 -0
- lore_sdk-0.1.0/stories/story-12.md +22 -0
- lore_sdk-0.1.0/stories/story-13.md +22 -0
- lore_sdk-0.1.0/stories/story-14.md +23 -0
- lore_sdk-0.1.0/stories/story-15.md +21 -0
- lore_sdk-0.1.0/stories/story-2.md +26 -0
- lore_sdk-0.1.0/stories/story-3.md +23 -0
- lore_sdk-0.1.0/stories/story-4.md +24 -0
- lore_sdk-0.1.0/stories/story-5.md +25 -0
- lore_sdk-0.1.0/stories/story-6.md +21 -0
- lore_sdk-0.1.0/stories/story-7.md +23 -0
- lore_sdk-0.1.0/stories/story-8.md +25 -0
- lore_sdk-0.1.0/stories/story-9.md +23 -0
- lore_sdk-0.1.0/tests/__init__.py +0 -0
- lore_sdk-0.1.0/tests/test_cli.py +101 -0
- lore_sdk-0.1.0/tests/test_decay_voting.py +208 -0
- lore_sdk-0.1.0/tests/test_edge_cases.py +202 -0
- lore_sdk-0.1.0/tests/test_embedder.py +92 -0
- lore_sdk-0.1.0/tests/test_export_import.py +128 -0
- lore_sdk-0.1.0/tests/test_lesson.py +38 -0
- lore_sdk-0.1.0/tests/test_prompt.py +94 -0
- lore_sdk-0.1.0/tests/test_query.py +110 -0
- lore_sdk-0.1.0/tests/test_redact.py +173 -0
- lore_sdk-0.1.0/tests/test_redact_integration.py +69 -0
- lore_sdk-0.1.0/tests/test_stores.py +209 -0
- lore_sdk-0.1.0/ts/.eslintrc.json +16 -0
- lore_sdk-0.1.0/ts/.gitignore +3 -0
- lore_sdk-0.1.0/ts/README.md +151 -0
- lore_sdk-0.1.0/ts/examples/basic-usage.ts +55 -0
- lore_sdk-0.1.0/ts/examples/custom-embeddings.ts +53 -0
- lore_sdk-0.1.0/ts/package-lock.json +4061 -0
- lore_sdk-0.1.0/ts/package.json +46 -0
- lore_sdk-0.1.0/ts/src/embed.ts +59 -0
- lore_sdk-0.1.0/ts/src/index.ts +9 -0
- lore_sdk-0.1.0/ts/src/lore.ts +238 -0
- lore_sdk-0.1.0/ts/src/prompt.ts +46 -0
- lore_sdk-0.1.0/ts/src/redact.ts +129 -0
- lore_sdk-0.1.0/ts/src/store/base.ts +13 -0
- lore_sdk-0.1.0/ts/src/store/index.ts +3 -0
- lore_sdk-0.1.0/ts/src/store/memory.ts +57 -0
- lore_sdk-0.1.0/ts/src/store/sqlite.ts +147 -0
- lore_sdk-0.1.0/ts/src/types.ts +57 -0
- lore_sdk-0.1.0/ts/tests/edge-cases.test.ts +165 -0
- lore_sdk-0.1.0/ts/tests/embed.test.ts +77 -0
- lore_sdk-0.1.0/ts/tests/lore.test.ts +134 -0
- lore_sdk-0.1.0/ts/tests/memory-store.test.ts +89 -0
- lore_sdk-0.1.0/ts/tests/prompt.test.ts +66 -0
- lore_sdk-0.1.0/ts/tests/query.test.ts +167 -0
- lore_sdk-0.1.0/ts/tests/redact.test.ts +124 -0
- lore_sdk-0.1.0/ts/tests/sqlite-store.test.ts +116 -0
- lore_sdk-0.1.0/ts/tsconfig.json +18 -0
- lore_sdk-0.1.0/ts/vitest.config.ts +7 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
python:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.9", "3.11", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: |
|
|
23
|
+
python -m pip install --upgrade pip
|
|
24
|
+
pip install -e ".[dev]"
|
|
25
|
+
- name: Lint
|
|
26
|
+
run: ruff check src/ tests/
|
|
27
|
+
- name: Test
|
|
28
|
+
run: pytest
|
|
29
|
+
|
|
30
|
+
typescript:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
strategy:
|
|
33
|
+
matrix:
|
|
34
|
+
node-version: [18, 20]
|
|
35
|
+
defaults:
|
|
36
|
+
run:
|
|
37
|
+
working-directory: ts
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
- name: Set up Node ${{ matrix.node-version }}
|
|
41
|
+
uses: actions/setup-node@v4
|
|
42
|
+
with:
|
|
43
|
+
node-version: ${{ matrix.node-version }}
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: npm ci
|
|
46
|
+
- name: Build
|
|
47
|
+
run: npm run build
|
|
48
|
+
- name: Test
|
|
49
|
+
run: npm test
|
lore_sdk-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amit Paz
|
|
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.
|
lore_sdk-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lore-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Cross-agent memory library
|
|
5
|
+
Project-URL: Homepage, https://github.com/amitpaz1/lore
|
|
6
|
+
Project-URL: Repository, https://github.com/amitpaz1/lore
|
|
7
|
+
Project-URL: Issues, https://github.com/amitpaz1/lore/issues
|
|
8
|
+
Author-email: Amit Paz <amit.paz@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent,lessons,lore,memory
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Requires-Dist: numpy>=1.21.0
|
|
20
|
+
Requires-Dist: onnxruntime>=1.14.0
|
|
21
|
+
Requires-Dist: python-ulid>=2.0.0
|
|
22
|
+
Requires-Dist: tokenizers>=0.13.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
<](https://pypi.org/project/lore-sdk/)
|
|
31
|
+
[](https://www.npmjs.com/package/lore-sdk)
|
|
32
|
+
[](https://github.com/amitpaz/lore/actions)
|
|
33
|
+
[](LICENSE)
|
|
34
|
+
|
|
35
|
+
**Cross-agent memory.** Agents publish what they learn, other agents query it. PII redacted automatically.
|
|
36
|
+
|
|
37
|
+
## Why Lore?
|
|
38
|
+
|
|
39
|
+
Your agents keep making the same mistakes. Agent A discovers Stripe rate-limits at 100 req/min. Agent B hits the same wall tomorrow. No learning transfer.
|
|
40
|
+
|
|
41
|
+
Lore fixes this. It's a tiny library — no server, no infra — that gives agents a shared memory of operational lessons. Publish a lesson in one line, query it in another. Sensitive data is redacted before storage automatically.
|
|
42
|
+
|
|
43
|
+
**What Lore is:** A local-first SDK for storing and retrieving structured lessons across agent runs. SQLite-backed, embedding-powered semantic search, automatic PII redaction.
|
|
44
|
+
|
|
45
|
+
**What Lore is not:** A conversation memory store (see Mem0/Zep), a vector database, or a RAG framework.
|
|
46
|
+
|
|
47
|
+
## Quickstart
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from lore import Lore
|
|
51
|
+
|
|
52
|
+
lore = Lore() # zero config — local SQLite, built-in embeddings
|
|
53
|
+
|
|
54
|
+
lore.publish(
|
|
55
|
+
problem="Stripe API returns 429 after 100 req/min",
|
|
56
|
+
resolution="Exponential backoff starting at 1s, cap at 32s",
|
|
57
|
+
tags=["stripe", "rate-limit"],
|
|
58
|
+
confidence=0.9,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
lessons = lore.query("stripe rate limiting")
|
|
62
|
+
prompt = lore.as_prompt(lessons) # ready for system prompt injection
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { Lore } from 'lore-sdk';
|
|
67
|
+
|
|
68
|
+
const lore = new Lore({ embeddingFn: yourEmbedFn });
|
|
69
|
+
|
|
70
|
+
await lore.publish({
|
|
71
|
+
problem: 'Stripe API returns 429 after 100 req/min',
|
|
72
|
+
resolution: 'Exponential backoff starting at 1s, cap at 32s',
|
|
73
|
+
tags: ['stripe', 'rate-limit'],
|
|
74
|
+
confidence: 0.9,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const lessons = await lore.query('stripe rate limiting');
|
|
78
|
+
const prompt = lore.asPrompt(lessons);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
**Python** (3.9+):
|
|
84
|
+
```bash
|
|
85
|
+
pip install lore-sdk
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**TypeScript** (Node 18+):
|
|
89
|
+
```bash
|
|
90
|
+
npm install lore-sdk
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Python API Reference
|
|
94
|
+
|
|
95
|
+
### `Lore(project?, db_path?, store?, embedding_fn?, embedder?, redact?, redact_patterns?, decay_half_life_days?)`
|
|
96
|
+
|
|
97
|
+
Create a Lore instance.
|
|
98
|
+
|
|
99
|
+
| Parameter | Type | Default | Description |
|
|
100
|
+
|-----------|------|---------|-------------|
|
|
101
|
+
| `project` | `str \| None` | `None` | Scope lessons to a project name |
|
|
102
|
+
| `db_path` | `str \| None` | `~/.lore/default.db` | Path to SQLite database |
|
|
103
|
+
| `store` | `Store \| None` | `None` | Custom storage backend |
|
|
104
|
+
| `embedding_fn` | `Callable[[str], list[float]] \| None` | `None` | Custom embedding function |
|
|
105
|
+
| `embedder` | `Embedder \| None` | `None` | Custom embedder instance |
|
|
106
|
+
| `redact` | `bool` | `True` | Enable automatic PII redaction |
|
|
107
|
+
| `redact_patterns` | `list[tuple[str, str]] \| None` | `None` | Custom redaction patterns as `(regex, label)` |
|
|
108
|
+
| `decay_half_life_days` | `float` | `30` | Half-life for lesson score decay |
|
|
109
|
+
|
|
110
|
+
Lore supports context manager usage:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
with Lore() as lore:
|
|
114
|
+
lore.publish(problem="...", resolution="...")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `lore.publish(problem, resolution, context?, tags?, confidence?, source?, project?) → str`
|
|
118
|
+
|
|
119
|
+
Publish a lesson. Returns the lesson ID (ULID).
|
|
120
|
+
|
|
121
|
+
| Parameter | Type | Default | Description |
|
|
122
|
+
|-----------|------|---------|-------------|
|
|
123
|
+
| `problem` | `str` | *required* | What went wrong |
|
|
124
|
+
| `resolution` | `str` | *required* | How to fix it |
|
|
125
|
+
| `context` | `str \| None` | `None` | Additional context |
|
|
126
|
+
| `tags` | `list[str] \| None` | `[]` | Filterable tags |
|
|
127
|
+
| `confidence` | `float` | `0.5` | Confidence score (0.0–1.0) |
|
|
128
|
+
| `source` | `str \| None` | `None` | Who/what created this lesson |
|
|
129
|
+
| `project` | `str \| None` | instance default | Override project scope |
|
|
130
|
+
|
|
131
|
+
### `lore.query(text, tags?, limit?, min_confidence?) → list[QueryResult]`
|
|
132
|
+
|
|
133
|
+
Query lessons by semantic similarity.
|
|
134
|
+
|
|
135
|
+
| Parameter | Type | Default | Description |
|
|
136
|
+
|-----------|------|---------|-------------|
|
|
137
|
+
| `text` | `str` | *required* | Search query |
|
|
138
|
+
| `tags` | `list[str] \| None` | `None` | Filter: lessons must have ALL these tags |
|
|
139
|
+
| `limit` | `int` | `5` | Max results |
|
|
140
|
+
| `min_confidence` | `float` | `0.0` | Minimum confidence threshold |
|
|
141
|
+
|
|
142
|
+
Returns `list[QueryResult]` sorted by score (cosine similarity × confidence × time decay × vote factor).
|
|
143
|
+
|
|
144
|
+
### `lore.as_prompt(lessons, max_tokens?) → str`
|
|
145
|
+
|
|
146
|
+
Format query results as a markdown string for system prompt injection.
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Default | Description |
|
|
149
|
+
|-----------|------|---------|-------------|
|
|
150
|
+
| `lessons` | `list[QueryResult]` | *required* | Results from `query()` |
|
|
151
|
+
| `max_tokens` | `int` | `1000` | Approximate token budget (1 token ≈ 4 chars) |
|
|
152
|
+
|
|
153
|
+
### `lore.get(lesson_id) → Lesson | None`
|
|
154
|
+
|
|
155
|
+
Retrieve a single lesson by ID.
|
|
156
|
+
|
|
157
|
+
### `lore.list(project?, limit?) → list[Lesson]`
|
|
158
|
+
|
|
159
|
+
List lessons, optionally filtered by project.
|
|
160
|
+
|
|
161
|
+
### `lore.delete(lesson_id) → bool`
|
|
162
|
+
|
|
163
|
+
Delete a lesson. Returns `True` if found and deleted.
|
|
164
|
+
|
|
165
|
+
### `lore.upvote(lesson_id) → None`
|
|
166
|
+
|
|
167
|
+
Increment a lesson's upvote count. Raises `LessonNotFoundError` if not found.
|
|
168
|
+
|
|
169
|
+
### `lore.downvote(lesson_id) → None`
|
|
170
|
+
|
|
171
|
+
Increment a lesson's downvote count. Raises `LessonNotFoundError` if not found.
|
|
172
|
+
|
|
173
|
+
### `lore.export_lessons(path?) → list[dict]`
|
|
174
|
+
|
|
175
|
+
Export lessons as JSON-serializable dicts. If `path` is given, writes to file.
|
|
176
|
+
|
|
177
|
+
### `lore.import_lessons(path?, data?) → int`
|
|
178
|
+
|
|
179
|
+
Import lessons from file or data. Skips duplicates by ID. Returns count imported.
|
|
180
|
+
|
|
181
|
+
### `lore.close() → None`
|
|
182
|
+
|
|
183
|
+
Close the underlying store.
|
|
184
|
+
|
|
185
|
+
## TypeScript API Reference
|
|
186
|
+
|
|
187
|
+
The TypeScript SDK mirrors the Python API. See [ts/README.md](ts/README.md) for full details.
|
|
188
|
+
|
|
189
|
+
Key differences:
|
|
190
|
+
- All store operations are `async`
|
|
191
|
+
- Constructor takes an options object: `new Lore({ project, dbPath, embeddingFn, ... })`
|
|
192
|
+
- No built-in embedding model — you must provide `embeddingFn`
|
|
193
|
+
- `asPrompt()` instead of `as_prompt()`
|
|
194
|
+
- `minConfidence` instead of `min_confidence` (camelCase throughout)
|
|
195
|
+
|
|
196
|
+
## Redaction
|
|
197
|
+
|
|
198
|
+
Lore automatically redacts sensitive data before storage:
|
|
199
|
+
|
|
200
|
+
- **API keys** (Bearer tokens, `sk-*`, `key-*`, etc.)
|
|
201
|
+
- **Email addresses**
|
|
202
|
+
- **Phone numbers**
|
|
203
|
+
- **IP addresses** (IPv4 and IPv6)
|
|
204
|
+
- **Credit card numbers** (with Luhn validation)
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
lore.publish(
|
|
208
|
+
problem="Auth failed with key sk-abc123def456ghi789jkl012mno",
|
|
209
|
+
resolution="Rotate the key",
|
|
210
|
+
)
|
|
211
|
+
# Stored as: "Auth failed with key [REDACTED:api_key]"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Add custom patterns:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
lore = Lore(redact_patterns=[
|
|
218
|
+
(r"ACCT-\d{8}", "account_id"),
|
|
219
|
+
])
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Disable redaction entirely with `redact=False`.
|
|
223
|
+
|
|
224
|
+
## Scoring
|
|
225
|
+
|
|
226
|
+
Query results are ranked by:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
score = cosine_similarity × confidence × time_decay × vote_factor
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
- **Time decay:** Lessons lose relevance over time (configurable half-life, default 30 days)
|
|
233
|
+
- **Vote factor:** `1.0 + (upvotes - downvotes) × 0.1`, floored at 0.1
|
|
234
|
+
- **Confidence:** Author's self-assessed confidence (0.0–1.0)
|
|
235
|
+
|
|
236
|
+
## Examples
|
|
237
|
+
|
|
238
|
+
See [`examples/`](examples/) for runnable scripts:
|
|
239
|
+
- [`basic_usage.py`](examples/basic_usage.py) — publish, query, format
|
|
240
|
+
- [`custom_embeddings.py`](examples/custom_embeddings.py) — bring your own embedding function
|
|
241
|
+
- [`redaction_demo.py`](examples/redaction_demo.py) — see redaction in action
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT
|
|
246
|
+
]]>
|
lore_sdk-0.1.0/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
<](https://pypi.org/project/lore-sdk/)
|
|
4
|
+
[](https://www.npmjs.com/package/lore-sdk)
|
|
5
|
+
[](https://github.com/amitpaz/lore/actions)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
**Cross-agent memory.** Agents publish what they learn, other agents query it. PII redacted automatically.
|
|
9
|
+
|
|
10
|
+
## Why Lore?
|
|
11
|
+
|
|
12
|
+
Your agents keep making the same mistakes. Agent A discovers Stripe rate-limits at 100 req/min. Agent B hits the same wall tomorrow. No learning transfer.
|
|
13
|
+
|
|
14
|
+
Lore fixes this. It's a tiny library — no server, no infra — that gives agents a shared memory of operational lessons. Publish a lesson in one line, query it in another. Sensitive data is redacted before storage automatically.
|
|
15
|
+
|
|
16
|
+
**What Lore is:** A local-first SDK for storing and retrieving structured lessons across agent runs. SQLite-backed, embedding-powered semantic search, automatic PII redaction.
|
|
17
|
+
|
|
18
|
+
**What Lore is not:** A conversation memory store (see Mem0/Zep), a vector database, or a RAG framework.
|
|
19
|
+
|
|
20
|
+
## Quickstart
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from lore import Lore
|
|
24
|
+
|
|
25
|
+
lore = Lore() # zero config — local SQLite, built-in embeddings
|
|
26
|
+
|
|
27
|
+
lore.publish(
|
|
28
|
+
problem="Stripe API returns 429 after 100 req/min",
|
|
29
|
+
resolution="Exponential backoff starting at 1s, cap at 32s",
|
|
30
|
+
tags=["stripe", "rate-limit"],
|
|
31
|
+
confidence=0.9,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
lessons = lore.query("stripe rate limiting")
|
|
35
|
+
prompt = lore.as_prompt(lessons) # ready for system prompt injection
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Lore } from 'lore-sdk';
|
|
40
|
+
|
|
41
|
+
const lore = new Lore({ embeddingFn: yourEmbedFn });
|
|
42
|
+
|
|
43
|
+
await lore.publish({
|
|
44
|
+
problem: 'Stripe API returns 429 after 100 req/min',
|
|
45
|
+
resolution: 'Exponential backoff starting at 1s, cap at 32s',
|
|
46
|
+
tags: ['stripe', 'rate-limit'],
|
|
47
|
+
confidence: 0.9,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const lessons = await lore.query('stripe rate limiting');
|
|
51
|
+
const prompt = lore.asPrompt(lessons);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
**Python** (3.9+):
|
|
57
|
+
```bash
|
|
58
|
+
pip install lore-sdk
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**TypeScript** (Node 18+):
|
|
62
|
+
```bash
|
|
63
|
+
npm install lore-sdk
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Python API Reference
|
|
67
|
+
|
|
68
|
+
### `Lore(project?, db_path?, store?, embedding_fn?, embedder?, redact?, redact_patterns?, decay_half_life_days?)`
|
|
69
|
+
|
|
70
|
+
Create a Lore instance.
|
|
71
|
+
|
|
72
|
+
| Parameter | Type | Default | Description |
|
|
73
|
+
|-----------|------|---------|-------------|
|
|
74
|
+
| `project` | `str \| None` | `None` | Scope lessons to a project name |
|
|
75
|
+
| `db_path` | `str \| None` | `~/.lore/default.db` | Path to SQLite database |
|
|
76
|
+
| `store` | `Store \| None` | `None` | Custom storage backend |
|
|
77
|
+
| `embedding_fn` | `Callable[[str], list[float]] \| None` | `None` | Custom embedding function |
|
|
78
|
+
| `embedder` | `Embedder \| None` | `None` | Custom embedder instance |
|
|
79
|
+
| `redact` | `bool` | `True` | Enable automatic PII redaction |
|
|
80
|
+
| `redact_patterns` | `list[tuple[str, str]] \| None` | `None` | Custom redaction patterns as `(regex, label)` |
|
|
81
|
+
| `decay_half_life_days` | `float` | `30` | Half-life for lesson score decay |
|
|
82
|
+
|
|
83
|
+
Lore supports context manager usage:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
with Lore() as lore:
|
|
87
|
+
lore.publish(problem="...", resolution="...")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### `lore.publish(problem, resolution, context?, tags?, confidence?, source?, project?) → str`
|
|
91
|
+
|
|
92
|
+
Publish a lesson. Returns the lesson ID (ULID).
|
|
93
|
+
|
|
94
|
+
| Parameter | Type | Default | Description |
|
|
95
|
+
|-----------|------|---------|-------------|
|
|
96
|
+
| `problem` | `str` | *required* | What went wrong |
|
|
97
|
+
| `resolution` | `str` | *required* | How to fix it |
|
|
98
|
+
| `context` | `str \| None` | `None` | Additional context |
|
|
99
|
+
| `tags` | `list[str] \| None` | `[]` | Filterable tags |
|
|
100
|
+
| `confidence` | `float` | `0.5` | Confidence score (0.0–1.0) |
|
|
101
|
+
| `source` | `str \| None` | `None` | Who/what created this lesson |
|
|
102
|
+
| `project` | `str \| None` | instance default | Override project scope |
|
|
103
|
+
|
|
104
|
+
### `lore.query(text, tags?, limit?, min_confidence?) → list[QueryResult]`
|
|
105
|
+
|
|
106
|
+
Query lessons by semantic similarity.
|
|
107
|
+
|
|
108
|
+
| Parameter | Type | Default | Description |
|
|
109
|
+
|-----------|------|---------|-------------|
|
|
110
|
+
| `text` | `str` | *required* | Search query |
|
|
111
|
+
| `tags` | `list[str] \| None` | `None` | Filter: lessons must have ALL these tags |
|
|
112
|
+
| `limit` | `int` | `5` | Max results |
|
|
113
|
+
| `min_confidence` | `float` | `0.0` | Minimum confidence threshold |
|
|
114
|
+
|
|
115
|
+
Returns `list[QueryResult]` sorted by score (cosine similarity × confidence × time decay × vote factor).
|
|
116
|
+
|
|
117
|
+
### `lore.as_prompt(lessons, max_tokens?) → str`
|
|
118
|
+
|
|
119
|
+
Format query results as a markdown string for system prompt injection.
|
|
120
|
+
|
|
121
|
+
| Parameter | Type | Default | Description |
|
|
122
|
+
|-----------|------|---------|-------------|
|
|
123
|
+
| `lessons` | `list[QueryResult]` | *required* | Results from `query()` |
|
|
124
|
+
| `max_tokens` | `int` | `1000` | Approximate token budget (1 token ≈ 4 chars) |
|
|
125
|
+
|
|
126
|
+
### `lore.get(lesson_id) → Lesson | None`
|
|
127
|
+
|
|
128
|
+
Retrieve a single lesson by ID.
|
|
129
|
+
|
|
130
|
+
### `lore.list(project?, limit?) → list[Lesson]`
|
|
131
|
+
|
|
132
|
+
List lessons, optionally filtered by project.
|
|
133
|
+
|
|
134
|
+
### `lore.delete(lesson_id) → bool`
|
|
135
|
+
|
|
136
|
+
Delete a lesson. Returns `True` if found and deleted.
|
|
137
|
+
|
|
138
|
+
### `lore.upvote(lesson_id) → None`
|
|
139
|
+
|
|
140
|
+
Increment a lesson's upvote count. Raises `LessonNotFoundError` if not found.
|
|
141
|
+
|
|
142
|
+
### `lore.downvote(lesson_id) → None`
|
|
143
|
+
|
|
144
|
+
Increment a lesson's downvote count. Raises `LessonNotFoundError` if not found.
|
|
145
|
+
|
|
146
|
+
### `lore.export_lessons(path?) → list[dict]`
|
|
147
|
+
|
|
148
|
+
Export lessons as JSON-serializable dicts. If `path` is given, writes to file.
|
|
149
|
+
|
|
150
|
+
### `lore.import_lessons(path?, data?) → int`
|
|
151
|
+
|
|
152
|
+
Import lessons from file or data. Skips duplicates by ID. Returns count imported.
|
|
153
|
+
|
|
154
|
+
### `lore.close() → None`
|
|
155
|
+
|
|
156
|
+
Close the underlying store.
|
|
157
|
+
|
|
158
|
+
## TypeScript API Reference
|
|
159
|
+
|
|
160
|
+
The TypeScript SDK mirrors the Python API. See [ts/README.md](ts/README.md) for full details.
|
|
161
|
+
|
|
162
|
+
Key differences:
|
|
163
|
+
- All store operations are `async`
|
|
164
|
+
- Constructor takes an options object: `new Lore({ project, dbPath, embeddingFn, ... })`
|
|
165
|
+
- No built-in embedding model — you must provide `embeddingFn`
|
|
166
|
+
- `asPrompt()` instead of `as_prompt()`
|
|
167
|
+
- `minConfidence` instead of `min_confidence` (camelCase throughout)
|
|
168
|
+
|
|
169
|
+
## Redaction
|
|
170
|
+
|
|
171
|
+
Lore automatically redacts sensitive data before storage:
|
|
172
|
+
|
|
173
|
+
- **API keys** (Bearer tokens, `sk-*`, `key-*`, etc.)
|
|
174
|
+
- **Email addresses**
|
|
175
|
+
- **Phone numbers**
|
|
176
|
+
- **IP addresses** (IPv4 and IPv6)
|
|
177
|
+
- **Credit card numbers** (with Luhn validation)
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
lore.publish(
|
|
181
|
+
problem="Auth failed with key sk-abc123def456ghi789jkl012mno",
|
|
182
|
+
resolution="Rotate the key",
|
|
183
|
+
)
|
|
184
|
+
# Stored as: "Auth failed with key [REDACTED:api_key]"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Add custom patterns:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
lore = Lore(redact_patterns=[
|
|
191
|
+
(r"ACCT-\d{8}", "account_id"),
|
|
192
|
+
])
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Disable redaction entirely with `redact=False`.
|
|
196
|
+
|
|
197
|
+
## Scoring
|
|
198
|
+
|
|
199
|
+
Query results are ranked by:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
score = cosine_similarity × confidence × time_decay × vote_factor
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- **Time decay:** Lessons lose relevance over time (configurable half-life, default 30 days)
|
|
206
|
+
- **Vote factor:** `1.0 + (upvotes - downvotes) × 0.1`, floored at 0.1
|
|
207
|
+
- **Confidence:** Author's self-assessed confidence (0.0–1.0)
|
|
208
|
+
|
|
209
|
+
## Examples
|
|
210
|
+
|
|
211
|
+
See [`examples/`](examples/) for runnable scripts:
|
|
212
|
+
- [`basic_usage.py`](examples/basic_usage.py) — publish, query, format
|
|
213
|
+
- [`custom_embeddings.py`](examples/custom_embeddings.py) — bring your own embedding function
|
|
214
|
+
- [`redaction_demo.py`](examples/redaction_demo.py) — see redaction in action
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT
|
|
219
|
+
]]>
|