universal-agent-protocol 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +462 -0
- package/dist/analyzers/index.d.ts +3 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +656 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +506 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/tool-calls.d.ts +3 -0
- package/dist/bin/tool-calls.d.ts.map +1 -0
- package/dist/bin/tool-calls.js +4 -0
- package/dist/bin/tool-calls.js.map +1 -0
- package/dist/cli/agent.d.ts +20 -0
- package/dist/cli/agent.d.ts.map +1 -0
- package/dist/cli/agent.js +434 -0
- package/dist/cli/agent.js.map +1 -0
- package/dist/cli/analyze.d.ts +7 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +103 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/coord.d.ts +7 -0
- package/dist/cli/coord.d.ts.map +1 -0
- package/dist/cli/coord.js +138 -0
- package/dist/cli/coord.js.map +1 -0
- package/dist/cli/dashboard.d.ts +8 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +704 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/deploy.d.ts +19 -0
- package/dist/cli/deploy.d.ts.map +1 -0
- package/dist/cli/deploy.js +267 -0
- package/dist/cli/deploy.js.map +1 -0
- package/dist/cli/droids.d.ts +9 -0
- package/dist/cli/droids.d.ts.map +1 -0
- package/dist/cli/droids.js +227 -0
- package/dist/cli/droids.js.map +1 -0
- package/dist/cli/generate.d.ts +17 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +432 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/cli/hooks.d.ts +9 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +374 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/init.d.ts +11 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +316 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp-router.d.ts +16 -0
- package/dist/cli/mcp-router.d.ts.map +1 -0
- package/dist/cli/mcp-router.js +143 -0
- package/dist/cli/mcp-router.js.map +1 -0
- package/dist/cli/memory.d.ts +24 -0
- package/dist/cli/memory.d.ts.map +1 -0
- package/dist/cli/memory.js +877 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/model.d.ts +15 -0
- package/dist/cli/model.d.ts.map +1 -0
- package/dist/cli/model.js +270 -0
- package/dist/cli/model.js.map +1 -0
- package/dist/cli/patterns.d.ts +26 -0
- package/dist/cli/patterns.d.ts.map +1 -0
- package/dist/cli/patterns.js +587 -0
- package/dist/cli/patterns.js.map +1 -0
- package/dist/cli/setup-mcp-router.d.ts +8 -0
- package/dist/cli/setup-mcp-router.d.ts.map +1 -0
- package/dist/cli/setup-mcp-router.js +163 -0
- package/dist/cli/setup-mcp-router.js.map +1 -0
- package/dist/cli/setup.d.ts +13 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +146 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/sync.d.ts +7 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +26 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/task.d.ts +33 -0
- package/dist/cli/task.d.ts.map +1 -0
- package/dist/cli/task.js +616 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/tool-calls.d.ts +8 -0
- package/dist/cli/tool-calls.d.ts.map +1 -0
- package/dist/cli/tool-calls.js +239 -0
- package/dist/cli/tool-calls.js.map +1 -0
- package/dist/cli/update.d.ts +10 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +300 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/visualize.d.ts +77 -0
- package/dist/cli/visualize.d.ts.map +1 -0
- package/dist/cli/visualize.js +287 -0
- package/dist/cli/visualize.js.map +1 -0
- package/dist/cli/worktree.d.ts +9 -0
- package/dist/cli/worktree.d.ts.map +1 -0
- package/dist/cli/worktree.js +175 -0
- package/dist/cli/worktree.js.map +1 -0
- package/dist/coordination/capability-router.d.ts +79 -0
- package/dist/coordination/capability-router.d.ts.map +1 -0
- package/dist/coordination/capability-router.js +324 -0
- package/dist/coordination/capability-router.js.map +1 -0
- package/dist/coordination/database.d.ts +13 -0
- package/dist/coordination/database.d.ts.map +1 -0
- package/dist/coordination/database.js +131 -0
- package/dist/coordination/database.js.map +1 -0
- package/dist/coordination/deploy-batcher.d.ts +101 -0
- package/dist/coordination/deploy-batcher.d.ts.map +1 -0
- package/dist/coordination/deploy-batcher.js +565 -0
- package/dist/coordination/deploy-batcher.js.map +1 -0
- package/dist/coordination/index.d.ts +5 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +5 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/service.d.ts +81 -0
- package/dist/coordination/service.d.ts.map +1 -0
- package/dist/coordination/service.js +603 -0
- package/dist/coordination/service.js.map +1 -0
- package/dist/generators/claude-md.d.ts +3 -0
- package/dist/generators/claude-md.d.ts.map +1 -0
- package/dist/generators/claude-md.js +977 -0
- package/dist/generators/claude-md.js.map +1 -0
- package/dist/generators/template-loader.d.ts +105 -0
- package/dist/generators/template-loader.d.ts.map +1 -0
- package/dist/generators/template-loader.js +291 -0
- package/dist/generators/template-loader.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-router/config/parser.d.ts +9 -0
- package/dist/mcp-router/config/parser.d.ts.map +1 -0
- package/dist/mcp-router/config/parser.js +174 -0
- package/dist/mcp-router/config/parser.js.map +1 -0
- package/dist/mcp-router/executor/client.d.ts +31 -0
- package/dist/mcp-router/executor/client.d.ts.map +1 -0
- package/dist/mcp-router/executor/client.js +187 -0
- package/dist/mcp-router/executor/client.js.map +1 -0
- package/dist/mcp-router/index.d.ts +22 -0
- package/dist/mcp-router/index.d.ts.map +1 -0
- package/dist/mcp-router/index.js +18 -0
- package/dist/mcp-router/index.js.map +1 -0
- package/dist/mcp-router/output-compressor.d.ts +26 -0
- package/dist/mcp-router/output-compressor.d.ts.map +1 -0
- package/dist/mcp-router/output-compressor.js +236 -0
- package/dist/mcp-router/output-compressor.js.map +1 -0
- package/dist/mcp-router/search/fuzzy.d.ts +26 -0
- package/dist/mcp-router/search/fuzzy.d.ts.map +1 -0
- package/dist/mcp-router/search/fuzzy.js +94 -0
- package/dist/mcp-router/search/fuzzy.js.map +1 -0
- package/dist/mcp-router/server.d.ts +50 -0
- package/dist/mcp-router/server.d.ts.map +1 -0
- package/dist/mcp-router/server.js +229 -0
- package/dist/mcp-router/server.js.map +1 -0
- package/dist/mcp-router/session-stats.d.ts +37 -0
- package/dist/mcp-router/session-stats.d.ts.map +1 -0
- package/dist/mcp-router/session-stats.js +56 -0
- package/dist/mcp-router/session-stats.js.map +1 -0
- package/dist/mcp-router/tools/discover.d.ts +37 -0
- package/dist/mcp-router/tools/discover.d.ts.map +1 -0
- package/dist/mcp-router/tools/discover.js +65 -0
- package/dist/mcp-router/tools/discover.js.map +1 -0
- package/dist/mcp-router/tools/execute.d.ts +43 -0
- package/dist/mcp-router/tools/execute.d.ts.map +1 -0
- package/dist/mcp-router/tools/execute.js +103 -0
- package/dist/mcp-router/tools/execute.js.map +1 -0
- package/dist/mcp-router/types.d.ts +62 -0
- package/dist/mcp-router/types.d.ts.map +1 -0
- package/dist/mcp-router/types.js +6 -0
- package/dist/mcp-router/types.js.map +1 -0
- package/dist/memory/adaptive-context.d.ts +146 -0
- package/dist/memory/adaptive-context.d.ts.map +1 -0
- package/dist/memory/adaptive-context.js +1022 -0
- package/dist/memory/adaptive-context.js.map +1 -0
- package/dist/memory/agent-scoped-memory.d.ts +67 -0
- package/dist/memory/agent-scoped-memory.d.ts.map +1 -0
- package/dist/memory/agent-scoped-memory.js +126 -0
- package/dist/memory/agent-scoped-memory.js.map +1 -0
- package/dist/memory/backends/base.d.ts +18 -0
- package/dist/memory/backends/base.d.ts.map +1 -0
- package/dist/memory/backends/base.js +2 -0
- package/dist/memory/backends/base.js.map +1 -0
- package/dist/memory/backends/factory.d.ts +4 -0
- package/dist/memory/backends/factory.d.ts.map +1 -0
- package/dist/memory/backends/factory.js +53 -0
- package/dist/memory/backends/factory.js.map +1 -0
- package/dist/memory/backends/github.d.ts +22 -0
- package/dist/memory/backends/github.d.ts.map +1 -0
- package/dist/memory/backends/github.js +118 -0
- package/dist/memory/backends/github.js.map +1 -0
- package/dist/memory/backends/qdrant-cloud.d.ts +32 -0
- package/dist/memory/backends/qdrant-cloud.d.ts.map +1 -0
- package/dist/memory/backends/qdrant-cloud.js +168 -0
- package/dist/memory/backends/qdrant-cloud.js.map +1 -0
- package/dist/memory/context-compressor.d.ts +74 -0
- package/dist/memory/context-compressor.d.ts.map +1 -0
- package/dist/memory/context-compressor.js +289 -0
- package/dist/memory/context-compressor.js.map +1 -0
- package/dist/memory/correction-propagator.d.ts +44 -0
- package/dist/memory/correction-propagator.d.ts.map +1 -0
- package/dist/memory/correction-propagator.js +156 -0
- package/dist/memory/correction-propagator.js.map +1 -0
- package/dist/memory/daily-log.d.ts +67 -0
- package/dist/memory/daily-log.d.ts.map +1 -0
- package/dist/memory/daily-log.js +143 -0
- package/dist/memory/daily-log.js.map +1 -0
- package/dist/memory/dynamic-retrieval.d.ts +110 -0
- package/dist/memory/dynamic-retrieval.d.ts.map +1 -0
- package/dist/memory/dynamic-retrieval.js +688 -0
- package/dist/memory/dynamic-retrieval.js.map +1 -0
- package/dist/memory/embeddings.d.ts +116 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +461 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/hierarchical-memory.d.ts +141 -0
- package/dist/memory/hierarchical-memory.d.ts.map +1 -0
- package/dist/memory/hierarchical-memory.js +477 -0
- package/dist/memory/hierarchical-memory.js.map +1 -0
- package/dist/memory/memory-consolidator.d.ts +124 -0
- package/dist/memory/memory-consolidator.d.ts.map +1 -0
- package/dist/memory/memory-consolidator.js +514 -0
- package/dist/memory/memory-consolidator.js.map +1 -0
- package/dist/memory/memory-maintenance.d.ts +39 -0
- package/dist/memory/memory-maintenance.d.ts.map +1 -0
- package/dist/memory/memory-maintenance.js +305 -0
- package/dist/memory/memory-maintenance.js.map +1 -0
- package/dist/memory/model-router.d.ts +102 -0
- package/dist/memory/model-router.d.ts.map +1 -0
- package/dist/memory/model-router.js +448 -0
- package/dist/memory/model-router.js.map +1 -0
- package/dist/memory/multi-view-memory.d.ts +134 -0
- package/dist/memory/multi-view-memory.d.ts.map +1 -0
- package/dist/memory/multi-view-memory.js +420 -0
- package/dist/memory/multi-view-memory.js.map +1 -0
- package/dist/memory/prepopulate.d.ts +76 -0
- package/dist/memory/prepopulate.d.ts.map +1 -0
- package/dist/memory/prepopulate.js +815 -0
- package/dist/memory/prepopulate.js.map +1 -0
- package/dist/memory/semantic-compression.d.ts +77 -0
- package/dist/memory/semantic-compression.d.ts.map +1 -0
- package/dist/memory/semantic-compression.js +348 -0
- package/dist/memory/semantic-compression.js.map +1 -0
- package/dist/memory/serverless-qdrant.d.ts +102 -0
- package/dist/memory/serverless-qdrant.d.ts.map +1 -0
- package/dist/memory/serverless-qdrant.js +369 -0
- package/dist/memory/serverless-qdrant.js.map +1 -0
- package/dist/memory/short-term/factory.d.ts +26 -0
- package/dist/memory/short-term/factory.d.ts.map +1 -0
- package/dist/memory/short-term/factory.js +28 -0
- package/dist/memory/short-term/factory.js.map +1 -0
- package/dist/memory/short-term/indexeddb.d.ts +25 -0
- package/dist/memory/short-term/indexeddb.d.ts.map +1 -0
- package/dist/memory/short-term/indexeddb.js +64 -0
- package/dist/memory/short-term/indexeddb.js.map +1 -0
- package/dist/memory/short-term/schema.d.ts +6 -0
- package/dist/memory/short-term/schema.d.ts.map +1 -0
- package/dist/memory/short-term/schema.js +119 -0
- package/dist/memory/short-term/schema.js.map +1 -0
- package/dist/memory/short-term/sqlite.d.ts +50 -0
- package/dist/memory/short-term/sqlite.d.ts.map +1 -0
- package/dist/memory/short-term/sqlite.js +221 -0
- package/dist/memory/short-term/sqlite.js.map +1 -0
- package/dist/memory/speculative-cache.d.ts +111 -0
- package/dist/memory/speculative-cache.d.ts.map +1 -0
- package/dist/memory/speculative-cache.js +409 -0
- package/dist/memory/speculative-cache.js.map +1 -0
- package/dist/memory/task-classifier.d.ts +34 -0
- package/dist/memory/task-classifier.d.ts.map +1 -0
- package/dist/memory/task-classifier.js +300 -0
- package/dist/memory/task-classifier.js.map +1 -0
- package/dist/memory/terminal-bench-knowledge.d.ts +48 -0
- package/dist/memory/terminal-bench-knowledge.d.ts.map +1 -0
- package/dist/memory/terminal-bench-knowledge.js +399 -0
- package/dist/memory/terminal-bench-knowledge.js.map +1 -0
- package/dist/memory/write-gate.d.ts +39 -0
- package/dist/memory/write-gate.d.ts.map +1 -0
- package/dist/memory/write-gate.js +190 -0
- package/dist/memory/write-gate.js.map +1 -0
- package/dist/models/executor.d.ts +130 -0
- package/dist/models/executor.d.ts.map +1 -0
- package/dist/models/executor.js +383 -0
- package/dist/models/executor.js.map +1 -0
- package/dist/models/index.d.ts +15 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +17 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/planner.d.ts +71 -0
- package/dist/models/planner.d.ts.map +1 -0
- package/dist/models/planner.js +344 -0
- package/dist/models/planner.js.map +1 -0
- package/dist/models/router.d.ts +75 -0
- package/dist/models/router.d.ts.map +1 -0
- package/dist/models/router.js +344 -0
- package/dist/models/router.js.map +1 -0
- package/dist/models/types.d.ts +370 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +181 -0
- package/dist/models/types.js.map +1 -0
- package/dist/tasks/coordination.d.ts +74 -0
- package/dist/tasks/coordination.d.ts.map +1 -0
- package/dist/tasks/coordination.js +237 -0
- package/dist/tasks/coordination.js.map +1 -0
- package/dist/tasks/database.d.ts +14 -0
- package/dist/tasks/database.d.ts.map +1 -0
- package/dist/tasks/database.js +128 -0
- package/dist/tasks/database.js.map +1 -0
- package/dist/tasks/index.d.ts +5 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +5 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/service.d.ts +39 -0
- package/dist/tasks/service.d.ts.map +1 -0
- package/dist/tasks/service.js +582 -0
- package/dist/tasks/service.js.map +1 -0
- package/dist/tasks/types.d.ts +224 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +64 -0
- package/dist/tasks/types.js.map +1 -0
- package/dist/types/analysis.d.ts +82 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +2 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/config.d.ts +3023 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +292 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/coordination.d.ts +240 -0
- package/dist/types/coordination.d.ts.map +1 -0
- package/dist/types/coordination.js +43 -0
- package/dist/types/coordination.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/calculate-average.d.ts +15 -0
- package/dist/utils/calculate-average.d.ts.map +1 -0
- package/dist/utils/calculate-average.js +21 -0
- package/dist/utils/calculate-average.js.map +1 -0
- package/dist/utils/config-manager.d.ts +30 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +41 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/dijkstra.d.ts +17 -0
- package/dist/utils/dijkstra.d.ts.map +1 -0
- package/dist/utils/dijkstra.js +91 -0
- package/dist/utils/dijkstra.js.map +1 -0
- package/dist/utils/fetch-with-retry.d.ts +5 -0
- package/dist/utils/fetch-with-retry.d.ts.map +1 -0
- package/dist/utils/fetch-with-retry.js +61 -0
- package/dist/utils/fetch-with-retry.js.map +1 -0
- package/dist/utils/merge-claude-md.d.ts +28 -0
- package/dist/utils/merge-claude-md.d.ts.map +1 -0
- package/dist/utils/merge-claude-md.js +342 -0
- package/dist/utils/merge-claude-md.js.map +1 -0
- package/dist/utils/order-processor-refactored.d.ts +126 -0
- package/dist/utils/order-processor-refactored.d.ts.map +1 -0
- package/dist/utils/order-processor-refactored.js +165 -0
- package/dist/utils/order-processor-refactored.js.map +1 -0
- package/dist/utils/order-processor-strategy.d.ts +72 -0
- package/dist/utils/order-processor-strategy.d.ts.map +1 -0
- package/dist/utils/order-processor-strategy.js +158 -0
- package/dist/utils/order-processor-strategy.js.map +1 -0
- package/dist/utils/order-processor.d.ts +242 -0
- package/dist/utils/order-processor.d.ts.map +1 -0
- package/dist/utils/order-processor.js +370 -0
- package/dist/utils/order-processor.js.map +1 -0
- package/dist/utils/rate-limiter-simple.d.ts +58 -0
- package/dist/utils/rate-limiter-simple.d.ts.map +1 -0
- package/dist/utils/rate-limiter-simple.js +100 -0
- package/dist/utils/rate-limiter-simple.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +62 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +150 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +37 -0
- package/dist/utils/string-similarity.d.ts.map +1 -0
- package/dist/utils/string-similarity.js +114 -0
- package/dist/utils/string-similarity.js.map +1 -0
- package/dist/utils/validate-json.d.ts +51 -0
- package/dist/utils/validate-json.d.ts.map +1 -0
- package/dist/utils/validate-json.js +99 -0
- package/dist/utils/validate-json.js.map +1 -0
- package/package.json +96 -0
- package/templates/CLAUDE.template.md +11 -0
- package/templates/CLAUDE_ARCHITECTURE.template.md +103 -0
- package/templates/CLAUDE_CODING.template.md +125 -0
- package/templates/CLAUDE_DROIDS.template.md +109 -0
- package/templates/CLAUDE_MEMORY.template.md +130 -0
- package/templates/CLAUDE_WORKFLOWS.template.md +136 -0
- package/templates/PROJECT.template.md +209 -0
- package/templates/SCHEMA.md +57 -0
- package/templates/archive/CLAUDE.template.root-v6.md +762 -0
- package/templates/archive/CLAUDE.template.v6.md +762 -0
- package/templates/hooks/pre-compact.sh +68 -0
- package/templates/hooks/session-start.sh +106 -0
- package/tools/agents/README.md +224 -0
- package/tools/agents/UAP/README.md +351 -0
- package/tools/agents/UAP/__init__.py +9 -0
- package/tools/agents/UAP/cli.py +675 -0
- package/tools/agents/UAP/version.py +2 -0
- package/tools/agents/benchmarks/benchmark_memory_systems.py +637 -0
- package/tools/agents/benchmarks/results/benchmark_20260106_064817.json +170 -0
- package/tools/agents/benchmarks/results/benchmark_20260106_064817.md +51 -0
- package/tools/agents/config/chat_template.jinja +172 -0
- package/tools/agents/docker-compose.qdrant.yml +24 -0
- package/tools/agents/migrations/apply.py +256 -0
- package/tools/agents/scripts/fix_qwen_chat_template.py +314 -0
- package/tools/agents/scripts/init_qdrant.py +151 -0
- package/tools/agents/scripts/memory_migration.py +518 -0
- package/tools/agents/scripts/migrate_memory_to_qdrant.py +113 -0
- package/tools/agents/scripts/query_memory.py +189 -0
- package/tools/agents/scripts/qwen_tool_call_test.py +419 -0
- package/tools/agents/scripts/qwen_tool_call_wrapper.py +517 -0
- package/tools/agents/scripts/start-services.sh +96 -0
- package/tools/agents/tests/test_uap_compliance.py +257 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Memory Migration Tool
|
|
4
|
+
|
|
5
|
+
Provides automated migration between different memory system implementations:
|
|
6
|
+
- SQLite short-term <-> JSON export
|
|
7
|
+
- Qdrant long-term <-> JSON export
|
|
8
|
+
- Qdrant -> Mem0 format
|
|
9
|
+
- Qdrant -> A-MEM format
|
|
10
|
+
- Full backup/restore capabilities
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
# Export all memories to JSON
|
|
14
|
+
python memory_migration.py export all output.json
|
|
15
|
+
|
|
16
|
+
# Export Qdrant to Mem0 format
|
|
17
|
+
python memory_migration.py export qdrant --format mem0 output.json
|
|
18
|
+
|
|
19
|
+
# Backup everything
|
|
20
|
+
python memory_migration.py backup
|
|
21
|
+
|
|
22
|
+
# Restore from backup
|
|
23
|
+
python memory_migration.py restore <backup_id>
|
|
24
|
+
|
|
25
|
+
# Migrate to enhanced schema
|
|
26
|
+
python memory_migration.py upgrade
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
import argparse
|
|
30
|
+
import hashlib
|
|
31
|
+
import json
|
|
32
|
+
import os
|
|
33
|
+
import shutil
|
|
34
|
+
import sqlite3
|
|
35
|
+
import uuid
|
|
36
|
+
from datetime import datetime
|
|
37
|
+
from pathlib import Path
|
|
38
|
+
from typing import Any, Optional
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
from sentence_transformers import SentenceTransformer
|
|
42
|
+
from qdrant_client import QdrantClient
|
|
43
|
+
from qdrant_client.models import PointStruct
|
|
44
|
+
QDRANT_AVAILABLE = True
|
|
45
|
+
except ImportError:
|
|
46
|
+
QDRANT_AVAILABLE = False
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_project_root() -> Path:
|
|
50
|
+
return Path(__file__).parent.parent.parent.parent
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_data_dir() -> Path:
|
|
54
|
+
return get_project_root() / "tools/agents/data/memory"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_backup_dir() -> Path:
|
|
58
|
+
backup_dir = get_data_dir() / "backups"
|
|
59
|
+
backup_dir.mkdir(parents=True, exist_ok=True)
|
|
60
|
+
return backup_dir
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class MemoryMigration:
|
|
64
|
+
def __init__(self):
|
|
65
|
+
self.data_dir = get_data_dir()
|
|
66
|
+
self.backup_dir = get_backup_dir()
|
|
67
|
+
self.short_term_db = self.data_dir / "short_term.db"
|
|
68
|
+
self.long_term_json = self.data_dir / "long_term.json"
|
|
69
|
+
|
|
70
|
+
self.qdrant = None
|
|
71
|
+
self.model = None
|
|
72
|
+
if QDRANT_AVAILABLE:
|
|
73
|
+
try:
|
|
74
|
+
self.qdrant = QdrantClient(host="localhost", port=6333)
|
|
75
|
+
self.model = SentenceTransformer("all-MiniLM-L6-v2")
|
|
76
|
+
except Exception:
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def export_sqlite(self) -> list[dict]:
|
|
80
|
+
"""Export all SQLite memories to list of dicts."""
|
|
81
|
+
if not self.short_term_db.exists():
|
|
82
|
+
return []
|
|
83
|
+
|
|
84
|
+
conn = sqlite3.connect(self.short_term_db)
|
|
85
|
+
conn.row_factory = sqlite3.Row
|
|
86
|
+
cursor = conn.cursor()
|
|
87
|
+
|
|
88
|
+
memories = []
|
|
89
|
+
|
|
90
|
+
# Export main memories table
|
|
91
|
+
cursor.execute("SELECT * FROM memories ORDER BY id")
|
|
92
|
+
for row in cursor.fetchall():
|
|
93
|
+
memories.append({
|
|
94
|
+
"source": "sqlite_memories",
|
|
95
|
+
"id": row["id"],
|
|
96
|
+
"timestamp": row["timestamp"],
|
|
97
|
+
"type": row["type"],
|
|
98
|
+
"content": row["content"]
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
# Export session_memories if exists
|
|
102
|
+
try:
|
|
103
|
+
cursor.execute("SELECT * FROM session_memories ORDER BY id")
|
|
104
|
+
for row in cursor.fetchall():
|
|
105
|
+
memories.append({
|
|
106
|
+
"source": "sqlite_session_memories",
|
|
107
|
+
"id": row["id"],
|
|
108
|
+
"session_id": row["session_id"],
|
|
109
|
+
"timestamp": row["timestamp"],
|
|
110
|
+
"type": row["type"],
|
|
111
|
+
"content": row["content"],
|
|
112
|
+
"context": row["context"],
|
|
113
|
+
"importance": row["importance"]
|
|
114
|
+
})
|
|
115
|
+
except sqlite3.OperationalError:
|
|
116
|
+
pass # Table doesn't exist
|
|
117
|
+
|
|
118
|
+
# Export entities if exists
|
|
119
|
+
try:
|
|
120
|
+
cursor.execute("SELECT * FROM entities ORDER BY id")
|
|
121
|
+
for row in cursor.fetchall():
|
|
122
|
+
memories.append({
|
|
123
|
+
"source": "sqlite_entities",
|
|
124
|
+
"id": row["id"],
|
|
125
|
+
"type": row["type"],
|
|
126
|
+
"name": row["name"],
|
|
127
|
+
"context": row["context"],
|
|
128
|
+
"first_seen": row["first_seen"],
|
|
129
|
+
"last_seen": row["last_seen"],
|
|
130
|
+
"mention_count": row["mention_count"]
|
|
131
|
+
})
|
|
132
|
+
except sqlite3.OperationalError:
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
# Export relationships if exists
|
|
136
|
+
try:
|
|
137
|
+
cursor.execute("SELECT * FROM relationships ORDER BY id")
|
|
138
|
+
for row in cursor.fetchall():
|
|
139
|
+
memories.append({
|
|
140
|
+
"source": "sqlite_relationships",
|
|
141
|
+
"id": row["id"],
|
|
142
|
+
"source_id": row["source_id"],
|
|
143
|
+
"target_id": row["target_id"],
|
|
144
|
+
"relation": row["relation"],
|
|
145
|
+
"weight": row["weight"],
|
|
146
|
+
"timestamp": row["timestamp"]
|
|
147
|
+
})
|
|
148
|
+
except sqlite3.OperationalError:
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
conn.close()
|
|
152
|
+
return memories
|
|
153
|
+
|
|
154
|
+
def export_qdrant(self, format: str = "native") -> list[dict]:
|
|
155
|
+
"""Export Qdrant memories.
|
|
156
|
+
|
|
157
|
+
Formats:
|
|
158
|
+
- native: Raw Qdrant format
|
|
159
|
+
- mem0: Mem0-compatible format
|
|
160
|
+
- amem: A-MEM compatible format
|
|
161
|
+
"""
|
|
162
|
+
if not self.qdrant:
|
|
163
|
+
return []
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
# Get all points (scroll through collection)
|
|
167
|
+
points = []
|
|
168
|
+
offset = None
|
|
169
|
+
|
|
170
|
+
while True:
|
|
171
|
+
result = self.qdrant.scroll(
|
|
172
|
+
collection_name="claude_memory",
|
|
173
|
+
limit=100,
|
|
174
|
+
offset=offset,
|
|
175
|
+
with_vectors=True,
|
|
176
|
+
with_payload=True
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if not result[0]:
|
|
180
|
+
break
|
|
181
|
+
|
|
182
|
+
points.extend(result[0])
|
|
183
|
+
offset = result[1]
|
|
184
|
+
|
|
185
|
+
if offset is None:
|
|
186
|
+
break
|
|
187
|
+
|
|
188
|
+
memories = []
|
|
189
|
+
for point in points:
|
|
190
|
+
if format == "native":
|
|
191
|
+
memories.append({
|
|
192
|
+
"source": "qdrant",
|
|
193
|
+
"id": str(point.id),
|
|
194
|
+
"vector": point.vector,
|
|
195
|
+
"payload": point.payload
|
|
196
|
+
})
|
|
197
|
+
elif format == "mem0":
|
|
198
|
+
# Mem0 format
|
|
199
|
+
memories.append({
|
|
200
|
+
"id": str(point.id),
|
|
201
|
+
"memory": point.payload.get("content", ""),
|
|
202
|
+
"hash": hashlib.md5(point.payload.get("content", "").encode()).hexdigest(),
|
|
203
|
+
"metadata": {
|
|
204
|
+
"type": point.payload.get("type"),
|
|
205
|
+
"tags": point.payload.get("tags", []),
|
|
206
|
+
"importance": point.payload.get("importance", 5),
|
|
207
|
+
"created_at": point.payload.get("timestamp"),
|
|
208
|
+
"updated_at": point.payload.get("timestamp")
|
|
209
|
+
},
|
|
210
|
+
"user_id": "claude_agent"
|
|
211
|
+
})
|
|
212
|
+
elif format == "amem":
|
|
213
|
+
# A-MEM format (Zettelkasten-style)
|
|
214
|
+
memories.append({
|
|
215
|
+
"id": str(point.id),
|
|
216
|
+
"title": point.payload.get("content", "")[:50] + "...",
|
|
217
|
+
"content": point.payload.get("content", ""),
|
|
218
|
+
"keywords": point.payload.get("tags", []),
|
|
219
|
+
"tags": point.payload.get("tags", []),
|
|
220
|
+
"links": [], # Would need to be computed from similarity
|
|
221
|
+
"created": point.payload.get("timestamp"),
|
|
222
|
+
"modified": point.payload.get("timestamp"),
|
|
223
|
+
"importance": point.payload.get("importance", 5)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
return memories
|
|
227
|
+
|
|
228
|
+
except Exception as e:
|
|
229
|
+
print(f"Error exporting Qdrant: {e}")
|
|
230
|
+
return []
|
|
231
|
+
|
|
232
|
+
def export_all(self, output_path: str, format: str = "native"):
|
|
233
|
+
"""Export all memories to a JSON file."""
|
|
234
|
+
export = {
|
|
235
|
+
"metadata": {
|
|
236
|
+
"exported_at": datetime.utcnow().isoformat() + "Z",
|
|
237
|
+
"format": format,
|
|
238
|
+
"version": "2.0"
|
|
239
|
+
},
|
|
240
|
+
"sqlite": self.export_sqlite(),
|
|
241
|
+
"qdrant": self.export_qdrant(format)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
with open(output_path, "w") as f:
|
|
245
|
+
json.dump(export, f, indent=2, default=str)
|
|
246
|
+
|
|
247
|
+
print(f"Exported {len(export['sqlite'])} SQLite entries")
|
|
248
|
+
print(f"Exported {len(export['qdrant'])} Qdrant entries")
|
|
249
|
+
print(f"Saved to: {output_path}")
|
|
250
|
+
|
|
251
|
+
def backup(self) -> str:
|
|
252
|
+
"""Create a full backup of all memory stores."""
|
|
253
|
+
backup_id = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
|
|
254
|
+
backup_path = self.backup_dir / backup_id
|
|
255
|
+
backup_path.mkdir(parents=True, exist_ok=True)
|
|
256
|
+
|
|
257
|
+
# Backup SQLite
|
|
258
|
+
if self.short_term_db.exists():
|
|
259
|
+
shutil.copy2(self.short_term_db, backup_path / "short_term.db")
|
|
260
|
+
print(f"Backed up SQLite: {self.short_term_db}")
|
|
261
|
+
|
|
262
|
+
# Backup long_term.json
|
|
263
|
+
if self.long_term_json.exists():
|
|
264
|
+
shutil.copy2(self.long_term_json, backup_path / "long_term.json")
|
|
265
|
+
print(f"Backed up JSON: {self.long_term_json}")
|
|
266
|
+
|
|
267
|
+
# Export Qdrant to JSON
|
|
268
|
+
qdrant_export = self.export_qdrant("native")
|
|
269
|
+
with open(backup_path / "qdrant_export.json", "w") as f:
|
|
270
|
+
json.dump(qdrant_export, f, indent=2, default=str)
|
|
271
|
+
print(f"Backed up Qdrant: {len(qdrant_export)} entries")
|
|
272
|
+
|
|
273
|
+
# Create manifest
|
|
274
|
+
manifest = {
|
|
275
|
+
"backup_id": backup_id,
|
|
276
|
+
"created_at": datetime.utcnow().isoformat() + "Z",
|
|
277
|
+
"files": os.listdir(backup_path),
|
|
278
|
+
"sqlite_entries": len(self.export_sqlite()),
|
|
279
|
+
"qdrant_entries": len(qdrant_export)
|
|
280
|
+
}
|
|
281
|
+
with open(backup_path / "manifest.json", "w") as f:
|
|
282
|
+
json.dump(manifest, f, indent=2)
|
|
283
|
+
|
|
284
|
+
print(f"\nBackup complete: {backup_path}")
|
|
285
|
+
print(f"Backup ID: {backup_id}")
|
|
286
|
+
return backup_id
|
|
287
|
+
|
|
288
|
+
def restore(self, backup_id: str):
|
|
289
|
+
"""Restore from a backup."""
|
|
290
|
+
backup_path = self.backup_dir / backup_id
|
|
291
|
+
|
|
292
|
+
if not backup_path.exists():
|
|
293
|
+
print(f"Backup not found: {backup_id}")
|
|
294
|
+
print(f"Available backups: {os.listdir(self.backup_dir)}")
|
|
295
|
+
return False
|
|
296
|
+
|
|
297
|
+
# Confirm
|
|
298
|
+
manifest_path = backup_path / "manifest.json"
|
|
299
|
+
if manifest_path.exists():
|
|
300
|
+
with open(manifest_path) as f:
|
|
301
|
+
manifest = json.load(f)
|
|
302
|
+
print(f"Backup from: {manifest['created_at']}")
|
|
303
|
+
print(f"SQLite entries: {manifest['sqlite_entries']}")
|
|
304
|
+
print(f"Qdrant entries: {manifest['qdrant_entries']}")
|
|
305
|
+
|
|
306
|
+
# Restore SQLite
|
|
307
|
+
sqlite_backup = backup_path / "short_term.db"
|
|
308
|
+
if sqlite_backup.exists():
|
|
309
|
+
# Backup current before overwriting
|
|
310
|
+
if self.short_term_db.exists():
|
|
311
|
+
shutil.copy2(self.short_term_db, self.short_term_db.with_suffix(".db.pre_restore"))
|
|
312
|
+
shutil.copy2(sqlite_backup, self.short_term_db)
|
|
313
|
+
print(f"Restored SQLite: {self.short_term_db}")
|
|
314
|
+
|
|
315
|
+
# Restore long_term.json
|
|
316
|
+
json_backup = backup_path / "long_term.json"
|
|
317
|
+
if json_backup.exists():
|
|
318
|
+
if self.long_term_json.exists():
|
|
319
|
+
shutil.copy2(self.long_term_json, self.long_term_json.with_suffix(".json.pre_restore"))
|
|
320
|
+
shutil.copy2(json_backup, self.long_term_json)
|
|
321
|
+
print(f"Restored JSON: {self.long_term_json}")
|
|
322
|
+
|
|
323
|
+
# Restore Qdrant
|
|
324
|
+
qdrant_backup = backup_path / "qdrant_export.json"
|
|
325
|
+
if qdrant_backup.exists() and self.qdrant and self.model:
|
|
326
|
+
with open(qdrant_backup) as f:
|
|
327
|
+
qdrant_data = json.load(f)
|
|
328
|
+
|
|
329
|
+
if qdrant_data:
|
|
330
|
+
# Recreate collection
|
|
331
|
+
try:
|
|
332
|
+
self.qdrant.delete_collection("claude_memory")
|
|
333
|
+
except Exception:
|
|
334
|
+
pass
|
|
335
|
+
|
|
336
|
+
from qdrant_client.models import VectorParams, Distance
|
|
337
|
+
self.qdrant.create_collection(
|
|
338
|
+
collection_name="claude_memory",
|
|
339
|
+
vectors_config=VectorParams(size=384, distance=Distance.COSINE)
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Restore points
|
|
343
|
+
points = []
|
|
344
|
+
for entry in qdrant_data:
|
|
345
|
+
points.append(PointStruct(
|
|
346
|
+
id=entry["id"],
|
|
347
|
+
vector=entry["vector"],
|
|
348
|
+
payload=entry["payload"]
|
|
349
|
+
))
|
|
350
|
+
|
|
351
|
+
if points:
|
|
352
|
+
self.qdrant.upsert(collection_name="claude_memory", points=points)
|
|
353
|
+
print(f"Restored Qdrant: {len(points)} entries")
|
|
354
|
+
|
|
355
|
+
print("\nRestore complete!")
|
|
356
|
+
return True
|
|
357
|
+
|
|
358
|
+
def upgrade_schema(self):
|
|
359
|
+
"""Upgrade SQLite schema to enhanced v2.0 with session memory and graph tables."""
|
|
360
|
+
if not self.short_term_db.exists():
|
|
361
|
+
print("No SQLite database to upgrade")
|
|
362
|
+
return
|
|
363
|
+
|
|
364
|
+
conn = sqlite3.connect(self.short_term_db)
|
|
365
|
+
cursor = conn.cursor()
|
|
366
|
+
|
|
367
|
+
# Check current schema
|
|
368
|
+
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
|
369
|
+
existing_tables = {row[0] for row in cursor.fetchall()}
|
|
370
|
+
|
|
371
|
+
# Add session_memories table if not exists
|
|
372
|
+
if "session_memories" not in existing_tables:
|
|
373
|
+
print("Creating session_memories table...")
|
|
374
|
+
cursor.execute("""
|
|
375
|
+
CREATE TABLE session_memories (
|
|
376
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
377
|
+
session_id TEXT NOT NULL,
|
|
378
|
+
timestamp TEXT NOT NULL,
|
|
379
|
+
type TEXT NOT NULL CHECK(type IN ('summary', 'decision', 'entity', 'error')),
|
|
380
|
+
content TEXT NOT NULL,
|
|
381
|
+
context TEXT,
|
|
382
|
+
importance INTEGER DEFAULT 5
|
|
383
|
+
)
|
|
384
|
+
""")
|
|
385
|
+
cursor.execute("CREATE INDEX idx_session_memories_session ON session_memories(session_id)")
|
|
386
|
+
cursor.execute("CREATE INDEX idx_session_memories_type ON session_memories(type)")
|
|
387
|
+
|
|
388
|
+
# Add entities table if not exists
|
|
389
|
+
if "entities" not in existing_tables:
|
|
390
|
+
print("Creating entities table...")
|
|
391
|
+
cursor.execute("""
|
|
392
|
+
CREATE TABLE entities (
|
|
393
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
394
|
+
type TEXT NOT NULL CHECK(type IN ('file', 'function', 'concept', 'error', 'config', 'service')),
|
|
395
|
+
name TEXT NOT NULL,
|
|
396
|
+
context TEXT,
|
|
397
|
+
first_seen TEXT NOT NULL,
|
|
398
|
+
last_seen TEXT NOT NULL,
|
|
399
|
+
mention_count INTEGER DEFAULT 1,
|
|
400
|
+
UNIQUE(type, name)
|
|
401
|
+
)
|
|
402
|
+
""")
|
|
403
|
+
cursor.execute("CREATE INDEX idx_entities_type ON entities(type)")
|
|
404
|
+
cursor.execute("CREATE INDEX idx_entities_name ON entities(name)")
|
|
405
|
+
|
|
406
|
+
# Add relationships table if not exists
|
|
407
|
+
if "relationships" not in existing_tables:
|
|
408
|
+
print("Creating relationships table...")
|
|
409
|
+
cursor.execute("""
|
|
410
|
+
CREATE TABLE relationships (
|
|
411
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
412
|
+
source_id INTEGER NOT NULL,
|
|
413
|
+
target_id INTEGER NOT NULL,
|
|
414
|
+
relation TEXT NOT NULL CHECK(relation IN ('depends_on', 'fixes', 'causes', 'related_to', 'contains', 'implements')),
|
|
415
|
+
weight REAL DEFAULT 1.0,
|
|
416
|
+
timestamp TEXT NOT NULL,
|
|
417
|
+
FOREIGN KEY (source_id) REFERENCES entities(id),
|
|
418
|
+
FOREIGN KEY (target_id) REFERENCES entities(id)
|
|
419
|
+
)
|
|
420
|
+
""")
|
|
421
|
+
cursor.execute("CREATE INDEX idx_relationships_source ON relationships(source_id)")
|
|
422
|
+
cursor.execute("CREATE INDEX idx_relationships_target ON relationships(target_id)")
|
|
423
|
+
cursor.execute("CREATE INDEX idx_relationships_relation ON relationships(relation)")
|
|
424
|
+
|
|
425
|
+
conn.commit()
|
|
426
|
+
conn.close()
|
|
427
|
+
|
|
428
|
+
print("Schema upgrade complete!")
|
|
429
|
+
print("\nNew tables added:")
|
|
430
|
+
print(" - session_memories: For session-scoped context")
|
|
431
|
+
print(" - entities: For knowledge graph nodes")
|
|
432
|
+
print(" - relationships: For knowledge graph edges")
|
|
433
|
+
|
|
434
|
+
def list_backups(self):
|
|
435
|
+
"""List all available backups."""
|
|
436
|
+
backups = []
|
|
437
|
+
for backup_id in sorted(os.listdir(self.backup_dir)):
|
|
438
|
+
backup_path = self.backup_dir / backup_id
|
|
439
|
+
manifest_path = backup_path / "manifest.json"
|
|
440
|
+
|
|
441
|
+
if manifest_path.exists():
|
|
442
|
+
with open(manifest_path) as f:
|
|
443
|
+
manifest = json.load(f)
|
|
444
|
+
backups.append({
|
|
445
|
+
"id": backup_id,
|
|
446
|
+
"created_at": manifest.get("created_at"),
|
|
447
|
+
"sqlite_entries": manifest.get("sqlite_entries", 0),
|
|
448
|
+
"qdrant_entries": manifest.get("qdrant_entries", 0)
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
if not backups:
|
|
452
|
+
print("No backups found")
|
|
453
|
+
return
|
|
454
|
+
|
|
455
|
+
print("\nAvailable Backups:")
|
|
456
|
+
print("-" * 60)
|
|
457
|
+
for b in backups:
|
|
458
|
+
print(f" {b['id']} | {b['created_at']} | SQLite: {b['sqlite_entries']} Qdrant: {b['qdrant_entries']}")
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def main():
|
|
462
|
+
parser = argparse.ArgumentParser(description="Memory Migration Tool")
|
|
463
|
+
subparsers = parser.add_subparsers(dest="command", help="Command")
|
|
464
|
+
|
|
465
|
+
# Export command
|
|
466
|
+
export_parser = subparsers.add_parser("export", help="Export memories")
|
|
467
|
+
export_parser.add_argument("source", choices=["all", "sqlite", "qdrant"])
|
|
468
|
+
export_parser.add_argument("output", help="Output file path")
|
|
469
|
+
export_parser.add_argument("--format", choices=["native", "mem0", "amem"], default="native")
|
|
470
|
+
|
|
471
|
+
# Backup command
|
|
472
|
+
subparsers.add_parser("backup", help="Create full backup")
|
|
473
|
+
|
|
474
|
+
# Restore command
|
|
475
|
+
restore_parser = subparsers.add_parser("restore", help="Restore from backup")
|
|
476
|
+
restore_parser.add_argument("backup_id", help="Backup ID to restore")
|
|
477
|
+
|
|
478
|
+
# List command
|
|
479
|
+
subparsers.add_parser("list", help="List available backups")
|
|
480
|
+
|
|
481
|
+
# Upgrade command
|
|
482
|
+
subparsers.add_parser("upgrade", help="Upgrade schema to v2.0")
|
|
483
|
+
|
|
484
|
+
args = parser.parse_args()
|
|
485
|
+
migration = MemoryMigration()
|
|
486
|
+
|
|
487
|
+
if args.command == "export":
|
|
488
|
+
if args.source == "all":
|
|
489
|
+
migration.export_all(args.output, args.format)
|
|
490
|
+
elif args.source == "sqlite":
|
|
491
|
+
data = migration.export_sqlite()
|
|
492
|
+
with open(args.output, "w") as f:
|
|
493
|
+
json.dump(data, f, indent=2)
|
|
494
|
+
print(f"Exported {len(data)} SQLite entries to {args.output}")
|
|
495
|
+
elif args.source == "qdrant":
|
|
496
|
+
data = migration.export_qdrant(args.format)
|
|
497
|
+
with open(args.output, "w") as f:
|
|
498
|
+
json.dump(data, f, indent=2, default=str)
|
|
499
|
+
print(f"Exported {len(data)} Qdrant entries to {args.output}")
|
|
500
|
+
|
|
501
|
+
elif args.command == "backup":
|
|
502
|
+
migration.backup()
|
|
503
|
+
|
|
504
|
+
elif args.command == "restore":
|
|
505
|
+
migration.restore(args.backup_id)
|
|
506
|
+
|
|
507
|
+
elif args.command == "list":
|
|
508
|
+
migration.list_backups()
|
|
509
|
+
|
|
510
|
+
elif args.command == "upgrade":
|
|
511
|
+
migration.upgrade_schema()
|
|
512
|
+
|
|
513
|
+
else:
|
|
514
|
+
parser.print_help()
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
if __name__ == "__main__":
|
|
518
|
+
main()
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Migrate long-term memory from JSON to Qdrant vector database.
|
|
4
|
+
|
|
5
|
+
This script:
|
|
6
|
+
1. Reads memories from agents/data/memory/long_term.json
|
|
7
|
+
2. Generates embeddings using sentence-transformers
|
|
8
|
+
3. Upserts vectors to Qdrant collection 'claude_memory'
|
|
9
|
+
|
|
10
|
+
Requirements:
|
|
11
|
+
pip install sentence-transformers qdrant-client
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
python agents/scripts/migrate_memory_to_qdrant.py
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import uuid
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
from sentence_transformers import SentenceTransformer
|
|
23
|
+
from qdrant_client import QdrantClient
|
|
24
|
+
from qdrant_client.models import PointStruct
|
|
25
|
+
except ImportError as e:
|
|
26
|
+
print(f"Error: Missing required packages: {e}")
|
|
27
|
+
print("\nPlease install dependencies:")
|
|
28
|
+
print(" cd /home/cogtek/dev/miller-tech/pay2u")
|
|
29
|
+
print(" agents/.venv/bin/pip install sentence-transformers qdrant-client")
|
|
30
|
+
print("\nThen run:")
|
|
31
|
+
print(" agents/.venv/bin/python agents/scripts/migrate_memory_to_qdrant.py")
|
|
32
|
+
exit(1)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main():
|
|
36
|
+
# Configuration
|
|
37
|
+
QDRANT_HOST = "localhost"
|
|
38
|
+
QDRANT_PORT = 6333
|
|
39
|
+
COLLECTION_NAME = "claude_memory"
|
|
40
|
+
MODEL_NAME = "all-MiniLM-L6-v2" # 384 dimensions, fast and effective
|
|
41
|
+
|
|
42
|
+
project_root = Path(__file__).parent.parent.parent
|
|
43
|
+
memory_file = project_root / "agents/data/memory/long_term.json"
|
|
44
|
+
|
|
45
|
+
print(f"Loading memories from {memory_file}")
|
|
46
|
+
with open(memory_file) as f:
|
|
47
|
+
data = json.load(f)
|
|
48
|
+
|
|
49
|
+
memories = data.get("memories", [])
|
|
50
|
+
print(f"Found {len(memories)} memories to migrate")
|
|
51
|
+
|
|
52
|
+
# Initialize embedding model
|
|
53
|
+
print(f"Loading embedding model: {MODEL_NAME}")
|
|
54
|
+
model = SentenceTransformer(MODEL_NAME)
|
|
55
|
+
|
|
56
|
+
# Initialize Qdrant client
|
|
57
|
+
print(f"Connecting to Qdrant at {QDRANT_HOST}:{QDRANT_PORT}")
|
|
58
|
+
client = QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT)
|
|
59
|
+
|
|
60
|
+
# Prepare points for upsert
|
|
61
|
+
points = []
|
|
62
|
+
for memory in memories:
|
|
63
|
+
# Generate embedding from content
|
|
64
|
+
content = memory["content"]
|
|
65
|
+
embedding = model.encode(content).tolist()
|
|
66
|
+
|
|
67
|
+
# Create point with payload
|
|
68
|
+
point = PointStruct(
|
|
69
|
+
id=str(uuid.uuid4()),
|
|
70
|
+
vector=embedding,
|
|
71
|
+
payload={
|
|
72
|
+
"original_id": memory["id"],
|
|
73
|
+
"type": memory["type"],
|
|
74
|
+
"tags": memory.get("tags", []),
|
|
75
|
+
"importance": memory.get("importance", 5),
|
|
76
|
+
"content": content,
|
|
77
|
+
"timestamp": memory.get("timestamp", "")
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
points.append(point)
|
|
81
|
+
print(f" Encoded: [{memory['type']}] {memory['id']}")
|
|
82
|
+
|
|
83
|
+
# Upsert to Qdrant
|
|
84
|
+
print(f"\nUpserting {len(points)} points to collection '{COLLECTION_NAME}'")
|
|
85
|
+
client.upsert(
|
|
86
|
+
collection_name=COLLECTION_NAME,
|
|
87
|
+
points=points
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Verify
|
|
91
|
+
collection_info = client.get_collection(COLLECTION_NAME)
|
|
92
|
+
print(f"\nCollection '{COLLECTION_NAME}' now has {collection_info.points_count} points")
|
|
93
|
+
|
|
94
|
+
# Test search
|
|
95
|
+
print("\nTesting semantic search for 'Redis caching'...")
|
|
96
|
+
test_query = "Redis caching performance"
|
|
97
|
+
test_embedding = model.encode(test_query).tolist()
|
|
98
|
+
results = client.query_points(
|
|
99
|
+
collection_name=COLLECTION_NAME,
|
|
100
|
+
query=test_embedding,
|
|
101
|
+
limit=3
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
print("Top 3 results:")
|
|
105
|
+
for i, point in enumerate(results.points, 1):
|
|
106
|
+
print(f" {i}. [{point.payload['type']}] Score: {point.score:.3f}")
|
|
107
|
+
print(f" {point.payload['content'][:80]}...")
|
|
108
|
+
|
|
109
|
+
print("\nMigration complete!")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
main()
|