@lossless-claude/lcm 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/.claude-plugin/commands/lcm-compact.md +31 -0
  2. package/.claude-plugin/commands/lcm-curate.md +31 -0
  3. package/.claude-plugin/commands/lcm-diagnose.md +29 -0
  4. package/.claude-plugin/commands/lcm-doctor.md +23 -0
  5. package/.claude-plugin/commands/lcm-dogfood.md +101 -0
  6. package/.claude-plugin/commands/lcm-import.md +48 -0
  7. package/.claude-plugin/commands/lcm-promote.md +29 -0
  8. package/.claude-plugin/commands/lcm-sensitive.md +55 -0
  9. package/.claude-plugin/commands/lcm-stats.md +19 -0
  10. package/.claude-plugin/commands/lcm-status.md +27 -0
  11. package/.claude-plugin/hooks/README.md +47 -0
  12. package/.claude-plugin/marketplace.json +20 -0
  13. package/.claude-plugin/mcp.mjs +12 -0
  14. package/.claude-plugin/plugin.json +46 -0
  15. package/.claude-plugin/skills/lcm-context/SKILL.md +107 -0
  16. package/.claude-plugin/skills/lcm-dogfood/SKILL.md +102 -0
  17. package/.claude-plugin/skills/lcm-dogfood/references/checks.md +239 -0
  18. package/.claude-plugin/skills/lcm-dogfood/references/known-issues.md +11 -0
  19. package/.claude-plugin/skills/lcm-dogfood/scripts/db-integrity.js +40 -0
  20. package/.claude-plugin/skills/lcm-dogfood/scripts/prompt-search-test.js +35 -0
  21. package/.claude-plugin/skills/lcm-e2e/SKILL.md +61 -0
  22. package/.claude-plugin/skills/lcm-e2e/checklist.md +367 -0
  23. package/.claude-plugin/skills/lossless-claude-upgrade/SKILL.md +47 -0
  24. package/LICENSE +21 -0
  25. package/README.md +231 -0
  26. package/dist/bin/lcm.d.ts +2 -0
  27. package/dist/bin/lcm.js +461 -0
  28. package/dist/bin/lcm.js.map +1 -0
  29. package/dist/installer/dry-run-deps.d.ts +23 -0
  30. package/dist/installer/dry-run-deps.js +66 -0
  31. package/dist/installer/dry-run-deps.js.map +1 -0
  32. package/dist/installer/install.d.ts +39 -0
  33. package/dist/installer/install.js +236 -0
  34. package/dist/installer/install.js.map +1 -0
  35. package/dist/installer/uninstall.d.ts +11 -0
  36. package/dist/installer/uninstall.js +80 -0
  37. package/dist/installer/uninstall.js.map +1 -0
  38. package/dist/src/batch-compact.d.ts +16 -0
  39. package/dist/src/batch-compact.js +121 -0
  40. package/dist/src/batch-compact.js.map +1 -0
  41. package/dist/src/compaction.d.ts +198 -0
  42. package/dist/src/compaction.js +964 -0
  43. package/dist/src/compaction.js.map +1 -0
  44. package/dist/src/connectors/constants.d.ts +5 -0
  45. package/dist/src/connectors/constants.js +6 -0
  46. package/dist/src/connectors/constants.js.map +1 -0
  47. package/dist/src/connectors/installer.d.ts +16 -0
  48. package/dist/src/connectors/installer.js +200 -0
  49. package/dist/src/connectors/installer.js.map +1 -0
  50. package/dist/src/connectors/registry.d.ts +4 -0
  51. package/dist/src/connectors/registry.js +264 -0
  52. package/dist/src/connectors/registry.js.map +1 -0
  53. package/dist/src/connectors/template-service.d.ts +5 -0
  54. package/dist/src/connectors/template-service.js +54 -0
  55. package/dist/src/connectors/template-service.js.map +1 -0
  56. package/dist/src/connectors/templates/base.md +1 -0
  57. package/dist/src/connectors/templates/mcp-base.md +1 -0
  58. package/dist/src/connectors/templates/sections/command-reference.md +15 -0
  59. package/dist/src/connectors/templates/sections/mcp-workflow.md +18 -0
  60. package/dist/src/connectors/templates/sections/workflow.md +29 -0
  61. package/dist/src/connectors/templates/skill/SKILL.md +74 -0
  62. package/dist/src/connectors/types.d.ts +19 -0
  63. package/dist/src/connectors/types.js +10 -0
  64. package/dist/src/connectors/types.js.map +1 -0
  65. package/dist/src/daemon/client.d.ts +9 -0
  66. package/dist/src/daemon/client.js +28 -0
  67. package/dist/src/daemon/client.js.map +1 -0
  68. package/dist/src/daemon/config.d.ts +48 -0
  69. package/dist/src/daemon/config.js +67 -0
  70. package/dist/src/daemon/config.js.map +1 -0
  71. package/dist/src/daemon/lifecycle.d.ts +19 -0
  72. package/dist/src/daemon/lifecycle.js +102 -0
  73. package/dist/src/daemon/lifecycle.js.map +1 -0
  74. package/dist/src/daemon/orientation.d.ts +1 -0
  75. package/dist/src/daemon/orientation.js +9 -0
  76. package/dist/src/daemon/orientation.js.map +1 -0
  77. package/dist/src/daemon/project-queue.d.ts +1 -0
  78. package/dist/src/daemon/project-queue.js +17 -0
  79. package/dist/src/daemon/project-queue.js.map +1 -0
  80. package/dist/src/daemon/project.d.ts +7 -0
  81. package/dist/src/daemon/project.js +25 -0
  82. package/dist/src/daemon/project.js.map +1 -0
  83. package/dist/src/daemon/proxy-manager.d.ts +21 -0
  84. package/dist/src/daemon/proxy-manager.js +205 -0
  85. package/dist/src/daemon/proxy-manager.js.map +1 -0
  86. package/dist/src/daemon/routes/compact.d.ts +13 -0
  87. package/dist/src/daemon/routes/compact.js +195 -0
  88. package/dist/src/daemon/routes/compact.js.map +1 -0
  89. package/dist/src/daemon/routes/describe.d.ts +3 -0
  90. package/dist/src/daemon/routes/describe.js +39 -0
  91. package/dist/src/daemon/routes/describe.js.map +1 -0
  92. package/dist/src/daemon/routes/expand.d.ts +3 -0
  93. package/dist/src/daemon/routes/expand.js +41 -0
  94. package/dist/src/daemon/routes/expand.js.map +1 -0
  95. package/dist/src/daemon/routes/grep.d.ts +3 -0
  96. package/dist/src/daemon/routes/grep.js +43 -0
  97. package/dist/src/daemon/routes/grep.js.map +1 -0
  98. package/dist/src/daemon/routes/ingest.d.ts +3 -0
  99. package/dist/src/daemon/routes/ingest.js +101 -0
  100. package/dist/src/daemon/routes/ingest.js.map +1 -0
  101. package/dist/src/daemon/routes/promote.d.ts +4 -0
  102. package/dist/src/daemon/routes/promote.js +104 -0
  103. package/dist/src/daemon/routes/promote.js.map +1 -0
  104. package/dist/src/daemon/routes/prompt-search.d.ts +3 -0
  105. package/dist/src/daemon/routes/prompt-search.js +65 -0
  106. package/dist/src/daemon/routes/prompt-search.js.map +1 -0
  107. package/dist/src/daemon/routes/recent.d.ts +3 -0
  108. package/dist/src/daemon/routes/recent.js +37 -0
  109. package/dist/src/daemon/routes/recent.js.map +1 -0
  110. package/dist/src/daemon/routes/restore.d.ts +3 -0
  111. package/dist/src/daemon/routes/restore.js +120 -0
  112. package/dist/src/daemon/routes/restore.js.map +1 -0
  113. package/dist/src/daemon/routes/search.d.ts +2 -0
  114. package/dist/src/daemon/routes/search.js +66 -0
  115. package/dist/src/daemon/routes/search.js.map +1 -0
  116. package/dist/src/daemon/routes/status.d.ts +3 -0
  117. package/dist/src/daemon/routes/status.js +80 -0
  118. package/dist/src/daemon/routes/status.js.map +1 -0
  119. package/dist/src/daemon/routes/store.d.ts +2 -0
  120. package/dist/src/daemon/routes/store.js +46 -0
  121. package/dist/src/daemon/routes/store.js.map +1 -0
  122. package/dist/src/daemon/server.d.ts +19 -0
  123. package/dist/src/daemon/server.js +183 -0
  124. package/dist/src/daemon/server.js.map +1 -0
  125. package/dist/src/daemon/summarizer.d.ts +11 -0
  126. package/dist/src/daemon/summarizer.js +51 -0
  127. package/dist/src/daemon/summarizer.js.map +1 -0
  128. package/dist/src/db/config.d.ts +31 -0
  129. package/dist/src/db/config.js +83 -0
  130. package/dist/src/db/config.js.map +1 -0
  131. package/dist/src/db/connection.d.ts +3 -0
  132. package/dist/src/db/connection.js +62 -0
  133. package/dist/src/db/connection.js.map +1 -0
  134. package/dist/src/db/features.d.ts +11 -0
  135. package/dist/src/db/features.js +36 -0
  136. package/dist/src/db/features.js.map +1 -0
  137. package/dist/src/db/migration.d.ts +4 -0
  138. package/dist/src/db/migration.js +499 -0
  139. package/dist/src/db/migration.js.map +1 -0
  140. package/dist/src/db/promoted.d.ts +47 -0
  141. package/dist/src/db/promoted.js +96 -0
  142. package/dist/src/db/promoted.js.map +1 -0
  143. package/dist/src/db/redaction-stats.d.ts +6 -0
  144. package/dist/src/db/redaction-stats.js +16 -0
  145. package/dist/src/db/redaction-stats.js.map +1 -0
  146. package/dist/src/diagnose.d.ts +39 -0
  147. package/dist/src/diagnose.js +432 -0
  148. package/dist/src/diagnose.js.map +1 -0
  149. package/dist/src/doctor/doctor.d.ts +4 -0
  150. package/dist/src/doctor/doctor.js +378 -0
  151. package/dist/src/doctor/doctor.js.map +1 -0
  152. package/dist/src/doctor/types.d.ts +24 -0
  153. package/dist/src/doctor/types.js +2 -0
  154. package/dist/src/doctor/types.js.map +1 -0
  155. package/dist/src/expansion.d.ts +100 -0
  156. package/dist/src/expansion.js +268 -0
  157. package/dist/src/expansion.js.map +1 -0
  158. package/dist/src/hooks/auto-heal.d.ts +12 -0
  159. package/dist/src/hooks/auto-heal.js +49 -0
  160. package/dist/src/hooks/auto-heal.js.map +1 -0
  161. package/dist/src/hooks/compact.d.ts +5 -0
  162. package/dist/src/hooks/compact.js +22 -0
  163. package/dist/src/hooks/compact.js.map +1 -0
  164. package/dist/src/hooks/dispatch.d.ts +7 -0
  165. package/dist/src/hooks/dispatch.js +36 -0
  166. package/dist/src/hooks/dispatch.js.map +1 -0
  167. package/dist/src/hooks/probe-precompact.d.ts +2 -0
  168. package/dist/src/hooks/probe-precompact.js +17 -0
  169. package/dist/src/hooks/probe-precompact.js.map +1 -0
  170. package/dist/src/hooks/probe-sessionstart.d.ts +2 -0
  171. package/dist/src/hooks/probe-sessionstart.js +18 -0
  172. package/dist/src/hooks/probe-sessionstart.js.map +1 -0
  173. package/dist/src/hooks/restore.d.ts +5 -0
  174. package/dist/src/hooks/restore.js +19 -0
  175. package/dist/src/hooks/restore.js.map +1 -0
  176. package/dist/src/hooks/session-end.d.ts +16 -0
  177. package/dist/src/hooks/session-end.js +73 -0
  178. package/dist/src/hooks/session-end.js.map +1 -0
  179. package/dist/src/hooks/user-prompt.d.ts +5 -0
  180. package/dist/src/hooks/user-prompt.js +31 -0
  181. package/dist/src/hooks/user-prompt.js.map +1 -0
  182. package/dist/src/import.d.ts +24 -0
  183. package/dist/src/import.js +119 -0
  184. package/dist/src/import.js.map +1 -0
  185. package/dist/src/large-files.d.ts +28 -0
  186. package/dist/src/large-files.js +413 -0
  187. package/dist/src/large-files.js.map +1 -0
  188. package/dist/src/llm/anthropic.d.ts +9 -0
  189. package/dist/src/llm/anthropic.js +54 -0
  190. package/dist/src/llm/anthropic.js.map +1 -0
  191. package/dist/src/llm/claude-process.d.ts +2 -0
  192. package/dist/src/llm/claude-process.js +55 -0
  193. package/dist/src/llm/claude-process.js.map +1 -0
  194. package/dist/src/llm/codex-process.d.ts +15 -0
  195. package/dist/src/llm/codex-process.js +142 -0
  196. package/dist/src/llm/codex-process.js.map +1 -0
  197. package/dist/src/llm/mock-summarizer.d.ts +9 -0
  198. package/dist/src/llm/mock-summarizer.js +17 -0
  199. package/dist/src/llm/mock-summarizer.js.map +1 -0
  200. package/dist/src/llm/openai.d.ts +10 -0
  201. package/dist/src/llm/openai.js +52 -0
  202. package/dist/src/llm/openai.js.map +1 -0
  203. package/dist/src/llm/types.d.ts +6 -0
  204. package/dist/src/llm/types.js +2 -0
  205. package/dist/src/llm/types.js.map +1 -0
  206. package/dist/src/mcp/server.d.ts +9 -0
  207. package/dist/src/mcp/server.js +128 -0
  208. package/dist/src/mcp/server.js.map +1 -0
  209. package/dist/src/mcp/tools/lcm-describe.d.ts +14 -0
  210. package/dist/src/mcp/tools/lcm-describe.js +12 -0
  211. package/dist/src/mcp/tools/lcm-describe.js.map +1 -0
  212. package/dist/src/mcp/tools/lcm-doctor.d.ts +8 -0
  213. package/dist/src/mcp/tools/lcm-doctor.js +9 -0
  214. package/dist/src/mcp/tools/lcm-doctor.js.map +1 -0
  215. package/dist/src/mcp/tools/lcm-expand.d.ts +18 -0
  216. package/dist/src/mcp/tools/lcm-expand.js +13 -0
  217. package/dist/src/mcp/tools/lcm-expand.js.map +1 -0
  218. package/dist/src/mcp/tools/lcm-grep.d.ts +27 -0
  219. package/dist/src/mcp/tools/lcm-grep.js +15 -0
  220. package/dist/src/mcp/tools/lcm-grep.js.map +1 -0
  221. package/dist/src/mcp/tools/lcm-search.d.ts +33 -0
  222. package/dist/src/mcp/tools/lcm-search.js +15 -0
  223. package/dist/src/mcp/tools/lcm-search.js.map +1 -0
  224. package/dist/src/mcp/tools/lcm-stats.d.ts +14 -0
  225. package/dist/src/mcp/tools/lcm-stats.js +11 -0
  226. package/dist/src/mcp/tools/lcm-stats.js.map +1 -0
  227. package/dist/src/mcp/tools/lcm-store.d.ts +26 -0
  228. package/dist/src/mcp/tools/lcm-store.js +22 -0
  229. package/dist/src/mcp/tools/lcm-store.js.map +1 -0
  230. package/dist/src/memory/index.d.ts +22 -0
  231. package/dist/src/memory/index.js +21 -0
  232. package/dist/src/memory/index.js.map +1 -0
  233. package/dist/src/promotion/dedup.d.ts +19 -0
  234. package/dist/src/promotion/dedup.js +42 -0
  235. package/dist/src/promotion/dedup.js.map +1 -0
  236. package/dist/src/promotion/detector.d.ts +15 -0
  237. package/dist/src/promotion/detector.js +31 -0
  238. package/dist/src/promotion/detector.js.map +1 -0
  239. package/dist/src/prompts/condensed-d1.yaml +38 -0
  240. package/dist/src/prompts/condensed-d2.yaml +32 -0
  241. package/dist/src/prompts/condensed-d3plus.yaml +32 -0
  242. package/dist/src/prompts/leaf-aggressive.yaml +34 -0
  243. package/dist/src/prompts/leaf-normal.yaml +34 -0
  244. package/dist/src/prompts/loader.d.ts +9 -0
  245. package/dist/src/prompts/loader.js +37 -0
  246. package/dist/src/prompts/loader.js.map +1 -0
  247. package/dist/src/prompts/promoted-merge.yaml +18 -0
  248. package/dist/src/prompts/system.yaml +5 -0
  249. package/dist/src/retrieval.d.ts +122 -0
  250. package/dist/src/retrieval.js +214 -0
  251. package/dist/src/retrieval.js.map +1 -0
  252. package/dist/src/scrub.d.ts +46 -0
  253. package/dist/src/scrub.js +184 -0
  254. package/dist/src/scrub.js.map +1 -0
  255. package/dist/src/sensitive.d.ts +4 -0
  256. package/dist/src/sensitive.js +258 -0
  257. package/dist/src/sensitive.js.map +1 -0
  258. package/dist/src/stats.d.ts +34 -0
  259. package/dist/src/stats.js +260 -0
  260. package/dist/src/stats.js.map +1 -0
  261. package/dist/src/store/conversation-store.d.ts +115 -0
  262. package/dist/src/store/conversation-store.js +447 -0
  263. package/dist/src/store/conversation-store.js.map +1 -0
  264. package/dist/src/store/fts5-sanitize.d.ts +23 -0
  265. package/dist/src/store/fts5-sanitize.js +30 -0
  266. package/dist/src/store/fts5-sanitize.js.map +1 -0
  267. package/dist/src/store/full-text-fallback.d.ts +16 -0
  268. package/dist/src/store/full-text-fallback.js +60 -0
  269. package/dist/src/store/full-text-fallback.js.map +1 -0
  270. package/dist/src/store/index.d.ts +4 -0
  271. package/dist/src/store/index.js +3 -0
  272. package/dist/src/store/index.js.map +1 -0
  273. package/dist/src/store/summary-store.d.ts +118 -0
  274. package/dist/src/store/summary-store.js +570 -0
  275. package/dist/src/store/summary-store.js.map +1 -0
  276. package/dist/src/summarize.d.ts +59 -0
  277. package/dist/src/summarize.js +619 -0
  278. package/dist/src/summarize.js.map +1 -0
  279. package/dist/src/transcript.d.ts +7 -0
  280. package/dist/src/transcript.js +51 -0
  281. package/dist/src/transcript.js.map +1 -0
  282. package/dist/src/types.d.ts +116 -0
  283. package/dist/src/types.js +8 -0
  284. package/dist/src/types.js.map +1 -0
  285. package/docs/agent-tools.md +187 -0
  286. package/docs/architecture.md +224 -0
  287. package/docs/configuration.md +168 -0
  288. package/docs/fts5.md +161 -0
  289. package/docs/hook-protocol.md +41 -0
  290. package/docs/privacy.md +101 -0
  291. package/mcp.mjs +17 -0
  292. package/package.json +79 -0
