Commit graph

44 commits

Author SHA1 Message Date
Viktor Barzin
1e100cefd1
fix: use Woodpecker repo ID in API URL, quote YAML commands
- Woodpecker API requires numeric repo IDs, not owner/name paths
- Quote kubectl commands to prevent YAML map parsing on empty vars
2026-03-16 00:06:26 +00:00
Viktor Barzin
7dc285a677
fix deploy.yml: accept push events, check IMAGE_TAG var 2026-03-15 23:58:09 +00:00
Viktor Barzin
da9b4716c2
fix last mypy error: asyncpg import-untyped ignore 2026-03-15 23:39:56 +00:00
Viktor Barzin
d370855abf
fix mypy across all source files, remove || true from CI
- Add type annotations to all FastAPI endpoints in api/app.py
- Fix bare list/dict generics in sync.py and app.py
- Fix no-any-return in vault_client.py and sync.py
- Remove mypy || true from GitHub Actions CI — mypy is now clean
2026-03-15 23:36:34 +00:00
Viktor Barzin
678d50654b
fix all mypy errors in mcp_server.py
- Add type annotations to all _sqlite_* private methods
- Type sqlite_conn as sqlite3.Connection | None with assert narrowing
- Fix _api_request return type (dict[str, Any])
- Add return type to _init_sqlite
- Fix tool_name type in handle_tools_call
- Import sqlite3 at module level
2026-03-15 23:33:05 +00:00
Viktor Barzin
df1f36a4f8
make mypy non-blocking in CI (pre-existing errors) 2026-03-15 23:30:50 +00:00
Viktor Barzin
bfc20d2ce9
move Docker builds to GitHub Actions, Woodpecker becomes deploy-only
- GHA ci.yml: add build + deploy jobs (push to DockerHub, trigger Woodpecker)
- Drop test matrix to single Python 3.12, preserve mypy step
- Build/deploy gated on push to main (PRs still run tests only)
- Woodpecker: deploy.yml (manual event, kubectl set image + slack notify)
- Old pipeline preserved as build-fallback.yml (manual trigger)
2026-03-15 23:25:36 +00:00
Viktor Barzin
44e1b84a5a
fix CI deploy: use kubectl set image instead of rollout restart
rollout restart re-pulls the same tag without updating it. Use set image
with CI_PIPELINE_NUMBER to deploy the actual new build.
2026-03-15 22:51:20 +00:00
Viktor Barzin
2fbca35e77
fix: remove extraneous f-string prefixes to pass ruff lint 2026-03-15 22:50:57 +00:00
Viktor Barzin
ba9d31f479
fix pre-existing test failures blocking CI
- test_sync: URL-decode before asserting since param (percent-encoded +)
- test_api: already fixed in previous commit (included for completeness)
2026-03-15 22:44:16 +00:00
Viktor Barzin
dbbacd75c2
fix delete tests to match idempotent endpoint behavior
The delete endpoint intentionally returns 200 (not 404) when a memory
is already deleted, to prevent retry loops in old clients. Tests were
asserting 404 incorrectly.
2026-03-15 22:41:10 +00:00
Viktor Barzin
17206cd855
improve search relevance: hybrid scoring + AND-then-OR matching
- Blend BM25/ts_rank relevance with importance instead of sorting by one
  dimension only. Default mode: 40% relevance + 60% importance. Relevance
  mode: 70% relevance + 30% importance.
- Try AND-match first for precise results, fall back to OR-match when too
  few results are found. Prevents single-word matches from flooding results.
- Applied to both SQLite (local) and PostgreSQL (API) search paths.
2026-03-15 22:36:35 +00:00
Viktor Barzin
5a73dff622
add 800-char memory limit and optimize for focused recall
- Add MAX_MEMORY_CHARS=800 Pydantic validation on MemoryStore.content
- Update auto-learn judge prompts: "ONE topic per event", 100-500 chars,
  include the WHY not just the WHAT
- Split 9 mega-memories (800-2400ch) into 70 focused memories (100-500ch)
  via migration script

Before: median 331ch, 11 memories >800ch, recall wastes 84% of returned tokens
After: median 213ch, 2 memories >800ch (dense single-topic refs), recall returns
only the relevant knowledge

