claude-code-workflow 6.2.2 → 6.2.4

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 (346) hide show
  1. package/ccw/dist/cli.d.ts +2 -0
  2. package/ccw/dist/cli.d.ts.map +1 -0
  3. package/ccw/dist/cli.js +219 -0
  4. package/ccw/dist/cli.js.map +1 -0
  5. package/ccw/dist/commands/cli.d.ts +32 -0
  6. package/ccw/dist/commands/cli.d.ts.map +1 -0
  7. package/ccw/dist/commands/cli.js +619 -0
  8. package/ccw/dist/commands/cli.js.map +1 -0
  9. package/ccw/dist/commands/core-memory.d.ts +32 -0
  10. package/ccw/dist/commands/core-memory.d.ts.map +1 -0
  11. package/ccw/dist/commands/core-memory.js +640 -0
  12. package/ccw/dist/commands/core-memory.js.map +1 -0
  13. package/ccw/dist/commands/hook.d.ts +16 -0
  14. package/ccw/dist/commands/hook.d.ts.map +1 -0
  15. package/ccw/dist/commands/hook.js +276 -0
  16. package/ccw/dist/commands/hook.js.map +1 -0
  17. package/ccw/dist/commands/install.d.ts +12 -0
  18. package/ccw/dist/commands/install.d.ts.map +1 -0
  19. package/ccw/dist/commands/install.js +443 -0
  20. package/ccw/dist/commands/install.js.map +1 -0
  21. package/ccw/dist/commands/list.d.ts +5 -0
  22. package/ccw/dist/commands/list.d.ts.map +1 -0
  23. package/ccw/dist/commands/list.js +32 -0
  24. package/ccw/dist/commands/list.js.map +1 -0
  25. package/ccw/dist/commands/memory.d.ts +57 -0
  26. package/ccw/dist/commands/memory.d.ts.map +1 -0
  27. package/ccw/dist/commands/memory.js +890 -0
  28. package/ccw/dist/commands/memory.js.map +1 -0
  29. package/ccw/dist/commands/serve.d.ts +12 -0
  30. package/ccw/dist/commands/serve.d.ts.map +1 -0
  31. package/ccw/dist/commands/serve.js +63 -0
  32. package/ccw/dist/commands/serve.js.map +1 -0
  33. package/ccw/dist/commands/session-path-resolver.d.ts +45 -0
  34. package/ccw/dist/commands/session-path-resolver.d.ts.map +1 -0
  35. package/ccw/dist/commands/session-path-resolver.js +302 -0
  36. package/ccw/dist/commands/session-path-resolver.js.map +1 -0
  37. package/ccw/dist/commands/session.d.ts +12 -0
  38. package/ccw/dist/commands/session.d.ts.map +1 -0
  39. package/ccw/dist/commands/session.js +954 -0
  40. package/ccw/dist/commands/session.js.map +1 -0
  41. package/ccw/dist/commands/stop.d.ts +11 -0
  42. package/ccw/dist/commands/stop.d.ts.map +1 -0
  43. package/ccw/dist/commands/stop.js +96 -0
  44. package/ccw/dist/commands/stop.js.map +1 -0
  45. package/ccw/dist/commands/tool.d.ts +29 -0
  46. package/ccw/dist/commands/tool.d.ts.map +1 -0
  47. package/ccw/dist/commands/tool.js +173 -0
  48. package/ccw/dist/commands/tool.js.map +1 -0
  49. package/ccw/dist/commands/uninstall.d.ts +9 -0
  50. package/ccw/dist/commands/uninstall.d.ts.map +1 -0
  51. package/ccw/dist/commands/uninstall.js +239 -0
  52. package/ccw/dist/commands/uninstall.js.map +1 -0
  53. package/ccw/dist/commands/upgrade.d.ts +10 -0
  54. package/ccw/dist/commands/upgrade.d.ts.map +1 -0
  55. package/ccw/dist/commands/upgrade.js +288 -0
  56. package/ccw/dist/commands/upgrade.js.map +1 -0
  57. package/ccw/dist/commands/view.d.ts +14 -0
  58. package/ccw/dist/commands/view.d.ts.map +1 -0
  59. package/ccw/dist/commands/view.js +100 -0
  60. package/ccw/dist/commands/view.js.map +1 -0
  61. package/ccw/dist/config/storage-paths.d.ts +184 -0
  62. package/ccw/dist/config/storage-paths.d.ts.map +1 -0
  63. package/ccw/dist/config/storage-paths.js +536 -0
  64. package/ccw/dist/config/storage-paths.js.map +1 -0
  65. package/ccw/dist/core/cache-manager.d.ts +80 -0
  66. package/ccw/dist/core/cache-manager.d.ts.map +1 -0
  67. package/ccw/dist/core/cache-manager.js +260 -0
  68. package/ccw/dist/core/cache-manager.js.map +1 -0
  69. package/ccw/dist/core/claude-freshness.d.ts +53 -0
  70. package/ccw/dist/core/claude-freshness.d.ts.map +1 -0
  71. package/ccw/dist/core/claude-freshness.js +232 -0
  72. package/ccw/dist/core/claude-freshness.js.map +1 -0
  73. package/ccw/dist/core/core-memory-store.d.ts +320 -0
  74. package/ccw/dist/core/core-memory-store.d.ts.map +1 -0
  75. package/ccw/dist/core/core-memory-store.js +1177 -0
  76. package/ccw/dist/core/core-memory-store.js.map +1 -0
  77. package/ccw/dist/core/dashboard-generator-patch.d.ts +2 -0
  78. package/ccw/dist/core/dashboard-generator-patch.d.ts.map +1 -0
  79. package/ccw/dist/core/dashboard-generator-patch.js +48 -0
  80. package/ccw/dist/core/dashboard-generator-patch.js.map +1 -0
  81. package/ccw/dist/core/dashboard-generator.d.ts +8 -0
  82. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -0
  83. package/ccw/dist/core/dashboard-generator.js +695 -0
  84. package/ccw/dist/core/dashboard-generator.js.map +1 -0
  85. package/ccw/dist/core/data-aggregator.d.ts +145 -0
  86. package/ccw/dist/core/data-aggregator.d.ts.map +1 -0
  87. package/ccw/dist/core/data-aggregator.js +416 -0
  88. package/ccw/dist/core/data-aggregator.js.map +1 -0
  89. package/ccw/dist/core/history-importer.d.ts +102 -0
  90. package/ccw/dist/core/history-importer.d.ts.map +1 -0
  91. package/ccw/dist/core/history-importer.js +493 -0
  92. package/ccw/dist/core/history-importer.js.map +1 -0
  93. package/ccw/dist/core/lite-scanner-complete.d.ts +81 -0
  94. package/ccw/dist/core/lite-scanner-complete.d.ts.map +1 -0
  95. package/ccw/dist/core/lite-scanner-complete.js +368 -0
  96. package/ccw/dist/core/lite-scanner-complete.js.map +1 -0
  97. package/ccw/dist/core/lite-scanner.d.ts +81 -0
  98. package/ccw/dist/core/lite-scanner.d.ts.map +1 -0
  99. package/ccw/dist/core/lite-scanner.js +368 -0
  100. package/ccw/dist/core/lite-scanner.js.map +1 -0
  101. package/ccw/dist/core/manifest.d.ts +88 -0
  102. package/ccw/dist/core/manifest.d.ts.map +1 -0
  103. package/ccw/dist/core/manifest.js +214 -0
  104. package/ccw/dist/core/manifest.js.map +1 -0
  105. package/ccw/dist/core/memory-embedder-bridge.d.ts +83 -0
  106. package/ccw/dist/core/memory-embedder-bridge.d.ts.map +1 -0
  107. package/ccw/dist/core/memory-embedder-bridge.js +181 -0
  108. package/ccw/dist/core/memory-embedder-bridge.js.map +1 -0
  109. package/ccw/dist/core/memory-store.d.ts +249 -0
  110. package/ccw/dist/core/memory-store.d.ts.map +1 -0
  111. package/ccw/dist/core/memory-store.js +781 -0
  112. package/ccw/dist/core/memory-store.js.map +1 -0
  113. package/ccw/dist/core/routes/ccw-routes.d.ts +20 -0
  114. package/ccw/dist/core/routes/ccw-routes.d.ts.map +1 -0
  115. package/ccw/dist/core/routes/ccw-routes.js +70 -0
  116. package/ccw/dist/core/routes/ccw-routes.js.map +1 -0
  117. package/ccw/dist/core/routes/claude-routes.d.ts +19 -0
  118. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -0
  119. package/ccw/dist/core/routes/claude-routes.js +1017 -0
  120. package/ccw/dist/core/routes/claude-routes.js.map +1 -0
  121. package/ccw/dist/core/routes/cli-routes.d.ts +20 -0
  122. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -0
  123. package/ccw/dist/core/routes/cli-routes.js +468 -0
  124. package/ccw/dist/core/routes/cli-routes.js.map +1 -0
  125. package/ccw/dist/core/routes/codexlens-routes.d.ts +20 -0
  126. package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -0
  127. package/ccw/dist/core/routes/codexlens-routes.js +754 -0
  128. package/ccw/dist/core/routes/codexlens-routes.js.map +1 -0
  129. package/ccw/dist/core/routes/core-memory-routes.d.ts +21 -0
  130. package/ccw/dist/core/routes/core-memory-routes.d.ts.map +1 -0
  131. package/ccw/dist/core/routes/core-memory-routes.js +520 -0
  132. package/ccw/dist/core/routes/core-memory-routes.js.map +1 -0
  133. package/ccw/dist/core/routes/files-routes.d.ts +20 -0
  134. package/ccw/dist/core/routes/files-routes.d.ts.map +1 -0
  135. package/ccw/dist/core/routes/files-routes.js +374 -0
  136. package/ccw/dist/core/routes/files-routes.js.map +1 -0
  137. package/ccw/dist/core/routes/graph-routes.d.ts +20 -0
  138. package/ccw/dist/core/routes/graph-routes.d.ts.map +1 -0
  139. package/ccw/dist/core/routes/graph-routes.js +517 -0
  140. package/ccw/dist/core/routes/graph-routes.js.map +1 -0
  141. package/ccw/dist/core/routes/help-routes.d.ts +20 -0
  142. package/ccw/dist/core/routes/help-routes.d.ts.map +1 -0
  143. package/ccw/dist/core/routes/help-routes.js +250 -0
  144. package/ccw/dist/core/routes/help-routes.js.map +1 -0
  145. package/ccw/dist/core/routes/hooks-routes.d.ts +21 -0
  146. package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -0
  147. package/ccw/dist/core/routes/hooks-routes.js +346 -0
  148. package/ccw/dist/core/routes/hooks-routes.js.map +1 -0
  149. package/ccw/dist/core/routes/mcp-routes.d.ts +20 -0
  150. package/ccw/dist/core/routes/mcp-routes.d.ts.map +1 -0
  151. package/ccw/dist/core/routes/mcp-routes.js +1129 -0
  152. package/ccw/dist/core/routes/mcp-routes.js.map +1 -0
  153. package/ccw/dist/core/routes/mcp-templates-db.d.ts +54 -0
  154. package/ccw/dist/core/routes/mcp-templates-db.d.ts.map +1 -0
  155. package/ccw/dist/core/routes/mcp-templates-db.js +226 -0
  156. package/ccw/dist/core/routes/mcp-templates-db.js.map +1 -0
  157. package/ccw/dist/core/routes/memory-routes.d.ts +21 -0
  158. package/ccw/dist/core/routes/memory-routes.d.ts.map +1 -0
  159. package/ccw/dist/core/routes/memory-routes.js +1095 -0
  160. package/ccw/dist/core/routes/memory-routes.js.map +1 -0
  161. package/ccw/dist/core/routes/rules-routes.d.ts +20 -0
  162. package/ccw/dist/core/routes/rules-routes.d.ts.map +1 -0
  163. package/ccw/dist/core/routes/rules-routes.js +442 -0
  164. package/ccw/dist/core/routes/rules-routes.js.map +1 -0
  165. package/ccw/dist/core/routes/session-routes.d.ts +20 -0
  166. package/ccw/dist/core/routes/session-routes.d.ts.map +1 -0
  167. package/ccw/dist/core/routes/session-routes.js +423 -0
  168. package/ccw/dist/core/routes/session-routes.js.map +1 -0
  169. package/ccw/dist/core/routes/skills-routes.d.ts +20 -0
  170. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -0
  171. package/ccw/dist/core/routes/skills-routes.js +533 -0
  172. package/ccw/dist/core/routes/skills-routes.js.map +1 -0
  173. package/ccw/dist/core/routes/status-routes.d.ts +20 -0
  174. package/ccw/dist/core/routes/status-routes.d.ts.map +1 -0
  175. package/ccw/dist/core/routes/status-routes.js +38 -0
  176. package/ccw/dist/core/routes/status-routes.js.map +1 -0
  177. package/ccw/dist/core/routes/system-routes.d.ts +22 -0
  178. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -0
  179. package/ccw/dist/core/routes/system-routes.js +354 -0
  180. package/ccw/dist/core/routes/system-routes.js.map +1 -0
  181. package/ccw/dist/core/server.d.ts +17 -0
  182. package/ccw/dist/core/server.d.ts.map +1 -0
  183. package/ccw/dist/core/server.js +386 -0
  184. package/ccw/dist/core/server.js.map +1 -0
  185. package/ccw/dist/core/session-clustering-service.d.ts +153 -0
  186. package/ccw/dist/core/session-clustering-service.d.ts.map +1 -0
  187. package/ccw/dist/core/session-clustering-service.js +1065 -0
  188. package/ccw/dist/core/session-clustering-service.js.map +1 -0
  189. package/ccw/dist/core/session-scanner.d.ts +32 -0
  190. package/ccw/dist/core/session-scanner.d.ts.map +1 -0
  191. package/ccw/dist/core/session-scanner.js +253 -0
  192. package/ccw/dist/core/session-scanner.js.map +1 -0
  193. package/ccw/dist/core/websocket.d.ts +23 -0
  194. package/ccw/dist/core/websocket.d.ts.map +1 -0
  195. package/ccw/dist/core/websocket.js +168 -0
  196. package/ccw/dist/core/websocket.js.map +1 -0
  197. package/ccw/dist/index.d.ts +10 -0
  198. package/ccw/dist/index.d.ts.map +1 -0
  199. package/ccw/dist/index.js +10 -0
  200. package/ccw/dist/index.js.map +1 -0
  201. package/ccw/dist/mcp-server/index.d.ts +7 -0
  202. package/ccw/dist/mcp-server/index.d.ts.map +1 -0
  203. package/ccw/dist/mcp-server/index.js +157 -0
  204. package/ccw/dist/mcp-server/index.js.map +1 -0
  205. package/ccw/dist/tools/classify-folders.d.ts +26 -0
  206. package/ccw/dist/tools/classify-folders.d.ts.map +1 -0
  207. package/ccw/dist/tools/classify-folders.js +201 -0
  208. package/ccw/dist/tools/classify-folders.js.map +1 -0
  209. package/ccw/dist/tools/cli-config-manager.d.ts +62 -0
  210. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -0
  211. package/ccw/dist/tools/cli-config-manager.js +221 -0
  212. package/ccw/dist/tools/cli-config-manager.js.map +1 -0
  213. package/ccw/dist/tools/cli-executor.d.ts +373 -0
  214. package/ccw/dist/tools/cli-executor.d.ts.map +1 -0
  215. package/ccw/dist/tools/cli-executor.js +1625 -0
  216. package/ccw/dist/tools/cli-executor.js.map +1 -0
  217. package/ccw/dist/tools/cli-history-store.d.ts +330 -0
  218. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -0
  219. package/ccw/dist/tools/cli-history-store.js +916 -0
  220. package/ccw/dist/tools/cli-history-store.js.map +1 -0
  221. package/ccw/dist/tools/codex-lens.d.ts +118 -0
  222. package/ccw/dist/tools/codex-lens.d.ts.map +1 -0
  223. package/ccw/dist/tools/codex-lens.js +962 -0
  224. package/ccw/dist/tools/codex-lens.js.map +1 -0
  225. package/ccw/dist/tools/convert-tokens-to-css.d.ts +14 -0
  226. package/ccw/dist/tools/convert-tokens-to-css.d.ts.map +1 -0
  227. package/ccw/dist/tools/convert-tokens-to-css.js +244 -0
  228. package/ccw/dist/tools/convert-tokens-to-css.js.map +1 -0
  229. package/ccw/dist/tools/core-memory.d.ts +66 -0
  230. package/ccw/dist/tools/core-memory.d.ts.map +1 -0
  231. package/ccw/dist/tools/core-memory.js +324 -0
  232. package/ccw/dist/tools/core-memory.js.map +1 -0
  233. package/ccw/dist/tools/detect-changed-modules.d.ts +24 -0
  234. package/ccw/dist/tools/detect-changed-modules.d.ts.map +1 -0
  235. package/ccw/dist/tools/detect-changed-modules.js +277 -0
  236. package/ccw/dist/tools/detect-changed-modules.js.map +1 -0
  237. package/ccw/dist/tools/discover-design-files.d.ts +36 -0
  238. package/ccw/dist/tools/discover-design-files.d.ts.map +1 -0
  239. package/ccw/dist/tools/discover-design-files.js +147 -0
  240. package/ccw/dist/tools/discover-design-files.js.map +1 -0
  241. package/ccw/dist/tools/edit-file.d.ts +28 -0
  242. package/ccw/dist/tools/edit-file.d.ts.map +1 -0
  243. package/ccw/dist/tools/edit-file.js +479 -0
  244. package/ccw/dist/tools/edit-file.js.map +1 -0
  245. package/ccw/dist/tools/generate-module-docs.d.ts +22 -0
  246. package/ccw/dist/tools/generate-module-docs.d.ts.map +1 -0
  247. package/ccw/dist/tools/generate-module-docs.js +379 -0
  248. package/ccw/dist/tools/generate-module-docs.js.map +1 -0
  249. package/ccw/dist/tools/get-modules-by-depth.d.ts +15 -0
  250. package/ccw/dist/tools/get-modules-by-depth.d.ts.map +1 -0
  251. package/ccw/dist/tools/get-modules-by-depth.js +296 -0
  252. package/ccw/dist/tools/get-modules-by-depth.js.map +1 -0
  253. package/ccw/dist/tools/index.d.ts +55 -0
  254. package/ccw/dist/tools/index.d.ts.map +1 -0
  255. package/ccw/dist/tools/index.js +304 -0
  256. package/ccw/dist/tools/index.js.map +1 -0
  257. package/ccw/dist/tools/native-session-discovery.d.ts +97 -0
  258. package/ccw/dist/tools/native-session-discovery.d.ts.map +1 -0
  259. package/ccw/dist/tools/native-session-discovery.js +700 -0
  260. package/ccw/dist/tools/native-session-discovery.js.map +1 -0
  261. package/ccw/dist/tools/notifier.d.ts +50 -0
  262. package/ccw/dist/tools/notifier.d.ts.map +1 -0
  263. package/ccw/dist/tools/notifier.js +90 -0
  264. package/ccw/dist/tools/notifier.js.map +1 -0
  265. package/ccw/dist/tools/read-file.d.ts +32 -0
  266. package/ccw/dist/tools/read-file.d.ts.map +1 -0
  267. package/ccw/dist/tools/read-file.js +329 -0
  268. package/ccw/dist/tools/read-file.js.map +1 -0
  269. package/ccw/dist/tools/resume-strategy.d.ts +48 -0
  270. package/ccw/dist/tools/resume-strategy.d.ts.map +1 -0
  271. package/ccw/dist/tools/resume-strategy.js +248 -0
  272. package/ccw/dist/tools/resume-strategy.js.map +1 -0
  273. package/ccw/dist/tools/session-content-parser.d.ts +58 -0
  274. package/ccw/dist/tools/session-content-parser.d.ts.map +1 -0
  275. package/ccw/dist/tools/session-content-parser.js +420 -0
  276. package/ccw/dist/tools/session-content-parser.js.map +1 -0
  277. package/ccw/dist/tools/session-manager.d.ts +9 -0
  278. package/ccw/dist/tools/session-manager.d.ts.map +1 -0
  279. package/ccw/dist/tools/session-manager.js +834 -0
  280. package/ccw/dist/tools/session-manager.js.map +1 -0
  281. package/ccw/dist/tools/smart-context.d.ts +35 -0
  282. package/ccw/dist/tools/smart-context.d.ts.map +1 -0
  283. package/ccw/dist/tools/smart-context.js +182 -0
  284. package/ccw/dist/tools/smart-context.js.map +1 -0
  285. package/ccw/dist/tools/smart-search.d.ts +105 -0
  286. package/ccw/dist/tools/smart-search.d.ts.map +1 -0
  287. package/ccw/dist/tools/smart-search.js +1753 -0
  288. package/ccw/dist/tools/smart-search.js.map +1 -0
  289. package/ccw/dist/tools/storage-manager.d.ts +114 -0
  290. package/ccw/dist/tools/storage-manager.d.ts.map +1 -0
  291. package/ccw/dist/tools/storage-manager.js +392 -0
  292. package/ccw/dist/tools/storage-manager.js.map +1 -0
  293. package/ccw/dist/tools/ui-generate-preview.d.ts +39 -0
  294. package/ccw/dist/tools/ui-generate-preview.d.ts.map +1 -0
  295. package/ccw/dist/tools/ui-generate-preview.js +300 -0
  296. package/ccw/dist/tools/ui-generate-preview.js.map +1 -0
  297. package/ccw/dist/tools/ui-instantiate-prototypes.d.ts +75 -0
  298. package/ccw/dist/tools/ui-instantiate-prototypes.d.ts.map +1 -0
  299. package/ccw/dist/tools/ui-instantiate-prototypes.js +256 -0
  300. package/ccw/dist/tools/ui-instantiate-prototypes.js.map +1 -0
  301. package/ccw/dist/tools/update-module-claude.d.ts +80 -0
  302. package/ccw/dist/tools/update-module-claude.d.ts.map +1 -0
  303. package/ccw/dist/tools/update-module-claude.js +351 -0
  304. package/ccw/dist/tools/update-module-claude.js.map +1 -0
  305. package/ccw/dist/tools/write-file.d.ts +19 -0
  306. package/ccw/dist/tools/write-file.d.ts.map +1 -0
  307. package/ccw/dist/tools/write-file.js +193 -0
  308. package/ccw/dist/tools/write-file.js.map +1 -0
  309. package/ccw/dist/types/config.d.ts +11 -0
  310. package/ccw/dist/types/config.d.ts.map +1 -0
  311. package/ccw/dist/types/config.js +2 -0
  312. package/ccw/dist/types/config.js.map +1 -0
  313. package/ccw/dist/types/index.d.ts +4 -0
  314. package/ccw/dist/types/index.d.ts.map +1 -0
  315. package/ccw/dist/types/index.js +4 -0
  316. package/ccw/dist/types/index.js.map +1 -0
  317. package/ccw/dist/types/session.d.ts +20 -0
  318. package/ccw/dist/types/session.d.ts.map +1 -0
  319. package/ccw/dist/types/session.js +2 -0
  320. package/ccw/dist/types/session.js.map +1 -0
  321. package/ccw/dist/types/tool.d.ts +36 -0
  322. package/ccw/dist/types/tool.d.ts.map +1 -0
  323. package/ccw/dist/types/tool.js +11 -0
  324. package/ccw/dist/types/tool.js.map +1 -0
  325. package/ccw/dist/utils/browser-launcher.d.ts +13 -0
  326. package/ccw/dist/utils/browser-launcher.d.ts.map +1 -0
  327. package/ccw/dist/utils/browser-launcher.js +60 -0
  328. package/ccw/dist/utils/browser-launcher.js.map +1 -0
  329. package/ccw/dist/utils/file-utils.d.ts +25 -0
  330. package/ccw/dist/utils/file-utils.d.ts.map +1 -0
  331. package/ccw/dist/utils/file-utils.js +48 -0
  332. package/ccw/dist/utils/file-utils.js.map +1 -0
  333. package/ccw/dist/utils/path-resolver.d.ts +80 -0
  334. package/ccw/dist/utils/path-resolver.d.ts.map +1 -0
  335. package/ccw/dist/utils/path-resolver.js +260 -0
  336. package/ccw/dist/utils/path-resolver.js.map +1 -0
  337. package/ccw/dist/utils/path-validator.d.ts +49 -0
  338. package/ccw/dist/utils/path-validator.d.ts.map +1 -0
  339. package/ccw/dist/utils/path-validator.js +123 -0
  340. package/ccw/dist/utils/path-validator.js.map +1 -0
  341. package/ccw/dist/utils/ui.d.ts +62 -0
  342. package/ccw/dist/utils/ui.d.ts.map +1 -0
  343. package/ccw/dist/utils/ui.js +129 -0
  344. package/ccw/dist/utils/ui.js.map +1 -0
  345. package/ccw/package.json +1 -1
  346. package/package.json +5 -2
