squish-memory 0.7.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/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +32 -0
- package/.mcp.json +14 -0
- package/LICENSE +21 -0
- package/README.md +556 -0
- package/commands/context-paging.md +51 -0
- package/commands/context-status.md +22 -0
- package/commands/context.md +5 -0
- package/commands/core-memory.md +56 -0
- package/commands/health.md +5 -0
- package/commands/init.md +39 -0
- package/commands/merge.md +113 -0
- package/commands/observe.md +5 -0
- package/commands/recall.md +5 -0
- package/commands/remember.md +11 -0
- package/commands/search.md +10 -0
- package/dist/adapters/claude-code/capture.d.ts +11 -0
- package/dist/adapters/claude-code/capture.d.ts.map +1 -0
- package/dist/adapters/claude-code/capture.js +100 -0
- package/dist/adapters/claude-code/capture.js.map +1 -0
- package/dist/adapters/claude-code/index.d.ts +5 -0
- package/dist/adapters/claude-code/index.d.ts.map +1 -0
- package/dist/adapters/claude-code/index.js +6 -0
- package/dist/adapters/claude-code/index.js.map +1 -0
- package/dist/adapters/claude-code/injection.d.ts +34 -0
- package/dist/adapters/claude-code/injection.d.ts.map +1 -0
- package/dist/adapters/claude-code/injection.js +127 -0
- package/dist/adapters/claude-code/injection.js.map +1 -0
- package/dist/adapters/claude-code/plugin-wrapper.d.ts +21 -0
- package/dist/adapters/claude-code/plugin-wrapper.d.ts.map +1 -0
- package/dist/adapters/claude-code/plugin-wrapper.js +239 -0
- package/dist/adapters/claude-code/plugin-wrapper.js.map +1 -0
- package/dist/adapters/claude-code/types.d.ts +46 -0
- package/dist/adapters/claude-code/types.d.ts.map +1 -0
- package/dist/adapters/claude-code/types.js +6 -0
- package/dist/adapters/claude-code/types.js.map +1 -0
- package/dist/algorithms/merge/analytics/token-estimator.d.ts +50 -0
- package/dist/algorithms/merge/analytics/token-estimator.d.ts.map +1 -0
- package/dist/algorithms/merge/analytics/token-estimator.js +154 -0
- package/dist/algorithms/merge/analytics/token-estimator.js.map +1 -0
- package/dist/algorithms/merge/detection/hash-filters.d.ts +47 -0
- package/dist/algorithms/merge/detection/hash-filters.d.ts.map +1 -0
- package/dist/algorithms/merge/detection/hash-filters.js +190 -0
- package/dist/algorithms/merge/detection/hash-filters.js.map +1 -0
- package/dist/algorithms/merge/detection/semantic-ranker.d.ts +32 -0
- package/dist/algorithms/merge/detection/semantic-ranker.d.ts.map +1 -0
- package/dist/algorithms/merge/detection/semantic-ranker.js +118 -0
- package/dist/algorithms/merge/detection/semantic-ranker.js.map +1 -0
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts +49 -0
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts.map +1 -0
- package/dist/algorithms/merge/detection/two-stage-detector.js +185 -0
- package/dist/algorithms/merge/detection/two-stage-detector.js.map +1 -0
- package/dist/algorithms/merge/handlers/approve-merge.d.ts +22 -0
- package/dist/algorithms/merge/handlers/approve-merge.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/approve-merge.js +179 -0
- package/dist/algorithms/merge/handlers/approve-merge.js.map +1 -0
- package/dist/algorithms/merge/handlers/detect-duplicates.d.ts +47 -0
- package/dist/algorithms/merge/handlers/detect-duplicates.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/detect-duplicates.js +165 -0
- package/dist/algorithms/merge/handlers/detect-duplicates.js.map +1 -0
- package/dist/algorithms/merge/handlers/get-stats.d.ts +39 -0
- package/dist/algorithms/merge/handlers/get-stats.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/get-stats.js +88 -0
- package/dist/algorithms/merge/handlers/get-stats.js.map +1 -0
- package/dist/algorithms/merge/handlers/list-proposals.d.ts +45 -0
- package/dist/algorithms/merge/handlers/list-proposals.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/list-proposals.js +83 -0
- package/dist/algorithms/merge/handlers/list-proposals.js.map +1 -0
- package/dist/algorithms/merge/handlers/preview-merge.d.ts +39 -0
- package/dist/algorithms/merge/handlers/preview-merge.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/preview-merge.js +93 -0
- package/dist/algorithms/merge/handlers/preview-merge.js.map +1 -0
- package/dist/algorithms/merge/handlers/reject-merge.d.ts +28 -0
- package/dist/algorithms/merge/handlers/reject-merge.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/reject-merge.js +69 -0
- package/dist/algorithms/merge/handlers/reject-merge.js.map +1 -0
- package/dist/algorithms/merge/handlers/reverse-merge.d.ts +21 -0
- package/dist/algorithms/merge/handlers/reverse-merge.d.ts.map +1 -0
- package/dist/algorithms/merge/handlers/reverse-merge.js +121 -0
- package/dist/algorithms/merge/handlers/reverse-merge.js.map +1 -0
- package/dist/algorithms/merge/safety/safety-checks.d.ts +22 -0
- package/dist/algorithms/merge/safety/safety-checks.d.ts.map +1 -0
- package/dist/algorithms/merge/safety/safety-checks.js +215 -0
- package/dist/algorithms/merge/safety/safety-checks.js.map +1 -0
- package/dist/algorithms/merge/strategies/merge-strategies.d.ts +32 -0
- package/dist/algorithms/merge/strategies/merge-strategies.d.ts.map +1 -0
- package/dist/algorithms/merge/strategies/merge-strategies.js +337 -0
- package/dist/algorithms/merge/strategies/merge-strategies.js.map +1 -0
- package/dist/api/web/web.d.ts +4 -0
- package/dist/api/web/web.d.ts.map +1 -0
- package/dist/api/web/web.js +484 -0
- package/dist/api/web/web.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-memory.d.ts +22 -0
- package/dist/core/agent-memory.d.ts.map +1 -0
- package/dist/core/agent-memory.js +111 -0
- package/dist/core/agent-memory.js.map +1 -0
- package/dist/core/associations.d.ts +32 -0
- package/dist/core/associations.d.ts.map +1 -0
- package/dist/core/associations.js +249 -0
- package/dist/core/associations.js.map +1 -0
- package/dist/core/cache.d.ts +13 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +202 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/consolidation.d.ts +6 -0
- package/dist/core/consolidation.d.ts.map +1 -0
- package/dist/core/consolidation.js +40 -0
- package/dist/core/consolidation.js.map +1 -0
- package/dist/core/context-paging.d.ts +90 -0
- package/dist/core/context-paging.d.ts.map +1 -0
- package/dist/core/context-paging.js +348 -0
- package/dist/core/context-paging.js.map +1 -0
- package/dist/core/context.d.ts +7 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +24 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/core-memory.d.ts +73 -0
- package/dist/core/core-memory.d.ts.map +1 -0
- package/dist/core/core-memory.js +214 -0
- package/dist/core/core-memory.js.map +1 -0
- package/dist/core/database.d.ts +12 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +12 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/embeddings/qmd-client.d.ts +136 -0
- package/dist/core/embeddings/qmd-client.d.ts.map +1 -0
- package/dist/core/embeddings/qmd-client.js +403 -0
- package/dist/core/embeddings/qmd-client.js.map +1 -0
- package/dist/core/embeddings/qmd-provider.d.ts +65 -0
- package/dist/core/embeddings/qmd-provider.d.ts.map +1 -0
- package/dist/core/embeddings/qmd-provider.js +133 -0
- package/dist/core/embeddings/qmd-provider.js.map +1 -0
- package/dist/core/embeddings.d.ts +19 -0
- package/dist/core/embeddings.d.ts.map +1 -0
- package/dist/core/embeddings.js +297 -0
- package/dist/core/embeddings.js.map +1 -0
- package/dist/core/governance.d.ts +21 -0
- package/dist/core/governance.d.ts.map +1 -0
- package/dist/core/governance.js +64 -0
- package/dist/core/governance.js.map +1 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lifecycle.d.ts +19 -0
- package/dist/core/lifecycle.d.ts.map +1 -0
- package/dist/core/lifecycle.js +182 -0
- package/dist/core/lifecycle.js.map +1 -0
- package/dist/core/local-embeddings.d.ts +14 -0
- package/dist/core/local-embeddings.d.ts.map +1 -0
- package/dist/core/local-embeddings.js +94 -0
- package/dist/core/local-embeddings.js.map +1 -0
- package/dist/core/logger.d.ts +16 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +34 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/memory/bridge-discovery.d.ts +50 -0
- package/dist/core/memory/bridge-discovery.d.ts.map +1 -0
- package/dist/core/memory/bridge-discovery.js +291 -0
- package/dist/core/memory/bridge-discovery.js.map +1 -0
- package/dist/core/memory/entity-extractor.d.ts +33 -0
- package/dist/core/memory/entity-extractor.d.ts.map +1 -0
- package/dist/core/memory/entity-extractor.js +336 -0
- package/dist/core/memory/entity-extractor.js.map +1 -0
- package/dist/core/memory/entity-resolver.d.ts +23 -0
- package/dist/core/memory/entity-resolver.d.ts.map +1 -0
- package/dist/core/memory/entity-resolver.js +64 -0
- package/dist/core/memory/entity-resolver.js.map +1 -0
- package/dist/core/memory/fact-extractor.d.ts +24 -0
- package/dist/core/memory/fact-extractor.d.ts.map +1 -0
- package/dist/core/memory/fact-extractor.js +89 -0
- package/dist/core/memory/fact-extractor.js.map +1 -0
- package/dist/core/memory/hybrid-retrieval.d.ts +30 -0
- package/dist/core/memory/hybrid-retrieval.d.ts.map +1 -0
- package/dist/core/memory/hybrid-retrieval.js +63 -0
- package/dist/core/memory/hybrid-retrieval.js.map +1 -0
- package/dist/core/memory/hybrid-scorer.d.ts +51 -0
- package/dist/core/memory/hybrid-scorer.d.ts.map +1 -0
- package/dist/core/memory/hybrid-scorer.js +248 -0
- package/dist/core/memory/hybrid-scorer.js.map +1 -0
- package/dist/core/memory/index.d.ts +8 -0
- package/dist/core/memory/index.d.ts.map +1 -0
- package/dist/core/memory/index.js +10 -0
- package/dist/core/memory/index.js.map +1 -0
- package/dist/core/memory/memories.d.ts +35 -0
- package/dist/core/memory/memories.d.ts.map +1 -0
- package/dist/core/memory/memories.js +338 -0
- package/dist/core/memory/memories.js.map +1 -0
- package/dist/core/memory/memory-manager.d.ts +15 -0
- package/dist/core/memory/memory-manager.d.ts.map +1 -0
- package/dist/core/memory/memory-manager.js +46 -0
- package/dist/core/memory/memory-manager.js.map +1 -0
- package/dist/core/memory/query-processor.d.ts +21 -0
- package/dist/core/memory/query-processor.d.ts.map +1 -0
- package/dist/core/memory/query-processor.js +72 -0
- package/dist/core/memory/query-processor.js.map +1 -0
- package/dist/core/memory/serialization.d.ts +6 -0
- package/dist/core/memory/serialization.d.ts.map +1 -0
- package/dist/core/memory/serialization.js +35 -0
- package/dist/core/memory/serialization.js.map +1 -0
- package/dist/core/memory/temporal-parser.d.ts +32 -0
- package/dist/core/memory/temporal-parser.d.ts.map +1 -0
- package/dist/core/memory/temporal-parser.js +385 -0
- package/dist/core/memory/temporal-parser.js.map +1 -0
- package/dist/core/observations.d.ts +26 -0
- package/dist/core/observations.d.ts.map +1 -0
- package/dist/core/observations.js +118 -0
- package/dist/core/observations.js.map +1 -0
- package/dist/core/privacy.d.ts +23 -0
- package/dist/core/privacy.d.ts.map +1 -0
- package/dist/core/privacy.js +82 -0
- package/dist/core/privacy.js.map +1 -0
- package/dist/core/projects.d.ts +10 -0
- package/dist/core/projects.d.ts.map +1 -0
- package/dist/core/projects.js +66 -0
- package/dist/core/projects.js.map +1 -0
- package/dist/core/redis.d.ts +11 -0
- package/dist/core/redis.d.ts.map +1 -0
- package/dist/core/redis.js +69 -0
- package/dist/core/redis.js.map +1 -0
- package/dist/core/requirements.d.ts +20 -0
- package/dist/core/requirements.d.ts.map +1 -0
- package/dist/core/requirements.js +35 -0
- package/dist/core/requirements.js.map +1 -0
- package/dist/core/search/conversations.d.ts +25 -0
- package/dist/core/search/conversations.d.ts.map +1 -0
- package/dist/core/search/conversations.js +112 -0
- package/dist/core/search/conversations.js.map +1 -0
- package/dist/core/search/entities.d.ts +12 -0
- package/dist/core/search/entities.d.ts.map +1 -0
- package/dist/core/search/entities.js +34 -0
- package/dist/core/search/entities.js.map +1 -0
- package/dist/core/search/folder-context.d.ts +25 -0
- package/dist/core/search/folder-context.d.ts.map +1 -0
- package/dist/core/search/folder-context.js +119 -0
- package/dist/core/search/folder-context.js.map +1 -0
- package/dist/core/search/index.d.ts +4 -0
- package/dist/core/search/index.d.ts.map +1 -0
- package/dist/core/search/index.js +5 -0
- package/dist/core/search/index.js.map +1 -0
- package/dist/core/search/qmd-search.d.ts +61 -0
- package/dist/core/search/qmd-search.d.ts.map +1 -0
- package/dist/core/search/qmd-search.js +178 -0
- package/dist/core/search/qmd-search.js.map +1 -0
- package/dist/core/secret-detector.d.ts +32 -0
- package/dist/core/secret-detector.d.ts.map +1 -0
- package/dist/core/secret-detector.js +88 -0
- package/dist/core/secret-detector.js.map +1 -0
- package/dist/core/snapshots/cleanup.d.ts +9 -0
- package/dist/core/snapshots/cleanup.d.ts.map +1 -0
- package/dist/core/snapshots/cleanup.js +12 -0
- package/dist/core/snapshots/cleanup.js.map +1 -0
- package/dist/core/snapshots/comparison.d.ts +19 -0
- package/dist/core/snapshots/comparison.d.ts.map +1 -0
- package/dist/core/snapshots/comparison.js +37 -0
- package/dist/core/snapshots/comparison.js.map +1 -0
- package/dist/core/snapshots/creation.d.ts +19 -0
- package/dist/core/snapshots/creation.d.ts.map +1 -0
- package/dist/core/snapshots/creation.js +126 -0
- package/dist/core/snapshots/creation.js.map +1 -0
- package/dist/core/snapshots/retrieval.d.ts +7 -0
- package/dist/core/snapshots/retrieval.d.ts.map +1 -0
- package/dist/core/snapshots/retrieval.js +41 -0
- package/dist/core/snapshots/retrieval.js.map +1 -0
- package/dist/core/snapshots/stats.d.ts +11 -0
- package/dist/core/snapshots/stats.d.ts.map +1 -0
- package/dist/core/snapshots/stats.js +52 -0
- package/dist/core/snapshots/stats.js.map +1 -0
- package/dist/core/snapshots.d.ts +29 -0
- package/dist/core/snapshots.d.ts.map +1 -0
- package/dist/core/snapshots.js +220 -0
- package/dist/core/snapshots.js.map +1 -0
- package/dist/core/summarization/cleanup.d.ts +9 -0
- package/dist/core/summarization/cleanup.d.ts.map +1 -0
- package/dist/core/summarization/cleanup.js +12 -0
- package/dist/core/summarization/cleanup.js.map +1 -0
- package/dist/core/summarization/queries.d.ts +9 -0
- package/dist/core/summarization/queries.d.ts.map +1 -0
- package/dist/core/summarization/queries.js +28 -0
- package/dist/core/summarization/queries.js.map +1 -0
- package/dist/core/summarization/stats.d.ts +14 -0
- package/dist/core/summarization/stats.d.ts.map +1 -0
- package/dist/core/summarization/stats.js +52 -0
- package/dist/core/summarization/stats.js.map +1 -0
- package/dist/core/summarization/strategies.d.ts +24 -0
- package/dist/core/summarization/strategies.d.ts.map +1 -0
- package/dist/core/summarization/strategies.js +28 -0
- package/dist/core/summarization/strategies.js.map +1 -0
- package/dist/core/summarization.d.ts +37 -0
- package/dist/core/summarization.d.ts.map +1 -0
- package/dist/core/summarization.js +188 -0
- package/dist/core/summarization.js.map +1 -0
- package/dist/core/sync/qmd-sync.d.ts +106 -0
- package/dist/core/sync/qmd-sync.d.ts.map +1 -0
- package/dist/core/sync/qmd-sync.js +213 -0
- package/dist/core/sync/qmd-sync.js.map +1 -0
- package/dist/core/temporal-facts.d.ts +54 -0
- package/dist/core/temporal-facts.d.ts.map +1 -0
- package/dist/core/temporal-facts.js +193 -0
- package/dist/core/temporal-facts.js.map +1 -0
- package/dist/core/utils/cleanup-operations.d.ts +13 -0
- package/dist/core/utils/cleanup-operations.d.ts.map +1 -0
- package/dist/core/utils/cleanup-operations.js +44 -0
- package/dist/core/utils/cleanup-operations.js.map +1 -0
- package/dist/core/utils/content-extraction.d.ts +19 -0
- package/dist/core/utils/content-extraction.d.ts.map +1 -0
- package/dist/core/utils/content-extraction.js +65 -0
- package/dist/core/utils/content-extraction.js.map +1 -0
- package/dist/core/utils/filter-builder.d.ts +13 -0
- package/dist/core/utils/filter-builder.d.ts.map +1 -0
- package/dist/core/utils/filter-builder.js +44 -0
- package/dist/core/utils/filter-builder.js.map +1 -0
- package/dist/core/utils/history-traversal.d.ts +13 -0
- package/dist/core/utils/history-traversal.d.ts.map +1 -0
- package/dist/core/utils/history-traversal.js +50 -0
- package/dist/core/utils/history-traversal.js.map +1 -0
- package/dist/core/utils/memory-operations.d.ts +17 -0
- package/dist/core/utils/memory-operations.d.ts.map +1 -0
- package/dist/core/utils/memory-operations.js +41 -0
- package/dist/core/utils/memory-operations.js.map +1 -0
- package/dist/core/utils/query-operations.d.ts +18 -0
- package/dist/core/utils/query-operations.d.ts.map +1 -0
- package/dist/core/utils/query-operations.js +65 -0
- package/dist/core/utils/query-operations.js.map +1 -0
- package/dist/core/utils/summarization-helpers.d.ts +21 -0
- package/dist/core/utils/summarization-helpers.d.ts.map +1 -0
- package/dist/core/utils/summarization-helpers.js +35 -0
- package/dist/core/utils/summarization-helpers.js.map +1 -0
- package/dist/core/utils/temporal-queries.d.ts +13 -0
- package/dist/core/utils/temporal-queries.d.ts.map +1 -0
- package/dist/core/utils/temporal-queries.js +27 -0
- package/dist/core/utils/temporal-queries.js.map +1 -0
- package/dist/core/utils/version-management.d.ts +9 -0
- package/dist/core/utils/version-management.d.ts.map +1 -0
- package/dist/core/utils/version-management.js +61 -0
- package/dist/core/utils/version-management.js.map +1 -0
- package/dist/core/utils.d.ts +13 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +51 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/core/worker.d.ts +62 -0
- package/dist/core/worker.d.ts.map +1 -0
- package/dist/core/worker.js +186 -0
- package/dist/core/worker.js.map +1 -0
- package/dist/db/adapter.d.ts +6 -0
- package/dist/db/adapter.d.ts.map +1 -0
- package/dist/db/adapter.js +43 -0
- package/dist/db/adapter.js.map +1 -0
- package/dist/db/bootstrap.d.ts +9 -0
- package/dist/db/bootstrap.d.ts.map +1 -0
- package/dist/db/bootstrap.js +444 -0
- package/dist/db/bootstrap.js.map +1 -0
- package/dist/db/index.d.ts +11 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +43 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +11 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/drizzle/schema-sqlite.d.ts +3046 -0
- package/dist/drizzle/schema-sqlite.d.ts.map +1 -0
- package/dist/drizzle/schema-sqlite.js +405 -0
- package/dist/drizzle/schema-sqlite.js.map +1 -0
- package/dist/drizzle/schema.d.ts +2969 -0
- package/dist/drizzle/schema.d.ts.map +1 -0
- package/dist/drizzle/schema.js +555 -0
- package/dist/drizzle/schema.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +784 -0
- package/dist/index.js.map +1 -0
- package/hooks/hooks.json +52 -0
- package/hooks/post-tool-use.js +26 -0
- package/hooks/session-end.js +28 -0
- package/hooks/session-start.js +33 -0
- package/hooks/user-prompt-submit.js +26 -0
- package/hooks/utils.js +153 -0
- package/npx-installer.js +208 -0
- package/package.json +101 -0
- package/plugin.json +32 -0
- package/skills/memory-guide/SKILL.md +198 -0
- package/skills/squish-memory/SKILL.md +87 -0
- package/skills/squish-memory/install.sh +91 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,784 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Squish v0.6.0 - Major tool consolidation milestone
|
|
4
|
+
*
|
|
5
|
+
* This is a significant refactor reducing MCP tools from 18 to 11 (39% reduction).
|
|
6
|
+
* Breaking changes in tool API - migration guide: see docs/MIGRATION-v0.6.0.md
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - 11 consolidated MCP tools (from 18)
|
|
10
|
+
* - Local mode: SQLite with FTS5 + auto-capture + folder context
|
|
11
|
+
* - Team mode: PostgreSQL + pgvector + Redis
|
|
12
|
+
* - Plugin system: Hooks for auto-capture, context injection, privacy filtering, folder context generation
|
|
13
|
+
* - Privacy-first: Secret detection, <private> tag filtering, async worker pipeline
|
|
14
|
+
* - Pluggable embeddings: OpenAI, Ollama, or local TF-IDF
|
|
15
|
+
*
|
|
16
|
+
* Consolidated MCP Tools (v0.6.0):
|
|
17
|
+
* - core_memory: Unified tool for view/edit/append operations (was 3 tools)
|
|
18
|
+
* - context_paging: Unified tool for load/evict/view operations (was 3 tools)
|
|
19
|
+
* - merge: Unified tool for detect/list/preview/stats/approve/reject/reverse (was 2 tools)
|
|
20
|
+
* - context_status, remember, recall, search, observe, context, health (unchanged)
|
|
21
|
+
* - lifecycle, summarize_session, protect_memory (unchanged)
|
|
22
|
+
*
|
|
23
|
+
* Plugin hooks (registered in plugin.json):
|
|
24
|
+
* - onInstall: Initialize database, create config files
|
|
25
|
+
* - onSessionStart: Inject relevant context + generate folder context
|
|
26
|
+
* - onUserPromptSubmit: Auto-capture user prompts with privacy filtering
|
|
27
|
+
* - onPostToolUse: Auto-capture tool executions and observe patterns
|
|
28
|
+
* - onSessionStop: Finalize observations, summarize via async worker
|
|
29
|
+
*
|
|
30
|
+
* See src/plugin/plugin-wrapper.ts for hook implementations
|
|
31
|
+
* See docs/MIGRATION-v0.6.0.md for migration guide
|
|
32
|
+
*/
|
|
33
|
+
import 'dotenv/config';
|
|
34
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
35
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
36
|
+
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
37
|
+
import { logger } from './core/logger.js';
|
|
38
|
+
import { checkDatabaseHealth, config } from './db/index.js';
|
|
39
|
+
import { checkRedisHealth, closeCache } from './core/cache.js';
|
|
40
|
+
import { rememberMemory, getMemoryById, searchMemories } from './core/memory/memories.js';
|
|
41
|
+
import { searchConversations, getRecentConversations } from './core/search/conversations.js';
|
|
42
|
+
import { createObservation } from './core/observations.js';
|
|
43
|
+
import { getProjectContext } from './core/context.js';
|
|
44
|
+
import { startWebServer } from './api/web/web.js';
|
|
45
|
+
import { handleDetectDuplicates } from './algorithms/merge/handlers/detect-duplicates.js';
|
|
46
|
+
import { handleListProposals } from './algorithms/merge/handlers/list-proposals.js';
|
|
47
|
+
import { handlePreviewMerge } from './algorithms/merge/handlers/preview-merge.js';
|
|
48
|
+
import { handleApproveMerge } from './algorithms/merge/handlers/approve-merge.js';
|
|
49
|
+
import { handleRejectMerge } from './algorithms/merge/handlers/reject-merge.js';
|
|
50
|
+
import { handleReverseMerge } from './algorithms/merge/handlers/reverse-merge.js';
|
|
51
|
+
import { handleGetMergeStats } from './algorithms/merge/handlers/get-stats.js';
|
|
52
|
+
import { forceLifecycleMaintenance } from './core/worker.js';
|
|
53
|
+
import { summarizeSession } from './core/summarization.js';
|
|
54
|
+
import { storeAgentMemory } from './core/agent-memory.js';
|
|
55
|
+
import { getRelatedMemories } from './core/associations.js';
|
|
56
|
+
import { protectMemory, pinMemory } from './core/governance.js';
|
|
57
|
+
import { isDatabaseUnavailableError, determineOverallStatus } from './core/utils.js';
|
|
58
|
+
import { searchWithQMD, isQMDAvailable } from './core/search/qmd-search.js';
|
|
59
|
+
import { initializeCoreMemory, getCoreMemory, editCoreMemorySection, appendCoreMemorySection, getCoreMemoryStats, } from './core/core-memory.js';
|
|
60
|
+
import { loadMemoryToContext, evictMemoryFromContext, viewLoadedMemories, getContextStatus, } from './core/context-paging.js';
|
|
61
|
+
const VERSION = '0.6.0';
|
|
62
|
+
const TOOLS = [
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Core Memory Tool (Tier 1 - Always-In-Context)
|
|
65
|
+
// ============================================================================
|
|
66
|
+
{
|
|
67
|
+
name: 'core_memory',
|
|
68
|
+
description: 'View or edit your core memory (always-visible). Use this to see your persona, user info, project context, and working notes. Update this when you learn something important that should always be visible.',
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
action: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
enum: ['view', 'edit', 'append'],
|
|
75
|
+
description: 'Memory action: view all, edit specific section, or append to section'
|
|
76
|
+
},
|
|
77
|
+
projectId: { type: 'string', description: 'Project ID' },
|
|
78
|
+
section: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
enum: ['persona', 'user_info', 'project_context', 'working_notes'],
|
|
81
|
+
description: 'Section name (required for edit/append actions)'
|
|
82
|
+
},
|
|
83
|
+
content: { type: 'string', description: 'New content for section (edit action)' },
|
|
84
|
+
text: { type: 'string', description: 'Text to append to section (append action)' },
|
|
85
|
+
},
|
|
86
|
+
required: ['action', 'projectId']
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// Context Paging Tool (Tier 2 - Working Set Management)
|
|
91
|
+
// Note: Claude manages its own context/tokens. These track your working set.
|
|
92
|
+
// ============================================================================
|
|
93
|
+
{
|
|
94
|
+
name: 'context_paging',
|
|
95
|
+
description: 'Manage your working memory set. Load specific memories you want to keep visible, evict ones you no longer need, or view what is currently loaded.',
|
|
96
|
+
inputSchema: {
|
|
97
|
+
type: 'object',
|
|
98
|
+
properties: {
|
|
99
|
+
action: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
enum: ['load', 'evict', 'view'],
|
|
102
|
+
description: 'Paging action: load memory, evict memory, or view all loaded'
|
|
103
|
+
},
|
|
104
|
+
sessionId: { type: 'string', description: 'Session ID' },
|
|
105
|
+
memoryId: { type: 'string', description: 'Memory UUID (required for load/evict actions)' },
|
|
106
|
+
},
|
|
107
|
+
required: ['action', 'sessionId']
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'context_status',
|
|
112
|
+
description: 'View comprehensive context window status and token usage',
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: 'object',
|
|
115
|
+
properties: {
|
|
116
|
+
sessionId: { type: 'string', description: 'Session ID' },
|
|
117
|
+
projectId: { type: 'string', description: 'Project ID' },
|
|
118
|
+
},
|
|
119
|
+
required: ['sessionId', 'projectId']
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// Memory Tools (Original)
|
|
124
|
+
// ============================================================================
|
|
125
|
+
{
|
|
126
|
+
name: 'remember',
|
|
127
|
+
description: 'Store information for future use. Use this when you learn something important that you might need to recall later. Perfect for facts, decisions, code snippets, configuration details, or user preferences.',
|
|
128
|
+
inputSchema: {
|
|
129
|
+
type: 'object',
|
|
130
|
+
properties: {
|
|
131
|
+
content: { type: 'string', description: 'Content to store' },
|
|
132
|
+
type: { type: 'string', enum: ['observation', 'fact', 'decision', 'context', 'preference'] },
|
|
133
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
134
|
+
project: { type: 'string', description: 'Project path' },
|
|
135
|
+
metadata: { type: 'object', description: 'Custom metadata' },
|
|
136
|
+
agentId: { type: 'string', description: 'Agent identifier (optional)' },
|
|
137
|
+
agentRole: { type: 'string', description: 'Agent role (optional)' },
|
|
138
|
+
visibilityScope: { type: 'string', enum: ['private', 'project', 'team', 'global'], description: 'Visibility scope for agent memories' },
|
|
139
|
+
sector: { type: 'string', enum: ['episodic', 'semantic', 'procedural', 'autobiographical', 'working'], description: 'Memory sector classification' }
|
|
140
|
+
},
|
|
141
|
+
required: ['content']
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'recall',
|
|
146
|
+
description: 'Retrieve a specific stored memory by ID (like reading a file). Use this when you have a memory ID and want to get its full content.',
|
|
147
|
+
inputSchema: {
|
|
148
|
+
type: 'object',
|
|
149
|
+
properties: {
|
|
150
|
+
id: { type: 'string', description: 'Memory UUID' }
|
|
151
|
+
},
|
|
152
|
+
required: ['id']
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'search',
|
|
157
|
+
description: 'Search your stored memories for information (like grep). Use this when you need to find memories matching a query, or when the user asks about something you might have remembered. Leave query empty to list recent memories.',
|
|
158
|
+
inputSchema: {
|
|
159
|
+
type: 'object',
|
|
160
|
+
properties: {
|
|
161
|
+
query: { type: 'string', description: 'Search query (not required for scope=recent)' },
|
|
162
|
+
scope: {
|
|
163
|
+
type: 'string',
|
|
164
|
+
enum: ['memories', 'conversations', 'recent'],
|
|
165
|
+
default: 'memories',
|
|
166
|
+
description: 'Search scope: memories, conversations, or recent items'
|
|
167
|
+
},
|
|
168
|
+
type: { type: 'string', enum: ['observation', 'fact', 'decision', 'context', 'preference'] },
|
|
169
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
170
|
+
limit: { type: 'number', default: 10 },
|
|
171
|
+
project: { type: 'string' },
|
|
172
|
+
role: { type: 'string', enum: ['user', 'assistant'], description: 'Filter by role (conversations scope)' },
|
|
173
|
+
n: { type: 'number', description: 'Number of recent items (recent scope)' },
|
|
174
|
+
before: { type: 'string', description: 'ISO datetime for recent scope' },
|
|
175
|
+
after: { type: 'string', description: 'ISO datetime for recent scope' }
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'observe',
|
|
181
|
+
description: 'Record an observation about your work (tool usage, patterns, errors). Use this to document what you\'re learning about the codebase and problems you encounter.',
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: 'object',
|
|
184
|
+
properties: {
|
|
185
|
+
type: { type: 'string', enum: ['tool_use', 'file_change', 'error', 'pattern', 'insight'] },
|
|
186
|
+
action: { type: 'string', description: 'Action taken' },
|
|
187
|
+
target: { type: 'string', description: 'Target of action' },
|
|
188
|
+
summary: { type: 'string', description: 'Summary' },
|
|
189
|
+
details: { type: 'object' },
|
|
190
|
+
session: { type: 'string', description: 'Session ID' }
|
|
191
|
+
},
|
|
192
|
+
required: ['type', 'action', 'summary']
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: 'context',
|
|
197
|
+
description: 'Get project context',
|
|
198
|
+
inputSchema: {
|
|
199
|
+
type: 'object',
|
|
200
|
+
properties: {
|
|
201
|
+
project: { type: 'string', description: 'Project path' },
|
|
202
|
+
include: {
|
|
203
|
+
type: 'array',
|
|
204
|
+
items: { type: 'string', enum: ['memories', 'observations', 'entities', 'messages'] },
|
|
205
|
+
default: ['memories', 'observations']
|
|
206
|
+
},
|
|
207
|
+
limit: { type: 'number', default: 10 }
|
|
208
|
+
},
|
|
209
|
+
required: ['project']
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: 'init',
|
|
214
|
+
description: 'Initialize Squish memory system for the current project. Creates the database structure and default settings. Run once when starting to use Squish in a new project.',
|
|
215
|
+
inputSchema: {
|
|
216
|
+
type: 'object',
|
|
217
|
+
properties: {
|
|
218
|
+
projectPath: {
|
|
219
|
+
type: 'string',
|
|
220
|
+
description: 'Project path (optional, defaults to current directory)'
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: 'health',
|
|
227
|
+
description: 'Check service status',
|
|
228
|
+
inputSchema: { type: 'object', properties: {} }
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: 'merge',
|
|
232
|
+
description: 'Manage memory merges: detect duplicates, list proposals, preview merges, get statistics, approve, reject, or reverse merges',
|
|
233
|
+
inputSchema: {
|
|
234
|
+
type: 'object',
|
|
235
|
+
properties: {
|
|
236
|
+
action: {
|
|
237
|
+
type: 'string',
|
|
238
|
+
enum: ['detect', 'list', 'preview', 'stats', 'approve', 'reject', 'reverse'],
|
|
239
|
+
description: 'Merge action: detect duplicates, list proposals, preview merge, view stats, approve, reject, or reverse'
|
|
240
|
+
},
|
|
241
|
+
projectId: { type: 'string', description: 'Project ID (required for detect, list, stats)' },
|
|
242
|
+
proposalId: { type: 'string', description: 'Proposal ID (required for preview, approve, reject)' },
|
|
243
|
+
mergeHistoryId: { type: 'string', description: 'Merge history ID (required for reverse action)' },
|
|
244
|
+
threshold: { type: 'number', description: 'Similarity threshold 0-1 (detect action only)' },
|
|
245
|
+
memoryType: { type: 'string', enum: ['fact', 'preference', 'decision', 'observation', 'context'], description: 'Memory type filter (detect action only)' },
|
|
246
|
+
status: { type: 'string', enum: ['pending', 'approved', 'rejected', 'expired'], description: 'Proposal status filter (list action only)' },
|
|
247
|
+
reviewNotes: { type: 'string', description: 'Notes or reason for decision (approve/reject only)' },
|
|
248
|
+
limit: { type: 'number', description: 'Max results to return' }
|
|
249
|
+
},
|
|
250
|
+
required: ['action']
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: 'lifecycle',
|
|
255
|
+
description: 'Run memory lifecycle maintenance (decay, eviction, tier updates)',
|
|
256
|
+
inputSchema: {
|
|
257
|
+
type: 'object',
|
|
258
|
+
properties: {
|
|
259
|
+
project: { type: 'string', description: 'Project path (optional)' },
|
|
260
|
+
force: { type: 'boolean', description: 'Force immediate execution' }
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: 'summarize_session',
|
|
266
|
+
description: 'Summarize a conversation session',
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: 'object',
|
|
269
|
+
properties: {
|
|
270
|
+
conversationId: { type: 'string', description: 'Conversation UUID' },
|
|
271
|
+
type: { type: 'string', enum: ['incremental', 'rolling', 'final'], description: 'Summary type' }
|
|
272
|
+
},
|
|
273
|
+
required: ['conversationId', 'type']
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: 'protect_memory',
|
|
278
|
+
description: 'Mark memory as protected (cannot be evicted)',
|
|
279
|
+
inputSchema: {
|
|
280
|
+
type: 'object',
|
|
281
|
+
properties: {
|
|
282
|
+
memoryId: { type: 'string', description: 'Memory UUID' },
|
|
283
|
+
reason: { type: 'string', description: 'Protection reason' }
|
|
284
|
+
},
|
|
285
|
+
required: ['memoryId', 'reason']
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: 'pin_memory',
|
|
290
|
+
description: 'Pin memory for automatic injection into context',
|
|
291
|
+
inputSchema: {
|
|
292
|
+
type: 'object',
|
|
293
|
+
properties: {
|
|
294
|
+
memoryId: { type: 'string', description: 'Memory UUID' }
|
|
295
|
+
},
|
|
296
|
+
required: ['memoryId']
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'get_related',
|
|
301
|
+
description: 'Find memories related to a specific memory by ID. Use this for iterative search - if a search result is relevant, find similar memories without needing new queries.',
|
|
302
|
+
inputSchema: {
|
|
303
|
+
type: 'object',
|
|
304
|
+
properties: {
|
|
305
|
+
memoryId: { type: 'string', description: 'Memory UUID' },
|
|
306
|
+
limit: { type: 'number', description: 'Max results (default: 10)' }
|
|
307
|
+
},
|
|
308
|
+
required: ['memoryId']
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
// ============================================================================
|
|
312
|
+
// QMD Hybrid Search Tool (v0.7.0)
|
|
313
|
+
// ============================================================================
|
|
314
|
+
{
|
|
315
|
+
name: 'qmd_search',
|
|
316
|
+
description: 'Search memories using QMD hybrid search (BM25 + vector + rerank). Provides higher quality results when QMD is available. Falls back to standard search if QMD is not installed.',
|
|
317
|
+
inputSchema: {
|
|
318
|
+
type: 'object',
|
|
319
|
+
properties: {
|
|
320
|
+
query: { type: 'string', description: 'Search query' },
|
|
321
|
+
type: { type: 'string', enum: ['observation', 'fact', 'decision', 'context', 'preference'], description: 'Memory type filter' },
|
|
322
|
+
limit: { type: 'number', description: 'Max results (default: 10)', default: 10 },
|
|
323
|
+
useHybrid: { type: 'boolean', description: 'Use full hybrid pipeline with reranking (default: true)', default: true },
|
|
324
|
+
collection: { type: 'string', description: 'Override default collection mapping' }
|
|
325
|
+
},
|
|
326
|
+
required: ['query']
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
];
|
|
330
|
+
class Squish {
|
|
331
|
+
server;
|
|
332
|
+
constructor() {
|
|
333
|
+
this.server = new Server({ name: 'squish', version: VERSION }, { capabilities: { tools: {} } });
|
|
334
|
+
this.setup();
|
|
335
|
+
}
|
|
336
|
+
setup() {
|
|
337
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
338
|
+
tools: TOOLS
|
|
339
|
+
}));
|
|
340
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
341
|
+
const { name } = req.params;
|
|
342
|
+
const args = (req.params.arguments ?? {});
|
|
343
|
+
try {
|
|
344
|
+
switch (name) {
|
|
345
|
+
case 'core_memory':
|
|
346
|
+
return await this.handleCoreMemory(args);
|
|
347
|
+
case 'context_paging':
|
|
348
|
+
return await this.handleContextPaging(args);
|
|
349
|
+
case 'context_status': {
|
|
350
|
+
if (!args.sessionId || !args.projectId) {
|
|
351
|
+
throw new McpError(ErrorCode.InvalidParams, 'sessionId and projectId are required');
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
const result = await getContextStatus(String(args.sessionId), String(args.projectId));
|
|
355
|
+
return this.jsonResponse({ ok: true, ...result });
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
throw new McpError(ErrorCode.InternalError, `Context status failed: ${error.message}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Original Memory Tools
|
|
362
|
+
case 'remember': {
|
|
363
|
+
if (typeof args.content !== 'string' || !args.content) {
|
|
364
|
+
throw new McpError(ErrorCode.InvalidParams, 'content is required');
|
|
365
|
+
}
|
|
366
|
+
try {
|
|
367
|
+
// Check if agent context is provided
|
|
368
|
+
if (args.agentId) {
|
|
369
|
+
const memoryId = await storeAgentMemory(args.content, {
|
|
370
|
+
agentId: args.agentId,
|
|
371
|
+
agentRole: args.agentRole,
|
|
372
|
+
}, {
|
|
373
|
+
type: args.type,
|
|
374
|
+
visibilityScope: args.visibilityScope,
|
|
375
|
+
sector: args.sector,
|
|
376
|
+
tags: args.tags,
|
|
377
|
+
metadata: args.metadata,
|
|
378
|
+
});
|
|
379
|
+
return this.jsonResponse({ ok: true, memoryId, agentContext: true });
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
// Standard memory storage
|
|
383
|
+
return this.jsonResponse({ ok: true, data: await rememberMemory(args) });
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
catch (dbError) {
|
|
387
|
+
if (isDatabaseUnavailableError(dbError)) {
|
|
388
|
+
throw new McpError(ErrorCode.InternalError, 'Database unavailable - memory storage disabled');
|
|
389
|
+
}
|
|
390
|
+
throw dbError;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
case 'recall': {
|
|
394
|
+
if (!args.id) {
|
|
395
|
+
throw new McpError(ErrorCode.InvalidParams, 'id is required');
|
|
396
|
+
}
|
|
397
|
+
try {
|
|
398
|
+
const memory = await getMemoryById(String(args.id));
|
|
399
|
+
return this.jsonResponse({ ok: true, found: !!memory, data: memory });
|
|
400
|
+
}
|
|
401
|
+
catch (dbError) {
|
|
402
|
+
if (isDatabaseUnavailableError(dbError)) {
|
|
403
|
+
throw new McpError(ErrorCode.InternalError, 'Database unavailable - memory retrieval disabled');
|
|
404
|
+
}
|
|
405
|
+
throw dbError;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
case 'search': {
|
|
409
|
+
const scope = args.scope || 'memories';
|
|
410
|
+
try {
|
|
411
|
+
if (scope === 'memories') {
|
|
412
|
+
if (typeof args.query !== 'string' || !args.query) {
|
|
413
|
+
throw new McpError(ErrorCode.InvalidParams, 'query is required for memory search');
|
|
414
|
+
}
|
|
415
|
+
return this.jsonResponse({ ok: true, scope: 'memories', data: await searchMemories(args) });
|
|
416
|
+
}
|
|
417
|
+
else if (scope === 'conversations') {
|
|
418
|
+
if (typeof args.query !== 'string' || !args.query) {
|
|
419
|
+
throw new McpError(ErrorCode.InvalidParams, 'query is required for conversation search');
|
|
420
|
+
}
|
|
421
|
+
return this.jsonResponse({ ok: true, scope: 'conversations', data: await searchConversations(args) });
|
|
422
|
+
}
|
|
423
|
+
else if (scope === 'recent') {
|
|
424
|
+
return this.jsonResponse({ ok: true, scope: 'recent', data: await getRecentConversations(args) });
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown scope: ${scope}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
catch (dbError) {
|
|
431
|
+
if (isDatabaseUnavailableError(dbError)) {
|
|
432
|
+
throw new McpError(ErrorCode.InternalError, 'Database unavailable - search disabled');
|
|
433
|
+
}
|
|
434
|
+
throw dbError;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
case 'observe': {
|
|
438
|
+
if (!args.type || !args.action || !args.summary) {
|
|
439
|
+
throw new McpError(ErrorCode.InvalidParams, 'type, action, and summary are required');
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
return this.jsonResponse({ ok: true, data: await createObservation(args) });
|
|
443
|
+
}
|
|
444
|
+
catch (dbError) {
|
|
445
|
+
if (isDatabaseUnavailableError(dbError)) {
|
|
446
|
+
throw new McpError(ErrorCode.InternalError, 'Database unavailable - observation storage disabled');
|
|
447
|
+
}
|
|
448
|
+
throw dbError;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
case 'context': {
|
|
452
|
+
if (!args.project) {
|
|
453
|
+
throw new McpError(ErrorCode.InvalidParams, 'project is required');
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
return this.jsonResponse({ ok: true, data: await getProjectContext(args) });
|
|
457
|
+
}
|
|
458
|
+
catch (dbError) {
|
|
459
|
+
if (isDatabaseUnavailableError(dbError)) {
|
|
460
|
+
throw new McpError(ErrorCode.InternalError, 'Database unavailable - context retrieval disabled');
|
|
461
|
+
}
|
|
462
|
+
throw dbError;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
case 'init': {
|
|
466
|
+
const { projectPath } = args;
|
|
467
|
+
const targetPath = projectPath || process.cwd();
|
|
468
|
+
const { ensureProject } = await import('./core/projects.js');
|
|
469
|
+
const { ensureDataDirectory } = await import('./db/bootstrap.js');
|
|
470
|
+
const path = await import('path');
|
|
471
|
+
try {
|
|
472
|
+
// Ensure data directory exists
|
|
473
|
+
await ensureDataDirectory();
|
|
474
|
+
// Ensure project exists
|
|
475
|
+
const project = await ensureProject(targetPath);
|
|
476
|
+
if (!project) {
|
|
477
|
+
return this.jsonResponse({
|
|
478
|
+
success: false,
|
|
479
|
+
error: 'Failed to create project',
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
return this.jsonResponse({
|
|
483
|
+
success: true,
|
|
484
|
+
message: `Squish initialized for project: ${project.name}`,
|
|
485
|
+
project: {
|
|
486
|
+
id: project.id,
|
|
487
|
+
name: project.name,
|
|
488
|
+
path: project.path,
|
|
489
|
+
},
|
|
490
|
+
nextSteps: [
|
|
491
|
+
'Squish is now ready to capture and store memories',
|
|
492
|
+
'Use /squish:remember to store important information',
|
|
493
|
+
'Use /squish:search to find stored memories',
|
|
494
|
+
'Use /squish:core_memory to view/edit your always-visible context',
|
|
495
|
+
],
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
catch (error) {
|
|
499
|
+
return this.jsonResponse({
|
|
500
|
+
success: false,
|
|
501
|
+
error: error instanceof Error ? error.message : String(error),
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
case 'health':
|
|
506
|
+
return this.health();
|
|
507
|
+
case 'merge':
|
|
508
|
+
return await this.handleMerge(args);
|
|
509
|
+
case 'lifecycle': {
|
|
510
|
+
const { project } = args;
|
|
511
|
+
const result = await forceLifecycleMaintenance(project);
|
|
512
|
+
return this.jsonResponse({
|
|
513
|
+
success: true,
|
|
514
|
+
message: 'Lifecycle maintenance completed',
|
|
515
|
+
stats: result,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
case 'summarize_session': {
|
|
519
|
+
const { conversationId, type } = args;
|
|
520
|
+
if (!conversationId || !type) {
|
|
521
|
+
throw new McpError(ErrorCode.InvalidParams, 'conversationId and type are required');
|
|
522
|
+
}
|
|
523
|
+
const result = await summarizeSession(conversationId, type);
|
|
524
|
+
return this.jsonResponse({
|
|
525
|
+
success: true,
|
|
526
|
+
summaryId: result.summaryId,
|
|
527
|
+
tokensSaved: result.tokensSaved,
|
|
528
|
+
message: `Session summarized with type: ${type}`,
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
case 'protect_memory': {
|
|
532
|
+
const { memoryId, reason } = args;
|
|
533
|
+
if (!memoryId || !reason) {
|
|
534
|
+
throw new McpError(ErrorCode.InvalidParams, 'memoryId and reason are required');
|
|
535
|
+
}
|
|
536
|
+
await protectMemory(memoryId, reason);
|
|
537
|
+
return this.jsonResponse({
|
|
538
|
+
success: true,
|
|
539
|
+
memoryId,
|
|
540
|
+
message: 'Memory protected from eviction',
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
case 'pin_memory': {
|
|
544
|
+
const { memoryId } = args;
|
|
545
|
+
if (!memoryId) {
|
|
546
|
+
throw new McpError(ErrorCode.InvalidParams, 'memoryId is required');
|
|
547
|
+
}
|
|
548
|
+
await pinMemory(memoryId);
|
|
549
|
+
return this.jsonResponse({
|
|
550
|
+
success: true,
|
|
551
|
+
memoryId,
|
|
552
|
+
message: 'Memory pinned for auto-injection',
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
case 'get_related': {
|
|
556
|
+
const { memoryId, limit } = args;
|
|
557
|
+
if (!memoryId) {
|
|
558
|
+
throw new McpError(ErrorCode.InvalidParams, 'memoryId is required');
|
|
559
|
+
}
|
|
560
|
+
const related = await getRelatedMemories(memoryId, limit || 10);
|
|
561
|
+
return this.jsonResponse({
|
|
562
|
+
success: true,
|
|
563
|
+
memoryId,
|
|
564
|
+
relatedCount: related.length,
|
|
565
|
+
memories: related,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
case 'qmd_search': {
|
|
569
|
+
if (typeof args.query !== 'string' || !args.query) {
|
|
570
|
+
throw new McpError(ErrorCode.InvalidParams, 'query is required');
|
|
571
|
+
}
|
|
572
|
+
try {
|
|
573
|
+
const available = await isQMDAvailable();
|
|
574
|
+
if (!available) {
|
|
575
|
+
return this.jsonResponse({
|
|
576
|
+
ok: true,
|
|
577
|
+
qmdAvailable: false,
|
|
578
|
+
message: 'QMD is not installed. Install with: bun install -g qmd',
|
|
579
|
+
fallback: 'Using standard Squish search',
|
|
580
|
+
data: await searchMemories(args)
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
const results = await searchWithQMD({
|
|
584
|
+
query: args.query,
|
|
585
|
+
type: args.type,
|
|
586
|
+
limit: args.limit || 10,
|
|
587
|
+
useHybrid: args.useHybrid ?? true,
|
|
588
|
+
collection: args.collection
|
|
589
|
+
});
|
|
590
|
+
return this.jsonResponse({
|
|
591
|
+
ok: true,
|
|
592
|
+
qmdAvailable: true,
|
|
593
|
+
data: results
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
catch (dbError) {
|
|
597
|
+
if (isDatabaseUnavailableError(dbError)) {
|
|
598
|
+
throw new McpError(ErrorCode.InternalError, 'Database unavailable - search disabled');
|
|
599
|
+
}
|
|
600
|
+
throw dbError;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
default:
|
|
604
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
if (error instanceof McpError)
|
|
609
|
+
throw error;
|
|
610
|
+
logger.error('Tool error', error);
|
|
611
|
+
throw new McpError(ErrorCode.InternalError, `Tool '${name}' failed`);
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
this.server.onerror = (e) => logger.error('MCP Server error', e);
|
|
615
|
+
process.on('SIGINT', () => this.shutdown());
|
|
616
|
+
process.on('SIGTERM', () => this.shutdown());
|
|
617
|
+
}
|
|
618
|
+
jsonResponse(payload) {
|
|
619
|
+
return {
|
|
620
|
+
content: [{
|
|
621
|
+
type: 'text',
|
|
622
|
+
text: JSON.stringify(payload, null, 2)
|
|
623
|
+
}]
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
async handleCoreMemory(args) {
|
|
627
|
+
const action = args.action;
|
|
628
|
+
if (!args.projectId) {
|
|
629
|
+
throw new McpError(ErrorCode.InvalidParams, 'projectId is required');
|
|
630
|
+
}
|
|
631
|
+
const projectId = String(args.projectId);
|
|
632
|
+
try {
|
|
633
|
+
await initializeCoreMemory(projectId);
|
|
634
|
+
if (action === 'view') {
|
|
635
|
+
const content = await getCoreMemory(projectId);
|
|
636
|
+
const stats = await getCoreMemoryStats(projectId);
|
|
637
|
+
return this.jsonResponse({ ok: true, action: 'view', content, stats });
|
|
638
|
+
}
|
|
639
|
+
if (action === 'edit') {
|
|
640
|
+
if (!args.section || typeof args.content !== 'string') {
|
|
641
|
+
throw new McpError(ErrorCode.InvalidParams, 'section and content are required for edit action');
|
|
642
|
+
}
|
|
643
|
+
const result = await editCoreMemorySection(projectId, args.section, String(args.content));
|
|
644
|
+
if (!result.success) {
|
|
645
|
+
throw new McpError(ErrorCode.InvalidParams, result.message || 'Edit failed');
|
|
646
|
+
}
|
|
647
|
+
return this.jsonResponse({ ok: true, action: 'edit', ...result });
|
|
648
|
+
}
|
|
649
|
+
if (action === 'append') {
|
|
650
|
+
if (!args.section || typeof args.text !== 'string') {
|
|
651
|
+
throw new McpError(ErrorCode.InvalidParams, 'section and text are required for append action');
|
|
652
|
+
}
|
|
653
|
+
const result = await appendCoreMemorySection(projectId, args.section, String(args.text));
|
|
654
|
+
if (!result.success) {
|
|
655
|
+
throw new McpError(ErrorCode.InvalidParams, result.message || 'Append failed');
|
|
656
|
+
}
|
|
657
|
+
return this.jsonResponse({ ok: true, action: 'append', ...result });
|
|
658
|
+
}
|
|
659
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown core_memory action: ${action}`);
|
|
660
|
+
}
|
|
661
|
+
catch (error) {
|
|
662
|
+
if (error instanceof McpError)
|
|
663
|
+
throw error;
|
|
664
|
+
throw new McpError(ErrorCode.InternalError, `Core memory failed: ${error.message}`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
async handleContextPaging(args) {
|
|
668
|
+
const action = args.action;
|
|
669
|
+
if (!args.sessionId) {
|
|
670
|
+
throw new McpError(ErrorCode.InvalidParams, 'sessionId is required');
|
|
671
|
+
}
|
|
672
|
+
const sessionId = String(args.sessionId);
|
|
673
|
+
try {
|
|
674
|
+
if (action === 'load') {
|
|
675
|
+
if (!args.memoryId) {
|
|
676
|
+
throw new McpError(ErrorCode.InvalidParams, 'memoryId is required for load action');
|
|
677
|
+
}
|
|
678
|
+
const result = await loadMemoryToContext(sessionId, String(args.memoryId));
|
|
679
|
+
if (!result.success) {
|
|
680
|
+
throw new McpError(ErrorCode.InvalidParams, result.message || 'Load failed');
|
|
681
|
+
}
|
|
682
|
+
return this.jsonResponse({ ok: true, action: 'load', ...result });
|
|
683
|
+
}
|
|
684
|
+
if (action === 'evict') {
|
|
685
|
+
if (!args.memoryId) {
|
|
686
|
+
throw new McpError(ErrorCode.InvalidParams, 'memoryId is required for evict action');
|
|
687
|
+
}
|
|
688
|
+
const result = await evictMemoryFromContext(sessionId, String(args.memoryId));
|
|
689
|
+
if (!result.success) {
|
|
690
|
+
throw new McpError(ErrorCode.InvalidParams, result.message || 'Evict failed');
|
|
691
|
+
}
|
|
692
|
+
return this.jsonResponse({ ok: true, action: 'evict', ...result });
|
|
693
|
+
}
|
|
694
|
+
if (action === 'view') {
|
|
695
|
+
const result = await viewLoadedMemories(sessionId);
|
|
696
|
+
return this.jsonResponse({ ok: true, action: 'view', ...result });
|
|
697
|
+
}
|
|
698
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown context_paging action: ${action}`);
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
if (error instanceof McpError)
|
|
702
|
+
throw error;
|
|
703
|
+
throw new McpError(ErrorCode.InternalError, `Context paging failed: ${error.message}`);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
async handleMerge(args) {
|
|
707
|
+
const action = args.action;
|
|
708
|
+
try {
|
|
709
|
+
if (action === 'detect') {
|
|
710
|
+
return this.jsonResponse(await handleDetectDuplicates(args));
|
|
711
|
+
}
|
|
712
|
+
if (action === 'list') {
|
|
713
|
+
return this.jsonResponse(await handleListProposals(args));
|
|
714
|
+
}
|
|
715
|
+
if (action === 'preview') {
|
|
716
|
+
return this.jsonResponse(await handlePreviewMerge(args));
|
|
717
|
+
}
|
|
718
|
+
if (action === 'stats') {
|
|
719
|
+
return this.jsonResponse(await handleGetMergeStats(args));
|
|
720
|
+
}
|
|
721
|
+
if (action === 'approve') {
|
|
722
|
+
return this.jsonResponse(await handleApproveMerge(args));
|
|
723
|
+
}
|
|
724
|
+
if (action === 'reject') {
|
|
725
|
+
return this.jsonResponse(await handleRejectMerge(args));
|
|
726
|
+
}
|
|
727
|
+
if (action === 'reverse') {
|
|
728
|
+
return this.jsonResponse(await handleReverseMerge(args));
|
|
729
|
+
}
|
|
730
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown merge action: ${action}`);
|
|
731
|
+
}
|
|
732
|
+
catch (error) {
|
|
733
|
+
if (error instanceof McpError)
|
|
734
|
+
throw error;
|
|
735
|
+
throw new McpError(ErrorCode.InternalError, `Merge operation failed: ${error.message}`);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
async shutdown() {
|
|
739
|
+
await closeCache();
|
|
740
|
+
process.exit(0);
|
|
741
|
+
}
|
|
742
|
+
async health() {
|
|
743
|
+
let dbOk = false;
|
|
744
|
+
let dbStatus = 'ok';
|
|
745
|
+
try {
|
|
746
|
+
dbOk = await checkDatabaseHealth();
|
|
747
|
+
dbStatus = dbOk ? 'ok' : 'unavailable';
|
|
748
|
+
}
|
|
749
|
+
catch (error) {
|
|
750
|
+
if (isDatabaseUnavailableError(error)) {
|
|
751
|
+
dbStatus = 'unavailable';
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
dbStatus = 'error';
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const redisOk = await checkRedisHealth();
|
|
758
|
+
const overallStatus = determineOverallStatus(dbStatus, redisOk);
|
|
759
|
+
return this.jsonResponse({
|
|
760
|
+
version: VERSION,
|
|
761
|
+
mode: config.isTeamMode ? 'team' : 'local',
|
|
762
|
+
database: config.isTeamMode ? 'postgresql' : 'sqlite',
|
|
763
|
+
cache: config.redisEnabled ? 'redis' : 'memory',
|
|
764
|
+
embeddingsProvider: config.embeddingsProvider,
|
|
765
|
+
status: overallStatus,
|
|
766
|
+
checks: {
|
|
767
|
+
database: dbStatus,
|
|
768
|
+
cache: redisOk ? 'ok' : 'error'
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
async run() {
|
|
773
|
+
const transport = new StdioServerTransport();
|
|
774
|
+
await this.server.connect(transport);
|
|
775
|
+
logger.info(`v${VERSION}`);
|
|
776
|
+
// Start web UI server in background
|
|
777
|
+
startWebServer();
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
new Squish().run().catch((e) => {
|
|
781
|
+
logger.error('Fatal error', e);
|
|
782
|
+
process.exit(1);
|
|
783
|
+
});
|
|
784
|
+
//# sourceMappingURL=index.js.map
|