basic-memory 0.1.1__tar.gz → 0.1.2__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.
Potentially problematic release.
This version of basic-memory might be problematic. Click here for more details.
- {basic_memory-0.1.1 → basic_memory-0.1.2}/.github/workflows/test.yml +4 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/.gitignore +16 -14
- {basic_memory-0.1.1 → basic_memory-0.1.2}/CHANGELOG.md +14 -0
- basic_memory-0.1.2/Makefile +42 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/PKG-INFO +2 -7
- basic_memory-0.1.2/alembic.ini +119 -0
- basic_memory-0.1.2/installer/installer.py +89 -0
- basic_memory-0.1.2/installer/setup.py +40 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/pyproject.toml +17 -10
- basic_memory-0.1.2/scripts/install.sh +36 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/__init__.py +1 -1
- basic_memory-0.1.2/src/basic_memory/alembic/README +1 -0
- basic_memory-0.1.2/src/basic_memory/alembic/env.py +75 -0
- basic_memory-0.1.2/src/basic_memory/alembic/migrations.py +29 -0
- basic_memory-0.1.2/src/basic_memory/alembic/script.py.mako +26 -0
- basic_memory-0.1.2/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +93 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/__init__.py +2 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/app.py +26 -24
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/routers/knowledge_router.py +28 -26
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/routers/memory_router.py +17 -11
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/routers/search_router.py +6 -12
- basic_memory-0.1.2/src/basic_memory/cli/__init__.py +1 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/cli/app.py +0 -1
- basic_memory-0.1.2/src/basic_memory/cli/commands/__init__.py +5 -0
- basic_memory-0.1.2/src/basic_memory/cli/commands/db.py +25 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/cli/commands/import_memory_json.py +35 -31
- basic_memory-0.1.2/src/basic_memory/cli/commands/mcp.py +20 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/cli/commands/status.py +10 -6
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/cli/commands/sync.py +5 -56
- basic_memory-0.1.2/src/basic_memory/cli/main.py +14 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/config.py +3 -3
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/db.py +15 -22
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/deps.py +3 -4
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/file_utils.py +36 -35
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/markdown/entity_parser.py +13 -30
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/markdown/markdown_processor.py +7 -7
- basic_memory-0.1.2/src/basic_memory/markdown/plugins.py +222 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/markdown/schemas.py +7 -8
- basic_memory-0.1.2/src/basic_memory/markdown/utils.py +93 -0
- basic_memory-0.1.2/src/basic_memory/mcp/__init__.py +1 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/async_client.py +0 -2
- basic_memory-0.1.2/src/basic_memory/mcp/server.py +15 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/tools/__init__.py +5 -3
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/tools/knowledge.py +2 -2
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/tools/memory.py +8 -4
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/tools/search.py +2 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/tools/utils.py +1 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/models/__init__.py +1 -2
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/models/base.py +3 -3
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/models/knowledge.py +23 -60
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/models/search.py +1 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/repository/__init__.py +5 -3
- basic_memory-0.1.2/src/basic_memory/repository/entity_repository.py +92 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/repository/relation_repository.py +0 -7
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/repository/repository.py +2 -39
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/repository/search_repository.py +20 -25
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/__init__.py +4 -4
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/base.py +21 -62
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/delete.py +2 -3
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/discovery.py +4 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/memory.py +12 -13
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/request.py +4 -23
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/response.py +10 -9
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/schemas/search.py +4 -7
- basic_memory-0.1.2/src/basic_memory/services/__init__.py +7 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/services/context_service.py +116 -110
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/services/entity_service.py +25 -62
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/services/exceptions.py +1 -0
- basic_memory-0.1.2/src/basic_memory/services/file_service.py +176 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/services/link_resolver.py +9 -9
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/services/search_service.py +22 -15
- basic_memory-0.1.2/src/basic_memory/services/service.py +15 -0
- basic_memory-0.1.2/src/basic_memory/sync/__init__.py +5 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/sync/file_change_scanner.py +3 -7
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/sync/sync_service.py +35 -40
- basic_memory-0.1.2/src/basic_memory/sync/utils.py +34 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/sync/watch_service.py +26 -5
- basic_memory-0.1.2/src/basic_memory/utils.py +87 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/api/test_knowledge_router.py +18 -6
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/api/test_memory_router.py +1 -10
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/api/test_resource_router.py +1 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/api/test_search_router.py +8 -8
- basic_memory-0.1.2/tests/cli/test_import_memory_json.py +134 -0
- basic_memory-0.1.2/tests/cli/test_status.py +160 -0
- basic_memory-0.1.2/tests/cli/test_sync.py +109 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/conftest.py +113 -161
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/edit_file_test.py +5 -3
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/markdown/test_entity_parser.py +67 -14
- basic_memory-0.1.2/tests/markdown/test_markdown_plugins.py +165 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/markdown/test_markdown_processor.py +3 -3
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/markdown/test_observation_edge_cases.py +0 -1
- basic_memory-0.1.2/tests/markdown/test_task_detection.py +17 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/mcp/conftest.py +2 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/mcp/test_tool_get_entity.py +2 -5
- basic_memory-0.1.2/tests/mcp/test_tool_knowledge.py +87 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/mcp/test_tool_notes.py +14 -9
- basic_memory-0.1.2/tests/mcp/test_tool_search.py +65 -0
- basic_memory-0.1.2/tests/mcp/test_tool_utils.py +140 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/repository/test_entity_repository.py +0 -150
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/repository/test_repository.py +37 -45
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/schemas/test_memory_url.py +3 -5
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/schemas/test_schemas.py +2 -2
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/schemas/test_search.py +19 -14
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/services/test_context_service.py +15 -42
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/services/test_entity_service.py +55 -23
- basic_memory-0.1.2/tests/services/test_file_service.py +164 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/services/test_link_resolver.py +32 -39
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/services/test_search_service.py +10 -6
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/sync/test_sync_service.py +42 -48
- basic_memory-0.1.2/tests/sync/test_watch_service.py +121 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/test_basic_memory.py +1 -1
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/utils/test_file_utils.py +22 -14
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/utils/test_permalink_formatting.py +10 -5
- {basic_memory-0.1.1 → basic_memory-0.1.2}/uv.lock +399 -123
- basic_memory-0.1.1/Makefile +0 -39
- basic_memory-0.1.1/src/basic_memory/cli/__init__.py +0 -1
- basic_memory-0.1.1/src/basic_memory/cli/commands/__init__.py +0 -5
- basic_memory-0.1.1/src/basic_memory/cli/main.py +0 -47
- basic_memory-0.1.1/src/basic_memory/markdown/plugins.py +0 -236
- basic_memory-0.1.1/src/basic_memory/markdown/utils.py +0 -144
- basic_memory-0.1.1/src/basic_memory/mcp/__init__.py +0 -1
- basic_memory-0.1.1/src/basic_memory/mcp/main.py +0 -21
- basic_memory-0.1.1/src/basic_memory/mcp/server.py +0 -39
- basic_memory-0.1.1/src/basic_memory/mcp/tools/ai_edit.py +0 -84
- basic_memory-0.1.1/src/basic_memory/repository/entity_repository.py +0 -156
- basic_memory-0.1.1/src/basic_memory/services/__init__.py +0 -12
- basic_memory-0.1.1/src/basic_memory/services/database_service.py +0 -159
- basic_memory-0.1.1/src/basic_memory/services/file_service.py +0 -212
- basic_memory-0.1.1/src/basic_memory/services/service.py +0 -36
- basic_memory-0.1.1/src/basic_memory/sync/__init__.py +0 -5
- basic_memory-0.1.1/src/basic_memory/sync/utils.py +0 -66
- basic_memory-0.1.1/src/basic_memory/utils.py +0 -78
- basic_memory-0.1.1/tests/cli/test_import_memory_json.py +0 -175
- basic_memory-0.1.1/tests/markdown/test_markdown_plugins.py +0 -163
- basic_memory-0.1.1/tests/mcp/test_tool_ai_edit.py +0 -95
- basic_memory-0.1.1/tests/services/test_database_service.py +0 -158
- basic_memory-0.1.1/tests/services/test_file_service.py +0 -372
- basic_memory-0.1.1/tests/sync/test_watch_service.py +0 -154
- {basic_memory-0.1.1 → basic_memory-0.1.2}/.github/workflows/release.yml +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/.python-version +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/CITATION.cff +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/CODE_OF_CONDUCT.md +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/CONTRIBUTING.md +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/LICENSE +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/README.md +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/basic-memory.md +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/memory.json +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/routers/__init__.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/api/routers/resource_router.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/markdown/__init__.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/mcp/tools/notes.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/src/basic_memory/repository/observation_repository.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tasks.md +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/api/conftest.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/markdown/__init__.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/markdown/test_parser_edge_cases.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/markdown/test_relation_edge_cases.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/mcp/test_tool_memory.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/repository/test_observation_repository.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/repository/test_relation_repository.py +0 -0
- {basic_memory-0.1.1 → basic_memory-0.1.2}/tests/sync/test_file_change_scanner.py +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
# Python
|
|
2
|
-
__pycache__/
|
|
3
1
|
*.py[cod]
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
__pycache__/
|
|
3
|
+
.pytest_cache/
|
|
4
|
+
.coverage
|
|
5
|
+
htmlcov/
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
6
8
|
.Python
|
|
7
9
|
build/
|
|
8
10
|
develop-eggs/
|
|
@@ -20,7 +22,12 @@ wheels/
|
|
|
20
22
|
.installed.cfg
|
|
21
23
|
*.egg
|
|
22
24
|
|
|
23
|
-
#
|
|
25
|
+
# Installer artifacts
|
|
26
|
+
installer/build/
|
|
27
|
+
installer/dist/
|
|
28
|
+
rw.*.dmg # Temporary disk images
|
|
29
|
+
|
|
30
|
+
# Virtual environments
|
|
24
31
|
.env
|
|
25
32
|
.venv
|
|
26
33
|
env/
|
|
@@ -30,13 +37,8 @@ ENV/
|
|
|
30
37
|
# IDE
|
|
31
38
|
.idea/
|
|
32
39
|
.vscode/
|
|
40
|
+
*.swp
|
|
41
|
+
*.swo
|
|
33
42
|
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
projects/*.db-journal
|
|
37
|
-
/.coverage
|
|
38
|
-
|
|
39
|
-
**/.DS_Store
|
|
40
|
-
|
|
41
|
-
*.log
|
|
42
|
-
/.coverage.*
|
|
43
|
+
# macOS
|
|
44
|
+
.DS_Store
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.1.2 (2025-02-14)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- Fix installer for mac
|
|
9
|
+
([`dde9ff2`](https://github.com/basicmachines-co/basic-memory/commit/dde9ff228b72852b5abc58faa1b5e7c6f8d2c477))
|
|
10
|
+
|
|
11
|
+
- Remove unused FileChange dataclass
|
|
12
|
+
([`eb3360c`](https://github.com/basicmachines-co/basic-memory/commit/eb3360cc221f892b12a17137ae740819d48248e8))
|
|
13
|
+
|
|
14
|
+
- Update uv installer url
|
|
15
|
+
([`2f9178b`](https://github.com/basicmachines-co/basic-memory/commit/2f9178b0507b3b69207d5c80799f2d2f573c9a04))
|
|
16
|
+
|
|
17
|
+
|
|
4
18
|
## v0.1.1 (2025-02-07)
|
|
5
19
|
|
|
6
20
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
.PHONY: install test lint clean format type-check installer-mac installer-win
|
|
2
|
+
|
|
3
|
+
install:
|
|
4
|
+
pip install -e ".[dev]"
|
|
5
|
+
|
|
6
|
+
test:
|
|
7
|
+
pytest -p pytest_mock -v
|
|
8
|
+
|
|
9
|
+
lint:
|
|
10
|
+
ruff check . --fix
|
|
11
|
+
|
|
12
|
+
type-check:
|
|
13
|
+
uv run pyright
|
|
14
|
+
|
|
15
|
+
clean:
|
|
16
|
+
find . -type f -name '*.pyc' -delete
|
|
17
|
+
find . -type d -name '__pycache__' -exec rm -r {} +
|
|
18
|
+
rm -rf installer/build/
|
|
19
|
+
rm -rf installer/dist/
|
|
20
|
+
rm -f rw.*.dmg
|
|
21
|
+
rm -rf dist
|
|
22
|
+
rm -rf installer/build
|
|
23
|
+
rm -rf installer/dist
|
|
24
|
+
rm -f .coverage.*
|
|
25
|
+
|
|
26
|
+
format:
|
|
27
|
+
uv run ruff format .
|
|
28
|
+
|
|
29
|
+
# run inspector tool
|
|
30
|
+
run-dev:
|
|
31
|
+
uv run mcp dev src/basic_memory/mcp/main.py
|
|
32
|
+
|
|
33
|
+
# Build app installer
|
|
34
|
+
installer-mac:
|
|
35
|
+
cd installer && uv run python setup.py bdist_mac
|
|
36
|
+
|
|
37
|
+
installer-win:
|
|
38
|
+
cd installer && uv run python setup.py bdist_win32
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
update-deps:
|
|
42
|
+
uv lock f--upgrade
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
|
|
5
5
|
Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
|
|
6
6
|
Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
|
|
@@ -23,17 +23,12 @@ Requires-Dist: pydantic[email,timezone]>=2.10.3
|
|
|
23
23
|
Requires-Dist: pyright>=1.1.390
|
|
24
24
|
Requires-Dist: python-frontmatter>=1.1.0
|
|
25
25
|
Requires-Dist: pyyaml>=6.0.1
|
|
26
|
+
Requires-Dist: qasync>=0.27.1
|
|
26
27
|
Requires-Dist: rich>=13.9.4
|
|
27
28
|
Requires-Dist: sqlalchemy>=2.0.0
|
|
28
29
|
Requires-Dist: typer>=0.9.0
|
|
29
30
|
Requires-Dist: unidecode>=1.3.8
|
|
30
31
|
Requires-Dist: watchfiles>=1.0.4
|
|
31
|
-
Provides-Extra: dev
|
|
32
|
-
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
33
|
-
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
34
|
-
Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
|
|
35
|
-
Requires-Dist: pytest>=8.3.4; extra == 'dev'
|
|
36
|
-
Requires-Dist: ruff>=0.1.6; extra == 'dev'
|
|
37
32
|
Description-Content-Type: text/markdown
|
|
38
33
|
|
|
39
34
|
# Basic Memory
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# A generic, single database configuration.
|
|
2
|
+
|
|
3
|
+
[alembic]
|
|
4
|
+
# path to migration scripts
|
|
5
|
+
# Use forward slashes (/) also on windows to provide an os agnostic path
|
|
6
|
+
script_location = src/basic_memory/alembic
|
|
7
|
+
|
|
8
|
+
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
|
|
9
|
+
# Uncomment the line below if you want the files to be prepended with date and time
|
|
10
|
+
# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
|
|
11
|
+
# for all available tokens
|
|
12
|
+
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
|
|
13
|
+
|
|
14
|
+
# sys.path path, will be prepended to sys.path if present.
|
|
15
|
+
# defaults to the current working directory.
|
|
16
|
+
prepend_sys_path = .
|
|
17
|
+
|
|
18
|
+
# timezone to use when rendering the date within the migration file
|
|
19
|
+
# as well as the filename.
|
|
20
|
+
# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
|
|
21
|
+
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
|
|
22
|
+
# string value is passed to ZoneInfo()
|
|
23
|
+
# leave blank for localtime
|
|
24
|
+
# timezone =
|
|
25
|
+
|
|
26
|
+
# max length of characters to apply to the "slug" field
|
|
27
|
+
# truncate_slug_length = 40
|
|
28
|
+
|
|
29
|
+
# set to 'true' to run the environment during
|
|
30
|
+
# the 'revision' command, regardless of autogenerate
|
|
31
|
+
# revision_environment = false
|
|
32
|
+
|
|
33
|
+
# set to 'true' to allow .pyc and .pyo files without
|
|
34
|
+
# a source .py file to be detected as revisions in the
|
|
35
|
+
# versions/ directory
|
|
36
|
+
# sourceless = false
|
|
37
|
+
|
|
38
|
+
# version location specification; This defaults
|
|
39
|
+
# to migrations/versions. When using multiple version
|
|
40
|
+
# directories, initial revisions must be specified with --version-path.
|
|
41
|
+
# The path separator used here should be the separator specified by "version_path_separator" below.
|
|
42
|
+
# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions
|
|
43
|
+
|
|
44
|
+
# version path separator; As mentioned above, this is the character used to split
|
|
45
|
+
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
|
|
46
|
+
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
|
|
47
|
+
# Valid values for version_path_separator are:
|
|
48
|
+
#
|
|
49
|
+
# version_path_separator = :
|
|
50
|
+
# version_path_separator = ;
|
|
51
|
+
# version_path_separator = space
|
|
52
|
+
# version_path_separator = newline
|
|
53
|
+
#
|
|
54
|
+
# Use os.pathsep. Default configuration used for new projects.
|
|
55
|
+
version_path_separator = os
|
|
56
|
+
|
|
57
|
+
# set to 'true' to search source files recursively
|
|
58
|
+
# in each "version_locations" directory
|
|
59
|
+
# new in Alembic version 1.10
|
|
60
|
+
# recursive_version_locations = false
|
|
61
|
+
|
|
62
|
+
# the output encoding used when revision files
|
|
63
|
+
# are written from script.py.mako
|
|
64
|
+
# output_encoding = utf-8
|
|
65
|
+
|
|
66
|
+
sqlalchemy.url = driver://user:pass@localhost/dbname
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
[post_write_hooks]
|
|
70
|
+
# post_write_hooks defines scripts or Python functions that are run
|
|
71
|
+
# on newly generated revision scripts. See the documentation for further
|
|
72
|
+
# detail and examples
|
|
73
|
+
|
|
74
|
+
# format using "black" - use the console_scripts runner, against the "black" entrypoint
|
|
75
|
+
# hooks = black
|
|
76
|
+
# black.type = console_scripts
|
|
77
|
+
# black.entrypoint = black
|
|
78
|
+
# black.options = -l 79 REVISION_SCRIPT_FILENAME
|
|
79
|
+
|
|
80
|
+
# lint with attempts to fix using "ruff" - use the exec runner, execute a binary
|
|
81
|
+
# hooks = ruff
|
|
82
|
+
# ruff.type = exec
|
|
83
|
+
# ruff.executable = %(here)s/.venv/bin/ruff
|
|
84
|
+
# ruff.options = --fix REVISION_SCRIPT_FILENAME
|
|
85
|
+
|
|
86
|
+
# Logging configuration
|
|
87
|
+
[loggers]
|
|
88
|
+
keys = root,sqlalchemy,alembic
|
|
89
|
+
|
|
90
|
+
[handlers]
|
|
91
|
+
keys = console
|
|
92
|
+
|
|
93
|
+
[formatters]
|
|
94
|
+
keys = generic
|
|
95
|
+
|
|
96
|
+
[logger_root]
|
|
97
|
+
level = WARNING
|
|
98
|
+
handlers = console
|
|
99
|
+
qualname =
|
|
100
|
+
|
|
101
|
+
[logger_sqlalchemy]
|
|
102
|
+
level = WARNING
|
|
103
|
+
handlers =
|
|
104
|
+
qualname = sqlalchemy.engine
|
|
105
|
+
|
|
106
|
+
[logger_alembic]
|
|
107
|
+
level = INFO
|
|
108
|
+
handlers =
|
|
109
|
+
qualname = alembic
|
|
110
|
+
|
|
111
|
+
[handler_console]
|
|
112
|
+
class = StreamHandler
|
|
113
|
+
args = (sys.stderr,)
|
|
114
|
+
level = NOTSET
|
|
115
|
+
formatter = generic
|
|
116
|
+
|
|
117
|
+
[formatter_generic]
|
|
118
|
+
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
119
|
+
datefmt = %H:%M:%S
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
# Use tkinter for GUI alerts on macOS
|
|
7
|
+
if sys.platform == "darwin":
|
|
8
|
+
import tkinter as tk
|
|
9
|
+
from tkinter import messagebox
|
|
10
|
+
|
|
11
|
+
def ensure_uv_installed():
|
|
12
|
+
"""Check if uv is installed, install if not."""
|
|
13
|
+
try:
|
|
14
|
+
subprocess.run(["uv", "--version"], capture_output=True, check=True)
|
|
15
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
16
|
+
print("Installing uv package manager...")
|
|
17
|
+
subprocess.run(
|
|
18
|
+
[
|
|
19
|
+
"curl",
|
|
20
|
+
"-LsSf",
|
|
21
|
+
"https://astral.sh/uv/install.sh",
|
|
22
|
+
"|",
|
|
23
|
+
"sh",
|
|
24
|
+
],
|
|
25
|
+
shell=True,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_config_path():
|
|
30
|
+
"""Get Claude Desktop config path for current platform."""
|
|
31
|
+
if sys.platform == "darwin":
|
|
32
|
+
return Path.home() / "Library/Application Support/Claude/claude_desktop_config.json"
|
|
33
|
+
elif sys.platform == "win32":
|
|
34
|
+
return Path.home() / "AppData/Roaming/Claude/claude_desktop_config.json"
|
|
35
|
+
else:
|
|
36
|
+
raise RuntimeError(f"Unsupported platform: {sys.platform}")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def update_claude_config():
|
|
40
|
+
"""Update Claude Desktop config to include basic-memory."""
|
|
41
|
+
config_path = get_config_path()
|
|
42
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
|
|
44
|
+
# Load existing config or create new
|
|
45
|
+
if config_path.exists():
|
|
46
|
+
config = json.loads(config_path.read_text())
|
|
47
|
+
else:
|
|
48
|
+
config = {"mcpServers": {}}
|
|
49
|
+
|
|
50
|
+
# Add/update basic-memory config
|
|
51
|
+
config["mcpServers"]["basic-memory"] = {"command": "uvx", "args": ["basic-memory", "mcp"]}
|
|
52
|
+
|
|
53
|
+
# Write back config
|
|
54
|
+
config_path.write_text(json.dumps(config, indent=2))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def print_completion_message():
|
|
58
|
+
"""Show completion message with helpful tips."""
|
|
59
|
+
message = """Installation complete! Basic Memory is now available in Claude Desktop.
|
|
60
|
+
|
|
61
|
+
Please restart Claude Desktop for changes to take effect.
|
|
62
|
+
|
|
63
|
+
Quick Start:
|
|
64
|
+
1. You can run sync directly using: uvx basic-memory sync
|
|
65
|
+
2. Optionally, install globally with: uv pip install basic-memory
|
|
66
|
+
|
|
67
|
+
Built with ♥️ by Basic Machines."""
|
|
68
|
+
|
|
69
|
+
if sys.platform == "darwin":
|
|
70
|
+
# Show GUI message on macOS
|
|
71
|
+
root = tk.Tk()
|
|
72
|
+
root.withdraw() # Hide the main window
|
|
73
|
+
messagebox.showinfo("Basic Memory", message)
|
|
74
|
+
root.destroy()
|
|
75
|
+
else:
|
|
76
|
+
# Fallback to console output
|
|
77
|
+
print(message)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def main():
|
|
81
|
+
print("Welcome to Basic Memory installer")
|
|
82
|
+
ensure_uv_installed()
|
|
83
|
+
print("Configuring Claude Desktop...")
|
|
84
|
+
update_claude_config()
|
|
85
|
+
print_completion_message()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from cx_Freeze import setup, Executable
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# Build options for all platforms
|
|
5
|
+
build_exe_options = {
|
|
6
|
+
"packages": ["json", "pathlib"],
|
|
7
|
+
"excludes": [],
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
# Platform-specific options
|
|
11
|
+
if sys.platform == "win32":
|
|
12
|
+
base = "Win32GUI" # Use GUI base for Windows
|
|
13
|
+
build_exe_options.update({
|
|
14
|
+
"include_msvcr": True, # Include Visual C++ runtime
|
|
15
|
+
})
|
|
16
|
+
target_name = "Basic Memory Installer.exe"
|
|
17
|
+
else: # darwin
|
|
18
|
+
base = None # Don't use GUI base for macOS
|
|
19
|
+
target_name = "Basic Memory Installer"
|
|
20
|
+
|
|
21
|
+
executables = [
|
|
22
|
+
Executable(
|
|
23
|
+
script="installer.py",
|
|
24
|
+
target_name=target_name,
|
|
25
|
+
base=base,
|
|
26
|
+
)
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
setup(
|
|
30
|
+
name="basic-memory",
|
|
31
|
+
version=open("../pyproject.toml").read().split('version = "', 1)[1].split('"', 1)[0],
|
|
32
|
+
description="Basic Memory - Local-first knowledge management",
|
|
33
|
+
options={
|
|
34
|
+
"build_exe": build_exe_options,
|
|
35
|
+
"bdist_mac": {
|
|
36
|
+
"bundle_name": "Basic Memory Installer",
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
executables=executables,
|
|
40
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "basic-memory"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "Local-first knowledge management combining Zettelkasten with knowledge graphs"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12.1"
|
|
@@ -28,16 +28,9 @@ dependencies = [
|
|
|
28
28
|
"watchfiles>=1.0.4",
|
|
29
29
|
"fastapi[standard]>=0.115.8",
|
|
30
30
|
"alembic>=1.14.1",
|
|
31
|
+
"qasync>=0.27.1",
|
|
31
32
|
]
|
|
32
33
|
|
|
33
|
-
[project.optional-dependencies]
|
|
34
|
-
dev = [
|
|
35
|
-
"pytest>=8.3.4",
|
|
36
|
-
"pytest-cov>=4.1.0",
|
|
37
|
-
"pytest-mock>=3.12.0",
|
|
38
|
-
"pytest-asyncio>=0.24.0",
|
|
39
|
-
"ruff>=0.1.6",
|
|
40
|
-
]
|
|
41
34
|
|
|
42
35
|
[project.urls]
|
|
43
36
|
Homepage = "https://github.com/basicmachines-co/basic-memory"
|
|
@@ -64,10 +57,22 @@ target-version = "py312"
|
|
|
64
57
|
|
|
65
58
|
[tool.uv]
|
|
66
59
|
dev-dependencies = [
|
|
60
|
+
"gevent>=24.11.1",
|
|
67
61
|
"icecream>=2.1.3",
|
|
62
|
+
"pytest>=8.3.4",
|
|
63
|
+
"pytest-cov>=4.1.0",
|
|
64
|
+
"pytest-mock>=3.12.0",
|
|
65
|
+
"pytest-asyncio>=0.24.0",
|
|
66
|
+
"ruff>=0.1.6",
|
|
67
|
+
"pytest>=8.3.4",
|
|
68
|
+
"pytest-cov>=4.1.0",
|
|
69
|
+
"pytest-mock>=3.12.0",
|
|
70
|
+
"pytest-asyncio>=0.24.0",
|
|
71
|
+
"ruff>=0.1.6",
|
|
72
|
+
"cx-freeze>=7.2.10",
|
|
73
|
+
"pyqt6>=6.8.1",
|
|
68
74
|
]
|
|
69
75
|
|
|
70
|
-
|
|
71
76
|
[tool.pyright]
|
|
72
77
|
include = ["src/"]
|
|
73
78
|
exclude = ["**/__pycache__"]
|
|
@@ -91,3 +96,5 @@ dist_path = "dist/"
|
|
|
91
96
|
upload_to_pypi = true
|
|
92
97
|
commit_message = "chore(release): {version} [skip ci]"
|
|
93
98
|
|
|
99
|
+
[tool.coverage.run]
|
|
100
|
+
concurrency = ["thread", "gevent"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
echo "Welcome to Basic Memory installer"
|
|
5
|
+
|
|
6
|
+
# 1. Install uv if not present
|
|
7
|
+
if ! command -v uv &> /dev/null; then
|
|
8
|
+
echo "Installing uv package manager..."
|
|
9
|
+
curl -LsSf https://github.com/astral-sh/uv/releases/download/0.1.23/uv-installer.sh | sh
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
# 2. Configure Claude Desktop
|
|
13
|
+
echo "Configuring Claude Desktop..."
|
|
14
|
+
CONFIG_FILE="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
|
|
15
|
+
|
|
16
|
+
# Create config directory if it doesn't exist
|
|
17
|
+
mkdir -p "$(dirname "$CONFIG_FILE")"
|
|
18
|
+
|
|
19
|
+
# If config file doesn't exist, create it with initial structure
|
|
20
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
21
|
+
echo '{"mcpServers": {}}' > "$CONFIG_FILE"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Add/update the basic-memory config using jq
|
|
25
|
+
jq '.mcpServers."basic-memory" = {
|
|
26
|
+
"command": "uvx",
|
|
27
|
+
"args": ["basic-memory"]
|
|
28
|
+
}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
|
|
29
|
+
|
|
30
|
+
echo "Installation complete! Basic Memory is now available in Claude Desktop."
|
|
31
|
+
echo "Please restart Claude Desktop for changes to take effect."
|
|
32
|
+
|
|
33
|
+
echo -e "\nQuick Start:"
|
|
34
|
+
echo "1. You can run sync directly using: uvx basic-memory sync"
|
|
35
|
+
echo "2. Optionally, install globally with: uv pip install basic-memory"
|
|
36
|
+
echo -e "\nBuilt with ♥️ by Basic Machines."
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Generic single-database configuration.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Alembic environment configuration."""
|
|
2
|
+
|
|
3
|
+
from logging.config import fileConfig
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import engine_from_config
|
|
6
|
+
from sqlalchemy import pool
|
|
7
|
+
|
|
8
|
+
from alembic import context
|
|
9
|
+
|
|
10
|
+
from basic_memory.models import Base
|
|
11
|
+
from basic_memory.config import config as app_config
|
|
12
|
+
|
|
13
|
+
# this is the Alembic Config object, which provides
|
|
14
|
+
# access to the values within the .ini file in use.
|
|
15
|
+
config = context.config
|
|
16
|
+
|
|
17
|
+
# Set the SQLAlchemy URL from our app config
|
|
18
|
+
sqlalchemy_url = f"sqlite:///{app_config.database_path}"
|
|
19
|
+
config.set_main_option("sqlalchemy.url", sqlalchemy_url)
|
|
20
|
+
|
|
21
|
+
# Interpret the config file for Python logging.
|
|
22
|
+
if config.config_file_name is not None:
|
|
23
|
+
fileConfig(config.config_file_name)
|
|
24
|
+
|
|
25
|
+
# add your model's MetaData object here
|
|
26
|
+
# for 'autogenerate' support
|
|
27
|
+
target_metadata = Base.metadata
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def run_migrations_offline() -> None:
|
|
31
|
+
"""Run migrations in 'offline' mode.
|
|
32
|
+
|
|
33
|
+
This configures the context with just a URL
|
|
34
|
+
and not an Engine, though an Engine is acceptable
|
|
35
|
+
here as well. By skipping the Engine creation
|
|
36
|
+
we don't even need a DBAPI to be available.
|
|
37
|
+
|
|
38
|
+
Calls to context.execute() here emit the given string to the
|
|
39
|
+
script output.
|
|
40
|
+
"""
|
|
41
|
+
url = config.get_main_option("sqlalchemy.url")
|
|
42
|
+
context.configure(
|
|
43
|
+
url=url,
|
|
44
|
+
target_metadata=target_metadata,
|
|
45
|
+
literal_binds=True,
|
|
46
|
+
dialect_opts={"paramstyle": "named"},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
with context.begin_transaction():
|
|
50
|
+
context.run_migrations()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def run_migrations_online() -> None:
|
|
54
|
+
"""Run migrations in 'online' mode.
|
|
55
|
+
|
|
56
|
+
In this scenario we need to create an Engine
|
|
57
|
+
and associate a connection with the context.
|
|
58
|
+
"""
|
|
59
|
+
connectable = engine_from_config(
|
|
60
|
+
config.get_section(config.config_ini_section, {}),
|
|
61
|
+
prefix="sqlalchemy.",
|
|
62
|
+
poolclass=pool.NullPool,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
with connectable.connect() as connection:
|
|
66
|
+
context.configure(connection=connection, target_metadata=target_metadata)
|
|
67
|
+
|
|
68
|
+
with context.begin_transaction():
|
|
69
|
+
context.run_migrations()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if context.is_offline_mode():
|
|
73
|
+
run_migrations_offline()
|
|
74
|
+
else:
|
|
75
|
+
run_migrations_online()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Functions for managing database migrations."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from loguru import logger
|
|
6
|
+
from alembic.config import Config
|
|
7
|
+
from alembic import command
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_alembic_config() -> Config: # pragma: no cover
|
|
11
|
+
"""Get alembic config with correct paths."""
|
|
12
|
+
migrations_path = Path(__file__).parent
|
|
13
|
+
alembic_ini = migrations_path.parent.parent.parent / "alembic.ini"
|
|
14
|
+
|
|
15
|
+
config = Config(alembic_ini)
|
|
16
|
+
config.set_main_option("script_location", str(migrations_path))
|
|
17
|
+
return config
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def reset_database(): # pragma: no cover
|
|
21
|
+
"""Drop and recreate all tables."""
|
|
22
|
+
logger.info("Resetting database...")
|
|
23
|
+
config = get_alembic_config()
|
|
24
|
+
|
|
25
|
+
def _reset(cfg):
|
|
26
|
+
command.downgrade(cfg, "base")
|
|
27
|
+
command.upgrade(cfg, "head")
|
|
28
|
+
|
|
29
|
+
await asyncio.get_event_loop().run_in_executor(None, _reset, config)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""${message}
|
|
2
|
+
|
|
3
|
+
Revision ID: ${up_revision}
|
|
4
|
+
Revises: ${down_revision | comma,n}
|
|
5
|
+
Create Date: ${create_date}
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from typing import Sequence, Union
|
|
9
|
+
|
|
10
|
+
from alembic import op
|
|
11
|
+
import sqlalchemy as sa
|
|
12
|
+
${imports if imports else ""}
|
|
13
|
+
|
|
14
|
+
# revision identifiers, used by Alembic.
|
|
15
|
+
revision: str = ${repr(up_revision)}
|
|
16
|
+
down_revision: Union[str, None] = ${repr(down_revision)}
|
|
17
|
+
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
18
|
+
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def upgrade() -> None:
|
|
22
|
+
${upgrades if upgrades else "pass"}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def downgrade() -> None:
|
|
26
|
+
${downgrades if downgrades else "pass"}
|