squish-memory 1.1.5 → 1.2.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/.env.example +32 -16
- package/CHANGELOG.md +147 -0
- package/README.md +120 -78
- package/{scripts → bin}/dependency-manager.mjs +217 -217
- package/{scripts → bin}/detect-clients.mjs +78 -78
- package/bin/install-interactive.mjs +321 -0
- package/bin/squish-mcp.mjs +46 -0
- package/bin/squish.mjs +33 -0
- package/config/mcp-migration-map.json +1 -6
- package/config/mcp-mode-semantics.json +19 -23
- package/config/mcp-remote-auth.json +3 -26
- package/config/mcp-universal.schema.json +5 -35
- package/config/settings.json +107 -52
- package/config.js +5 -0
- package/config.ts +218 -0
- package/core/adapters/config/claude-code.ts +133 -0
- package/core/adapters/config/cursor.ts +90 -0
- package/core/adapters/config/opencode.ts +89 -0
- package/core/adapters/config/windsurf.ts +90 -0
- package/core/adapters/index.ts +102 -0
- package/core/adapters/timeline.ts +116 -0
- package/core/adapters/types.ts +166 -0
- package/core/agent-preferences.ts +140 -0
- package/core/algorithms/analytics/token-estimator.ts +216 -0
- package/core/algorithms/detection/hash-filters.ts +260 -0
- package/core/algorithms/detection/semantic-ranker.ts +194 -0
- package/core/algorithms/detection/two-stage-detector.ts +421 -0
- package/core/algorithms/handlers/approve-merge.ts +215 -0
- package/core/algorithms/handlers/detect-duplicates.ts +192 -0
- package/core/algorithms/handlers/get-stats.ts +132 -0
- package/core/algorithms/handlers/list-proposals.ts +130 -0
- package/core/algorithms/handlers/preview-merge.ts +139 -0
- package/core/algorithms/handlers/reject-merge.ts +93 -0
- package/core/algorithms/handlers/reverse-merge.ts +155 -0
- package/core/algorithms/index.ts +39 -0
- package/core/algorithms/operations/cache-maintenance.ts +182 -0
- package/core/algorithms/safety/safety-checks.ts +256 -0
- package/core/algorithms/strategies/merge-strategies.ts +381 -0
- package/core/algorithms/types.ts +140 -0
- package/core/algorithms/utils/response-builder.ts +61 -0
- package/core/associations.ts +363 -0
- package/core/beliefs/decay.ts +289 -0
- package/core/beliefs/extractor.ts +131 -0
- package/core/beliefs/store.ts +557 -0
- package/core/beliefs/types.ts +38 -0
- package/core/commands/mcp-server.ts +5 -0
- package/core/compression.ts +177 -0
- package/core/config.js +2 -0
- package/core/consolidation.ts +330 -0
- package/core/context/agent-context.ts +388 -0
- package/core/context/context-paging.ts +449 -0
- package/core/context/context-window.ts +234 -0
- package/core/context/context.ts +35 -0
- package/core/embeddings/embeddings.ts +616 -0
- package/core/embeddings/google-multimodal.ts +200 -0
- package/{dist/core/local-embeddings.js → core/embeddings/local-embeddings.ts} +12 -11
- package/core/embeddings/qmd-client.ts +495 -0
- package/core/embeddings/transformers-local.ts +261 -0
- package/core/embeddings.js +4 -0
- package/core/error-handling.ts +206 -0
- package/core/external +219 -0
- package/core/graph/entity-deduplicator.ts +232 -0
- package/core/graph/graph-builder.ts +257 -0
- package/core/graph/graph-traversal.ts +490 -0
- package/core/graph/index.ts +24 -0
- package/core/graph/llm-entity-extractor.ts +402 -0
- package/core/graph/multi-hop-retrieval.ts +317 -0
- package/core/graph/relationship-extractor.ts +465 -0
- package/core/hooks/agent-hooks.ts +653 -0
- package/core/hooks/auto-tagger.ts +149 -0
- package/core/hooks/capture-filter.ts +169 -0
- package/core/hot-cache.ts +388 -0
- package/core/index.ts +10 -0
- package/core/ingestion/agent-memory.ts +167 -0
- package/core/ingestion/core-memory.ts +326 -0
- package/core/ingestion/learnings.ts +260 -0
- package/core/ingestion/signal-engine.ts +266 -0
- package/core/integrations/obsidian-vault.ts +197 -0
- package/core/layers/generator.ts +115 -0
- package/core/lib/db-client.ts +168 -0
- package/core/lib/parse-embedding.ts +59 -0
- package/core/lib/schemas.ts +102 -0
- package/core/lib/types.ts +49 -0
- package/core/lib/utils.ts +151 -0
- package/core/lib/validation.ts +180 -0
- package/core/lifecycle.ts +353 -0
- package/core/logger.ts +59 -0
- package/core/memory/bridge-discovery.ts +395 -0
- package/core/memory/categorizer.ts +390 -0
- package/core/memory/conflict-detector.ts +62 -0
- package/core/memory/consolidation.ts +372 -0
- package/core/memory/context-collector.ts +75 -0
- package/core/memory/contradiction-resolver.ts +494 -0
- package/core/memory/edit-workflow.ts +174 -0
- package/core/memory/entity-extractor.ts +426 -0
- package/core/memory/entity-resolver.ts +89 -0
- package/core/memory/explain.ts +112 -0
- package/core/memory/fact-deriver.ts +300 -0
- package/core/memory/fact-extractor.ts +120 -0
- package/core/memory/feedback-tracker.ts +200 -0
- package/core/memory/hooks.ts +230 -0
- package/core/memory/hybrid-retrieval.ts +65 -0
- package/core/memory/hybrid-scorer.ts +325 -0
- package/core/memory/hybrid-search.ts +748 -0
- package/core/memory/importance.ts +319 -0
- package/core/memory/index.ts +11 -0
- package/core/memory/loader.ts +178 -0
- package/core/memory/markdown/markdown-storage.ts +318 -0
- package/core/memory/memories.ts +565 -0
- package/core/memory/memory-lifecycle.ts +51 -0
- package/core/memory/memory-manager.ts +53 -0
- package/core/memory/migrate.ts +173 -0
- package/core/memory/normalization.ts +30 -0
- package/core/memory/path-strengthener.ts +211 -0
- package/core/memory/progressive-disclosure.ts +392 -0
- package/core/memory/query-processor.ts +130 -0
- package/core/memory/query-rewriter.ts +153 -0
- package/core/memory/response-analyzer.ts +81 -0
- package/core/memory/retrieval-feedback.ts +276 -0
- package/core/memory/serialization.ts +83 -0
- package/core/memory/stale-cleaner.ts +147 -0
- package/core/memory/stats.ts +181 -0
- package/core/memory/telemetry.ts +392 -0
- package/core/memory/temporal-facts.ts +356 -0
- package/core/memory/temporal-parser.ts +477 -0
- package/core/memory/trigger-detector.ts +104 -0
- package/core/memory/write-gate.ts +288 -0
- package/core/places/index.ts +14 -0
- package/core/places/memory-places.ts +339 -0
- package/core/places/places.ts +406 -0
- package/core/places/rules.ts +308 -0
- package/core/places/walking.ts +192 -0
- package/core/projects +89 -0
- package/core/projects.ts +131 -0
- package/core/redis.ts +82 -0
- package/core/responses.ts +187 -0
- package/core/runtime/trust-report.ts +195 -0
- package/core/runtime/trust-state.ts +360 -0
- package/core/scheduler/cron-scheduler.ts +581 -0
- package/core/scheduler/heartbeat.ts +91 -0
- package/core/scheduler/index.ts +8 -0
- package/core/scheduler/job-runner.ts +197 -0
- package/core/search/conversations.ts +166 -0
- package/core/search/entities.ts +46 -0
- package/core/search/folder-context.ts +154 -0
- package/core/search/graph-boost.ts +22 -0
- package/core/search/index.ts +4 -0
- package/core/search/qmd-wrapper.ts +84 -0
- package/core/security/encrypt.ts +51 -0
- package/core/security/governance.ts +102 -0
- package/core/security/privacy.ts +108 -0
- package/core/security/secret-detector.ts +122 -0
- package/core/session/auto-load.ts +160 -0
- package/core/session/entity-tracker.ts +363 -0
- package/core/session/index.ts +7 -0
- package/core/session/reference-resolver.ts +158 -0
- package/core/session/self-iteration-job.ts +478 -0
- package/core/session/session-hooks.ts +69 -0
- package/core/session/types.ts +36 -0
- package/core/session/working-set.ts +275 -0
- package/core/snapshots/cleanup.ts +13 -0
- package/core/snapshots/comparison.ts +59 -0
- package/core/snapshots/creation.ts +139 -0
- package/core/snapshots/retrieval.ts +44 -0
- package/core/snapshots/stats.ts +63 -0
- package/core/storage/cache.ts +241 -0
- package/core/storage/database.ts +23 -0
- package/core/summarization/cleanup.ts +13 -0
- package/core/summarization/queries.ts +32 -0
- package/core/summarization/stats.ts +64 -0
- package/core/summarization/strategies.ts +52 -0
- package/core/summarization.ts +248 -0
- package/core/temporal-facts.ts +244 -0
- package/core/tracing/collector.ts +470 -0
- package/core/tracing/visualizer.ts +195 -0
- package/core/utils/cleanup-operations.ts +50 -0
- package/core/utils/content-extraction.ts +95 -0
- package/core/utils/filter-builder.ts +56 -0
- package/core/utils/history-traversal.ts +63 -0
- package/core/utils/memory-operations.ts +56 -0
- package/core/utils/query-operations.ts +83 -0
- package/core/utils/summarization-helpers.ts +45 -0
- package/core/utils/temporal-queries.ts +39 -0
- package/core/utils/vector-operations.ts +135 -0
- package/core/utils/version-management.ts +74 -0
- package/core/worker.ts +324 -0
- package/db/adapter.ts +215 -0
- package/db/bootstrap.ts +1055 -0
- package/db/drizzle/migrations/0000_needy_cerebro.sql +402 -0
- package/db/drizzle/migrations/meta/0000_snapshot.json +3451 -0
- package/db/drizzle/migrations/meta/_journal.json +13 -0
- package/db/drizzle/schema-sqlite.ts +1032 -0
- package/db/drizzle/schema.ts +1128 -0
- package/db/drizzle.config.ts +12 -0
- package/db/index.ts +83 -0
- package/db/init.sql +5 -0
- package/db/migrations/associations.ts +35 -0
- package/db/migrations/beliefs.ts +89 -0
- package/db/migrations/core-memory.ts +35 -0
- package/db/migrations/fts.ts +59 -0
- package/db/migrations/index.ts +54 -0
- package/db/migrations/indexes.ts +36 -0
- package/db/migrations/learnings.ts +34 -0
- package/db/migrations/maintenance.ts +68 -0
- package/db/migrations/memories.ts +22 -0
- package/db/migrations/memory-places.ts +35 -0
- package/db/migrations/places.ts +49 -0
- package/db/migrations/projects.ts +21 -0
- package/db/migrations/tier-conversion.ts +24 -0
- package/db/neon.ts +22 -0
- package/db/schema/beliefs.ts +50 -0
- package/db/schema/generator.ts +159 -0
- package/db/schema/index.ts +58 -0
- package/db/schema/learnings.ts +32 -0
- package/db/schema/memories.ts +83 -0
- package/db/schema/projects.ts +33 -0
- package/db/schema.ts +13 -0
- package/db/supabase.ts +27 -0
- package/dist/config.d.ts +40 -17
- package/dist/config.js +150 -198
- package/dist/core/adapters/types.d.ts +13 -33
- package/dist/core/adapters/types.js +1 -1
- package/dist/core/agent-preferences.d.ts +16 -0
- package/dist/core/agent-preferences.js +124 -0
- package/dist/core/algorithms/safety/safety-checks.d.ts +1 -5
- package/dist/core/algorithms/types.d.ts +0 -8
- package/dist/core/associations.d.ts +3 -1
- package/dist/core/associations.js +37 -1
- package/dist/core/beliefs/decay.d.ts +27 -0
- package/dist/core/beliefs/decay.js +217 -0
- package/dist/core/beliefs/extractor.d.ts +9 -0
- package/dist/core/beliefs/extractor.js +113 -0
- package/dist/core/beliefs/store.d.ts +46 -0
- package/dist/core/beliefs/store.js +466 -0
- package/dist/core/beliefs/types.d.ts +28 -0
- package/dist/core/beliefs/types.js +2 -0
- package/dist/core/commands/mcp-server.d.ts +0 -1
- package/dist/core/commands/mcp-server.js +4 -737
- package/dist/core/commands/remember.d.ts +24 -0
- package/dist/core/commands/remember.js +144 -0
- package/dist/core/{toon.d.ts → compression.d.ts} +6 -4
- package/dist/core/{toon.js → compression.js} +8 -8
- package/dist/core/context/agent-context.js +1 -1
- package/dist/core/embeddings/embeddings.d.ts +29 -0
- package/dist/core/embeddings/embeddings.js +546 -0
- package/dist/core/embeddings/google-multimodal.js +6 -2
- package/dist/core/{local-embeddings.d.ts → embeddings/local-embeddings.d.ts} +1 -1
- package/dist/core/embeddings/local-embeddings.js +11 -0
- package/dist/core/embeddings/qmd-client.js +1 -1
- package/dist/core/embeddings/transformers-local.d.ts +64 -0
- package/dist/core/embeddings/transformers-local.js +213 -0
- package/dist/core/embeddings.d.ts +1 -28
- package/dist/core/embeddings.js +2 -453
- package/dist/core/graph/entity-deduplicator.d.ts +24 -0
- package/dist/core/graph/entity-deduplicator.js +183 -0
- package/dist/core/graph/graph-builder.d.ts +46 -0
- package/dist/core/graph/graph-builder.js +174 -0
- package/dist/core/graph/graph-traversal.d.ts +80 -0
- package/dist/core/graph/graph-traversal.js +315 -0
- package/dist/core/graph/index.d.ts +19 -0
- package/dist/core/graph/index.js +13 -0
- package/dist/core/graph/llm-entity-extractor.d.ts +49 -0
- package/dist/core/graph/llm-entity-extractor.js +313 -0
- package/dist/core/graph/multi-hop-retrieval.d.ts +48 -0
- package/dist/core/graph/multi-hop-retrieval.js +215 -0
- package/dist/core/graph/relationship-extractor.d.ts +48 -0
- package/dist/core/graph/relationship-extractor.js +351 -0
- package/dist/core/hooks/agent-hooks.d.ts +10 -1
- package/dist/core/hooks/agent-hooks.js +301 -24
- package/dist/core/hot-cache.d.ts +86 -0
- package/dist/core/hot-cache.js +285 -0
- package/dist/core/index.d.ts +9 -9
- package/dist/core/index.js +9 -12
- package/dist/core/ingestion/core-memory.d.ts +2 -2
- package/dist/core/ingestion/core-memory.js +3 -3
- package/dist/core/ingestion/learnings.js +3 -0
- package/dist/core/ingestion/signal-engine.d.ts +41 -0
- package/dist/core/ingestion/signal-engine.js +201 -0
- package/dist/core/{obsidian-vault.d.ts → integrations/obsidian-vault.d.ts} +2 -1
- package/dist/core/{obsidian-vault.js → integrations/obsidian-vault.js} +69 -7
- package/dist/core/lib/parse-embedding.d.ts +9 -0
- package/dist/core/lib/parse-embedding.js +58 -0
- package/dist/core/lib/schemas.d.ts +57 -54
- package/dist/core/lib/types.d.ts +45 -0
- package/dist/core/lib/types.js +6 -0
- package/dist/core/lib/utils.d.ts +4 -0
- package/dist/core/lib/utils.js +55 -0
- package/dist/core/lifecycle.d.ts +0 -1
- package/dist/core/lifecycle.js +13 -23
- package/dist/core/logger.d.ts +1 -0
- package/dist/core/logger.js +14 -8
- package/dist/core/mcp/tools.d.ts +0 -2
- package/dist/core/mcp/tools.js +0 -87
- package/dist/core/mcp/types.d.ts +25 -253
- package/dist/core/mcp/types.js +2 -2
- package/dist/core/memory/categorizer.js +1 -0
- package/dist/core/memory/consolidation.js +2 -28
- package/dist/core/memory/entity-extractor.d.ts +4 -0
- package/dist/core/memory/entity-extractor.js +30 -16
- package/dist/core/memory/explain.d.ts +18 -0
- package/dist/core/memory/explain.js +92 -0
- package/dist/core/memory/fact-deriver.d.ts +31 -0
- package/dist/core/memory/fact-deriver.js +236 -0
- package/dist/core/memory/hybrid-retrieval.d.ts +14 -16
- package/dist/core/memory/hybrid-retrieval.js +25 -127
- package/dist/core/memory/hybrid-scorer.js +6 -23
- package/dist/core/memory/hybrid-search.d.ts +10 -7
- package/dist/core/memory/hybrid-search.js +458 -221
- package/dist/core/memory/importance.d.ts +0 -17
- package/dist/core/memory/importance.js +1 -58
- package/dist/core/memory/index.d.ts +1 -0
- package/dist/core/memory/index.js +1 -0
- package/dist/core/memory/memories.d.ts +13 -17
- package/dist/core/memory/memories.js +78 -75
- package/dist/core/memory/memory-lifecycle.d.ts +2 -2
- package/dist/core/memory/memory-lifecycle.js +10 -18
- package/dist/core/memory/normalization.d.ts +1 -16
- package/dist/core/memory/path-strengthener.d.ts +39 -0
- package/dist/core/memory/path-strengthener.js +150 -0
- package/dist/core/memory/query-processor.js +37 -3
- package/dist/core/memory/retrieval-feedback.d.ts +70 -0
- package/dist/core/memory/retrieval-feedback.js +213 -0
- package/dist/core/memory/stale-cleaner.d.ts +26 -0
- package/dist/core/memory/stale-cleaner.js +97 -0
- package/dist/core/memory/stats.d.ts +10 -0
- package/dist/core/memory/stats.js +8 -3
- package/dist/core/memory/trigger-detector.d.ts +8 -1
- package/dist/core/memory/trigger-detector.js +42 -5
- package/dist/core/places/index.d.ts +1 -1
- package/dist/core/places/index.js +1 -1
- package/dist/core/places/places.d.ts +13 -13
- package/dist/core/places/places.js +27 -27
- package/dist/core/places/rules.js +23 -23
- package/dist/core/places/walking.d.ts +3 -3
- package/dist/core/places/walking.js +7 -7
- package/dist/core/projects.js +8 -0
- package/dist/core/runtime/trust-report.d.ts +102 -0
- package/dist/core/runtime/trust-report.js +107 -0
- package/dist/core/runtime/trust-state.d.ts +12 -0
- package/dist/core/runtime/trust-state.js +309 -0
- package/dist/core/scheduler/cron-scheduler.d.ts +1 -1
- package/dist/core/scheduler/cron-scheduler.js +164 -3
- package/dist/core/scheduler/job-runner.js +1 -1
- package/dist/core/search/qmd-wrapper.d.ts +36 -0
- package/dist/core/search/qmd-wrapper.js +58 -0
- package/dist/core/session/auto-load.js +28 -3
- package/dist/core/session/entity-tracker.d.ts +62 -0
- package/dist/core/session/entity-tracker.js +287 -0
- package/dist/core/session/reference-resolver.d.ts +26 -0
- package/dist/core/session/reference-resolver.js +121 -0
- package/dist/core/session/self-iteration-job.d.ts +15 -0
- package/dist/core/session/self-iteration-job.js +163 -58
- package/dist/core/session/working-set.d.ts +50 -0
- package/dist/core/session/working-set.js +212 -0
- package/dist/core/snapshots/creation.d.ts +2 -8
- package/dist/core/snapshots/creation.js +3 -12
- package/dist/core/utils/summarization-helpers.d.ts +0 -4
- package/dist/core/utils/summarization-helpers.js +1 -6
- package/dist/db/bootstrap.d.ts +2 -0
- package/dist/db/bootstrap.js +229 -280
- package/dist/db/drizzle/schema-sqlite.d.ts +702 -1
- package/dist/db/drizzle/schema-sqlite.js +83 -4
- package/dist/db/drizzle/schema.d.ts +653 -1
- package/dist/db/drizzle/schema.js +93 -4
- package/dist/db/migrations/associations.d.ts +6 -0
- package/dist/db/migrations/associations.js +29 -0
- package/dist/db/migrations/beliefs.d.ts +10 -0
- package/dist/db/migrations/beliefs.js +76 -0
- package/dist/db/migrations/core-memory.d.ts +6 -0
- package/dist/db/migrations/core-memory.js +29 -0
- package/dist/db/migrations/fts.d.ts +6 -0
- package/dist/db/migrations/fts.js +52 -0
- package/dist/db/migrations/index.d.ts +25 -0
- package/dist/db/migrations/index.js +51 -0
- package/dist/db/migrations/indexes.d.ts +6 -0
- package/dist/db/migrations/indexes.js +30 -0
- package/dist/db/migrations/learnings.d.ts +7 -0
- package/dist/db/migrations/learnings.js +26 -0
- package/dist/db/migrations/maintenance.d.ts +6 -0
- package/dist/db/migrations/maintenance.js +61 -0
- package/dist/db/migrations/memories.d.ts +7 -0
- package/dist/db/migrations/memories.js +16 -0
- package/dist/db/migrations/memory-places.d.ts +6 -0
- package/dist/db/migrations/memory-places.js +29 -0
- package/dist/db/migrations/places.d.ts +6 -0
- package/dist/db/migrations/places.js +43 -0
- package/dist/db/migrations/projects.d.ts +3 -0
- package/dist/db/migrations/projects.js +13 -0
- package/dist/db/migrations/tier-conversion.d.ts +7 -0
- package/dist/db/migrations/tier-conversion.js +20 -0
- package/dist/db/schema/beliefs.d.ts +9 -0
- package/dist/db/schema/beliefs.js +46 -0
- package/dist/db/schema/generator.d.ts +38 -0
- package/dist/db/schema/generator.js +108 -0
- package/dist/db/schema/index.d.ts +19 -20
- package/dist/db/schema/index.js +25 -79
- package/dist/db/schema/learnings.d.ts +7 -0
- package/dist/db/schema/learnings.js +30 -0
- package/dist/db/schema/memories.d.ts +7 -0
- package/dist/db/schema/memories.js +81 -0
- package/dist/db/schema/projects.d.ts +4 -0
- package/dist/db/schema/projects.js +31 -0
- package/dist/packages/mcp/src/index.d.ts +3 -0
- package/dist/packages/mcp/src/index.js +733 -0
- package/mcp.json.example +8 -11
- package/package.json +57 -76
- package/packages/cli/package.json +22 -0
- package/packages/cli/src/commands/clean.ts +68 -0
- package/packages/cli/src/commands/context.ts +79 -0
- package/packages/cli/src/commands/doctor.ts +357 -0
- package/packages/cli/src/commands/forget.ts +72 -0
- package/packages/cli/src/commands/health.ts +36 -0
- package/packages/cli/src/commands/inspect.ts +41 -0
- package/packages/cli/src/commands/link.ts +50 -0
- package/packages/cli/src/commands/migrate.ts +93 -0
- package/packages/cli/src/commands/recall.ts +99 -0
- package/packages/cli/src/commands/recent.ts +57 -0
- package/packages/cli/src/commands/remember.ts +139 -0
- package/packages/cli/src/commands/run.ts +58 -0
- package/packages/cli/src/commands/stale.ts +43 -0
- package/packages/cli/src/commands/stats.ts +42 -0
- package/packages/cli/src/index.ts +57 -0
- package/packages/cli/tsconfig.json +24 -0
- package/packages/mcp/package.json +26 -0
- package/packages/mcp/src/index.ts +877 -0
- package/packages/mcp/tsconfig.json +20 -0
- package/skills/squish-memory/SKILL.md +38 -35
- package/skills/squish-memory/{scripts/install.sh → install.sh} +1 -1
- package/skills/squish-memory/references/claude-desktop.json +12 -0
- package/skills/squish-memory/references/openclaw.json +13 -0
- package/skills/squish-memory/references/opencode.json +14 -0
- package/config/hooks/claude-code-hooks.json +0 -39
- package/config/hooks/cursor-hooks.json +0 -30
- package/config/hooks/opencode-hooks.json +0 -30
- package/config/hooks/windsurf-hooks.json +0 -30
- package/config/mcp-cli-fallback-policy.json +0 -22
- package/config/mcp.json +0 -38
- package/config/plugin-manifest.json +0 -101
- package/config/plugin-manifest.schema.json +0 -244
- package/config/plugin.json +0 -32
- package/config/remote-memory-policy.json +0 -32
- package/core/commands/context-paging.md +0 -51
- package/core/commands/context-status.md +0 -22
- package/core/commands/context.md +0 -5
- package/core/commands/core-memory.md +0 -56
- package/core/commands/health.md +0 -5
- package/core/commands/init.md +0 -39
- package/core/commands/merge.md +0 -113
- package/core/commands/recall.md +0 -5
- package/core/commands/remember.md +0 -11
- package/core/commands/search.md +0 -10
- package/dist/core/commands/managed-sync.d.ts +0 -10
- package/dist/core/commands/managed-sync.js +0 -64
- package/dist/core/external-folder/index.d.ts +0 -102
- package/dist/core/external-folder/index.js +0 -294
- package/dist/core/namespaces/index.d.ts +0 -71
- package/dist/core/namespaces/index.js +0 -305
- package/dist/core/namespaces/uri-parser.d.ts +0 -31
- package/dist/core/namespaces/uri-parser.js +0 -74
- package/dist/core/search/qmd-search.d.ts +0 -61
- package/dist/core/search/qmd-search.js +0 -178
- package/dist/core/session-hooks/self-iteration-job.d.ts +0 -20
- package/dist/core/session-hooks/self-iteration-job.js +0 -282
- package/dist/core/session-hooks/session-hooks.d.ts +0 -18
- package/dist/core/session-hooks/session-hooks.js +0 -58
- package/dist/core/snapshots.d.ts +0 -29
- package/dist/core/snapshots.js +0 -220
- package/dist/core/sync/qmd-sync.d.ts +0 -94
- package/dist/core/sync/qmd-sync.js +0 -201
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -1677
- package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
- package/dist/webui/server.d.ts +0 -5
- package/dist/webui/server.js +0 -642
- package/generated/mcp/manifest.json +0 -23
- package/generated/mcp/mcp-servers.json +0 -25
- package/generated/mcp/mcporter.json +0 -34
- package/generated/mcp/openclaw-memory-qmd.json +0 -17
- package/generated/mcp/runtime.json +0 -12
- package/scripts/README.md +0 -60
- package/scripts/build-release.sh +0 -36
- package/scripts/check-secrets.js +0 -132
- package/scripts/copy-runtime-assets.mjs +0 -26
- package/scripts/generate-mcp.mjs +0 -264
- package/scripts/github-release.sh +0 -77
- package/scripts/init-dirs.mjs +0 -13
- package/scripts/install-claude-code.sh +0 -85
- package/scripts/install-cursor.sh +0 -56
- package/scripts/install-hooks.sh +0 -73
- package/scripts/install-interactive.mjs +0 -357
- package/scripts/install-opencode.sh +0 -75
- package/scripts/install-plugin.mjs +0 -415
- package/scripts/install-windsurf.sh +0 -67
- package/scripts/remote-preflight.mjs +0 -62
- package/scripts/squish-fallback.mjs +0 -132
- package/scripts/test-interactive.mjs +0 -131
- package/scripts/verify-mcp.mjs +0 -214
- package/skills/squish-memory/scripts/install.mjs +0 -335
- package/skills/squish-memory/write_skill.js +0 -2
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type BeliefType =
|
|
2
|
+
| 'decision'
|
|
3
|
+
| 'preference'
|
|
4
|
+
| 'failure_cause'
|
|
5
|
+
| 'constraint'
|
|
6
|
+
| 'state_change'
|
|
7
|
+
| 'dispute';
|
|
8
|
+
|
|
9
|
+
export type BeliefStatus = 'active' | 'superseded' | 'disputed';
|
|
10
|
+
|
|
11
|
+
export type BeliefEdgeType = 'causes' | 'supports' | 'rejects' | 'supersedes' | 'depends_on';
|
|
12
|
+
|
|
13
|
+
export interface ExtractedBelief {
|
|
14
|
+
type: BeliefType;
|
|
15
|
+
statement: string;
|
|
16
|
+
confidence: number;
|
|
17
|
+
sourceMemoryIds: string[];
|
|
18
|
+
status: BeliefStatus;
|
|
19
|
+
reason?: string;
|
|
20
|
+
context?: string;
|
|
21
|
+
evidenceSummary?: string;
|
|
22
|
+
edges?: Array<{
|
|
23
|
+
type: BeliefEdgeType;
|
|
24
|
+
targetStatement: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface StoredBelief extends ExtractedBelief {
|
|
29
|
+
id: string;
|
|
30
|
+
projectId: string;
|
|
31
|
+
normalizedKey: string;
|
|
32
|
+
createdAt?: Date | string | number | null;
|
|
33
|
+
updatedAt?: Date | string | number | null;
|
|
34
|
+
// Decay fields
|
|
35
|
+
lastConfirmedAt?: Date | string | number | null;
|
|
36
|
+
sourceCount?: number;
|
|
37
|
+
beliefDecayRate?: number;
|
|
38
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOON Compression - Token-efficient memory format
|
|
3
|
+
*
|
|
4
|
+
* Compact format for memory context using abbreviated notation.
|
|
5
|
+
* Achieves efficient token usage for context injection.
|
|
6
|
+
*
|
|
7
|
+
* Format:
|
|
8
|
+
* {
|
|
9
|
+
* m:[type], // memory type (1-2 chars)
|
|
10
|
+
* c:"...", // content (truncated)
|
|
11
|
+
* t:[], // tags (array)
|
|
12
|
+
* d:123 // days ago
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const MAX_CONTENT_LENGTH = 80; // Max chars per content
|
|
17
|
+
const MAX_TAGS = 3; // Max tags to include
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Compress a memory to TOON format
|
|
21
|
+
*/
|
|
22
|
+
export function compressForContext(content: string): string {
|
|
23
|
+
// If not JSON or already short, just return
|
|
24
|
+
if (!isJson(content) || content.length <= MAX_CONTENT_LENGTH) {
|
|
25
|
+
return content;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(content);
|
|
30
|
+
|
|
31
|
+
// Build compact TOON object
|
|
32
|
+
const toon: any = {
|
|
33
|
+
m: parsed.type?.substring(0, 2) || 'ob', // observation -> ob
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Truncate content
|
|
37
|
+
if (parsed.content) {
|
|
38
|
+
const truncated = parsed.content.substring(0, MAX_CONTENT_LENGTH);
|
|
39
|
+
toon.c = truncated.length < parsed.content.length ? truncated + '..' : truncated;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Add tags (limited)
|
|
43
|
+
if (parsed.tags && Array.isArray(parsed.tags)) {
|
|
44
|
+
toon.t = parsed.tags.slice(0, MAX_TAGS);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Add days ago if there's a date
|
|
48
|
+
if (parsed.createdAt) {
|
|
49
|
+
const days = Math.floor((Date.now() - new Date(parsed.createdAt).getTime()) / (1000 * 60 * 60 * 24));
|
|
50
|
+
if (days > 0) {
|
|
51
|
+
toon.d = days;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return JSON.stringify(toon);
|
|
56
|
+
} catch {
|
|
57
|
+
// Not parseable JSON, return truncated content
|
|
58
|
+
return content.substring(0, MAX_CONTENT_LENGTH);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Decompress TOON back to readable format
|
|
64
|
+
*/
|
|
65
|
+
export function decompressFromContext(toonString: string): string {
|
|
66
|
+
// Check if it's TOON format
|
|
67
|
+
if (!isCompressed(toonString)) {
|
|
68
|
+
return toonString;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(toonString);
|
|
73
|
+
|
|
74
|
+
// If it has TOON markers, expand it
|
|
75
|
+
if (parsed.m || parsed.c || parsed.t) {
|
|
76
|
+
const typeMap: Record<string, string> = {
|
|
77
|
+
ob: 'observation',
|
|
78
|
+
su: 'success',
|
|
79
|
+
f: 'failure',
|
|
80
|
+
fx: 'fix',
|
|
81
|
+
i: 'insight',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const type = typeMap[parsed.m] || 'observation';
|
|
85
|
+
const parts = [`[${type}]`];
|
|
86
|
+
|
|
87
|
+
if (parsed.c) {
|
|
88
|
+
parts.push(parsed.c);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (parsed.t && parsed.t.length > 0) {
|
|
92
|
+
parts.push(`#${parsed.t.join(' #')}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (parsed.d) {
|
|
96
|
+
parts.push(`(${parsed.d}d ago)`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return parts.join(' ');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return toonString;
|
|
103
|
+
} catch {
|
|
104
|
+
// Not valid TOON, return as-is
|
|
105
|
+
return toonString;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Estimate compression ratio
|
|
111
|
+
*/
|
|
112
|
+
export function estimateCompressionRatio(content: string): number {
|
|
113
|
+
if (!isJson(content) || content.length <= MAX_CONTENT_LENGTH) {
|
|
114
|
+
return 1.0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const compressed = compressForContext(content);
|
|
118
|
+
return compressed.length / content.length;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Check if content is JSON
|
|
123
|
+
*/
|
|
124
|
+
export function isJson(content: string): boolean {
|
|
125
|
+
try { JSON.parse(content); return true; } catch { return false; }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Check if content is compressed format
|
|
130
|
+
*/
|
|
131
|
+
export function isCompressed(content: string): boolean {
|
|
132
|
+
if (!content.startsWith('{') || !content.endsWith('}')) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(content);
|
|
138
|
+
// Has compressed markers
|
|
139
|
+
return parsed.m !== undefined || parsed.c !== undefined;
|
|
140
|
+
} catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Count tokens (rough estimate)
|
|
147
|
+
* Import from context-window.ts - single source of truth
|
|
148
|
+
*/
|
|
149
|
+
import { estimateTokens } from './context/context-window.js';
|
|
150
|
+
export { estimateTokens };
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Truncate to token budget
|
|
154
|
+
*/
|
|
155
|
+
export function truncateToTokenBudget(content: string, maxTokens: number): string {
|
|
156
|
+
const tokens = estimateTokens(content);
|
|
157
|
+
if (tokens <= maxTokens) {
|
|
158
|
+
return content;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Binary search for the right length
|
|
162
|
+
let low = 0;
|
|
163
|
+
let high = content.length;
|
|
164
|
+
|
|
165
|
+
while (low < high) {
|
|
166
|
+
const mid = Math.floor((low + high) / 2);
|
|
167
|
+
const estimated = estimateTokens(content.substring(0, mid));
|
|
168
|
+
|
|
169
|
+
if (estimated <= maxTokens) {
|
|
170
|
+
low = mid + 1;
|
|
171
|
+
} else {
|
|
172
|
+
high = mid;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return content.substring(0, low) + '...';
|
|
177
|
+
}
|
package/core/config.js
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// Memory Consolidation & Deduplication
|
|
2
|
+
import { eq, inArray, and, lt } from 'drizzle-orm';
|
|
3
|
+
import { getDb } from '../db/index.js';
|
|
4
|
+
import { getSchema } from '../db/schema.js';
|
|
5
|
+
import { config } from '../config.js';
|
|
6
|
+
import { createAssociation } from './associations.js';
|
|
7
|
+
import { logger } from './logger.js';
|
|
8
|
+
import { consolidateMemories, getConsolidationStats } from './memory/consolidation.js';
|
|
9
|
+
|
|
10
|
+
export interface ConsolidationStats {
|
|
11
|
+
clustered: number;
|
|
12
|
+
merged: number;
|
|
13
|
+
tokensRecovered: number;
|
|
14
|
+
deduped: number;
|
|
15
|
+
consolidated: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DeduplicationResult {
|
|
19
|
+
duplicatesFound: number;
|
|
20
|
+
mergedCount: number;
|
|
21
|
+
tokensRecovered: number;
|
|
22
|
+
groups: DuplicateGroup[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DuplicateGroup {
|
|
26
|
+
canonicalId: string;
|
|
27
|
+
duplicateIds: string[];
|
|
28
|
+
similarity: number;
|
|
29
|
+
reason: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Run automated deduplication job
|
|
34
|
+
* Finds and marks duplicates for review or auto-merges high-confidence duplicates
|
|
35
|
+
*/
|
|
36
|
+
export async function runDeduplicationJob(projectId?: string): Promise<DeduplicationResult> {
|
|
37
|
+
const result: DeduplicationResult = {
|
|
38
|
+
duplicatesFound: 0,
|
|
39
|
+
mergedCount: 0,
|
|
40
|
+
tokensRecovered: 0,
|
|
41
|
+
groups: [],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const db = await getDb();
|
|
46
|
+
const schema = await getSchema();
|
|
47
|
+
|
|
48
|
+
// Get active memories for deduplication check
|
|
49
|
+
const whereClause = projectId
|
|
50
|
+
? and(
|
|
51
|
+
eq(schema.memories.projectId, projectId),
|
|
52
|
+
eq(schema.memories.status, 'active')
|
|
53
|
+
)
|
|
54
|
+
: eq(schema.memories.status, 'active');
|
|
55
|
+
|
|
56
|
+
const memories = await (db as any)
|
|
57
|
+
.select()
|
|
58
|
+
.from(schema.memories)
|
|
59
|
+
.where(whereClause)
|
|
60
|
+
.limit(500);
|
|
61
|
+
|
|
62
|
+
if (memories.length < 2) {
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Find duplicate groups using SimHash
|
|
67
|
+
const duplicateGroups = await findDuplicatesBySimHash(memories);
|
|
68
|
+
|
|
69
|
+
result.duplicatesFound = duplicateGroups.reduce(
|
|
70
|
+
(sum, g) => sum + g.duplicateIds.length,
|
|
71
|
+
0
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Auto-merge high-confidence duplicates (>0.95 similarity)
|
|
75
|
+
for (const group of duplicateGroups) {
|
|
76
|
+
if (group.similarity >= 0.95) {
|
|
77
|
+
const tokensSaved = await autoMergeDuplicates(
|
|
78
|
+
group.canonicalId,
|
|
79
|
+
group.duplicateIds
|
|
80
|
+
);
|
|
81
|
+
result.mergedCount += group.duplicateIds.length;
|
|
82
|
+
result.tokensRecovered += tokensSaved;
|
|
83
|
+
} else {
|
|
84
|
+
// Lower confidence - just create association for review
|
|
85
|
+
for (const dupId of group.duplicateIds) {
|
|
86
|
+
await createAssociation(
|
|
87
|
+
group.canonicalId,
|
|
88
|
+
dupId,
|
|
89
|
+
'duplicate',
|
|
90
|
+
group.similarity
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
result.groups.push(group);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
logger.info('Deduplication job completed', {
|
|
98
|
+
duplicatesFound: result.duplicatesFound,
|
|
99
|
+
mergedCount: result.mergedCount,
|
|
100
|
+
tokensRecovered: result.tokensRecovered,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
} catch (error) {
|
|
104
|
+
logger.error('Deduplication job error', error);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Find duplicates using SimHash (efficient near-duplicate detection)
|
|
112
|
+
*/
|
|
113
|
+
async function findDuplicatesBySimHash(memories: any[]): Promise<DuplicateGroup[]> {
|
|
114
|
+
const groups: DuplicateGroup[] = [];
|
|
115
|
+
const processed = new Set<string>();
|
|
116
|
+
|
|
117
|
+
// Compute SimHash for each memory
|
|
118
|
+
const hashes = memories.map(m => ({
|
|
119
|
+
id: m.id,
|
|
120
|
+
hash: computeSimHash(m.content),
|
|
121
|
+
content: m.content,
|
|
122
|
+
createdAt: m.createdAt,
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
// Compare hashes to find similar content
|
|
126
|
+
for (let i = 0; i < hashes.length; i++) {
|
|
127
|
+
if (processed.has(hashes[i].id)) continue;
|
|
128
|
+
|
|
129
|
+
const duplicates: string[] = [];
|
|
130
|
+
let maxSimilarity = 0;
|
|
131
|
+
|
|
132
|
+
for (let j = i + 1; j < hashes.length; j++) {
|
|
133
|
+
if (processed.has(hashes[j].id)) continue;
|
|
134
|
+
|
|
135
|
+
const hammingDistance = computeHammingDistance(hashes[i].hash, hashes[j].hash);
|
|
136
|
+
const similarity = 1 - (hammingDistance / 64); // 64-bit hash
|
|
137
|
+
|
|
138
|
+
if (similarity >= 0.85) {
|
|
139
|
+
duplicates.push(hashes[j].id);
|
|
140
|
+
maxSimilarity = Math.max(maxSimilarity, similarity);
|
|
141
|
+
processed.add(hashes[j].id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (duplicates.length > 0) {
|
|
146
|
+
processed.add(hashes[i].id);
|
|
147
|
+
groups.push({
|
|
148
|
+
canonicalId: hashes[i].id, // Keep oldest as canonical
|
|
149
|
+
duplicateIds: duplicates,
|
|
150
|
+
similarity: maxSimilarity,
|
|
151
|
+
reason: 'content-similarity',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return groups;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Compute SimHash for text (64-bit fingerprint)
|
|
161
|
+
*/
|
|
162
|
+
function computeSimHash(text: string): bigint {
|
|
163
|
+
const tokens = text.toLowerCase().split(/\s+/).filter(t => t.length > 2);
|
|
164
|
+
const weights = new Array(64).fill(0);
|
|
165
|
+
|
|
166
|
+
for (const token of tokens) {
|
|
167
|
+
const hash = simpleHash(token);
|
|
168
|
+
for (let i = 0; i < 64; i++) {
|
|
169
|
+
if ((hash >> BigInt(i)) & 1n) {
|
|
170
|
+
weights[i] += 1;
|
|
171
|
+
} else {
|
|
172
|
+
weights[i] -= 1;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let simHash = 0n;
|
|
178
|
+
for (let i = 0; i < 64; i++) {
|
|
179
|
+
if (weights[i] > 0) {
|
|
180
|
+
simHash |= (1n << BigInt(i));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return simHash;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Simple hash function for strings
|
|
189
|
+
*/
|
|
190
|
+
function simpleHash(str: string): bigint {
|
|
191
|
+
let hash = 0n;
|
|
192
|
+
for (let i = 0; i < str.length; i++) {
|
|
193
|
+
const char = BigInt(str.charCodeAt(i));
|
|
194
|
+
hash = ((hash << 5n) - hash) + char;
|
|
195
|
+
hash = hash & hash; // Convert to 64bit integer
|
|
196
|
+
}
|
|
197
|
+
return hash;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Compute Hamming distance between two hashes
|
|
202
|
+
*/
|
|
203
|
+
function computeHammingDistance(a: bigint, b: bigint): number {
|
|
204
|
+
let xor = a ^ b;
|
|
205
|
+
let distance = 0;
|
|
206
|
+
while (xor !== 0n) {
|
|
207
|
+
distance += Number(xor & 1n);
|
|
208
|
+
xor >>= 1n;
|
|
209
|
+
}
|
|
210
|
+
return distance;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Auto-merge duplicates into canonical memory
|
|
215
|
+
*/
|
|
216
|
+
async function autoMergeDuplicates(
|
|
217
|
+
canonicalId: string,
|
|
218
|
+
duplicateIds: string[]
|
|
219
|
+
): Promise<number> {
|
|
220
|
+
try {
|
|
221
|
+
const db = await getDb();
|
|
222
|
+
const schema = await getSchema();
|
|
223
|
+
const now = new Date();
|
|
224
|
+
|
|
225
|
+
// Calculate tokens recovered
|
|
226
|
+
const duplicates = await (db as any)
|
|
227
|
+
.select()
|
|
228
|
+
.from(schema.memories)
|
|
229
|
+
.where(inArray(schema.memories.id, duplicateIds));
|
|
230
|
+
|
|
231
|
+
let tokensRecovered = 0;
|
|
232
|
+
for (const dup of duplicates) {
|
|
233
|
+
tokensRecovered += Math.ceil((dup.content?.length || 0) / 4);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Mark duplicates as merged
|
|
237
|
+
await (db as any)
|
|
238
|
+
.update(schema.memories)
|
|
239
|
+
.set({
|
|
240
|
+
status: 'merged',
|
|
241
|
+
mergedInto: canonicalId,
|
|
242
|
+
mergedAt: now,
|
|
243
|
+
updatedAt: now,
|
|
244
|
+
})
|
|
245
|
+
.where(inArray(schema.memories.id, duplicateIds));
|
|
246
|
+
|
|
247
|
+
// Create associations for traceability
|
|
248
|
+
for (const dupId of duplicateIds) {
|
|
249
|
+
await createAssociation(canonicalId, dupId, 'merged', 0.95);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return tokensRecovered;
|
|
253
|
+
|
|
254
|
+
} catch (error) {
|
|
255
|
+
logger.error('Error auto-merging duplicates', error);
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Run full consolidation job (dedup + memory consolidation)
|
|
262
|
+
*/
|
|
263
|
+
export async function runFullConsolidationJob(projectId?: string): Promise<ConsolidationStats> {
|
|
264
|
+
const stats: ConsolidationStats = {
|
|
265
|
+
clustered: 0,
|
|
266
|
+
merged: 0,
|
|
267
|
+
tokensRecovered: 0,
|
|
268
|
+
deduped: 0,
|
|
269
|
+
consolidated: 0,
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// Run deduplication first
|
|
273
|
+
const dedupResult = await runDeduplicationJob(projectId);
|
|
274
|
+
stats.deduped = dedupResult.duplicatesFound;
|
|
275
|
+
stats.merged = dedupResult.mergedCount;
|
|
276
|
+
stats.tokensRecovered += dedupResult.tokensRecovered;
|
|
277
|
+
|
|
278
|
+
// Run memory consolidation for each project
|
|
279
|
+
if (projectId) {
|
|
280
|
+
const consolidationResults = await consolidateMemories({
|
|
281
|
+
projectId,
|
|
282
|
+
minAge: 60,
|
|
283
|
+
maxImportance: 25,
|
|
284
|
+
minClusterSize: 3,
|
|
285
|
+
limit: 100,
|
|
286
|
+
});
|
|
287
|
+
stats.consolidated = consolidationResults.length;
|
|
288
|
+
stats.clustered = consolidationResults.reduce(
|
|
289
|
+
(sum, r) => sum + r.clusterSize,
|
|
290
|
+
0
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
logger.info('Full consolidation job completed', stats);
|
|
295
|
+
|
|
296
|
+
return stats;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Get deduplication statistics
|
|
301
|
+
*/
|
|
302
|
+
export async function getDeduplicationStats(projectId?: string): Promise<{
|
|
303
|
+
totalMemories: number;
|
|
304
|
+
mergedMemories: number;
|
|
305
|
+
pendingDuplicates: number;
|
|
306
|
+
}> {
|
|
307
|
+
try {
|
|
308
|
+
const db = await getDb();
|
|
309
|
+
const schema = await getSchema();
|
|
310
|
+
|
|
311
|
+
const whereClause = projectId
|
|
312
|
+
? eq(schema.memories.projectId, projectId)
|
|
313
|
+
: undefined;
|
|
314
|
+
|
|
315
|
+
const memories = await (db as any)
|
|
316
|
+
.select()
|
|
317
|
+
.from(schema.memories)
|
|
318
|
+
.where(whereClause);
|
|
319
|
+
|
|
320
|
+
return {
|
|
321
|
+
totalMemories: memories.length,
|
|
322
|
+
mergedMemories: memories.filter((m: any) => m.status === 'merged').length,
|
|
323
|
+
pendingDuplicates: 0, // Would need to query associations
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
} catch (error) {
|
|
327
|
+
logger.error('Error getting deduplication stats', error);
|
|
328
|
+
return { totalMemories: 0, mergedMemories: 0, pendingDuplicates: 0 };
|
|
329
|
+
}
|
|
330
|
+
}
|