squish-memory 1.0.0 → 1.0.2

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.
Files changed (300) hide show
  1. package/.env.mcp.example +18 -11
  2. package/README.md +59 -24
  3. package/bin/squish-add.mjs +32 -0
  4. package/bin/squish-rm.mjs +21 -0
  5. package/config/plugin-manifest.json +1 -1
  6. package/config/settings.json +51 -0
  7. package/dist/api/web/web.js +479 -452
  8. package/dist/commands/mcp-server.js +7 -3
  9. package/dist/config.d.ts +10 -10
  10. package/dist/config.js +78 -23
  11. package/dist/core/embeddings.d.ts +1 -1
  12. package/dist/core/embeddings.js +10 -67
  13. package/dist/core/local-embeddings.d.ts +3 -11
  14. package/dist/core/local-embeddings.js +2 -76
  15. package/dist/core/mcp/server.js +27 -1
  16. package/dist/core/mcp/types.d.ts +4 -4
  17. package/dist/core/memory/context-collector.js +3 -2
  18. package/dist/core/memory/feedback-tracker.js +10 -6
  19. package/dist/core/memory/hybrid-search.js +32 -32
  20. package/dist/core/memory/memories.js +55 -52
  21. package/dist/core/memory/query-rewriter.js +9 -9
  22. package/dist/core/memory/stats.js +5 -5
  23. package/dist/core/namespaces/index.js +20 -11
  24. package/dist/core/scheduler/cron-scheduler.js +78 -20
  25. package/dist/core/scheduler/job-runner.js +8 -5
  26. package/dist/core/search/conversations.js +33 -33
  27. package/dist/core/session-hooks/self-iteration-job.js +43 -39
  28. package/dist/core/session-hooks/session-hooks.js +6 -3
  29. package/dist/core/tracing/collector.js +25 -13
  30. package/dist/db/adapter.d.ts +6 -1
  31. package/dist/db/adapter.js +122 -126
  32. package/dist/db/bootstrap.js +622 -548
  33. package/dist/db/index.d.ts +5 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +195 -49
  36. package/generated/mcp/manifest.json +23 -23
  37. package/package.json +72 -59
  38. package/scripts/install-interactive.mjs +7 -4
  39. package/skills/memory-guide/SKILL.md +94 -18
  40. package/skills/squish-cli/SKILL.md +61 -21
  41. package/skills/squish-mcp/SKILL.md +46 -2
  42. package/skills/squish-memory/SKILL.md +30 -16
  43. package/dist/algorithms/analytics/token-estimator.d.ts.map +0 -1
  44. package/dist/algorithms/analytics/token-estimator.js.map +0 -1
  45. package/dist/algorithms/detection/hash-filters.d.ts.map +0 -1
  46. package/dist/algorithms/detection/hash-filters.js.map +0 -1
  47. package/dist/algorithms/detection/semantic-ranker.d.ts.map +0 -1
  48. package/dist/algorithms/detection/semantic-ranker.js.map +0 -1
  49. package/dist/algorithms/detection/two-stage-detector.d.ts.map +0 -1
  50. package/dist/algorithms/detection/two-stage-detector.js.map +0 -1
  51. package/dist/algorithms/handlers/approve-merge.d.ts.map +0 -1
  52. package/dist/algorithms/handlers/approve-merge.js.map +0 -1
  53. package/dist/algorithms/handlers/detect-duplicates.d.ts.map +0 -1
  54. package/dist/algorithms/handlers/detect-duplicates.js.map +0 -1
  55. package/dist/algorithms/handlers/get-stats.d.ts.map +0 -1
  56. package/dist/algorithms/handlers/get-stats.js.map +0 -1
  57. package/dist/algorithms/handlers/list-proposals.d.ts.map +0 -1
  58. package/dist/algorithms/handlers/list-proposals.js.map +0 -1
  59. package/dist/algorithms/handlers/preview-merge.d.ts.map +0 -1
  60. package/dist/algorithms/handlers/preview-merge.js.map +0 -1
  61. package/dist/algorithms/handlers/reject-merge.d.ts.map +0 -1
  62. package/dist/algorithms/handlers/reject-merge.js.map +0 -1
  63. package/dist/algorithms/handlers/reverse-merge.d.ts.map +0 -1
  64. package/dist/algorithms/handlers/reverse-merge.js.map +0 -1
  65. package/dist/algorithms/safety/safety-checks.d.ts.map +0 -1
  66. package/dist/algorithms/safety/safety-checks.js.map +0 -1
  67. package/dist/algorithms/strategies/merge-strategies.d.ts.map +0 -1
  68. package/dist/algorithms/strategies/merge-strategies.js.map +0 -1
  69. package/dist/algorithms/utils/response-builder.d.ts.map +0 -1
  70. package/dist/algorithms/utils/response-builder.js.map +0 -1
  71. package/dist/api/web/index.d.ts.map +0 -1
  72. package/dist/api/web/index.js.map +0 -1
  73. package/dist/api/web/web-server.d.ts.map +0 -1
  74. package/dist/api/web/web-server.js.map +0 -1
  75. package/dist/api/web/web.d.ts.map +0 -1
  76. package/dist/api/web/web.js.map +0 -1
  77. package/dist/commands/managed-sync.d.ts.map +0 -1
  78. package/dist/commands/managed-sync.js.map +0 -1
  79. package/dist/commands/mcp-server.d.ts.map +0 -1
  80. package/dist/commands/mcp-server.js.map +0 -1
  81. package/dist/config.d.ts.map +0 -1
  82. package/dist/config.js.map +0 -1
  83. package/dist/core/agent-memory.d.ts.map +0 -1
  84. package/dist/core/agent-memory.js.map +0 -1
  85. package/dist/core/associations.d.ts.map +0 -1
  86. package/dist/core/associations.js.map +0 -1
  87. package/dist/core/cache.d.ts.map +0 -1
  88. package/dist/core/cache.js.map +0 -1
  89. package/dist/core/consolidation.d.ts.map +0 -1
  90. package/dist/core/consolidation.js.map +0 -1
  91. package/dist/core/context-paging.d.ts.map +0 -1
  92. package/dist/core/context-paging.js.map +0 -1
  93. package/dist/core/context.d.ts.map +0 -1
  94. package/dist/core/context.js.map +0 -1
  95. package/dist/core/core-memory.d.ts.map +0 -1
  96. package/dist/core/core-memory.js.map +0 -1
  97. package/dist/core/database.d.ts.map +0 -1
  98. package/dist/core/database.js.map +0 -1
  99. package/dist/core/embeddings/google-multimodal.d.ts.map +0 -1
  100. package/dist/core/embeddings/google-multimodal.js.map +0 -1
  101. package/dist/core/embeddings/qmd-client.d.ts.map +0 -1
  102. package/dist/core/embeddings/qmd-client.js.map +0 -1
  103. package/dist/core/embeddings.d.ts.map +0 -1
  104. package/dist/core/embeddings.js.map +0 -1
  105. package/dist/core/governance.d.ts.map +0 -1
  106. package/dist/core/governance.js.map +0 -1
  107. package/dist/core/index.d.ts.map +0 -1
  108. package/dist/core/index.js.map +0 -1
  109. package/dist/core/layers/generator.d.ts.map +0 -1
  110. package/dist/core/layers/generator.js.map +0 -1
  111. package/dist/core/lifecycle.d.ts.map +0 -1
  112. package/dist/core/lifecycle.js.map +0 -1
  113. package/dist/core/local-embeddings.d.ts.map +0 -1
  114. package/dist/core/local-embeddings.js.map +0 -1
  115. package/dist/core/logger.d.ts.map +0 -1
  116. package/dist/core/logger.js.map +0 -1
  117. package/dist/core/mcp/client.d.ts.map +0 -1
  118. package/dist/core/mcp/client.js.map +0 -1
  119. package/dist/core/mcp/index.d.ts.map +0 -1
  120. package/dist/core/mcp/index.js.map +0 -1
  121. package/dist/core/mcp/server.d.ts.map +0 -1
  122. package/dist/core/mcp/server.js.map +0 -1
  123. package/dist/core/mcp/standalone-server.d.ts.map +0 -1
  124. package/dist/core/mcp/standalone-server.js.map +0 -1
  125. package/dist/core/mcp/tools.d.ts.map +0 -1
  126. package/dist/core/mcp/tools.js.map +0 -1
  127. package/dist/core/mcp/types.d.ts.map +0 -1
  128. package/dist/core/mcp/types.js.map +0 -1
  129. package/dist/core/memory/bridge-discovery.d.ts.map +0 -1
  130. package/dist/core/memory/bridge-discovery.js.map +0 -1
  131. package/dist/core/memory/categorizer.d.ts.map +0 -1
  132. package/dist/core/memory/categorizer.js.map +0 -1
  133. package/dist/core/memory/conflict-detector.d.ts.map +0 -1
  134. package/dist/core/memory/conflict-detector.js.map +0 -1
  135. package/dist/core/memory/consolidation.d.ts.map +0 -1
  136. package/dist/core/memory/consolidation.js.map +0 -1
  137. package/dist/core/memory/context-collector.d.ts.map +0 -1
  138. package/dist/core/memory/context-collector.js.map +0 -1
  139. package/dist/core/memory/contradiction-resolver.d.ts.map +0 -1
  140. package/dist/core/memory/contradiction-resolver.js.map +0 -1
  141. package/dist/core/memory/edit-workflow.d.ts.map +0 -1
  142. package/dist/core/memory/edit-workflow.js.map +0 -1
  143. package/dist/core/memory/entity-extractor.d.ts.map +0 -1
  144. package/dist/core/memory/entity-extractor.js.map +0 -1
  145. package/dist/core/memory/entity-resolver.d.ts.map +0 -1
  146. package/dist/core/memory/entity-resolver.js.map +0 -1
  147. package/dist/core/memory/fact-extractor.d.ts.map +0 -1
  148. package/dist/core/memory/fact-extractor.js.map +0 -1
  149. package/dist/core/memory/feedback-tracker.d.ts.map +0 -1
  150. package/dist/core/memory/feedback-tracker.js.map +0 -1
  151. package/dist/core/memory/hybrid-retrieval.d.ts.map +0 -1
  152. package/dist/core/memory/hybrid-retrieval.js.map +0 -1
  153. package/dist/core/memory/hybrid-scorer.d.ts.map +0 -1
  154. package/dist/core/memory/hybrid-scorer.js.map +0 -1
  155. package/dist/core/memory/hybrid-search.d.ts.map +0 -1
  156. package/dist/core/memory/hybrid-search.js.map +0 -1
  157. package/dist/core/memory/importance.d.ts.map +0 -1
  158. package/dist/core/memory/importance.js.map +0 -1
  159. package/dist/core/memory/index.d.ts.map +0 -1
  160. package/dist/core/memory/index.js.map +0 -1
  161. package/dist/core/memory/memories.d.ts.map +0 -1
  162. package/dist/core/memory/memories.js.map +0 -1
  163. package/dist/core/memory/memory-manager.d.ts.map +0 -1
  164. package/dist/core/memory/memory-manager.js.map +0 -1
  165. package/dist/core/memory/progressive-disclosure.d.ts.map +0 -1
  166. package/dist/core/memory/progressive-disclosure.js.map +0 -1
  167. package/dist/core/memory/query-processor.d.ts.map +0 -1
  168. package/dist/core/memory/query-processor.js.map +0 -1
  169. package/dist/core/memory/query-rewriter.d.ts.map +0 -1
  170. package/dist/core/memory/query-rewriter.js.map +0 -1
  171. package/dist/core/memory/response-analyzer.d.ts.map +0 -1
  172. package/dist/core/memory/response-analyzer.js.map +0 -1
  173. package/dist/core/memory/serialization.d.ts.map +0 -1
  174. package/dist/core/memory/serialization.js.map +0 -1
  175. package/dist/core/memory/stats.d.ts.map +0 -1
  176. package/dist/core/memory/stats.js.map +0 -1
  177. package/dist/core/memory/telemetry.d.ts.map +0 -1
  178. package/dist/core/memory/telemetry.js.map +0 -1
  179. package/dist/core/memory/temporal-facts.d.ts.map +0 -1
  180. package/dist/core/memory/temporal-facts.js.map +0 -1
  181. package/dist/core/memory/temporal-parser.d.ts.map +0 -1
  182. package/dist/core/memory/temporal-parser.js.map +0 -1
  183. package/dist/core/memory/trigger-detector.d.ts.map +0 -1
  184. package/dist/core/memory/trigger-detector.js.map +0 -1
  185. package/dist/core/memory/write-gate.d.ts.map +0 -1
  186. package/dist/core/memory/write-gate.js.map +0 -1
  187. package/dist/core/namespaces/index.d.ts.map +0 -1
  188. package/dist/core/namespaces/index.js.map +0 -1
  189. package/dist/core/namespaces/uri-parser.d.ts.map +0 -1
  190. package/dist/core/namespaces/uri-parser.js.map +0 -1
  191. package/dist/core/observations.d.ts.map +0 -1
  192. package/dist/core/observations.js.map +0 -1
  193. package/dist/core/privacy.d.ts.map +0 -1
  194. package/dist/core/privacy.js.map +0 -1
  195. package/dist/core/projects.d.ts.map +0 -1
  196. package/dist/core/projects.js.map +0 -1
  197. package/dist/core/redis.d.ts.map +0 -1
  198. package/dist/core/redis.js.map +0 -1
  199. package/dist/core/requirements.d.ts.map +0 -1
  200. package/dist/core/requirements.js.map +0 -1
  201. package/dist/core/scheduler/cron-scheduler.d.ts.map +0 -1
  202. package/dist/core/scheduler/cron-scheduler.js.map +0 -1
  203. package/dist/core/scheduler/heartbeat.d.ts.map +0 -1
  204. package/dist/core/scheduler/heartbeat.js.map +0 -1
  205. package/dist/core/scheduler/index.d.ts.map +0 -1
  206. package/dist/core/scheduler/index.js.map +0 -1
  207. package/dist/core/scheduler/job-runner.d.ts.map +0 -1
  208. package/dist/core/scheduler/job-runner.js.map +0 -1
  209. package/dist/core/search/conversations.d.ts.map +0 -1
  210. package/dist/core/search/conversations.js.map +0 -1
  211. package/dist/core/search/entities.d.ts.map +0 -1
  212. package/dist/core/search/entities.js.map +0 -1
  213. package/dist/core/search/folder-context.d.ts.map +0 -1
  214. package/dist/core/search/folder-context.js.map +0 -1
  215. package/dist/core/search/index.d.ts.map +0 -1
  216. package/dist/core/search/index.js.map +0 -1
  217. package/dist/core/search/qmd-search.d.ts.map +0 -1
  218. package/dist/core/search/qmd-search.js.map +0 -1
  219. package/dist/core/secret-detector.d.ts.map +0 -1
  220. package/dist/core/secret-detector.js.map +0 -1
  221. package/dist/core/session/auto-load.d.ts.map +0 -1
  222. package/dist/core/session/auto-load.js.map +0 -1
  223. package/dist/core/session/index.d.ts.map +0 -1
  224. package/dist/core/session/index.js.map +0 -1
  225. package/dist/core/session/types.d.ts.map +0 -1
  226. package/dist/core/session/types.js.map +0 -1
  227. package/dist/core/session-hooks/self-iteration-job.d.ts.map +0 -1
  228. package/dist/core/session-hooks/self-iteration-job.js.map +0 -1
  229. package/dist/core/session-hooks/session-hooks.d.ts.map +0 -1
  230. package/dist/core/session-hooks/session-hooks.js.map +0 -1
  231. package/dist/core/snapshots/cleanup.d.ts.map +0 -1
  232. package/dist/core/snapshots/cleanup.js.map +0 -1
  233. package/dist/core/snapshots/comparison.d.ts.map +0 -1
  234. package/dist/core/snapshots/comparison.js.map +0 -1
  235. package/dist/core/snapshots/creation.d.ts.map +0 -1
  236. package/dist/core/snapshots/creation.js.map +0 -1
  237. package/dist/core/snapshots/retrieval.d.ts.map +0 -1
  238. package/dist/core/snapshots/retrieval.js.map +0 -1
  239. package/dist/core/snapshots/stats.d.ts.map +0 -1
  240. package/dist/core/snapshots/stats.js.map +0 -1
  241. package/dist/core/snapshots.d.ts.map +0 -1
  242. package/dist/core/snapshots.js.map +0 -1
  243. package/dist/core/summarization/cleanup.d.ts.map +0 -1
  244. package/dist/core/summarization/cleanup.js.map +0 -1
  245. package/dist/core/summarization/queries.d.ts.map +0 -1
  246. package/dist/core/summarization/queries.js.map +0 -1
  247. package/dist/core/summarization/stats.d.ts.map +0 -1
  248. package/dist/core/summarization/stats.js.map +0 -1
  249. package/dist/core/summarization/strategies.d.ts.map +0 -1
  250. package/dist/core/summarization/strategies.js.map +0 -1
  251. package/dist/core/summarization.d.ts.map +0 -1
  252. package/dist/core/summarization.js.map +0 -1
  253. package/dist/core/sync/qmd-sync.d.ts.map +0 -1
  254. package/dist/core/sync/qmd-sync.js.map +0 -1
  255. package/dist/core/temporal-facts.d.ts.map +0 -1
  256. package/dist/core/temporal-facts.js.map +0 -1
  257. package/dist/core/tracing/collector.d.ts.map +0 -1
  258. package/dist/core/tracing/collector.js.map +0 -1
  259. package/dist/core/tracing/visualizer.d.ts.map +0 -1
  260. package/dist/core/tracing/visualizer.js.map +0 -1
  261. package/dist/core/utils/cleanup-operations.d.ts.map +0 -1
  262. package/dist/core/utils/cleanup-operations.js.map +0 -1
  263. package/dist/core/utils/content-extraction.d.ts.map +0 -1
  264. package/dist/core/utils/content-extraction.js.map +0 -1
  265. package/dist/core/utils/filter-builder.d.ts.map +0 -1
  266. package/dist/core/utils/filter-builder.js.map +0 -1
  267. package/dist/core/utils/history-traversal.d.ts.map +0 -1
  268. package/dist/core/utils/history-traversal.js.map +0 -1
  269. package/dist/core/utils/memory-operations.d.ts.map +0 -1
  270. package/dist/core/utils/memory-operations.js.map +0 -1
  271. package/dist/core/utils/query-operations.d.ts.map +0 -1
  272. package/dist/core/utils/query-operations.js.map +0 -1
  273. package/dist/core/utils/summarization-helpers.d.ts.map +0 -1
  274. package/dist/core/utils/summarization-helpers.js.map +0 -1
  275. package/dist/core/utils/temporal-queries.d.ts.map +0 -1
  276. package/dist/core/utils/temporal-queries.js.map +0 -1
  277. package/dist/core/utils/version-management.d.ts.map +0 -1
  278. package/dist/core/utils/version-management.js.map +0 -1
  279. package/dist/core/utils.d.ts.map +0 -1
  280. package/dist/core/utils.js.map +0 -1
  281. package/dist/core/worker.d.ts.map +0 -1
  282. package/dist/core/worker.js.map +0 -1
  283. package/dist/db/adapter.d.ts.map +0 -1
  284. package/dist/db/adapter.js.map +0 -1
  285. package/dist/db/bootstrap.d.ts.map +0 -1
  286. package/dist/db/bootstrap.js.map +0 -1
  287. package/dist/db/index.d.ts.map +0 -1
  288. package/dist/db/index.js.map +0 -1
  289. package/dist/db/schema.d.ts.map +0 -1
  290. package/dist/db/schema.js.map +0 -1
  291. package/dist/drizzle/schema-sqlite.d.ts.map +0 -1
  292. package/dist/drizzle/schema-sqlite.js.map +0 -1
  293. package/dist/drizzle/schema.d.ts.map +0 -1
  294. package/dist/drizzle/schema.js.map +0 -1
  295. package/dist/index.d.ts.map +0 -1
  296. package/dist/index.js.map +0 -1
  297. package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts.map +0 -1
  298. package/packages/plugin-claude-code/dist/plugin-wrapper.js.map +0 -1
  299. package/packages/plugin-openclaw/dist/index.d.ts.map +0 -1
  300. package/packages/plugin-openclaw/dist/index.js.map +0 -1