Trade-off research: PostgreSQL ts_rank gives the same score regardless of
document size, so a 2400-char memory with 12 topics gets recalled for any
of its 12 topics but wastes context with the other 11. Focused memories
(100-500ch) give higher signal-to-noise per recall.
2026-03-15 15:51:18 +00:00
Viktor Barzin
6aa4d31170
fix: make DELETE idempotent — return 200 for already-deleted memories
Old sync clients without 404 handling get stuck in infinite retry
loops when trying to delete an already-deleted memory. Making the
endpoint idempotent (returning success regardless) fixes this for
all existing clients without requiring client upgrades.
2026-03-15 15:32:41 +00:00
Viktor Barzin
b6869ef496
ci: trigger rebuild with URL-decode fix 2026-03-15 15:29:08 +00:00
Viktor Barzin
e22a8f743a
fix: 404 retry loop on delete and URL-encode since param
Three fixes for high 4xx alert rate:
1. Catch urllib.error.HTTPError (not just RuntimeError) for 404 on
   DELETE in pending_ops — was causing infinite retry loop for
   already-deleted memories
2. try_sync_delete: treat 404 as success instead of enqueuing
   a retry that will also 404 forever
3. URL-encode the `since` query param to prevent `+` in timezone
   offset being decoded to a space (the asyncpg-string-timestamp
   pattern applied to the sync client)
2026-03-15 15:28:19 +00:00
Viktor Barzin
4456922294
add fallback chain for judge: claude CLI → ollama → heuristic
- claude CLI: run from /tmp to avoid internet-mode-used marker prompts
- ollama: try small local models (qwen2.5:3b, llama3.2:3b, etc.)
- heuristic: pattern matching for corrections, preferences, decisions
- better JSON extraction: handles markdown fences and surrounding text
2026-03-15 11:15:14 +00:00
Viktor Barzin
a8679d6cfb
enhance auto-learn hook: multi-turn extraction, dedup, and auto-memory files
- Deep extraction every 5 turns: reads last 5 exchanges for debugging
  insights, workarounds, architectural patterns, and operational knowledge
- Single-turn extraction on every other turn (cheap, corrections/prefs only)
- State tracking per session: turn counter, content hashes for dedup
- Writes to both memory API/SQLite AND auto-memory markdown files
- Expanded judge prompt: now catches debugging (error→cause→fix),
  workarounds, and operational knowledge — not just corrections/facts
- Auto-cleanup of state files older than 24 hours
2026-03-15 10:59:15 +00:00
Viktor Barzin
9b618711ee
fix: handle URL-decoded '+' in timezone offset for sync endpoint
The '+' in '+00:00' timezone offsets gets URL-decoded to a space,
causing datetime.fromisoformat() to fail with ValueError. Replace
spaces back to '+' before parsing.
2026-03-15 02:33:52 +00:00
Viktor Barzin
a52afe050d
Fix MCP server startup for Claude Code compatibility
- Suppress stderr output (Claude Code rejects servers with stderr)
- Make SyncEngine.start() non-blocking (blocking sync caused 15s+ timeout)
- Skip Content-Length header lines gracefully (NDJSON transport)
- Silently ignore malformed JSON lines instead of sending error responses
2026-03-14 16:05:35 +00:00
Viktor Barzin
be9e6352c3
Rewrite README to showcase plugin functionality
Lead with value prop and install command, add conversation example,
restructure around features/hooks/auto-behaviors, consolidate env
vars and API reference into clean tables, move API server docs below
plugin setup since it's optional.
2026-03-14 14:52:09 +00:00
Viktor Barzin
0d1cff3038
Add Claude Code plugin scaffold for single-repo install
Consolidates plugin components (hooks, commands, skills, MCP config)
into this repo so it can be installed with:
  claude plugins install github:ViktorBarzin/claude-memory-mcp

- .claude-plugin/plugin.json: manifest with all hook events
- mcp/memory-mcp.json: MCP server config using existing src/
- hooks/: compaction survival, auto-recall, auto-learn, auto-approve
- commands/: /remember and /recall slash commands
- skills/: memory-management skill
- Bump MCP server to v2.0.0 with metaclaw migration fallback
- Update README with quick install and plugin hooks docs
2026-03-14 14:49:18 +00:00
Viktor Barzin
66bb407bae
Add OpenClaw memory-api plugin
Provides memory_store, memory_recall, memory_list, memory_delete tools
as an OpenClaw plugin backed by the shared PostgreSQL memory API.
2026-03-14 13:54:03 +00:00
Viktor Barzin
e08486f2bd
fix: parse since param to datetime for asyncpg compatibility
asyncpg requires datetime objects, not strings, for timestamptz params.
Also use Z suffix in tests to avoid URL-encoding issues with +00:00.
2026-03-14 13:13:48 +00:00
Viktor Barzin
0a4aed9e1b
fix: resolve ruff lint errors (unused imports and variables) 2026-03-14 13:04:40 +00:00
Viktor Barzin
e77832e6b4
ci: re-trigger build after woodpecker recovery 2026-03-14 13:01:08 +00:00
Viktor Barzin
8e3735a35f
ci: trigger rebuild for sync engine deployment 2026-03-14 12:58:36 +00:00
Viktor Barzin
64265bf12b
docs: update README with hybrid sync architecture and HA deployment
Add architecture diagram, update operating modes table to reflect
three-mode support, document sync endpoint, new environment variables,
and HA deployment details.
2026-03-14 12:45:18 +00:00
Viktor Barzin
cd80a67dfa
feat: add local SQLite cache with background sync and HA deployment
- Add SyncEngine for background sync between local SQLite cache and
  remote API with pending_ops queue for offline resilience