@@ -0,0 +1,916 @@
1
+ /**
2
+ * CLI History Store - SQLite Storage Backend
3
+ * Provides persistent storage for CLI execution history with efficient queries
4
+ */
5
+ import Database from 'better-sqlite3';
6
+ import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { parseSessionFile, formatConversation, extractConversationPairs } from './session-content-parser.js';
9
+ import { StoragePaths, ensureStorageDir, getProjectId } from '../config/storage-paths.js';
10
+ /**
11
+ * CLI History Store using SQLite
12
+ */
13
+ export class CliHistoryStore {
14
+ db;
15
+ dbPath;
16
+ projectPath;
17
+ constructor(baseDir) {
18
+ this.projectPath = baseDir;
19
+ // Use centralized storage path
20
+ const paths = StoragePaths.project(baseDir);
21
+ const historyDir = paths.cliHistory;
22
+ ensureStorageDir(historyDir);
23
+ this.dbPath = paths.historyDb;
24
+ this.db = new Database(this.dbPath);
25
+ this.db.pragma('journal_mode = WAL');
26
+ this.db.pragma('synchronous = NORMAL');
27
+ this.initSchema();
28
+ this.migrateFromJson(historyDir);
29
+ }
30
+ /**
31
+ * Initialize database schema
32
+ */
33
+ initSchema() {
34
+ this.db.exec(`
35
+ -- Conversations table (conversation metadata)
36
+ CREATE TABLE IF NOT EXISTS conversations (
37
+ id TEXT PRIMARY KEY,
38
+ created_at TEXT NOT NULL,
39
+ updated_at TEXT NOT NULL,
40
+ tool TEXT NOT NULL,
41
+ model TEXT DEFAULT 'default',
42
+ mode TEXT DEFAULT 'analysis',
43
+ category TEXT DEFAULT 'user',
44
+ total_duration_ms INTEGER DEFAULT 0,
45
+ turn_count INTEGER DEFAULT 0,
46
+ latest_status TEXT DEFAULT 'success',
47
+ prompt_preview TEXT,
48
+ parent_execution_id TEXT,
49
+ FOREIGN KEY (parent_execution_id) REFERENCES conversations(id) ON DELETE SET NULL
50
+ );
51
+
52
+ -- Turns table (individual conversation turns)
53
+ CREATE TABLE IF NOT EXISTS turns (
54
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
55
+ conversation_id TEXT NOT NULL,
56
+ turn_number INTEGER NOT NULL,
57
+ timestamp TEXT NOT NULL,
58
+ prompt TEXT NOT NULL,
59
+ duration_ms INTEGER DEFAULT 0,
60
+ status TEXT DEFAULT 'success',
61
+ exit_code INTEGER,
62
+ stdout TEXT,
63
+ stderr TEXT,
64
+ truncated INTEGER DEFAULT 0,
65
+ FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
66
+ UNIQUE(conversation_id, turn_number)
67
+ );
68
+
69
+ -- Indexes for efficient queries
70
+ CREATE INDEX IF NOT EXISTS idx_conversations_tool ON conversations(tool);
71
+ CREATE INDEX IF NOT EXISTS idx_conversations_status ON conversations(latest_status);
72
+ CREATE INDEX IF NOT EXISTS idx_conversations_category ON conversations(category);
73
+ CREATE INDEX IF NOT EXISTS idx_conversations_updated ON conversations(updated_at DESC);
74
+ CREATE INDEX IF NOT EXISTS idx_conversations_created ON conversations(created_at DESC);
75
+ CREATE INDEX IF NOT EXISTS idx_turns_conversation ON turns(conversation_id);
76
+
77
+ -- Full-text search for prompts
78
+ CREATE VIRTUAL TABLE IF NOT EXISTS turns_fts USING fts5(
79
+ prompt,
80
+ stdout,
81
+ content='turns',
82
+ content_rowid='id'
83
+ );
84
+
85
+ -- Triggers to keep FTS index updated
86
+ CREATE TRIGGER IF NOT EXISTS turns_ai AFTER INSERT ON turns BEGIN
87
+ INSERT INTO turns_fts(rowid, prompt, stdout) VALUES (new.id, new.prompt, new.stdout);
88
+ END;
89
+
90
+ CREATE TRIGGER IF NOT EXISTS turns_ad AFTER DELETE ON turns BEGIN
91
+ INSERT INTO turns_fts(turns_fts, rowid, prompt, stdout) VALUES('delete', old.id, old.prompt, old.stdout);
92
+ END;
93
+
94
+ CREATE TRIGGER IF NOT EXISTS turns_au AFTER UPDATE ON turns BEGIN
95
+ INSERT INTO turns_fts(turns_fts, rowid, prompt, stdout) VALUES('delete', old.id, old.prompt, old.stdout);
96
+ INSERT INTO turns_fts(rowid, prompt, stdout) VALUES (new.id, new.prompt, new.stdout);
97
+ END;
98
+
99
+ -- Native session mapping table (CCW ID <-> Native Session ID)
100
+ CREATE TABLE IF NOT EXISTS native_session_mapping (
101
+ ccw_id TEXT PRIMARY KEY,
102
+ tool TEXT NOT NULL,
103
+ native_session_id TEXT NOT NULL,
104
+ native_session_path TEXT,
105
+ project_hash TEXT,
106
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
107
+ UNIQUE(tool, native_session_id)
108
+ );
109
+
110
+ -- Indexes for native session lookups
111
+ CREATE INDEX IF NOT EXISTS idx_native_tool_session ON native_session_mapping(tool, native_session_id);
112
+ CREATE INDEX IF NOT EXISTS idx_native_session_id ON native_session_mapping(native_session_id);
113
+
114
+ -- Insights analysis history table
115
+ CREATE TABLE IF NOT EXISTS insights (
116
+ id TEXT PRIMARY KEY,
117
+ created_at TEXT NOT NULL,
118
+ tool TEXT NOT NULL,
119
+ prompt_count INTEGER DEFAULT 0,
120
+ patterns TEXT,
121
+ suggestions TEXT,
122
+ raw_output TEXT,
123
+ execution_id TEXT,
124
+ lang TEXT DEFAULT 'en'
125
+ );
126
+
127
+ CREATE INDEX IF NOT EXISTS idx_insights_created ON insights(created_at DESC);
128
+ CREATE INDEX IF NOT EXISTS idx_insights_tool ON insights(tool);
129
+
130
+ -- Reviews table for CLI execution reviews
131
+ CREATE TABLE IF NOT EXISTS reviews (
132
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
133
+ execution_id TEXT NOT NULL UNIQUE,
134
+ status TEXT NOT NULL DEFAULT 'pending',
135
+ rating INTEGER,
136
+ comments TEXT,
137
+ reviewer TEXT,
138
+ created_at TEXT NOT NULL,
139
+ updated_at TEXT NOT NULL,
140
+ FOREIGN KEY (execution_id) REFERENCES conversations(id) ON DELETE CASCADE
141
+ );
142
+
143
+ CREATE INDEX IF NOT EXISTS idx_reviews_execution ON reviews(execution_id);
144
+ CREATE INDEX IF NOT EXISTS idx_reviews_status ON reviews(status);
145
+ CREATE INDEX IF NOT EXISTS idx_reviews_created ON reviews(created_at DESC);
146
+ `);
147
+ // Migration: Add category column if not exists (for existing databases)
148
+ this.migrateSchema();
149
+ }
150
+ /**
151
+ * Migrate schema for existing databases
152
+ */
153
+ migrateSchema() {
154
+ try {
155
+ // Check if columns exist
156
+ const tableInfo = this.db.prepare('PRAGMA table_info(conversations)').all();
157
+ const hasCategory = tableInfo.some(col => col.name === 'category');
158
+ const hasParentExecutionId = tableInfo.some(col => col.name === 'parent_execution_id');
159
+ const hasProjectRoot = tableInfo.some(col => col.name === 'project_root');
160
+ const hasRelativePath = tableInfo.some(col => col.name === 'relative_path');
161
+ if (!hasCategory) {
162
+ console.log('[CLI History] Migrating database: adding category column...');
163
+ this.db.exec(`
164
+ ALTER TABLE conversations ADD COLUMN category TEXT DEFAULT 'user';
165
+ `);
166
+ // Create index separately to handle potential errors
167
+ try {
168
+ this.db.exec(`CREATE INDEX IF NOT EXISTS idx_conversations_category ON conversations(category);`);
169
+ }
170
+ catch (indexErr) {
171
+ console.warn('[CLI History] Category index creation warning:', indexErr.message);
172
+ }
173
+ console.log('[CLI History] Migration complete: category column added');
174
+ }
175
+ if (!hasParentExecutionId) {
176
+ console.log('[CLI History] Migrating database: adding parent_execution_id column...');
177
+ this.db.exec(`
178
+ ALTER TABLE conversations ADD COLUMN parent_execution_id TEXT;
179
+ `);
180
+ try {
181
+ this.db.exec(`CREATE INDEX IF NOT EXISTS idx_conversations_parent ON conversations(parent_execution_id);`);
182
+ }
183
+ catch (indexErr) {
184
+ console.warn('[CLI History] Parent execution index creation warning:', indexErr.message);
185
+ }
186
+ console.log('[CLI History] Migration complete: parent_execution_id column added');
187
+ }
188
+ // Add hierarchical storage support columns
189
+ if (!hasProjectRoot) {
190
+ console.log('[CLI History] Migrating database: adding project_root column for hierarchical storage...');
191
+ this.db.exec(`
192
+ ALTER TABLE conversations ADD COLUMN project_root TEXT;
193
+ `);
194
+ try {
195
+ this.db.exec(`CREATE INDEX IF NOT EXISTS idx_conversations_project_root ON conversations(project_root);`);
196
+ }
197
+ catch (indexErr) {
198
+ console.warn('[CLI History] Project root index creation warning:', indexErr.message);
199
+ }
200
+ console.log('[CLI History] Migration complete: project_root column added');
201
+ }
202
+ if (!hasRelativePath) {
203
+ console.log('[CLI History] Migrating database: adding relative_path column for hierarchical storage...');
204
+ this.db.exec(`
205
+ ALTER TABLE conversations ADD COLUMN relative_path TEXT;
206
+ `);
207
+ console.log('[CLI History] Migration complete: relative_path column added');
208
+ }
209
+ // Add missing timestamp index for turns table (for time-based queries)
210
+ try {
211
+ const indexExists = this.db.prepare(`
212
+ SELECT name FROM sqlite_master
213
+ WHERE type='index' AND name='idx_turns_timestamp'
214
+ `).get();
215
+ if (!indexExists) {
216
+ console.log('[CLI History] Adding missing timestamp index to turns table...');
217
+ this.db.exec(`CREATE INDEX IF NOT EXISTS idx_turns_timestamp ON turns(timestamp DESC);`);
218
+ console.log('[CLI History] Migration complete: turns timestamp index added');
219
+ }
220
+ }
221
+ catch (indexErr) {
222
+ console.warn('[CLI History] Turns timestamp index creation warning:', indexErr.message);
223
+ }
224
+ }
225
+ catch (err) {
226
+ console.error('[CLI History] Migration error:', err.message);
227
+ // Don't throw - allow the store to continue working with existing schema
228
+ }
229
+ }
230
+ /**
231
+ * Migrate existing JSON files to SQLite
232
+ */
233
+ migrateFromJson(historyDir) {
234
+ const migrationMarker = join(historyDir, '.migrated');
235
+ if (existsSync(migrationMarker)) {
236
+ return; // Already migrated
237
+ }
238
+ // Find all date directories
239
+ const dateDirs = readdirSync(historyDir).filter(d => {
240
+ const dirPath = join(historyDir, d);
241
+ return statSync(dirPath).isDirectory() && /^\d{4}-\d{2}-\d{2}$/.test(d);
242
+ });
243
+ let migratedCount = 0;
244
+ for (const dateDir of dateDirs) {
245
+ const dirPath = join(historyDir, dateDir);
246
+ const files = readdirSync(dirPath).filter(f => f.endsWith('.json'));
247
+ for (const file of files) {
248
+ try {
249
+ const filePath = join(dirPath, file);
250
+ const data = JSON.parse(readFileSync(filePath, 'utf8'));
251
+ // Convert to conversation record if legacy format
252
+ const conversation = this.normalizeRecord(data);
253
+ this.saveConversation(conversation);
254
+ migratedCount++;
255
+ // Optionally delete the JSON file after migration
256
+ // unlinkSync(filePath);
257
+ }
258
+ catch (err) {
259
+ console.error(`Failed to migrate ${file}:`, err.message);
260
+ }
261
+ }
262
+ }
263
+ // Create migration marker
264
+ if (migratedCount > 0) {
265
+ require('fs').writeFileSync(migrationMarker, new Date().toISOString());
266
+ console.log(`[CLI History] Migrated ${migratedCount} records to SQLite`);
267
+ }
268
+ }
269
+ /**
270
+ * Normalize legacy record to ConversationRecord format
271
+ */
272
+ normalizeRecord(data) {
273
+ if (data.turns && Array.isArray(data.turns)) {
274
+ return data;
275
+ }
276
+ // Legacy single execution format
277
+ return {
278
+ id: data.id,
279
+ created_at: data.timestamp,
280
+ updated_at: data.timestamp,
281
+ tool: data.tool,
282
+ model: data.model || 'default',
283
+ mode: data.mode || 'analysis',
284
+ category: data.category || 'user',
285
+ total_duration_ms: data.duration_ms || 0,
286
+ turn_count: 1,
287
+ latest_status: data.status || 'success',
288
+ turns: [{
289
+ turn: 1,
290
+ timestamp: data.timestamp,
291
+ prompt: data.prompt,
292
+ duration_ms: data.duration_ms || 0,
293
+ status: data.status || 'success',
294
+ exit_code: data.exit_code,
295
+ output: data.output || { stdout: '', stderr: '', truncated: false }
296
+ }]
297
+ };
298
+ }
299
+ /**
300
+ * Save or update a conversation
301
+ */
302
+ saveConversation(conversation) {
303
+ const promptPreview = conversation.turns.length > 0
304
+ ? conversation.turns[conversation.turns.length - 1].prompt.substring(0, 100)
305
+ : '';
306
+ const upsertConversation = this.db.prepare(`
307
+ INSERT INTO conversations (id, created_at, updated_at, tool, model, mode, category, total_duration_ms, turn_count, latest_status, prompt_preview, parent_execution_id, project_root, relative_path)
308
+ VALUES (@id, @created_at, @updated_at, @tool, @model, @mode, @category, @total_duration_ms, @turn_count, @latest_status, @prompt_preview, @parent_execution_id, @project_root, @relative_path)
309
+ ON CONFLICT(id) DO UPDATE SET
310
+ updated_at = @updated_at,
311
+ total_duration_ms = @total_duration_ms,
312
+ turn_count = @turn_count,
313
+ latest_status = @latest_status,
314
+ prompt_preview = @prompt_preview,
315
+ project_root = @project_root,
316
+ relative_path = @relative_path
317
+ `);
318
+ const upsertTurn = this.db.prepare(`
319
+ INSERT INTO turns (conversation_id, turn_number, timestamp, prompt, duration_ms, status, exit_code, stdout, stderr, truncated)
320
+ VALUES (@conversation_id, @turn_number, @timestamp, @prompt, @duration_ms, @status, @exit_code, @stdout, @stderr, @truncated)
321
+ ON CONFLICT(conversation_id, turn_number) DO UPDATE SET
322
+ timestamp = @timestamp,
323
+ prompt = @prompt,
324
+ duration_ms = @duration_ms,
325
+ status = @status,
326
+ exit_code = @exit_code,
327
+ stdout = @stdout,
328
+ stderr = @stderr,
329
+ truncated = @truncated
330
+ `);
331
+ const transaction = this.db.transaction(() => {
332
+ upsertConversation.run({
333
+ id: conversation.id,
334
+ created_at: conversation.created_at,
335
+ updated_at: conversation.updated_at,
336
+ tool: conversation.tool,
337
+ model: conversation.model,
338
+ mode: conversation.mode,
339
+ category: conversation.category || 'user',
340
+ total_duration_ms: conversation.total_duration_ms,
341
+ turn_count: conversation.turn_count,
342
+ latest_status: conversation.latest_status,
343
+ prompt_preview: promptPreview,
344
+ parent_execution_id: conversation.parent_execution_id || null,
345
+ project_root: this.projectPath,
346
+ relative_path: null // For future hierarchical tracking
347
+ });
348
+ for (const turn of conversation.turns) {
349
+ upsertTurn.run({
350
+ conversation_id: conversation.id,
351
+ turn_number: turn.turn,
352
+ timestamp: turn.timestamp,
353
+ prompt: turn.prompt,
354
+ duration_ms: turn.duration_ms,
355
+ status: turn.status,
356
+ exit_code: turn.exit_code,
357
+ stdout: turn.output.stdout,
358
+ stderr: turn.output.stderr,
359
+ truncated: turn.output.truncated ? 1 : 0
360
+ });
361
+ }
362
+ });
363
+ transaction();
364
+ }
365
+ /**
366
+ * Get conversation by ID
367
+ */
368
+ getConversation(id) {
369
+ const conv = this.db.prepare(`
370
+ SELECT * FROM conversations WHERE id = ?
371
+ `).get(id);
372
+ if (!conv)
373
+ return null;
374
+ const turns = this.db.prepare(`
375
+ SELECT * FROM turns WHERE conversation_id = ? ORDER BY turn_number ASC
376
+ `).all(id);
377
+ return {
378
+ id: conv.id,
379
+ created_at: conv.created_at,
380
+ updated_at: conv.updated_at,
381
+ tool: conv.tool,
382
+ model: conv.model,
383
+ mode: conv.mode,
384
+ category: conv.category || 'user',
385
+ total_duration_ms: conv.total_duration_ms,
386
+ turn_count: conv.turn_count,
387
+ latest_status: conv.latest_status,
388
+ parent_execution_id: conv.parent_execution_id || undefined,
389
+ turns: turns.map(t => ({
390
+ turn: t.turn_number,
391
+ timestamp: t.timestamp,
392
+ prompt: t.prompt,
393
+ duration_ms: t.duration_ms,
394
+ status: t.status,
395
+ exit_code: t.exit_code,
396
+ output: {
397
+ stdout: t.stdout || '',
398
+ stderr: t.stderr || '',
399
+ truncated: !!t.truncated
400
+ }
401
+ }))
402
+ };
403
+ }
404
+ /**
405
+ * Get conversation with native session info
406
+ */
407
+ getConversationWithNativeInfo(id) {
408
+ const conv = this.getConversation(id);
409
+ if (!conv)
410
+ return null;
411
+ const mapping = this.getNativeSessionMapping(id);
412
+ return {
413
+ ...conv,
414
+ hasNativeSession: !!mapping,
415
+ nativeSessionId: mapping?.native_session_id,
416
+ nativeSessionPath: mapping?.native_session_path
417
+ };
418
+ }
419
+ /**
420
+ * Query execution history
421
+ */
422
+ getHistory(options = {}) {
423
+ const { limit = 50, offset = 0, tool, status, category, search, startDate, endDate } = options;
424
+ let whereClause = '1=1';
425
+ const params = {};
426
+ if (tool) {
427
+ whereClause += ' AND tool = @tool';
428
+ params.tool = tool;
429
+ }
430
+ if (status) {
431
+ whereClause += ' AND latest_status = @status';
432
+ params.status = status;
433
+ }
434
+ if (category) {
435
+ whereClause += ' AND category = @category';
436
+ params.category = category;
437
+ }
438
+ if (startDate) {
439
+ whereClause += ' AND created_at >= @startDate';
440
+ params.startDate = startDate;
441
+ }
442
+ if (endDate) {
443
+ whereClause += ' AND created_at <= @endDate';
444
+ params.endDate = endDate;
445
+ }
446
+ // Full-text search
447
+ let joinClause = '';
448
+ if (search) {
449
+ joinClause = `
450
+ INNER JOIN (
451
+ SELECT DISTINCT conversation_id FROM turns t
452
+ INNER JOIN turns_fts ON turns_fts.rowid = t.id
453
+ WHERE turns_fts MATCH @search
454
+ ) AS matched ON c.id = matched.conversation_id
455
+ `;
456
+ params.search = search;
457
+ }
458
+ const countQuery = this.db.prepare(`
459
+ SELECT COUNT(*) as count FROM conversations c ${joinClause} WHERE ${whereClause}
460
+ `);
461
+ const total = countQuery.get(params).count;
462
+ const dataQuery = this.db.prepare(`
463
+ SELECT c.* FROM conversations c ${joinClause}
464
+ WHERE ${whereClause}
465
+ ORDER BY c.updated_at DESC
466
+ LIMIT @limit OFFSET @offset
467
+ `);
468
+ const rows = dataQuery.all({ ...params, limit, offset });
469
+ return {
470
+ total,
471
+ count: rows.length,
472
+ executions: rows.map(r => ({
473
+ id: r.id,
474
+ timestamp: r.created_at,
475
+ updated_at: r.updated_at,
476
+ tool: r.tool,
477
+ status: r.latest_status,
478
+ category: r.category || 'user',
479
+ duration_ms: r.total_duration_ms,
480
+ turn_count: r.turn_count,
481
+ prompt_preview: r.prompt_preview || ''
482
+ }))
483
+ };
484
+ }
485
+ /**
486
+ * Delete a conversation
487
+ */
488
+ deleteConversation(id) {
489
+ try {
490
+ const result = this.db.prepare('DELETE FROM conversations WHERE id = ?').run(id);
491
+ return { success: result.changes > 0 };
492
+ }
493
+ catch (err) {
494
+ return { success: false, error: err.message };
495
+ }
496
+ }
497
+ /**
498
+ * Batch delete conversations
499
+ */
500
+ batchDelete(ids) {
501
+ const deleteStmt = this.db.prepare('DELETE FROM conversations WHERE id = ?');
502
+ const errors = [];
503
+ let deleted = 0;
504
+ const transaction = this.db.transaction(() => {
505
+ for (const id of ids) {
506
+ try {
507
+ const result = deleteStmt.run(id);
508
+ if (result.changes > 0)
509
+ deleted++;
510
+ }
511
+ catch (err) {
512
+ errors.push(`${id}: ${err.message}`);
513
+ }
514
+ }
515
+ });
516
+ transaction();
517
+ return {
518
+ success: true,
519
+ deleted,
520
+ errors: errors.length > 0 ? errors : undefined
521
+ };
522
+ }
523
+ /**
524
+ * Delete conversations by tool
525
+ */
526
+ deleteByTool(tool) {
527
+ const result = this.db.prepare('DELETE FROM conversations WHERE tool = ?').run(tool);
528
+ return { success: true, deleted: result.changes };
529
+ }
530
+ /**
531
+ * Delete all conversations
532
+ */
533
+ deleteAll() {
534
+ const count = this.db.prepare('SELECT COUNT(*) as c FROM conversations').get().c;
535
+ this.db.prepare('DELETE FROM conversations').run();
536
+ return { success: true, deleted: count };
537
+ }
538
+ /**
539
+ * Get statistics
540
+ */
541
+ getStats() {
542
+ const total = this.db.prepare('SELECT COUNT(*) as c FROM conversations').get().c;
543
+ const byToolRows = this.db.prepare(`
544
+ SELECT tool, COUNT(*) as count FROM conversations GROUP BY tool
545
+ `).all();
546
+ const byTool = {};
547
+ for (const row of byToolRows) {
548
+ byTool[row.tool] = row.count;
549
+ }
550
+ const byStatusRows = this.db.prepare(`
551
+ SELECT latest_status, COUNT(*) as count FROM conversations GROUP BY latest_status
552
+ `).all();
553
+ const byStatus = {};
554
+ for (const row of byStatusRows) {
555
+ byStatus[row.latest_status] = row.count;
556
+ }
557
+ const totalDuration = this.db.prepare(`
558
+ SELECT COALESCE(SUM(total_duration_ms), 0) as total FROM conversations
559
+ `).get().total;
560
+ return { total, byTool, byStatus, totalDuration };
561
+ }
562
+ // ========== Native Session Mapping Methods ==========
563
+ /**
564
+ * Save or update native session mapping
565
+ */
566
+ saveNativeSessionMapping(mapping) {
567
+ const stmt = this.db.prepare(`
568
+ INSERT INTO native_session_mapping (ccw_id, tool, native_session_id, native_session_path, project_hash, created_at)
569
+ VALUES (@ccw_id, @tool, @native_session_id, @native_session_path, @project_hash, @created_at)
570
+ ON CONFLICT(ccw_id) DO UPDATE SET
571
+ native_session_id = @native_session_id,
572
+ native_session_path = @native_session_path,
573
+ project_hash = @project_hash
574
+ `);
575
+ stmt.run({
576
+ ccw_id: mapping.ccw_id,
577
+ tool: mapping.tool,
578
+ native_session_id: mapping.native_session_id,
579
+ native_session_path: mapping.native_session_path || null,
580
+ project_hash: mapping.project_hash || null,
581
+ created_at: mapping.created_at || new Date().toISOString()
582
+ });
583
+ }
584
+ /**
585
+ * Get native session ID by CCW ID
586
+ */
587
+ getNativeSessionId(ccwId) {
588
+ const row = this.db.prepare(`
589
+ SELECT native_session_id FROM native_session_mapping WHERE ccw_id = ?
590
+ `).get(ccwId);
591
+ return row?.native_session_id || null;
592
+ }
593
+ /**
594
+ * Get CCW ID by native session ID
595
+ */
596
+ getCcwIdByNativeSession(tool, nativeSessionId) {
597
+ const row = this.db.prepare(`
598
+ SELECT ccw_id FROM native_session_mapping WHERE tool = ? AND native_session_id = ?
599
+ `).get(tool, nativeSessionId);
600
+ return row?.ccw_id || null;
601
+ }
602
+ /**
603
+ * Get full mapping by CCW ID
604
+ */
605
+ getNativeSessionMapping(ccwId) {
606
+ const row = this.db.prepare(`
607
+ SELECT * FROM native_session_mapping WHERE ccw_id = ?
608
+ `).get(ccwId);
609
+ if (!row)
610
+ return null;
611
+ return {
612
+ ccw_id: row.ccw_id,
613
+ tool: row.tool,
614
+ native_session_id: row.native_session_id,
615
+ native_session_path: row.native_session_path,
616
+ project_hash: row.project_hash,
617
+ created_at: row.created_at
618
+ };
619
+ }
620
+ /**
621
+ * Get latest native session mapping for a tool
622
+ */
623
+ getLatestNativeMapping(tool) {
624
+ const row = this.db.prepare(`
625
+ SELECT * FROM native_session_mapping
626
+ WHERE tool = ?
627
+ ORDER BY created_at DESC
628
+ LIMIT 1
629
+ `).get(tool);
630
+ if (!row)
631
+ return null;
632
+ return {
633
+ ccw_id: row.ccw_id,
634
+ tool: row.tool,
635
+ native_session_id: row.native_session_id,
636
+ native_session_path: row.native_session_path,
637
+ project_hash: row.project_hash,
638
+ created_at: row.created_at
639
+ };
640
+ }
641
+ /**
642
+ * Delete native session mapping
643
+ */
644
+ deleteNativeSessionMapping(ccwId) {
645
+ const result = this.db.prepare('DELETE FROM native_session_mapping WHERE ccw_id = ?').run(ccwId);
646
+ return result.changes > 0;
647
+ }
648
+ /**
649
+ * Check if CCW ID has native session mapping
650
+ */
651
+ hasNativeSession(ccwId) {
652
+ const row = this.db.prepare(`
653
+ SELECT 1 FROM native_session_mapping WHERE ccw_id = ? LIMIT 1
654
+ `).get(ccwId);
655
+ return !!row;
656
+ }
657
+ // ========== Native Session Content Methods ==========
658
+ /**
659
+ * Get parsed native session content by CCW ID
660
+ * Returns full conversation with all turns from native session file
661
+ */
662
+ getNativeSessionContent(ccwId) {
663
+ const mapping = this.getNativeSessionMapping(ccwId);
664
+ if (!mapping || !mapping.native_session_path) {
665
+ return null;
666
+ }
667
+ return parseSessionFile(mapping.native_session_path, mapping.tool);
668
+ }
669
+ /**
670
+ * Get formatted conversation text from native session
671
+ */
672
+ getFormattedNativeConversation(ccwId, options) {
673
+ const session = this.getNativeSessionContent(ccwId);
674
+ if (!session) {
675
+ return null;
676
+ }
677
+ return formatConversation(session, options);
678
+ }
679
+ /**
680
+ * Get conversation pairs (user prompt + assistant response) from native session
681
+ */
682
+ getNativeConversationPairs(ccwId) {
683
+ const session = this.getNativeSessionContent(ccwId);
684
+ if (!session) {
685
+ return null;
686
+ }
687
+ return extractConversationPairs(session);
688
+ }
689
+ /**
690
+ * Get conversation with enriched native session data
691
+ * Merges CCW history with native session content
692
+ */
693
+ getEnrichedConversation(ccwId) {
694
+ const ccwConv = this.getConversation(ccwId);
695
+ const nativeSession = this.getNativeSessionContent(ccwId);
696
+ if (!ccwConv && !nativeSession) {
697
+ return null;
698
+ }
699
+ const merged = [];
700
+ // Determine max turn count
701
+ const maxTurns = Math.max(ccwConv?.turn_count || 0, nativeSession?.turns.filter(t => t.role === 'user').length || 0);
702
+ for (let i = 1; i <= maxTurns; i++) {
703
+ const ccwTurn = ccwConv?.turns.find(t => t.turn === i);
704
+ const nativeUserTurn = nativeSession?.turns.find(t => t.turnNumber === i && t.role === 'user');
705
+ const nativeAssistantTurn = nativeSession?.turns.find(t => t.turnNumber === i && t.role === 'assistant');
706
+ merged.push({
707
+ turn: i,
708
+ timestamp: ccwTurn?.timestamp || nativeUserTurn?.timestamp || '',
709
+ ccwPrompt: ccwTurn?.prompt,
710
+ ccwOutput: ccwTurn?.output.stdout,
711
+ nativeUserContent: nativeUserTurn?.content,
712
+ nativeAssistantContent: nativeAssistantTurn?.content,
713
+ nativeThoughts: nativeAssistantTurn?.thoughts,
714
+ nativeToolCalls: nativeAssistantTurn?.toolCalls
715
+ });
716
+ }
717
+ return { ccw: ccwConv, native: nativeSession, merged };
718
+ }
719
+ /**
720
+ * List all conversations with native session info
721
+ */
722
+ getHistoryWithNativeInfo(options = {}) {
723
+ const history = this.getHistory(options);
724
+ const enrichedExecutions = history.executions.map(exec => {
725
+ const mapping = this.getNativeSessionMapping(exec.id);
726
+ return {
727
+ ...exec,
728
+ hasNativeSession: !!mapping,
729
+ nativeSessionId: mapping?.native_session_id,
730
+ nativeSessionPath: mapping?.native_session_path
731
+ };
732
+ });
733
+ return {
734
+ total: history.total,
735
+ count: history.count,
736
+ executions: enrichedExecutions
737
+ };
738
+ }
739
+ // ========== Insights Methods ==========
740
+ /**
741
+ * Save an insights analysis result
742
+ */
743
+ saveInsight(insight) {
744
+ const stmt = this.db.prepare(`
745
+ INSERT OR REPLACE INTO insights (id, created_at, tool, prompt_count, patterns, suggestions, raw_output, execution_id, lang)
746
+ VALUES (@id, @created_at, @tool, @prompt_count, @patterns, @suggestions, @raw_output, @execution_id, @lang)
747
+ `);
748
+ stmt.run({
749
+ id: insight.id,
750
+ created_at: new Date().toISOString(),
751
+ tool: insight.tool,
752
+ prompt_count: insight.promptCount,
753
+ patterns: JSON.stringify(insight.patterns || []),
754
+ suggestions: JSON.stringify(insight.suggestions || []),
755
+ raw_output: insight.rawOutput || null,
756
+ execution_id: insight.executionId || null,
757
+ lang: insight.lang || 'en'
758
+ });
759
+ }
760
+ /**
761
+ * Get insights history
762
+ */
763
+ getInsights(options = {}) {
764
+ const { limit = 20, tool } = options;
765
+ let sql = 'SELECT id, created_at, tool, prompt_count, patterns, suggestions, execution_id, lang FROM insights';
766
+ const params = {};
767
+ if (tool) {
768
+ sql += ' WHERE tool = @tool';
769
+ params.tool = tool;
770
+ }
771
+ sql += ' ORDER BY created_at DESC LIMIT @limit';
772
+ params.limit = limit;
773
+ const rows = this.db.prepare(sql).all(params);
774
+ return rows.map(row => ({
775
+ ...row,
776
+ patterns: JSON.parse(row.patterns || '[]'),
777
+ suggestions: JSON.parse(row.suggestions || '[]')
778
+ }));
779
+ }
780
+ /**
781
+ * Get a single insight by ID
782
+ */
783
+ getInsight(id) {
784
+ const row = this.db.prepare('SELECT * FROM insights WHERE id = ?').get(id);
785
+ if (!row)
786
+ return null;
787
+ return {
788
+ ...row,
789
+ patterns: JSON.parse(row.patterns || '[]'),
790
+ suggestions: JSON.parse(row.suggestions || '[]')
791
+ };
792
+ }
793
+ /**
794
+ * Delete an insight
795
+ */
796
+ deleteInsight(id) {
797
+ const result = this.db.prepare('DELETE FROM insights WHERE id = ?').run(id);
798
+ return result.changes > 0;
799
+ }
800
+ /**
801
+ * Save or update a review for an execution
802
+ */
803
+ saveReview(review) {
804
+ const now = new Date().toISOString();
805
+ const created_at = review.created_at || now;
806
+ const updated_at = review.updated_at || now;
807
+ const stmt = this.db.prepare(`
808
+ INSERT INTO reviews (execution_id, status, rating, comments, reviewer, created_at, updated_at)
809
+ VALUES (@execution_id, @status, @rating, @comments, @reviewer, @created_at, @updated_at)
810
+ ON CONFLICT(execution_id) DO UPDATE SET
811
+ status = @status,
812
+ rating = @rating,
813
+ comments = @comments,
814
+ reviewer = @reviewer,
815
+ updated_at = @updated_at
816
+ `);
817
+ const result = stmt.run({
818
+ execution_id: review.execution_id,
819
+ status: review.status,
820
+ rating: review.rating ?? null,
821
+ comments: review.comments ?? null,
822
+ reviewer: review.reviewer ?? null,
823
+ created_at,
824
+ updated_at
825
+ });
826
+ return {
827
+ id: result.lastInsertRowid,
828
+ execution_id: review.execution_id,
829
+ status: review.status,
830
+ rating: review.rating,
831
+ comments: review.comments,
832
+ reviewer: review.reviewer,
833
+ created_at,
834
+ updated_at
835
+ };
836
+ }
837
+ /**
838
+ * Get review for an execution
839
+ */
840
+ getReview(executionId) {
841
+ const row = this.db.prepare('SELECT * FROM reviews WHERE execution_id = ?').get(executionId);
842
+ if (!row)
843
+ return null;
844
+ return {
845
+ id: row.id,
846
+ execution_id: row.execution_id,
847
+ status: row.status,
848
+ rating: row.rating,
849
+ comments: row.comments,
850
+ reviewer: row.reviewer,
851
+ created_at: row.created_at,
852
+ updated_at: row.updated_at
853
+ };
854
+ }
855
+ /**
856
+ * Get reviews with optional filtering
857
+ */
858
+ getReviews(options = {}) {
859
+ const { status, limit = 50 } = options;
860
+ let sql = 'SELECT * FROM reviews';
861
+ const params = { limit };
862
+ if (status) {
863
+ sql += ' WHERE status = @status';
864
+ params.status = status;
865
+ }
866
+ sql += ' ORDER BY updated_at DESC LIMIT @limit';
867
+ const rows = this.db.prepare(sql).all(params);
868
+ return rows.map(row => ({
869
+ id: row.id,
870
+ execution_id: row.execution_id,
871
+ status: row.status,
872
+ rating: row.rating,
873
+ comments: row.comments,
874
+ reviewer: row.reviewer,
875
+ created_at: row.created_at,
876
+ updated_at: row.updated_at
877
+ }));
878
+ }
879
+ /**
880
+ * Delete a review
881
+ */
882
+ deleteReview(executionId) {
883
+ const result = this.db.prepare('DELETE FROM reviews WHERE execution_id = ?').run(executionId);
884
+ return result.changes > 0;
885
+ }
886
+ /**
887
+ * Close database connection
888
+ */
889
+ close() {
890
+ this.db.close();
891
+ }
892
+ }
893
+ // Singleton instance cache - keyed by normalized project ID for consistency
894
+ const storeCache = new Map();
895
+ /**
896
+ * Get or create a store instance for a directory
897
+ * Uses normalized project ID as cache key to handle path casing differences
898
+ */
899
+ export function getHistoryStore(baseDir) {
900
+ // Use getProjectId to normalize path for consistent cache key
901
+ const cacheKey = getProjectId(baseDir);
902
+ if (!storeCache.has(cacheKey)) {
903
+ storeCache.set(cacheKey, new CliHistoryStore(baseDir));
904
+ }
905
+ return storeCache.get(cacheKey);
906
+ }
907
+ /**
908
+ * Close all store instances
909
+ */
910
+ export function closeAllStores() {
911
+ for (const store of storeCache.values()) {
912
+ store.close();
913
+ }
914
+ storeCache.clear();
915
+ }
916
+ //# sourceMappingURL=cli-history-store.js.map