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,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Paging Service - Agent-controlled memory loading
|
|
3
|
+
* Allows agents to load/evict memories from working set
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { eq, and, inArray } from 'drizzle-orm';
|
|
7
|
+
import { sql } from 'drizzle-orm';
|
|
8
|
+
import { getMemory } from '../memory/memories.js';
|
|
9
|
+
import { getDbClient } from '../lib/db-client.js';
|
|
10
|
+
|
|
11
|
+
interface LoadedMemory {
|
|
12
|
+
id: string;
|
|
13
|
+
type: string;
|
|
14
|
+
content: string;
|
|
15
|
+
contentPreview: string;
|
|
16
|
+
loadedAt: Date;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Initialize or get a context session
|
|
21
|
+
* Simplified - just tracks what's loaded, not tokens (Claude manages its own context)
|
|
22
|
+
*/
|
|
23
|
+
export async function initializeContextSession(
|
|
24
|
+
sessionId: string,
|
|
25
|
+
projectId: string,
|
|
26
|
+
userId?: string
|
|
27
|
+
): Promise<void> {
|
|
28
|
+
const { db, schema } = await getDbClient();
|
|
29
|
+
const { contextSessions } = schema;
|
|
30
|
+
|
|
31
|
+
// Check if session exists
|
|
32
|
+
const existing = await db
|
|
33
|
+
.select()
|
|
34
|
+
.from(contextSessions)
|
|
35
|
+
.where(eq(contextSessions.sessionId, sessionId))
|
|
36
|
+
.limit(1);
|
|
37
|
+
|
|
38
|
+
if (existing.length === 0) {
|
|
39
|
+
await db.insert(contextSessions).values({
|
|
40
|
+
sessionId,
|
|
41
|
+
projectId: projectId as any,
|
|
42
|
+
userId: userId || null,
|
|
43
|
+
loadedMemoryIds: JSON.stringify([]) as any,
|
|
44
|
+
tokenBudget: 8000,
|
|
45
|
+
tokensUsed: 0,
|
|
46
|
+
coreMemoryTokens: 0,
|
|
47
|
+
loadedMemoriesTokens: 0,
|
|
48
|
+
metadata: JSON.stringify({}) as any,
|
|
49
|
+
} as any);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Load a memory into working set
|
|
55
|
+
*/
|
|
56
|
+
export async function loadMemoryToContext(
|
|
57
|
+
sessionId: string,
|
|
58
|
+
memoryId: string
|
|
59
|
+
): Promise<{
|
|
60
|
+
success: boolean;
|
|
61
|
+
message?: string;
|
|
62
|
+
memory?: LoadedMemory;
|
|
63
|
+
}> {
|
|
64
|
+
const { db, schema } = await getDbClient();
|
|
65
|
+
const { contextSessions } = schema;
|
|
66
|
+
|
|
67
|
+
// Get session
|
|
68
|
+
const session = await db
|
|
69
|
+
.select()
|
|
70
|
+
.from(contextSessions)
|
|
71
|
+
.where(eq(contextSessions.sessionId, sessionId))
|
|
72
|
+
.limit(1);
|
|
73
|
+
|
|
74
|
+
if (session.length === 0) {
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
message: `Session "${sessionId}" not found. Initialize session first.`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const currentSession = session[0];
|
|
82
|
+
const loadedIds = (currentSession.loadedMemoryIds as string[]) || [];
|
|
83
|
+
|
|
84
|
+
// Check if already loaded
|
|
85
|
+
if (loadedIds.includes(memoryId)) {
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
message: `Memory "${memoryId}" is already in working set`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Get memory
|
|
93
|
+
const memory = await getMemory(memoryId);
|
|
94
|
+
if (!memory) {
|
|
95
|
+
return {
|
|
96
|
+
success: false,
|
|
97
|
+
message: `Memory "${memoryId}" not found`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Update session
|
|
102
|
+
const newLoadedIds = [...loadedIds, memoryId];
|
|
103
|
+
await db
|
|
104
|
+
.update(contextSessions)
|
|
105
|
+
.set({
|
|
106
|
+
loadedMemoryIds: newLoadedIds as any,
|
|
107
|
+
updatedAt: new Date() as any,
|
|
108
|
+
} as any)
|
|
109
|
+
.where(eq(contextSessions.sessionId, sessionId));
|
|
110
|
+
|
|
111
|
+
// Also update memory's contextStatus to 'in-context'
|
|
112
|
+
await db
|
|
113
|
+
.update(schema.memories as any)
|
|
114
|
+
.set({
|
|
115
|
+
contextStatus: 'in-context' as any,
|
|
116
|
+
})
|
|
117
|
+
.where(eq((schema.memories as any).id, memoryId));
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
memory: {
|
|
122
|
+
id: memory.id,
|
|
123
|
+
type: memory.type,
|
|
124
|
+
content: memory.content,
|
|
125
|
+
contentPreview: memory.content.substring(0, 200) + (memory.content.length > 200 ? '...' : ''),
|
|
126
|
+
loadedAt: new Date(),
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Evict a memory from working set
|
|
133
|
+
*/
|
|
134
|
+
export async function evictMemoryFromContext(
|
|
135
|
+
sessionId: string,
|
|
136
|
+
memoryId: string
|
|
137
|
+
): Promise<{
|
|
138
|
+
success: boolean;
|
|
139
|
+
message?: string;
|
|
140
|
+
}> {
|
|
141
|
+
const { db, schema } = await getDbClient();
|
|
142
|
+
const { contextSessions } = schema;
|
|
143
|
+
|
|
144
|
+
// Get session
|
|
145
|
+
const session = await db
|
|
146
|
+
.select()
|
|
147
|
+
.from(contextSessions)
|
|
148
|
+
.where(eq(contextSessions.sessionId, sessionId))
|
|
149
|
+
.limit(1);
|
|
150
|
+
|
|
151
|
+
if (session.length === 0) {
|
|
152
|
+
return {
|
|
153
|
+
success: false,
|
|
154
|
+
message: `Session "${sessionId}" not found`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const currentSession = session[0];
|
|
159
|
+
const loadedIds = (currentSession.loadedMemoryIds as string[]) || [];
|
|
160
|
+
|
|
161
|
+
// Check if loaded
|
|
162
|
+
if (!loadedIds.includes(memoryId)) {
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
message: `Memory "${memoryId}" is not in working set`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Update session
|
|
170
|
+
const newLoadedIds = loadedIds.filter((id) => id !== memoryId);
|
|
171
|
+
|
|
172
|
+
await db
|
|
173
|
+
.update(contextSessions)
|
|
174
|
+
.set({
|
|
175
|
+
loadedMemoryIds: newLoadedIds as any,
|
|
176
|
+
updatedAt: new Date() as any,
|
|
177
|
+
} as any)
|
|
178
|
+
.where(eq(contextSessions.sessionId, sessionId));
|
|
179
|
+
|
|
180
|
+
// Also update memory's contextStatus to 'out-of-context'
|
|
181
|
+
await db
|
|
182
|
+
.update(schema.memories as any)
|
|
183
|
+
.set({
|
|
184
|
+
contextStatus: 'out-of-context' as any,
|
|
185
|
+
})
|
|
186
|
+
.where(eq((schema.memories as any).id, memoryId));
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
success: true,
|
|
190
|
+
message: `Memory "${memoryId}" removed from working set`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* View all memories in working set
|
|
196
|
+
*/
|
|
197
|
+
export async function viewLoadedMemories(
|
|
198
|
+
sessionId: string
|
|
199
|
+
): Promise<{
|
|
200
|
+
success: boolean;
|
|
201
|
+
memories: LoadedMemory[];
|
|
202
|
+
count: number;
|
|
203
|
+
}> {
|
|
204
|
+
const { db, schema } = await getDbClient();
|
|
205
|
+
const { contextSessions } = schema;
|
|
206
|
+
|
|
207
|
+
// Get session
|
|
208
|
+
const session = await db
|
|
209
|
+
.select()
|
|
210
|
+
.from(contextSessions)
|
|
211
|
+
.where(eq(contextSessions.sessionId, sessionId))
|
|
212
|
+
.limit(1);
|
|
213
|
+
|
|
214
|
+
if (session.length === 0) {
|
|
215
|
+
return {
|
|
216
|
+
success: false,
|
|
217
|
+
memories: [],
|
|
218
|
+
count: 0,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const currentSession = session[0];
|
|
223
|
+
const loadedIds = (currentSession.loadedMemoryIds as string[]) || [];
|
|
224
|
+
|
|
225
|
+
if (loadedIds.length === 0) {
|
|
226
|
+
return {
|
|
227
|
+
success: true,
|
|
228
|
+
memories: [],
|
|
229
|
+
count: 0,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Get all loaded memories
|
|
234
|
+
const memories: LoadedMemory[] = [];
|
|
235
|
+
for (const id of loadedIds) {
|
|
236
|
+
const memory = await getMemory(id);
|
|
237
|
+
if (memory) {
|
|
238
|
+
memories.push({
|
|
239
|
+
id: memory.id,
|
|
240
|
+
type: memory.type,
|
|
241
|
+
content: memory.content,
|
|
242
|
+
contentPreview: memory.content.substring(0, 200) + (memory.content.length > 200 ? '...' : ''),
|
|
243
|
+
loadedAt: currentSession.updatedAt,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
success: true,
|
|
250
|
+
memories,
|
|
251
|
+
count: memories.length,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Get context status - what's in your working set and what's available
|
|
257
|
+
*/
|
|
258
|
+
export async function getContextStatus(
|
|
259
|
+
sessionId: string,
|
|
260
|
+
projectId: string
|
|
261
|
+
): Promise<{
|
|
262
|
+
success: boolean;
|
|
263
|
+
coreMemory: {
|
|
264
|
+
sizeBytes: number;
|
|
265
|
+
maxBytes: number;
|
|
266
|
+
usagePercent: number;
|
|
267
|
+
};
|
|
268
|
+
workingSet: {
|
|
269
|
+
loadedCount: number;
|
|
270
|
+
loadedMemories: Array<{
|
|
271
|
+
id: string;
|
|
272
|
+
type: string;
|
|
273
|
+
contentLength: number;
|
|
274
|
+
}>;
|
|
275
|
+
};
|
|
276
|
+
available: {
|
|
277
|
+
totalMemories: number;
|
|
278
|
+
totalObservations: number;
|
|
279
|
+
};
|
|
280
|
+
note: string;
|
|
281
|
+
}> {
|
|
282
|
+
const { db, schema } = await getDbClient();
|
|
283
|
+
const { contextSessions, memories, learnings } = schema;
|
|
284
|
+
|
|
285
|
+
// Get session
|
|
286
|
+
const session = await db
|
|
287
|
+
.select()
|
|
288
|
+
.from(contextSessions)
|
|
289
|
+
.where(eq(contextSessions.sessionId, sessionId))
|
|
290
|
+
.limit(1);
|
|
291
|
+
|
|
292
|
+
if (session.length === 0) {
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
coreMemory: { sizeBytes: 0, maxBytes: 2048, usagePercent: 0 },
|
|
296
|
+
workingSet: { loadedCount: 0, loadedMemories: [] },
|
|
297
|
+
available: { totalMemories: 0, totalObservations: 0 },
|
|
298
|
+
note: "Session not found. Initialize session first.",
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const currentSession = session[0];
|
|
303
|
+
|
|
304
|
+
// Get core memory stats
|
|
305
|
+
const { getCoreMemoryStats } = await import('../ingestion/core-memory.js');
|
|
306
|
+
const coreStats = await getCoreMemoryStats(projectId);
|
|
307
|
+
|
|
308
|
+
// Get loaded memories
|
|
309
|
+
const loadedIds = (currentSession.loadedMemoryIds as string[]) || [];
|
|
310
|
+
const loadedMemories = [];
|
|
311
|
+
for (const id of loadedIds) {
|
|
312
|
+
const memory = await getMemory(id);
|
|
313
|
+
if (memory) {
|
|
314
|
+
loadedMemories.push({
|
|
315
|
+
id: memory.id,
|
|
316
|
+
type: memory.type,
|
|
317
|
+
contentLength: memory.content.length,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Get external context stats (counts)
|
|
323
|
+
const totalMemories = await db
|
|
324
|
+
.select()
|
|
325
|
+
.from(memories)
|
|
326
|
+
.where(eq(memories.projectId, projectId as any));
|
|
327
|
+
|
|
328
|
+
const totalObservations = await db
|
|
329
|
+
.select()
|
|
330
|
+
.from(learnings)
|
|
331
|
+
.where(eq(learnings.projectId, projectId as any));
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
success: true,
|
|
335
|
+
coreMemory: {
|
|
336
|
+
sizeBytes: coreStats.totalBytes,
|
|
337
|
+
maxBytes: coreStats.maxBytes,
|
|
338
|
+
usagePercent: coreStats.usagePercent,
|
|
339
|
+
},
|
|
340
|
+
workingSet: {
|
|
341
|
+
loadedCount: loadedMemories.length,
|
|
342
|
+
loadedMemories,
|
|
343
|
+
},
|
|
344
|
+
available: {
|
|
345
|
+
totalMemories: totalMemories.length,
|
|
346
|
+
totalObservations: totalObservations.length,
|
|
347
|
+
},
|
|
348
|
+
note: "Claude manages its own context and token limits. This shows what memories you've loaded into your working set.",
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Clear all loaded memories from working set
|
|
354
|
+
*/
|
|
355
|
+
export async function clearLoadedMemories(sessionId: string): Promise<{
|
|
356
|
+
success: boolean;
|
|
357
|
+
message?: string;
|
|
358
|
+
}> {
|
|
359
|
+
const { db, schema } = await getDbClient();
|
|
360
|
+
const { contextSessions } = schema;
|
|
361
|
+
|
|
362
|
+
await db
|
|
363
|
+
.update(contextSessions)
|
|
364
|
+
.set({
|
|
365
|
+
loadedMemoryIds: [] as any,
|
|
366
|
+
updatedAt: new Date() as any,
|
|
367
|
+
} as any)
|
|
368
|
+
.where(eq(contextSessions.sessionId, sessionId));
|
|
369
|
+
|
|
370
|
+
return {
|
|
371
|
+
success: true,
|
|
372
|
+
message: 'All memories cleared from working set',
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Get all memories currently marked as in-context for a session
|
|
378
|
+
*/
|
|
379
|
+
export async function getInContextMemories(
|
|
380
|
+
sessionId: string
|
|
381
|
+
): Promise<LoadedMemory[]> {
|
|
382
|
+
const { db, schema } = await getDbClient();
|
|
383
|
+
const { contextSessions } = schema;
|
|
384
|
+
|
|
385
|
+
// Get session to find project
|
|
386
|
+
const session = await db
|
|
387
|
+
.select()
|
|
388
|
+
.from(contextSessions)
|
|
389
|
+
.where(eq(contextSessions.sessionId, sessionId))
|
|
390
|
+
.limit(1);
|
|
391
|
+
|
|
392
|
+
if (session.length === 0) {
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const { memories } = schema;
|
|
397
|
+
const projectId = session[0].projectId;
|
|
398
|
+
|
|
399
|
+
// Get all in-context memories
|
|
400
|
+
const inContextMemories = await db
|
|
401
|
+
.select()
|
|
402
|
+
.from(memories)
|
|
403
|
+
.where(
|
|
404
|
+
and(
|
|
405
|
+
eq(memories.projectId, projectId as any),
|
|
406
|
+
eq(memories.contextStatus, 'in-context' as any)
|
|
407
|
+
)
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
return inContextMemories.map((mem: any) => ({
|
|
411
|
+
id: mem.id,
|
|
412
|
+
type: mem.type,
|
|
413
|
+
content: mem.content,
|
|
414
|
+
contentPreview: mem.content.substring(0, 200) + (mem.content.length > 200 ? '...' : ''),
|
|
415
|
+
loadedAt: mem.updatedAt,
|
|
416
|
+
}));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Get out-of-context (archived) memories for a project
|
|
421
|
+
*/
|
|
422
|
+
export async function getOutOfContextMemories(
|
|
423
|
+
projectId: string,
|
|
424
|
+
limit: number = 10
|
|
425
|
+
): Promise<LoadedMemory[]> {
|
|
426
|
+
const { db, schema } = await getDbClient();
|
|
427
|
+
const { memories } = schema;
|
|
428
|
+
|
|
429
|
+
// Get out-of-context memories, ordered by last accessed
|
|
430
|
+
const outOfContextMemories = await db
|
|
431
|
+
.select()
|
|
432
|
+
.from(memories)
|
|
433
|
+
.where(
|
|
434
|
+
and(
|
|
435
|
+
eq(memories.projectId, projectId as any),
|
|
436
|
+
eq(memories.contextStatus, 'out-of-context' as any)
|
|
437
|
+
)
|
|
438
|
+
)
|
|
439
|
+
.orderBy(sql`COALESCE(${memories.lastAccessedAt}, ${memories.createdAt}) DESC`)
|
|
440
|
+
.limit(limit);
|
|
441
|
+
|
|
442
|
+
return outOfContextMemories.map((mem: any) => ({
|
|
443
|
+
id: mem.id,
|
|
444
|
+
type: mem.type,
|
|
445
|
+
content: mem.content,
|
|
446
|
+
contentPreview: mem.content.substring(0, 200) + (mem.content.length > 200 ? '...' : ''),
|
|
447
|
+
loadedAt: mem.lastAccessedAt || mem.createdAt,
|
|
448
|
+
}));
|
|
449
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { eq, and, sql } from 'drizzle-orm';
|
|
2
|
+
import { getDb } from '../../db/index.js';
|
|
3
|
+
import { getSchema } from '../../db/schema.js';
|
|
4
|
+
import { createDatabaseClient } from '../storage/database.js';
|
|
5
|
+
import { requireProject } from '../projects.js';
|
|
6
|
+
|
|
7
|
+
export interface ContextWindowConfig {
|
|
8
|
+
maxTokens: number;
|
|
9
|
+
warningThreshold: number;
|
|
10
|
+
criticalThreshold: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DEFAULT_CONTEXT_CONFIG: ContextWindowConfig = {
|
|
14
|
+
maxTokens: 128000,
|
|
15
|
+
warningThreshold: 0.80,
|
|
16
|
+
criticalThreshold: 0.95,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export interface TokenUsageStats {
|
|
20
|
+
coreMemoryTokens: number;
|
|
21
|
+
memoriesTokens: number;
|
|
22
|
+
totalTokens: number;
|
|
23
|
+
maxTokens: number;
|
|
24
|
+
usagePercent: number;
|
|
25
|
+
status: 'ok' | 'warning' | 'critical';
|
|
26
|
+
remainingTokens: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface OptimizationSuggestion {
|
|
30
|
+
type: 'drop' | 'summarize' | 'consolidate';
|
|
31
|
+
memoryId: string;
|
|
32
|
+
memoryType: string;
|
|
33
|
+
contentPreview: string;
|
|
34
|
+
tokens: number;
|
|
35
|
+
reason: string;
|
|
36
|
+
priority: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function estimateTokens(content: string): number {
|
|
40
|
+
if (!content) return 0;
|
|
41
|
+
return Math.ceil(content.length / 4);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function getTokenUsage(projectPath: string): Promise<TokenUsageStats> {
|
|
45
|
+
const project = await requireProject(projectPath);
|
|
46
|
+
const projectId = project.id;
|
|
47
|
+
const db = createDatabaseClient(await getDb());
|
|
48
|
+
const schema = await getSchema();
|
|
49
|
+
const memories = schema.memories; const coreMemory = schema.coreMemory;
|
|
50
|
+
|
|
51
|
+
const coreMemoryRows = await db
|
|
52
|
+
.select()
|
|
53
|
+
.from(coreMemory)
|
|
54
|
+
.where(eq(coreMemory.projectId, projectId as any));
|
|
55
|
+
|
|
56
|
+
let coreMemoryTokens = 0;
|
|
57
|
+
for (const row of coreMemoryRows) {
|
|
58
|
+
coreMemoryTokens += (row as any).tokensEstimate || estimateTokens((row as any).content || '');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const memoryRows = await db
|
|
62
|
+
.select({
|
|
63
|
+
tokens: (memories as any).tokensEstimate,
|
|
64
|
+
content: memories.content,
|
|
65
|
+
})
|
|
66
|
+
.from(memories)
|
|
67
|
+
.where(eq(memories.projectId, projectId as any));
|
|
68
|
+
|
|
69
|
+
let memoriesTokens = 0;
|
|
70
|
+
for (const row of memoryRows) {
|
|
71
|
+
memoriesTokens += (row as any).tokens || estimateTokens((row as any).content || '');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const totalTokens = coreMemoryTokens + memoriesTokens;
|
|
75
|
+
const config = DEFAULT_CONTEXT_CONFIG;
|
|
76
|
+
const usagePercent = (totalTokens / config.maxTokens) * 100;
|
|
77
|
+
const remainingTokens = Math.max(0, config.maxTokens - totalTokens);
|
|
78
|
+
|
|
79
|
+
let status: 'ok' | 'warning' | 'critical' = 'ok';
|
|
80
|
+
if (usagePercent >= config.criticalThreshold * 100) {
|
|
81
|
+
status = 'critical';
|
|
82
|
+
} else if (usagePercent >= config.warningThreshold * 100) {
|
|
83
|
+
status = 'warning';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
coreMemoryTokens,
|
|
88
|
+
memoriesTokens,
|
|
89
|
+
totalTokens,
|
|
90
|
+
maxTokens: config.maxTokens,
|
|
91
|
+
usagePercent,
|
|
92
|
+
status,
|
|
93
|
+
remainingTokens,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function checkContextLimit(
|
|
98
|
+
projectPath: string,
|
|
99
|
+
additionalTokens: number
|
|
100
|
+
): Promise<{ ok: boolean; warning?: string; stats: TokenUsageStats }> {
|
|
101
|
+
const stats = await getTokenUsage(projectPath);
|
|
102
|
+
const projectedTotal = stats.totalTokens + additionalTokens;
|
|
103
|
+
const projectedPercent = (projectedTotal / stats.maxTokens) * 100;
|
|
104
|
+
|
|
105
|
+
if (projectedPercent >= DEFAULT_CONTEXT_CONFIG.criticalThreshold * 100) {
|
|
106
|
+
return {
|
|
107
|
+
ok: false,
|
|
108
|
+
warning: `CRITICAL: Adding ${additionalTokens} tokens would exceed ${(DEFAULT_CONTEXT_CONFIG.criticalThreshold * 100).toFixed(0)}% of context limit (${projectedPercent.toFixed(1)}% projected). Consider optimizing first.`,
|
|
109
|
+
stats,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (projectedPercent >= DEFAULT_CONTEXT_CONFIG.warningThreshold * 100) {
|
|
114
|
+
return {
|
|
115
|
+
ok: true,
|
|
116
|
+
warning: `WARNING: Adding ${additionalTokens} tokens would reach ${(projectedPercent.toFixed(1))}% of context limit. Consider optimizing soon.`,
|
|
117
|
+
stats,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return { ok: true, stats };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function getOptimizationSuggestions(
|
|
125
|
+
projectPath: string
|
|
126
|
+
): Promise<OptimizationSuggestion[]> {
|
|
127
|
+
const project = await requireProject(projectPath);
|
|
128
|
+
const projectId = project.id;
|
|
129
|
+
const db = createDatabaseClient(await getDb());
|
|
130
|
+
const schema = await getSchema();
|
|
131
|
+
const memories = schema.memories;
|
|
132
|
+
|
|
133
|
+
const candidates = await db
|
|
134
|
+
.select({
|
|
135
|
+
id: memories.id,
|
|
136
|
+
type: memories.type,
|
|
137
|
+
content: memories.content,
|
|
138
|
+
tokens: (memories as any).tokensEstimate,
|
|
139
|
+
importanceScore: (memories as any).importanceScore,
|
|
140
|
+
accessCount: (memories as any).accessCount,
|
|
141
|
+
createdAt: memories.createdAt,
|
|
142
|
+
isPinned: (memories as any).isPinned,
|
|
143
|
+
isProtected: (memories as any).isProtected,
|
|
144
|
+
})
|
|
145
|
+
.from(memories)
|
|
146
|
+
.where(eq(memories.projectId, projectId as any))
|
|
147
|
+
.orderBy(sql`(importance_score * 0.4 + (100 - COALESCE(access_count, 0)) * 0.3 + (strftime('%s', 'now') - created_at / 1000) / 86400 * 0.3) ASC`)
|
|
148
|
+
.limit(20);
|
|
149
|
+
|
|
150
|
+
const suggestions: OptimizationSuggestion[] = [];
|
|
151
|
+
|
|
152
|
+
for (const mem of candidates) {
|
|
153
|
+
const tokens = (mem as any).tokens || estimateTokens((mem as any).content || '');
|
|
154
|
+
const contentPreview = (mem as any).content?.substring(0, 100) + '...';
|
|
155
|
+
const isPinned = (mem as any).isPinned === 1 || (mem as any).isPinned === true;
|
|
156
|
+
const isProtected = (mem as any).isProtected === 1 || (mem as any).isProtected === true;
|
|
157
|
+
const accessCount = (mem as any).accessCount || 0;
|
|
158
|
+
const importanceScore = (mem as any).importanceScore || 50;
|
|
159
|
+
|
|
160
|
+
if (isPinned || isProtected) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (importanceScore < 30 && accessCount < 3) {
|
|
165
|
+
suggestions.push({
|
|
166
|
+
type: 'drop',
|
|
167
|
+
memoryId: mem.id,
|
|
168
|
+
memoryType: mem.type,
|
|
169
|
+
contentPreview,
|
|
170
|
+
tokens,
|
|
171
|
+
reason: `Low importance (${importanceScore}) and rarely accessed (${accessCount} times)`,
|
|
172
|
+
priority: 1,
|
|
173
|
+
});
|
|
174
|
+
} else if (importanceScore < 50 && tokens > 500) {
|
|
175
|
+
suggestions.push({
|
|
176
|
+
type: 'summarize',
|
|
177
|
+
memoryId: mem.id,
|
|
178
|
+
memoryType: mem.type,
|
|
179
|
+
contentPreview,
|
|
180
|
+
tokens,
|
|
181
|
+
reason: `Large memory (${tokens} tokens) with moderate importance`,
|
|
182
|
+
priority: 2,
|
|
183
|
+
});
|
|
184
|
+
} else if (tokens > 1000) {
|
|
185
|
+
suggestions.push({
|
|
186
|
+
type: 'consolidate',
|
|
187
|
+
memoryId: mem.id,
|
|
188
|
+
memoryType: mem.type,
|
|
189
|
+
contentPreview,
|
|
190
|
+
tokens,
|
|
191
|
+
reason: `Very large memory (${tokens} tokens) - candidate for consolidation`,
|
|
192
|
+
priority: 3,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return suggestions.sort((a, b) => a.priority - b.priority).slice(0, 10);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export async function getContextWindowStatus(projectPath: string): Promise<{
|
|
201
|
+
config: ContextWindowConfig;
|
|
202
|
+
usage: TokenUsageStats;
|
|
203
|
+
suggestions: OptimizationSuggestion[];
|
|
204
|
+
memoryCount: number;
|
|
205
|
+
coreMemorySections: number;
|
|
206
|
+
}> {
|
|
207
|
+
const project = await requireProject(projectPath);
|
|
208
|
+
const projectId = project.id;
|
|
209
|
+
const db = createDatabaseClient(await getDb());
|
|
210
|
+
const schema = await getSchema();
|
|
211
|
+
|
|
212
|
+
const [usage, suggestions] = await Promise.all([
|
|
213
|
+
getTokenUsage(projectPath),
|
|
214
|
+
getOptimizationSuggestions(projectPath),
|
|
215
|
+
]);
|
|
216
|
+
|
|
217
|
+
const memoryCount = await db
|
|
218
|
+
.select({ count: sql`COUNT(*)` })
|
|
219
|
+
.from(schema.memories)
|
|
220
|
+
.where(eq(schema.memories.projectId, projectId as any));
|
|
221
|
+
|
|
222
|
+
const coreMemorySections = await db
|
|
223
|
+
.select({ count: sql`COUNT(*)` })
|
|
224
|
+
.from(schema.coreMemory)
|
|
225
|
+
.where(eq(schema.coreMemory.projectId, projectId as any));
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
config: DEFAULT_CONTEXT_CONFIG,
|
|
229
|
+
usage,
|
|
230
|
+
suggestions,
|
|
231
|
+
memoryCount: (memoryCount[0] as any)?.count || 0,
|
|
232
|
+
coreMemorySections: (coreMemorySections[0] as any)?.count || 0,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { requireProject } from '../projects.js';
|
|
2
|
+
import { getRecent } from '../memory/memories.js';
|
|
3
|
+
import { getObservations } from '../ingestion/learnings.js';
|
|
4
|
+
import { getEntitiesForProject } from '../search/entities.js';
|
|
5
|
+
import { validateLimit } from '../lib/validation.js';
|
|
6
|
+
|
|
7
|
+
export interface ContextInput {
|
|
8
|
+
project: string;
|
|
9
|
+
include?: Array<'memories' | 'observations' | 'entities'>;
|
|
10
|
+
limit?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function getProjectContext(input: ContextInput): Promise<Record<string, unknown>> {
|
|
14
|
+
const project = await requireProject(input.project);
|
|
15
|
+
const include = input.include ?? ['memories', 'observations'];
|
|
16
|
+
const limit = validateLimit(input.limit, 10, 1, 100);
|
|
17
|
+
|
|
18
|
+
const result: Record<string, unknown> = { project };
|
|
19
|
+
|
|
20
|
+
if (include.includes('memories')) {
|
|
21
|
+
result.memories = await getRecent(project.path, limit);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (include.includes('observations')) {
|
|
25
|
+
result.observations = await getObservations(project.path, limit);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (include.includes('entities')) {
|
|
29
|
+
result.entities = await getEntitiesForProject(project.path, limit);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|