- Refactor MCP server to support three modes: SQLite-only, hybrid
  (local cache + sync, new default), and HTTP-only (legacy)
- Add GET /api/memories/sync endpoint for incremental sync
- Change DELETE to soft delete (set deleted_at) for sync support
- Add deleted_at IS NULL filters to all read queries
- Scale API deployment to 2 replicas with pod anti-affinity, PDB,
  and startup probe for high availability
- Add migration 003 for deleted_at column and updated_at index
- Add comprehensive tests for sync engine and API sync endpoint
2026-03-14 12:42:39 +00:00
Viktor Barzin
fe55ac634b
fix: add psycopg2-binary for Alembic and add connection retry logic 2026-03-14 12:05:41 +00:00
Viktor Barzin
a831547736
feat: add background knowledge extraction script for Stop hook 2026-03-14 11:55:51 +00:00
Viktor Barzin
58ea218044
fix: add preview to delete response for MCP server compatibility 2026-03-14 11:14:05 +00:00
Viktor Barzin
3207ecf3e9
ci: retrigger after fixing woodpecker namespace quota 2026-03-14 11:04:00 +00:00
Viktor Barzin
756db25b53
ci: retrigger after fixing namespace resource quota 2026-03-14 10:56:30 +00:00
Viktor Barzin
245d86b361
ci: retrigger after agent recovery 2026-03-14 10:52:53 +00:00
Viktor Barzin
0a0f96ae67
ci: retrigger build 2026-03-14 10:44:58 +00:00
Viktor Barzin
4c75e9d801
fix: wrap recall/list responses in {memories: []} and update README
- API recall and list endpoints now return {"memories": [...]} matching
  the format expected by the MCP server
- Rewrote README with comprehensive setup instructions for new agents,
  accurate API reference, migration docs, and multi-user setup guide
2026-03-14 10:39:12 +00:00
Viktor Barzin
8a7239fb77
feat: add Alembic for database migrations
Replace inline migration logic with proper Alembic migrations:
- 001: Initial schema (creates memories table with FTS)
- 002: Add multi-user and secrets columns (user_id, is_sensitive,
  vault_path, encrypted_content)

Migrations run automatically on app startup. Existing databases
are handled gracefully with IF NOT EXISTS / column existence checks.
2026-03-14 10:34:45 +00:00
Viktor Barzin
63205dbd0c
fix: add migration logic for existing databases without new columns 2026-03-14 10:22:14 +00:00
Viktor Barzin
c67a8336cf
fix: copy README.md in Dockerfile for hatchling metadata 2026-03-14 10:14:54 +00:00
Viktor Barzin
2d9d3a8d36
fix: add cryptography to dev dependencies for crypto tests 2026-03-14 10:09:01 +00:00
Viktor Barzin
eba5cf6a82
fix: resolve ruff lint errors (unused imports and variables) 2026-03-14 10:01:41 +00:00
Viktor Barzin
1e00cc9de6
chore: trigger first CI build 2026-03-14 09:57:40 +00:00
Viktor Barzin
0ed5e1e016
feat: standalone claude-memory-mcp with multi-user support and Vault integration
Extracted from private infra repo into standalone open-source project.

Three operating modes:
- Local: SQLite + FTS5 (zero dependencies)
- Server: PostgreSQL via HTTP API with multi-user auth
- Full: PostgreSQL + HashiCorp Vault for secret management

Features:
- MCP stdio server with 5 tools (store/recall/list/delete/secret_get)
- FastAPI HTTP API with multi-user Bearer token auth (API_KEYS JSON map)
- Regex-based credential detection with auto-redaction
- AES-256-GCM encryption fallback for non-Vault deployments
- Vault KV v2 client (stdlib urllib, K8s SA auto-auth)
- Per-user data isolation (all queries scoped by user_id)
- Secret migration endpoint for existing plain-text credentials
- Backward-compatible env var aliases (CLAUDE_MEMORY_API_URL)

Infrastructure:
- Docker + docker-compose (API + PostgreSQL + optional Vault)
- Woodpecker CI (test → build → push → kubectl deploy)
- GitHub Actions CI (Python 3.11/3.12/3.13) + Release (GHCR + PyPI)
- Helm chart + raw Kubernetes manifests

96 tests passing across 6 test files.
2026-03-14 09:42:05 +00:00