@@ -21,7 +21,7 @@ import { getDb } from "../db/index.js";
21
21
  import { getSchema } from "../db/schema.js";
22
22
  import { eq } from "drizzle-orm";
23
23
  const SERVER_NAME = "squish-memory";
24
- const SERVER_VERSION = "1.0.0";
24
+ const SERVER_VERSION = "1.0.2";
25
25
  function parseArgs() {
26
26
  const args = process.argv.slice(2);
27
27
  let mode = "stdio";
@@ -116,7 +116,9 @@ function createSquishServer() {
116
116
  }, async ({ memoryId }) => {
117
117
  const db = await getDb();
118
118
  const schema = await getSchema();
119
- const result = await db.delete(schema.memories).where(eq(schema.memories.id, memoryId));
119
+ // Cast to any to handle Drizzle ORM union type issue
120
+ const sqliteDb = db;
121
+ const result = await sqliteDb.delete(schema.memories).where(eq(schema.memories.id, memoryId));
120
122
  return { content: [{ type: "text", text: `Memory deleted: ${memoryId}` }] };
121
123
  }))
122
124
  toolCount++;
@@ -141,7 +143,9 @@ function createSquishServer() {
141
143
  if (Object.keys(updates).length === 0) {
142
144
  return { content: [{ type: "text", text: "No updates provided" }], isError: true };
143
145
  }
144
- await db.update(schema.memories).set(updates).where(eq(schema.memories.id, memoryId));
146
+ // Cast to any to handle Drizzle ORM union type issue
147
+ const sqliteDb2 = db;
148
+ await sqliteDb2.update(schema.memories).set(updates).where(eq(schema.memories.id, memoryId));
145
149
  return { content: [{ type: "text", text: `Memory updated: ${memoryId}` }] };
146
150
  }))
