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,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Lifecycle Hooks
|
|
3
|
+
*
|
|
4
|
+
* Provides event hooks for memory operations:
|
|
5
|
+
* - memoryCreated: When a memory is stored (DB or markdown files)
|
|
6
|
+
* - memoryUpdated: When a memory is updated
|
|
7
|
+
* - memoryDeleted: When a memory is deleted
|
|
8
|
+
* - tierChange: When memory tier changes (hot/warm/cold)
|
|
9
|
+
* - decayApplied: When decay score is updated
|
|
10
|
+
*
|
|
11
|
+
* Each hook can have sync and async handlers.
|
|
12
|
+
* Usage: Register handlers to auto-capture, sync to external systems, etc.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { logger } from '../logger.js';
|
|
16
|
+
|
|
17
|
+
export type HookEvent =
|
|
18
|
+
| 'memoryCreated'
|
|
19
|
+
| 'memoryUpdated'
|
|
20
|
+
| 'memoryDeleted'
|
|
21
|
+
| 'tierChange'
|
|
22
|
+
| 'decayApplied';
|
|
23
|
+
|
|
24
|
+
export interface MemoryHookContext {
|
|
25
|
+
memoryId: string;
|
|
26
|
+
content: string;
|
|
27
|
+
type: string;
|
|
28
|
+
tags: string[];
|
|
29
|
+
project?: string;
|
|
30
|
+
source?: string;
|
|
31
|
+
tier?: string;
|
|
32
|
+
importance?: number;
|
|
33
|
+
oldContent?: string; // For memoryUpdated events
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TierChangeContext extends MemoryHookContext {
|
|
37
|
+
oldTier: string;
|
|
38
|
+
newTier: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface DecayContext extends MemoryHookContext {
|
|
42
|
+
oldScore: number;
|
|
43
|
+
newScore: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type HookHandler<T = MemoryHookContext> = (context: T) => void | Promise<void>;
|
|
47
|
+
|
|
48
|
+
interface HookRegistration {
|
|
49
|
+
event: HookEvent;
|
|
50
|
+
handler: HookHandler;
|
|
51
|
+
priority: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Global hook registry
|
|
55
|
+
const hooks: HookRegistration[] = [];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Register a hook handler for a specific event
|
|
59
|
+
*/
|
|
60
|
+
export function registerHook(
|
|
61
|
+
event: HookEvent,
|
|
62
|
+
handler: HookHandler,
|
|
63
|
+
priority: number = 100
|
|
64
|
+
): void {
|
|
65
|
+
hooks.push({ event, handler, priority });
|
|
66
|
+
hooks.sort((a, b) => b.priority - a.priority);
|
|
67
|
+
logger.info('[Hooks] Registered handler for: ' + event + ' (priority: ' + priority + ')');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Unregister a hook handler
|
|
72
|
+
*/
|
|
73
|
+
export function unregisterHook(event: HookEvent, handler: HookHandler): void {
|
|
74
|
+
const idx = hooks.findIndex(h => h.event === event && h.handler === handler);
|
|
75
|
+
if (idx !== -1) {
|
|
76
|
+
hooks.splice(idx, 1);
|
|
77
|
+
logger.info('[Hooks] Unregistered handler for: ' + event);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Clear all hooks for an event
|
|
83
|
+
*/
|
|
84
|
+
export function clearHooks(event?: HookEvent): void {
|
|
85
|
+
if (event) {
|
|
86
|
+
const before = hooks.length;
|
|
87
|
+
const filtered = hooks.filter(h => h.event !== event);
|
|
88
|
+
hooks.length = 0;
|
|
89
|
+
hooks.push(...filtered);
|
|
90
|
+
logger.info('[Hooks] Cleared ' + (before - filtered.length) + ' hooks for: ' + event);
|
|
91
|
+
} else {
|
|
92
|
+
const count = hooks.length;
|
|
93
|
+
hooks.length = 0;
|
|
94
|
+
logger.info('[Hooks] Cleared all ' + count + ' hooks');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get registered hooks for an event
|
|
100
|
+
*/
|
|
101
|
+
export function getHooks(event: HookEvent): HookHandler[] {
|
|
102
|
+
return hooks.filter(h => h.event === event).map(h => h.handler);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* List all registered hooks (for debugging)
|
|
107
|
+
*/
|
|
108
|
+
export function listHooks(): { event: HookEvent; priority: number }[] {
|
|
109
|
+
return hooks.map(h => ({ event: h.event, priority: h.priority }));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// --- Trigger functions ---
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Trigger memoryCreated hooks
|
|
116
|
+
* Called when a memory is stored in DB or markdown files
|
|
117
|
+
*/
|
|
118
|
+
export async function triggerMemoryCreated(context: MemoryHookContext): Promise<void> {
|
|
119
|
+
const handlers = getHooks('memoryCreated');
|
|
120
|
+
|
|
121
|
+
for (const handler of handlers) {
|
|
122
|
+
try {
|
|
123
|
+
const result = handler(context);
|
|
124
|
+
if (result instanceof Promise) {
|
|
125
|
+
await result;
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
logger.error('[Hooks] Error in memoryCreated handler: ' + error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Trigger memoryUpdated hooks
|
|
135
|
+
* Called when a memory content/tags/etc changes
|
|
136
|
+
*/
|
|
137
|
+
export async function triggerMemoryUpdated(
|
|
138
|
+
context: MemoryHookContext,
|
|
139
|
+
oldContent?: string
|
|
140
|
+
): Promise<void> {
|
|
141
|
+
const handlers = getHooks('memoryUpdated');
|
|
142
|
+
|
|
143
|
+
for (const handler of handlers) {
|
|
144
|
+
try {
|
|
145
|
+
const result = handler({ ...context, oldContent: oldContent || '' });
|
|
146
|
+
if (result instanceof Promise) {
|
|
147
|
+
await result;
|
|
148
|
+
}
|
|
149
|
+
} catch (error) {
|
|
150
|
+
logger.error('[Hooks] Error in memoryUpdated handler: ' + error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Trigger memoryDeleted hooks
|
|
157
|
+
* Called when a memory is deleted
|
|
158
|
+
*/
|
|
159
|
+
export async function triggerMemoryDeleted(context: MemoryHookContext): Promise<void> {
|
|
160
|
+
const handlers = getHooks('memoryDeleted');
|
|
161
|
+
|
|
162
|
+
for (const handler of handlers) {
|
|
163
|
+
try {
|
|
164
|
+
const result = handler(context);
|
|
165
|
+
if (result instanceof Promise) {
|
|
166
|
+
await result;
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
logger.error('[Hooks] Error in memoryDeleted handler: ' + error);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Trigger tierChange hooks
|
|
176
|
+
* Called when memory tier changes
|
|
177
|
+
*/
|
|
178
|
+
export async function triggerTierChange(context: TierChangeContext): Promise<void> {
|
|
179
|
+
const handlers = getHooks('tierChange');
|
|
180
|
+
|
|
181
|
+
for (const handler of handlers) {
|
|
182
|
+
try {
|
|
183
|
+
const result = handler(context);
|
|
184
|
+
if (result instanceof Promise) {
|
|
185
|
+
await result;
|
|
186
|
+
}
|
|
187
|
+
} catch (error) {
|
|
188
|
+
logger.error('[Hooks] Error in tierChange handler: ' + error);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Trigger decayApplied hooks
|
|
195
|
+
* Called when memory decay score changes
|
|
196
|
+
*/
|
|
197
|
+
export async function triggerDecayApplied(context: DecayContext): Promise<void> {
|
|
198
|
+
const handlers = getHooks('decayApplied');
|
|
199
|
+
|
|
200
|
+
for (const handler of handlers) {
|
|
201
|
+
try {
|
|
202
|
+
const result = handler(context);
|
|
203
|
+
if (result instanceof Promise) {
|
|
204
|
+
await result;
|
|
205
|
+
}
|
|
206
|
+
} catch (error) {
|
|
207
|
+
logger.error('[Hooks] Error in decayApplied handler: ' + error);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Built-in hook: Auto-save to memory files when storing to DB
|
|
214
|
+
* Use this to have dual storage (DB + markdown files)
|
|
215
|
+
*/
|
|
216
|
+
export function createMarkdownAutoSyncHook() {
|
|
217
|
+
return async function markdownAutoSync(context: MemoryHookContext) {
|
|
218
|
+
if (context.tier === 'hot') {
|
|
219
|
+
const { saveToMarkdown } = await import('./markdown/markdown-storage.js');
|
|
220
|
+
await saveToMarkdown({
|
|
221
|
+
content: context.content,
|
|
222
|
+
type: context.type as any,
|
|
223
|
+
tags: context.tags,
|
|
224
|
+
project: context.project,
|
|
225
|
+
source: context.source,
|
|
226
|
+
});
|
|
227
|
+
logger.info('[Hooks] Auto-synced memory to markdown: ' + context.memoryId);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { MemoryRecord } from '../lib/types.js';
|
|
2
|
+
import { hybridSearch as currentHybridSearch } from './hybrid-search.js';
|
|
3
|
+
import type { SearchInput } from './memories.js';
|
|
4
|
+
|
|
5
|
+
export interface HybridSearchOptions extends SearchInput {
|
|
6
|
+
candidateLimit?: number;
|
|
7
|
+
resultLimit?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface HybridSearchResult extends MemoryRecord {
|
|
11
|
+
hybridScore: number;
|
|
12
|
+
semanticScore: number;
|
|
13
|
+
recencyScore: number;
|
|
14
|
+
importanceScore: number;
|
|
15
|
+
coactivationScore: number;
|
|
16
|
+
rank: number;
|
|
17
|
+
explanation: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type ScoredItem = {
|
|
21
|
+
memoryId: string;
|
|
22
|
+
memory: Record<string, unknown>;
|
|
23
|
+
totalScore: number;
|
|
24
|
+
components: Record<string, number>;
|
|
25
|
+
rank: number;
|
|
26
|
+
explanation: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function applyEntityBoostAndRerank<T extends ScoredItem>(scored: T[]): T[] {
|
|
30
|
+
return scored
|
|
31
|
+
.map((item) => {
|
|
32
|
+
const rawBoost = item.memory._entityBoost;
|
|
33
|
+
const entityBoost = typeof rawBoost === 'number' ? rawBoost : 0;
|
|
34
|
+
return {
|
|
35
|
+
...item,
|
|
36
|
+
totalScore: item.totalScore + entityBoost * 20,
|
|
37
|
+
};
|
|
38
|
+
})
|
|
39
|
+
.sort((a, b) => b.totalScore - a.totalScore)
|
|
40
|
+
.map((item, index) => ({
|
|
41
|
+
...item,
|
|
42
|
+
rank: index + 1,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function hybridSearch(options: HybridSearchOptions): Promise<HybridSearchResult[]> {
|
|
47
|
+
const limit = options.resultLimit ?? options.limit ?? 5;
|
|
48
|
+
const results = await currentHybridSearch(options, {
|
|
49
|
+
limit,
|
|
50
|
+
project: options.project,
|
|
51
|
+
type: options.type,
|
|
52
|
+
tags: options.tags,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return results.map((result, index) => ({
|
|
56
|
+
...result,
|
|
57
|
+
hybridScore: result.similarity ?? 0,
|
|
58
|
+
semanticScore: result.similarity ?? 0,
|
|
59
|
+
recencyScore: 0,
|
|
60
|
+
importanceScore: typeof result.importance === 'number' ? result.importance : 0,
|
|
61
|
+
coactivationScore: 0,
|
|
62
|
+
rank: index + 1,
|
|
63
|
+
explanation: 'Compatibility result from current hybrid search',
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/** Hybrid Scorer - Multi-factor relevance scoring for memory ranking */
|
|
2
|
+
|
|
3
|
+
import { logger } from '../../core/logger.js';
|
|
4
|
+
import { cosineSimilarity } from '../utils/vector-operations.js';
|
|
5
|
+
|
|
6
|
+
export interface ScoredMemory {
|
|
7
|
+
memoryId: string;
|
|
8
|
+
memory: any;
|
|
9
|
+
totalScore: number;
|
|
10
|
+
components: {
|
|
11
|
+
semantic: number;
|
|
12
|
+
recency: number;
|
|
13
|
+
coactivation: number;
|
|
14
|
+
importance: number;
|
|
15
|
+
confidence: number;
|
|
16
|
+
feedback: number;
|
|
17
|
+
};
|
|
18
|
+
rank: number;
|
|
19
|
+
explanation: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface HybridScorerOptions {
|
|
23
|
+
weights?: {
|
|
24
|
+
semantic?: number;
|
|
25
|
+
recency?: number;
|
|
26
|
+
coactivation?: number;
|
|
27
|
+
importance?: number;
|
|
28
|
+
confidence?: number;
|
|
29
|
+
feedback?: number;
|
|
30
|
+
};
|
|
31
|
+
decayDays?: number;
|
|
32
|
+
minSemanticScore?: number;
|
|
33
|
+
includeExplanation?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function hybridScore(
|
|
37
|
+
queryEmbedding: number[] | null,
|
|
38
|
+
memories: any[],
|
|
39
|
+
options: HybridScorerOptions = {}
|
|
40
|
+
): Promise<ScoredMemory[]> {
|
|
41
|
+
const weights = {
|
|
42
|
+
semantic: options.weights?.semantic ?? 0.30,
|
|
43
|
+
recency: options.weights?.recency ?? 0.20,
|
|
44
|
+
coactivation: options.weights?.coactivation ?? 0.10,
|
|
45
|
+
importance: options.weights?.importance ?? 0.15,
|
|
46
|
+
confidence: options.weights?.confidence ?? 0.15,
|
|
47
|
+
feedback: options.weights?.feedback ?? 0.10,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const decayDays = options.decayDays ?? 30;
|
|
51
|
+
const minSemanticScore = options.minSemanticScore ?? 0.0;
|
|
52
|
+
|
|
53
|
+
const scored: ScoredMemory[] = [];
|
|
54
|
+
const now = new Date();
|
|
55
|
+
|
|
56
|
+
for (const memory of memories) {
|
|
57
|
+
if (queryEmbedding && weights.semantic > 0) {
|
|
58
|
+
const semanticScore = calculateSemanticScore(queryEmbedding, memory);
|
|
59
|
+
if (semanticScore < minSemanticScore) continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const components = {
|
|
63
|
+
semantic: queryEmbedding ? calculateSemanticScore(queryEmbedding, memory) : 50,
|
|
64
|
+
recency: calculateRecencyScore(memory, now, decayDays),
|
|
65
|
+
coactivation: calculateCoactivationScore(memory),
|
|
66
|
+
importance: calculateImportanceScore(memory),
|
|
67
|
+
confidence: calculateConfidenceScore(memory),
|
|
68
|
+
feedback: calculateFeedbackScore(memory),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const totalScore = Math.min(
|
|
72
|
+
100,
|
|
73
|
+
components.semantic * weights.semantic +
|
|
74
|
+
components.recency * weights.recency +
|
|
75
|
+
components.coactivation * weights.coactivation +
|
|
76
|
+
components.importance * weights.importance +
|
|
77
|
+
components.confidence * weights.confidence +
|
|
78
|
+
components.feedback * weights.feedback
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
scored.push({
|
|
82
|
+
memoryId: memory.id,
|
|
83
|
+
memory,
|
|
84
|
+
totalScore: Math.round(totalScore * 100) / 100,
|
|
85
|
+
components: {
|
|
86
|
+
semantic: Math.round(components.semantic * 100) / 100,
|
|
87
|
+
recency: Math.round(components.recency * 100) / 100,
|
|
88
|
+
coactivation: Math.round(components.coactivation * 100) / 100,
|
|
89
|
+
importance: Math.round(components.importance * 100) / 100,
|
|
90
|
+
confidence: Math.round(components.confidence * 100) / 100,
|
|
91
|
+
feedback: Math.round(components.feedback * 100) / 100,
|
|
92
|
+
},
|
|
93
|
+
rank: 0,
|
|
94
|
+
explanation: options.includeExplanation
|
|
95
|
+
? generateScoreExplanation(components, weights, memory)
|
|
96
|
+
: '',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
scored.sort((a, b) => b.totalScore - a.totalScore);
|
|
101
|
+
for (let i = 0; i < scored.length; i++) {
|
|
102
|
+
scored[i].rank = i + 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return scored;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function calculateSemanticScore(queryEmbedding: number[], memory: any): number {
|
|
109
|
+
if (!memory.embedding || queryEmbedding.length === 0) return 50;
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
let memoryEmbedding: number[] | null = null;
|
|
113
|
+
|
|
114
|
+
if (Array.isArray(memory.embedding)) {
|
|
115
|
+
memoryEmbedding = memory.embedding;
|
|
116
|
+
} else if (typeof memory.embedding === 'string') {
|
|
117
|
+
memoryEmbedding = JSON.parse(memory.embedding);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!memoryEmbedding || memoryEmbedding.length === 0) return 50;
|
|
121
|
+
|
|
122
|
+
const semanticScore = cosineSimilarity(queryEmbedding, memoryEmbedding);
|
|
123
|
+
return Math.max(0, Math.min(100, (semanticScore + 1) * 50));
|
|
124
|
+
} catch (error) {
|
|
125
|
+
logger.error('Error calculating semantic score', error);
|
|
126
|
+
return 50;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function calculateRecencyScore(memory: any, now: Date, decayDays: number): number {
|
|
131
|
+
// Enhanced bi-temporal recency scoring: considers validity period and learning time
|
|
132
|
+
const validFromDate = memory.validFrom ? new Date(memory.validFrom) : null;
|
|
133
|
+
const validToDate = memory.validTo ? new Date(memory.validTo) : null;
|
|
134
|
+
const recordedAtDate = memory.recordedAt ? new Date(memory.recordedAt) : null;
|
|
135
|
+
const createdDate = memory.createdAt ? new Date(memory.createdAt) : null;
|
|
136
|
+
|
|
137
|
+
// Calculate score based on how relevant the memory is right now
|
|
138
|
+
let score = 50; // Default neutral score
|
|
139
|
+
|
|
140
|
+
// If we have a validity period, score based on current time's position within that period
|
|
141
|
+
if (validFromDate && validToDate) {
|
|
142
|
+
const timeInPeriod = now.getTime() - validFromDate.getTime();
|
|
143
|
+
const periodLength = validToDate.getTime() - validFromDate.getTime();
|
|
144
|
+
|
|
145
|
+
if (periodLength > 0) {
|
|
146
|
+
// If now is within the validity period, high score
|
|
147
|
+
if (now >= validFromDate && now <= validToDate) {
|
|
148
|
+
// Full score if right in middle, decreasing toward edges
|
|
149
|
+
const progress = timeInPeriod / periodLength;
|
|
150
|
+
const distanceFromCenter = Math.abs(0.5 - progress) * 2; // 0 at center, 1 at edges
|
|
151
|
+
score = 100 * (1 - distanceFromCenter * 0.8); // 100 at center, 40 at edges
|
|
152
|
+
} else {
|
|
153
|
+
// Outside validity period - score based on how recently it expired or how far in future
|
|
154
|
+
if (now < validFromDate) {
|
|
155
|
+
// Future validity - score based on how soon it becomes valid
|
|
156
|
+
const daysUntilValid = (validFromDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000);
|
|
157
|
+
score = Math.max(20, 100 - Math.min(80, daysUntilValid / decayDays * 100));
|
|
158
|
+
} else {
|
|
159
|
+
// Past validity - score based on how recently it expired
|
|
160
|
+
const daysSinceExpired = (now.getTime() - validToDate.getTime()) / (24 * 60 * 60 * 1000);
|
|
161
|
+
score = Math.max(10, 60 - Math.min(50, daysSinceExpired / decayDays * 100));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// If we only have validFrom (open-ended validity)
|
|
167
|
+
else if (validFromDate) {
|
|
168
|
+
const daysSinceValid = (now.getTime() - validFromDate.getTime()) / (24 * 60 * 60 * 1000);
|
|
169
|
+
if (now >= validFromDate) {
|
|
170
|
+
// Still valid - decay from full score over time
|
|
171
|
+
score = Math.max(30, 100 - Math.min(70, daysSinceValid / decayDays * 100));
|
|
172
|
+
} else {
|
|
173
|
+
// Becomes valid in future
|
|
174
|
+
const daysUntilValid = (validFromDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000);
|
|
175
|
+
score = Math.max(20, 100 - Math.min(80, daysUntilValid / decayDays * 100));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Fallback to learned/recorded time
|
|
179
|
+
else {
|
|
180
|
+
const learnedDate = recordedAtDate || createdDate;
|
|
181
|
+
if (learnedDate) {
|
|
182
|
+
const daysSinceLearned = (now.getTime() - learnedDate.getTime()) / (24 * 60 * 60 * 1000);
|
|
183
|
+
score = 100 * Math.pow(0.5, daysSinceLearned / decayDays);
|
|
184
|
+
score = Math.max(0, Math.min(100, score));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return Math.round(score * 10) / 10; // Return one decimal place
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function calculateCoactivationScore(memory: any): number {
|
|
192
|
+
if (!memory.coactivationScore || memory.coactivationScore === 0) return 10;
|
|
193
|
+
return Math.min(100, memory.coactivationScore * 5);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function calculateImportanceScore(memory: any): number {
|
|
197
|
+
let score = 50;
|
|
198
|
+
|
|
199
|
+
// Simplified: hot or cold only (warm removed)
|
|
200
|
+
if (memory.tier === 'hot') score += 30;
|
|
201
|
+
// No bonus for cold - it's the fallback
|
|
202
|
+
|
|
203
|
+
if (memory.relevanceScore) score += memory.relevanceScore * 0.2;
|
|
204
|
+
if (memory.isPinned) score += 10;
|
|
205
|
+
if (memory.isProtected) score += 10;
|
|
206
|
+
if (memory.isMergeable || memory.isMerged) score -= 10;
|
|
207
|
+
|
|
208
|
+
return Math.max(0, Math.min(100, score));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function calculateConfidenceScore(memory: any): number {
|
|
212
|
+
let score = 50;
|
|
213
|
+
|
|
214
|
+
const signals = memory.metadata?.memorySignals;
|
|
215
|
+
|
|
216
|
+
if (signals) {
|
|
217
|
+
if (signals.priority === 'high') score += 25;
|
|
218
|
+
|
|
219
|
+
if (signals.explicitTriggers && signals.explicitTriggers.length > 0) {
|
|
220
|
+
score += 15 * Math.min(signals.explicitTriggers.length, 2);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (signals.implicit) {
|
|
224
|
+
if (signals.implicit.decision) score += 10;
|
|
225
|
+
if (signals.implicit.correction) score += 15;
|
|
226
|
+
if (signals.implicit.preference) score += 8;
|
|
227
|
+
if (signals.implicit.workflowRule) score += 12;
|
|
228
|
+
if (signals.implicit.lesson) score += 10;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (signals.requiresConflictCheck) score -= 5;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
switch (memory.type) {
|
|
235
|
+
case 'decision': score += 10; break;
|
|
236
|
+
case 'preference': score += 5; break;
|
|
237
|
+
case 'fact': score += 8; break;
|
|
238
|
+
case 'context': score += 3; break;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (memory.source === 'mcp') score += 5;
|
|
242
|
+
|
|
243
|
+
if (memory.accessCount && memory.accessCount > 5) {
|
|
244
|
+
score += Math.min(10, memory.accessCount / 2);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return Math.max(0, Math.min(100, score));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function calculateFeedbackScore(memory: any): number {
|
|
251
|
+
const retrievalPriority = memory.retrievalPriority ?? 50;
|
|
252
|
+
return Math.max(0, Math.min(100, retrievalPriority));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function generateScoreExplanation(
|
|
256
|
+
components: ScoredMemory['components'],
|
|
257
|
+
weights: ScoredMemory['components'],
|
|
258
|
+
memory: any
|
|
259
|
+
): string {
|
|
260
|
+
const parts: string[] = [];
|
|
261
|
+
|
|
262
|
+
if (components.semantic > 70) parts.push(`highly relevant (${components.semantic.toFixed(0)})`);
|
|
263
|
+
else if (components.semantic > 50) parts.push(`somewhat relevant (${components.semantic.toFixed(0)})`);
|
|
264
|
+
else parts.push(`low relevance (${components.semantic.toFixed(0)})`);
|
|
265
|
+
|
|
266
|
+
if (components.recency > 70) parts.push('recent');
|
|
267
|
+
else if (components.recency > 30) parts.push('moderately recent');
|
|
268
|
+
else parts.push('older');
|
|
269
|
+
|
|
270
|
+
// Simplified: hot or cold only (warm removed)
|
|
271
|
+
if (memory.tier === 'hot') parts.push('active memory');
|
|
272
|
+
else parts.push('archived memory');
|
|
273
|
+
|
|
274
|
+
if (components.coactivation > 60) parts.push('frequently associated');
|
|
275
|
+
|
|
276
|
+
if (components.confidence > 80) parts.push('high confidence');
|
|
277
|
+
else if (components.confidence > 60) parts.push('moderate confidence');
|
|
278
|
+
else if (components.confidence < 40) parts.push('low confidence');
|
|
279
|
+
|
|
280
|
+
if (components.feedback > 70) parts.push('frequently useful');
|
|
281
|
+
else if (components.feedback < 30) parts.push('rarely used');
|
|
282
|
+
|
|
283
|
+
return parts.join(', ');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export async function scoreAndRankMemories(
|
|
287
|
+
queryEmbedding: number[] | null,
|
|
288
|
+
memories: any[],
|
|
289
|
+
topK: number = 10,
|
|
290
|
+
options: HybridScorerOptions = {}
|
|
291
|
+
): Promise<ScoredMemory[]> {
|
|
292
|
+
const scored = await hybridScore(queryEmbedding, memories, options);
|
|
293
|
+
|
|
294
|
+
logger.debug('Scored and ranked memories', {
|
|
295
|
+
total: scored.length,
|
|
296
|
+
topK,
|
|
297
|
+
topScores: scored.slice(0, topK).map((s) => ({ id: s.memoryId, score: s.totalScore })),
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return scored.slice(0, topK);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function getScoreDistribution(scored: ScoredMemory[]): {
|
|
304
|
+
min: number;
|
|
305
|
+
max: number;
|
|
306
|
+
avg: number;
|
|
307
|
+
median: number;
|
|
308
|
+
p95: number;
|
|
309
|
+
p99: number;
|
|
310
|
+
} {
|
|
311
|
+
if (scored.length === 0) {
|
|
312
|
+
return { min: 0, max: 0, avg: 0, median: 0, p95: 0, p99: 0 };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const scores = scored.map((s) => s.totalScore).sort((a, b) => a - b);
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
min: scores[0],
|
|
319
|
+
max: scores[scores.length - 1],
|
|
320
|
+
avg: scores.reduce((a, b) => a + b, 0) / scores.length,
|
|
321
|
+
median: scores[Math.floor(scores.length / 2)],
|
|
322
|
+
p95: scores[Math.floor((95 / 100) * scores.length)],
|
|
323
|
+
p99: scores[Math.floor((99 / 100) * scores.length)],
|
|
324
|
+
};
|
|
325
|
+
}
|