agentmemo 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.
- agentmemo-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
- agentmemo-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +32 -0
- agentmemo-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +45 -0
- agentmemo-0.1.0/.github/SECURITY.md +32 -0
- agentmemo-0.1.0/.github/workflows/ci.yml +63 -0
- agentmemo-0.1.0/.github/workflows/publish.yml +32 -0
- agentmemo-0.1.0/.gitignore +30 -0
- agentmemo-0.1.0/.mlc-config.json +29 -0
- agentmemo-0.1.0/.pre-commit-config.yaml +16 -0
- agentmemo-0.1.0/ARCHITECTURE.md +152 -0
- agentmemo-0.1.0/CHANGELOG.md +63 -0
- agentmemo-0.1.0/CLAUDE.md +40 -0
- agentmemo-0.1.0/CODE_OF_CONDUCT.md +41 -0
- agentmemo-0.1.0/CONTRIBUTING.md +89 -0
- agentmemo-0.1.0/DECISIONS.md +75 -0
- agentmemo-0.1.0/DEVELOPMENT.md +164 -0
- agentmemo-0.1.0/LICENSE +21 -0
- agentmemo-0.1.0/MANIFEST.in +4 -0
- agentmemo-0.1.0/PKG-INFO +491 -0
- agentmemo-0.1.0/README.md +455 -0
- agentmemo-0.1.0/examples/openai_integration.py +52 -0
- agentmemo-0.1.0/examples/quickstart.py +42 -0
- agentmemo-0.1.0/pyproject.toml +89 -0
- agentmemo-0.1.0/skills/principal_architect.md +179 -0
- agentmemo-0.1.0/skills/principal_devops.md +169 -0
- agentmemo-0.1.0/skills/principal_python_developer.md +141 -0
- agentmemo-0.1.0/skills/principal_qa_engineer.md +195 -0
- agentmemo-0.1.0/skills/user_guide.md +296 -0
- agentmemo-0.1.0/src/agentmemo/__init__.py +16 -0
- agentmemo-0.1.0/src/agentmemo/cli.py +222 -0
- agentmemo-0.1.0/src/agentmemo/extractor.py +157 -0
- agentmemo-0.1.0/src/agentmemo/forgetting.py +77 -0
- agentmemo-0.1.0/src/agentmemo/integrations/__init__.py +7 -0
- agentmemo-0.1.0/src/agentmemo/integrations/openai.py +78 -0
- agentmemo-0.1.0/src/agentmemo/knowledge.py +240 -0
- agentmemo-0.1.0/src/agentmemo/providers/__init__.py +126 -0
- agentmemo-0.1.0/src/agentmemo/providers/anthropic.py +54 -0
- agentmemo-0.1.0/src/agentmemo/providers/base.py +112 -0
- agentmemo-0.1.0/src/agentmemo/providers/openai_compat.py +67 -0
- agentmemo-0.1.0/src/agentmemo/providers/yandex.py +61 -0
- agentmemo-0.1.0/src/agentmemo/py.typed +0 -0
- agentmemo-0.1.0/src/agentmemo/retriever.py +98 -0
- agentmemo-0.1.0/src/agentmemo/storage/__init__.py +51 -0
- agentmemo-0.1.0/src/agentmemo/storage/base.py +31 -0
- agentmemo-0.1.0/src/agentmemo/storage/postgres_storage.py +146 -0
- agentmemo-0.1.0/src/agentmemo/storage/sqlite_storage.py +125 -0
- agentmemo-0.1.0/src/agentmemo/storage/yaml_storage.py +138 -0
- agentmemo-0.1.0/src/agentmemo/types.py +61 -0
- agentmemo-0.1.0/tests/__init__.py +0 -0
- agentmemo-0.1.0/tests/conftest.py +115 -0
- agentmemo-0.1.0/tests/test_cli.py +146 -0
- agentmemo-0.1.0/tests/test_cli_errors.py +132 -0
- agentmemo-0.1.0/tests/test_concurrent.py +146 -0
- agentmemo-0.1.0/tests/test_examples.py +107 -0
- agentmemo-0.1.0/tests/test_extractor.py +88 -0
- agentmemo-0.1.0/tests/test_extractor_errors.py +164 -0
- agentmemo-0.1.0/tests/test_forgetting.py +120 -0
- agentmemo-0.1.0/tests/test_forgetting_scenarios.py +129 -0
- agentmemo-0.1.0/tests/test_integration.py +125 -0
- agentmemo-0.1.0/tests/test_knowledge.py +131 -0
- agentmemo-0.1.0/tests/test_knowledge_edge_cases.py +107 -0
- agentmemo-0.1.0/tests/test_openai_integration.py +69 -0
- agentmemo-0.1.0/tests/test_performance.py +118 -0
- agentmemo-0.1.0/tests/test_providers.py +190 -0
- agentmemo-0.1.0/tests/test_retriever.py +110 -0
- agentmemo-0.1.0/tests/test_retriever_relevance.py +67 -0
- agentmemo-0.1.0/tests/test_simulation_scenarios.py +630 -0
- agentmemo-0.1.0/tests/test_sqlite_storage.py +115 -0
- agentmemo-0.1.0/tests/test_storage_compat.py +69 -0
- agentmemo-0.1.0/tests/test_storage_factory.py +39 -0
- agentmemo-0.1.0/tests/test_types.py +79 -0
- agentmemo-0.1.0/tests/test_yaml_storage.py +111 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something doesn't work as expected
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Environment
|
|
8
|
+
|
|
9
|
+
- OS: <!-- e.g. macOS 14, Ubuntu 22.04, Windows 11 -->
|
|
10
|
+
- Python version: <!-- e.g. 3.11.9 -->
|
|
11
|
+
- agentmemo version: <!-- e.g. 0.1.0 — run `agentmemo --version` or `pip show agentmemo` -->
|
|
12
|
+
- Storage backend: <!-- yaml / sqlite / postgres -->
|
|
13
|
+
- LLM provider: <!-- openai / anthropic / yandex / gigachat / qwen / openai-compat -->
|
|
14
|
+
|
|
15
|
+
## Steps to reproduce
|
|
16
|
+
|
|
17
|
+
1.
|
|
18
|
+
2.
|
|
19
|
+
3.
|
|
20
|
+
|
|
21
|
+
## Expected behaviour
|
|
22
|
+
|
|
23
|
+
<!-- What should happen -->
|
|
24
|
+
|
|
25
|
+
## Actual behaviour
|
|
26
|
+
|
|
27
|
+
<!-- What actually happens — include the full traceback if there is one -->
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
paste error output here
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Minimal reproducing example
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
# Paste the smallest snippet that triggers the bug
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Additional context
|
|
40
|
+
|
|
41
|
+
<!-- Anything else that might be relevant: custom storage path, concurrent access, specific LLM model, etc. -->
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Propose a new feature or improvement
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
<!-- What are you trying to do that agentmemo doesn't support yet?
|
|
10
|
+
Be specific: "I want to store facts in Redis" is better than "more backends". -->
|
|
11
|
+
|
|
12
|
+
## Proposed solution
|
|
13
|
+
|
|
14
|
+
<!-- How would you like it to work? Include API sketch if relevant. -->
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
# Example of what the API could look like
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Alternatives considered
|
|
21
|
+
|
|
22
|
+
<!-- What workarounds have you tried? Why don't they work for your case? -->
|
|
23
|
+
|
|
24
|
+
## Would you be willing to implement this?
|
|
25
|
+
|
|
26
|
+
- [ ] Yes, I can open a PR
|
|
27
|
+
- [ ] I can help test/review
|
|
28
|
+
- [ ] No, just reporting the need
|
|
29
|
+
|
|
30
|
+
## Additional context
|
|
31
|
+
|
|
32
|
+
<!-- Links, related issues, prior art in other libraries, etc. -->
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? 2-3 bullet points. -->
|
|
4
|
+
|
|
5
|
+
-
|
|
6
|
+
-
|
|
7
|
+
|
|
8
|
+
## Type of change
|
|
9
|
+
|
|
10
|
+
- [ ] Bug fix
|
|
11
|
+
- [ ] New feature
|
|
12
|
+
- [ ] Refactoring (no functional change)
|
|
13
|
+
- [ ] Documentation
|
|
14
|
+
- [ ] CI / DevOps
|
|
15
|
+
|
|
16
|
+
## Principal Python Developer review checklist
|
|
17
|
+
|
|
18
|
+
> Reviewer applies `skills/principal_python_developer.md` before approving.
|
|
19
|
+
|
|
20
|
+
- [ ] All public classes and functions have docstrings
|
|
21
|
+
- [ ] `from __future__ import annotations` present in every new module
|
|
22
|
+
- [ ] All type annotations correct and `mypy --strict` passes
|
|
23
|
+
- [ ] No bare `except:` — specific exceptions only
|
|
24
|
+
- [ ] No mutable default arguments (use `field(default_factory=...)`)
|
|
25
|
+
- [ ] `StorageBackend` protocol fully satisfied (if storage changes)
|
|
26
|
+
- [ ] No hardcoded secrets or absolute paths
|
|
27
|
+
- [ ] `ruff check` and `ruff format --check` pass clean
|
|
28
|
+
|
|
29
|
+
## Test checklist
|
|
30
|
+
|
|
31
|
+
- [ ] New behaviour covered by unit tests
|
|
32
|
+
- [ ] LLM calls mocked (no real API calls in tests)
|
|
33
|
+
- [ ] Storage tests include round-trip + multi-agent isolation
|
|
34
|
+
- [ ] `pytest --cov-fail-under=80` passes
|
|
35
|
+
- [ ] Both YAML and SQLite backends tested (if storage-related)
|
|
36
|
+
|
|
37
|
+
## Documentation
|
|
38
|
+
|
|
39
|
+
- [ ] `CHANGELOG.md` updated under `[Unreleased]`
|
|
40
|
+
- [ ] Docstrings updated for changed public API
|
|
41
|
+
- [ ] `ARCHITECTURE.md` updated if new layer or extension point added
|
|
42
|
+
|
|
43
|
+
## Screenshots / output (if applicable)
|
|
44
|
+
|
|
45
|
+
<!-- Paste CLI output or relevant logs -->
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---------|-----------|
|
|
7
|
+
| 0.1.x | Yes |
|
|
8
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
If you discover a security vulnerability in agentmemo, please report it responsibly:
|
|
12
|
+
|
|
13
|
+
1. **Do not** open a public issue.
|
|
14
|
+
2. Email the maintainers or open a private security advisory via
|
|
15
|
+
[GitHub Security Advisories](https://github.com/alsoleg89/agentmemo/security/advisories/new).
|
|
16
|
+
3. Include a description of the vulnerability, steps to reproduce, and potential impact.
|
|
17
|
+
|
|
18
|
+
We will acknowledge receipt within 48 hours and aim to release a fix within 7 days
|
|
19
|
+
for critical issues.
|
|
20
|
+
|
|
21
|
+
## Scope
|
|
22
|
+
|
|
23
|
+
- agentmemo library code (`src/agentmemo/`)
|
|
24
|
+
- CLI interface
|
|
25
|
+
- Storage backends (YAML, SQLite, PostgreSQL)
|
|
26
|
+
- LLM provider integrations
|
|
27
|
+
|
|
28
|
+
## Out of Scope
|
|
29
|
+
|
|
30
|
+
- Vulnerabilities in third-party dependencies (report upstream)
|
|
31
|
+
- Issues requiring physical access to the machine
|
|
32
|
+
- Social engineering attacks
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint:
|
|
14
|
+
name: Lint & Type Check
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
cache: pip
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
- name: Ruff check
|
|
28
|
+
run: ruff check src/ tests/
|
|
29
|
+
|
|
30
|
+
- name: Ruff format check
|
|
31
|
+
run: ruff format --check src/ tests/
|
|
32
|
+
|
|
33
|
+
- name: Mypy
|
|
34
|
+
run: mypy src/agentmemo/
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
strategy:
|
|
40
|
+
fail-fast: false
|
|
41
|
+
matrix:
|
|
42
|
+
python-version: ["3.11", "3.12"]
|
|
43
|
+
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
|
|
47
|
+
- uses: actions/setup-python@v5
|
|
48
|
+
with:
|
|
49
|
+
python-version: ${{ matrix.python-version }}
|
|
50
|
+
cache: pip
|
|
51
|
+
|
|
52
|
+
- name: Install dependencies
|
|
53
|
+
run: pip install -e ".[dev,openai]"
|
|
54
|
+
|
|
55
|
+
- name: Run tests
|
|
56
|
+
run: pytest --cov=agentmemo --cov-report=xml --cov-report=term-missing
|
|
57
|
+
|
|
58
|
+
- name: Upload coverage
|
|
59
|
+
if: matrix.python-version == '3.12'
|
|
60
|
+
uses: codecov/codecov-action@v4
|
|
61
|
+
with:
|
|
62
|
+
files: coverage.xml
|
|
63
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: pypi
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Install build tools
|
|
26
|
+
run: pip install hatch
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: hatch build
|
|
30
|
+
|
|
31
|
+
- name: Publish to PyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.egg
|
|
9
|
+
.eggs/
|
|
10
|
+
*.whl
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
.env
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
htmlcov/
|
|
19
|
+
coverage.xml
|
|
20
|
+
.coverage
|
|
21
|
+
.coverage.*
|
|
22
|
+
*.log
|
|
23
|
+
.DS_Store
|
|
24
|
+
Thumbs.db
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.swp
|
|
28
|
+
*.swo
|
|
29
|
+
*~
|
|
30
|
+
.agentmemo/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ignorePatterns": [
|
|
3
|
+
{
|
|
4
|
+
"pattern": "^https://shields\\.io"
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
"pattern": "^https://img\\.shields\\.io"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"pattern": "^https://github\\.com/.*/actions/workflows"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"pattern": "^https://pypi\\.org/project/agentmemo"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"pattern": "^http://localhost"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"pattern": "^https://github\\.com/alsoleg89/agentmemo/compare/"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"pattern": "^https://github\\.com/alsoleg89/agentmemo/releases/tag/"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"timeout": "10s",
|
|
26
|
+
"retryOn429": true,
|
|
27
|
+
"retryCount": 3,
|
|
28
|
+
"aliveStatusCodes": [200, 206]
|
|
29
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.4.10
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
10
|
+
rev: v1.10.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: mypy
|
|
13
|
+
additional_dependencies:
|
|
14
|
+
- types-PyYAML>=6.0
|
|
15
|
+
- httpx>=0.27
|
|
16
|
+
args: [--strict]
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# agentmemo — Architecture
|
|
2
|
+
|
|
3
|
+
## Design goals
|
|
4
|
+
|
|
5
|
+
| Goal | How |
|
|
6
|
+
|---|---|
|
|
7
|
+
| **Zero vendor lock-in** | Pluggable `StorageBackend` protocol |
|
|
8
|
+
| **Zero mandatory cloud deps** | Only `click`, `pyyaml`, `httpx` required |
|
|
9
|
+
| **Human-readable storage** | YAML files by default |
|
|
10
|
+
| **Signal over noise** | LLM distillation + Ebbinghaus decay |
|
|
11
|
+
| **Framework-agnostic** | Plain Python objects, no base classes to inherit |
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Layer diagram
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
19
|
+
│ CLI (agentmemo.cli) Integrations (*.integrations) │
|
|
20
|
+
├─────────────────────────────────────────────────────────────┤
|
|
21
|
+
│ KnowledgeBase (agentmemo.knowledge) │ ← public API
|
|
22
|
+
├──────────────┬──────────────────┬───────────────────────────┤
|
|
23
|
+
│ Extractor │ TFIDFRetriever │ apply_decay / forgetting │
|
|
24
|
+
│ (LLM calls) │ (TF-IDF search) │ (Ebbinghaus curve) │
|
|
25
|
+
├──────────────┴──────────────────┴───────────────────────────┤
|
|
26
|
+
│ StorageBackend (protocol) │
|
|
27
|
+
│ YAMLStorage SQLiteStorage (future: PG …) │
|
|
28
|
+
├─────────────────────────────────────────────────────────────┤
|
|
29
|
+
│ Core types: Fact, MemoryType, ConversationTurn │
|
|
30
|
+
└─────────────────────────────────────────────────────────────┘
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Dependency rules (no circular imports)
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
types ← storage ← forgetting
|
|
37
|
+
← retriever
|
|
38
|
+
← extractor
|
|
39
|
+
← knowledge ← cli
|
|
40
|
+
← integrations
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`knowledge.py` is the top of the internal dependency graph.
|
|
44
|
+
Nothing in `storage/`, `forgetting.py`, or `retriever.py` may import from `knowledge.py`.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Core types (`agentmemo.types`)
|
|
49
|
+
|
|
50
|
+
### `Fact`
|
|
51
|
+
The atomic unit of knowledge.
|
|
52
|
+
|
|
53
|
+
| Field | Type | Description |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `content` | `str` | Human-readable knowledge string |
|
|
56
|
+
| `type` | `MemoryType` | `semantic` / `procedural` / `episodic` |
|
|
57
|
+
| `importance` | `float` | 0.0–1.0; controls decay speed |
|
|
58
|
+
| `retention_score` | `float` | Current Ebbinghaus score (updated on recall) |
|
|
59
|
+
| `access_count` | `int` | Times retrieved — increases stability |
|
|
60
|
+
| `tags` | `list[str]` | Optional labels |
|
|
61
|
+
| `id` | `str` | 8-char UUID hex |
|
|
62
|
+
| `created_at` | `datetime` | UTC |
|
|
63
|
+
| `last_accessed` | `datetime` | UTC |
|
|
64
|
+
|
|
65
|
+
### `MemoryType`
|
|
66
|
+
`SEMANTIC` — facts about the world/user
|
|
67
|
+
`PROCEDURAL` — how the user wants things done
|
|
68
|
+
`EPISODIC` — specific past events
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Storage layer
|
|
73
|
+
|
|
74
|
+
### `StorageBackend` protocol
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
def save(self, agent_id: str, facts: list[Fact]) -> None: ...
|
|
78
|
+
def load(self, agent_id: str) -> list[Fact]: ...
|
|
79
|
+
def delete(self, agent_id: str, fact_id: str) -> None: ...
|
|
80
|
+
def list_agents(self) -> list[str]: ...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`save` is a **full replace** — the caller always loads, mutates, then saves.
|
|
84
|
+
|
|
85
|
+
Backends are responsible for:
|
|
86
|
+
- Namespacing by `agent_id`
|
|
87
|
+
- Serialising all `Fact` fields including datetime with UTC timezone
|
|
88
|
+
|
|
89
|
+
### YAMLStorage
|
|
90
|
+
File layout: `{base_dir}/{agent_id}/knowledge.yaml`
|
|
91
|
+
Key: `fact.id` (8-char hex)
|
|
92
|
+
Human-readable, Git-trackable, editable by hand.
|
|
93
|
+
|
|
94
|
+
### SQLiteStorage
|
|
95
|
+
Single `.db` file. Schema:
|
|
96
|
+
```sql
|
|
97
|
+
CREATE TABLE facts (
|
|
98
|
+
id TEXT, agent_id TEXT,
|
|
99
|
+
content TEXT, type TEXT,
|
|
100
|
+
importance REAL, retention REAL,
|
|
101
|
+
access_count INTEGER, tags TEXT,
|
|
102
|
+
created_at TEXT, last_accessed TEXT,
|
|
103
|
+
PRIMARY KEY (agent_id, id)
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Forgetting curve (`agentmemo.forgetting`)
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
retention(t) = exp(−t / stability)
|
|
113
|
+
|
|
114
|
+
stability = 168h × importance × (1 + ln(1 + access_count))
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- `t` = hours since `last_accessed`
|
|
118
|
+
- Base stability = 168 h (1 week) for `importance=1.0, access_count=0`
|
|
119
|
+
- Applied via `apply_decay(facts)` **before** every retrieval in `KnowledgeBase.recall()`
|
|
120
|
+
- After retrieval, `access_count` is incremented and `last_accessed` is updated → reinforcement
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Retrieval (`agentmemo.retriever`)
|
|
125
|
+
|
|
126
|
+
`TFIDFRetriever.search(query, facts, top_k)` — zero external dependencies.
|
|
127
|
+
|
|
128
|
+
Scoring:
|
|
129
|
+
```
|
|
130
|
+
hybrid_score = 0.6 × tfidf + 0.2 × retention_score + 0.2 × importance
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
TF-IDF is computed fresh per query (no index) — suitable for knowledge bases up to ~10k facts.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Extraction (`agentmemo.extractor`)
|
|
138
|
+
|
|
139
|
+
`Extractor.extract(turns)` sends the conversation to an LLM and parses the returned JSON array of facts.
|
|
140
|
+
Supports `openai` and `anthropic` providers via `httpx`.
|
|
141
|
+
Deduplication: Jaccard word-similarity ≥ 0.8 → keep first occurrence.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Extension points
|
|
146
|
+
|
|
147
|
+
| What | Where | Interface |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| New storage backend | `src/agentmemo/storage/` | `StorageBackend` protocol |
|
|
150
|
+
| New LLM provider | `Extractor._call_<provider>` | Returns `list[dict]` from LLM |
|
|
151
|
+
| New integration | `src/agentmemo/integrations/` | Import `KnowledgeBase`, wrap |
|
|
152
|
+
| New retriever | Replace `TFIDFRetriever` | `.search(query, facts, top_k)` |
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to agentmemo are documented here.
|
|
4
|
+
Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
5
|
+
Versioning: [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
### Planned
|
|
12
|
+
- MongoDB storage backend
|
|
13
|
+
- Qdrant and Weaviate backends
|
|
14
|
+
- Semantic embeddings (sentence-transformers / OpenAI)
|
|
15
|
+
- MCP server support
|
|
16
|
+
- LangChain / CrewAI integrations
|
|
17
|
+
- Web UI knowledge inspector
|
|
18
|
+
- REST API / sidecar mode
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [0.1.0] — 2026-03-28
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **Core `KnowledgeBase`** with `add`, `learn`, `recall`, `forget`, `decay`, `stats`
|
|
26
|
+
- **Ebbinghaus forgetting curve** — `forgetting.py`
|
|
27
|
+
`retention = exp(−t / stability)` where `stability = 336h × importance × (1 + ln(1 + access_count))`
|
|
28
|
+
- **TF-IDF retriever** — zero external dependencies, hybrid score with retention and importance boost
|
|
29
|
+
- **LLM fact extractor** — Jaccard deduplication, markdown fence stripping
|
|
30
|
+
- **6 LLM providers** — OpenAI, Anthropic (Claude), GigaChat (Sber), Yandex GPT, Qwen, generic OpenAI-compatible
|
|
31
|
+
- **Pluggable LLM providers** — `LLMProvider` Protocol with `call_with_retry()` shared retry logic
|
|
32
|
+
- **Provider factory** — `create_provider("openai"|"anthropic"|"gigachat"|"yandex"|"qwen"|"openai-compat")`
|
|
33
|
+
- **Env var API key resolution** — `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GIGACHAT_API_KEY`, `YANDEX_API_KEY`, `QWEN_API_KEY`, `LLM_API_KEY`
|
|
34
|
+
- **YAML storage backend** — human-readable, Git-trackable, editable by hand; thread-safe with per-file lock + atomic write
|
|
35
|
+
- **SQLite storage backend** — zero-server production storage with WAL mode
|
|
36
|
+
- **PostgreSQL storage backend** — provide a DSN, table auto-created; `pip install agentmemo[postgres]`
|
|
37
|
+
- **Configurable storage** — `create_storage("yaml"|"sqlite"|"postgres")` factory; CLI `--storage` / `--dsn` options
|
|
38
|
+
- **`StorageBackend` protocol** — plug-in interface for custom backends
|
|
39
|
+
- **OpenAI integration** — `MemoryEnabledOpenAI` wraps message lists with memory context injection
|
|
40
|
+
- **CLI** — `show`, `add`, `recall`, `stats`, `decay`, `clear`, `export`, `import` commands with `--data-dir`, `--storage`, `--dsn` group options
|
|
41
|
+
- **Core types** — `Fact`, `MemoryType` (StrEnum), `ConversationTurn`
|
|
42
|
+
- **Full test suite** — 235+ tests, 80%+ coverage, both backends parametrized, all LLM calls mocked
|
|
43
|
+
- **32 simulation scenarios** — end-to-end tests for memory, storage, providers, CLI, and integrations
|
|
44
|
+
- **Performance benchmarks** — `test_performance.py` with `@pytest.mark.slow`
|
|
45
|
+
- **pytest markers** — `unit`, `integration`, `slow`, `requires_api_key`
|
|
46
|
+
- **GitHub Actions CI** — lint + type check + test on Python 3.11 & 3.12
|
|
47
|
+
- **GitHub Actions publish** — PyPI Trusted Publishing on `v*` tags
|
|
48
|
+
- **PEP 561** — `py.typed` marker file
|
|
49
|
+
- **pre-commit config** — ruff lint+format + mypy hooks
|
|
50
|
+
- **Security policy** — `.github/SECURITY.md`
|
|
51
|
+
- **Project documentation** — README, CONTRIBUTING, ARCHITECTURE, DEVELOPMENT, skills/
|
|
52
|
+
|
|
53
|
+
### Changed (since initial development)
|
|
54
|
+
- Extractor refactored to use `LLMProvider` Protocol (removed duplicated retry logic)
|
|
55
|
+
- `KnowledgeBase.learn()` accepts provider name or `LLMProvider` instance + `**provider_kwargs`
|
|
56
|
+
- `MemoryEnabledOpenAI.enrich_messages()` is now a public method
|
|
57
|
+
- `datetime.UTC` alias used everywhere (Python 3.11+)
|
|
58
|
+
- Input validation in `KnowledgeBase.add()` and CLI `add`/`import` commands
|
|
59
|
+
- `BASE_STABILITY_HOURS` set to 336 (2 weeks retention baseline)
|
|
60
|
+
- TF-IDF tokenizer: camelCase splitting + basic plural stemming
|
|
61
|
+
|
|
62
|
+
[Unreleased]: https://github.com/alsoleg89/agentmemo/compare/v0.1.0...HEAD
|
|
63
|
+
[0.1.0]: https://github.com/alsoleg89/agentmemo/releases/tag/v0.1.0
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Dev Notes
|
|
2
|
+
|
|
3
|
+
## Git workflow
|
|
4
|
+
|
|
5
|
+
**Never push directly to `main`.** No exceptions.
|
|
6
|
+
|
|
7
|
+
- All changes go to a feature branch
|
|
8
|
+
- To merge into `main`: open a pull request, wait for maintainer approval
|
|
9
|
+
- Force-pushing `main` is forbidden
|
|
10
|
+
- To fix something on `main`: branch → commit → PR → merge
|
|
11
|
+
|
|
12
|
+
## Commit conventions
|
|
13
|
+
|
|
14
|
+
**Author**: commits must be attributed to the project maintainer:
|
|
15
|
+
`alsoleg89 <155813332+alsoleg89@users.noreply.github.com>`
|
|
16
|
+
|
|
17
|
+
Verify before pushing:
|
|
18
|
+
```bash
|
|
19
|
+
git log -1 --format="%an" # must be: alsoleg89
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Subject line** — keep it short and factual. Avoid:
|
|
23
|
+
- Tool or service names (editor, AI assistant, CI bot names)
|
|
24
|
+
- Internal workflow jargon (audit names, pipeline step names)
|
|
25
|
+
- Auto-generated session or trace URLs
|
|
26
|
+
|
|
27
|
+
**Body** — optional. If present: one blank line after subject, then context.
|
|
28
|
+
No auto-generated footers or URLs.
|
|
29
|
+
|
|
30
|
+
**Merge commits** — subject must not expose internal branch naming conventions.
|
|
31
|
+
|
|
32
|
+
## Sanity check before push
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Confirm author
|
|
36
|
+
git log --format="%an" | sort -u
|
|
37
|
+
|
|
38
|
+
# Confirm no leaked URLs
|
|
39
|
+
git log --format="%B" | grep "https://claude\|session_"
|
|
40
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive environment:
|
|
12
|
+
|
|
13
|
+
* Demonstrating empathy and kindness toward other people
|
|
14
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
* Giving and gracefully accepting constructive feedback
|
|
16
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
|
17
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior:
|
|
20
|
+
|
|
21
|
+
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
22
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
23
|
+
* Public or private harassment
|
|
24
|
+
* Publishing others' private information, such as a physical or email address, without their explicit permission
|
|
25
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement Responsibilities
|
|
28
|
+
|
|
29
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
30
|
+
|
|
31
|
+
## Scope
|
|
32
|
+
|
|
33
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces.
|
|
34
|
+
|
|
35
|
+
## Enforcement
|
|
36
|
+
|
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening a GitHub issue or contacting the maintainers directly via GitHub. All complaints will be reviewed and investigated promptly and fairly.
|
|
38
|
+
|
|
39
|
+
## Attribution
|
|
40
|
+
|
|
41
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|