mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a7206ad9a | |||
| 39f811f8b5 | |||
| 8e69c8b533 | |||
| 627a5c3c22 | |||
| cd88945b22 | |||
| cd8e372f0a | |||
| a589f8b894 | |||
| c2f4b632cf | |||
| 46d102cef1 |
+81
@@ -0,0 +1,81 @@
|
||||
# Development files
|
||||
.venv/
|
||||
.pytest_cache/
|
||||
.coverage*
|
||||
htmlcov/
|
||||
.ruff_cache/
|
||||
**/__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Testing
|
||||
test*/
|
||||
tests/
|
||||
*.test.js
|
||||
*.test.py
|
||||
pytest.ini
|
||||
|
||||
# Build artifacts
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
.tox/
|
||||
|
||||
# IDE files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Claude
|
||||
.claude
|
||||
|
||||
# Git files
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# Documentation build
|
||||
docs/_build/
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# DXT package output
|
||||
*.dxt
|
||||
dxt-bundle/
|
||||
|
||||
|
||||
# Lock files
|
||||
uv.lock
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Docker
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
.dockerignore
|
||||
|
||||
# CI/CD
|
||||
.github/
|
||||
justfile
|
||||
smithery.yaml
|
||||
|
||||
# Project files
|
||||
.python.version
|
||||
CHANGELOG.md
|
||||
CITATION.cff
|
||||
CLA.md
|
||||
CLAUDE.md
|
||||
CODE_OF_CONDUCT.md
|
||||
CONTRIBUTING.md
|
||||
README.md
|
||||
SECURITY.md
|
||||
docs/
|
||||
llms-install.md
|
||||
+5
-1
@@ -52,4 +52,8 @@ ENV/
|
||||
|
||||
# claude action
|
||||
claude-output
|
||||
**/.claude/settings.local.json
|
||||
**/.claude/settings.local.json
|
||||
|
||||
# DXT package files
|
||||
basic-memory.dxt
|
||||
dxt-bundle/
|
||||
+119
-37
@@ -1,56 +1,138 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.13.8 (2025-06-20)
|
||||
## v0.14.0 (2025-06-26)
|
||||
|
||||
### Features
|
||||
|
||||
- **Docker Container Support** - Complete Docker integration with volume mounting for Obsidian directories
|
||||
([`3269a2f`](https://github.com/basicmachines-co/basic-memory/commit/3269a2f33a7595f6d9e5207924062e2542f46759))
|
||||
- Docker Compose configuration for easy deployment
|
||||
- Volume mounting for persistent data and Obsidian integration
|
||||
- Comprehensive Docker documentation and setup guides
|
||||
- Streamlined container-based workflow
|
||||
- **Docker Container Registry Migration** - Switch from Docker Hub to GitHub Container Registry for better security and integration
|
||||
([`616c1f0`](https://github.com/basicmachines-co/basic-memory/commit/616c1f0710da59c7098a5f4843d4f017877ff7b2))
|
||||
- Automated Docker image publishing via GitHub Actions CI/CD pipeline
|
||||
- Enhanced container security with GitHub's integrated vulnerability scanning
|
||||
- Streamlined container deployment workflow for production environments
|
||||
|
||||
- **Enhanced Search Documentation** - Comprehensive search syntax examples for improved user experience
|
||||
([`a589f8b`](https://github.com/basicmachines-co/basic-memory/commit/a589f8b894e78cce01eb25656856cfea8785fbbf))
|
||||
- Detailed examples for Boolean search operators (AND, OR, NOT)
|
||||
- Advanced search patterns including phrase matching and field-specific queries
|
||||
- User-friendly documentation for complex search scenarios
|
||||
|
||||
- **Cross-Project File Management** - Intelligent move operations with project boundary detection
|
||||
([`db5ef7d`](https://github.com/basicmachines-co/basic-memory/commit/db5ef7d35cc0894309c7a57b5741c9dd978526d4))
|
||||
- Automatic detection of cross-project move attempts with helpful guidance
|
||||
- Clear error messages when attempting unsupported cross-project operations
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **#151**: Fix reset command project configuration persistence issue
|
||||
([`af44941`](https://github.com/basicmachines-co/basic-memory/commit/af44941d5aa57b5ad7fcc6af4ed700f49bdb6d4d))
|
||||
- Reset command now properly clears project configuration from `~/.basic-memory/config.json`
|
||||
- Eliminates issue where projects would be recreated after database reset
|
||||
- Ensures clean slate when resetting Basic Memory installation
|
||||
- **#184**: Preserve permalinks when editing notes without frontmatter permalinks
|
||||
([`c2f4b63`](https://github.com/basicmachines-co/basic-memory/commit/c2f4b632cf04921b1a3c2f0d43831b80c519cb31))
|
||||
- Fix permalink preservation during note editing operations
|
||||
- Ensure consistent permalink handling across different note formats
|
||||
- Maintain note identity and searchability during incremental edits
|
||||
|
||||
- **#148**: Resolve project state inconsistency between MCP and CLI
|
||||
([`35e4f73`](https://github.com/basicmachines-co/basic-memory/commit/35e4f73ae8a65501da4d48258ed702f957184c92))
|
||||
- Fix "Project not found" errors when switching default projects
|
||||
- MCP session now automatically refreshes when project configuration changes
|
||||
- Eliminates need to restart MCP server after project operations
|
||||
- Ensures consistent project state across CLI and MCP interfaces
|
||||
- **#183**: Implement project-specific sync status checks for MCP tools
|
||||
([`12b5152`](https://github.com/basicmachines-co/basic-memory/commit/12b51522bc953fca117fc5bc01fcb29c6ca7e13c))
|
||||
- Fix sync status reporting to correctly reflect current project state
|
||||
- Resolve inconsistencies where sync status showed global instead of project-specific information
|
||||
- Improve project isolation for sync operations and status reporting
|
||||
|
||||
- **FastMCP Compatibility** - Resolve deprecation warnings for FastMCP integration
|
||||
([`7be001c`](https://github.com/basicmachines-co/basic-memory/commit/7be001ca6834b3344bb6160cbe537b36bcbaa579))
|
||||
- Update FastMCP usage patterns to eliminate deprecation warnings
|
||||
- Improve future compatibility with FastMCP library updates
|
||||
- Clean up entity repository and service layer code
|
||||
- **#180**: Handle Boolean search syntax with hyphenated terms
|
||||
([`546e3cd`](https://github.com/basicmachines-co/basic-memory/commit/546e3cd8db98b74f746749d41887f8a213cd0b11))
|
||||
- Fix search parsing issues with hyphenated terms in Boolean queries
|
||||
- Improve search query tokenization for complex term structures
|
||||
- Enhanced search reliability for technical documentation and multi-word concepts
|
||||
|
||||
- **#174**: Respect BASIC_MEMORY_HOME environment variable in Docker containers
|
||||
([`9f1db23`](https://github.com/basicmachines-co/basic-memory/commit/9f1db23c78d4648e2c242ad1ee27eed85e3f3b5d))
|
||||
- Fix Docker container configuration to properly honor custom home directory settings
|
||||
- Improve containerized deployment flexibility with environment variable support
|
||||
- Ensure consistent behavior between local and containerized installations
|
||||
|
||||
- **#168**: Scope entity queries by project_id in upsert_entity method
|
||||
([`2a3adc1`](https://github.com/basicmachines-co/basic-memory/commit/2a3adc109a3e4d7ccd65cae4abf63d9bb2338326))
|
||||
- Fix entity isolation issues in multi-project setups
|
||||
- Prevent cross-project entity conflicts during database operations
|
||||
- Strengthen project boundary enforcement at the database level
|
||||
|
||||
- **#166**: Handle None from_entity in Context API RelationSummary
|
||||
([`8a065c3`](https://github.com/basicmachines-co/basic-memory/commit/8a065c32f4e41613207d29aafc952a56e3a52241))
|
||||
- Fix null pointer exceptions in relation processing
|
||||
- Improve error handling for incomplete relation data
|
||||
- Enhanced stability for knowledge graph traversal operations
|
||||
|
||||
- **#164**: Remove log level configuration from mcp_server.run()
|
||||
([`224e4bf`](https://github.com/basicmachines-co/basic-memory/commit/224e4bf9e4438c44a82ffc21bd1a282fe9087690))
|
||||
- Simplify MCP server startup by removing redundant log level settings
|
||||
- Fix potential logging configuration conflicts
|
||||
- Streamline server initialization process
|
||||
|
||||
- **#162**: Ensure permalinks are generated for entities with null permalinks during move operations
|
||||
([`f506507`](https://github.com/basicmachines-co/basic-memory/commit/f50650763dbd4322c132e4bdc959ce4bf074374b))
|
||||
- Fix move operations for entities without existing permalinks
|
||||
- Automatic permalink generation during file move operations
|
||||
- Maintain database consistency during file reorganization
|
||||
|
||||
### Technical Improvements
|
||||
|
||||
- **Comprehensive Integration Testing** - New test suites for critical user workflows
|
||||
- Full integration tests for database reset functionality
|
||||
- End-to-end project state synchronization testing
|
||||
- Real MCP client-server communication validation
|
||||
- Direct config file validation without complex mocking
|
||||
- **Comprehensive Test Coverage** - Extensive test suites for new features and edge cases
|
||||
- Enhanced test coverage for project-specific sync status functionality
|
||||
- Additional test scenarios for search syntax validation and edge cases
|
||||
- Integration tests for Docker CI workflow and container publishing
|
||||
- Comprehensive move operations testing with project boundary validation
|
||||
|
||||
- **Code Quality** - Enhanced error handling and validation
|
||||
- Improved project state management across system components
|
||||
- Better session refresh patterns for configuration changes
|
||||
- Streamlined Docker setup with reduced image size
|
||||
- **Docker CI/CD Pipeline** - Production-ready automated container publishing
|
||||
([`74847cc`](https://github.com/basicmachines-co/basic-memory/commit/74847cc3807b0c6ed511e0d83e0d560e9f07ec44))
|
||||
- Automated Docker image building and publishing on release
|
||||
- Multi-architecture container support for AMD64 and ARM64 platforms
|
||||
- Integrated security scanning and vulnerability assessments
|
||||
- Streamlined deployment pipeline for production environments
|
||||
|
||||
### Documentation
|
||||
- **Release Process Improvements** - Enhanced automation and quality gates
|
||||
([`a52ce1c`](https://github.com/basicmachines-co/basic-memory/commit/a52ce1c8605ec2cd450d1f909154172cbc30faa2))
|
||||
- Homebrew formula updates limited to stable releases only
|
||||
- Improved release automation with better quality control
|
||||
- Enhanced CI/CD pipeline reliability and error handling
|
||||
|
||||
- **Docker Integration Guide** - Complete documentation for container deployment
|
||||
- Step-by-step Docker Compose setup instructions
|
||||
- Volume mounting configuration for Obsidian workflows
|
||||
- Container-based development environment setup
|
||||
- **Code Quality Enhancements** - Improved error handling and validation
|
||||
- Better null safety in entity and relation processing
|
||||
- Enhanced project isolation validation throughout the codebase
|
||||
- Improved error messages and user guidance for edge cases
|
||||
- Strengthened database consistency guarantees across operations
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- **GitHub Container Registry Integration** - Modern container infrastructure
|
||||
- Migration from Docker Hub to GitHub Container Registry (ghcr.io)
|
||||
- Improved security with integrated vulnerability scanning
|
||||
- Better integration with GitHub-based development workflow
|
||||
- Enhanced container versioning and artifact management
|
||||
|
||||
- **Enhanced CI/CD Workflows** - Robust automated testing and deployment
|
||||
- Automated Docker image publishing on releases
|
||||
- Comprehensive test coverage validation before deployment
|
||||
- Multi-platform container building and publishing
|
||||
- Integration with GitHub's security and monitoring tools
|
||||
|
||||
### Migration Guide
|
||||
|
||||
This release includes several behind-the-scenes improvements and fixes. All changes are backward compatible:
|
||||
|
||||
- **Docker Users**: Container images now served from `ghcr.io/basicmachines-co/basic-memory` instead of Docker Hub
|
||||
- **Search Users**: Enhanced search syntax handling - existing queries continue to work unchanged
|
||||
- **Multi-Project Users**: Improved project isolation - all existing projects remain fully functional
|
||||
- **All Users**: Enhanced stability and error handling - no breaking changes to existing workflows
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Latest stable release
|
||||
uv tool install basic-memory
|
||||
|
||||
# Update existing installation
|
||||
uv tool upgrade basic-memory
|
||||
|
||||
# Docker (new registry)
|
||||
docker pull ghcr.io/basicmachines-co/basic-memory:latest
|
||||
```
|
||||
|
||||
## v0.13.7 (2025-06-19)
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ https://github.com/user-attachments/assets/a55d8238-8dd0-454a-be4c-8860dbbd0ddc
|
||||
# Install with uv (recommended)
|
||||
uv tool install basic-memory
|
||||
|
||||
# or with Homebrew
|
||||
brew tap basicmachines-co/basic-memory
|
||||
brew install basic-memory
|
||||
|
||||
# Configure Claude Desktop (edit ~/Library/Application Support/Claude/claude_desktop_config.json)
|
||||
# Add this to your config:
|
||||
{
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 306 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
@@ -177,6 +177,40 @@ beta version:
|
||||
echo "🔗 Monitor at: https://github.com/basicmachines-co/basic-memory/actions"
|
||||
echo "📥 Install with: uv tool install basic-memory --pre"
|
||||
|
||||
# Build DXT package with bundled virtual environment
|
||||
dxt:
|
||||
#!/usr/bin/env bash
|
||||
echo "🏗️ Building DXT package..."
|
||||
|
||||
# Clean and create bundle directory
|
||||
rm -rf dxt-bundle
|
||||
mkdir -p dxt-bundle/server/lib dxt-bundle/src
|
||||
|
||||
# Bundle dependencies to server/lib (like Anthropic example)
|
||||
echo "📦 Bundling Python dependencies..."
|
||||
uv pip install -e . --target dxt-bundle/server/lib --force-reinstall
|
||||
|
||||
# Copy source code
|
||||
echo "📄 Copying source code..."
|
||||
cp -r src/basic_memory dxt-bundle/src/
|
||||
|
||||
# Copy manifest
|
||||
cp manifest.json dxt-bundle/
|
||||
|
||||
# Copy assets (icons, screenshots)
|
||||
echo "🖼️ Copying assets..."
|
||||
mkdir -p dxt-bundle/images
|
||||
cp images/disk-ai-logo-black-fg-white-bg.png dxt-bundle/images/
|
||||
cp images/claude-*.png dxt-bundle/images/
|
||||
|
||||
# Create DXT package
|
||||
echo "📦 Creating DXT package..."
|
||||
cd dxt-bundle && dxt pack . ../basic-memory.dxt
|
||||
|
||||
echo "✅ DXT package created: basic-memory.dxt"
|
||||
echo "🔍 Info: dxt info basic-memory.dxt"
|
||||
echo "🧪 Test: Install in Claude Desktop"
|
||||
|
||||
# List all available recipes
|
||||
default:
|
||||
@just --list
|
||||
-128
@@ -1,128 +0,0 @@
|
||||
# Basic Memory Installation Guide for LLMs
|
||||
|
||||
This guide is specifically designed to help AI assistants like Cline install and configure Basic Memory. Follow these
|
||||
steps in order.
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### 1. Install Basic Memory Package
|
||||
|
||||
Use one of the following package managers to install:
|
||||
|
||||
```bash
|
||||
# Install with uv (recommended)
|
||||
uv tool install basic-memory
|
||||
|
||||
# Or with pip
|
||||
pip install basic-memory
|
||||
```
|
||||
|
||||
### 2. Configure MCP Server
|
||||
|
||||
Add the following to your config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": [
|
||||
"basic-memory",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For Claude Desktop, this file is located at:
|
||||
|
||||
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
|
||||
Windows: %APPDATA%\Claude\claude_desktop_config.json
|
||||
|
||||
### 3. Start Synchronization (optional)
|
||||
|
||||
To synchronize files in real-time, run:
|
||||
|
||||
```bash
|
||||
basic-memory sync --watch
|
||||
```
|
||||
|
||||
Or for a one-time sync:
|
||||
|
||||
```bash
|
||||
basic-memory sync
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Custom Directory
|
||||
|
||||
To use a directory other than the default `~/basic-memory`:
|
||||
|
||||
```bash
|
||||
basic-memory project add custom-project /path/to/your/directory
|
||||
basic-memory project default custom-project
|
||||
```
|
||||
|
||||
### Multiple Projects
|
||||
|
||||
To manage multiple knowledge bases:
|
||||
|
||||
```bash
|
||||
# List all projects
|
||||
basic-memory project list
|
||||
|
||||
# Add a new project
|
||||
basic-memory project add work ~/work-basic-memory
|
||||
|
||||
# Set default project
|
||||
basic-memory project default work
|
||||
```
|
||||
|
||||
## Importing Existing Data
|
||||
|
||||
### From Claude.ai
|
||||
|
||||
```bash
|
||||
basic-memory import claude conversations path/to/conversations.json
|
||||
basic-memory import claude projects path/to/projects.json
|
||||
```
|
||||
|
||||
### From ChatGPT
|
||||
|
||||
```bash
|
||||
basic-memory import chatgpt path/to/conversations.json
|
||||
```
|
||||
|
||||
### From MCP Memory Server
|
||||
|
||||
```bash
|
||||
basic-memory import memory-json path/to/memory.json
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. Check that Basic Memory is properly installed:
|
||||
```bash
|
||||
basic-memory --version
|
||||
```
|
||||
|
||||
2. Verify the sync process is running:
|
||||
```bash
|
||||
ps aux | grep basic-memory
|
||||
```
|
||||
|
||||
3. Check sync output for errors:
|
||||
```bash
|
||||
basic-memory sync --verbose
|
||||
```
|
||||
|
||||
4. Check log output:
|
||||
```bash
|
||||
cat ~/.basic-memory/basic-memory.log
|
||||
```
|
||||
|
||||
For more detailed information, refer to the [full documentation](https://memory.basicmachines.co/).
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"dxt_version": "0.1",
|
||||
"name": "basic-memory",
|
||||
"display_name": "Basic Memory Knowledge Management",
|
||||
"version": "0.14.0",
|
||||
"description": "Local-first knowledge management with AI integration",
|
||||
"long_description": "Basic Memory is a local-first knowledge management system that creates a personal knowledge graph from markdown files. It enables bidirectional communication between LLMs and your local knowledge base through the Model Context Protocol (MCP), allowing AI assistants to read, write, and navigate your knowledge seamlessly.",
|
||||
"author": {
|
||||
"name": "Basic Machines",
|
||||
"email": "hello@basicmachines.co",
|
||||
"url": "https://github.com/basicmachines-co"
|
||||
},
|
||||
"homepage": "https://basicmemory.com/",
|
||||
"documentation": "https://memory.basicmachines.co/",
|
||||
"support": "https://memory.basicmachines.co/user-guide",
|
||||
"icon": "images/disk-ai-logo-black-fg-white-bg.png",
|
||||
"screenshots": [
|
||||
"images/claude-continue-conversation.png",
|
||||
"images/claude-switch-project.png",
|
||||
"images/claude-view-note.png"
|
||||
],
|
||||
"server": {
|
||||
"type": "python",
|
||||
"entry_point": "src/basic_memory/cli/main.py",
|
||||
"mcp_config": {
|
||||
"command": "python3",
|
||||
"args": [
|
||||
"${__dirname}/src/basic_memory/cli/main.py",
|
||||
"mcp",
|
||||
"--transport=stdio"
|
||||
],
|
||||
"env": {
|
||||
"BASIC_MEMORY_HOME": "${user_data_dir}/basic-memory",
|
||||
"PYTHONPATH": "${__dirname}/server/lib:${__dirname}/src"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"name": "write_note",
|
||||
"description": "Create or update markdown notes with semantic structure"
|
||||
},
|
||||
{
|
||||
"name": "read_note",
|
||||
"description": "Read notes by title, permalink, or memory:// URL"
|
||||
},
|
||||
{
|
||||
"name": "edit_note",
|
||||
"description": "Edit notes incrementally (append, prepend, find/replace)"
|
||||
},
|
||||
{
|
||||
"name": "move_note",
|
||||
"description": "Move or rename notes"
|
||||
},
|
||||
{
|
||||
"name": "view_note",
|
||||
"description": "Display notes as formatted artifacts"
|
||||
},
|
||||
{
|
||||
"name": "read_content",
|
||||
"description": "Read raw file content (text, images, binaries)"
|
||||
},
|
||||
{
|
||||
"name": "delete_note",
|
||||
"description": "Delete notes from knowledge base"
|
||||
},
|
||||
{
|
||||
"name": "search_notes",
|
||||
"description": "Full-text search across knowledge base"
|
||||
},
|
||||
{
|
||||
"name": "build_context",
|
||||
"description": "Navigate knowledge graph via memory:// URLs"
|
||||
},
|
||||
{
|
||||
"name": "recent_activity",
|
||||
"description": "Get recently updated information"
|
||||
},
|
||||
{
|
||||
"name": "list_directory",
|
||||
"description": "Browse directory contents with filtering"
|
||||
},
|
||||
{
|
||||
"name": "canvas",
|
||||
"description": "Generate Obsidian canvas files for knowledge visualization"
|
||||
},
|
||||
{
|
||||
"name": "list_memory_projects",
|
||||
"description": "List all projects with status"
|
||||
},
|
||||
{
|
||||
"name": "switch_project",
|
||||
"description": "Switch between project contexts"
|
||||
},
|
||||
{
|
||||
"name": "get_current_project",
|
||||
"description": "Show current project stats"
|
||||
},
|
||||
{
|
||||
"name": "create_memory_project",
|
||||
"description": "Create new projects"
|
||||
},
|
||||
{
|
||||
"name": "delete_project",
|
||||
"description": "Remove projects"
|
||||
},
|
||||
{
|
||||
"name": "set_default_project",
|
||||
"description": "Set default project"
|
||||
},
|
||||
{
|
||||
"name": "sync_status",
|
||||
"description": "Check synchronization status"
|
||||
}
|
||||
],
|
||||
"prompts": [
|
||||
{
|
||||
"name": "continue_conversation",
|
||||
"description": "Continue previous conversations with relevant historical context",
|
||||
"arguments": [
|
||||
"topic",
|
||||
"timeframe"
|
||||
],
|
||||
"text": "Continue our conversation about {{topic}} from {{timeframe}} ago. Use the continue_conversation tool to find relevant context and build on our previous discussion."
|
||||
},
|
||||
{
|
||||
"name": "search_notes",
|
||||
"description": "Search knowledge base with detailed, formatted results",
|
||||
"arguments": [
|
||||
"query",
|
||||
"after_date"
|
||||
],
|
||||
"text": "Search my knowledge base for information about {{query}}. Use the search_notes tool to find relevant notes and provide a comprehensive summary of what I know about this topic."
|
||||
},
|
||||
{
|
||||
"name": "recent_activity",
|
||||
"description": "View recently changed items with formatted output",
|
||||
"arguments": [
|
||||
"timeframe"
|
||||
],
|
||||
"text": "Show me what I've been working on recently in the past {{timeframe}}. Use the recent_activity tool to display my recent notes and changes."
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"knowledge",
|
||||
"management",
|
||||
"local-first",
|
||||
"ai",
|
||||
"mcp",
|
||||
"markdown",
|
||||
"notes",
|
||||
"zettelkasten"
|
||||
],
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/basicmachines-co/basic-memory"
|
||||
},
|
||||
"compatibility": {
|
||||
"claude_desktop": ">=0.10.0",
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"runtimes": {
|
||||
"python": ">=3.12.0 <4"
|
||||
}
|
||||
}
|
||||
}
|
||||
-378
@@ -1,378 +0,0 @@
|
||||
{"type":"entity","name":"Paul","entityType":"person","observations":["Software developer combining DIY ethics, Free Software principles, and theoretical computer science","Created the Basic Machines project","Values authentic exchange of ideas","Approaches AI interaction with emphasis on genuine technical discussion","Comfortable with uncertainty and open dialogue","Balances practical implementation with broader implications"]}
|
||||
{"type":"entity","name":"Basic_Machines","entityType":"project","observations":["Local-first knowledge management system","Combines filesystem durability with graph-based knowledge representation","Focuses on enhancing human agency and understanding","Synthesizes DIY ethics, Free Software philosophy, and theoretical computer science","Current focus includes basic-memory system"]}
|
||||
{"type":"entity","name":"basic-memory","entityType":"software_system","observations":["A core component of Basic Machines","Local-first knowledge management system","Combines filesystem persistence with graph-based knowledge representation","Being implemented collaboratively by Paul and Claude"]}
|
||||
{"type":"entity","name":"basic-memory_implementation_patterns","entityType":"technical_patterns","observations":["Filesystem is source of truth - all changes write to files first","Clean separation of concerns between models (SQLAlchemy), schemas (Pydantic), and services","Repository pattern for database access","Service layer handling business logic and coordination","Atomic file operations using temporary files for safety","Clear error handling hierarchy with specific error types","Comprehensive test coverage with pytest and fixtures","Async/await used throughout the codebase","Validation using Pydantic models with custom validators"]}
|
||||
{"type":"entity","name":"fileio_module","entityType":"code_module","observations":["Extracted from EntityService to handle all file operations","Provides read_entity_file, write_entity_file, and delete_entity_file functions","Handles markdown parsing and formatting","Implements atomic file operations","Provides consistent error handling","Enables reuse across services"]}
|
||||
{"type":"entity","name":"entity_service","entityType":"code_module","observations":["Manages entities in both filesystem and database","Uses fileio module for file operations","Maintains database index of entities","Handles entity creation, retrieval, and deletion","Follows 'filesystem is source of truth' principle","Coordinates with observation service for full entity management"]}
|
||||
{"type":"entity","name":"observation_service","entityType":"code_module","observations":["Manages observations within entity files","Provides database indexing for efficient observation queries","Works with complete Entity objects rather than IDs","Handles observation addition and search","Maintains consistency between files and database","Under development for update/remove operations"]}
|
||||
{"type":"entity","name":"observation_management","entityType":"design_challenge","observations":["Key challenge: maintaining observation state across files and database","Exploring bulk update approach - treating all observations as a unit","Considering tracked observations with markdown comments for IDs","Investigating diff-based approach for observation-level changes","Evaluating position-based management without explicit IDs","Trade-offs between implementation complexity and markdown readability"]}
|
||||
{"type":"entity","name":"testing_infrastructure","entityType":"technical_patterns","observations":["Uses pytest with async support via pytest-asyncio","In-memory SQLite database for test isolation","Temporary directories for file operation testing","Comprehensive fixture system for test setup","Tests organized by component (entity, observation, etc)","Covers happy path, error cases, and edge cases","Uses monkeypatch for mocking dependencies","Clear separation between arrange, act, assert sections","Uses in-memory SQLite database for test isolation","Comprehensive fixture system for test data setup","Proper async test handling with pytest-asyncio"]}
|
||||
{"type":"entity","name":"test_categories","entityType":"test_suite","observations":["Happy path tests verify core functionality","Error path tests ensure proper error handling","Edge cases test special characters and long content","File operation tests verify atomic writes and rollbacks","Database sync tests verify index consistency","Recovery tests for rebuild operations","Punted on concurrent operation tests due to session management complexity"]}
|
||||
{"type":"entity","name":"completed_work","entityType":"project_milestone","observations":["Extracted file operations to fileio.py module","Updated EntityService to use fileio functions","Implemented initial ObservationService","Created comprehensive test suite","Established clear project patterns and principles","Set up basic database schema with SQLAlchemy","Created Pydantic models for validation"]}
|
||||
{"type":"entity","name":"future_work","entityType":"project_tasks","observations":["Implement observation updates/removals","Design proper session management for concurrent operations","Update EntityService tests for new fileio module","Add more sophisticated search functionality","Handle markdown formatting edge cases","Consider versioning for file changes","Implement proper backup strategy"]}
|
||||
{"type":"entity","name":"design_decisions","entityType":"technical_decisions","observations":["Filesystem as source of truth over database","Markdown format for human readability and editing","Atomic file operations for safety","SQLite + SQLAlchemy for proven reliability","Pydantic for validation and ID generation","Async/await for better scalability","Clear separation between files and database roles","Explicit error hierarchies for better handling"]}
|
||||
{"type":"entity","name":"concurrency_considerations","entityType":"technical_challenge","observations":["SQLAlchemy session management in async context","File operation atomicity","Transaction isolation levels","Potential for conflicting updates","Need for proper session lifecycle","Possibility of file system race conditions","Database lock management"]}
|
||||
{"type":"entity","name":"observation_update_approaches","entityType":"design_alternatives","observations":["Each approach trades off between simplicity, efficiency, and robustness","Four main approaches considered: bulk update, tracked IDs, diff-based, and position-based","Discussion revealed importance of human readability in file format","Consideration of manual editing workflows key to design","File system as source of truth principle guides tradeoffs"]}
|
||||
{"type":"entity","name":"bulk_update_approach","entityType":"design_option","observations":["Update all observations at once in a single operation","Simpler file operations - just rewrite the whole list","No need for observation matching or IDs","Very consistent with source of truth principle","Less efficient for small changes","May have concurrency implications","Simplest implementation option"]}
|
||||
{"type":"entity","name":"tracked_observations_approach","entityType":"design_option","observations":["Use markdown comments to store observation IDs","Enables precise updates and deletes","IDs stored as HTML comments in markdown","More complex markdown parsing required","IDs visible in raw markdown files","Balances tracking with readability"]}
|
||||
{"type":"entity","name":"diff_based_approach","entityType":"design_option","observations":["Implement observation-aware diffing","Track changes at observation level","More efficient for updates","Preserves manual edits and changes","More complex implementation needed","Must handle merge conflicts","Most sophisticated option considered"]}
|
||||
{"type":"entity","name":"position_based_approach","entityType":"design_option","observations":["Track observations by position/order","No explicit IDs needed","Cleanest markdown format","Order changes could break references","Difficult to handle concurrent edits","Most fragile option considered"]}
|
||||
{"type":"entity","name":"tasks_and_progress","entityType":"project_tracking","observations":["Current focus on observation management implementation","Completed core file operations extraction","Completed EntityService updates","Completed initial ObservationService","Basic test coverage in place","Future work includes concurrent operations","Future work includes search improvements","Need to handle markdown edge cases"]}
|
||||
{"type":"entity","name":"error_handling_patterns","entityType":"technical_patterns","observations":["Custom exception hierarchy with ServiceError base","Specific error types (FileOperationError, DatabaseSyncError, etc)","Clear separation between file and database errors","Error propagation patterns established","Focus on actionable error messages","Error handling at appropriate levels"]}
|
||||
{"type":"entity","name":"data_models","entityType":"technical_implementation","observations":["SQLAlchemy models for database structure","Pydantic schemas for API/service layer","Entity model with UUID-based IDs","Observation model with entity relationships","UTCDateTime custom type for timestamps","Automatic ID generation in Pydantic models","Strict validation rules"]}
|
||||
{"type":"entity","name":"markdown_format","entityType":"file_format","observations":["Simple, human-readable format","Entity name as H1 header","Metadata in key-value format","Observations as bullet points","Atomic file operations for updates","Designed for manual editing","No hidden metadata in main content"]}
|
||||
{"type":"entity","name":"test_driven_development","entityType":"development_pattern","observations":["Tests revealed need for atomic file operations","Error cases drove error hierarchy design","Edge cases informed validation rules","Test fixtures shaped service interfaces","File operations extracted due to test patterns","Concurrent test issues revealed session management needs"]}
|
||||
{"type":"entity","name":"architecture_evolution","entityType":"design_process","observations":["Started with simple EntityService implementation","Circular dependency between Entity and Observation services revealed design flaw","Extracted file operations to separate module","Moved to passing Entity objects rather than IDs","Improved separation of concerns through iterations","File operations became reusable across services","Database became true 'index' rather than source of truth"]}
|
||||
{"type":"entity","name":"validation_patterns","entityType":"technical_patterns","observations":["Pydantic models provide schema validation","Automatic ID generation if not provided","Database constraints via SQLAlchemy","Runtime checks in services","Markdown format validation","Error handling for invalid states"]}
|
||||
{"type":"entity","name":"markdown_examples","entityType":"documentation","observations":["Example of basic entity:\n# Entity Name\ntype: entity_type\n\n## Observations\n- First observation\n- Second observation","Example with special characters:\n# Test & Entity!\ntype: test\n\n## Observations\n- Test & observation with @#$% special chars!","Format ensures human readability:\n# Basic Machines\ntype: project\n\n## Observations\n- Local-first knowledge management system\n- Combines filesystem durability with graph-based knowledge representation","Future consideration for observation IDs:\n# Entity Name\ntype: entity_type\n\n## Observations\n- <!-- obs-id: abc123 -->\n This is an observation with ID"]}
|
||||
{"type":"entity","name":"markdown_parsing_rules","entityType":"technical_implementation","observations":["H1 header contains entity name","Metadata uses key: value format","Observations section marked by H2 header","Each observation is a markdown list item","Blank lines separate sections","Special characters allowed in content","No restrictions on observation content"]}
|
||||
{"type":"entity","name":"schema_definitions","entityType":"technical_documentation","observations":["SQLAlchemy Entity model:\nclass Entity(Base):\n id: str (primary key)\n name: str (unique)\n entity_type: str\n created_at: datetime\n updated_at: datetime","SQLAlchemy Observation model:\nclass Observation(Base):\n id: str (primary key)\n entity_id: str (foreign key)\n content: str\n created_at: datetime\n context: Optional[str]","Pydantic Entity schema:\nclass Entity(BaseModel):\n id: str\n name: str\n entity_type: str\n observations: List[Observation]"]}
|
||||
{"type":"entity","name":"test_evolution","entityType":"development_history","observations":["Started with basic Entity CRUD tests","Added filesystem verification to all tests","Developed concurrent operation tests (later removed)","Edge case tests drove better error handling","Test fixtures evolved to support both file and DB testing","Mocking patterns for file/DB operations","Special cases for long content and special characters"]}
|
||||
{"type":"entity","name":"implementation_challenges","entityType":"technical_issues","observations":["Initial circular dependency between services","SQLAlchemy session management in async context","Atomic file operations with proper error handling","Maintaining DB sync with filesystem changes","Handling long content in observations","Managing test isolation with file operations","Deciding on markdown format tradeoffs","Concurrent operation complexity"]}
|
||||
{"type":"entity","name":"Basic_Factory","entityType":"Project","observations":["Collaborative project between Paul and Claude","Explores AI-human collaboration in software development","Uses MCP tools for file and memory management","Built with git integration capabilities","Focuses on maintaining project context across sessions","About 90% complete with MCP tools","Still needs improvements in collaboration via files/git/github","Will be used to document and share collaborative development process"]}
|
||||
{"type":"entity","name":"Basic_Factory_Components","entityType":"Technical","observations":["Server-side rendering with JinjaX","HTMX for dynamic updates","Alpine.js for client-side state","Tailwind CSS for styling","Component translation from React/shadcn/ui","Focus on simplicity and understandability","Demonstrates meta-compiler principles in component translation"]}
|
||||
{"type":"entity","name":"Component_Translation_Process","entityType":"Methodology","observations":["Treats component porting as meta-compilation","Maps between React/TypeScript and JinjaX/Alpine.js domains","Uses formal grammar transformation approaches","Maintains functionality while simplifying implementation","Focuses on server-side rendering patterns","Preserves accessibility and performance","Uses short, focused git branches for each component"]}
|
||||
{"type":"entity","name":"Basic_Machines_Philosophy","entityType":"Philosophy","observations":["Combines DIY punk ethics with software development","Emphasizes user empowerment and understanding","Values simplicity and composability","Treats complex systems as combinations of simple parts","Focuses on authentic creation and sharing","Draws inspiration from punk rock, Free Software, and theoretical CS","Emphasizes the cycle of creation, complexity, and renewal"]}
|
||||
{"type":"entity","name":"Basic_Machines_Manifesto","entityType":"Document","observations":["Created through collaboration between Paul and Claude","Explores connection between DIY punk ethics and software development","Emphasizes composition over inheritance in both philosophy and practice","Views software development through lens of basic machines that combine for complex computation","Advocates for user empowerment and technological independence","Structured in sections covering Origins, Philosophy, Technical Implementation, and AI Collaboration","Draws connections between punk rock, free software, and theoretical computer science","Emphasizes importance of sharing knowledge and building community","Released in December 2024"]}
|
||||
{"type":"entity","name":"AI_Human_Collaboration_Model","entityType":"Methodology","observations":["Focuses on deep collaboration rather than simple task completion","Maintains rich context across sessions via knowledge graph","Uses short, focused git branches for each collaborative session","Values intellectual partnership over simple code generation","Emphasizes both practical implementation and theoretical exploration","Creates space for authentic exchange while maintaining AI/human clarity","Uses formal methods when appropriate (like grammar transformation)","Documents decisions and processes for future reference","Developed through Basic Machines project experience"]}
|
||||
{"type":"entity","name":"Basic_Machines_Roadmap","entityType":"Project_Plan","observations":["Phase 1 (30 days): Build basic-machines.co website","Phase 2 (60-90 days): Develop premium component bundles","Phase 3 (90-120 days): Launch Basic Foundation commercial offering","Focus on building brand and marketing presence","Prioritize components needed for own site development","Document and share collaboration process","Build sustainable business model aligned with values"]}
|
||||
{"type":"entity","name":"Basic_Machines_Website","entityType":"Project","observations":["To be built at basic-machines.co","Will showcase products and vision","Needs components for navigation, hero sections, features","Will demonstrate component usage in production","Will include blog for sharing progress","Focus on clear value proposition","Platform for sharing Basic Machines philosophy"]}
|
||||
{"type":"entity","name":"Basic_Memory_Markdown_Example","entityType":"Example","observations":["Shows complete markdown structure for basic-memory entity","Uses frontmatter for metadata (id, type, created, context)","Has main description section after title","Includes Observations as bullet points","Shows Relations with [id] relation_type | context format","Lists References at bottom","Created during initial design discussion","Serves as canonical example of file format"]}
|
||||
{"type":"entity","name":"Basic_Memory_Database_Schema","entityType":"Technical","observations":["Uses SQLite for local storage","Entities table with id, name, type, created_at, context, description, references","Observations table linking to entities with content and context","Relations table tracking directional relationships between entities","References column needs quotes as SQL reserved word","Designed for easy rebuilding from markdown files","Foreign key constraints maintain data integrity","Unique constraint on relations prevents duplicates","Created_at timestamps track history","Context fields enable tracking information sources"]}
|
||||
{"type":"entity","name":"Basic_Memory_Project_Structure","entityType":"Technical","observations":["Uses dbmate for database migrations","Projects directory stores SQLite databases and markdown files","Makefile provides common development commands","Environment vars configure database connection","db/migrations directory for SQL schema changes","Gitignore excludes database files and env config","Uses Python 3.12 with modern tooling","Tests directory for pytest files","Follows Basic Machines project conventions"]}
|
||||
{"type":"entity","name":"Basic_Memory_Project_Isolation_Decision","entityType":"Decision","observations":["Decided to defer multi-project support to post-MVP","Will use separate SQLite databases per project","Initially using projects directory in code repository","Plan to make location configurable later","No changes needed to core domain model","Keeps initial implementation simple","FTS/search capabilities also deferred for simplicity"]}
|
||||
{"type":"entity","name":"Basic_Memory_Implementation_Plan","entityType":"Plan","observations":["Start with SQLAlchemy models matching schema","Then build CLI for basic operations","Then implement markdown parser","Use TDD approach throughout","Begin with core domain model","CLI will support CRUD operations","Parser must handle frontmatter and sections","Following modular development approach","Planning to use typer for CLI","Will use modern Python tools and practices"]}
|
||||
{"type":"entity","name":"Basic_Memory_Implementation_Status","entityType":"Status","observations":["Core modules implemented: models, services, repository, fileio","Modular architecture with clear separation of concerns","File operations extracted to separate fileio module","Initial ObservationService implementation complete","Basic test coverage in place","Exploring observation management strategies","Using SQLAlchemy for database interaction","Markdown file operations working","Entity management functional","Repository layer implementation complete with SQLAlchemy models and tests","Database operations working with proper UTC timestamp handling","In-memory SQLite testing infrastructure proven effective"]}
|
||||
{"type":"entity","name":"Basic_Memory_Observation_Management_Design","entityType":"Design","observations":["Four approaches under consideration","Bulk Update: Simple but less efficient","Tracked Observations: Precise but clutters markdown","Diff-based: Efficient but complex","Position-based: Clean but fragile","Key challenge is balancing markdown readability with efficient updates","Must maintain filesystem as source of truth","Need to consider concurrent edits","Currently evaluating trade-offs","Implementation choice pending discussion"]}
|
||||
{"type":"entity","name":"Basic_Memory_Architectural_Decisions","entityType":"Decisions","observations":["Split file operations into separate fileio module","Using SQLAlchemy for database operations","Maintain filesystem as source of truth","Modular service-based architecture","Clear separation between data access and business logic","Repository pattern for database interactions","Schemas separate from models","Focus on maintainability and testability","Services handle business rules","Considering concurrency in design"]}
|
||||
{"type":"entity","name":"Basic_Memory_Implementation_Analysis","entityType":"Analysis","observations":["Clean modular architecture with clear responsibilities","Strong typing throughout codebase","Excellent error handling with custom exceptions","SQLAlchemy models perfectly match our domain model","Atomic file operations for data safety","Services implement filesystem-as-source-of-truth principle","Async support throughout","Good separation between domain models and database models","Careful handling of UTC timestamps","Smart use of SQLAlchemy relationships"]}
|
||||
{"type":"entity","name":"Basic_Memory_Current_Challenges","entityType":"Challenges","observations":["Observation update/removal strategy needs to be chosen","Need to handle concurrent file operations safely","Search functionality to be implemented","Edge cases in markdown formatting to be handled","Session management for concurrent operations needed","Balance between file operations and database sync","Testing coverage could be expanded","Need to handle relationship updates in files"]}
|
||||
{"type":"entity","name":"Basic_Memory_Observation_Hash_Tracking","entityType":"Design","observations":["Use content hashes to track observation identity","Store hashes in database but not in markdown","Can match observations across file edits using hashes","Similar to how git tracks content changes","Keeps markdown clean and human-friendly","Allows efficient bulk updates","Handles reordering of observations","Maintains filesystem as source of truth","No need for visible IDs in markdown","Could track observation history through hash changes"]}
|
||||
{"type":"entity","name":"Basic_Memory_Repository_Implementation","entityType":"Code_Implementation","observations":["Implemented base Repository class with CRUD operations","Added specialized EntityRepository, ObservationRepository, and RelationRepository","Used string IDs instead of UUIDs","Added UTCDateTime custom type for timestamp handling","Used in-memory SQLite for testing","Achieved 84% test coverage","Created comprehensive pytest fixtures"]}
|
||||
{"type":"entity","name":"Basic_Memory_Dependencies","entityType":"Technical","observations":["Uses Python 3.12","SQLAlchemy with async support","pytest-asyncio for async testing","aiosqlite for async SQLite operations","greenlet for SQLAlchemy async support","uv for dependency management","pytest-cov for coverage reporting","Development dependencies managed in pyproject.toml"]}
|
||||
{"type":"entity","name":"Basic_Memory_Current_Architecture","entityType":"Architecture_Analysis","observations":["Clear separation between domain models (Pydantic) and storage models (SQLAlchemy)","File I/O completely separated into dedicated module","Strong 'filesystem as source of truth' pattern in services","Atomic file operations with proper error handling","Service layer coordinates between filesystem and database","Database acts as queryable index rather than primary storage","Clean error hierarchy with specific exception types","Rebuild operations available for recovery scenarios"]}
|
||||
{"type":"entity","name":"Basic_Memory_Evolution","entityType":"Analysis","observations":["Started with repository pattern following basic-foundation","Evolved to more sophisticated architecture with clear layers","Added Pydantic schemas for domain modeling","Separated file operations into dedicated module","Implemented robust error handling throughout","Maintained filesystem as source of truth principle","Added observation management with context tracking","Introduced rebuild capabilities for system recovery"]}
|
||||
{"type":"entity","name":"Basic_Memory_Service_Layer","entityType":"Implementation","observations":["EntityService handles entity lifecycle and coordinates storage","ObservationService manages observations within entities","Services ensure filesystem and database stay in sync","Clear error handling with ServiceError hierarchy","Strong typing throughout service interfaces","Implements filesystem as source of truth pattern","Handles UUID generation and timestamp management","Provides methods for system recovery and rebuild"]}
|
||||
{"type":"entity","name":"Basic_Memory_Schema_Design","entityType":"Implementation","observations":["Uses Pydantic for domain models and validation","Automatic ID generation with timestamp and UUID","Clear separation from SQLAlchemy storage models","Supports optional context tracking","Models match markdown file structure","Enables clean serialization/deserialization","Strong typing with proper validation rules","Independent from storage concerns"]}
|
||||
{"type":"entity","name":"Basic_Memory_Next_Tasks","entityType":"TaskList","observations":["✅ Implement SQLAlchemy models and repositories (Done)","✅ Add SQLAlchemy migrations (Done)","✅ Create service layer (Done)","✅ Implement file I/O module (Done)","✅ Set up domain models with Pydantic (Done)","✅ Initial test infrastructure (Done)","✅ Basic CRUD operations (Done)","⏳ Implement full test coverage for db.py","⏳ Add more sophisticated search functionality","⏳ Implement CLI interface","⏳ Add relationship management to services","⏳ Handle concurrent file operations safely","⏳ Add versioning for file changes","⏳ Implement proper backup strategy","⏳ Add type hints throughout codebase","⏳ Improve error messages and logging","⏳ Add documentation for core modules"]}
|
||||
{"type":"entity","name":"Basic_Memory_Meta_Experience","entityType":"Case_Study","observations":["Experienced our own context loss when reconstructing project knowledge","Had to rebuild task list and project context from filesystem and memory","Validated 'filesystem as source of truth' principle through reconstruction","Code and tests served as reliable historical record","Knowledge graph structure helped guide reconstruction process","Markdown files provided human-readable context","Atomic information design made piece-by-piece reconstruction possible","Ironic validation of the need for basic-memory's features","Experience demonstrates value of durable, human-readable knowledge storage","Shows importance of separating durable storage from ephemeral context"]}
|
||||
{"type":"entity","name":"Model_Context_Protocol","entityType":"protocol","observations":["Core part of the basic-memory architecture","Enables AI-human collaboration on projects","Provides tool-based interaction with knowledge graph","Developed by Anthropic for structured AI-system interaction","Used for maintaining consistent, rich context across conversations"]}
|
||||
{"type":"entity","name":"basic-memory_core_principles","entityType":"principles","observations":["Local First: All data stored locally in SQLite","Project Isolation: Separate databases per project","Human Readable: Everything exportable to plain text","AI Friendly: Structure optimized for LLM interaction","DIY Ethics: User owns and controls their data","Simple Core: Start simple, expand based on needs","Tool Integration: MCP-based interaction model"]}
|
||||
{"type":"entity","name":"basic-memory_business_model","entityType":"business_strategy","observations":["Core features free: Local SQLite, basic knowledge graph, search, markdown export, basic MCP tools","Professional features potential: Rich document export, advanced versioning, collaboration features, custom integrations, priority support","Focus on maintaining DIY/punk philosophy while enabling sustainability"]}
|
||||
{"type":"entity","name":"basic-memory_cli","entityType":"interface","observations":["Supports project management commands (create, switch, list)","Entity management (add entity, add observation, add relation)","Future support for export and batch operations","Follows consistent command structure","Planned integration with MCP tools"]}
|
||||
{"type":"entity","name":"basic-memory_export_format","entityType":"file_format","observations":["Uses markdown with frontmatter metadata","Includes entity name, type, creation timestamp","Observations as bullet points","Relations in structured format with links","References section at bottom","Designed for human readability and machine parsing","Example format documented in project specs"]}
|
||||
{"type":"entity","name":"relation_service","entityType":"code_module","observations":["Planned service for managing relations in both filesystem and database","Will follow filesystem-is-source-of-truth principle like other services","Needs to handle atomic file operations for relation updates","Must coordinate with EntityService for relationship integrity","Will handle bidirectional relationship tracking","Will support relation validation and type enforcement","Must implement rebuild functionality for index recovery","Will need careful error handling for file/db sync","Should support relation search and filtering","Must handle relation lifecycle (create/read/update/delete)"]}
|
||||
{"type":"entity","name":"service_layer_patterns","entityType":"implementation_patterns","observations":["Services handle both file and database operations","Filesystem is always source of truth","Database serves as queryable index","Services implement atomic file operations","Clear error hierarchy with specific exceptions","Use of dependency injection via constructor params","Async/await used throughout service layer","Services coordinate between storage layers","Repository pattern used for database access","Services maintain entity integrity across storage","Rich error types extend from ServiceError base","Rebuild operations available for recovery"]}
|
||||
{"type":"entity","name":"database_models","entityType":"implementation","observations":["Entity model with unique name and type","Observation model linked to entities","Relation model tracks connections between entities","Custom UTCDateTime type for timestamp handling","Use of SQLAlchemy relationships for navigation","Cascading deletes for dependent objects","String IDs used for compatibility","Rich relationship modeling with backpopulates","Proper indexing on foreign keys","Context tracking available on models","Models include created_at timestamps","Relationships handle bidirectional navigation"]}
|
||||
{"type":"entity","name":"repository_patterns","entityType":"implementation_patterns","observations":["Generic Repository[T] base class implementation","Type-safe operations with SQLAlchemy","Specialized repositories for each model type","Async operations throughout","Clear error handling patterns","Support for custom queries and filtering","Pagination support built-in","Transaction management via session","Proper type hints and generics usage","Entity-specific query methods in subclasses"]}
|
||||
{"type":"entity","name":"relation_service_design","entityType":"design","observations":["Must handle relation lifecycle in both files and DB","Needs to validate existence of both entities","Should support relation type enforcement","Must maintain bidirectional consistency","Should support relation querying and filtering","Needs proper error handling for graph consistency","Must integrate with entity file format","Should support bulk operations for efficiency","Must handle relation deletion and cascading","Should provide search by type and entities"]}
|
||||
{"type":"entity","name":"relation_service_implementation_plan","entityType":"plan","observations":["1. Define core relation operations (create, get, delete)","2. Implement file format handling for relations","3. Add database sync with RelationRepository","4. Implement validation and error handling","5. Add rebuild and recovery operations","6. Implement relation type enforcement","7. Add relation search and filtering","8. Implement bulk operations","9. Add comprehensive tests","10. Document API and error handling"]}
|
||||
{"type":"entity","name":"relation_service_challenges","entityType":"challenges","observations":["Maintaining consistency between file and database","Handling relation type validation efficiently","Managing bidirectional relationships in files","Ensuring atomic updates across entities","Handling deletion with proper cascading","Efficient querying of relation graphs","Recovery from partial file/db sync failures","Bulk operation atomicity","Clear error reporting for graph operations","Performance with large relation sets"]}
|
||||
{"type":"entity","name":"relation_file_format","entityType":"file_format","observations":["Relations stored in entity markdown files","Format: [target_id] relation_type | context","Relations section marked by ## Relations header","Outgoing relations only stored in source entity","Relations rebuild on entity load","Clean human-readable format","Context is optional with pipe separator","Links generate valid navigation references","Markdown-friendly formatting","Example: [Paul] authored | with Claude"]}
|
||||
{"type":"entity","name":"relation_service_error_handling","entityType":"implementation_patterns","observations":["RelationError extends ServiceError base","Specific errors for validation failures","Handles entity not found cases","Manages relation type validation errors","File operation errors properly wrapped","Database sync errors clearly reported","Transaction rollback on errors","Proper error propagation chain","Clear error messages for debugging","Recovery paths for common errors"]}
|
||||
{"type":"entity","name":"relation_service_testing","entityType":"testing","observations":["Test all relation lifecycle operations","Verify file and database consistency","Test relation type validation","Check error handling paths","Test bulk operations","Verify bidirectional consistency","Test recovery operations","Check cascade operations","Verify search and filtering","Test with large relation sets"]}
|
||||
{"type":"entity","name":"fileio_patterns","entityType":"implementation_patterns","observations":["Atomic file operations with temporary files","Clear error handling for IO operations","Consistent file naming and paths","Support for different file formats","Efficient file reading and writing","Proper file locking mechanisms","Recovery from partial writes","Consistent encoding handling","Directory management utilities","Path manipulation helpers","Currently implemented in fileio.py module","Uses pathlib for path operations","Handles file not found cases gracefully","Maintains data integrity during writes"]}
|
||||
{"type":"entity","name":"pytest_patterns","entityType":"implementation_patterns","observations":["Common fixtures should be in conftest.py for reuse","Use pytest_asyncio.fixture for async fixtures","Session fixtures need proper async cleanup","Temporary directories should be managed with context managers","Test categories: happy path, error path, recovery, edge cases","Services need project_path and repo injected","Use monkeypatch for mocking in async context","SQLite in-memory database ideal for testing","Explicit test verification: file content and database state"]}
|
||||
{"type":"entity","name":"relation_implementation_learnings","entityType":"implementation_learnings","observations":["Better to pass full Entity objects than IDs to services","Services should not re-read entities if they have them","File operations should be atomic and verified","Database serves as queryable index, not source of truth","Relations stored in source entity's markdown file","Clear separation between file ops and database sync","Entity objects should own their relations list","Context is optional but fully supported in implementation"]}
|
||||
{"type":"entity","name":"test_driven_insights","entityType":"learnings","observations":["Tests help reveal better API design (e.g., passing Entity objects)","Error cases drive proper exception hierarchy","File verification as important as database checks","Edge cases inform markdown format decisions","Recovery tests ensure system resilience","Tests document expected behavior clearly","Fixtures significantly reduce test complexity","Common patterns emerge through test writing"]}
|
||||
{"type":"entity","name":"meta_development_insights","entityType":"process","observations":["Break down large tasks into reviewable chunks","One file at a time prevents response truncation","Iterative development with tests leads to better design","Infrastructure code (fixtures) should be consolidated early","Test categories help ensure comprehensive coverage","Knowledge capture should happen during development","APIs tend to evolve toward simpler patterns","File operations require careful verification"]}
|
||||
{"type":"entity","name":"AI_Assistant_Learnings","entityType":"meta_insights","observations":["Output management: Breaking responses into single files prevents truncation and allows better review","Knowledge graph helps maintain context: I can reference previous decisions and patterns accurately","Memory rebuilding experience validated the need for durable storage","Test-driven development provides clear steps and verification","Explicit relation tracking in knowledge graph helps me understand project context","Rich context from multiple sources (code, docs, tests) enables better assistance","File-at-a-time approach allows deeper analysis of each component","Keeping entity names consistent helps with referencing and relationships"]}
|
||||
{"type":"entity","name":"Effective_Response_Patterns","entityType":"meta_patterns","observations":["When showing code changes, break into discrete files","Review existing code before suggesting changes","Reference knowledge graph for context and patterns","Explicitly connect new code to existing patterns","Validate suggestions against test cases","Keep track of file changes for atomic commits","Check both implementation and test files for consistency","Maintain clear separation of concerns in responses"]}
|
||||
{"type":"entity","name":"AI_Context_Management","entityType":"meta_practice","observations":["Knowledge graph provides reliable persistent memory","Project documentation gives high-level context","Code review shows implementation patterns","Tests demonstrate expected behavior","Important to actively track what has been modified","Entity relationships help understand dependencies","Regular knowledge capture during development","Using consistent entity references across conversations"]}
|
||||
{"type":"entity","name":"AI_Tool_Usage_Patterns","entityType":"meta_practice","observations":["read_file before suggesting changes","write_file one file at a time","list_directory to understand project structure","search_nodes to find relevant context","create_entities to capture new learnings","create_relations to connect concepts","Using knowledge graph to track decisions","Validating changes through test execution"]}
|
||||
{"type":"entity","name":"relation_service_learnings","entityType":"implementation_learnings","observations":["Entity-based API cleaner than ID-based for service layer","Model_dump method can handle storage serialization","File format needs explicit section markers (## Relations)","Whitespace handling important for long content comparisons","Test fixtures allow focused test cases","SQLAlchemy selects better than raw SQL for type safety","Atomic file operations maintained for relations"]}
|
||||
{"type":"entity","name":"test_driven_insights_relations","entityType":"learnings","observations":["Tests revealed need for whitespace normalization","Edge cases drove file format decisions","SQLAlchemy model access safer than raw queries","Fixtures reduced test setup complexity","File verification as important as database checks","Testing both memory model and storage format","Test categories ensure comprehensive coverage"]}
|
||||
{"type":"entity","name":"relation_service_patterns","entityType":"patterns","observations":["Use Entity objects in API","Serialize to IDs for storage","Maintain file as source of truth","Keep file format human-readable","Handle circular references in serialization","Use repository pattern for database","Clear error hierarchies"]}
|
||||
{"type":"entity","name":"packaging_learnings","entityType":"technical_learnings","observations":["When using pytest-mock, traditional pip install works more reliably than uv sync","Package discovery behavior can differ between uv and pip","Clean venv with pip install is a reliable fallback for dependency issues","Package installation location might differ between uv and pip","Dependencies in pyproject.toml dev section work reliably with pip install -e .[dev]"]}
|
||||
{"type":"entity","name":"Recent_Implementation_Progress","entityType":"progress_update","observations":["Successfully split services.py into modular structure under services/","Created __init__.py, entity_service.py, observation_service.py, relation_service.py","Fixed pytest-mock installation issues by using pip install -e .[dev] instead of uv sync","Improved test structure with minimal mocking - only used for error testing","Implemented relation service with Entity-based API","Achieved good test coverage across services","File operations are only mocked when testing error conditions","Services follow filesystem-as-source-of-truth pattern"]}
|
||||
{"type":"entity","name":"Next_Steps","entityType":"project_tasks","observations":["Consider adding more relation service tests","Potentially expand relations features","Look for opportunities to improve test coverage","Consider documenting package management preferences (pip vs uv)","Consider adding integration tests for services","Review and possibly expand error handling cases"]}
|
||||
{"type":"entity","name":"Development_Practices","entityType":"process","observations":["Favor real operations over mocks in tests","Only mock for error condition testing","Use pip install -e .[dev] for reliable dev dependency installation","Maintain modular service structure","Keep filesystem as source of truth","Use Entity objects in service APIs instead of IDs","Validate both file and database state in tests"]}
|
||||
{"type":"entity","name":"MCP_Resources","entityType":"Concept","observations":["Stateful objects in Model Context Protocol","Enable persistent access to capabilities"]}
|
||||
{"type":"entity","name":"MCP_Server_Implementation","entityType":"Technical_Design","observations":["Inherits from mcp.server.Server base class","Tools are implemented as async methods","Each tool method maps directly to a function available to the AI","Tools can request user input via Prompts","Simple function call interface rather than explicit resource management","State management handled by server instance","Returns serialized data using model_dump() for consistency"]}
|
||||
{"type":"entity","name":"MCP_Tools","entityType":"Protocol_Feature","observations":["Defined as async methods on server class","Return values must match tool definition schema","Can maintain state between invocations via server instance","Tools can prompt for user input when needed","No need for explicit Resource objects in implementation"]}
|
||||
{"type":"entity","name":"Basic_Memory_MCP","entityType":"Implementation","observations":["Uses MemoryService for core operations","Implements project selection via prompts","Maintains project context across tool invocations","Maps directly to memory graph operations","Handles serialization of Pydantic models"]}
|
||||
{"type":"entity","name":"Basic_Memory_Testing","entityType":"Testing_Design","observations":["Needs pytest for async testing","Should isolate filesystem operations for tests","Needs to handle MCP server lifecycle in tests","Should test both service layer and MCP interface","Will need mocks for project paths and file operations"]}
|
||||
{"type":"entity","name":"Memory_Service_Tests","entityType":"Test_Suite","observations":["Should test entity creation with observations","Should test relation creation between entities","Should verify proper ID generation and model validation","Should test deletion cascading","Should test search functionality","Must verify proper serialization of entities and relations"]}
|
||||
{"type":"entity","name":"MCP_Server_Tests","entityType":"Test_Suite","observations":["Should test project initialization workflow","Should test prompt handling","Should verify tool input/output formats","Should test error cases and validation","Must verify proper serialization in tool responses"]}
|
||||
{"type":"entity","name":"Memory_Service_Refactoring","entityType":"Technical_Task","observations":["MemoryService uses create() but EntityService might expect create_entity()","MemoryService assumes get_by_name() but EntityService might use different method","Need to verify deletion method signatures","Need to check if search interface matches","Should verify observation handling matches ObservationService interface","RelationService methods need verification","EntityService.create_entity takes name, type, and optional observations directly, not an Entity object","EntityService requires project_path and entity_repo in constructor","ObservationService.add_observation takes Entity object and content string, not raw data","RelationService.create_relation takes Entity objects directly, not dict data","All services follow filesystem-as-source-of-truth pattern with DB indexing","All services handle database synchronization internally","Services expect Path objects for filesystem operations"]}
|
||||
{"type":"entity","name":"Service_Interface_Audit","entityType":"Technical_Task","observations":["Need to review all existing service interfaces","Document current method signatures","Map discrepancies between MemoryService assumptions and actual interfaces","Check return types and error handling patterns","Review transaction/atomicity requirements","Method signatures need alignment: create vs create_entity etc","Need to handle DB repositories in service constructors","File operations should use project_path consistently","Need to maintain filesystem-as-source-of-truth pattern","Should handle database synchronization at service level","Error handling should align with existing patterns","Consider making MemoryService handle DB indexing consistently"]}
|
||||
{"type":"entity","name":"Memory_Service_Patterns","entityType":"Technical_Pattern","observations":["Uses inner async functions to encapsulate operation logic","Leverages list comprehensions with async functions for parallel operations","Each operation follows a consistent pattern: validate, update DB, write file","Inner functions make the code more readable and maintainable","Operations can run in parallel when using list comprehensions with async functions"]}
|
||||
{"type":"entity","name":"Pydantic_Create_Pattern","entityType":"Technical_Pattern","observations":["Separate Create models match the exact shape of incoming data","Provides clear contract for MCP tool inputs","Handles validation of raw input data","Converts cleanly to domain models via from_create methods","Maintains separation between external API format and internal models","Similar to FastAPI request model pattern","Allows camelCase in API while using snake_case internally"]}
|
||||
{"type":"entity","name":"Basic_Memory_Business","entityType":"Business_Model","observations":["Core system is open source and free","Local-first, giving users data control","Professional features could be licensed","Enterprise support and customization services","Potential for MCP tool marketplace"]}
|
||||
{"type":"entity","name":"MCP_Marketplace","entityType":"Business_Concept","observations":["Could host verified MCP tools for different use cases","Tools rated by performance and reliability","Marketplace takes percentage of tool usage fees","Enterprise tool verification and security scanning","Custom tool development services","Integration support for existing tools"]}
|
||||
{"type":"entity","name":"Persistence_Of_Vision","entityType":"Concept","observations":["Mental model for continuous AI-human interaction","Like cinema: 24fps creates illusion of smooth motion","Basic-memory provides 'frames' of structured knowledge","Current state: Better than flipbook, not yet digital cinema","Goal: Achieve smoother cognitive continuity between interactions","Proposed by Drew as metaphor for AI conversation continuity"]}
|
||||
{"type":"entity","name":"Conversation_Continuity_Pattern","entityType":"Usage_Pattern","observations":["Use basic-memory entity/relation schema for conversations","Each chat becomes an entity with observations for key points","Relations link to discussed concepts and other chats","Uses zettelkasten format IDs for natural ordering","Can be used as template/recipe for others","Future possibility: Git SHA integration for versioning"]}
|
||||
{"type":"entity","name":"Usage_Recipes","entityType":"Feature_Concept","observations":["Predefined patterns users can follow or adapt","Could include conversation tracking recipe","Templates for different knowledge management styles","Shows practical applications of the generic schema","Helps users get started with the system"]}
|
||||
{"type":"entity","name":"Chat_References","entityType":"Technical_Feature","observations":["Uses ref:* syntax to reference previous conversations","Combines reference semantics with pointer symbolism","Format: ref:*{zettelkasten-id}","Allows explicit context loading between chats","Inspired by C++ references and pointers","Provides memory-model-like access to conversation context","Uses ref:// URI format following MCP Resource pattern","Could support multiple reference schemes (chat/entity/concept)","Makes reference semantics explicit and unambiguous","Aligns with standard URI formatting"]}
|
||||
{"type":"entity","name":"Chat_Reference_Protocol","entityType":"Technical_Specification","observations":["Uses URI format: ref://basic-memory/chat/[id]","Follows MCP Resource pattern: [protocol]://[host]/[path]","Enables explicit context loading between chats","Can support multiple resource types (chat/entity/concept)","Provides standardized way to reference previous conversations","Example: ref://basic-memory/chat/20240307-drew-ab12ef34"]}
|
||||
{"type":"entity","name":"20240307-chat-reference-protocol","entityType":"conversation","observations":["Developed ref:// URI format for chat references","Added Chat Reference Protocol to prompt instructions","Discussed implementation of chat continuation","Created complete prompt instructions document","Reference format follows MCP Resource pattern","Reviewed and confirmed complete prompt instructions","Ready to test ref://basic-memory/chat/20240307-chat-reference-protocol in new chat"]}
|
||||
{"type":"entity","name":"20240307-chat-reference-protocol-test","entityType":"conversation","observations":["First implementation test of chat reference protocol","Testing continuation from 20240307-chat-reference-protocol","Focused on practical implementation of ref:// URI format"]}
|
||||
{"type":"entity","name":"Write_File_Tool_Usage","entityType":"Tool_Usage_Pattern","observations":["Never use placeholders like '# Rest of...' when writing files - must include complete file content","File content must be complete and valid - partial updates will truncate the file","If showing partial changes, should inform human and let them handle the file write","write_file tool replaces entire file contents - cannot do partial updates","Code files especially must be complete and valid to avoid breaking functionality","Always read_file before write_file to understand current state","Using write_file without reading first risks reverting recent changes","Pattern should be: read current state, make modifications, then write if needed","Especially important in collaborative development where files may have been updated"]}
|
||||
{"type":"entity","name":"Run_Tests_Tool_Request","entityType":"Feature_Request","observations":["Need to add a tool enabling Claude to run tests locally","Would help with direct validation of code changes","Current workaround: Claude has to ask human to run tests","Should support running specific test functions (e.g. pytest tests/test_memory_service.py::test_create_relations)","Would improve iterative development workflow between human and AI"]}
|
||||
{"type":"entity","name":"SQLAlchemy_Async_Loading_Pattern","entityType":"Technical_Pattern","observations":["Use selectinload() instead of lazy loading when accessing SQLAlchemy relationships in async code","Lazy loading doesn't work with async due to greenlet context requirements","selectinload performs a single efficient query with an IN clause","Pattern used in basic-memory's EntityRepository for loading relations","Documented in find_by_id method with thorough explanation","Alternative approaches: joinedload (single JOIN query) or subqueryload (subquery approach)","Benefits: prevents 'MissingGreenlet' errors, reduces N+1 query problems","Key insight: load all needed relationships upfront in async code","Example use: selectinload(Entity.outgoing_relations)"]}
|
||||
{"type":"entity","name":"20241207-sqlalchemy-async-pattern","entityType":"conversation","observations":["Fixed SQLAlchemy async relationship loading issues","Implemented selectinload pattern in EntityRepository","Updated find_by_id to eager load relations","Added documentation about the pattern","Created knowledge graph entry about SQLAlchemy async loading","Fixed failing tests by properly loading relations in memory_service","Discussed SQLAlchemy relationship loading best practices"]}
|
||||
{"type":"entity","name":"20241207-memory-service-relations","entityType":"conversation","observations":["Fixed SQLAlchemy async loading with selectinload pattern","Updated find_by_id in EntityRepository to eager load relations","Discovered create_relations works but returns empty list","Verified relations are being stored correctly in memory.json","Next step: Work on MemoryService.add_observations implementation","Improved understanding of MCP memory storage format through debugging"]}
|
||||
{"type":"entity","name":"add_observations_implementation_plan","entityType":"technical_plan","observations":["Follow pattern from create_entity and create_relation methods","File operations first (read & write) - filesystem is source of truth","Database updates in parallel","Simplify current implementation","Current flow is:"," - First read entities and create observations"," - Write files in parallel"," - Update DB indexes sequentially","Key tests needed:"," - Adding observations to multiple entities"," - Verifying filesystem state first"," - Verifying database state"," - Error cases for missing entities"," - Error cases for file operations"]}
|
||||
{"type":"entity","name":"MCP_Reference_Integration","entityType":"feature_idea","observations":["Can be implemented as a Model Context Protocol integration similar to the fetch tool","Would provide structured way to pass chat references to Claude","Could handle ref:// URL format systematically","Integration would fetch context from referenced chats and inject into conversation","Observed from Claude Desktop UI showing MCP integration pattern with fetch tool","Would be more robust than passing references in chat text"]}
|
||||
{"type":"entity","name":"Project_Priorities","entityType":"roadmap","observations":["P1: Dogfooding basic-memory system instead of JSON memory store","Future: Implement MCP-based reference system"]}
|
||||
{"type":"entity","name":"great_observation_loading_saga_20241207","entityType":"debugging_session","observations":["Occurred on December 7, 2024 while debugging basic-memory SQLAlchemy relationship loading","Issue: selectinload() wasn't properly loading relationships in async SQLAlchemy context","Tried multiple solutions: explicit joins, manual loading, various SQLAlchemy loading strategies","Final solution: Using session.refresh() with explicit relationship names","Memorable quote: 'The Great Observation Loading Saga'","Key learning: Sometimes the obvious SQLAlchemy patterns need adaptation for async contexts","Solution preserved in basic-memory repository in EntityRepository.find_by_id()"]}
|
||||
{"type":"entity","name":"basic_memory_implementation_20241208","entityType":"technical_milestone","observations":["Fixed async SQLAlchemy relationship loading issues by using explicit refresh with relationship names","Established pattern of relationship handling belonging in MemoryService not EntityService","Fixed ID generation flow through Pydantic schemas to DB layer","Standardized error handling using EntityNotFoundError","All 32 tests passing with 70% coverage","Core services (Entity, Observation, Relation) working properly","Ready for MCP server implementation","Notable debugging session: The Great Observation Loading Saga - resolved lazy loading issues","Established clear separation between MemoryService orchestration and individual service responsibilities"]}
|
||||
{"type":"entity","name":"MCP_Dependency_Risk","entityType":"technical_lesson","observations":["Experienced disruption when MCP npm package disappeared - 'leftpad moment'","Need to ensure basic-memory tools are resilient to external dependency issues","Local implementation of MCP server provides better stability than npm packages","Important to maintain control of critical infrastructure components","Validates DIY/local-first philosophy of basic-memory project","Package manager fragility revealed by simple 'npx @modelcontextprotocol/server-memory' failure"]}
|
||||
{"type":"entity","name":"basic_memory_project_20241208","entityType":"technical_milestone","observations":["Core MCP server implementation completed with tools: create_entities, search_nodes, open_nodes, add_observations, create_relations, delete_entities, delete_observations","ProjectConfig and dependency injection pattern established","Test framework in place with in-memory DB support","Support for both camelCase (MCP) and snake_case (internal) formats","Filesystem remains source of truth with SQLite as index","Two-way sync pattern identified between Claude MCP tools and direct markdown file editing","Ready for Claude Desktop integration testing phase","Next steps identified: passing tests, markdown format definition, file change tracking, real-world testing","Implementation prioritizes local-first principles with filesystem as source of truth"]}
|
||||
{"type":"entity","name":"basic_memory_mcp_architecture","entityType":"technical_design","observations":["MemoryServer class extends MCP Server with custom handler registration","Uses ProjectConfig for clean dependency injection and configuration","Memory service can be injected for testing","Handlers exposed as instance attributes for testing","Tool schemas leverage existing Pydantic models"]}
|
||||
{"type":"entity","name":"basic_memory_sync_considerations","entityType":"design_insight","observations":["Need to handle sync between direct markdown file edits and DB index","Watch for file system changes as potential future enhancement","Consider index rebuild patterns on startup","Keep human-friendly markdown format for direct editing"]}
|
||||
{"type":"entity","name":"mcp_server_learnings","entityType":"developer_insight","observations":["MCP protocol is new and documentation is still evolving","Test patterns are not well established yet in example implementations","Supporting both camelCase and snake_case helps with protocol/internal compatibility","Server.handle_* naming convention is important for handler registration"]}
|
||||
{"type":"entity","name":"20241208-mcp-tool-refactoring","entityType":"conversation","observations":["Decision to return structured data via EmbeddedResource instead of TextContent string parsing","Plan to create Pydantic result models (CreateEntitiesResult, SearchNodesResult etc)","Will use application/vnd.basic-memory+json as MIME type for our structured data","Currently debugging test issues with add_observations tool","Entity ID vs name resolution needed in add_observations","Goal is to make tools more joyful to use by eliminating string parsing","MCP spec supports EmbeddedResource for structured data returns"]}
|
||||
{"type":"entity","name":"Basic Memory MCP Server Implementation","entityType":"technical_notes","observations":["Server implements Model Context Protocol using proper structured data responses","Uses EmbeddedResource with custom MIME type 'application/vnd.basic-memory+json'","Clean separation between input validation and handlers via Pydantic models","All tool operations return structured data through create_response helper","Type safety with Literal types for tool names and proper typing for handlers","Handler registry pattern with TOOL_HANDLERS dictionary","Consistent error handling pattern using MCP error codes","Uses Pydantic ConfigDict for proper ORM integration","Tool schemas organized into Input and Response types","Input validation with Annotated types for extra constraints","Response models consistently use from_attributes=True for ORM data","Entity ID generation moved to model validator on EntityBase","Follows principle of making common operations easy and safe"]}
|
||||
{"type":"relation","from":"Paul","to":"Basic_Machines","relationType":"created_and_maintains"}
|
||||
{"type":"relation","from":"basic-memory","to":"Basic_Machines","relationType":"is_component_of"}
|
||||
{"type":"relation","from":"Paul","to":"basic-memory","relationType":"develops"}
|
||||
{"type":"relation","from":"fileio_module","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"entity_service","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"observation_service","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"fileio_module","to":"basic-memory","relationType":"is_component_of"}
|
||||
{"type":"relation","from":"entity_service","to":"basic-memory","relationType":"is_component_of"}
|
||||
{"type":"relation","from":"observation_service","to":"basic-memory","relationType":"is_component_of"}
|
||||
{"type":"relation","from":"entity_service","to":"fileio_module","relationType":"uses"}
|
||||
{"type":"relation","from":"observation_service","to":"fileio_module","relationType":"uses"}
|
||||
{"type":"relation","from":"observation_management","to":"observation_service","relationType":"influences_design_of"}
|
||||
{"type":"relation","to":"basic-memory","from":"testing_infrastructure","relationType":"supports"}
|
||||
{"type":"relation","to":"testing_infrastructure","from":"test_categories","relationType":"implements"}
|
||||
{"type":"relation","to":"basic-memory","from":"completed_work","relationType":"tracks_progress_of"}
|
||||
{"type":"relation","to":"basic-memory","from":"future_work","relationType":"guides_development_of"}
|
||||
{"type":"relation","to":"basic-memory","from":"design_decisions","relationType":"shapes_architecture_of"}
|
||||
{"type":"relation","to":"basic-memory","from":"concurrency_considerations","relationType":"influences_design_of"}
|
||||
{"type":"relation","to":"future_work","from":"concurrency_considerations","relationType":"informs"}
|
||||
{"type":"relation","to":"observation_management","from":"design_decisions","relationType":"guides"}
|
||||
{"type":"relation","to":"testing_infrastructure","from":"completed_work","relationType":"established"}
|
||||
{"type":"relation","to":"design_decisions","from":"fileio_module","relationType":"implements"}
|
||||
{"type":"relation","from":"observation_update_approaches","to":"observation_management","relationType":"analyzes"}
|
||||
{"type":"relation","from":"bulk_update_approach","to":"observation_update_approaches","relationType":"is_option_of"}
|
||||
{"type":"relation","from":"tracked_observations_approach","to":"observation_update_approaches","relationType":"is_option_of"}
|
||||
{"type":"relation","from":"diff_based_approach","to":"observation_update_approaches","relationType":"is_option_of"}
|
||||
{"type":"relation","from":"position_based_approach","to":"observation_update_approaches","relationType":"is_option_of"}
|
||||
{"type":"relation","from":"tasks_and_progress","to":"basic-memory","relationType":"tracks_status_of"}
|
||||
{"type":"relation","from":"design_decisions","to":"observation_update_approaches","relationType":"influences"}
|
||||
{"type":"relation","from":"observation_update_approaches","to":"future_work","relationType":"informs"}
|
||||
{"type":"relation","to":"basic-memory_implementation_patterns","from":"error_handling_patterns","relationType":"is_part_of"}
|
||||
{"type":"relation","to":"basic-memory","from":"data_models","relationType":"implements"}
|
||||
{"type":"relation","to":"basic-memory","from":"markdown_format","relationType":"defines"}
|
||||
{"type":"relation","to":"basic-memory","from":"test_driven_development","relationType":"guides_development_of"}
|
||||
{"type":"relation","to":"basic-memory","from":"architecture_evolution","relationType":"describes_development_of"}
|
||||
{"type":"relation","to":"basic-memory_implementation_patterns","from":"validation_patterns","relationType":"is_part_of"}
|
||||
{"type":"relation","to":"design_decisions","from":"architecture_evolution","relationType":"informs"}
|
||||
{"type":"relation","to":"fileio_module","from":"markdown_format","relationType":"implements"}
|
||||
{"type":"relation","to":"error_handling_patterns","from":"test_driven_development","relationType":"influenced"}
|
||||
{"type":"relation","to":"data_models","from":"validation_patterns","relationType":"implements"}
|
||||
{"type":"relation","to":"markdown_format","from":"markdown_examples","relationType":"documents"}
|
||||
{"type":"relation","to":"markdown_format","from":"markdown_parsing_rules","relationType":"defines"}
|
||||
{"type":"relation","to":"data_models","from":"schema_definitions","relationType":"documents"}
|
||||
{"type":"relation","to":"test_driven_development","from":"test_evolution","relationType":"describes"}
|
||||
{"type":"relation","to":"architecture_evolution","from":"implementation_challenges","relationType":"influenced"}
|
||||
{"type":"relation","to":"test_evolution","from":"implementation_challenges","relationType":"shaped"}
|
||||
{"type":"relation","to":"future_work","from":"implementation_challenges","relationType":"informs"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"Basic_Machines","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Factory_Components","to":"Basic_Factory","relationType":"is_part_of"}
|
||||
{"type":"relation","from":"Component_Translation_Process","to":"Basic_Factory_Components","relationType":"enables"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"Basic_Machines","relationType":"guides"}
|
||||
{"type":"relation","from":"Paul","to":"Basic_Factory","relationType":"develops"}
|
||||
{"type":"relation","from":"Paul","to":"Basic_Machines_Philosophy","relationType":"created"}
|
||||
{"type":"relation","from":"Basic_Machines_Manifesto","to":"Basic_Machines_Philosophy","relationType":"articulates"}
|
||||
{"type":"relation","from":"AI_Human_Collaboration_Model","to":"Basic_Factory","relationType":"guides_development_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Manifesto","to":"Paul","relationType":"written_by"}
|
||||
{"type":"relation","from":"Basic_Machines_Manifesto","to":"Component_Translation_Process","relationType":"documents"}
|
||||
{"type":"relation","from":"AI_Human_Collaboration_Model","to":"Basic_Machines","relationType":"shapes_development_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Roadmap","to":"Basic_Machines","relationType":"guides_development_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Website","to":"Basic_Machines_Roadmap","relationType":"implements_phase_of"}
|
||||
{"type":"relation","from":"Basic_Factory_Components","to":"Basic_Machines_Website","relationType":"enables"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"Basic_Machines_Website","relationType":"informs"}
|
||||
{"type":"relation","from":"Paul","to":"DIY_Ethics","relationType":"embodies"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"DIY_Ethics","relationType":"incorporates"}
|
||||
{"type":"relation","from":"Basic_Machines","to":"DIY_Ethics","relationType":"exemplifies"}
|
||||
{"type":"relation","from":"Component_Translation_Process","to":"Basic_Machines_Philosophy","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Factory_Components","to":"DIY_Ethics","relationType":"demonstrates"}
|
||||
{"type":"relation","from":"AI_Human_Collaboration_Model","to":"Basic_Machines_Philosophy","relationType":"aligns_with"}
|
||||
{"type":"relation","from":"AI_Human_Collaboration_Model","to":"Component_Translation_Process","relationType":"guides"}
|
||||
{"type":"relation","from":"Basic_Machines_Manifesto","to":"Basic_Machines","relationType":"defines_vision_for"}
|
||||
{"type":"relation","from":"Basic_Machines_Website","to":"Basic_Machines_Manifesto","relationType":"implements_vision_of"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"AI_Human_Collaboration_Model","relationType":"demonstrates"}
|
||||
{"type":"relation","from":"Paul","to":"AI_Human_Collaboration_Model","relationType":"developed_with_Claude"}
|
||||
{"type":"relation","from":"Basic_Factory_Components","to":"Component_Translation_Process","relationType":"created_through"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"Basic_Factory","relationType":"guides"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"MCP_Tools","relationType":"integrates"}
|
||||
{"type":"relation","from":"Basic_Machines_Website","to":"Basic_Factory_Components","relationType":"will_use"}
|
||||
{"type":"relation","from":"Basic_Machines_Roadmap","to":"Basic_Machines_Philosophy","relationType":"aligns_with"}
|
||||
{"type":"relation","from":"Component_Translation_Process","to":"MCP_Tools","relationType":"leverages"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"basic-memory","relationType":"will_document_process_in"}
|
||||
{"type":"relation","from":"AI_Human_Collaboration_Model","to":"basic-memory","relationType":"will_be_implemented_in"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"Basic_Machines_Roadmap","relationType":"informs_priorities_of"}
|
||||
{"type":"relation","from":"basic-memory","to":"Basic_Machines_Philosophy","relationType":"embodies"}
|
||||
{"type":"relation","from":"Paul","to":"Basic_Machines_Manifesto","relationType":"authored_with_Claude"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"Component_Translation_Process","relationType":"validated"}
|
||||
{"type":"relation","from":"AI_Human_Collaboration_Model","to":"MCP_Tools","relationType":"utilizes"}
|
||||
{"type":"relation","from":"Basic_Factory_Components","to":"Basic_Machines_Roadmap","relationType":"supports"}
|
||||
{"type":"relation","from":"Basic_Machines_Website","to":"Basic_Factory","relationType":"will_demonstrate"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"basic-memory-webui","relationType":"enables_development_of"}
|
||||
{"type":"relation","from":"basic-memory","to":"AI_Human_Development_Methodology","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"AI_Human_Development_Methodology","relationType":"guides"}
|
||||
{"type":"relation","from":"Basic_Factory_Components","to":"basic-memory-webui","relationType":"provides_ui_for"}
|
||||
{"type":"relation","from":"Component_Translation_Process","to":"AI_Human_Development_Methodology","relationType":"exemplifies"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"Basic Components","relationType":"enabled_creation_of"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"Tool Integration Discovery","relationType":"led_to"}
|
||||
{"type":"relation","from":"MCP_Integration_Progress","to":"AI_Human_Development_Methodology","relationType":"validates"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"MCP_Integration_Progress","relationType":"demonstrates"}
|
||||
{"type":"relation","from":"Basic_Factory","to":"AI_Human_Development_Methodology","relationType":"proves_effectiveness_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"Basic Components","relationType":"inspires_architecture_of"}
|
||||
{"type":"relation","from":"DIY_Ethics","to":"basic-memory","relationType":"shapes_design_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Philosophy","to":"Tool Integration Discovery","relationType":"guides_analysis_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Manifesto","to":"AI_Human_Development_Methodology","relationType":"documents_approach_of"}
|
||||
{"type":"relation","from":"Basic_Machines_Manifesto","to":"Basic_Factory_Components","relationType":"explains_principles_of"}
|
||||
{"type":"relation","from":"Basic_Memory_Project_Structure","to":"basic-memory","relationType":"organizes"}
|
||||
{"type":"relation","from":"Basic_Memory_Database_Schema","to":"basic-memory","relationType":"defines_storage_for"}
|
||||
{"type":"relation","from":"Basic_Memory_Markdown_Example","to":"Basic_Memory_File_Format","relationType":"demonstrates"}
|
||||
{"type":"relation","from":"Basic_Memory_Project_Isolation_Decision","to":"Basic_Memory_Future_Enhancement_Weighted_Relations","relationType":"similar_to"}
|
||||
{"type":"relation","to":"DIY_Ethics","from":"Basic_Memory_Project_Isolation_Decision","relationType":"follows"}
|
||||
{"type":"relation","from":"Basic_Memory_Implementation_Plan","to":"basic-memory","relationType":"guides"}
|
||||
{"type":"relation","from":"Basic_Memory_Implementation_Plan","to":"DIY_Ethics","relationType":"follows"}
|
||||
{"type":"relation","from":"Basic_Memory_Implementation_Plan","to":"Basic_Memory_Database_Schema","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Memory_Implementation_Status","to":"Basic_Memory_Implementation_Plan","relationType":"updates"}
|
||||
{"type":"relation","from":"Basic_Memory_Observation_Management_Design","to":"Basic_Memory_Technical_Design","relationType":"extends"}
|
||||
{"type":"relation","from":"Basic_Memory_Architectural_Decisions","to":"DIY_Ethics","relationType":"guided_by"}
|
||||
{"type":"relation","from":"Basic_Memory_Architectural_Decisions","to":"basic-memory","relationType":"structures"}
|
||||
{"type":"relation","from":"Basic_Memory_Implementation_Status","to":"basic-memory","relationType":"describes_state_of"}
|
||||
{"type":"relation","to":"Basic_Memory_Implementation_Status","from":"Basic_Memory_Implementation_Analysis","relationType":"analyzes"}
|
||||
{"type":"relation","to":"basic-memory","from":"Basic_Memory_Current_Challenges","relationType":"identifies_issues_in"}
|
||||
{"type":"relation","to":"DIY_Ethics","from":"Basic_Memory_Implementation_Analysis","relationType":"confirms_alignment_with"}
|
||||
{"type":"relation","to":"Basic_Memory_Observation_Management_Design","from":"Basic_Memory_Observation_Hash_Tracking","relationType":"solves"}
|
||||
{"type":"relation","to":"DIY_Ethics","from":"Basic_Memory_Observation_Hash_Tracking","relationType":"aligns_with"}
|
||||
{"type":"relation","to":"Basic_Memory_File_Format","from":"Basic_Memory_Observation_Hash_Tracking","relationType":"preserves"}
|
||||
{"type":"relation","to":"Basic_Memory_Technical_Design","from":"Basic_Memory_Observation_Hash_Tracking","relationType":"enhances"}
|
||||
{"type":"relation","from":"Basic_Memory_Repository_Implementation","to":"basic-memory","relationType":"implements_part_of"}
|
||||
{"type":"relation","from":"Basic_Memory_Repository_Implementation","to":"Basic_Memory_Database_Schema","relationType":"follows"}
|
||||
{"type":"relation","from":"Basic_Memory_Repository_Implementation","to":"DIY_Ethics","relationType":"aligns_with"}
|
||||
{"type":"relation","from":"Basic_Memory_Repository_Implementation","to":"testing_infrastructure","relationType":"demonstrates"}
|
||||
{"type":"relation","from":"Basic_Memory_Repository_Implementation","to":"Basic Foundation","relationType":"inspired_by"}
|
||||
{"type":"relation","from":"Basic_Memory_Dependencies","to":"basic-memory","relationType":"supports"}
|
||||
{"type":"relation","from":"Basic_Memory_Dependencies","to":"Basic_Memory_Repository_Implementation","relationType":"enables"}
|
||||
{"type":"relation","from":"Basic_Memory_Dependencies","to":"testing_infrastructure","relationType":"enables"}
|
||||
{"type":"relation","from":"Basic_Memory_Current_Architecture","to":"basic-memory","relationType":"describes_state_of"}
|
||||
{"type":"relation","from":"Basic_Memory_Evolution","to":"Basic_Memory_Current_Architecture","relationType":"explains_development_of"}
|
||||
{"type":"relation","from":"Basic_Memory_Service_Layer","to":"Basic_Memory_Current_Architecture","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Memory_Schema_Design","to":"Basic_Memory_Current_Architecture","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Memory_Evolution","to":"Basic_Memory_Implementation_Plan","relationType":"reflects_on"}
|
||||
{"type":"relation","from":"Basic_Memory_Evolution","to":"DIY_Ethics","relationType":"demonstrates_alignment_with"}
|
||||
{"type":"relation","from":"Basic_Memory_Current_Architecture","to":"DIY_Ethics","relationType":"embodies"}
|
||||
{"type":"relation","from":"Basic_Memory_Service_Layer","to":"fileio_module","relationType":"uses"}
|
||||
{"type":"relation","from":"Basic_Memory_Schema_Design","to":"markdown_format","relationType":"implements"}
|
||||
{"type":"relation","to":"basic-memory","from":"Basic_Memory_Next_Tasks","relationType":"guides_development_of"}
|
||||
{"type":"relation","to":"DIY_Ethics","from":"Basic_Memory_Next_Tasks","relationType":"aligns_with"}
|
||||
{"type":"relation","to":"Basic_Memory_Current_Architecture","from":"Basic_Memory_Next_Tasks","relationType":"extends"}
|
||||
{"type":"relation","from":"Basic_Memory_Meta_Experience","to":"basic-memory","relationType":"validates_design_of"}
|
||||
{"type":"relation","from":"Basic_Memory_Meta_Experience","to":"DIY_Ethics","relationType":"demonstrates_principles_of"}
|
||||
{"type":"relation","from":"Basic_Memory_Meta_Experience","to":"design_decisions","relationType":"reinforces"}
|
||||
{"type":"relation","from":"Basic_Memory_Meta_Experience","to":"Basic_Memory_Current_Architecture","relationType":"validates"}
|
||||
{"type":"relation","from":"Model_Context_Protocol","to":"basic-memory","relationType":"enables"}
|
||||
{"type":"relation","from":"basic-memory_core_principles","to":"basic-memory","relationType":"guides"}
|
||||
{"type":"relation","from":"basic-memory_core_principles","to":"DIY_Ethics","relationType":"aligns_with"}
|
||||
{"type":"relation","from":"basic-memory_business_model","to":"basic-memory","relationType":"defines_sustainability_for"}
|
||||
{"type":"relation","from":"basic-memory_business_model","to":"DIY_Ethics","relationType":"maintains_alignment_with"}
|
||||
{"type":"relation","from":"basic-memory_cli","to":"basic-memory","relationType":"provides_interface_for"}
|
||||
{"type":"relation","from":"basic-memory_cli","to":"Model_Context_Protocol","relationType":"integrates_with"}
|
||||
{"type":"relation","from":"basic-memory_export_format","to":"basic-memory","relationType":"standardizes_output_of"}
|
||||
{"type":"relation","from":"basic-memory_export_format","to":"markdown_format","relationType":"extends"}
|
||||
{"type":"relation","from":"basic-memory_core_principles","to":"Basic_Machines_Philosophy","relationType":"implements"}
|
||||
{"type":"relation","from":"Model_Context_Protocol","to":"AI_Human_Collaboration_Model","relationType":"enables"}
|
||||
{"type":"relation","from":"relation_service","to":"basic-memory","relationType":"will_be_component_of"}
|
||||
{"type":"relation","from":"relation_service","to":"service_layer_patterns","relationType":"follows"}
|
||||
{"type":"relation","from":"relation_service","to":"fileio_patterns","relationType":"uses"}
|
||||
{"type":"relation","from":"relation_service","to":"database_models","relationType":"uses"}
|
||||
{"type":"relation","from":"relation_service","to":"repository_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"relation_service_design","to":"relation_service","relationType":"guides_implementation_of"}
|
||||
{"type":"relation","from":"relation_service_implementation_plan","to":"relation_service","relationType":"defines_implementation_of"}
|
||||
{"type":"relation","from":"relation_service_challenges","to":"relation_service_design","relationType":"informs"}
|
||||
{"type":"relation","from":"relation_file_format","to":"markdown_format","relationType":"extends"}
|
||||
{"type":"relation","from":"relation_service_error_handling","to":"service_layer_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"relation_service_testing","to":"testing_infrastructure","relationType":"extends"}
|
||||
{"type":"relation","from":"fileio_patterns","to":"service_layer_patterns","relationType":"enables"}
|
||||
{"type":"relation","from":"database_models","to":"repository_patterns","relationType":"enables"}
|
||||
{"type":"relation","from":"relation_service","to":"entity_service","relationType":"coordinates_with"}
|
||||
{"type":"relation","from":"relation_file_format","to":"relation_service","relationType":"defines_storage_for"}
|
||||
{"type":"relation","from":"relation_service_error_handling","to":"relation_service","relationType":"ensures_reliability_of"}
|
||||
{"type":"relation","from":"relation_service_testing","to":"relation_service","relationType":"verifies"}
|
||||
{"type":"relation","from":"service_layer_patterns","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"repository_patterns","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"fileio_patterns","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"database_models","to":"basic-memory_implementation_patterns","relationType":"implements"}
|
||||
{"type":"relation","from":"relation_service_challenges","to":"implementation_challenges","relationType":"extends"}
|
||||
{"type":"relation","from":"relation_service_implementation_plan","to":"future_work","relationType":"details"}
|
||||
{"type":"relation","from":"relation_service_design","to":"design_decisions","relationType":"aligns_with"}
|
||||
{"type":"relation","from":"relation_file_format","to":"design_decisions","relationType":"follows"}
|
||||
{"type":"relation","from":"pytest_patterns","to":"testing_infrastructure","relationType":"extends"}
|
||||
{"type":"relation","from":"relation_implementation_learnings","to":"basic-memory_implementation_patterns","relationType":"informs"}
|
||||
{"type":"relation","from":"test_driven_insights","to":"test_driven_development","relationType":"enriches"}
|
||||
{"type":"relation","from":"meta_development_insights","to":"AI_Human_Collaboration_Model","relationType":"improves"}
|
||||
{"type":"relation","from":"relation_implementation_learnings","to":"relation_service","relationType":"guides_implementation_of"}
|
||||
{"type":"relation","from":"pytest_patterns","to":"test_evolution","relationType":"demonstrates"}
|
||||
{"type":"relation","from":"test_driven_insights","to":"design_decisions","relationType":"influences"}
|
||||
{"type":"relation","from":"meta_development_insights","to":"architecture_evolution","relationType":"informs"}
|
||||
{"type":"relation","from":"relation_service","to":"relation_implementation_learnings","relationType":"validates"}
|
||||
{"type":"relation","from":"test_driven_insights","to":"implementation_challenges","relationType":"helps_solve"}
|
||||
{"type":"relation","from":"AI_Assistant_Learnings","to":"meta_development_insights","relationType":"enriches"}
|
||||
{"type":"relation","from":"Effective_Response_Patterns","to":"AI_Assistant_Learnings","relationType":"implements"}
|
||||
{"type":"relation","from":"AI_Context_Management","to":"AI_Human_Collaboration_Model","relationType":"improves"}
|
||||
{"type":"relation","from":"AI_Tool_Usage_Patterns","to":"AI_Context_Management","relationType":"enables"}
|
||||
{"type":"relation","from":"AI_Assistant_Learnings","to":"Basic_Memory_Meta_Experience","relationType":"validates"}
|
||||
{"type":"relation","from":"AI_Tool_Usage_Patterns","to":"Model_Context_Protocol","relationType":"demonstrates_effective_use_of"}
|
||||
{"type":"relation","from":"AI_Context_Management","to":"basic-memory","relationType":"validates_design_of"}
|
||||
{"type":"relation","from":"Effective_Response_Patterns","to":"AI_Human_Development_Methodology","relationType":"refines"}
|
||||
{"type":"relation","to":"relation_service","from":"relation_service_patterns","relationType":"guides"}
|
||||
{"type":"relation","to":"test_driven_development","from":"test_driven_insights_relations","relationType":"enriches"}
|
||||
{"type":"relation","to":"implementation_challenges","from":"relation_service_learnings","relationType":"solves"}
|
||||
{"type":"relation","to":"basic-memory_implementation_patterns","from":"relation_service_patterns","relationType":"implements"}
|
||||
{"type":"relation","to":"markdown_format","from":"relation_service_patterns","relationType":"extends"}
|
||||
{"type":"relation","to":"service_layer_patterns","from":"relation_service_patterns","relationType":"refines"}
|
||||
{"type":"relation","from":"packaging_learnings","to":"implementation_challenges","relationType":"informs"}
|
||||
{"type":"relation","from":"packaging_learnings","to":"test_driven_development","relationType":"impacts"}
|
||||
{"type":"relation","to":"basic-memory","from":"Recent_Implementation_Progress","relationType":"updates_status_of"}
|
||||
{"type":"relation","to":"future_work","from":"Next_Steps","relationType":"extends"}
|
||||
{"type":"relation","to":"design_decisions","from":"Development_Practices","relationType":"informs"}
|
||||
{"type":"relation","to":"packaging_learnings","from":"Development_Practices","relationType":"incorporates"}
|
||||
{"type":"relation","to":"test_driven_development","from":"Development_Practices","relationType":"refines"}
|
||||
{"type":"relation","to":"basic-memory_implementation_patterns","from":"Development_Practices","relationType":"enhances"}
|
||||
{"type":"relation","from":"Basic_Memory_MCP","to":"MCP_Server_Implementation","relationType":"follows"}
|
||||
{"type":"relation","from":"Basic_Memory_MCP","to":"MCP_Tools","relationType":"uses"}
|
||||
{"type":"relation","from":"Basic_Memory","to":"MCP_Server_Implementation","relationType":"implements"}
|
||||
{"type":"relation","from":"Basic_Memory_Testing","to":"Memory_Service_Tests","relationType":"includes"}
|
||||
{"type":"relation","from":"Basic_Memory_Testing","to":"MCP_Server_Tests","relationType":"includes"}
|
||||
{"type":"relation","from":"Memory_Service_Tests","to":"Basic_Memory_MCP","relationType":"validates"}
|
||||
{"type":"relation","from":"MCP_Server_Tests","to":"Basic_Memory_MCP","relationType":"validates"}
|
||||
{"type":"relation","from":"Service_Interface_Audit","to":"Memory_Service_Refactoring","relationType":"informs"}
|
||||
{"type":"relation","from":"Memory_Service_Refactoring","to":"Basic_Memory_MCP","relationType":"affects"}
|
||||
{"type":"relation","from":"Memory_Service_Patterns","to":"Basic_Memory_MCP","relationType":"improves"}
|
||||
{"type":"relation","from":"Pydantic_Create_Pattern","to":"Memory_Service_Patterns","relationType":"enables"}
|
||||
{"type":"relation","from":"Pydantic_Create_Pattern","to":"Basic_Memory_MCP","relationType":"improves"}
|
||||
{"type":"relation","from":"MCP_Marketplace","to":"Basic_Memory_Business","relationType":"enables"}
|
||||
{"type":"relation","from":"Basic_Memory","to":"MCP_Marketplace","relationType":"could_integrate_with"}
|
||||
{"type":"relation","from":"Persistence_Of_Vision","to":"Basic_Memory","relationType":"helps_achieve"}
|
||||
{"type":"relation","from":"Drew","to":"Persistence_Of_Vision","relationType":"conceptualized"}
|
||||
{"type":"relation","to":"Usage_Recipes","from":"Conversation_Continuity_Pattern","relationType":"is_example_of"}
|
||||
{"type":"relation","to":"Basic_Memory","from":"Usage_Recipes","relationType":"enhances"}
|
||||
{"type":"relation","to":"Basic_Memory","from":"Chat_References","relationType":"enhances"}
|
||||
{"type":"relation","to":"Conversation_Continuity_Pattern","from":"Chat_References","relationType":"implements"}
|
||||
{"type":"relation","from":"20240307-chat-reference-protocol-test","to":"20240307-chat-reference-protocol","relationType":"continues_from"}
|
||||
{"type":"relation","from_id":"Run_Tests_Tool_Request","to_id":"Basic_Machines","relationType":"enhances","context":"development workflow improvement"}
|
||||
{"type":"relation","from_id":"SQLAlchemy_Async_Loading_Pattern","to_id":"basic-memory","relation_type":"improves","context":"database performance and async compatibility"}
|
||||
{"type":"relation","from_id":"SQLAlchemy_Async_Loading_Pattern","to_id":"Entity","relation_type":"applies_to","context":"relationship loading strategy"}
|
||||
{"type":"relation","from":"MCP_Reference_Integration","to":"Project_Priorities","relationType":"prioritized_after"}
|
||||
{"type":"relation","from":"great_observation_loading_saga_20241207","to":"Basic_Memory","relationType":"occurred_in"}
|
||||
{"type":"relation","from":"great_observation_loading_saga_20241207","to":"SQLAlchemy","relationType":"relates_to"}
|
||||
{"type":"relation","from":"basic_memory_implementation_20241208","to":"Basic_Memory","relationType":"improves"}
|
||||
{"type":"relation","from":"great_observation_loading_saga_20241207","to":"basic_memory_implementation_20241208","relationType":"leads_to"}
|
||||
{"type":"relation","from":"MCP_Dependency_Risk","to":"DIY_Ethics","relationType":"validates"}
|
||||
{"type":"relation","from":"MCP_Dependency_Risk","to":"basic-memory_core_principles","relationType":"reinforces"}
|
||||
{"type":"relation","from":"MCP_Dependency_Risk","to":"Basic_Memory_Implementation_Plan","relationType":"influences"}
|
||||
{"type":"relation","from":"basic_memory_mcp_architecture","to":"basic_memory_project_20241208","relationType":"implements"}
|
||||
{"type":"relation","from":"basic_memory_sync_considerations","to":"basic_memory_project_20241208","relationType":"influences"}
|
||||
{"type":"relation","from":"mcp_server_learnings","to":"basic_memory_mcp_architecture","relationType":"informs"}
|
||||
{"type":"relation","from":"20241208-mcp-tool-refactoring","to":"Basic_Memory_MCP","relationType":"improves"}
|
||||
{"type":"relation","from":"20241208-mcp-tool-refactoring","to":"Basic_Memory_Implementation_Plan","relationType":"implements"}
|
||||
@@ -1,7 +1,7 @@
|
||||
"""basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
|
||||
|
||||
# Package version - updated by release automation
|
||||
__version__ = "0.14.0b1"
|
||||
__version__ = "0.14.0"
|
||||
|
||||
# API version for FastAPI - independent of package version
|
||||
__api_version__ = "v0"
|
||||
|
||||
@@ -38,7 +38,9 @@ def entity_model_from_markdown(
|
||||
# Update basic fields
|
||||
model.title = markdown.frontmatter.title
|
||||
model.entity_type = markdown.frontmatter.type
|
||||
model.permalink = markdown.frontmatter.permalink
|
||||
# Only update permalink if it exists in frontmatter, otherwise preserve existing
|
||||
if markdown.frontmatter.permalink is not None:
|
||||
model.permalink = markdown.frontmatter.permalink
|
||||
model.file_path = str(file_path)
|
||||
model.content_type = "text/markdown"
|
||||
model.created_at = markdown.created
|
||||
|
||||
@@ -45,13 +45,18 @@ def _format_search_error_response(error_message: str, query: str, search_type: s
|
||||
- Boolean OR: `meeting OR discussion`
|
||||
- Boolean NOT: `project NOT archived`
|
||||
- Grouped: `(project OR planning) AND notes`
|
||||
- Exact phrases: `"weekly standup meeting"`
|
||||
- Content-specific: `tag:example` or `category:observation`
|
||||
|
||||
## Try again with:
|
||||
```
|
||||
search_notes("INSERT_CLEAN_QUERY_HERE")
|
||||
search_notes("{clean_query}")
|
||||
```
|
||||
|
||||
Replace INSERT_CLEAN_QUERY_HERE with your simplified search terms.
|
||||
## Alternative search strategies:
|
||||
- Break into simpler terms: `search_notes("{' '.join(clean_query.split()[:2])}")`
|
||||
- Try different search types: `search_notes("{clean_query}", search_type="title")`
|
||||
- Use filtering: `search_notes("{clean_query}", types=["entity"])`
|
||||
""").strip()
|
||||
|
||||
# Project not found errors (check before general "not found")
|
||||
@@ -85,24 +90,39 @@ def _format_search_error_response(error_message: str, query: str, search_type: s
|
||||
|
||||
No content found matching '{query}' in the current project.
|
||||
|
||||
## Suggestions to try:
|
||||
## Search strategy suggestions:
|
||||
1. **Broaden your search**: Try fewer or more general terms
|
||||
- Instead of: `{query}`
|
||||
- Try: `{simplified_query}`
|
||||
|
||||
2. **Check spelling**: Verify terms are spelled correctly
|
||||
3. **Try different search types**:
|
||||
- Text search: `search_notes("{query}", search_type="text")`
|
||||
- Title search: `search_notes("{query}", search_type="title")`
|
||||
- Permalink search: `search_notes("{query}", search_type="permalink")`
|
||||
2. **Check spelling and try variations**:
|
||||
- Verify terms are spelled correctly
|
||||
- Try synonyms or related terms
|
||||
|
||||
4. **Use boolean operators**:
|
||||
- Try OR search for broader results
|
||||
3. **Use different search approaches**:
|
||||
- **Text search**: `search_notes("{query}", search_type="text")` (searches full content)
|
||||
- **Title search**: `search_notes("{query}", search_type="title")` (searches only titles)
|
||||
- **Permalink search**: `search_notes("{query}", search_type="permalink")` (searches file paths)
|
||||
|
||||
## Check what content exists:
|
||||
- Recent activity: `recent_activity(timeframe="7d")`
|
||||
- List files: `list_directory("/")`
|
||||
- Browse by folder: `list_directory("/notes")` or `list_directory("/docs")`
|
||||
4. **Try boolean operators for broader results**:
|
||||
- OR search: `search_notes("{' OR '.join(query.split()[:3])}")`
|
||||
- Remove restrictive terms: Focus on the most important keywords
|
||||
|
||||
5. **Use filtering to narrow scope**:
|
||||
- By content type: `search_notes("{query}", types=["entity"])`
|
||||
- By recent content: `search_notes("{query}", after_date="1 week")`
|
||||
- By entity type: `search_notes("{query}", entity_types=["observation"])`
|
||||
|
||||
6. **Try advanced search patterns**:
|
||||
- Tag search: `search_notes("tag:your-tag")`
|
||||
- Category search: `search_notes("category:observation")`
|
||||
- Pattern matching: `search_notes("*{query}*", search_type="permalink")`
|
||||
|
||||
## Explore what content exists:
|
||||
- **Recent activity**: `recent_activity(timeframe="7d")` - See what's been updated recently
|
||||
- **List directories**: `list_directory("/")` - Browse all content
|
||||
- **Browse by folder**: `list_directory("/notes")` or `list_directory("/docs")`
|
||||
- **Check project**: `get_current_project()` - Verify you're in the right project
|
||||
""").strip()
|
||||
|
||||
# Server/API errors
|
||||
@@ -151,25 +171,36 @@ You don't have permission to search in the current project: {error_message}
|
||||
|
||||
Error searching for '{query}': {error_message}
|
||||
|
||||
## General troubleshooting:
|
||||
1. **Check your query**: Ensure it uses valid search syntax
|
||||
2. **Try simpler terms**: Use basic words without special characters
|
||||
## Troubleshooting steps:
|
||||
1. **Simplify your query**: Try basic words without special characters
|
||||
2. **Check search syntax**: Ensure boolean operators are correctly formatted
|
||||
3. **Verify project access**: Make sure you can access the current project
|
||||
4. **Check recent activity**: `recent_activity(timeframe="7d")` to see if content exists
|
||||
4. **Test with simple search**: Try `search_notes("test")` to verify search is working
|
||||
|
||||
## Alternative approaches:
|
||||
- Browse files: `list_directory("/")`
|
||||
- Try different search type: `search_notes("{query}", search_type="title")`
|
||||
- Search with filters: `search_notes("{query}", types=["entity"])`
|
||||
## Alternative search approaches:
|
||||
- **Different search types**:
|
||||
- Title only: `search_notes("{query}", search_type="title")`
|
||||
- Permalink patterns: `search_notes("{query}*", search_type="permalink")`
|
||||
- **With filters**: `search_notes("{query}", types=["entity"])`
|
||||
- **Recent content**: `search_notes("{query}", after_date="1 week")`
|
||||
- **Boolean variations**: `search_notes("{' OR '.join(query.split()[:2])}")`
|
||||
|
||||
## Need help?
|
||||
- View recent changes: `recent_activity()`
|
||||
- List projects: `list_projects()`
|
||||
- Check current project: `get_current_project()`"""
|
||||
## Explore your content:
|
||||
- **Browse files**: `list_directory("/")` - See all available content
|
||||
- **Recent activity**: `recent_activity(timeframe="7d")` - Check what's been updated
|
||||
- **Project info**: `get_current_project()` - Verify current project
|
||||
- **All projects**: `list_projects()` - Switch to different project if needed
|
||||
|
||||
## Search syntax reference:
|
||||
- **Basic**: `keyword` or `multiple words`
|
||||
- **Boolean**: `term1 AND term2`, `term1 OR term2`, `term1 NOT term2`
|
||||
- **Phrases**: `"exact phrase"`
|
||||
- **Grouping**: `(term1 OR term2) AND term3`
|
||||
- **Patterns**: `tag:example`, `category:observation`"""
|
||||
|
||||
|
||||
@mcp.tool(
|
||||
description="Search across all content in the knowledge base.",
|
||||
description="Search across all content in the knowledge base with advanced syntax support.",
|
||||
)
|
||||
async def search_notes(
|
||||
query: str,
|
||||
@@ -181,24 +212,60 @@ async def search_notes(
|
||||
after_date: Optional[str] = None,
|
||||
project: Optional[str] = None,
|
||||
) -> SearchResponse | str:
|
||||
"""Search across all content in the knowledge base.
|
||||
"""Search across all content in the knowledge base with comprehensive syntax support.
|
||||
|
||||
This tool searches the knowledge base using full-text search, pattern matching,
|
||||
or exact permalink lookup. It supports filtering by content type, entity type,
|
||||
and date.
|
||||
and date, with advanced boolean and phrase search capabilities.
|
||||
|
||||
## Search Syntax Examples
|
||||
|
||||
### Basic Searches
|
||||
- `search_notes("keyword")` - Find any content containing "keyword"
|
||||
- `search_notes("exact phrase")` - Search for exact phrase match
|
||||
|
||||
### Advanced Boolean Searches
|
||||
- `search_notes("term1 term2")` - Find content with both terms (implicit AND)
|
||||
- `search_notes("term1 AND term2")` - Explicit AND search (both terms required)
|
||||
- `search_notes("term1 OR term2")` - Either term can be present
|
||||
- `search_notes("term1 NOT term2")` - Include term1 but exclude term2
|
||||
- `search_notes("(project OR planning) AND notes")` - Grouped boolean logic
|
||||
|
||||
### Content-Specific Searches
|
||||
- `search_notes("tag:example")` - Search within specific tags (if supported by content)
|
||||
- `search_notes("category:observation")` - Filter by observation categories
|
||||
- `search_notes("author:username")` - Find content by author (if metadata available)
|
||||
|
||||
### Search Type Examples
|
||||
- `search_notes("Meeting", search_type="title")` - Search only in titles
|
||||
- `search_notes("docs/meeting-*", search_type="permalink")` - Pattern match permalinks
|
||||
- `search_notes("keyword", search_type="text")` - Full-text search (default)
|
||||
|
||||
### Filtering Options
|
||||
- `search_notes("query", types=["entity"])` - Search only entities
|
||||
- `search_notes("query", types=["note", "person"])` - Multiple content types
|
||||
- `search_notes("query", entity_types=["observation"])` - Filter by entity type
|
||||
- `search_notes("query", after_date="2024-01-01")` - Recent content only
|
||||
- `search_notes("query", after_date="1 week")` - Relative date filtering
|
||||
|
||||
### Advanced Pattern Examples
|
||||
- `search_notes("project AND (meeting OR discussion)")` - Complex boolean logic
|
||||
- `search_notes("\"exact phrase\" AND keyword")` - Combine phrase and keyword search
|
||||
- `search_notes("bug NOT fixed")` - Exclude resolved issues
|
||||
- `search_notes("docs/2024-*", search_type="permalink")` - Year-based permalink search
|
||||
|
||||
Args:
|
||||
query: The search query string
|
||||
query: The search query string (supports boolean operators, phrases, patterns)
|
||||
page: The page number of results to return (default 1)
|
||||
page_size: The number of results to return per page (default 10)
|
||||
search_type: Type of search to perform, one of: "text", "title", "permalink" (default: "text")
|
||||
types: Optional list of note types to search (e.g., ["note", "person"])
|
||||
entity_types: Optional list of entity types to filter by (e.g., ["entity", "observation"])
|
||||
after_date: Optional date filter for recent content (e.g., "1 week", "2d")
|
||||
after_date: Optional date filter for recent content (e.g., "1 week", "2d", "2024-01-01")
|
||||
project: Optional project name to search in. If not provided, uses current active project.
|
||||
|
||||
Returns:
|
||||
SearchResponse with results and pagination info
|
||||
SearchResponse with results and pagination info, or helpful error guidance if search fails
|
||||
|
||||
Examples:
|
||||
# Basic text search
|
||||
@@ -216,16 +283,19 @@ async def search_notes(
|
||||
# Boolean search with grouping
|
||||
results = await search_notes("(project OR planning) AND notes")
|
||||
|
||||
# Exact phrase search
|
||||
results = await search_notes("\"weekly standup meeting\"")
|
||||
|
||||
# Search with type filter
|
||||
results = await search_notes(
|
||||
query="meeting notes",
|
||||
types=["entity"],
|
||||
)
|
||||
|
||||
# Search with entity type filter, e.g., note vs
|
||||
# Search with entity type filter
|
||||
results = await search_notes(
|
||||
query="meeting notes",
|
||||
types=["entity"],
|
||||
entity_types=["observation"],
|
||||
)
|
||||
|
||||
# Search for recent content
|
||||
@@ -242,6 +312,13 @@ async def search_notes(
|
||||
|
||||
# Search in specific project
|
||||
results = await search_notes("meeting notes", project="work-project")
|
||||
|
||||
# Complex search with multiple filters
|
||||
results = await search_notes(
|
||||
query="(bug OR issue) AND NOT resolved",
|
||||
types=["entity"],
|
||||
after_date="2024-01-01"
|
||||
)
|
||||
"""
|
||||
# Create a SearchQuery object based on the parameters
|
||||
search_query = SearchQuery()
|
||||
|
||||
@@ -131,7 +131,7 @@ class EntityResponse(SQLAlchemyModel):
|
||||
}
|
||||
"""
|
||||
|
||||
permalink: Permalink
|
||||
permalink: Optional[Permalink]
|
||||
title: str
|
||||
file_path: str
|
||||
entity_type: EntityType
|
||||
|
||||
@@ -359,3 +359,42 @@ async def test_edit_note_find_replace_empty_find_text(client):
|
||||
assert isinstance(result, str)
|
||||
assert "# Edit Failed" in result
|
||||
# Should contain helpful guidance about the error
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_edit_note_preserves_permalink_when_frontmatter_missing(client):
|
||||
"""Test that editing a note preserves the permalink when frontmatter doesn't contain one.
|
||||
|
||||
This is a regression test for issue #170 where edit_note would fail with a validation error
|
||||
because the permalink was being set to None when the markdown file didn't have a permalink
|
||||
in its frontmatter.
|
||||
"""
|
||||
# Create initial note
|
||||
await write_note.fn(
|
||||
title="Test Note",
|
||||
folder="test",
|
||||
content="# Test Note\nOriginal content here.",
|
||||
)
|
||||
|
||||
# Verify the note was created with a permalink
|
||||
first_result = await edit_note.fn(
|
||||
identifier="test/test-note",
|
||||
operation="append",
|
||||
content="\nFirst edit.",
|
||||
)
|
||||
|
||||
assert isinstance(first_result, str)
|
||||
assert "permalink: test/test-note" in first_result
|
||||
|
||||
# Perform another edit - this should preserve the permalink even if the
|
||||
# file doesn't have a permalink in its frontmatter
|
||||
second_result = await edit_note.fn(
|
||||
identifier="test/test-note",
|
||||
operation="append",
|
||||
content="\nSecond edit.",
|
||||
)
|
||||
|
||||
assert isinstance(second_result, str)
|
||||
assert "Edited note (append)" in second_result
|
||||
assert "permalink: test/test-note" in second_result
|
||||
# The edit should succeed without validation errors
|
||||
|
||||
@@ -6,6 +6,7 @@ from unittest.mock import patch
|
||||
|
||||
from basic_memory.mcp.tools import write_note
|
||||
from basic_memory.mcp.tools.search import search_notes, _format_search_error_response
|
||||
from basic_memory.schemas.search import SearchResponse
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -23,9 +24,14 @@ async def test_search_text(client):
|
||||
# Search for it
|
||||
response = await search_notes.fn(query="searchable")
|
||||
|
||||
# Verify results
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify SearchResponse
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -43,9 +49,14 @@ async def test_search_title(client):
|
||||
# Search for it
|
||||
response = await search_notes.fn(query="Search Note", search_type="title")
|
||||
|
||||
# Verify results
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, str):
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
else:
|
||||
# Success case - verify SearchResponse
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -63,9 +74,14 @@ async def test_search_permalink(client):
|
||||
# Search for it
|
||||
response = await search_notes.fn(query="test/test-search-note", search_type="permalink")
|
||||
|
||||
# Verify results
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify SearchResponse
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -83,9 +99,14 @@ async def test_search_permalink_match(client):
|
||||
# Search for it
|
||||
response = await search_notes.fn(query="test/test-search-*", search_type="permalink")
|
||||
|
||||
# Verify results
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify SearchResponse
|
||||
assert len(response.results) > 0
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -103,9 +124,14 @@ async def test_search_pagination(client):
|
||||
# Search for it
|
||||
response = await search_notes.fn(query="searchable", page=1, page_size=1)
|
||||
|
||||
# Verify results
|
||||
assert len(response.results) == 1
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify SearchResponse
|
||||
assert len(response.results) == 1
|
||||
assert any(r.permalink == "test/test-search-note" for r in response.results)
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -121,8 +147,13 @@ async def test_search_with_type_filter(client):
|
||||
# Search with type filter
|
||||
response = await search_notes.fn(query="type", types=["note"])
|
||||
|
||||
# Verify all results are entities
|
||||
assert all(r.type == "entity" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify all results are entities
|
||||
assert all(r.type == "entity" for r in response.results)
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -138,8 +169,13 @@ async def test_search_with_entity_type_filter(client):
|
||||
# Search with entity type filter
|
||||
response = await search_notes.fn(query="type", entity_types=["entity"])
|
||||
|
||||
# Verify all results are entities
|
||||
assert all(r.type == "entity" for r in response.results)
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify all results are entities
|
||||
assert all(r.type == "entity" for r in response.results)
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -156,8 +192,13 @@ async def test_search_with_date_filter(client):
|
||||
one_hour_ago = datetime.now() - timedelta(hours=1)
|
||||
response = await search_notes.fn(query="recent", after_date=one_hour_ago.isoformat())
|
||||
|
||||
# Verify we get results within timeframe
|
||||
assert len(response.results) > 0
|
||||
# Verify results - handle both success and error cases
|
||||
if isinstance(response, SearchResponse):
|
||||
# Success case - verify we get results within timeframe
|
||||
assert len(response.results) > 0
|
||||
else:
|
||||
# If search failed and returned error message, test should fail with informative message
|
||||
pytest.fail(f"Search failed with error: {response}")
|
||||
|
||||
|
||||
class TestSearchErrorFormatting:
|
||||
@@ -212,7 +253,7 @@ class TestSearchErrorFormatting:
|
||||
|
||||
assert "# Search Failed" in result
|
||||
assert "Error searching for 'test query': unknown error" in result
|
||||
assert "General troubleshooting" in result
|
||||
assert "## Troubleshooting steps:" in result
|
||||
|
||||
|
||||
class TestSearchToolErrorHandling:
|
||||
|
||||
@@ -551,12 +551,14 @@ class TestSearchTermPreparation:
|
||||
def test_boolean_query_empty_parts_coverage(self, search_repository):
|
||||
"""Test Boolean query parsing with empty parts (line 143 coverage)."""
|
||||
# Create queries that will result in empty parts after splitting
|
||||
result1 = search_repository._prepare_boolean_query("hello AND AND world") # Double operator
|
||||
result1 = search_repository._prepare_boolean_query(
|
||||
"hello AND AND world"
|
||||
) # Double operator
|
||||
assert "hello" in result1 and "world" in result1
|
||||
|
||||
|
||||
result2 = search_repository._prepare_boolean_query(" OR test") # Leading operator
|
||||
assert "test" in result2
|
||||
|
||||
|
||||
result3 = search_repository._prepare_boolean_query("test OR ") # Trailing operator
|
||||
assert "test" in result3
|
||||
|
||||
@@ -566,19 +568,19 @@ class TestSearchTermPreparation:
|
||||
result = search_repository._prepare_parenthetical_term('(say "hello" world)')
|
||||
# Should escape quotes by doubling them
|
||||
assert '""hello""' in result
|
||||
|
||||
|
||||
# Test term with single quotes
|
||||
result2 = search_repository._prepare_parenthetical_term('(it\'s working)')
|
||||
result2 = search_repository._prepare_parenthetical_term("(it's working)")
|
||||
assert "it's working" in result2
|
||||
|
||||
def test_needs_quoting_empty_input(self, search_repository):
|
||||
"""Test _needs_quoting with empty inputs (line 207 coverage)."""
|
||||
# Test empty string
|
||||
assert not search_repository._needs_quoting("")
|
||||
|
||||
|
||||
# Test whitespace-only string
|
||||
assert not search_repository._needs_quoting(" ")
|
||||
|
||||
|
||||
# Test None-like cases
|
||||
assert not search_repository._needs_quoting("\t")
|
||||
|
||||
@@ -587,11 +589,11 @@ class TestSearchTermPreparation:
|
||||
# Test empty string
|
||||
result1 = search_repository._prepare_single_term("")
|
||||
assert result1 == ""
|
||||
|
||||
|
||||
# Test whitespace-only string
|
||||
result2 = search_repository._prepare_single_term(" ")
|
||||
assert result2 == " " # Should return as-is
|
||||
|
||||
|
||||
# Test string that becomes empty after strip
|
||||
result3 = search_repository._prepare_single_term("\t\n")
|
||||
assert result3 == "\t\n" # Should return original
|
||||
|
||||
@@ -127,6 +127,36 @@ def test_entity_out_from_attributes():
|
||||
assert len(entity.relations) == 1
|
||||
|
||||
|
||||
def test_entity_response_with_none_permalink():
|
||||
"""Test EntityResponse can handle None permalink (fixes issue #170).
|
||||
|
||||
This test ensures that EntityResponse properly validates when the permalink
|
||||
field is None, which can occur when markdown files don't have explicit
|
||||
permalinks in their frontmatter during edit operations.
|
||||
"""
|
||||
# Simulate database model attributes with None permalink
|
||||
db_data = {
|
||||
"title": "Test Entity",
|
||||
"permalink": None, # This should not cause validation errors
|
||||
"file_path": "test/test-entity.md",
|
||||
"entity_type": "note",
|
||||
"content_type": "text/markdown",
|
||||
"observations": [],
|
||||
"relations": [],
|
||||
"created_at": "2023-01-01T00:00:00",
|
||||
"updated_at": "2023-01-01T00:00:00",
|
||||
}
|
||||
|
||||
# This should not raise a ValidationError
|
||||
entity = EntityResponse.model_validate(db_data)
|
||||
assert entity.permalink is None
|
||||
assert entity.title == "Test Entity"
|
||||
assert entity.file_path == "test/test-entity.md"
|
||||
assert entity.entity_type == "note"
|
||||
assert len(entity.observations) == 0
|
||||
assert len(entity.relations) == 0
|
||||
|
||||
|
||||
def test_search_nodes_input():
|
||||
"""Test SearchNodesInput validation."""
|
||||
search = SearchNodesRequest.model_validate({"query": "test query"})
|
||||
|
||||
Reference in New Issue
Block a user