@jacques-ai/core 0.0.7-alpha.1

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 (341) hide show
  1. package/dist/archive/archive-store.d.ts +166 -0
  2. package/dist/archive/archive-store.d.ts.map +1 -0
  3. package/dist/archive/archive-store.js +612 -0
  4. package/dist/archive/archive-store.js.map +1 -0
  5. package/dist/archive/bulk-archive.d.ts +63 -0
  6. package/dist/archive/bulk-archive.d.ts.map +1 -0
  7. package/dist/archive/bulk-archive.js +315 -0
  8. package/dist/archive/bulk-archive.js.map +1 -0
  9. package/dist/archive/filename-utils.d.ts +39 -0
  10. package/dist/archive/filename-utils.d.ts.map +1 -0
  11. package/dist/archive/filename-utils.js +78 -0
  12. package/dist/archive/filename-utils.js.map +1 -0
  13. package/dist/archive/index.d.ts +21 -0
  14. package/dist/archive/index.d.ts.map +1 -0
  15. package/dist/archive/index.js +45 -0
  16. package/dist/archive/index.js.map +1 -0
  17. package/dist/archive/manifest-extractor.d.ts +40 -0
  18. package/dist/archive/manifest-extractor.d.ts.map +1 -0
  19. package/dist/archive/manifest-extractor.js +456 -0
  20. package/dist/archive/manifest-extractor.js.map +1 -0
  21. package/dist/archive/migration.d.ts +59 -0
  22. package/dist/archive/migration.d.ts.map +1 -0
  23. package/dist/archive/migration.js +172 -0
  24. package/dist/archive/migration.js.map +1 -0
  25. package/dist/archive/plan-cataloger.d.ts +24 -0
  26. package/dist/archive/plan-cataloger.d.ts.map +1 -0
  27. package/dist/archive/plan-cataloger.js +100 -0
  28. package/dist/archive/plan-cataloger.js.map +1 -0
  29. package/dist/archive/plan-extractor.d.ts +84 -0
  30. package/dist/archive/plan-extractor.d.ts.map +1 -0
  31. package/dist/archive/plan-extractor.js +371 -0
  32. package/dist/archive/plan-extractor.js.map +1 -0
  33. package/dist/archive/search-indexer.d.ts +50 -0
  34. package/dist/archive/search-indexer.d.ts.map +1 -0
  35. package/dist/archive/search-indexer.js +294 -0
  36. package/dist/archive/search-indexer.js.map +1 -0
  37. package/dist/archive/subagent-store.d.ts +113 -0
  38. package/dist/archive/subagent-store.d.ts.map +1 -0
  39. package/dist/archive/subagent-store.js +173 -0
  40. package/dist/archive/subagent-store.js.map +1 -0
  41. package/dist/archive/types.d.ts +236 -0
  42. package/dist/archive/types.d.ts.map +1 -0
  43. package/dist/archive/types.js +30 -0
  44. package/dist/archive/types.js.map +1 -0
  45. package/dist/branding.d.ts +9 -0
  46. package/dist/branding.d.ts.map +1 -0
  47. package/dist/branding.js +50 -0
  48. package/dist/branding.js.map +1 -0
  49. package/dist/cache/git-utils.d.ts +36 -0
  50. package/dist/cache/git-utils.d.ts.map +1 -0
  51. package/dist/cache/git-utils.js +160 -0
  52. package/dist/cache/git-utils.js.map +1 -0
  53. package/dist/cache/hidden-projects.d.ts +19 -0
  54. package/dist/cache/hidden-projects.d.ts.map +1 -0
  55. package/dist/cache/hidden-projects.js +48 -0
  56. package/dist/cache/hidden-projects.js.map +1 -0
  57. package/dist/cache/index.d.ts +15 -0
  58. package/dist/cache/index.d.ts.map +1 -0
  59. package/dist/cache/index.js +20 -0
  60. package/dist/cache/index.js.map +1 -0
  61. package/dist/cache/metadata-extractor.d.ts +62 -0
  62. package/dist/cache/metadata-extractor.d.ts.map +1 -0
  63. package/dist/cache/metadata-extractor.js +574 -0
  64. package/dist/cache/metadata-extractor.js.map +1 -0
  65. package/dist/cache/mode-detector.d.ts +19 -0
  66. package/dist/cache/mode-detector.d.ts.map +1 -0
  67. package/dist/cache/mode-detector.js +161 -0
  68. package/dist/cache/mode-detector.js.map +1 -0
  69. package/dist/cache/persistence.d.ts +39 -0
  70. package/dist/cache/persistence.d.ts.map +1 -0
  71. package/dist/cache/persistence.js +98 -0
  72. package/dist/cache/persistence.js.map +1 -0
  73. package/dist/cache/project-discovery.d.ts +41 -0
  74. package/dist/cache/project-discovery.d.ts.map +1 -0
  75. package/dist/cache/project-discovery.js +212 -0
  76. package/dist/cache/project-discovery.js.map +1 -0
  77. package/dist/cache/session-index.d.ts +258 -0
  78. package/dist/cache/session-index.d.ts.map +1 -0
  79. package/dist/cache/session-index.js +1030 -0
  80. package/dist/cache/session-index.js.map +1 -0
  81. package/dist/cache/types.d.ts +159 -0
  82. package/dist/cache/types.d.ts.map +1 -0
  83. package/dist/cache/types.js +29 -0
  84. package/dist/cache/types.js.map +1 -0
  85. package/dist/catalog/bulk-extractor.d.ts +18 -0
  86. package/dist/catalog/bulk-extractor.d.ts.map +1 -0
  87. package/dist/catalog/bulk-extractor.js +150 -0
  88. package/dist/catalog/bulk-extractor.js.map +1 -0
  89. package/dist/catalog/extractor.d.ts +53 -0
  90. package/dist/catalog/extractor.d.ts.map +1 -0
  91. package/dist/catalog/extractor.js +522 -0
  92. package/dist/catalog/extractor.js.map +1 -0
  93. package/dist/catalog/index.d.ts +10 -0
  94. package/dist/catalog/index.d.ts.map +1 -0
  95. package/dist/catalog/index.js +11 -0
  96. package/dist/catalog/index.js.map +1 -0
  97. package/dist/catalog/types.d.ts +134 -0
  98. package/dist/catalog/types.d.ts.map +1 -0
  99. package/dist/catalog/types.js +8 -0
  100. package/dist/catalog/types.js.map +1 -0
  101. package/dist/client/index.d.ts +6 -0
  102. package/dist/client/index.d.ts.map +1 -0
  103. package/dist/client/index.js +5 -0
  104. package/dist/client/index.js.map +1 -0
  105. package/dist/client/websocket-client.d.ts +96 -0
  106. package/dist/client/websocket-client.d.ts.map +1 -0
  107. package/dist/client/websocket-client.js +222 -0
  108. package/dist/client/websocket-client.js.map +1 -0
  109. package/dist/context/index.d.ts +13 -0
  110. package/dist/context/index.d.ts.map +1 -0
  111. package/dist/context/index.js +26 -0
  112. package/dist/context/index.js.map +1 -0
  113. package/dist/context/indexer.d.ts +73 -0
  114. package/dist/context/indexer.d.ts.map +1 -0
  115. package/dist/context/indexer.js +233 -0
  116. package/dist/context/indexer.js.map +1 -0
  117. package/dist/context/manager.d.ts +66 -0
  118. package/dist/context/manager.d.ts.map +1 -0
  119. package/dist/context/manager.js +310 -0
  120. package/dist/context/manager.js.map +1 -0
  121. package/dist/context/types.d.ts +149 -0
  122. package/dist/context/types.d.ts.map +1 -0
  123. package/dist/context/types.js +36 -0
  124. package/dist/context/types.js.map +1 -0
  125. package/dist/handoff/catalog.d.ts +54 -0
  126. package/dist/handoff/catalog.d.ts.map +1 -0
  127. package/dist/handoff/catalog.js +121 -0
  128. package/dist/handoff/catalog.js.map +1 -0
  129. package/dist/handoff/generator.d.ts +107 -0
  130. package/dist/handoff/generator.d.ts.map +1 -0
  131. package/dist/handoff/generator.js +603 -0
  132. package/dist/handoff/generator.js.map +1 -0
  133. package/dist/handoff/index.d.ts +13 -0
  134. package/dist/handoff/index.d.ts.map +1 -0
  135. package/dist/handoff/index.js +12 -0
  136. package/dist/handoff/index.js.map +1 -0
  137. package/dist/handoff/llm-generator.d.ts +77 -0
  138. package/dist/handoff/llm-generator.d.ts.map +1 -0
  139. package/dist/handoff/llm-generator.js +513 -0
  140. package/dist/handoff/llm-generator.js.map +1 -0
  141. package/dist/handoff/prompts.d.ts +18 -0
  142. package/dist/handoff/prompts.d.ts.map +1 -0
  143. package/dist/handoff/prompts.js +22 -0
  144. package/dist/handoff/prompts.js.map +1 -0
  145. package/dist/handoff/types.d.ts +28 -0
  146. package/dist/handoff/types.d.ts.map +1 -0
  147. package/dist/handoff/types.js +7 -0
  148. package/dist/handoff/types.js.map +1 -0
  149. package/dist/index.d.ts +56 -0
  150. package/dist/index.d.ts.map +1 -0
  151. package/dist/index.js +132 -0
  152. package/dist/index.js.map +1 -0
  153. package/dist/logging/claude-operations.d.ts +111 -0
  154. package/dist/logging/claude-operations.d.ts.map +1 -0
  155. package/dist/logging/claude-operations.js +132 -0
  156. package/dist/logging/claude-operations.js.map +1 -0
  157. package/dist/logging/error-utils.d.ts +18 -0
  158. package/dist/logging/error-utils.d.ts.map +1 -0
  159. package/dist/logging/error-utils.js +37 -0
  160. package/dist/logging/error-utils.js.map +1 -0
  161. package/dist/logging/index.d.ts +11 -0
  162. package/dist/logging/index.d.ts.map +1 -0
  163. package/dist/logging/index.js +10 -0
  164. package/dist/logging/index.js.map +1 -0
  165. package/dist/logging/logger.d.ts +25 -0
  166. package/dist/logging/logger.d.ts.map +1 -0
  167. package/dist/logging/logger.js +39 -0
  168. package/dist/logging/logger.js.map +1 -0
  169. package/dist/notifications/constants.d.ts +16 -0
  170. package/dist/notifications/constants.d.ts.map +1 -0
  171. package/dist/notifications/constants.js +49 -0
  172. package/dist/notifications/constants.js.map +1 -0
  173. package/dist/notifications/index.d.ts +9 -0
  174. package/dist/notifications/index.d.ts.map +1 -0
  175. package/dist/notifications/index.js +8 -0
  176. package/dist/notifications/index.js.map +1 -0
  177. package/dist/notifications/types.d.ts +28 -0
  178. package/dist/notifications/types.d.ts.map +1 -0
  179. package/dist/notifications/types.js +7 -0
  180. package/dist/notifications/types.js.map +1 -0
  181. package/dist/notifications/utils.d.ts +20 -0
  182. package/dist/notifications/utils.d.ts.map +1 -0
  183. package/dist/notifications/utils.js +37 -0
  184. package/dist/notifications/utils.js.map +1 -0
  185. package/dist/plan/index.d.ts +12 -0
  186. package/dist/plan/index.d.ts.map +1 -0
  187. package/dist/plan/index.js +15 -0
  188. package/dist/plan/index.js.map +1 -0
  189. package/dist/plan/plan-parser.d.ts +33 -0
  190. package/dist/plan/plan-parser.d.ts.map +1 -0
  191. package/dist/plan/plan-parser.js +189 -0
  192. package/dist/plan/plan-parser.js.map +1 -0
  193. package/dist/plan/progress-computer.d.ts +34 -0
  194. package/dist/plan/progress-computer.d.ts.map +1 -0
  195. package/dist/plan/progress-computer.js +211 -0
  196. package/dist/plan/progress-computer.js.map +1 -0
  197. package/dist/plan/progress-matcher.d.ts +34 -0
  198. package/dist/plan/progress-matcher.d.ts.map +1 -0
  199. package/dist/plan/progress-matcher.js +297 -0
  200. package/dist/plan/progress-matcher.js.map +1 -0
  201. package/dist/plan/task-extractor.d.ts +30 -0
  202. package/dist/plan/task-extractor.d.ts.map +1 -0
  203. package/dist/plan/task-extractor.js +435 -0
  204. package/dist/plan/task-extractor.js.map +1 -0
  205. package/dist/plan/types.d.ts +131 -0
  206. package/dist/plan/types.d.ts.map +1 -0
  207. package/dist/plan/types.js +8 -0
  208. package/dist/plan/types.js.map +1 -0
  209. package/dist/project/aggregator.d.ts +43 -0
  210. package/dist/project/aggregator.d.ts.map +1 -0
  211. package/dist/project/aggregator.js +218 -0
  212. package/dist/project/aggregator.js.map +1 -0
  213. package/dist/project/index.d.ts +9 -0
  214. package/dist/project/index.d.ts.map +1 -0
  215. package/dist/project/index.js +9 -0
  216. package/dist/project/index.js.map +1 -0
  217. package/dist/project/types.d.ts +65 -0
  218. package/dist/project/types.d.ts.map +1 -0
  219. package/dist/project/types.js +27 -0
  220. package/dist/project/types.js.map +1 -0
  221. package/dist/session/detector.d.ts +113 -0
  222. package/dist/session/detector.d.ts.map +1 -0
  223. package/dist/session/detector.js +333 -0
  224. package/dist/session/detector.js.map +1 -0
  225. package/dist/session/filters.d.ts +32 -0
  226. package/dist/session/filters.d.ts.map +1 -0
  227. package/dist/session/filters.js +100 -0
  228. package/dist/session/filters.js.map +1 -0
  229. package/dist/session/format-title.d.ts +16 -0
  230. package/dist/session/format-title.d.ts.map +1 -0
  231. package/dist/session/format-title.js +54 -0
  232. package/dist/session/format-title.js.map +1 -0
  233. package/dist/session/index.d.ts +16 -0
  234. package/dist/session/index.d.ts.map +1 -0
  235. package/dist/session/index.js +10 -0
  236. package/dist/session/index.js.map +1 -0
  237. package/dist/session/parser.d.ts +264 -0
  238. package/dist/session/parser.d.ts.map +1 -0
  239. package/dist/session/parser.js +588 -0
  240. package/dist/session/parser.js.map +1 -0
  241. package/dist/session/token-estimator.d.ts +32 -0
  242. package/dist/session/token-estimator.d.ts.map +1 -0
  243. package/dist/session/token-estimator.js +139 -0
  244. package/dist/session/token-estimator.js.map +1 -0
  245. package/dist/session/transformer.d.ts +126 -0
  246. package/dist/session/transformer.d.ts.map +1 -0
  247. package/dist/session/transformer.js +158 -0
  248. package/dist/session/transformer.js.map +1 -0
  249. package/dist/setup/hooks-config.d.ts +35 -0
  250. package/dist/setup/hooks-config.d.ts.map +1 -0
  251. package/dist/setup/hooks-config.js +107 -0
  252. package/dist/setup/hooks-config.js.map +1 -0
  253. package/dist/setup/hooks-symlink.d.ts +17 -0
  254. package/dist/setup/hooks-symlink.d.ts.map +1 -0
  255. package/dist/setup/hooks-symlink.js +89 -0
  256. package/dist/setup/hooks-symlink.js.map +1 -0
  257. package/dist/setup/index.d.ts +13 -0
  258. package/dist/setup/index.d.ts.map +1 -0
  259. package/dist/setup/index.js +12 -0
  260. package/dist/setup/index.js.map +1 -0
  261. package/dist/setup/prerequisites.d.ts +11 -0
  262. package/dist/setup/prerequisites.d.ts.map +1 -0
  263. package/dist/setup/prerequisites.js +72 -0
  264. package/dist/setup/prerequisites.js.map +1 -0
  265. package/dist/setup/settings-merge.d.ts +33 -0
  266. package/dist/setup/settings-merge.d.ts.map +1 -0
  267. package/dist/setup/settings-merge.js +131 -0
  268. package/dist/setup/settings-merge.js.map +1 -0
  269. package/dist/setup/skills-install.d.ts +17 -0
  270. package/dist/setup/skills-install.d.ts.map +1 -0
  271. package/dist/setup/skills-install.js +60 -0
  272. package/dist/setup/skills-install.js.map +1 -0
  273. package/dist/setup/types.d.ts +39 -0
  274. package/dist/setup/types.d.ts.map +1 -0
  275. package/dist/setup/types.js +7 -0
  276. package/dist/setup/types.js.map +1 -0
  277. package/dist/setup/verification.d.ts +9 -0
  278. package/dist/setup/verification.d.ts.map +1 -0
  279. package/dist/setup/verification.js +91 -0
  280. package/dist/setup/verification.js.map +1 -0
  281. package/dist/shortcuts/index.d.ts +8 -0
  282. package/dist/shortcuts/index.d.ts.map +1 -0
  283. package/dist/shortcuts/index.js +6 -0
  284. package/dist/shortcuts/index.js.map +1 -0
  285. package/dist/shortcuts/key-utils.d.ts +54 -0
  286. package/dist/shortcuts/key-utils.d.ts.map +1 -0
  287. package/dist/shortcuts/key-utils.js +129 -0
  288. package/dist/shortcuts/key-utils.js.map +1 -0
  289. package/dist/shortcuts/shortcut-registry.d.ts +37 -0
  290. package/dist/shortcuts/shortcut-registry.d.ts.map +1 -0
  291. package/dist/shortcuts/shortcut-registry.js +322 -0
  292. package/dist/shortcuts/shortcut-registry.js.map +1 -0
  293. package/dist/sources/config.d.ts +91 -0
  294. package/dist/sources/config.d.ts.map +1 -0
  295. package/dist/sources/config.js +229 -0
  296. package/dist/sources/config.js.map +1 -0
  297. package/dist/sources/googledocs.d.ts +43 -0
  298. package/dist/sources/googledocs.d.ts.map +1 -0
  299. package/dist/sources/googledocs.js +298 -0
  300. package/dist/sources/googledocs.js.map +1 -0
  301. package/dist/sources/index.d.ts +14 -0
  302. package/dist/sources/index.d.ts.map +1 -0
  303. package/dist/sources/index.js +19 -0
  304. package/dist/sources/index.js.map +1 -0
  305. package/dist/sources/notion.d.ts +35 -0
  306. package/dist/sources/notion.d.ts.map +1 -0
  307. package/dist/sources/notion.js +352 -0
  308. package/dist/sources/notion.js.map +1 -0
  309. package/dist/sources/obsidian.d.ts +38 -0
  310. package/dist/sources/obsidian.d.ts.map +1 -0
  311. package/dist/sources/obsidian.js +228 -0
  312. package/dist/sources/obsidian.js.map +1 -0
  313. package/dist/sources/types.d.ts +133 -0
  314. package/dist/sources/types.d.ts.map +1 -0
  315. package/dist/sources/types.js +19 -0
  316. package/dist/sources/types.js.map +1 -0
  317. package/dist/storage/index.d.ts +6 -0
  318. package/dist/storage/index.d.ts.map +1 -0
  319. package/dist/storage/index.js +5 -0
  320. package/dist/storage/index.js.map +1 -0
  321. package/dist/storage/writer.d.ts +86 -0
  322. package/dist/storage/writer.d.ts.map +1 -0
  323. package/dist/storage/writer.js +137 -0
  324. package/dist/storage/writer.js.map +1 -0
  325. package/dist/types.d.ts +203 -0
  326. package/dist/types.d.ts.map +1 -0
  327. package/dist/types.js +8 -0
  328. package/dist/types.js.map +1 -0
  329. package/dist/utils/claude-token.d.ts +49 -0
  330. package/dist/utils/claude-token.d.ts.map +1 -0
  331. package/dist/utils/claude-token.js +169 -0
  332. package/dist/utils/claude-token.js.map +1 -0
  333. package/dist/utils/index.d.ts +7 -0
  334. package/dist/utils/index.d.ts.map +1 -0
  335. package/dist/utils/index.js +13 -0
  336. package/dist/utils/index.js.map +1 -0
  337. package/dist/utils/settings.d.ts +100 -0
  338. package/dist/utils/settings.d.ts.map +1 -0
  339. package/dist/utils/settings.js +206 -0
  340. package/dist/utils/settings.js.map +1 -0
  341. package/package.json +54 -0
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Plan Extractor
3
+ *
4
+ * Detects and extracts embedded plans from user messages in sessions.
5
+ * Plans are often embedded when starting from plan mode with "Implement the following plan:".
6
+ */
7
+ import { promises as fs } from "fs";
8
+ import { createHash } from "crypto";
9
+ import { join } from "path";
10
+ import { readProjectIndex, addPlanToIndex } from "../context/indexer.js";
11
+ import { generatePlanFilename, generateVersionedFilename } from "./filename-utils.js";
12
+ import { extractKeywords } from "../plan/plan-parser.js";
13
+ /** Patterns that indicate an embedded plan */
14
+ export const PLAN_TRIGGER_PATTERNS = [
15
+ /^implement the following plan[:\s]*/i,
16
+ /^here is the plan[:\s]*/i,
17
+ /^follow this plan[:\s]*/i,
18
+ ];
19
+ /** Minimum content length after trigger phrase to be considered a valid plan */
20
+ const MIN_PLAN_LENGTH = 100;
21
+ /** Minimum similarity score (0-1) for fuzzy deduplication */
22
+ const MIN_SIMILARITY = 0.75;
23
+ /**
24
+ * Detect embedded plans in session entries.
25
+ * Checks all user messages for plan trigger patterns.
26
+ */
27
+ export function detectEmbeddedPlans(entries) {
28
+ const detected = [];
29
+ entries.forEach((entry, messageIndex) => {
30
+ if (entry.type === "user_message" && entry.content.text) {
31
+ const text = entry.content.text.trim();
32
+ // Check for trigger patterns
33
+ for (const pattern of PLAN_TRIGGER_PATTERNS) {
34
+ const match = text.match(pattern);
35
+ if (match) {
36
+ // Extract content after trigger phrase
37
+ const planContent = text.substring(match[0].length).trim();
38
+ // Validate plan content
39
+ if (planContent.length < MIN_PLAN_LENGTH) {
40
+ continue;
41
+ }
42
+ // Check for markdown heading (basic structure check)
43
+ if (!planContent.includes("#")) {
44
+ continue;
45
+ }
46
+ // Check if this message contains multiple plans
47
+ const plans = splitMultiplePlans(planContent);
48
+ plans.forEach((content, planIndex) => {
49
+ detected.push({
50
+ planContent: content,
51
+ messageIndex,
52
+ planIndex,
53
+ triggeredBy: match[0].trim(),
54
+ });
55
+ });
56
+ // Only match first trigger pattern per message
57
+ break;
58
+ }
59
+ }
60
+ }
61
+ });
62
+ return detected;
63
+ }
64
+ /**
65
+ * Split content that contains multiple plans by top-level headings.
66
+ */
67
+ export function splitMultiplePlans(content) {
68
+ const plans = [];
69
+ const lines = content.split("\n");
70
+ let currentPlan = [];
71
+ let foundFirstHeading = false;
72
+ for (const line of lines) {
73
+ // Check if this is a top-level heading
74
+ if (line.match(/^#\s+/)) {
75
+ // If we already have a plan, save it
76
+ if (foundFirstHeading && currentPlan.length > 0) {
77
+ plans.push(currentPlan.join("\n").trim());
78
+ currentPlan = [];
79
+ }
80
+ foundFirstHeading = true;
81
+ }
82
+ if (foundFirstHeading) {
83
+ currentPlan.push(line);
84
+ }
85
+ }
86
+ // Save the last plan
87
+ if (currentPlan.length > 0) {
88
+ plans.push(currentPlan.join("\n").trim());
89
+ }
90
+ // If no headings found, treat entire content as one plan
91
+ if (plans.length === 0 && content.trim().length > 0) {
92
+ return [content.trim()];
93
+ }
94
+ return plans;
95
+ }
96
+ /**
97
+ * Extract title from plan content.
98
+ * Prefers first markdown heading, falls back to first line.
99
+ */
100
+ export function extractPlanTitle(content) {
101
+ // Try to find first markdown heading
102
+ const headingMatch = content.match(/^#\s+(.+)$/m);
103
+ if (headingMatch) {
104
+ // Strip "Plan:" prefix if present — titles should be just the name
105
+ return headingMatch[1].trim().replace(/^Plan:\s*/i, "");
106
+ }
107
+ // Fallback: use first line
108
+ const firstLine = content.split("\n")[0].trim();
109
+ if (firstLine.length <= 80) {
110
+ return firstLine;
111
+ }
112
+ // Truncate if too long
113
+ return firstLine.substring(0, 77) + "...";
114
+ }
115
+ /**
116
+ * Extract plan body (content without the title heading).
117
+ * Strips the first markdown heading line and returns the rest.
118
+ */
119
+ export function extractPlanBody(content) {
120
+ const lines = content.split("\n");
121
+ let foundFirstHeading = false;
122
+ const bodyLines = [];
123
+ for (const line of lines) {
124
+ // Skip the first heading line
125
+ if (!foundFirstHeading && line.match(/^#\s+/)) {
126
+ foundFirstHeading = true;
127
+ continue;
128
+ }
129
+ bodyLines.push(line);
130
+ }
131
+ // If no heading found, return entire content
132
+ if (!foundFirstHeading) {
133
+ return content.trim();
134
+ }
135
+ return bodyLines.join("\n").trim();
136
+ }
137
+ /**
138
+ * Generate a hash of the plan body only (excludes title).
139
+ * Used for detecting duplicates with different titles but same content.
140
+ */
141
+ export function generateBodyHash(content) {
142
+ const body = extractPlanBody(content);
143
+ const normalized = body
144
+ .replace(/\s+/g, " ")
145
+ .toLowerCase()
146
+ .trim();
147
+ return createHash("sha256").update(normalized).digest("hex");
148
+ }
149
+ /**
150
+ * Generate a plan fingerprint for deduplication.
151
+ * Normalizes content to ignore whitespace differences.
152
+ */
153
+ export function generatePlanFingerprint(content) {
154
+ // Normalize content: remove extra whitespace, lowercase
155
+ const normalized = content
156
+ .replace(/\s+/g, " ")
157
+ .toLowerCase()
158
+ .trim();
159
+ // Generate full content hash
160
+ const contentHash = createHash("sha256")
161
+ .update(normalized)
162
+ .digest("hex");
163
+ // Generate body-only hash (for cross-title dedup)
164
+ const bodyHash = generateBodyHash(content);
165
+ // Extract and normalize title
166
+ const title = extractPlanTitle(content);
167
+ const titleNormalized = title
168
+ .toLowerCase()
169
+ .replace(/[^a-z0-9]+/g, "-")
170
+ .replace(/^-+|-+$/g, "");
171
+ // Calculate length range bucket
172
+ const length = content.length;
173
+ let lengthRange;
174
+ if (length <= 500) {
175
+ lengthRange = "0-500";
176
+ }
177
+ else if (length <= 2000) {
178
+ lengthRange = "501-2000";
179
+ }
180
+ else {
181
+ lengthRange = "2001+";
182
+ }
183
+ return {
184
+ contentHash,
185
+ bodyHash,
186
+ titleNormalized,
187
+ lengthRange,
188
+ };
189
+ }
190
+ /**
191
+ * Calculate text similarity using simple word overlap (Jaccard similarity).
192
+ * Returns a score between 0 (no overlap) and 1 (identical).
193
+ */
194
+ export function calculateSimilarity(text1, text2) {
195
+ const words1 = extractKeywords(text1);
196
+ const words2 = extractKeywords(text2);
197
+ if (words1.size === 0 || words2.size === 0) {
198
+ return 0;
199
+ }
200
+ const intersection = new Set([...words1].filter((w) => words2.has(w)));
201
+ const union = new Set([...words1, ...words2]);
202
+ return intersection.size / union.size;
203
+ }
204
+ /**
205
+ * Find a duplicate plan in the existing catalog.
206
+ * Uses a two-tier approach:
207
+ * 1. Exact contentHash match (full content identical)
208
+ * 2. Exact bodyHash match (same body, different title)
209
+ * 3. Fuzzy similarity >= 75% within same length range (no title gate)
210
+ *
211
+ * Returns the PlanEntry if found, null otherwise.
212
+ */
213
+ export async function findDuplicatePlan(content, projectPath) {
214
+ const fingerprint = generatePlanFingerprint(content);
215
+ const index = await readProjectIndex(projectPath);
216
+ // First pass: check indexed hashes (fast path)
217
+ for (const planEntry of index.plans) {
218
+ // Tier 1: Exact content hash match from index
219
+ if (planEntry.contentHash === fingerprint.contentHash) {
220
+ return planEntry;
221
+ }
222
+ // Tier 2: Body hash match from index (same body, different title)
223
+ if (planEntry.bodyHash === fingerprint.bodyHash) {
224
+ return planEntry;
225
+ }
226
+ }
227
+ // Second pass: read files and check computed hashes + similarity
228
+ for (const planEntry of index.plans) {
229
+ try {
230
+ // Read the plan file - construct absolute path from relative path in index
231
+ const absolutePath = join(projectPath, ".jacques", planEntry.path);
232
+ const planContent = await fs.readFile(absolutePath, "utf-8");
233
+ const existingFingerprint = generatePlanFingerprint(planContent);
234
+ // Tier 1: Exact content hash match (computed)
235
+ if (fingerprint.contentHash === existingFingerprint.contentHash) {
236
+ return planEntry;
237
+ }
238
+ // Tier 2: Body hash match (computed) - catches different titles, same body
239
+ if (fingerprint.bodyHash === existingFingerprint.bodyHash) {
240
+ return planEntry;
241
+ }
242
+ // Tier 3: Fuzzy similarity within same length range (no title gate!)
243
+ if (fingerprint.lengthRange === existingFingerprint.lengthRange) {
244
+ const similarity = calculateSimilarity(content, planContent);
245
+ if (similarity >= MIN_SIMILARITY) {
246
+ return planEntry;
247
+ }
248
+ }
249
+ }
250
+ catch (error) {
251
+ // Plan file not found or unreadable, skip
252
+ continue;
253
+ }
254
+ }
255
+ return null;
256
+ }
257
+ /**
258
+ * Index an embedded plan in the project index.
259
+ * Creates or updates the PlanEntry with session link.
260
+ */
261
+ export async function indexEmbeddedPlan(content, filename, sessionId, projectPath) {
262
+ const plansDir = join(projectPath, ".jacques", "plans");
263
+ await fs.mkdir(plansDir, { recursive: true });
264
+ const planPath = join(plansDir, filename);
265
+ const title = extractPlanTitle(content);
266
+ const now = new Date().toISOString();
267
+ // Check if plan already exists in index
268
+ const index = await readProjectIndex(projectPath);
269
+ const existingPlan = index.plans.find((p) => p.filename === filename);
270
+ if (existingPlan) {
271
+ // Update existing plan: merge session IDs
272
+ const updatedPlan = {
273
+ ...existingPlan,
274
+ updatedAt: now,
275
+ sessions: [...new Set([...existingPlan.sessions, sessionId])],
276
+ };
277
+ // For existing plans, we're just updating sessions array - no file write needed
278
+ await addPlanToIndex(projectPath, updatedPlan);
279
+ return updatedPlan;
280
+ }
281
+ else {
282
+ // Create new plan entry
283
+ const planEntry = {
284
+ id: filename.replace(".md", ""),
285
+ title,
286
+ filename,
287
+ path: `plans/${filename}`, // Relative path (consistent with Write tool plans)
288
+ createdAt: now,
289
+ updatedAt: now,
290
+ sessions: [sessionId],
291
+ };
292
+ // Write file FIRST - this can fail
293
+ try {
294
+ await fs.writeFile(planPath, content, "utf-8");
295
+ }
296
+ catch (error) {
297
+ throw new Error(`Failed to write plan file to ${planPath}: ${error instanceof Error ? error.message : String(error)}`);
298
+ }
299
+ // THEN update index - only if file write succeeded
300
+ await addPlanToIndex(projectPath, planEntry);
301
+ return planEntry;
302
+ }
303
+ }
304
+ /**
305
+ * Extract embedded plans from session entries and save to project.
306
+ * Returns array of PlanReference objects for the manifest.
307
+ */
308
+ export async function extractEmbeddedPlans(entries, projectPath, sessionId) {
309
+ const detected = detectEmbeddedPlans(entries);
310
+ if (detected.length === 0) {
311
+ return [];
312
+ }
313
+ const references = [];
314
+ const seenHashes = new Set();
315
+ for (const { planContent } of detected) {
316
+ try {
317
+ // Check for duplicates within this session
318
+ const fingerprint = generatePlanFingerprint(planContent);
319
+ if (seenHashes.has(fingerprint.contentHash)) {
320
+ continue; // Skip duplicate within same session
321
+ }
322
+ seenHashes.add(fingerprint.contentHash);
323
+ // Check for duplicate in existing catalog
324
+ const duplicate = await findDuplicatePlan(planContent, projectPath);
325
+ let planEntry;
326
+ let filename;
327
+ if (duplicate) {
328
+ // Reuse existing plan, add session link
329
+ planEntry = await indexEmbeddedPlan(planContent, duplicate.filename, sessionId, projectPath);
330
+ filename = duplicate.filename;
331
+ }
332
+ else {
333
+ // Create new plan
334
+ const title = extractPlanTitle(planContent);
335
+ filename = generatePlanFilename(title);
336
+ // Check for filename collision
337
+ const plansDir = join(projectPath, ".jacques", "plans");
338
+ const planPath = join(plansDir, filename);
339
+ try {
340
+ await fs.access(planPath);
341
+ // File exists with different content, create versioned filename
342
+ filename = await generateVersionedFilename(plansDir, filename);
343
+ }
344
+ catch {
345
+ // File doesn't exist, we can use this filename
346
+ }
347
+ planEntry = await indexEmbeddedPlan(planContent, filename, sessionId, projectPath);
348
+ }
349
+ // Create reference for manifest
350
+ // Note: path must be absolute for actual file access, even though index stores relative path
351
+ const absolutePath = join(projectPath, ".jacques", "plans", filename);
352
+ references.push({
353
+ path: absolutePath,
354
+ name: filename,
355
+ archivedPath: `plans/${filename}`,
356
+ source: "embedded",
357
+ });
358
+ }
359
+ catch (error) {
360
+ // Non-blocking: log and continue with detailed error info
361
+ console.error("Failed to extract embedded plan:", {
362
+ error: error instanceof Error ? error.message : String(error),
363
+ planContent: planContent.substring(0, 100) + "...",
364
+ projectPath,
365
+ sessionId,
366
+ });
367
+ }
368
+ }
369
+ return references;
370
+ }
371
+ //# sourceMappingURL=plan-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-extractor.js","sourceRoot":"","sources":["../../src/archive/plan-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Search Indexer
3
+ *
4
+ * Builds and maintains a keyword inverted index for conversation search.
5
+ */
6
+ import type { ConversationManifest, SearchIndex } from "./types.js";
7
+ /**
8
+ * Tokenize text into keywords.
9
+ */
10
+ export declare function tokenize(text: string): string[];
11
+ /**
12
+ * Extract keywords from a file path.
13
+ * "src/auth/jwt.ts" → ["src", "auth", "jwt", "ts"]
14
+ */
15
+ export declare function extractPathKeywords(filePath: string): string[];
16
+ /**
17
+ * Extract all keywords from a manifest with field attribution.
18
+ */
19
+ export declare function extractKeywordsWithFields(manifest: ConversationManifest): Array<{
20
+ keyword: string;
21
+ field: string;
22
+ score: number;
23
+ }>;
24
+ /**
25
+ * Add a conversation to the search index.
26
+ */
27
+ export declare function addToIndex(index: SearchIndex, manifest: ConversationManifest): SearchIndex;
28
+ /**
29
+ * Remove a conversation from the search index.
30
+ * @param projectId The projectId (encoded path) or projectSlug for old data
31
+ */
32
+ export declare function removeFromIndex(index: SearchIndex, manifestId: string, projectId: string): SearchIndex;
33
+ /**
34
+ * Search the index for matching conversations.
35
+ * Returns manifest IDs sorted by relevance score.
36
+ */
37
+ export declare function searchIndex(index: SearchIndex, query: string): Array<{
38
+ id: string;
39
+ score: number;
40
+ }>;
41
+ /**
42
+ * Get index statistics.
43
+ */
44
+ export declare function getIndexStats(index: SearchIndex): {
45
+ totalConversations: number;
46
+ totalKeywords: number;
47
+ totalProjects: number;
48
+ averageKeywordsPerConversation: number;
49
+ };
50
+ //# sourceMappingURL=search-indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-indexer.d.ts","sourceRoot":"","sources":["../../src/archive/search-indexer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,WAAW,EAEZ,MAAM,YAAY,CAAC;AAuGpB;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAK9D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,oBAAoB,GAC7B,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA+D1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,oBAAoB,GAC7B,WAAW,CAuDb;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,WAAW,CAgCb;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA2BtC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B,EAAE,MAAM,CAAC;CACxC,CAaA"}