@@ -0,0 +1,80 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { DatabaseSync } from "node:sqlite";
3
+ import { projectDbPath, projectMetaPath } from "../project.js";
4
+ import { sendJson } from "../server.js";
5
+ import { PKG_VERSION } from "../server.js";
6
+ export function createStatusHandler(config, startTime, actualPort) {
7
+ return async (_req, res, body) => {
8
+ const input = JSON.parse(body || "{}");
9
+ const { cwd } = input;
10
+ if (!cwd) {
11
+ sendJson(res, 400, { error: "cwd is required" });
12
+ return;
13
+ }
14
+ // Calculate daemon uptime in seconds
15
+ const uptime = Math.floor((Date.now() - startTime) / 1000);
16
+ // Use actual port if provided, otherwise fall back to config port
17
+ const port = actualPort ?? config.daemon.port;
18
+ // Query project database for stats
19
+ let messageCount = 0;
20
+ let summaryCount = 0;
21
+ let promotedCount = 0;
22
+ const dbPath = projectDbPath(cwd);
23
+ if (existsSync(dbPath)) {
24
+ const db = new DatabaseSync(dbPath);
25
+ try {
26
+ db.exec("PRAGMA busy_timeout = 5000");
27
+ // Count messages
28
+ const msgResult = db.prepare("SELECT COUNT(*) as count FROM messages").get();
29
+ messageCount = msgResult?.count ?? 0;
30
+ // Count summaries
31
+ const sumResult = db.prepare("SELECT COUNT(*) as count FROM summaries").get();
32
+ summaryCount = sumResult?.count ?? 0;
33
+ // Count promoted
34
+ const promResult = db.prepare("SELECT COUNT(*) as count FROM promoted").get();
35
+ promotedCount = promResult?.count ?? 0;
36
+ }
37
+ catch {
38
+ // If database query fails, return zeros
39
+ messageCount = 0;
40
+ summaryCount = 0;
41
+ promotedCount = 0;
42
+ }
43
+ finally {
44
+ db.close();
45
+ }
46
+ }
47
+ // Read meta.json for timestamps
48
+ let lastIngest = null;
49
+ let lastCompact = null;
50
+ let lastPromote = null;
51
+ const metaPath = projectMetaPath(cwd);
52
+ if (existsSync(metaPath)) {
53
+ try {
54
+ const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
55
+ lastIngest = meta.lastIngest ?? null;
56
+ lastCompact = meta.lastCompact ?? null;
57
+ lastPromote = meta.lastPromote ?? null;
58
+ }
59
+ catch {
60
+ // If meta.json parse fails, keep timestamps as null
61
+ }
62
+ }
63
+ sendJson(res, 200, {
64
+ daemon: {
65
+ version: PKG_VERSION,
66
+ uptime,
67
+ port,
68
+ },
69
+ project: {
70
+ messageCount,
71
+ summaryCount,
72
+ promotedCount,
73
+ lastIngest,
74
+ lastCompact,
75
+ lastPromote,
76
+ },
77
+ });
78
+ };
79
+ }
80
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/daemon/routes/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { RouteHandler } from "../server.js";
2
+ export declare function createStoreHandler(): RouteHandler;
@@ -0,0 +1,46 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { DatabaseSync } from "node:sqlite";
4
+ import { projectDbPath } from "../project.js";
5
+ import { sendJson } from "../server.js";
6
+ import { runLcmMigrations } from "../../db/migration.js";
7
+ import { PromotedStore } from "../../db/promoted.js";
8
+ export function createStoreHandler() {
9
+ return async (_req, res, body) => {
10
+ const input = JSON.parse(body || "{}");
11
+ const { text, tags = [], metadata = {}, cwd } = input;
12
+ if (!text) {
13
+ sendJson(res, 400, { error: "text is required" });
14
+ return;
15
+ }
16
+ const projectPath = cwd || metadata.projectPath || "";
17
+ if (!projectPath) {
18
+ sendJson(res, 400, { error: "cwd or metadata.projectPath is required" });
19
+ return;
20
+ }
21
+ const dbPath = projectDbPath(projectPath);
22
+ mkdirSync(dirname(dbPath), { recursive: true });
23
+ const db = new DatabaseSync(dbPath);
24
+ try {
25
+ // Core: write to SQLite promoted table
26
+ runLcmMigrations(db);
27
+ const store = new PromotedStore(db);
28
+ const id = store.insert({
29
+ content: text,
30
+ tags,
31
+ projectId: metadata.projectId ?? "manual",
32
+ sessionId: metadata.sessionId ?? "manual",
33
+ depth: metadata.depth ?? 0,
34
+ confidence: 1.0,
35
+ });
36
+ sendJson(res, 200, { stored: true, id });
37
+ }
38
+ catch (err) {
39
+ sendJson(res, 500, { error: err instanceof Error ? err.message : "store failed" });
40
+ }
41
+ finally {
42
+ db.close();
43
+ }
44
+ };
45
+ }
46
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/daemon/routes/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,UAAU,kBAAkB;IAChC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QACvC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,IAAI,QAAQ,CAAC,WAAW,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC,CAAC;YACzE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC1C,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,uCAAuC;YACvC,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACrB,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;YAEpC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;gBACtB,OAAO,EAAE,IAAI;gBACb,IAAI;gBACJ,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,QAAQ;gBACzC,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,QAAQ;gBACzC,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;gBAC1B,UAAU,EAAE,GAAG;aAChB,CAAC,CAAC;YAEH,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;QACrF,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type IncomingMessage, type ServerResponse } from "node:http";
2
+ import type { AddressInfo } from "node:net";
3
+ import type { DaemonConfig } from "./config.js";
4
+ import type { ProxyManager } from "./proxy-manager.js";
5
+ export declare const PKG_VERSION: any;
6
+ export type RouteHandler = (req: IncomingMessage, res: ServerResponse, body: string) => Promise<void>;
7
+ export type DaemonInstance = {
8
+ address: () => AddressInfo;
9
+ stop: () => Promise<void>;
10
+ registerRoute: (method: string, path: string, handler: RouteHandler) => void;
11
+ idleTriggered: boolean;
12
+ };
13
+ export type DaemonOptions = {
14
+ proxyManager?: ProxyManager;
15
+ onIdle?: () => void;
16
+ };
17
+ export declare function readBody(req: IncomingMessage): Promise<string>;
18
+ export declare function sendJson(res: ServerResponse, status: number, data: unknown): void;
19
+ export declare function createDaemon(config: DaemonConfig, options?: DaemonOptions): Promise<DaemonInstance>;
@@ -0,0 +1,183 @@
1
+ import { createServer } from "node:http";
2
+ import { readFileSync } from "node:fs";
3
+ import { join, dirname } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { resolveEffectiveProvider, createSummarizer } from "./summarizer.js";
6
+ import { createCompactHandler } from "./routes/compact.js";
7
+ import { createPromoteHandler } from "./routes/promote.js";
8
+ import { createRestoreHandler } from "./routes/restore.js";
9
+ import { createGrepHandler } from "./routes/grep.js";
10
+ import { createSearchHandler } from "./routes/search.js";
11
+ import { createExpandHandler } from "./routes/expand.js";
12
+ import { createDescribeHandler } from "./routes/describe.js";
13
+ import { createStoreHandler } from "./routes/store.js";
14
+ import { createRecentHandler } from "./routes/recent.js";
15
+ import { createIngestHandler } from "./routes/ingest.js";
16
+ import { createPromptSearchHandler } from "./routes/prompt-search.js";
17
+ import { createStatusHandler } from "./routes/status.js";
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ export const PKG_VERSION = (() => {
20
+ try {
21
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "..", "package.json"), "utf-8"));
22
+ return pkg.version;
23
+ }
24
+ catch {
25
+ return "0.0.0";
26
+ }
27
+ })();
28
+ export async function readBody(req) {
29
+ const chunks = [];
30
+ for await (const chunk of req)
31
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
32
+ return Buffer.concat(chunks).toString("utf-8");
33
+ }
34
+ export function sendJson(res, status, data) {
35
+ const body = JSON.stringify(data);
36
+ res.writeHead(status, { "Content-Type": "application/json" });
37
+ res.end(body);
38
+ }
39
+ export async function createDaemon(config, options) {
40
+ const startTime = Date.now();
41
+ const proxyManager = options?.proxyManager;
42
+ const routes = new Map();
43
+ let idleTimer = null;
44
+ let idleTriggered = false;
45
+ const onIdle = options?.onIdle ?? (() => {
46
+ console.log("[lcm] idle timeout — shutting down");
47
+ process.exit(0);
48
+ });
49
+ function resetIdleTimer() {
50
+ if (config.daemon.idleTimeoutMs <= 0)
51
+ return;
52
+ if (idleTimer)
53
+ clearTimeout(idleTimer);
54
+ idleTimer = setTimeout(() => {
55
+ idleTriggered = true;
56
+ onIdle();
57
+ }, config.daemon.idleTimeoutMs);
58
+ }
59
+ routes.set("GET /health", async (_req, res) => sendJson(res, 200, { status: "ok", version: PKG_VERSION, uptime: Math.floor((Date.now() - startTime) / 1000) }));
60
+ routes.set("POST /compact", createCompactHandler(config));
61
+ const promoteSummarizer = () => createSummarizer(resolveEffectiveProvider(config), config);
62
+ routes.set("POST /promote", createPromoteHandler(config, promoteSummarizer));
63
+ routes.set("POST /restore", createRestoreHandler(config));
64
+ routes.set("POST /grep", createGrepHandler(config));
65
+ routes.set("POST /search", createSearchHandler());
66
+ routes.set("POST /expand", createExpandHandler(config));
67
+ routes.set("POST /describe", createDescribeHandler(config));
68
+ routes.set("POST /store", createStoreHandler());
69
+ routes.set("POST /recent", createRecentHandler(config));
70
+ routes.set("POST /ingest", createIngestHandler(config));
71
+ routes.set("POST /prompt-search", createPromptSearchHandler(config));
72
+ // Status handler is registered after listen() when we know the actual port
73
+ // Periodic transcript ingestion scan
74
+ const INGEST_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
75
+ const ingestHandler = createIngestHandler(config);
76
+ const scanForTranscripts = async () => {
77
+ try {
78
+ const { readdirSync, existsSync, readFileSync } = await import("node:fs");
79
+ const { join } = await import("node:path");
80
+ const { homedir } = await import("node:os");
81
+ const projectsDir = join(homedir(), ".lossless-claude", "projects");
82
+ if (!existsSync(projectsDir))
83
+ return;
84
+ for (const entry of readdirSync(projectsDir, { withFileTypes: true })) {
85
+ if (!entry.isDirectory())
86
+ continue;
87
+ const metaPath = join(projectsDir, entry.name, "meta.json");
88
+ if (!existsSync(metaPath))
89
+ continue;
90
+ let meta = {};
91
+ try {
92
+ meta = JSON.parse(readFileSync(metaPath, "utf-8"));
93
+ }
94
+ catch {
95
+ continue;
96
+ }
97
+ if (!meta.cwd)
98
+ continue;
99
+ // Find Claude Code session files for this project's cwd
100
+ const cwdDashed = meta.cwd.replace(/\//g, "-").replace(/^-/, "");
101
+ const sessionsDir = join(homedir(), ".claude", "projects", cwdDashed);
102
+ if (!existsSync(sessionsDir))
103
+ continue;
104
+ for (const file of readdirSync(sessionsDir)) {
105
+ if (!file.endsWith(".jsonl"))
106
+ continue;
107
+ const sessionId = file.replace(".jsonl", "");
108
+ const transcriptPath = join(sessionsDir, file);
109
+ // Use the ingest route logic directly
110
+ const mockReq = {};
111
+ const response = { statusCode: 200, body: "" };
112
+ const mockRes = {
113
+ writeHead: (code) => { response.statusCode = code; },
114
+ end: (data) => { response.body = data; },
115
+ };
116
+ await ingestHandler(mockReq, mockRes, JSON.stringify({
117
+ session_id: sessionId,
118
+ cwd: meta.cwd,
119
+ transcript_path: transcriptPath,
120
+ }));
121
+ }
122
+ }
123
+ }
124
+ catch {
125
+ // non-fatal: periodic scan failure shouldn't crash daemon
126
+ }
127
+ };
128
+ const ingestInterval = setInterval(scanForTranscripts, INGEST_INTERVAL_MS);
129
+ ingestInterval.unref(); // don't prevent process exit
130
+ const server = createServer(async (req, res) => {
131
+ resetIdleTimer();
132
+ const key = `${req.method} ${req.url?.split("?")[0]}`;
133
+ const handler = routes.get(key);
134
+ if (!handler) {
135
+ sendJson(res, 404, { error: "not found" });
136
+ return;
137
+ }
138
+ try {
139
+ await handler(req, res, req.method !== "GET" ? await readBody(req) : "");
140
+ }
141
+ catch (err) {
142
+ sendJson(res, 500, { error: err instanceof Error ? err.message : "internal error" });
143
+ }
144
+ });
145
+ // Start proxy manager if provided (non-fatal on failure)
146
+ if (proxyManager) {
147
+ try {
148
+ await proxyManager.start();
149
+ }
150
+ catch (err) {
151
+ console.warn(`[lcm] claude-server proxy failed to start: ${err instanceof Error ? err.message : err}`);
152
+ }
153
+ }
154
+ return new Promise((resolve) => {
155
+ server.listen(config.daemon.port, "127.0.0.1", () => {
156
+ resetIdleTimer();
157
+ const addr = server.address();
158
+ const actualPort = addr.port;
159
+ // Now that we know the actual port, register the status handler
160
+ routes.set("POST /status", createStatusHandler(config, startTime, actualPort));
161
+ resolve({
162
+ address: () => addr,
163
+ stop: async () => {
164
+ clearInterval(ingestInterval);
165
+ if (idleTimer) {
166
+ clearTimeout(idleTimer);
167
+ idleTimer = null;
168
+ }
169
+ if (proxyManager) {
170
+ try {
171
+ await proxyManager.stop();
172
+ }
173
+ catch { /* non-fatal */ }
174
+ }
175
+ return new Promise((r) => server.close(() => r()));
176
+ },
177
+ registerRoute: (method, path, handler) => routes.set(`${method} ${path}`, handler),
178
+ get idleTriggered() { return idleTriggered; },
179
+ });
180
+ });
181
+ });
182
+ }
183
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/daemon/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { DaemonConfig } from "./config.js";
2
+ import type { LcmSummarizeFn } from "../llm/types.js";
3
+ export type CompactClient = "claude" | "codex";
4
+ export type EffectiveProvider = Exclude<DaemonConfig["llm"]["provider"], "auto">;
5
+ export declare function resolveEffectiveProvider(config: DaemonConfig, client?: CompactClient): EffectiveProvider;
6
+ export declare function createSummarizer(provider: EffectiveProvider, config: DaemonConfig): Promise<LcmSummarizeFn | null>;
7
+ /**
8
+ * Creates a cached summarizer factory for a given DaemonConfig.
9
+ * The returned function lazily creates summarizers per provider and memoizes them.
10
+ */
11
+ export declare function makeSummarizerCache(config: DaemonConfig): (provider: EffectiveProvider) => Promise<LcmSummarizeFn | null>;
@@ -0,0 +1,51 @@
1
+ import { createClaudeProcessSummarizer } from "../llm/claude-process.js";
2
+ import { createCodexProcessSummarizer } from "../llm/codex-process.js";
3
+ import { createMockSummarizer } from "../llm/mock-summarizer.js";
4
+ export function resolveEffectiveProvider(config, client) {
5
+ if (config.llm.provider === "auto") {
6
+ return client === "codex" ? "codex-process" : "claude-process";
7
+ }
8
+ return config.llm.provider;
9
+ }
10
+ export async function createSummarizer(provider, config) {
11
+ // Mock summarizer for E2E testing — deterministic, no LLM calls
12
+ if (config.summarizer?.mock)
13
+ return createMockSummarizer();
14
+ if (provider === "disabled")
15
+ return null;
16
+ if (provider === "claude-process")
17
+ return createClaudeProcessSummarizer();
18
+ if (provider === "codex-process") {
19
+ return createCodexProcessSummarizer({ model: config.llm.model });
20
+ }
21
+ if (provider === "openai") {
22
+ const { createOpenAISummarizer } = await import("../llm/openai.js");
23
+ return createOpenAISummarizer({
24
+ model: config.llm.model,
25
+ baseURL: config.llm.baseURL,
26
+ apiKey: config.llm.apiKey,
27
+ });
28
+ }
29
+ // anthropic
30
+ const { createAnthropicSummarizer } = await import("../llm/anthropic.js");
31
+ return createAnthropicSummarizer({
32
+ model: config.llm.model,
33
+ apiKey: config.llm.apiKey,
34
+ });
35
+ }
36
+ /**
37
+ * Creates a cached summarizer factory for a given DaemonConfig.
38
+ * The returned function lazily creates summarizers per provider and memoizes them.
39
+ */
40
+ export function makeSummarizerCache(config) {
41
+ const cache = new Map();
42
+ return (provider) => {
43
+ let cached = cache.get(provider);
44
+ if (!cached) {
45
+ cached = createSummarizer(provider, config);
46
+ cache.set(provider, cached);
47
+ }
48
+ return cached;
49
+ };
50
+ }
51
+ //# sourceMappingURL=summarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../../src/daemon/summarizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAMjE,MAAM,UAAU,wBAAwB,CAAC,MAAoB,EAAE,MAAsB;IACnF,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QACnC,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAA2B,EAC3B,MAAoB;IAEpB,gEAAgE;IAChE,IAAI,MAAM,CAAC,UAAU,EAAE,IAAI;QAAE,OAAO,oBAAoB,EAAE,CAAC;IAC3D,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,QAAQ,KAAK,gBAAgB;QAAE,OAAO,6BAA6B,EAAE,CAAC;IAC1E,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,OAAO,4BAA4B,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACpE,OAAO,sBAAsB,CAAC;YAC5B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK;YACvB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO;YAC3B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,YAAY;IACZ,MAAM,EAAE,yBAAyB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC1E,OAAO,yBAAyB,CAAC;QAC/B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK;QACvB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAO;KAC3B,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAoB;IACtD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqD,CAAC;IAC3E,OAAO,CAAC,QAA2B,EAAkC,EAAE;QACrE,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC5C,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ export type LcmConfig = {
2
+ enabled: boolean;
3
+ databasePath: string;
4
+ contextThreshold: number;
5
+ freshTailCount: number;
6
+ leafMinFanout: number;
7
+ condensedMinFanout: number;
8
+ condensedMinFanoutHard: number;
9
+ incrementalMaxDepth: number;
10
+ leafChunkTokens: number;
11
+ leafTargetTokens: number;
12
+ condensedTargetTokens: number;
13
+ maxExpandTokens: number;
14
+ largeFileTokenThreshold: number;
15
+ /** Provider override for large-file text summarization. */
16
+ largeFileSummaryProvider: string;
17
+ /** Model override for large-file text summarization. */
18
+ largeFileSummaryModel: string;
19
+ autocompactDisabled: boolean;
20
+ /** IANA timezone for timestamps in summaries (from TZ env or system default) */
21
+ timezone: string;
22
+ /** When true, retroactively delete HEARTBEAT_OK turn cycles from LCM storage. */
23
+ pruneHeartbeatOk: boolean;
24
+ };
25
+ /**
26
+ * Resolve LCM configuration with three-tier precedence:
27
+ * 1. Environment variables (highest — backward compat)
28
+ * 2. Plugin config object (from plugins.entries.lossless-claude.config)
29
+ * 3. Hardcoded defaults (lowest)
30
+ */
31
+ export declare function resolveLcmConfig(env?: NodeJS.ProcessEnv, pluginConfig?: Record<string, unknown>): LcmConfig;
@@ -0,0 +1,83 @@
1
+ import { homedir } from "os";
2
+ import { join } from "path";
3
+ /** Safely coerce an unknown value to a finite number, or return undefined. */
4
+ function toNumber(value) {
5
+ if (typeof value === "number" && Number.isFinite(value))
6
+ return value;
7
+ if (typeof value === "string") {
8
+ const n = Number(value);
9
+ if (Number.isFinite(n))
10
+ return n;
11
+ }
12
+ return undefined;
13
+ }
14
+ /** Safely coerce an unknown value to a boolean, or return undefined. */
15
+ function toBool(value) {
16
+ if (typeof value === "boolean")
17
+ return value;
18
+ if (value === "true")
19
+ return true;
20
+ if (value === "false")
21
+ return false;
22
+ return undefined;
23
+ }
24
+ /** Safely coerce an unknown value to a trimmed non-empty string, or return undefined. */
25
+ function toStr(value) {
26
+ if (typeof value === "string") {
27
+ const trimmed = value.trim();
28
+ return trimmed.length > 0 ? trimmed : undefined;
29
+ }
30
+ return undefined;
31
+ }
32
+ /**
33
+ * Resolve LCM configuration with three-tier precedence:
34
+ * 1. Environment variables (highest — backward compat)
35
+ * 2. Plugin config object (from plugins.entries.lossless-claude.config)
36
+ * 3. Hardcoded defaults (lowest)
37
+ */
38
+ export function resolveLcmConfig(env = process.env, pluginConfig) {
39
+ const pc = pluginConfig ?? {};
40
+ return {
41
+ enabled: env.LCM_ENABLED !== undefined
42
+ ? env.LCM_ENABLED !== "false"
43
+ : toBool(pc.enabled) ?? true,
44
+ databasePath: env.LCM_DATABASE_PATH
45
+ ?? toStr(pc.dbPath)
46
+ ?? toStr(pc.databasePath)
47
+ ?? join(homedir(), ".claude", "lcm.db"),
48
+ contextThreshold: (env.LCM_CONTEXT_THRESHOLD !== undefined ? parseFloat(env.LCM_CONTEXT_THRESHOLD) : undefined)
49
+ ?? toNumber(pc.contextThreshold) ?? 0.75,
50
+ freshTailCount: (env.LCM_FRESH_TAIL_COUNT !== undefined ? parseInt(env.LCM_FRESH_TAIL_COUNT, 10) : undefined)
51
+ ?? toNumber(pc.freshTailCount) ?? 32,
52
+ leafMinFanout: (env.LCM_LEAF_MIN_FANOUT !== undefined ? parseInt(env.LCM_LEAF_MIN_FANOUT, 10) : undefined)
53
+ ?? toNumber(pc.leafMinFanout) ?? 8,
54
+ condensedMinFanout: (env.LCM_CONDENSED_MIN_FANOUT !== undefined ? parseInt(env.LCM_CONDENSED_MIN_FANOUT, 10) : undefined)
55
+ ?? toNumber(pc.condensedMinFanout) ?? 4,
56
+ condensedMinFanoutHard: (env.LCM_CONDENSED_MIN_FANOUT_HARD !== undefined ? parseInt(env.LCM_CONDENSED_MIN_FANOUT_HARD, 10) : undefined)
57
+ ?? toNumber(pc.condensedMinFanoutHard) ?? 2,
58
+ incrementalMaxDepth: (env.LCM_INCREMENTAL_MAX_DEPTH !== undefined ? parseInt(env.LCM_INCREMENTAL_MAX_DEPTH, 10) : undefined)
59
+ ?? toNumber(pc.incrementalMaxDepth) ?? 0,
60
+ leafChunkTokens: (env.LCM_LEAF_CHUNK_TOKENS !== undefined ? parseInt(env.LCM_LEAF_CHUNK_TOKENS, 10) : undefined)
61
+ ?? toNumber(pc.leafChunkTokens) ?? 20000,
62
+ leafTargetTokens: (env.LCM_LEAF_TARGET_TOKENS !== undefined ? parseInt(env.LCM_LEAF_TARGET_TOKENS, 10) : undefined)
63
+ ?? toNumber(pc.leafTargetTokens) ?? 1200,
64
+ condensedTargetTokens: (env.LCM_CONDENSED_TARGET_TOKENS !== undefined ? parseInt(env.LCM_CONDENSED_TARGET_TOKENS, 10) : undefined)
65
+ ?? toNumber(pc.condensedTargetTokens) ?? 2000,
66
+ maxExpandTokens: (env.LCM_MAX_EXPAND_TOKENS !== undefined ? parseInt(env.LCM_MAX_EXPAND_TOKENS, 10) : undefined)
67
+ ?? toNumber(pc.maxExpandTokens) ?? 4000,
68
+ largeFileTokenThreshold: (env.LCM_LARGE_FILE_TOKEN_THRESHOLD !== undefined ? parseInt(env.LCM_LARGE_FILE_TOKEN_THRESHOLD, 10) : undefined)
69
+ ?? toNumber(pc.largeFileThresholdTokens)
70
+ ?? toNumber(pc.largeFileTokenThreshold)
71
+ ?? 25000,
72
+ largeFileSummaryProvider: env.LCM_LARGE_FILE_SUMMARY_PROVIDER?.trim() ?? toStr(pc.largeFileSummaryProvider) ?? "",
73
+ largeFileSummaryModel: env.LCM_LARGE_FILE_SUMMARY_MODEL?.trim() ?? toStr(pc.largeFileSummaryModel) ?? "",
74
+ autocompactDisabled: env.LCM_AUTOCOMPACT_DISABLED !== undefined
75
+ ? env.LCM_AUTOCOMPACT_DISABLED === "true"
76
+ : toBool(pc.autocompactDisabled) ?? false,
77
+ timezone: env.TZ ?? toStr(pc.timezone) ?? Intl.DateTimeFormat().resolvedOptions().timeZone,
78
+ pruneHeartbeatOk: env.LCM_PRUNE_HEARTBEAT_OK !== undefined
79
+ ? env.LCM_PRUNE_HEARTBEAT_OK === "true"
80
+ : toBool(pc.pruneHeartbeatOk) ?? false,
81
+ };
82
+ }
83
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/db/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AA2B5B,8EAA8E;AAC9E,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,wEAAwE;AACxE,SAAS,MAAM,CAAC,KAAc;IAC5B,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7C,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yFAAyF;AACzF,SAAS,KAAK,CAAC,KAAc;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAyB,OAAO,CAAC,GAAG,EACpC,YAAsC;IAEtC,MAAM,EAAE,GAAG,YAAY,IAAI,EAAE,CAAC;IAE9B,OAAO;QACL,OAAO,EACL,GAAG,CAAC,WAAW,KAAK,SAAS;YAC3B,CAAC,CAAC,GAAG,CAAC,WAAW,KAAK,OAAO;YAC7B,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI;QAChC,YAAY,EACV,GAAG,CAAC,iBAAiB;eAClB,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;eAChB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC;eACtB,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC;QACzC,gBAAgB,EACd,CAAC,GAAG,CAAC,qBAAqB,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eACxF,QAAQ,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,IAAI;QAC5C,cAAc,EACZ,CAAC,GAAG,CAAC,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eACxF,QAAQ,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE;QACxC,aAAa,EACX,CAAC,GAAG,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eACtF,QAAQ,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC;QACtC,kBAAkB,EAChB,CAAC,GAAG,CAAC,wBAAwB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAChG,QAAQ,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC;QAC3C,sBAAsB,EACpB,CAAC,GAAG,CAAC,6BAA6B,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAC1G,QAAQ,CAAC,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC;QAC/C,mBAAmB,EACjB,CAAC,GAAG,CAAC,yBAAyB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAClG,QAAQ,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAC5C,eAAe,EACb,CAAC,GAAG,CAAC,qBAAqB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAC1F,QAAQ,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,KAAK;QAC5C,gBAAgB,EACd,CAAC,GAAG,CAAC,sBAAsB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAC5F,QAAQ,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,IAAI;QAC5C,qBAAqB,EACnB,CAAC,GAAG,CAAC,2BAA2B,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eACtG,QAAQ,CAAC,EAAE,CAAC,qBAAqB,CAAC,IAAI,IAAI;QACjD,eAAe,EACb,CAAC,GAAG,CAAC,qBAAqB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAC1F,QAAQ,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,IAAI;QAC3C,uBAAuB,EACrB,CAAC,GAAG,CAAC,8BAA8B,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eAC5G,QAAQ,CAAC,EAAE,CAAC,wBAAwB,CAAC;eACrC,QAAQ,CAAC,EAAE,CAAC,uBAAuB,CAAC;eACpC,KAAK;QACZ,wBAAwB,EACtB,GAAG,CAAC,+BAA+B,EAAE,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAAC,IAAI,EAAE;QACzF,qBAAqB,EACnB,GAAG,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAAC,IAAI,EAAE;QACnF,mBAAmB,EACjB,GAAG,CAAC,wBAAwB,KAAK,SAAS;YACxC,CAAC,CAAC,GAAG,CAAC,wBAAwB,KAAK,MAAM;YACzC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,KAAK;QAC7C,QAAQ,EAAE,GAAG,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;QAC1F,gBAAgB,EACd,GAAG,CAAC,sBAAsB,KAAK,SAAS;YACtC,CAAC,CAAC,GAAG,CAAC,sBAAsB,KAAK,MAAM;YACvC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,KAAK;KAC3C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ export declare function getLcmConnection(dbPath: string): DatabaseSync;
3
+ export declare function closeLcmConnection(dbPath?: string): void;
@@ -0,0 +1,62 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { mkdirSync } from "fs";
3
+ import { dirname } from "path";
4
+ const _connections = new Map();
5
+ function isConnectionHealthy(db) {
6
+ try {
7
+ db.prepare("SELECT 1").get();
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ function forceCloseConnection(entry) {
15
+ try {
16
+ entry.db.close();
17
+ }
18
+ catch {
19
+ // Ignore close failures; caller is already replacing/removing this handle.
20
+ }
21
+ }
22
+ export function getLcmConnection(dbPath) {
23
+ const existing = _connections.get(dbPath);
24
+ if (existing) {
25
+ if (isConnectionHealthy(existing.db)) {
26
+ existing.refs += 1;
27
+ return existing.db;
28
+ }
29
+ forceCloseConnection(existing);
30
+ _connections.delete(dbPath);
31
+ }
32
+ // Ensure parent directory exists
33
+ mkdirSync(dirname(dbPath), { recursive: true });
34
+ const db = new DatabaseSync(dbPath);
35
+ // Enable WAL mode for better concurrent read performance
36
+ db.exec("PRAGMA journal_mode = WAL");
37
+ // Wait up to 5 seconds on busy instead of failing immediately
38
+ db.exec("PRAGMA busy_timeout = 5000");
39
+ // Enable foreign key enforcement
40
+ db.exec("PRAGMA foreign_keys = ON");
41
+ _connections.set(dbPath, { db, refs: 1 });
42
+ return db;
43
+ }
44
+ export function closeLcmConnection(dbPath) {
45
+ if (typeof dbPath === "string" && dbPath.trim()) {
46
+ const entry = _connections.get(dbPath);
47
+ if (!entry) {
48
+ return;
49
+ }
50
+ entry.refs = Math.max(0, entry.refs - 1);
51
+ if (entry.refs === 0) {
52
+ forceCloseConnection(entry);
53
+ _connections.delete(dbPath);
54
+ }
55
+ return;
56
+ }
57
+ for (const entry of _connections.values()) {
58
+ forceCloseConnection(entry);
59
+ }
60
+ _connections.clear();
61
+ }
62
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/db/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAO/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;AAExD,SAAS,mBAAmB,CAAC,EAAgB;IAC3C,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAsB;IAClD,IAAI,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;IAC7E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;YACnB,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QACD,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC/B,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,iCAAiC;IACjC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhD,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IAEpC,yDAAyD;IACzD,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACrC,8DAA8D;IAC9D,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACtC,iCAAiC;IACjC,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAEpC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1C,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAe;IAChD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC5B,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO;IACT,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1C,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { DatabaseSync } from "node:sqlite";
2
+ export type LcmDbFeatures = {
3
+ fts5Available: boolean;
4
+ };
5
+ /**
6
+ * Detect SQLite features exposed by the current Node runtime.
7
+ *
8
+ * The result is cached per DatabaseSync handle because the probe is runtime-
9
+ * specific, not database-file-specific.
10
+ */
11
+ export declare function getLcmDbFeatures(db: DatabaseSync): LcmDbFeatures;