synapto 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.
- synapto-0.1.0/.dockerignore +13 -0
- synapto-0.1.0/.env.example +25 -0
- synapto-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- synapto-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- synapto-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +18 -0
- synapto-0.1.0/.github/workflows/ci.yml +110 -0
- synapto-0.1.0/.github/workflows/release.yml +140 -0
- synapto-0.1.0/.gitignore +29 -0
- synapto-0.1.0/.tool-versions +2 -0
- synapto-0.1.0/CHANGELOG.md +33 -0
- synapto-0.1.0/CONTRIBUTING.md +111 -0
- synapto-0.1.0/Dockerfile +38 -0
- synapto-0.1.0/LICENSE +21 -0
- synapto-0.1.0/Makefile +47 -0
- synapto-0.1.0/PKG-INFO +269 -0
- synapto-0.1.0/README.md +226 -0
- synapto-0.1.0/docker-compose.yml +53 -0
- synapto-0.1.0/docs/agno.md +49 -0
- synapto-0.1.0/docs/claude-code.md +75 -0
- synapto-0.1.0/docs/cursor.md +41 -0
- synapto-0.1.0/docs/hrr.md +113 -0
- synapto-0.1.0/docs/langgraph.md +61 -0
- synapto-0.1.0/docs/migrations.md +67 -0
- synapto-0.1.0/docs/repository-pattern.md +173 -0
- synapto-0.1.0/docs/trust-scoring.md +55 -0
- synapto-0.1.0/migrations/001_initial.sql +82 -0
- synapto-0.1.0/migrations/002_add_hrr.sql +26 -0
- synapto-0.1.0/pyproject.toml +76 -0
- synapto-0.1.0/src/synapto/__init__.py +3 -0
- synapto-0.1.0/src/synapto/cli.py +620 -0
- synapto-0.1.0/src/synapto/config.py +125 -0
- synapto-0.1.0/src/synapto/db/__init__.py +1 -0
- synapto-0.1.0/src/synapto/db/migrations.py +300 -0
- synapto-0.1.0/src/synapto/db/postgres.py +88 -0
- synapto-0.1.0/src/synapto/db/redis_cache.py +103 -0
- synapto-0.1.0/src/synapto/decay/__init__.py +1 -0
- synapto-0.1.0/src/synapto/decay/maintenance.py +58 -0
- synapto-0.1.0/src/synapto/decay/scoring.py +50 -0
- synapto-0.1.0/src/synapto/embeddings/__init__.py +1 -0
- synapto-0.1.0/src/synapto/embeddings/base.py +31 -0
- synapto-0.1.0/src/synapto/embeddings/openai_provider.py +56 -0
- synapto-0.1.0/src/synapto/embeddings/registry.py +59 -0
- synapto-0.1.0/src/synapto/embeddings/sentence_transformer.py +53 -0
- synapto-0.1.0/src/synapto/graph/__init__.py +1 -0
- synapto-0.1.0/src/synapto/graph/entities.py +97 -0
- synapto-0.1.0/src/synapto/graph/relations.py +65 -0
- synapto-0.1.0/src/synapto/hrr/__init__.py +1 -0
- synapto-0.1.0/src/synapto/hrr/banks.py +74 -0
- synapto-0.1.0/src/synapto/hrr/core.py +160 -0
- synapto-0.1.0/src/synapto/hrr/retrieval.py +249 -0
- synapto-0.1.0/src/synapto/repositories/__init__.py +1 -0
- synapto-0.1.0/src/synapto/repositories/banks.py +54 -0
- synapto-0.1.0/src/synapto/repositories/entities.py +122 -0
- synapto-0.1.0/src/synapto/repositories/memories.py +204 -0
- synapto-0.1.0/src/synapto/repositories/relations.py +134 -0
- synapto-0.1.0/src/synapto/search/__init__.py +1 -0
- synapto-0.1.0/src/synapto/search/graph.py +178 -0
- synapto-0.1.0/src/synapto/search/hybrid.py +240 -0
- synapto-0.1.0/src/synapto/server.py +388 -0
- synapto-0.1.0/tests/__init__.py +0 -0
- synapto-0.1.0/tests/integration/__init__.py +0 -0
- synapto-0.1.0/tests/unit/__init__.py +0 -0
- synapto-0.1.0/tests/unit/conftest.py +37 -0
- synapto-0.1.0/tests/unit/test_cli.py +92 -0
- synapto-0.1.0/tests/unit/test_db.py +89 -0
- synapto-0.1.0/tests/unit/test_decay.py +66 -0
- synapto-0.1.0/tests/unit/test_embeddings.py +67 -0
- synapto-0.1.0/tests/unit/test_hrr.py +178 -0
- synapto-0.1.0/tests/unit/test_migrations.py +157 -0
- synapto-0.1.0/tests/unit/test_search_and_graph.py +240 -0
- synapto-0.1.0/uv.lock +3203 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Synapto — environment variables
|
|
2
|
+
# Copy this file to .env and adjust values for your setup.
|
|
3
|
+
# All variables are optional — sensible defaults are used when unset.
|
|
4
|
+
|
|
5
|
+
# PostgreSQL connection string
|
|
6
|
+
SYNAPTO_PG_DSN=postgresql://localhost/synapto
|
|
7
|
+
|
|
8
|
+
# Redis URL
|
|
9
|
+
SYNAPTO_REDIS_URL=redis://localhost:6379/0
|
|
10
|
+
|
|
11
|
+
# Default tenant (project/codebase scope for memory isolation)
|
|
12
|
+
SYNAPTO_DEFAULT_TENANT=default
|
|
13
|
+
|
|
14
|
+
# Embedding provider: leave empty for auto-select
|
|
15
|
+
# - auto-selects OpenAI if OPENAI_API_KEY is set, otherwise sentence-transformers (local)
|
|
16
|
+
# - valid values: sentence-transformers, openai
|
|
17
|
+
SYNAPTO_EMBEDDING_PROVIDER=
|
|
18
|
+
|
|
19
|
+
# Embedding model override (provider-specific)
|
|
20
|
+
# - sentence-transformers default: multi-qa-MiniLM-L6-cos-v1
|
|
21
|
+
# - openai default: text-embedding-3-small
|
|
22
|
+
SYNAPTO_EMBEDDING_MODEL=
|
|
23
|
+
|
|
24
|
+
# OpenAI API key (optional — only needed if using OpenAI embeddings)
|
|
25
|
+
OPENAI_API_KEY=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Report a bug or unexpected behavior
|
|
4
|
+
title: "[bug] "
|
|
5
|
+
labels: bug
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Description
|
|
9
|
+
|
|
10
|
+
A clear description of the bug.
|
|
11
|
+
|
|
12
|
+
## Steps to Reproduce
|
|
13
|
+
|
|
14
|
+
1. ...
|
|
15
|
+
2. ...
|
|
16
|
+
3. ...
|
|
17
|
+
|
|
18
|
+
## Expected Behavior
|
|
19
|
+
|
|
20
|
+
What you expected to happen.
|
|
21
|
+
|
|
22
|
+
## Actual Behavior
|
|
23
|
+
|
|
24
|
+
What actually happened. Include error messages or logs if available.
|
|
25
|
+
|
|
26
|
+
## Environment
|
|
27
|
+
|
|
28
|
+
- Synapto version:
|
|
29
|
+
- Python version:
|
|
30
|
+
- OS:
|
|
31
|
+
- PostgreSQL version:
|
|
32
|
+
- MCP client (Claude Code, Cursor, etc.):
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Suggest a new feature or improvement
|
|
4
|
+
title: "[feature] "
|
|
5
|
+
labels: enhancement
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Problem
|
|
9
|
+
|
|
10
|
+
What problem does this feature solve? Why is it needed?
|
|
11
|
+
|
|
12
|
+
## Proposed Solution
|
|
13
|
+
|
|
14
|
+
Describe your ideal solution.
|
|
15
|
+
|
|
16
|
+
## Alternatives Considered
|
|
17
|
+
|
|
18
|
+
Any other approaches you've thought about.
|
|
19
|
+
|
|
20
|
+
## Additional Context
|
|
21
|
+
|
|
22
|
+
Any extra context, mockups, or references.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Brief description of the changes.
|
|
4
|
+
|
|
5
|
+
## Related Issues
|
|
6
|
+
|
|
7
|
+
Closes #
|
|
8
|
+
|
|
9
|
+
## Changes
|
|
10
|
+
|
|
11
|
+
-
|
|
12
|
+
|
|
13
|
+
## Checklist
|
|
14
|
+
|
|
15
|
+
- [ ] Tests added/updated for new functionality
|
|
16
|
+
- [ ] `ruff check src/ tests/` passes with no errors
|
|
17
|
+
- [ ] `pytest tests/` passes locally
|
|
18
|
+
- [ ] Documentation updated (if applicable)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v6
|
|
17
|
+
with:
|
|
18
|
+
enable-cache: true
|
|
19
|
+
|
|
20
|
+
- name: set up python
|
|
21
|
+
run: uv python install 3.13
|
|
22
|
+
|
|
23
|
+
- name: install dependencies
|
|
24
|
+
run: uv sync --extra dev --python 3.13
|
|
25
|
+
env:
|
|
26
|
+
UV_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu
|
|
27
|
+
|
|
28
|
+
- name: ruff check
|
|
29
|
+
run: uv run ruff check src/ tests/
|
|
30
|
+
|
|
31
|
+
security:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: install uv
|
|
37
|
+
uses: astral-sh/setup-uv@v6
|
|
38
|
+
with:
|
|
39
|
+
enable-cache: true
|
|
40
|
+
|
|
41
|
+
- name: set up python
|
|
42
|
+
run: uv python install 3.13
|
|
43
|
+
|
|
44
|
+
- name: install dependencies
|
|
45
|
+
run: uv sync --extra dev --python 3.13
|
|
46
|
+
env:
|
|
47
|
+
UV_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu
|
|
48
|
+
|
|
49
|
+
- name: bandit security scan
|
|
50
|
+
run: uv run bandit -r src/synapto/ -c pyproject.toml
|
|
51
|
+
|
|
52
|
+
- name: pip-audit dependency scan
|
|
53
|
+
run: uv run pip-audit
|
|
54
|
+
|
|
55
|
+
test:
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
needs: [lint, security]
|
|
58
|
+
strategy:
|
|
59
|
+
matrix:
|
|
60
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
61
|
+
|
|
62
|
+
services:
|
|
63
|
+
postgres:
|
|
64
|
+
image: pgvector/pgvector:pg16
|
|
65
|
+
env:
|
|
66
|
+
POSTGRES_USER: synapto
|
|
67
|
+
POSTGRES_PASSWORD: synapto
|
|
68
|
+
POSTGRES_DB: synapto
|
|
69
|
+
ports:
|
|
70
|
+
- 5432:5432
|
|
71
|
+
options: >-
|
|
72
|
+
--health-cmd "pg_isready -U synapto"
|
|
73
|
+
--health-interval 5s
|
|
74
|
+
--health-timeout 3s
|
|
75
|
+
--health-retries 5
|
|
76
|
+
|
|
77
|
+
redis:
|
|
78
|
+
image: redis:7-alpine
|
|
79
|
+
ports:
|
|
80
|
+
- 6379:6379
|
|
81
|
+
options: >-
|
|
82
|
+
--health-cmd "redis-cli ping"
|
|
83
|
+
--health-interval 5s
|
|
84
|
+
--health-timeout 3s
|
|
85
|
+
--health-retries 5
|
|
86
|
+
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@v4
|
|
89
|
+
|
|
90
|
+
- name: install uv
|
|
91
|
+
uses: astral-sh/setup-uv@v6
|
|
92
|
+
with:
|
|
93
|
+
enable-cache: true
|
|
94
|
+
|
|
95
|
+
- name: set up python ${{ matrix.python-version }}
|
|
96
|
+
run: uv python install ${{ matrix.python-version }}
|
|
97
|
+
|
|
98
|
+
- name: install dependencies (cpu-only torch for ci)
|
|
99
|
+
run: uv sync --extra dev --python ${{ matrix.python-version }}
|
|
100
|
+
env:
|
|
101
|
+
UV_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu
|
|
102
|
+
|
|
103
|
+
- name: create pgvector extension
|
|
104
|
+
run: PGPASSWORD=synapto psql -h localhost -U synapto -d synapto -c "CREATE EXTENSION IF NOT EXISTS vector; CREATE EXTENSION IF NOT EXISTS pg_trgm;"
|
|
105
|
+
|
|
106
|
+
- name: test
|
|
107
|
+
env:
|
|
108
|
+
SYNAPTO_PG_DSN: postgresql://synapto:synapto@localhost:5432/synapto
|
|
109
|
+
SYNAPTO_REDIS_URL: redis://localhost:6379/1
|
|
110
|
+
run: uv run pytest tests/ -v --cov=synapto --cov-report=term-missing
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
bump_type:
|
|
7
|
+
description: "version bump type (use 'current' to publish without bumping)"
|
|
8
|
+
required: true
|
|
9
|
+
type: choice
|
|
10
|
+
options:
|
|
11
|
+
- current
|
|
12
|
+
- patch
|
|
13
|
+
- minor
|
|
14
|
+
- major
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
release:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
environment: release
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- name: check admin permission
|
|
27
|
+
uses: actions-cool/check-user-permission@v2
|
|
28
|
+
id: check
|
|
29
|
+
with:
|
|
30
|
+
require: admin
|
|
31
|
+
username: ${{ github.triggering_actor }}
|
|
32
|
+
|
|
33
|
+
- name: abort if not admin
|
|
34
|
+
if: steps.check.outputs.require-result != 'true'
|
|
35
|
+
run: |
|
|
36
|
+
echo "error: only repo admins can create releases"
|
|
37
|
+
exit 1
|
|
38
|
+
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
with:
|
|
41
|
+
fetch-depth: 0
|
|
42
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
43
|
+
|
|
44
|
+
- name: install uv
|
|
45
|
+
uses: astral-sh/setup-uv@v6
|
|
46
|
+
|
|
47
|
+
- name: set up python
|
|
48
|
+
run: uv python install 3.13
|
|
49
|
+
|
|
50
|
+
- name: install build tools
|
|
51
|
+
run: uv sync --extra dev --python 3.13
|
|
52
|
+
|
|
53
|
+
- name: bump version
|
|
54
|
+
id: bump
|
|
55
|
+
run: |
|
|
56
|
+
uv run python - <<'PYEOF'
|
|
57
|
+
import tomli, tomli_w, re, os
|
|
58
|
+
|
|
59
|
+
bump_type = "${{ inputs.bump_type }}"
|
|
60
|
+
|
|
61
|
+
with open("pyproject.toml", "rb") as f:
|
|
62
|
+
data = tomli.load(f)
|
|
63
|
+
|
|
64
|
+
current = data["project"]["version"]
|
|
65
|
+
|
|
66
|
+
if bump_type == "current":
|
|
67
|
+
new_version = current
|
|
68
|
+
else:
|
|
69
|
+
major, minor, patch = map(int, current.split("."))
|
|
70
|
+
if bump_type == "major":
|
|
71
|
+
major, minor, patch = major + 1, 0, 0
|
|
72
|
+
elif bump_type == "minor":
|
|
73
|
+
minor, patch = minor + 1, 0
|
|
74
|
+
else:
|
|
75
|
+
patch += 1
|
|
76
|
+
new_version = f"{major}.{minor}.{patch}"
|
|
77
|
+
|
|
78
|
+
# update pyproject.toml
|
|
79
|
+
data["project"]["version"] = new_version
|
|
80
|
+
with open("pyproject.toml", "wb") as f:
|
|
81
|
+
tomli_w.dump(data, f)
|
|
82
|
+
|
|
83
|
+
# update __init__.py
|
|
84
|
+
init_path = "src/synapto/__init__.py"
|
|
85
|
+
with open(init_path) as f:
|
|
86
|
+
content = f.read()
|
|
87
|
+
content = re.sub(r'__version__ = "[^"]+"', f'__version__ = "{new_version}"', content)
|
|
88
|
+
with open(init_path, "w") as f:
|
|
89
|
+
f.write(content)
|
|
90
|
+
|
|
91
|
+
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
|
|
92
|
+
f.write(f"version={new_version}\n")
|
|
93
|
+
f.write(f"previous={current}\n")
|
|
94
|
+
|
|
95
|
+
print(f"bumped {current} -> {new_version}")
|
|
96
|
+
PYEOF
|
|
97
|
+
|
|
98
|
+
- name: build package
|
|
99
|
+
run: uv run python -m build
|
|
100
|
+
|
|
101
|
+
- name: commit version bump
|
|
102
|
+
if: inputs.bump_type != 'current'
|
|
103
|
+
run: |
|
|
104
|
+
git config user.name "github-actions[bot]"
|
|
105
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
106
|
+
git add pyproject.toml src/synapto/__init__.py
|
|
107
|
+
git commit -m "chore(synapto): bump version to ${{ steps.bump.outputs.version }}"
|
|
108
|
+
git push origin main
|
|
109
|
+
|
|
110
|
+
- name: create tag
|
|
111
|
+
run: |
|
|
112
|
+
git config user.name "github-actions[bot]"
|
|
113
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
114
|
+
git tag "v${{ steps.bump.outputs.version }}"
|
|
115
|
+
git push origin "v${{ steps.bump.outputs.version }}"
|
|
116
|
+
|
|
117
|
+
- name: publish to pypi
|
|
118
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
119
|
+
|
|
120
|
+
- name: create github release
|
|
121
|
+
uses: softprops/action-gh-release@v2
|
|
122
|
+
with:
|
|
123
|
+
tag_name: "v${{ steps.bump.outputs.version }}"
|
|
124
|
+
name: "v${{ steps.bump.outputs.version }}"
|
|
125
|
+
body: |
|
|
126
|
+
## what's changed
|
|
127
|
+
|
|
128
|
+
see [CHANGELOG.md](https://github.com/ramonlimaramos/synapto/blob/main/CHANGELOG.md) for details.
|
|
129
|
+
|
|
130
|
+
### install / upgrade
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install synapto==${{ steps.bump.outputs.version }}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
or with auto-updates (recommended):
|
|
137
|
+
```json
|
|
138
|
+
{ "command": "uvx", "args": ["synapto", "serve"] }
|
|
139
|
+
```
|
|
140
|
+
files: dist/*
|
synapto-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
.env.*
|
|
16
|
+
!.env.example
|
|
17
|
+
*.log
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
*~
|
|
28
|
+
.DS_Store
|
|
29
|
+
tmp/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Synapto will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-04-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **MCP server** with 10 tools: remember, recall, relate, forget, trust_feedback, find_contradictions, graph_query, list_entities, memory_stats, maintain
|
|
12
|
+
- **3-way hybrid search** combining vector similarity (pgvector HNSW), full-text (tsvector + BM25), and HRR compositional algebra via Reciprocal Rank Fusion
|
|
13
|
+
- **holographic reduced representations (HRR)** for compositional memory queries — probe, reason, and contradict operations that no vector database can do
|
|
14
|
+
- **knowledge graph** with automatic entity extraction, directed relations, and N-hop recursive CTE traversal
|
|
15
|
+
- **time-based decay** with 4 depth layers: core (forever), stable (~6 months), working (~1 week), ephemeral (~6 hours)
|
|
16
|
+
- **trust scoring** with asymmetric feedback: helpful +0.05, unhelpful -0.10 for self-cleaning memory
|
|
17
|
+
- **memory banks** using HRR bundled superpositions for O(1) category-level queries
|
|
18
|
+
- **repository pattern** isolating all SQL into dedicated repository classes — zero raw SQL in business logic
|
|
19
|
+
- **CLI** with commands: serve, init, search, stats, doctor, migrate (up/down/status), export, import
|
|
20
|
+
- **interactive init** (`synapto init --interactive`) with MCP client auto-detection and uvx config
|
|
21
|
+
- **multi-tenant isolation** via tenant scoping on all tables
|
|
22
|
+
- **versioned SQL migrations** with up/down support and checksum validation
|
|
23
|
+
- **embedding providers**: sentence-transformers (CPU default) and OpenAI
|
|
24
|
+
- **CI pipeline** with lint (ruff), security (bandit), dependency audit (pip-audit), and tests across Python 3.11/3.12/3.13
|
|
25
|
+
- **documentation** for Claude Code, Cursor, LangGraph, Agno integration
|
|
26
|
+
- **docker compose** setup for quick start
|
|
27
|
+
- **uvx support** as recommended installation method for automatic updates
|
|
28
|
+
|
|
29
|
+
### Security
|
|
30
|
+
|
|
31
|
+
- all SQL queries use parameterized placeholders (no string interpolation)
|
|
32
|
+
- bandit static analysis integrated in CI
|
|
33
|
+
- pip-audit dependency scanning in CI
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Contributing to Synapto
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing to Synapto! This guide covers everything you need to get started.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Python 3.11+
|
|
8
|
+
- PostgreSQL 14+ with [pgvector](https://github.com/pgvector/pgvector)
|
|
9
|
+
- Redis 7+
|
|
10
|
+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
|
11
|
+
|
|
12
|
+
Or just use Docker:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
make docker-up # starts postgres + redis + synapto
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Development Setup
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/ramonlimaramos/synapto.git
|
|
22
|
+
cd synapto
|
|
23
|
+
|
|
24
|
+
# install with dev dependencies
|
|
25
|
+
uv sync --extra dev
|
|
26
|
+
# or: pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
# initialize the database
|
|
29
|
+
uv run synapto init
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Running Tests
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# full suite
|
|
36
|
+
uv run pytest tests/ -v
|
|
37
|
+
|
|
38
|
+
# with coverage
|
|
39
|
+
uv run pytest tests/ -v --cov=synapto --cov-report=term-missing
|
|
40
|
+
|
|
41
|
+
# specific file
|
|
42
|
+
uv run pytest tests/unit/test_hrr.py -v
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Tests require a running PostgreSQL (with pgvector) and Redis instance. Connection strings are read from environment variables:
|
|
46
|
+
|
|
47
|
+
| Variable | Default |
|
|
48
|
+
|----------|---------|
|
|
49
|
+
| `SYNAPTO_PG_DSN` | `postgresql://localhost/synapto` |
|
|
50
|
+
| `SYNAPTO_REDIS_URL` | `redis://localhost:6379/1` |
|
|
51
|
+
|
|
52
|
+
## Linting
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv run ruff check src/ tests/ # check code style
|
|
56
|
+
uv run ruff format --check src/ tests/ # check formatting
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
We use [ruff](https://docs.astral.sh/ruff/) for linting and formatting:
|
|
60
|
+
|
|
61
|
+
- Line length: 120 characters
|
|
62
|
+
- Target: Python 3.11+
|
|
63
|
+
- Rules: E, F, I, N, W, UP
|
|
64
|
+
|
|
65
|
+
## Code Style
|
|
66
|
+
|
|
67
|
+
- No ORM — raw SQL only (psycopg3)
|
|
68
|
+
- Type hints on all public functions
|
|
69
|
+
- Tests mirror the `src/` directory structure under `tests/unit/`
|
|
70
|
+
|
|
71
|
+
## Commit Format
|
|
72
|
+
|
|
73
|
+
All commit messages must be **lowercase** with a scoped prefix:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
feat(synapto): add new embedding provider
|
|
77
|
+
fix(synapto): handle empty query in hybrid search
|
|
78
|
+
docs(synapto): update quickstart guide
|
|
79
|
+
test(synapto): add graph traversal edge cases
|
|
80
|
+
chore(synapto): bump dependency versions
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Submitting Pull Requests
|
|
84
|
+
|
|
85
|
+
1. Fork the repository and create a branch from `main`
|
|
86
|
+
2. Make your changes, including tests for new functionality
|
|
87
|
+
3. Run `ruff check` and `pytest` to verify everything passes
|
|
88
|
+
4. Commit with the format described above
|
|
89
|
+
5. Open a PR against `main` with a clear description of what and why
|
|
90
|
+
|
|
91
|
+
### PR Requirements
|
|
92
|
+
|
|
93
|
+
- All CI checks must pass (lint + tests on Python 3.11/3.12/3.13)
|
|
94
|
+
- At least one maintainer approval is required
|
|
95
|
+
- Keep PRs focused — one feature or fix per PR
|
|
96
|
+
|
|
97
|
+
### PR Checklist
|
|
98
|
+
|
|
99
|
+
- [ ] Tests pass (`uv run pytest tests/`)
|
|
100
|
+
- [ ] Lint passes (`uv run ruff check src/ tests/`)
|
|
101
|
+
- [ ] New features include tests
|
|
102
|
+
- [ ] Commit messages follow the format above
|
|
103
|
+
- [ ] No new dependencies added without discussion
|
|
104
|
+
|
|
105
|
+
## Releases
|
|
106
|
+
|
|
107
|
+
Releases are published to PyPI and are **admin-only**. They are triggered manually via the GitHub Actions release workflow (`workflow_dispatch`). Contributors do not need to worry about versioning or publishing — maintainers handle this.
|
|
108
|
+
|
|
109
|
+
## Questions?
|
|
110
|
+
|
|
111
|
+
Open an [issue](https://github.com/ramonlimaramos/synapto/issues) or start a discussion on the repository.
|
synapto-0.1.0/Dockerfile
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# stage 1: builder
|
|
2
|
+
FROM python:3.13-slim AS builder
|
|
3
|
+
|
|
4
|
+
WORKDIR /app
|
|
5
|
+
|
|
6
|
+
COPY pyproject.toml README.md ./
|
|
7
|
+
COPY src/ src/
|
|
8
|
+
|
|
9
|
+
RUN pip install --no-cache-dir build && \
|
|
10
|
+
python -m build --wheel --outdir /app/dist
|
|
11
|
+
|
|
12
|
+
# stage 2: runtime
|
|
13
|
+
FROM python:3.13-slim
|
|
14
|
+
|
|
15
|
+
WORKDIR /app
|
|
16
|
+
|
|
17
|
+
RUN apt-get update && \
|
|
18
|
+
apt-get install -y --no-install-recommends libpq5 && \
|
|
19
|
+
rm -rf /var/lib/apt/lists/*
|
|
20
|
+
|
|
21
|
+
COPY --from=builder /app/dist/*.whl /tmp/
|
|
22
|
+
|
|
23
|
+
RUN pip install --no-cache-dir /tmp/*.whl && \
|
|
24
|
+
rm -f /tmp/*.whl
|
|
25
|
+
|
|
26
|
+
# pre-download the default embedding model so first run is fast
|
|
27
|
+
RUN python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('multi-qa-MiniLM-L6-cos-v1')"
|
|
28
|
+
|
|
29
|
+
COPY .env.example /app/.env.example
|
|
30
|
+
|
|
31
|
+
ENV SYNAPTO_PG_DSN=postgresql://synapto:synapto@postgres:5432/synapto
|
|
32
|
+
ENV SYNAPTO_REDIS_URL=redis://redis:6379/0
|
|
33
|
+
|
|
34
|
+
# optional SSE transport
|
|
35
|
+
EXPOSE 8080
|
|
36
|
+
|
|
37
|
+
ENTRYPOINT ["synapto"]
|
|
38
|
+
CMD ["serve"]
|
synapto-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ramon de Lima Ramos
|
|
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.
|
synapto-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.DEFAULT_GOAL := help
|
|
2
|
+
|
|
3
|
+
.PHONY: help install dev test lint format security audit serve init doctor docker-up docker-down clean
|
|
4
|
+
|
|
5
|
+
help: ## show this help
|
|
6
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
|
|
7
|
+
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
|
8
|
+
|
|
9
|
+
install: ## install synapto
|
|
10
|
+
uv sync
|
|
11
|
+
|
|
12
|
+
dev: ## install with dev extras (tests, linting)
|
|
13
|
+
uv sync --extra dev
|
|
14
|
+
|
|
15
|
+
test: ## run tests with pytest
|
|
16
|
+
uv run pytest tests/ -v
|
|
17
|
+
|
|
18
|
+
lint: ## run ruff linter
|
|
19
|
+
uv run ruff check src/ tests/
|
|
20
|
+
|
|
21
|
+
format: ## format code with ruff
|
|
22
|
+
uv run ruff format src/ tests/
|
|
23
|
+
|
|
24
|
+
security: ## run bandit security scan
|
|
25
|
+
uv run bandit -r src/synapto/ -c pyproject.toml
|
|
26
|
+
|
|
27
|
+
audit: ## audit dependencies for known vulnerabilities
|
|
28
|
+
uv run pip-audit
|
|
29
|
+
|
|
30
|
+
serve: ## start the mcp server (stdio)
|
|
31
|
+
uv run synapto serve
|
|
32
|
+
|
|
33
|
+
init: ## initialize database and config
|
|
34
|
+
uv run synapto init
|
|
35
|
+
|
|
36
|
+
doctor: ## check system health
|
|
37
|
+
uv run synapto doctor
|
|
38
|
+
|
|
39
|
+
docker-up: ## start all services with docker compose
|
|
40
|
+
docker compose up -d
|
|
41
|
+
|
|
42
|
+
docker-down: ## stop all docker compose services
|
|
43
|
+
docker compose down
|
|
44
|
+
|
|
45
|
+
clean: ## remove build artifacts and caches
|
|
46
|
+
rm -rf dist/ build/ *.egg-info/ .pytest_cache/ .ruff_cache/ htmlcov/
|
|
47
|
+
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|