147
151
  toolCount++;
package/dist/config.d.ts CHANGED
@@ -6,12 +6,16 @@ export declare const config: {
6
6
  dataDir: string;
7
7
  mcpServerPort: number;
8
8
  mcpServerEnabled: boolean;
9
- embeddingsProvider: "openai" | "ollama" | "local" | "none" | "qmd" | "hybrid" | "google-multimodal" | "auto";
9
+ embeddingsProvider: "local" | "openai" | "ollama" | "google" | "none" | "auto";
10
10
  openAiApiKey: string;
11
- openAiApiUrl: string;
12
- openAiEmbeddingModel: string;
13
- ollamaUrl: string;
14
- ollamaEmbeddingModel: string;
11
+ openAiApiUrl: any;
12
+ openAiEmbeddingModel: any;
13
+ googleCloudApiKey: string;
14
+ googleCloudProject: string;
15
+ googleCloudLocation: string;
16
+ googleEmbeddingModel: any;
17
+ ollamaUrl: any;
18
+ ollamaEmbeddingModel: any;
15
19
  lifecycleEnabled: boolean;
16
20
  lifecycleInterval: number;
17
21
  summarizationEnabled: boolean;
@@ -26,10 +30,6 @@ export declare const config: {
26
30
  qmdCollectionsPath: string;
27
31
  qmdFallbackMode: "qmd-only" | "cloud-first" | "hybrid" | "local-only";
28
32
  qmdCollectionMapping: any;
29
- googleCloudApiKey: string;
30
- googleCloudProject: string;
31
- googleCloudLocation: string;
32
- multimodalEmbeddingsEnabled: boolean;
33
33
  managedMode: boolean;
34
34
  managedApiUrl: string;
35
35
  managedApiKey: string;
@@ -53,7 +53,7 @@ export declare const config: {
53
53
  embeddingsRetryDelayMs: number;
54
54
  openAiTimeoutMs: number;
55
55
  ollamaTimeoutMs: number;
56
- googleMultimodalTimeoutMs: number;
56
+ googleTimeoutMs: number;
57
57
  };
58
58
  export default config;
59
59
  //# sourceMappingURL=config.d.ts.map
package/dist/config.js CHANGED
@@ -1,5 +1,9 @@
1
1
  import { join } from 'path';
2
- import { mkdirSync, existsSync } from 'fs';
2
+ import { mkdirSync, existsSync, readFileSync } from 'fs';
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname } from 'path';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
3
7
  export function getDataDir() {
4
8
  const projectRoot = process.env.CLAUDE_WORKING_DIRECTORY || process.cwd();
5
9
  const dir = process.env.SQUISH_DATA_DIR || join(projectRoot, '.squish');
@@ -7,21 +11,58 @@ export function getDataDir() {
7
11
  mkdirSync(dir, { recursive: true });
8
12
  return dir;
9
13
  }
14
+ // Load settings from config/settings.json
15
+ function loadSettings() {
16
+ const settingsPath = join(__dirname, 'config', 'settings.json');
17
+ try {
18
+ if (existsSync(settingsPath)) {
19
+ const content = readFileSync(settingsPath, 'utf-8');
20
+ return JSON.parse(content);
21
+ }
22
+ }
23
+ catch (error) {
24
+ console.warn('Failed to load settings.json, using defaults');
25
+ }
26
+ return {};
27
+ }
28
+ const settings = loadSettings();
29
+ // Helper to get env var or settings value
30
+ function getConfig(path, envVar, defaultValue) {
31
+ // Priority 1: Environment variable
32
+ if (envVar && process.env[envVar]) {
33
+ return process.env[envVar];
34
+ }
35
+ // Priority 2: Settings file
36
+ const keys = path.split('.');
37
+ let value = settings;
38
+ for (const key of keys) {
39
+ if (value && typeof value === 'object' && key in value) {
40
+ value = value[key];
41
+ }
42
+ else {
43
+ value = undefined;
44
+ break;
45
+ }
46
+ }
47
+ if (value !== undefined) {
48
+ return value;
49
+ }
50
+ // Priority 3: Default value
51
+ return defaultValue;
52
+ }
10
53
  const isTeamMode = !!process.env.DATABASE_URL?.startsWith('postgres');
11
54
  const isManagedMode = process.env.SQUISH_MANAGED_MODE === 'true';
12
- const openAiApiKey = process.env.SQUISH_OPENAI_API_KEY || process.env.OPENAI_API_KEY || '';
13
55
  // Embeddings providers:
14
56
  // - openai: OpenAI API (requires API key)
15
57
  // - ollama: Local Ollama server (requires nomic-embed-text)
16
58
  // - local: TF-IDF offline (no dependencies)
17
59
  // - none: Disable embeddings (stub)
18
- // - qmd: QMD (requires qmd CLI installed)
19
- // - hybrid: Try multiple providers with fallbacks
20
- // - google-multimodal: Google Cloud multimodal embeddings
21
- const VALID_PROVIDERS = new Set(['openai', 'ollama', 'local', 'none', 'qmd', 'hybrid', 'google-multimodal', 'auto']);
60
+ // - google: Google Cloud embeddings
61
+ // - auto: Smart fallback (cloud if available, local fallback)
62
+ const VALID_PROVIDERS = new Set(['openai', 'ollama', 'local', 'none', 'google', 'auto']);
22
63
  const embeddingsProvider = (() => {
23
- const explicit = process.env.SQUISH_EMBEDDINGS_PROVIDER?.toLowerCase();
24
- if (explicit && VALID_PROVIDERS.has(explicit)) {
64
+ const explicit = getConfig('embeddings.provider', 'SQUISH_EMBEDDINGS_PROVIDER', 'local').toLowerCase();
65
+ if (VALID_PROVIDERS.has(explicit)) {
25
66
  return explicit;
26
67
  }
27
68
  return 'local';
@@ -45,28 +86,47 @@ const defaultCollectionMapping = {
45
86
  const qmdCollectionMapping = process.env.SQUISH_QMD_COLLECTION_MAPPING
46
87
  ? JSON.parse(process.env.SQUISH_QMD_COLLECTION_MAPPING)
47
88
  : defaultCollectionMapping;
89
+ // OpenAI Configuration
90
+ const openAiApiKey = process.env.SQUISH_OPENAI_API_KEY || process.env.OPENAI_API_KEY || '';
91
+ const openAiApiUrl = getConfig('api.openai.apiUrl', 'SQUISH_OPENAI_API_URL', 'https://api.openai.com/v1/embeddings');
92
+ const openAiEmbeddingModel = getConfig('embeddings.models.openai.model', 'SQUISH_OPENAI_EMBEDDING_MODEL', 'text-embedding-3-small');
93
+ // Google Configuration
94
+ const googleCloudApiKey = process.env.GOOGLE_CLOUD_API_KEY || process.env.SQUISH_GOOGLE_CLOUD_API_KEY || '';
95
+ const googleCloudProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.SQUISH_GOOGLE_CLOUD_PROJECT || '';
96
+ const googleCloudLocation = process.env.GOOGLE_CLOUD_LOCATION || process.env.SQUISH_GOOGLE_CLOUD_LOCATION || 'us-central1';
97
+ const googleEmbeddingModel = getConfig('embeddings.models.google.model', 'SQUISH_GOOGLE_EMBEDDING_MODEL', 'gemini-embedding-001');
98
+ // Ollama Configuration
99
+ const ollamaUrl = getConfig('api.ollama.url', 'SQUISH_OLLAMA_URL', 'http://localhost:11434');
100
+ const ollamaEmbeddingModel = getConfig('embeddings.models.ollama.model', 'SQUISH_OLLAMA_EMBEDDING_MODEL', 'nomic-embed-text:v1.5');
48
101
  export const config = {
49
102
  isTeamMode,
50
103
  isManagedMode,
51
104
  redisEnabled: !!process.env.REDIS_URL,
52
105
  dataDir: getDataDir(),
53
- mcpServerPort: parseInt(process.env.SQUISH_MCP_PORT || '8767'),
54
- mcpServerEnabled: process.env.SQUISH_MCP_SERVER_ENABLED !== 'false',
106
+ mcpServerPort: parseInt(getConfig('mcp.serverPort', 'SQUISH_MCP_PORT', '8767')),
107
+ mcpServerEnabled: getConfig('mcp.serverEnabled', 'SQUISH_MCP_SERVER_ENABLED', true) !== false,
55
108
  embeddingsProvider: embeddingsProvider,
109
+ // OpenAI
56
110
  openAiApiKey,
57
- openAiApiUrl: process.env.SQUISH_OPENAI_API_URL || 'https://api.openai.com/v1/embeddings',
58
- openAiEmbeddingModel: process.env.SQUISH_OPENAI_EMBEDDING_MODEL || 'text-embedding-3-small',
59
- ollamaUrl: process.env.SQUISH_OLLAMA_URL || 'http://localhost:11434',
60
- ollamaEmbeddingModel: process.env.SQUISH_OLLAMA_EMBEDDING_MODEL || 'nomic-embed-text:v1.5',
111
+ openAiApiUrl,
112
+ openAiEmbeddingModel,
113
+ // Google
114
+ googleCloudApiKey,
115
+ googleCloudProject,
116
+ googleCloudLocation,
117
+ googleEmbeddingModel,
118
+ // Ollama
119
+ ollamaUrl,
120
+ ollamaEmbeddingModel,
61
121
  // Lifecycle Management
62
- lifecycleEnabled: process.env.SQUISH_LIFECYCLE_ENABLED !== 'false',
122
+ lifecycleEnabled: getConfig('features.lifecycleEnabled', 'SQUISH_LIFECYCLE_ENABLED', true) !== false,
63
123
  lifecycleInterval: parseInt(process.env.SQUISH_LIFECYCLE_INTERVAL || '3600000'),
64
124
  // Session Summarization
65
- summarizationEnabled: process.env.SQUISH_SUMMARIZATION_ENABLED !== 'false',
125
+ summarizationEnabled: getConfig('features.summarizationEnabled', 'SQUISH_SUMMARIZATION_ENABLED', true) !== false,
66
126
  incrementalThreshold: parseInt(process.env.SQUISH_INCREMENTAL_THRESHOLD || '10'),
67
127
  rollingWindowSize: parseInt(process.env.SQUISH_ROLLING_WINDOW_SIZE || '50'),
68
128
  // Agent-Aware Memory
69
- agentIsolationEnabled: process.env.SQUISH_AGENT_ISOLATION_ENABLED !== 'false',
129
+ agentIsolationEnabled: getConfig('features.agentIsolation', 'SQUISH_AGENT_ISOLATION_ENABLED', true) !== false,
70
130
  defaultVisibilityScope: (process.env.SQUISH_DEFAULT_VISIBILITY || 'private'),
71
131
  // Memory Governance
72
132
  governanceEnabled: process.env.SQUISH_GOVERNANCE_ENABLED !== 'false',
@@ -78,11 +138,6 @@ export const config = {
78
138
  qmdCollectionsPath,
79
139
  qmdFallbackMode: qmdFallbackMode,
80
140
  qmdCollectionMapping,
81
- // Google Cloud Multimodal Embeddings
82
- googleCloudApiKey: process.env.GOOGLE_CLOUD_API_KEY || process.env.SQUISH_GOOGLE_CLOUD_API_KEY || '',
83
- googleCloudProject: process.env.GOOGLE_CLOUD_PROJECT || process.env.SQUISH_GOOGLE_CLOUD_PROJECT || '',
84
- googleCloudLocation: process.env.GOOGLE_CLOUD_LOCATION || process.env.SQUISH_GOOGLE_CLOUD_LOCATION || 'us-central1',
85
- multimodalEmbeddingsEnabled: process.env.SQUISH_MULTIMODAL_EMBEDDINGS_ENABLED === 'true',
86
141
  // Managed Mode
87
142
  managedMode: process.env.SQUISH_MANAGED_MODE === 'true',
88
143
  managedApiUrl: process.env.SQUISH_MANAGED_API_URL || 'https://api.squish.dev',
@@ -113,7 +168,7 @@ export const config = {
113
168
  embeddingsRetryDelayMs: parseInt(process.env.SQUISH_EMBEDDINGS_RETRY_DELAY_MS || '1000'),
114
169
  openAiTimeoutMs: parseInt(process.env.SQUISH_OPENAI_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
115
170
  ollamaTimeoutMs: parseInt(process.env.SQUISH_OLLAMA_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
116
- googleMultimodalTimeoutMs: parseInt(process.env.SQUISH_GOOGLE_MULTIMODAL_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
171
+ googleTimeoutMs: parseInt(process.env.SQUISH_GOOGLE_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
117
172
  };
118
173
  export default config;
119
174
  //# sourceMappingURL=config.js.map
@@ -1,5 +1,5 @@
1
1
  import { MultimodalInput } from './embeddings/google-multimodal.js';
2
- export type EmbeddingProvider = 'openai' | 'ollama' | 'local' | 'none' | 'auto' | 'qmd' | 'hybrid' | 'google-multimodal';
2
+ export type EmbeddingProvider = 'local' | 'openai' | 'ollama' | 'google' | 'none' | 'auto';
3
3
  export declare function getEmbedding(input: string | MultimodalInput): Promise<number[] | null>;
4
4
  /**
5
5
  * Get embeddings for multiple inputs in parallel batches
@@ -1,5 +1,4 @@
1
1
  import { config } from '../config.js';
2
- import { getQMDClient } from './embeddings/qmd-client.js';
3
2
  import { getGoogleMultimodalEmbedding, isMultimodalInput } from './embeddings/google-multimodal.js';
4
3
  import { logger } from './logger.js';
5
4
  // Retry utility with exponential backoff
@@ -104,7 +103,7 @@ export async function getEmbedding(input) {
104
103
  }
105
104
  let result = null;
106
105
  // Handle multimodal input
107
- if (isMultimodalInput(input) && (provider === 'google-multimodal' || provider === 'hybrid')) {
106
+ if (isMultimodalInput(input) && provider === 'google') {
108
107
  const multimodalResult = await getGoogleMultimodalEmbedding(input);
109
108
  if (multimodalResult) {
110
109
  result = multimodalResult.embedding;
@@ -116,35 +115,10 @@ export async function getEmbedding(input) {
116
115
  if (provider === 'none') {
117
116
  result = null;
118
117
  }
119
- else if (provider === 'google-multimodal') {
118
+ else if (provider === 'google') {
120
119
  const multimodalResult = await getGoogleMultimodalEmbedding({ text: textInput });
121
120
  result = multimodalResult?.embedding || null;
122
121
  }
123
- else if (provider === 'qmd') {
124
- result = await getQMDEmbedding(textInput);
125
- // Fallback if QMD fails (unless qmd-only mode)
126
- if (!result && config.qmdFallbackMode !== 'qmd-only') {
127
- result = getLocalEmbedding(textInput);
128
- }
129
- }
130
- else if (provider === 'hybrid') {
131
- // Hybrid mode: Try cloud providers first (best quality), then local fallback
132
- // Order: Google Multimodal → OpenAI → Ollama → Local TF-IDF
133
- // Note: QMD is not used for embedding generation (search only)
134
- if (config.multimodalEmbeddingsEnabled) {
135
- const multimodalResult = await getGoogleMultimodalEmbedding({ text: textInput });
136
- result = multimodalResult?.embedding || null;
137
- }
138
- if (!result && config.openAiApiKey) {
139
- result = await getOpenAiEmbedding(textInput);
140
- }
141
- if (!result && config.ollamaUrl) {
142
- result = await getOllamaEmbedding(textInput);
143
- }
144
- if (!result) {
145
- result = getLocalEmbedding(textInput);
146
- }
147
- }
148
122
  else if (provider === 'openai') {
149
123
  result = await getOpenAiEmbedding(textInput);
150
124
  }
@@ -155,8 +129,7 @@ export async function getEmbedding(input) {
155
129
  result = getLocalEmbedding(textInput);
156
130
  }
157
131
  else {
158
- // Auto mode: use local TF-IDF by default (fast, no API needed)
159
- // Only try external providers if explicitly configured
132
+ // Auto mode: try cloud providers first if configured, then fall back to local
160
133
  if (config.openAiApiKey) {
161
134
  result = await getOpenAiEmbedding(textInput);
162
135
  }
@@ -288,34 +261,6 @@ function getLocalEmbedding(input) {
288
261
  }
289
262
  return vector;
290
263
  }
291
- /**
292
- * Get embedding via QMD
293
- * Note: QMD doesn't expose direct embedding generation via MCP.
294
- * This function returns null to trigger fallback to other providers.
295
- * The main QMD integration value is through hybrid search (qmd_query).
296
- */
297
- async function getQMDEmbedding(input) {
298
- if (!config.qmdEnabled) {
299
- return null;
300
- }
301
- try {
302
- const client = await getQMDClient();
303
- const available = await client.isAvailable();
304
- if (!available) {
305
- return null;
306
- }
307
- // QMD doesn't expose direct embedding generation via MCP
308
- // The search tools use embeddings internally but don't return them
309
- //
310
- // For embedding generation, we rely on fallback providers
311
- // QMD's main value is through the qmd_search, qmd_vsearch, qmd_query tools
312
- return null;
313
- }
314
- catch (error) {
315
- logger.debug('QMD embedding unavailable (expected if QMD server not running)');
316
- return null;
317
- }
318
- }
319
264
  /**
320
265
  * DJB2 hash function - fast, good distribution
321
266
  */
@@ -384,7 +329,7 @@ async function getOllamaEmbedding(input) {
384
329
  */
385
330
  export async function checkEmbeddingProviderHealth() {
386
331
  const results = new Map();
387
- const providers = ['local', 'openai', 'ollama', 'google-multimodal', 'qmd'];
332
+ const providers = ['local', 'openai', 'ollama', 'google', 'none', 'auto'];
388
333
  // Test local provider (always available)
389
334
  results.set('local', { available: true, latencyMs: 0 });
390
335
  // Test OpenAI if configured
@@ -431,29 +376,27 @@ export async function checkEmbeddingProviderHealth() {
431
376
  else {
432
377
  results.set('ollama', { available: false, error: 'Not configured' });
433
378
  }
434
- // Test Google Multimodal if configured
435
- if (config.multimodalEmbeddingsEnabled && (config.googleCloudApiKey || config.googleCloudProject)) {
379
+ // Test Google if configured
380
+ if (config.googleCloudApiKey || config.googleCloudProject) {
436
381
  const start = Date.now();
437
382
  try {
438
- const result = await withRetry(() => withTimeout(getGoogleMultimodalEmbedding({ text: 'health check' }), config.googleMultimodalTimeoutMs), config.embeddingsMaxRetries, config.embeddingsRetryDelayMs);
383
+ const result = await withRetry(() => withTimeout(getGoogleMultimodalEmbedding({ text: 'health check' }), config.googleTimeoutMs), config.embeddingsMaxRetries, config.embeddingsRetryDelayMs);
439
384
  const latency = Date.now() - start;
440
- results.set('google-multimodal', {
385
+ results.set('google', {
441
386
  available: result !== null && result.embedding.length > 0,
442
387
  latencyMs: latency
443
388
  });
444
389
  }
445
390
  catch (error) {
446
- results.set('google-multimodal', {
391
+ results.set('google', {
447
392
  available: false,
448
393
  error: error.message
449
394
  });
450
395
  }
451
396
  }
452
397
  else {
453
- results.set('google-multimodal', { available: false, error: 'Not configured' });
398
+ results.set('google', { available: false, error: 'Not configured' });
454
399
  }
455
- // QMD is not used for embedding generation (search only)
456
- results.set('qmd', { available: false, error: 'QMD not used for embeddings (search only)' });
457
400
  return results;
458
401
  }
459
402
  //# sourceMappingURL=embeddings.js.map
@@ -1,14 +1,6 @@
1
1
  /**
2
- * Local Vector Embeddings Service
3
- * Provides local embedding generation without external APIs
2
+ * Utility functions for local embeddings
3
+ * Note: Actual embedding generation is in core/embeddings.ts
4
4
  */
5
- export type Embedding = number[];
6
- export declare const EMBEDDING_DIMENSIONS = 1536;
7
- export interface EmbeddingProvider {
8
- embed(text: string): Promise<Embedding>;
9
- isAvailable(): Promise<boolean>;
10
- getDimensions(): number;
11
- }
12
- export declare function initializeEmbeddingProvider(): Promise<void>;
13
- export declare function cosineSimilarity(a: Embedding, b: Embedding): number;
5
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
14
6
  //# sourceMappingURL=local-embeddings.d.ts.map
@@ -1,81 +1,7 @@
1
1
  /**
2
- * Local Vector Embeddings Service
3
- * Provides local embedding generation without external APIs
2
+ * Utility functions for local embeddings
3
+ * Note: Actual embedding generation is in core/embeddings.ts
4
4
  */
5
- import { config } from '../config.js';
6
- import { logger } from './logger.js';
7
- export const EMBEDDING_DIMENSIONS = 1536;
8
- class StubEmbeddingProvider {
9
- async embed(_text) {
10
- return Array(EMBEDDING_DIMENSIONS).fill(0);
11
- }
12
- async isAvailable() {
13
- return true;
14
- }
15
- getDimensions() {
16
- return EMBEDDING_DIMENSIONS;
17
- }
18
- }
19
- class LocalTfidfEmbeddingProvider {
20
- idf = new Map();
21
- async embed(text) {
22
- const words = this.tokenize(text);
23
- const embedding = Array(EMBEDDING_DIMENSIONS).fill(0);
24
- const wordFreq = new Map();
25
- for (const word of words) {
26
- wordFreq.set(word, (wordFreq.get(word) || 0) + 1);
27
- }
28
- for (const [word, freq] of wordFreq.entries()) {
29
- const hash = this.hash(word) % EMBEDDING_DIMENSIONS;
30
- const idf = this.idf.get(word) || 1;
31
- embedding[hash] += freq * idf;
32
- }
33
- const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
34
- if (norm > 0) {
35
- for (let i = 0; i < embedding.length; i++) {
36
- embedding[i] /= norm;
37
- }
38
- }
39
- return embedding;
40
- }
41
- async isAvailable() {
42
- return true;
43
- }
44
- getDimensions() {
45
- return EMBEDDING_DIMENSIONS;
46
- }
47
- tokenize(text) {
48
- return text.toLowerCase().split(/\s+/).filter(w => w.length > 2).slice(0, 100);
49
- }
50
- hash(str) {
51
- let hash = 0;
52
- for (let i = 0; i < str.length; i++) {
53
- hash = ((hash << 5) - hash) + str.charCodeAt(i);
54
- hash = hash & hash;
55
- }
56
- return Math.abs(hash);
57
- }
58
- }
59
- let currentProvider = null;
60
- export async function initializeEmbeddingProvider() {
61
- if (config.embeddingsProvider === 'openai' && config.openAiApiKey) {
62
- logger.info('Using OpenAI embeddings (team mode - requires API key)');
63
- currentProvider = new StubEmbeddingProvider();
64
- }
65
- else if (config.embeddingsProvider === 'ollama') {
66
- logger.info('Using Ollama embeddings (team mode - local LLM)');
67
- currentProvider = new StubEmbeddingProvider();
68
- }
69
- else if (config.embeddingsProvider === 'local') {
70
- logger.info('Using local TF-IDF embeddings (SQLite mode - offline, no API key)');
71
- currentProvider = new LocalTfidfEmbeddingProvider();
72
- }
73
- else {
74
- // 'none' mode
75
- logger.info('Embeddings disabled (stub provider)');
76
- currentProvider = new StubEmbeddingProvider();
77
- }
78
- }
79
5
  export function cosineSimilarity(a, b) {
80
6
  if (a.length !== b.length) {
81
7
  throw new Error('Embeddings must have same dimensions');
@@ -1,5 +1,6 @@
1
1
  import express from 'express';
2
2
  import cors from 'cors';
3
+ import rateLimit from 'express-rate-limit';
3
4
  import { logger } from '../logger.js';
4
5
  export class MCPServer {
5
6
  app = express();
@@ -16,7 +17,32 @@ export class MCPServer {
16
17
  this.setupRoutes();
17
18
  }
18
19
  setupMiddleware() {
19
- this.app.use(cors());
20
+ const allowedOrigins = process.env.SQUISH_CORS_ORIGINS?.split(',').map(s => s.trim()) || ['http://localhost:*', 'http://127.0.0.1:*'];
21
+ const appCors = cors({
22
+ origin: (origin, callback) => {
23
+ if (!origin || allowedOrigins.some(allowed => {
24
+ if (allowed.endsWith(':*')) {
25
+ const prefix = allowed.slice(0, -1);
26
+ return origin.startsWith(prefix);
27
+ }
28
+ return origin === allowed;
29
+ })) {
30
+ callback(null, true);
31
+ }
32
+ else {
33
+ callback(new Error('Not allowed by CORS'));
34
+ }
35
+ }
36
+ });
37
+ const limiter = rateLimit({
38
+ windowMs: 15 * 60 * 1000,
39
+ max: 100,
40
+ message: { error: 'Too many requests, please try again later.' },
41
+ standardHeaders: true,
42
+ legacyHeaders: false,
43
+ });
44
+ this.app.use(appCors);
45
+ this.app.use(limiter);
20
46
  this.app.use(express.json());
21
47
  }
22
48
  setupRoutes() {
@@ -30,29 +30,29 @@ export declare const MCPToolResultSchema: z.ZodObject<{
30
30
  mimeType: z.ZodOptional<z.ZodString>;
31
31
  }, "strip", z.ZodTypeAny, {
32
32
  type: "text" | "image" | "resource";
33
- data?: string | undefined;
34
33
  text?: string | undefined;
34
+ data?: string | undefined;
35
35
  mimeType?: string | undefined;
36
36
  }, {
37
37
  type: "text" | "image" | "resource";
38
- data?: string | undefined;
39
38
  text?: string | undefined;
39
+ data?: string | undefined;
40
40
  mimeType?: string | undefined;
41
41
  }>, "many">;
42
42
  isError: z.ZodOptional<z.ZodBoolean>;
43
43
  }, "strip", z.ZodTypeAny, {
44
44
  content: {
45
45
  type: "text" | "image" | "resource";
46
- data?: string | undefined;
47
46
  text?: string | undefined;
47
+ data?: string | undefined;
48
48
  mimeType?: string | undefined;
49
49
  }[];
50
50
  isError?: boolean | undefined;
51
51
  }, {
52
52
  content: {
53
53
  type: "text" | "image" | "resource";
54
- data?: string | undefined;
55
54
  text?: string | undefined;
55
+ data?: string | undefined;
56
56
  mimeType?: string | undefined;
57
57
  }[];
58
58
  isError?: boolean | undefined;
@@ -10,7 +10,8 @@ export async function collectRecentContext(sessionId, count = 5) {
10
10
  return [];
11
11
  }
12
12
  try {
13
- const [conversation] = await db
13
+ const sqliteDb = db;
14
+ const [conversation] = await sqliteDb
14
15
  .select()
15
16
  .from(conversations)
16
17
  .where(eq(conversations.sessionId, sessionId))
@@ -20,7 +21,7 @@ export async function collectRecentContext(sessionId, count = 5) {
20
21
  logger.debug(`[ContextCollector] No conversation found for session ${sessionId}`);
21
22
  return [];
22
23
  }
23
- const recentMessages = await db
24
+ const recentMessages = await sqliteDb
24
25
  .select()
25
26
  .from(messages)
26
27
  .where(eq(messages.conversationId, conversation.id))
@@ -19,8 +19,9 @@ export async function recordInjection(sessionId, memoryIds, memoryContent) {
19
19
  return;
20
20
  try {
21
21
  const now = new Date();
22
+ const sqliteDb = db;
22
23
  for (const memoryId of memoryIds) {
23
- await db.insert(memoryFeedback).values({
24
+ await sqliteDb.insert(memoryFeedback).values({
24
25
  memoryId,
25
26
  sessionId,
26
27
  wasInjected: true,
@@ -55,16 +56,17 @@ export async function analyzeAndRecordFeedback(sessionId, responseText) {
55
56
  return;
56
57
  try {
57
58
  const now = new Date();
59
+ const sqliteDb = db;
58
60
  for (const memoryId of injection.memoryIds) {
59
61
  const wasReferenced = analysis.referencedMemoryIds.includes(memoryId);
60
62
  const delta = wasReferenced ? config.feedbackEchoBonus : -config.feedbackFizzlePenalty;
61
- const existing = await db
63
+ const existing = await sqliteDb
62
64
  .select()
63
65
  .from(memoryFeedback)
64
66
  .where(and(eq(memoryFeedback.memoryId, memoryId), eq(memoryFeedback.sessionId, sessionId)))
65
67
  .limit(1);
66
68
  if (existing.length > 0) {
67
- await db
69
+ await sqliteDb
68
70
  .update(memoryFeedback)
69
71
  .set({
70
72
  wasReferenced,
@@ -99,7 +101,8 @@ export async function updateRetrievalPriority(memoryId, delta) {
99
101
  if (!db)
100
102
  return;
101
103
  try {
102
- const [memory] = await db
104
+ const sqliteDb = db;
105
+ const [memory] = await sqliteDb
103
106
  .select({ retrievalPriority: memories.retrievalPriority })
104
107
  .from(memories)
105
108
  .where(eq(memories.id, memoryId))
@@ -108,7 +111,7 @@ export async function updateRetrievalPriority(memoryId, delta) {
108
111
  return;
109
112
  const currentPriority = memory.retrievalPriority ?? 50;
110
113
  const newPriority = Math.max(0, Math.min(100, currentPriority + delta));
111
- await db
114
+ await sqliteDb
112
115
  .update(memories)
113
116
  .set({ retrievalPriority: newPriority })
114
117
  .where(eq(memories.id, memoryId));
@@ -124,7 +127,8 @@ export async function getMemoryFeedbackStats(memoryId) {
124
127
  return { totalInjections: 0, totalReferences: 0, echoRate: 0, averagePriorityDelta: 0 };
125
128
  }
126
129
  try {
127
- const records = await db
130
+ const sqliteDb = db;
131
+ const records = await sqliteDb
128
132
  .select()
129
133
  .from(memoryFeedback)
130
134
  .where(eq(memoryFeedback.memoryId, memoryId));